diff --git a/Makefile b/Makefile index d0193c1b7..73ca3efa5 100644 --- a/Makefile +++ b/Makefile @@ -141,7 +141,7 @@ _SUBDIR= tools lib .WAIT include gnu external crypto/external bin games _SUBDIR+= libexec sbin usr.bin _SUBDIR+= commands man _SUBDIR+= common drivers kernel servers -_SUBDIR+= usr.sbin share rescue sys etc test compat .WAIT distrib regress +_SUBDIR+= usr.sbin share rescue sys etc test tests compat .WAIT distrib regress .if defined(__MINIX) _SUBDIR+= benchmarks diff --git a/distrib/sets/lists/minix/mi b/distrib/sets/lists/minix/mi index ecbe78608..3d88dc507 100644 --- a/distrib/sets/lists/minix/mi +++ b/distrib/sets/lists/minix/mi @@ -73,6 +73,7 @@ ./dev minix-sys ./dev/mouse minix-sys ./etc minix-sys +./etc/atf minix-sys atf ./etc/boot.cfg.default minix-sys ./etc/defaults minix-sys ./etc/defaults/minix.rc.conf minix-sys @@ -216,6 +217,12 @@ ./usr/bin/arp minix-sys ./usr/bin/as minix-sys binutils ./usr/bin/at minix-sys +./usr/bin/atf2kyua minix-sys kyua +./usr/bin/atf-config minix-sys atf,!kyua +./usr/bin/atf-report minix-sys atf +./usr/bin/atf-run minix-sys atf +./usr/bin/atf-sh minix-sys atf +./usr/bin/atf-version minix-sys atf,!kyua ./usr/bin/awk minix-sys ./usr/bin/backup minix-sys ./usr/bin/badblocks minix-sys obsolete @@ -344,6 +351,7 @@ ./usr/bin/isoread minix-sys ./usr/bin/join minix-sys ./usr/bin/kill minix-sys obsolete +./usr/bin/kyua minix-sys kyua ./usr/bin/last minix-sys ./usr/bin/ld minix-sys binutils ./usr/bin/ldd minix-sys @@ -361,6 +369,11 @@ ./usr/bin/lpd minix-sys ./usr/bin/lspci minix-sys ./usr/bin/lstat minix-sys +./usr/bin/lua minix-sys +./usr/bin/luac minix-sys +./usr/bin/lzcat minix-sys +./usr/bin/lzma minix-sys +./usr/bin/lzmainfo minix-sys ./usr/bin/m4 minix-sys ./usr/bin/mail minix-sys ./usr/bin/make minix-sys @@ -444,6 +457,7 @@ ./usr/bin/split minix-sys ./usr/bin/sprofalyze minix-sys ./usr/bin/sprofdiff minix-sys +./usr/bin/sqlite3 minix-sys ./usr/bin/srccrc minix-sys ./usr/bin/stat minix-sys ./usr/bin/strings minix-sys binutils @@ -484,7 +498,9 @@ ./usr/bin/uncompress minix-sys ./usr/bin/unexpand minix-sys ./usr/bin/uniq minix-sys +./usr/bin/unlzma minix-sys ./usr/bin/unstack minix-sys +./usr/bin/unxz minix-sys ./usr/bin/update minix-sys ./usr/bin/uptime minix-sys ./usr/bin/uud minix-sys @@ -505,6 +521,8 @@ ./usr/bin/write minix-sys ./usr/bin/writeisofs minix-sys ./usr/bin/xargs minix-sys +./usr/bin/xz minix-sys +./usr/bin/xzcat minix-sys ./usr/bin/yacc minix-sys ./usr/bin/yes minix-sys ./usr/bin/zcat minix-sys @@ -535,6 +553,27 @@ ./usr/include/arpa/telnet.h minix-sys ./usr/include/arpa/tftp.h minix-sys ./usr/include/assert.h minix-sys +./usr/include/atf-c++ minix-sys atf +./usr/include/atf-c minix-sys atf +./usr/include/atf-c/build.h minix-sys atf +./usr/include/atf-c++/build.hpp minix-sys atf +./usr/include/atf-c/check.h minix-sys atf +./usr/include/atf-c++/check.hpp minix-sys atf +./usr/include/atf-c/config.h minix-sys atf +./usr/include/atf-c++/config.hpp minix-sys atf +./usr/include/atf-c/defs.h minix-sys atf +./usr/include/atf-c/error_fwd.h minix-sys atf +./usr/include/atf-c/error.h minix-sys atf +./usr/include/atf-c/macros.h minix-sys atf +./usr/include/atf-c++/macros.hpp minix-sys atf +./usr/include/atf-c++/noncopyable.hpp minix-sys atf +./usr/include/atf-c/tc.h minix-sys atf +./usr/include/atf-c++/tests.hpp minix-sys atf +./usr/include/atf-c/tp.h minix-sys atf +./usr/include/atf-c/utils.h minix-sys atf +./usr/include/atf-c++/utils.hpp minix-sys atf +./usr/include/atf-c.h minix-sys atf +./usr/include/atf-c++.hpp minix-sys atf ./usr/include/atomic.h minix-sys ./usr/include/bitstring.h minix-sys ./usr/include/bm.h minix-sys @@ -1003,6 +1042,7 @@ ./usr/include/inttypes.h minix-sys ./usr/include/iso646.h minix-sys ./usr/include/langinfo.h minix-sys +./usr/include/lauxlib.h minix-sys ./usr/include/libelf.h minix-sys ./usr/include/libexec.h minix-sys ./usr/include/libgen.h minix-sys @@ -1014,6 +1054,19 @@ ./usr/include/link.h minix-sys ./usr/include/locale.h minix-sys ./usr/include/login_cap.h minix-sys +./usr/include/luaconf.h minix-sys +./usr/include/lua.h minix-sys +./usr/include/lua.hpp minix-sys +./usr/include/lualib.h minix-sys +./usr/include/lutok minix-sys +./usr/include/lutok/c_gate.hpp minix-sys kyua +./usr/include/lutok/debug.hpp minix-sys kyua +./usr/include/lutok/exceptions.hpp minix-sys kyua +./usr/include/lutok/operations.hpp minix-sys kyua +./usr/include/lutok/stack_cleaner.hpp minix-sys kyua +./usr/include/lutok/state.hpp minix-sys kyua +./usr/include/lutok/state.ipp minix-sys kyua +./usr/include/lutok/test_utils.hpp minix-sys kyua ./usr/include/lwp.h minix-sys ./usr/include/lzma minix-sys ./usr/include/lzma/base.h minix-sys @@ -1072,8 +1125,8 @@ ./usr/include/minix/gpio.h minix-sys ./usr/include/minix/hash.h minix-sys ./usr/include/minix/hgfs.h minix-sys -./usr/include/minix/i2c.h minix-sys ./usr/include/minix/i2cdriver.h minix-sys +./usr/include/minix/i2c.h minix-sys ./usr/include/minix/input.h minix-sys ./usr/include/minix/ioctl.h minix-sys ./usr/include/minix/ipcconst.h minix-sys @@ -1236,6 +1289,8 @@ ./usr/include/sha1.h minix-sys ./usr/include/sha2.h minix-sys ./usr/include/signal.h minix-sys +./usr/include/sqlite3ext.h minix-sys +./usr/include/sqlite3.h minix-sys ./usr/include/ssp minix-sys ./usr/include/ssp/ssp.h minix-sys ./usr/include/ssp/stdio.h minix-sys @@ -1488,6 +1543,16 @@ ./usr/lib/libarchive.so minix-sys ./usr/lib/libasyn.a minix-sys ./usr/lib/libasyn_pic.a minix-sys +./usr/lib/libatf-c.a minix-sys atf +./usr/lib/libatf-c++.a minix-sys atf +./usr/lib/libatf-c_pic.a minix-sys atf +./usr/lib/libatf-c++_pic.a minix-sys atf +./usr/lib/libatf-c.so.0.0 minix-sys atf +./usr/lib/libatf-c++.so.0.0 minix-sys atf +./usr/lib/libatf-c.so.0 minix-sys atf +./usr/lib/libatf-c++.so.0 minix-sys atf +./usr/lib/libatf-c.so minix-sys atf +./usr/lib/libatf-c++.so minix-sys atf ./usr/lib/libaudiodriver.a minix-sys ./usr/lib/libaudiodriver_pic.a minix-sys ./usr/lib/libbdev.a minix-sys @@ -1552,6 +1617,16 @@ ./usr/lib/libgcc_s.so.1.0 minix-sys gcccmds ./usr/lib/libgcc_s.so.1 minix-sys gcccmds ./usr/lib/libl.a minix-sys +./usr/lib/liblua.a minix-sys +./usr/lib/liblua_pic.a minix-sys +./usr/lib/liblua.so minix-sys +./usr/lib/liblua.so.1.0 minix-sys +./usr/lib/liblua.so.1 minix-sys +./usr/lib/liblutok.a minix-sys kyua +./usr/lib/liblutok_pic.a minix-sys kyua +./usr/lib/liblutok.so minix-sys kyua +./usr/lib/liblutok.so.1.0 minix-sys kyua +./usr/lib/liblutok.so.1 minix-sys kyua ./usr/lib/liblwip.a minix-sys ./usr/lib/liblwip_pic.a minix-sys ./usr/lib/liblzma.a minix-sys @@ -1609,6 +1684,11 @@ ./usr/lib/librmt.a minix-sys ./usr/lib/libsffs.a minix-sys ./usr/lib/libsffs_pic.a minix-sys +./usr/lib/libsqlite3.a minix-sys +./usr/lib/libsqlite3_pic.a minix-sys +./usr/lib/libsqlite3.so minix-sys +./usr/lib/libsqlite3.so.1 minix-sys +./usr/lib/libsqlite3.so.1.1 minix-sys ./usr/lib/libstdc++.a minix-sys gcccmds ./usr/lib/libstdc++_pic.a minix-sys gcccmds ./usr/lib/libstdc++.so minix-sys gcccmds @@ -1652,10 +1732,24 @@ ./usr/lib/libz.so.0 minix-sys ./usr/lib/libz.so minix-sys ./usr/lib/minlib.pc minix-sys +./usr/lib/pkgconfig minix-sys +./usr/lib/pkgconfig/atf-c.pc minix-sys atf +./usr/lib/pkgconfig/atf-c++.pc minix-sys atf +./usr/lib/pkgconfig/atf-sh.pc minix-sys atf +./usr/lib/pkgconfig/kyua-testers.pc minix-sys kyua +./usr/lib/pkgconfig/lutok.pc minix-sys kyua +./usr/lib/pkgconfig/sqlite3.pc minix-sys ./usr/lib/pwdauth minix-sys +./usr/libdata minix-sys atf +./usr/libdata/debug minix-sys atf +./usr/libdata/debug/usr minix-sys atf +./usr/libdata/debug/usr/tests/lib/libpthread/dlopen minix-sys atf ./usr/libexec minix-sys +./usr/libexec/atf-check minix-sys atf ./usr/libexec/fingerd minix-sys ./usr/libexec/ftpd minix-sys +./usr/libexec/kyua-atf-tester minix-sys kyua +./usr/libexec/kyua-plain-tester minix-sys kyua ./usr/libexec/ld.elf_so minix-sys ./usr/libexec/makewhatis minix-sys ./usr/log minix-sys @@ -1671,6 +1765,14 @@ ./usr/man/man1/as.1 minix-sys binutils ./usr/man/man1/ash.1 minix-sys ./usr/man/man1/at.1 minix-sys +./usr/man/man1/atf2kyua.1 minix-sys kyua +./usr/man/man1/atf-check.1 minix-sys atf +./usr/man/man1/atf-config.1 minix-sys atf,!kyua +./usr/man/man1/atf-report.1 minix-sys atf +./usr/man/man1/atf-run.1 minix-sys atf +./usr/man/man1/atf-sh.1 minix-sys atf +./usr/man/man1/atf-test-program.1 minix-sys atf +./usr/man/man1/atf-version.1 minix-sys atf,!kyua ./usr/man/man1/awk.1 minix-sys ./usr/man/man1/banner.1 minix-sys ./usr/man/man1/basename.1 minix-sys @@ -1791,6 +1893,20 @@ ./usr/man/man1/join.1 minix-sys ./usr/man/man1/kill.1 minix-sys ./usr/man/man1/ksh.1 minix-sys +./usr/man/man1/kyua.1 minix-sys kyua +./usr/man/man1/kyua-about.1 minix-sys kyua +./usr/man/man1/kyua-atf-tester.1 minix-sys kyua +./usr/man/man1/kyua-config.1 minix-sys kyua +./usr/man/man1/kyua-db-exec.1 minix-sys kyua +./usr/man/man1/kyua-db-migrate.1 minix-sys kyua +./usr/man/man1/kyua-debug.1 minix-sys kyua +./usr/man/man1/kyua-help.1 minix-sys kyua +./usr/man/man1/kyua-list.1 minix-sys kyua +./usr/man/man1/kyua-plain-tester.1 minix-sys kyua +./usr/man/man1/kyua-report.1 minix-sys kyua +./usr/man/man1/kyua-report-html.1 minix-sys kyua +./usr/man/man1/kyua-test.1 minix-sys kyua +./usr/man/man1/kyua-tester.1 minix-sys kyua ./usr/man/man1/last.1 minix-sys ./usr/man/man1/ld.1 minix-sys binutils ./usr/man/man1/ldd.1 minix-sys @@ -1811,6 +1927,11 @@ ./usr/man/man1/lp.1 minix-sys ./usr/man/man1/ls.1 minix-sys ./usr/man/man1/lspci.1 minix-sys +./usr/man/man1/lua.1 minix-sys +./usr/man/man1/luac.1 minix-sys +./usr/man/man1/lzcat.1 minix-sys +./usr/man/man1/lzma.1 minix-sys +./usr/man/man1/lzmainfo.1 minix-sys ./usr/man/man1/m4.1 minix-sys ./usr/man/man1/mail.1 minix-sys ./usr/man/man1/make.1 minix-sys @@ -1888,6 +2009,7 @@ ./usr/man/man1/sort.1 minix-sys ./usr/man/man1/spell.1 minix-sys ./usr/man/man1/split.1 minix-sys +./usr/man/man1/sqlite3.1 minix-sys ./usr/man/man1/stat.1 minix-sys ./usr/man/man1/strings.1 minix-sys binutils ./usr/man/man1/strip.1 minix-sys binutils @@ -1926,7 +2048,9 @@ ./usr/man/man1/uncompress.1 minix-sys ./usr/man/man1/unexpand.1 minix-sys ./usr/man/man1/uniq.1 minix-sys +./usr/man/man1/unlzma.1 minix-sys ./usr/man/man1/unset.1 minix-sys +./usr/man/man1/unxz.1 minix-sys ./usr/man/man1/uud.1 minix-sys ./usr/man/man1/uue.1 minix-sys ./usr/man/man1/vi.1 minix-sys @@ -1942,6 +2066,8 @@ ./usr/man/man1/worldstone.1 minix-sys ./usr/man/man1/write.1 minix-sys ./usr/man/man1/xargs.1 minix-sys +./usr/man/man1/xz.1 minix-sys +./usr/man/man1/xzcat.1 minix-sys ./usr/man/man1/yacc.1 minix-sys ./usr/man/man1/yap.1 minix-sys ./usr/man/man1/yes.1 minix-sys @@ -2259,6 +2385,9 @@ ./usr/man/man3/atanh.3 minix-sys ./usr/man/man3/atanhf.3 minix-sys ./usr/man/man3/atexit.3 minix-sys +./usr/man/man3/atf-c-api.3 minix-sys atf +./usr/man/man3/atf-c++-api.3 minix-sys atf +./usr/man/man3/atf-sh-api.3 minix-sys atf ./usr/man/man3/atof.3 minix-sys ./usr/man/man3/atoi.3 minix-sys ./usr/man/man3/atol.3 minix-sys @@ -4135,6 +4264,7 @@ ./usr/man/man4 minix-sys ./usr/man/man4/aha1540.4 minix-sys ./usr/man/man4/at.4 minix-sys +./usr/man/man4/atf-test-case.4 minix-sys atf ./usr/man/man4/bios.4 minix-sys ./usr/man/man4/console.4 minix-sys ./usr/man/man4/controller.4 minix-sys @@ -4155,6 +4285,7 @@ ./usr/man/man4/udp.4 minix-sys ./usr/man/man4/uds.4 minix-sys ./usr/man/man5 minix-sys +./usr/man/man5/atf-formats.5 minix-sys atf ./usr/man/man5/boot.cfg.5 minix-sys ./usr/man/man5/cdb.5 minix-sys ./usr/man/man5/configfile.5 minix-sys @@ -4174,6 +4305,10 @@ ./usr/man/man5/http_status.5 minix-sys ./usr/man/man5/info.5 minix-sys ./usr/man/man5/keymap.5 minix-sys +./usr/man/man5/kyua.conf.5 minix-sys kyua +./usr/man/man5/kyuafile.5 minix-sys kyua +./usr/man/man5/kyua-tester-list.5 minix-sys kyua +./usr/man/man5/kyua-tester-result.5 minix-sys kyua ./usr/man/man5/libarchive-formats.5 minix-sys ./usr/man/man5/magic.5 minix-sys ./usr/man/man5/man.conf.5 minix-sys @@ -4200,8 +4335,13 @@ ./usr/man/man6 minix-sys ./usr/man/man7 minix-sys ./usr/man/man7/ascii.7 minix-sys +./usr/man/man7/atf.7 minix-sys atf ./usr/man/man7/environ.7 minix-sys ./usr/man/man7/hier.7 minix-sys +./usr/man/man7/kyua-atf-interface.7 minix-sys kyua +./usr/man/man7/kyua-build-root.7 minix-sys kyua +./usr/man/man7/kyua-plain-interface.7 minix-sys kyua +./usr/man/man7/kyua-test-filters.7 minix-sys kyua ./usr/man/man7/man.7 minix-sys ./usr/man/man7/mandoc_char.7 minix-sys ./usr/man/man7/mandoc_man.7 minix-sys @@ -4348,10 +4488,33 @@ ./usr/sbin/vm minix-sys ./usr/sbin/zic minix-sys ./usr/share minix-sys +./usr/share/atf minix-sys atf +./usr/share/atf/atf-run.hooks minix-sys atf,!kyua +./usr/share/atf/libatf-sh.subr minix-sys atf ./usr/share/doc minix-sys +./usr/share/doc/atf minix-sys atf +./usr/share/doc/atf/AUTHORS minix-sys atf +./usr/share/doc/atf/COPYING minix-sys atf +./usr/share/doc/atf/NEWS minix-sys atf +./usr/share/doc/atf/README minix-sys atf ./usr/share/doc/html minix-sys ./usr/share/doc/html/bzip2 minix-sys ./usr/share/doc/html/bzip2/manual.html minix-sys +./usr/share/doc/kyua-atf-compat minix-sys atf +./usr/share/doc/kyua-atf-compat/AUTHORS minix-sys kyua +./usr/share/doc/kyua-atf-compat/COPYING minix-sys kyua +./usr/share/doc/kyua-atf-compat/NEWS minix-sys kyua +./usr/share/doc/kyua-atf-compat/README minix-sys kyua +./usr/share/doc/kyua-cli minix-sys atf +./usr/share/doc/kyua-cli/AUTHORS minix-sys kyua +./usr/share/doc/kyua-cli/COPYING minix-sys kyua +./usr/share/doc/kyua-cli/NEWS minix-sys kyua +./usr/share/doc/kyua-cli/README minix-sys kyua +./usr/share/doc/kyua-testers minix-sys atf +./usr/share/doc/kyua-testers/AUTHORS minix-sys kyua +./usr/share/doc/kyua-testers/COPYING minix-sys kyua +./usr/share/doc/kyua-testers/NEWS minix-sys kyua +./usr/share/doc/kyua-testers/README minix-sys kyua ./usr/share/doc/psd minix-sys ./usr/share/doc/psd/19.curses inix-sys ./usr/share/doc/psd/19.curses/appen.A minix-sys @@ -4379,6 +4542,18 @@ ./usr/share/doc/psd/19.curses/twinkle1.c minix-sys ./usr/share/doc/psd/19.curses/twinkle2.c minix-sys ./usr/share/doc/psd/19.curses/win_st.c minix-sys +./usr/share/examples minix-sys atf +./usr/share/examples/atf minix-sys atf +./usr/share/examples/atf/atf-run.hooks minix-sys atf,!kyua +./usr/share/examples/atf/tests-results.css minix-sys atf,!kyua +./usr/share/examples/kyua-cli minix-sys atf +./usr/share/examples/kyua-cli/kyua.conf minix-sys kyua +./usr/share/examples/kyua-cli/Kyuafile.top minix-sys kyua +./usr/share/examples/lutok minix-sys atf +./usr/share/examples/lutok/bindings.cpp minix-sys kyua +./usr/share/examples/lutok/hello.cpp minix-sys kyua +./usr/share/examples/lutok/interpreter.cpp minix-sys kyua +./usr/share/examples/lutok/raii.cpp minix-sys kyua ./usr/share/info minix-sys ./usr/share/info/as.info minix-sys binutils ./usr/share/info/bfd.info minix-sys binutils @@ -4391,6 +4566,18 @@ ./usr/share/info/info-stnd.info minix-sys ./usr/share/info/ld.info minix-sys binutils ./usr/share/info/texinfo.info minix-sys +./usr/share/kyua-atf-compat minix-sys atf +./usr/share/kyua-atf-compat/lib.subr minix-sys kyua +./usr/share/kyua-atf-compat/tests_lib.subr minix-sys kyua +./usr/share/kyua-cli minix-sys atf +./usr/share/kyua-cli/misc minix-sys atf +./usr/share/kyua-cli/misc/context.html minix-sys kyua +./usr/share/kyua-cli/misc/index.html minix-sys kyua +./usr/share/kyua-cli/misc/report.css minix-sys kyua +./usr/share/kyua-cli/misc/test_result.html minix-sys kyua +./usr/share/kyua-cli/store minix-sys atf +./usr/share/kyua-cli/store/migrate_v1_v2.sql minix-sys kyua +./usr/share/kyua-cli/store/schema_v2.sql minix-sys kyua ./usr/share/misc minix-sys ./usr/share/misc/acronyms minix-sys ./usr/share/misc/acronyms.comp minix-sys @@ -4462,6 +4649,12 @@ ./usr/share/terminfo/terminfo minix-sys ./usr/share/terminfo/terminfo.cdb minix-sys ./usr/share/terminfo/terminfo.db minix-sys obsolete +./usr/share/xml minix-sys atf +./usr/share/xml/atf minix-sys atf +./usr/share/xml/atf/tests-results.dtd minix-sys atf,!kyua +./usr/share/xsl minix-sys atf +./usr/share/xsl/atf minix-sys atf +./usr/share/xsl/atf/tests-results.xsl minix-sys atf,!kyua ./usr/share/zoneinfo minix-sys ./usr/share/zoneinfo/Africa minix-sys ./usr/share/zoneinfo/Africa/Abidjan minix-sys @@ -5077,6 +5270,12 @@ ./usr/spool/mail minix-sys ./usr/src minix-sys ./usr/tests minix-sys +./usr/tests/atf/atf-c++/detail/auto_array_test minix-sys atf +./usr/tests/lib/libc/stdio/t_mktemp minix-sys atf +./usr/tests/lib/libc/stdio/t_printf minix-sys atf +./usr/tests/lib/libcurses/director minix-sys atf +./usr/tests/lib/libpthread/dlopen minix-sys atf +./usr/tests/libexec/Atffile minix-sys atf ./usr/tests/minix-posix minix-sys ./usr/tests/minix-posix/run minix-sys ./usr/tests/minix-posix/t10a minix-sys @@ -5169,6 +5368,51 @@ ./usr/tests/minix-posix/testsh2 minix-sys ./usr/tests/minix-posix/testvm minix-sys ./usr/tests/minix-posix/testvm.conf minix-sys +./usr/tests/usr.bin/jot/Atffile minix-sys atf +./usr/tests/usr.bin/jot/d_basic.out minix-sys atf +./usr/tests/usr.bin/jot/t_jot minix-sys atf +./usr/tests/usr.bin/xlint/Atffile minix-sys atf +./usr/tests/usr.bin/xlint/lint1/Atffile minix-sys atf +./usr/tests/usr.bin/xlint/lint1/d_alignof.c minix-sys atf +./usr/tests/usr.bin/xlint/lint1/d_c99_complex_num.c minix-sys atf +./usr/tests/usr.bin/xlint/lint1/d_c99_decls_after_stmt2.c minix-sys atf +./usr/tests/usr.bin/xlint/lint1/d_c99_decls_after_stmt.c minix-sys atf +./usr/tests/usr.bin/xlint/lint1/d_c99_for_loops.c minix-sys atf +./usr/tests/usr.bin/xlint/lint1/d_c99_func.c minix-sys atf +./usr/tests/usr.bin/xlint/lint1/d_c99_recursive_init.c minix-sys atf +./usr/tests/usr.bin/xlint/lint1/d_c99_struct_init.c minix-sys atf +./usr/tests/usr.bin/xlint/lint1/d_c99_union_init1.c minix-sys atf +./usr/tests/usr.bin/xlint/lint1/d_c99_union_init2.c minix-sys atf +./usr/tests/usr.bin/xlint/lint1/d_c99_union_init3.c minix-sys atf +./usr/tests/usr.bin/xlint/lint1/d_c9x_array_init.c minix-sys atf +./usr/tests/usr.bin/xlint/lint1/d_c9x_recursive_init.c minix-sys atf +./usr/tests/usr.bin/xlint/lint1/d_cast_init2.c minix-sys atf +./usr/tests/usr.bin/xlint/lint1/d_cast_init.c minix-sys atf +./usr/tests/usr.bin/xlint/lint1/d_cast_lhs.c minix-sys atf +./usr/tests/usr.bin/xlint/lint1/d_compound_literals1.c minix-sys atf +./usr/tests/usr.bin/xlint/lint1/d_compound_literals2.c minix-sys atf +./usr/tests/usr.bin/xlint/lint1/d_constant_conv1.c minix-sys atf +./usr/tests/usr.bin/xlint/lint1/d_constant_conv2.c minix-sys atf +./usr/tests/usr.bin/xlint/lint1/d_cvt_in_ternary.c minix-sys atf +./usr/tests/usr.bin/xlint/lint1/d_ellipsis_in_switch.c minix-sys atf +./usr/tests/usr.bin/xlint/lint1/d_gcc_compound_statements1.c minix-sys atf +./usr/tests/usr.bin/xlint/lint1/d_gcc_compound_statements2.c minix-sys atf +./usr/tests/usr.bin/xlint/lint1/d_gcc_compound_statements3.c minix-sys atf +./usr/tests/usr.bin/xlint/lint1/d_gcc_func.c minix-sys atf +./usr/tests/usr.bin/xlint/lint1/d_gcc_variable_array_init.c minix-sys atf +./usr/tests/usr.bin/xlint/lint1/d_incorrect_array_size.c minix-sys atf +./usr/tests/usr.bin/xlint/lint1/d_long_double_int.c minix-sys atf +./usr/tests/usr.bin/xlint/lint1/d_nested_structs.c minix-sys atf +./usr/tests/usr.bin/xlint/lint1/d_nolimit_init.c minix-sys atf +./usr/tests/usr.bin/xlint/lint1/d_packed_structs.c minix-sys atf +./usr/tests/usr.bin/xlint/lint1/d_shift_to_narrower_type.c minix-sys atf +./usr/tests/usr.bin/xlint/lint1/d_type_conv1.c minix-sys atf +./usr/tests/usr.bin/xlint/lint1/d_type_conv2.c minix-sys atf +./usr/tests/usr.bin/xlint/lint1/d_type_conv3.c minix-sys atf +./usr/tests/usr.bin/xlint/lint1/d_typename_as_var.c minix-sys atf +./usr/tests/usr.bin/xlint/lint1/d_zero_sized_arrays.c minix-sys atf +./usr/tests/usr.bin/xlint/lint1/Kyuafile minix-sys kyua +./usr/tests/usr.bin/xlint/lint1/t_integration minix-sys atf ./usr/tmp minix-sys ./usr/var minix-sys ./usr/var/db minix-sys @@ -5178,6 +5422,7 @@ ./var/db minix-sys ./var/db/obsolete minix-sys ./var/db/obsolete/minix minix-sys +./var/db/obsolete/tests minix-sys atf ./var/log minix-sys ./var/run minix-sys ./var/tmp minix-sys diff --git a/distrib/sets/lists/tests/mi b/distrib/sets/lists/tests/mi index aeeb9d219..37622e25e 100644 --- a/distrib/sets/lists/tests/mi +++ b/distrib/sets/lists/tests/mi @@ -1,4 +1,4 @@ -# $NetBSD: mi,v 1.496 2012/09/27 00:38:57 joerg Exp $ +# $NetBSD: mi,v 1.527 2013/02/28 21:54:09 christos Exp $ # # Note: don't delete entries from here - mark them as "obsolete" instead. # @@ -6,823 +6,172 @@ ./usr/libdata/debug/usr/tests tests-base-debug ./usr/libdata/debug/usr/tests/atf tests-atf-debug ./usr/libdata/debug/usr/tests/atf/atf-c tests-atf-debug -./usr/libdata/debug/usr/tests/atf/atf-c/atf_c_test.debug tests-atf-debug debug,atf -./usr/libdata/debug/usr/tests/atf/atf-c/build_test.debug tests-atf-debug debug,atf -./usr/libdata/debug/usr/tests/atf/atf-c/check_test.debug tests-atf-debug debug,atf -./usr/libdata/debug/usr/tests/atf/atf-c/config_test.debug tests-atf-debug debug,atf ./usr/libdata/debug/usr/tests/atf/atf-c/detail tests-atf-debug -./usr/libdata/debug/usr/tests/atf/atf-c/detail/dynstr_test.debug tests-atf-debug debug,atf -./usr/libdata/debug/usr/tests/atf/atf-c/detail/env_test.debug tests-atf-debug debug,atf -./usr/libdata/debug/usr/tests/atf/atf-c/detail/fs_test.debug tests-atf-debug debug,atf -./usr/libdata/debug/usr/tests/atf/atf-c/detail/list_test.debug tests-atf-debug debug,atf -./usr/libdata/debug/usr/tests/atf/atf-c/detail/map_test.debug tests-atf-debug debug,atf -./usr/libdata/debug/usr/tests/atf/atf-c/detail/process_helpers.debug tests-atf-debug debug,atf -./usr/libdata/debug/usr/tests/atf/atf-c/detail/process_test.debug tests-atf-debug debug,atf -./usr/libdata/debug/usr/tests/atf/atf-c/detail/sanity_test.debug tests-atf-debug debug,atf -./usr/libdata/debug/usr/tests/atf/atf-c/detail/test_helpers_test.debug tests-atf-debug debug,atf -./usr/libdata/debug/usr/tests/atf/atf-c/detail/text_test.debug tests-atf-debug debug,atf -./usr/libdata/debug/usr/tests/atf/atf-c/detail/user_test.debug tests-atf-debug debug,atf -./usr/libdata/debug/usr/tests/atf/atf-c/dynstr_test.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c/env_test.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c/error_test.debug tests-atf-debug debug,atf -./usr/libdata/debug/usr/tests/atf/atf-c/fs_test.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c/h_check.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c/h_processes.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c/list_test.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c/macros_test.debug tests-atf-debug debug,atf -./usr/libdata/debug/usr/tests/atf/atf-c/map_test.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c/process_helpers.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c/process_test.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c/sanity_test.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c/t_atf_c.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c/t_build.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c/t_check.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c/t_config.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c/t_dynstr.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c/t_env.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c/t_error.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c/t_expand.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c/t_fs.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c/t_h_lib.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c/t_io.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c/t_list.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c/t_macros.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c/t_map.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c/t_process.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c/t_sanity.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c/t_signals.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c/t_tc.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c/t_tcr.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c/t_text.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c/t_tp.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c/t_ui.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c/t_user.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c/tc_test.debug tests-atf-debug debug,atf -./usr/libdata/debug/usr/tests/atf/atf-c/test_helpers_test.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c/text_test.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c/tp_test.debug tests-atf-debug debug,atf -./usr/libdata/debug/usr/tests/atf/atf-c/user_test.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c/utils_test.debug tests-atf-debug debug,atf ./usr/libdata/debug/usr/tests/atf/atf-c++ tests-atf-debug -./usr/libdata/debug/usr/tests/atf/atf-c++/application_test.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c++/atf_c++_test.debug tests-atf-debug debug,atf -./usr/libdata/debug/usr/tests/atf/atf-c++/build_test.debug tests-atf-debug debug,atf -./usr/libdata/debug/usr/tests/atf/atf-c++/check_test.debug tests-atf-debug debug,atf -./usr/libdata/debug/usr/tests/atf/atf-c++/config_test.debug tests-atf-debug debug,atf ./usr/libdata/debug/usr/tests/atf/atf-c++/detail tests-atf-debug -./usr/libdata/debug/usr/tests/atf/atf-c++/detail/application_test.debug tests-atf-debug debug,atf -./usr/libdata/debug/usr/tests/atf/atf-c++/detail/env_test.debug tests-atf-debug debug,atf -./usr/libdata/debug/usr/tests/atf/atf-c++/detail/exceptions_test.debug tests-atf-debug debug,atf -./usr/libdata/debug/usr/tests/atf/atf-c++/detail/expand_test.debug tests-atf-debug debug,atf -./usr/libdata/debug/usr/tests/atf/atf-c++/detail/fs_test.debug tests-atf-debug debug,atf -./usr/libdata/debug/usr/tests/atf/atf-c++/detail/parser_test.debug tests-atf-debug debug,atf -./usr/libdata/debug/usr/tests/atf/atf-c++/detail/process_test.debug tests-atf-debug debug,atf -./usr/libdata/debug/usr/tests/atf/atf-c++/detail/sanity_test.debug tests-atf-debug debug,atf -./usr/libdata/debug/usr/tests/atf/atf-c++/detail/text_test.debug tests-atf-debug debug,atf -./usr/libdata/debug/usr/tests/atf/atf-c++/detail/ui_test.debug tests-atf-debug debug,atf -./usr/libdata/debug/usr/tests/atf/atf-c++/env_test.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c++/exceptions_test.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c++/expand_test.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c++/fs_test.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c++/io_test.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c++/macros_test.debug tests-atf-debug debug,atf -./usr/libdata/debug/usr/tests/atf/atf-c++/parser_test.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c++/process_test.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c++/sanity_test.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c++/signals_test.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c++/tests_test.debug tests-atf-debug debug,atf -./usr/libdata/debug/usr/tests/atf/atf-c++/text_test.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c++/ui_test.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c++/user_test.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c++/utils_test.debug tests-atf-debug debug,atf -./usr/libdata/debug/usr/tests/atf/atf-c++/t_application.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c++/t_atf_c++.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c++/t_atffile.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c++/t_build.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c++/t_check.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c++/t_config.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c++/t_env.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c++/t_exceptions.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c++/t_expand.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c++/t_formats.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c++/t_fs.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c++/t_io.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c++/t_macros.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c++/t_parser.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c++/t_process.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c++/t_sanity.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c++/t_signals.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c++/t_tests.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c++/t_text.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c++/t_ui.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c++/t_user.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-c++/t_utils.debug tests-obsolete obsolete ./usr/libdata/debug/usr/tests/atf/atf-compile tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-compile/h_mode.debug tests-obsolete obsolete ./usr/libdata/debug/usr/tests/atf/atf-report tests-atf-tests -./usr/libdata/debug/usr/tests/atf/atf-report/fail_helper.debug tests-atf-tests debug,atf -./usr/libdata/debug/usr/tests/atf/atf-report/h_fail.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-report/h_misc.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-report/h_pass.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-report/h_xfail.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-report/misc_helpers.debug tests-atf-tests debug,atf -./usr/libdata/debug/usr/tests/atf/atf-report/pass_helper.debug tests-atf-tests debug,atf -./usr/libdata/debug/usr/tests/atf/atf-report/reader_test.debug tests-atf-tests debug,atf ./usr/libdata/debug/usr/tests/atf/atf-run tests-atf-tests -./usr/libdata/debug/usr/tests/atf/atf-run/atffile_test.debug tests-atf-tests debug,atf -./usr/libdata/debug/usr/tests/atf/atf-run/bad_metadata_helper.debug tests-atf-tests debug,atf -./usr/libdata/debug/usr/tests/atf/atf-run/config_test.debug tests-atf-tests debug,atf -./usr/libdata/debug/usr/tests/atf/atf-run/expect_helpers.debug tests-atf-tests debug,atf -./usr/libdata/debug/usr/tests/atf/atf-run/fs_test.debug tests-atf-tests debug,atf -./usr/libdata/debug/usr/tests/atf/atf-run/h_bad_metadata.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-run/h_fail.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-run/h_misc.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-run/h_pass.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-run/h_several_tcs.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-run/h_zero_tcs.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-run/io_test.debug tests-atf-tests debug,atf -./usr/libdata/debug/usr/tests/atf/atf-run/misc_helpers.debug tests-atf-tests debug,atf -./usr/libdata/debug/usr/tests/atf/atf-run/pass_helper.debug tests-atf-tests debug,atf -./usr/libdata/debug/usr/tests/atf/atf-run/requirements_test.debug tests-atf-tests debug,atf -./usr/libdata/debug/usr/tests/atf/atf-run/several_tcs_helper.debug tests-atf-tests debug,atf -./usr/libdata/debug/usr/tests/atf/atf-run/signals_test.debug tests-atf-tests debug,atf -./usr/libdata/debug/usr/tests/atf/atf-run/t_config.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-run/t_requirements.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-run/t_test_program.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/atf-run/test_program_test.debug tests-atf-tests debug,atf -./usr/libdata/debug/usr/tests/atf/atf-run/user_test.debug tests-atf-tests debug,atf -./usr/libdata/debug/usr/tests/atf/atf-run/zero_tcs_helper.debug tests-atf-tests debug,atf ./usr/libdata/debug/usr/tests/atf/formats tests-atf-debug -./usr/libdata/debug/usr/tests/atf/formats/h_parser.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/formats/t_writers.debug tests-obsolete obsolete ./usr/libdata/debug/usr/tests/atf/test_programs tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/test_programs/h_c.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/test_programs/h_cpp.debug tests-obsolete obsolete ./usr/libdata/debug/usr/tests/atf/test-programs tests-atf-debug -./usr/libdata/debug/usr/tests/atf/test-programs/c_helpers.debug tests-atf-debug debug,atf -./usr/libdata/debug/usr/tests/atf/test-programs/cpp_helpers.debug tests-atf-debug debug,atf ./usr/libdata/debug/usr/tests/atf/tools tests-atf-debug obsolete -./usr/libdata/debug/usr/tests/atf/tools/h_fail.debug tests-atf-debug obsolete -./usr/libdata/debug/usr/tests/atf/tools/h_misc.debug tests-atf-debug obsolete -./usr/libdata/debug/usr/tests/atf/tools/h_mode.debug tests-atf-debug obsolete -./usr/libdata/debug/usr/tests/atf/tools/h_pass.debug tests-atf-debug obsolete ./usr/libdata/debug/usr/tests/atf/units tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/units/t_config.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/units/t_env.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/units/t_expand.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/units/t_fs.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/units/t_io.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/units/t_parser.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/units/t_sanity.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/units/t_signals.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/units/t_tests.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/units/t_text.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/units/t_user.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/atf/units/t_utils.debug tests-obsolete obsolete ./usr/libdata/debug/usr/tests/bin tests-bin-debug ./usr/libdata/debug/usr/tests/bin/df tests-bin-debug -./usr/libdata/debug/usr/tests/bin/df/h_df.debug tests-bin-debug debug ./usr/libdata/debug/usr/tests/crypto tests-crypto-debug ./usr/libdata/debug/usr/tests/crypto/libcrypto tests-crypto-debug -./usr/libdata/debug/usr/tests/crypto/libcrypto/h_bftest.debug tests-crypto-debug debug,crypto -./usr/libdata/debug/usr/tests/crypto/libcrypto/h_bntest.debug tests-crypto-debug debug,crypto -./usr/libdata/debug/usr/tests/crypto/libcrypto/h_casttest.debug tests-crypto-debug debug,crypto -./usr/libdata/debug/usr/tests/crypto/libcrypto/h_conftest.debug tests-crypto-debug debug,crypto -./usr/libdata/debug/usr/tests/crypto/libcrypto/h_destest.debug tests-crypto-debug debug,crypto -./usr/libdata/debug/usr/tests/crypto/libcrypto/h_dhtest.debug tests-crypto-debug debug,crypto -./usr/libdata/debug/usr/tests/crypto/libcrypto/h_divtest.debug tests-crypto-debug debug,crypto -./usr/libdata/debug/usr/tests/crypto/libcrypto/h_dsatest.debug tests-crypto-debug debug,crypto -./usr/libdata/debug/usr/tests/crypto/libcrypto/h_ecdhtest.debug tests-crypto-debug debug,crypto -./usr/libdata/debug/usr/tests/crypto/libcrypto/h_ecdsatest.debug tests-crypto-debug debug,crypto -./usr/libdata/debug/usr/tests/crypto/libcrypto/h_ectest.debug tests-crypto-debug debug,crypto -./usr/libdata/debug/usr/tests/crypto/libcrypto/h_enginetest.debug tests-crypto-debug debug,crypto -./usr/libdata/debug/usr/tests/crypto/libcrypto/h_evp_test.debug tests-crypto-debug debug,crypto -./usr/libdata/debug/usr/tests/crypto/libcrypto/h_exptest.debug tests-crypto-debug debug,crypto -./usr/libdata/debug/usr/tests/crypto/libcrypto/h_ideatest.debug tests-crypto-debug debug,crypto -./usr/libdata/debug/usr/tests/crypto/libcrypto/h_hmactest.debug tests-crypto-debug debug,crypto -./usr/libdata/debug/usr/tests/crypto/libcrypto/h_lhashtest.debug tests-crypto-debug debug,crypto -./usr/libdata/debug/usr/tests/crypto/libcrypto/h_md2test.debug tests-crypto-debug debug,crypto -./usr/libdata/debug/usr/tests/crypto/libcrypto/h_md4test.debug tests-crypto-debug debug,crypto -./usr/libdata/debug/usr/tests/crypto/libcrypto/h_md5test.debug tests-crypto-debug debug,crypto -./usr/libdata/debug/usr/tests/crypto/libcrypto/h_mdc2test.debug tests-crypto-debug debug,crypto -./usr/libdata/debug/usr/tests/crypto/libcrypto/h_randtest.debug tests-crypto-debug debug,crypto -./usr/libdata/debug/usr/tests/crypto/libcrypto/h_rc2test.debug tests-crypto-debug debug,crypto -./usr/libdata/debug/usr/tests/crypto/libcrypto/h_rc4test.debug tests-crypto-debug debug,crypto -./usr/libdata/debug/usr/tests/crypto/libcrypto/h_rc5test.debug tests-crypto-debug debug,crypto_rc5,crypto -./usr/libdata/debug/usr/tests/crypto/libcrypto/h_ripemdtest.debug tests-crypto-debug debug,crypto -./usr/libdata/debug/usr/tests/crypto/libcrypto/h_rsatest.debug tests-crypto-debug debug,crypto -./usr/libdata/debug/usr/tests/crypto/libcrypto/h_sha1test.debug tests-crypto-debug debug,crypto -./usr/libdata/debug/usr/tests/crypto/libcrypto/h_shatest.debug tests-crypto-debug debug,crypto -./usr/libdata/debug/usr/tests/crypto/libcrypto/h_srptest.debug tests-crypto-debug debug,crypto -./usr/libdata/debug/usr/tests/crypto/libcrypto/h_threadstest.debug tests-crypto-debug debug,crypto -./usr/libdata/debug/usr/tests/crypto/libcrypto/h_x509v3test.debug tests-crypto-debug debug,crypto ./usr/libdata/debug/usr/tests/fs tests-fs-debug ./usr/libdata/debug/usr/tests/dev tests-fs-debug ./usr/libdata/debug/usr/tests/dev/audio tests-fs-debug -./usr/libdata/debug/usr/tests/dev/audio/h_pad.debug tests-fs-debug debug,atf,rump ./usr/libdata/debug/usr/tests/dev/cgd tests-fs-debug ./usr/libdata/debug/usr/tests/dev/cgd/h_img2cgd tests-obsolete obsolete -./usr/libdata/debug/usr/tests/dev/cgd/h_img2cgd/h_img2cgd.debug tests-obsolete obsolete ./usr/libdata/debug/usr/tests/dev/md tests-fs-debug -./usr/libdata/debug/usr/tests/dev/md/h_mdserv.debug tests-fs-debug debug,atf,rump ./usr/libdata/debug/usr/tests/dev/scsipi tests-fs-debug -./usr/libdata/debug/usr/tests/dev/scsipi/t_cd.debug tests-fs-debug debug,atf,rump ./usr/libdata/debug/usr/tests/dev/sysmon tests-fs-debug -./usr/libdata/debug/usr/tests/dev/sysmon/t_swwdog.debug tests-fs-debug debug,atf,rump ./usr/libdata/debug/usr/tests/fs/ffs tests-fs-debug,rump -./usr/libdata/debug/usr/tests/fs/ffs/h_ffs_server.debug tests-fs-debug debug,atf,rump -./usr/libdata/debug/usr/tests/fs/ffs/h_quota2_server.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/fs/ffs/h_quota2_tests.debug tests-fs-debug debug,atf,rump -./usr/libdata/debug/usr/tests/fs/ffs/t_fifos.debug tests-fs-debug debug,atf,rump -./usr/libdata/debug/usr/tests/fs/ffs/t_mount.debug tests-fs-debug debug,atf,rump -./usr/libdata/debug/usr/tests/fs/ffs/t_quota2_1.debug tests-fs-debug debug,atf,rump -./usr/libdata/debug/usr/tests/fs/ffs/t_quota2_remount.debug tests-fs-debug debug,atf,rump -./usr/libdata/debug/usr/tests/fs/ffs/t_renamerace.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/fs/ffs/t_snapshot.debug tests-fs-debug debug,atf,rump -./usr/libdata/debug/usr/tests/fs/ffs/t_snapshot_log.debug tests-fs-debug debug,atf,rump -./usr/libdata/debug/usr/tests/fs/ffs/t_snapshot_v2.debug tests-fs-debug debug,atf,rump ./usr/libdata/debug/usr/tests/fs/fifofs tests-fs-debug,rump -./usr/libdata/debug/usr/tests/fs/fifofs/t_fifo.debug tests-fs-debug debug,atf,rump ./usr/libdata/debug/usr/tests/fs/hfs tests-fs-debug,rump -./usr/libdata/debug/usr/tests/fs/hfs/t_pathconvert.debug tests-fs-debug debug,atf,rump ./usr/libdata/debug/usr/tests/fs/kernfs tests-fs-debug,rump -./usr/libdata/debug/usr/tests/fs/kernfs/t_basic.debug tests-fs-debug debug,atf,rump ./usr/libdata/debug/usr/tests/fs/lfs tests-fs-debug,rump -./usr/libdata/debug/usr/tests/fs/lfs/t_pr.debug tests-fs-debug debug,atf,rump ./usr/libdata/debug/usr/tests/fs/msdosfs tests-fs-debug,rump -./usr/libdata/debug/usr/tests/fs/msdosfs/t_snapshot.debug tests-fs-debug debug,atf,rump ./usr/libdata/debug/usr/tests/fs/nfs tests-fs-debug,rump -./usr/libdata/debug/usr/tests/fs/nfs/t_mountd.debug tests-fs-debug debug,atf,rump ./usr/libdata/debug/usr/tests/fs/nfs/nfsservice tests-fs-debug,rump -./usr/libdata/debug/usr/tests/fs/nfs/nfsservice/rumpnfsd.debug tests-fs-debug debug,atf,rump ./usr/libdata/debug/usr/tests/fs/nullfs tests-fs-debug,rump -./usr/libdata/debug/usr/tests/fs/nullfs/t_basic.debug tests-fs-debug debug,atf,rump ./usr/libdata/debug/usr/tests/fs/psshfs tests-fs-debug,rump -./usr/libdata/debug/usr/tests/fs/psshfs/h_have_puffs.debug tests-fs-debug debug,atf,rump ./usr/libdata/debug/usr/tests/fs/ptyfs tests-fs-debug,rump -./usr/libdata/debug/usr/tests/fs/ptyfs/t_ptyfs.debug tests-fs-debug debug,atf,rump -./usr/libdata/debug/usr/tests/fs/ptyfs/t_nullpts.debug tests-fs-debug debug,atf,rump ./usr/libdata/debug/usr/tests/fs/puffs tests-fs-debug,rump -./usr/libdata/debug/usr/tests/fs/puffs/h_have_puffs.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/fs/puffs/t_basic.debug tests-fs-debug debug,atf,rump -./usr/libdata/debug/usr/tests/fs/puffs/t_fuzz.debug tests-fs-debug debug,atf,rump -./usr/libdata/debug/usr/tests/fs/puffs/t_io.debug tests-fs-debug debug,atf,rump ./usr/libdata/debug/usr/tests/fs/puffs/h_dtfs tests-fs-debug,rump -./usr/libdata/debug/usr/tests/fs/puffs/h_dtfs/h_dtfs.debug tests-fs-debug debug,atf,rump ./usr/libdata/debug/usr/tests/fs/tmpfs tests-fs-debug,rump -./usr/libdata/debug/usr/tests/fs/tmpfs/h_tools.debug tests-fs-debug debug,atf,rump -./usr/libdata/debug/usr/tests/fs/tmpfs/t_renamerace.debug tests-fs-debug debug,atf,rump ./usr/libdata/debug/usr/tests/fs/umapfs tests-fs-debug,rump -./usr/libdata/debug/usr/tests/fs/umapfs/t_basic.debug tests-fs-debug debug,atf,rump ./usr/libdata/debug/usr/tests/fs/union tests-fs-debug,rump -./usr/libdata/debug/usr/tests/fs/union/t_basic.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/fs/union/t_pr.debug tests-fs-debug debug,atf,rump ./usr/libdata/debug/usr/tests/fs/vfs tests-fs-debug,rump -./usr/libdata/debug/usr/tests/fs/vfs/t_full.debug tests-fs-debug debug,atf,rump -./usr/libdata/debug/usr/tests/fs/vfs/t_io.debug tests-fs-debug debug,atf,rump -./usr/libdata/debug/usr/tests/fs/vfs/t_renamerace.debug tests-fs-debug debug,atf,rump -./usr/libdata/debug/usr/tests/fs/vfs/t_rmdirrace.debug tests-fs-debug debug,atf,rump -./usr/libdata/debug/usr/tests/fs/vfs/t_ro.debug tests-fs-debug debug,atf,rump -./usr/libdata/debug/usr/tests/fs/vfs/t_union.debug tests-obsolete debug,atf,rump -./usr/libdata/debug/usr/tests/fs/vfs/t_unpriv.debug tests-fs-debug debug,atf,rump -./usr/libdata/debug/usr/tests/fs/vfs/t_vfsops.debug tests-fs-debug debug,atf,rump -./usr/libdata/debug/usr/tests/fs/vfs/t_vnops.debug tests-fs-debug debug,atf,rump ./usr/libdata/debug/usr/tests/include tests-include-tests ./usr/libdata/debug/usr/tests/include/machine tests-include-tests -./usr/libdata/debug/usr/tests/include/machine/t_bswap.debug tests-include-tests debug,atf ./usr/libdata/debug/usr/tests/include/sys tests-include-tests -./usr/libdata/debug/usr/tests/include/sys/t_bitops.debug tests-include-tests debug,atf -./usr/libdata/debug/usr/tests/include/sys/t_bootblock.debug tests-include-tests debug,atf -./usr/libdata/debug/usr/tests/include/sys/t_cdefs.debug tests-include-tests debug,atf -./usr/libdata/debug/usr/tests/include/sys/t_socket.debug tests-include-tests debug,atf,rump -./usr/libdata/debug/usr/tests/include/sys/t_tree.debug tests-include-tests debug,atf -./usr/libdata/debug/usr/tests/include/sys/t_types.debug tests-include-tests debug,atf -./usr/libdata/debug/usr/tests/include/t_bitstring.debug tests-include-tests debug,atf -./usr/libdata/debug/usr/tests/include/t_bswap.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/include/t_errno.debug tests-include-tests debug,atf -./usr/libdata/debug/usr/tests/include/t_glob.debug tests-include-tests debug,atf -./usr/libdata/debug/usr/tests/include/t_inttypes.debug tests-include-tests debug,atf -./usr/libdata/debug/usr/tests/include/t_limits.debug tests-include-tests debug,atf -./usr/libdata/debug/usr/tests/include/t_netdb.debug tests-include-tests debug,atf -./usr/libdata/debug/usr/tests/include/t_paths.debug tests-include-tests debug,atf -./usr/libdata/debug/usr/tests/include/t_stdint.debug tests-include-tests debug,atf -./usr/libdata/debug/usr/tests/include/t_types.debug tests-obsolete obsolete ./usr/libdata/debug/usr/tests/ipf tests-ipf-tests ./usr/libdata/debug/usr/tests/kernel tests-kernel-tests -./usr/libdata/debug/usr/tests/kernel/h_ps_strings1.debug tests-kernel-tests debug,atf -./usr/libdata/debug/usr/tests/kernel/h_ps_strings2.debug tests-kernel-tests debug,atf ./usr/libdata/debug/usr/tests/kernel/kqueue tests-kernel-tests ./usr/libdata/debug/usr/tests/kernel/kqueue/read tests-kernel-tests -./usr/libdata/debug/usr/tests/kernel/kqueue/read/t_fifo.debug tests-kernel-tests debug,atf -./usr/libdata/debug/usr/tests/kernel/kqueue/read/t_file.debug tests-kernel-tests debug,atf -./usr/libdata/debug/usr/tests/kernel/kqueue/read/t_file2.debug tests-kernel-tests debug,atf -./usr/libdata/debug/usr/tests/kernel/kqueue/read/t_pipe.debug tests-kernel-tests debug,atf -./usr/libdata/debug/usr/tests/kernel/kqueue/read/t_ttypty.debug tests-kernel-tests debug,atf -./usr/libdata/debug/usr/tests/kernel/kqueue/t_ioctl.debug tests-kernel-tests debug,atf -./usr/libdata/debug/usr/tests/kernel/kqueue/t_proc1.debug tests-kernel-tests debug,atf -./usr/libdata/debug/usr/tests/kernel/kqueue/t_proc2.debug tests-kernel-tests debug,atf -./usr/libdata/debug/usr/tests/kernel/kqueue/t_sig.debug tests-kernel-tests debug,atf ./usr/libdata/debug/usr/tests/kernel/kqueue/write tests-kernel-tests -./usr/libdata/debug/usr/tests/kernel/kqueue/write/t_fifo.debug tests-kernel-tests debug,atf -./usr/libdata/debug/usr/tests/kernel/kqueue/write/t_pipe.debug tests-kernel-tests debug,atf -./usr/libdata/debug/usr/tests/kernel/kqueue/write/t_ttypty.debug tests-kernel-tests debug,atf ./usr/libdata/debug/usr/tests/kernel/posix_spawn tests-kernel-tests obsolete -./usr/libdata/debug/usr/tests/kernel/posix_spawn/t_spawn.debug tests-kernel-tests obsolete -./usr/libdata/debug/usr/tests/kernel/posix_spawn/t_spawnattr.debug tests-kernel-tests obsolete -./usr/libdata/debug/usr/tests/kernel/posix_spawn/t_fileactions.debug tests-kernel-tests obsolete -./usr/libdata/debug/usr/tests/kernel/posix_spawn/h_spawn.debug tests-kernel-tests obsolete -./usr/libdata/debug/usr/tests/kernel/posix_spawn/h_fileactions.debug tests-kernel-tests obsolete -./usr/libdata/debug/usr/tests/kernel/posix_spawn/h_spawnattr.debug tests-kernel-tests obsolete -./usr/libdata/debug/usr/tests/kernel/t_extattrctl.debug tests-kernel-tests debug,atf,rump -./usr/libdata/debug/usr/tests/kernel/t_extent.debug tests-kernel-tests debug,atf -./usr/libdata/debug/usr/tests/kernel/t_filedesc.debug tests-kernel-tests debug,atf,rump -./usr/libdata/debug/usr/tests/kernel/t_lock.debug tests-kernel-tests debug,atf -./usr/libdata/debug/usr/tests/kernel/t_lwpctl.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/kernel/t_mkdir.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/kernel/t_pipe.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/kernel/t_poll3w.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/kernel/t_pollts.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/kernel/t_posix_fadvise.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/kernel/t_pty.debug tests-kernel-tests debug,atf -./usr/libdata/debug/usr/tests/kernel/t_rnd.debug tests-kernel-tests debug,atf,rump -./usr/libdata/debug/usr/tests/kernel/t_sigaction.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/kernel/t_subr_prf.debug tests-kernel-tests debug,atf -./usr/libdata/debug/usr/tests/kernel/t_time.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/kernel/t_ucontext.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/kernel/t_writev.debug tests-obsolete obsolete ./usr/libdata/debug/usr/tests/kernel/tty tests-kernel-tests -./usr/libdata/debug/usr/tests/kernel/tty/t_pr.debug tests-kernel-tests debug,atf,rump +./usr/libdata/debug/usr/tests/kyua-cli tests-kyua-tests +./usr/libdata/debug/usr/tests/kyua-cli/bootstrap tests-kyua-tests +./usr/libdata/debug/usr/tests/kyua-cli/cli tests-kyua-tests +./usr/libdata/debug/usr/tests/kyua-cli/engine tests-kyua-tests +./usr/libdata/debug/usr/tests/kyua-cli/engine/drivers tests-kyua-tests +./usr/libdata/debug/usr/tests/kyua-cli/examples tests-kyua-tests +./usr/libdata/debug/usr/tests/kyua-cli/integration tests-kyua-tests +./usr/libdata/debug/usr/tests/kyua-cli/integration/helpers tests-kyua-tests +./usr/libdata/debug/usr/tests/kyua-cli/store tests-kyua-tests +./usr/libdata/debug/usr/tests/kyua-cli/utils tests-kyua-tests +./usr/libdata/debug/usr/tests/kyua-cli/utils/cmdline tests-kyua-tests +./usr/libdata/debug/usr/tests/kyua-cli/utils/config tests-kyua-tests +./usr/libdata/debug/usr/tests/kyua-cli/utils/format tests-kyua-tests +./usr/libdata/debug/usr/tests/kyua-cli/utils/fs tests-kyua-tests +./usr/libdata/debug/usr/tests/kyua-cli/utils/logging tests-kyua-tests +./usr/libdata/debug/usr/tests/kyua-cli/utils/process tests-kyua-tests +./usr/libdata/debug/usr/tests/kyua-cli/utils/signals tests-kyua-tests +./usr/libdata/debug/usr/tests/kyua-cli/utils/sqlite tests-kyua-tests +./usr/libdata/debug/usr/tests/kyua-cli/utils/text tests-kyua-tests +./usr/libdata/debug/usr/tests/kyua-testers tests-kyua-tests ./usr/libdata/debug/usr/tests/lib tests-lib-debug ./usr/libdata/debug/usr/tests/lib/csu tests-lib-debug -./usr/libdata/debug/usr/tests/lib/csu/h_initfini.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/lib/csu/h_initfini1.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/csu/h_initfini2.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/csu/h_initfini3.debug tests-lib-debug debug,atf ./usr/libdata/debug/usr/tests/lib/libbluetooth tests-lib-debug -./usr/libdata/debug/usr/tests/lib/libbluetooth/t_bluetooth.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libbluetooth/t_sdp_data.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libbluetooth/t_sdp_get.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libbluetooth/t_sdp_match.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libbluetooth/t_sdp_put.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libbluetooth/t_sdp_set.debug tests-lib-debug debug,atf +./usr/libdata/debug/usr/tests/lib/libbpfjit tests-lib-debug ./usr/libdata/debug/usr/tests/lib/libc tests-lib-debug +./usr/libdata/debug/usr/tests/lib/libc/c063 tests-lib-debug ./usr/libdata/debug/usr/tests/lib/libc/db tests-lib-debug -./usr/libdata/debug/usr/tests/lib/libc/db/h_db.debug tests-lib-debug debug,atf ./usr/libdata/debug/usr/tests/lib/libc/gen tests-lib-debug ./usr/libdata/debug/usr/tests/lib/libc/gen/posix_spawn tests-kernel-tests -./usr/libdata/debug/usr/tests/lib/libc/gen/posix_spawn/t_spawn.debug tests-kernel-tests debug,atf -./usr/libdata/debug/usr/tests/lib/libc/gen/posix_spawn/t_spawnattr.debug tests-kernel-tests debug,atf -./usr/libdata/debug/usr/tests/lib/libc/gen/posix_spawn/t_fileactions.debug tests-kernel-tests debug,atf -./usr/libdata/debug/usr/tests/lib/libc/gen/posix_spawn/h_spawn.debug tests-kernel-tests debug,atf -./usr/libdata/debug/usr/tests/lib/libc/gen/posix_spawn/h_fileactions.debug tests-kernel-tests debug,atf -./usr/libdata/debug/usr/tests/lib/libc/gen/posix_spawn/h_spawnattr.debug tests-kernel-tests debug,atf -./usr/libdata/debug/usr/tests/lib/libc/gen/t_alarm.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/gen/t_assert.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/gen/t_basedirname.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/gen/t_closefrom.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/gen/t_cpuset.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/gen/t_dir.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/gen/t_fmtcheck.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/gen/t_fnmatch.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/gen/t_fpclassify.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/gen/t_fpsetmask.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/gen/t_fpsetround.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/gen/t_ftok.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/gen/t_getcwd.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/gen/t_getgrent.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/gen/t_glob.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/gen/t_glob_star.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/lib/libc/gen/t_humanize_number.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/gen/t_isnan.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/gen/t_ldexp.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/lib/libc/gen/t_nice.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/gen/t_pause.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/gen/t_raise.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/gen/t_randomid.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/gen/t_realpath.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/gen/t_rbstress.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/lib/libc/gen/t_setdomainname.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/gen/t_sethostname.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/gen/t_siginfo.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/gen/t_syslog.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/gen/t_syslog_pthread.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/lib/libc/gen/t_time.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/gen/t_ttyname.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/gen/t_vis.debug tests-lib-debug debug,atf ./usr/libdata/debug/usr/tests/lib/libc/getaddrinfo tests-obsolete obsolete ./usr/libdata/debug/usr/tests/lib/libc/getaddrinfo/data tests-obsolete obsolete ./usr/libdata/debug/usr/tests/lib/libc/getaddrinfo/h_gai tests-obsolete obsolete -./usr/libdata/debug/usr/tests/lib/libc/h_atexit.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/lib/libc/h_nsd_recurse.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/lib/libc/h_protoent.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/lib/libc/h_servent.debug tests-obsolete obsolete ./usr/libdata/debug/usr/tests/lib/libc/hash tests-lib-debug -./usr/libdata/debug/usr/tests/lib/libc/hash/h_hash.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/hash/t_sha2.debug tests-lib-debug debug,atf ./usr/libdata/debug/usr/tests/lib/libc/ieeefp tests-obsolete obsolete -./usr/libdata/debug/usr/tests/lib/libc/ieeefp/t_except.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/lib/libc/ieeefp/t_nan_inf.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/lib/libc/ieeefp/t_round.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/lib/libc/ieeefp/t_subnormal.debug tests-obsolete obsolete ./usr/libdata/debug/usr/tests/lib/libc/locale tests-lib-debug -./usr/libdata/debug/usr/tests/lib/libc/locale/t_ctype1.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/lib/libc/locale/t_ctype2.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/lib/libc/locale/t_mbrtowc.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/locale/t_mbstowcs.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/locale/t_mbtowc.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/locale/t_wcscspn.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/locale/t_wcspbrk.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/locale/t_wcsspn.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/locale/t_wcstod.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/locale/t_wctomb.debug tests-lib-debug debug,atf ./usr/libdata/debug/usr/tests/lib/libc/inet tests-lib-debug -./usr/libdata/debug/usr/tests/lib/libc/inet/t_inet_network.debug tests-lib-debug debug,atf ./usr/libdata/debug/usr/tests/lib/libc/net tests-lib-debug ./usr/libdata/debug/usr/tests/lib/libc/net/getaddrinfo tests-lib-debug -./usr/libdata/debug/usr/tests/lib/libc/net/getaddrinfo/h_gai.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/net/h_nsd_recurse.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/net/h_protoent.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/net/h_servent.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/net/t_ether_aton.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/net/t_getprotoent.debug tests-lib-debug debug,atf ./usr/libdata/debug/usr/tests/lib/libc/regex tests-lib-debug -./usr/libdata/debug/usr/tests/lib/libc/regex/t_exhaust.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/regex/h_regex.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/regex/h_regex_att.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/lib/libc/regex/t_regex_att.debug tests-lib-debug debug,atf ./usr/libdata/debug/usr/tests/lib/libc/rpc tests-lib-debug -./usr/libdata/debug/usr/tests/lib/libc/rpc/t_xdr.debug tests-lib-debug debug,atf ./usr/libdata/debug/usr/tests/lib/libc/setjmp tests-lib-debug -./usr/libdata/debug/usr/tests/lib/libc/setjmp/t_threadjmp.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/setjmp/t_setjmp.debug tests-lib-debug debug,atf ./usr/libdata/debug/usr/tests/lib/libc/ssp tests-lib-debug -./usr/libdata/debug/usr/tests/lib/libc/ssp/h_fgets.debug tests-lib-debug debug,atf,ssp -./usr/libdata/debug/usr/tests/lib/libc/ssp/h_getcwd.debug tests-lib-debug debug,atf,ssp -./usr/libdata/debug/usr/tests/lib/libc/ssp/h_gets.debug tests-lib-debug debug,atf,ssp -./usr/libdata/debug/usr/tests/lib/libc/ssp/h_memcpy.debug tests-lib-debug debug,atf,ssp -./usr/libdata/debug/usr/tests/lib/libc/ssp/h_memmove.debug tests-lib-debug debug,atf,ssp -./usr/libdata/debug/usr/tests/lib/libc/ssp/h_memset.debug tests-lib-debug debug,atf,ssp -./usr/libdata/debug/usr/tests/lib/libc/ssp/h_raw.debug tests-lib-debug debug,atf,ssp -./usr/libdata/debug/usr/tests/lib/libc/ssp/h_read.debug tests-lib-debug debug,atf,ssp -./usr/libdata/debug/usr/tests/lib/libc/ssp/h_readlink.debug tests-lib-debug debug,atf,ssp -./usr/libdata/debug/usr/tests/lib/libc/ssp/h_snprintf.debug tests-lib-debug debug,atf,ssp -./usr/libdata/debug/usr/tests/lib/libc/ssp/h_sprintf.debug tests-lib-debug debug,atf,ssp -./usr/libdata/debug/usr/tests/lib/libc/ssp/h_strcat.debug tests-lib-debug debug,atf,ssp -./usr/libdata/debug/usr/tests/lib/libc/ssp/h_strcpy.debug tests-lib-debug debug,atf,ssp -./usr/libdata/debug/usr/tests/lib/libc/ssp/h_strncat.debug tests-lib-debug debug,atf,ssp -./usr/libdata/debug/usr/tests/lib/libc/ssp/h_strncpy.debug tests-lib-debug debug,atf,ssp -./usr/libdata/debug/usr/tests/lib/libc/ssp/h_vsnprintf.debug tests-lib-debug debug,atf,ssp -./usr/libdata/debug/usr/tests/lib/libc/ssp/h_vsprintf.debug tests-lib-debug debug,atf,ssp ./usr/libdata/debug/usr/tests/lib/libc/stdio tests-lib-debug -./usr/libdata/debug/usr/tests/lib/libc/stdio/t_clearerr.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/stdio/t_fflush.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/stdio/t_fmemopen.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/stdio/t_fopen.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/stdio/t_fputc.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/stdio/t_format.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/lib/libc/stdio/t_popen.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/stdio/t_printf.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/stdio/t_scanf.debug tests-lib-debug debug,atf ./usr/libdata/debug/usr/tests/lib/libc/stdlib tests-lib-debug -./usr/libdata/debug/usr/tests/lib/libc/stdlib/h_atexit.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/stdlib/h_getopt.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/stdlib/h_getopt_long.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/stdlib/t_abs.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/stdlib/t_atoi.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/stdlib/t_div.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/stdlib/t_environment.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/lib/libc/stdlib/t_environment_pth.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/lib/libc/stdlib/t_exit.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/stdlib/t_getenv.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/stdlib/t_getenv_thread.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/stdlib/t_hsearch.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/stdlib/t_mi_vector_hash.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/stdlib/t_posix_memalign.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/stdlib/t_random.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/stdlib/t_strtod.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/stdlib/t_strtol.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/stdlib/t_strtox.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/lib/libc/stdlib/t_system.debug tests-lib-debug debug,atf ./usr/libdata/debug/usr/tests/lib/libc/string tests-lib-debug -./usr/libdata/debug/usr/tests/lib/libc/string/t_memchr.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/string/t_memcpy.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/string/t_memmem.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/string/t_memset.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/string/t_popcount.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/string/t_strcat.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/string/t_strchr.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/string/t_strcmp.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/string/t_strcpy.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/string/t_strcspn.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/string/t_strerror.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/string/t_stresep.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/string/t_string.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/lib/libc/string/t_strlen.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/string/t_strpbrk.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/string/t_strrchr.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/string/t_strspn.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/string/t_swab.debug tests-lib-debug debug,atf ./usr/libdata/debug/usr/tests/lib/libc/sys tests-lib-debug -./usr/libdata/debug/usr/tests/lib/libc/sys/t_access.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/sys/t_cerror.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/lib/libc/sys/t_chroot.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/sys/t_clock_gettime.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/sys/t_clone.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/sys/t_connect.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/sys/t_context.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/lib/libc/sys/t_dup.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/sys/t_fsync.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/sys/t_getcontext.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/sys/t_getgroups.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/sys/t_getitimer.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/sys/t_getlogin.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/sys/t_getpid.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/sys/t_getrusage.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/sys/t_getsid.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/sys/t_gettimeofday.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/sys/t_issetugid.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/sys/t_kevent.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/sys/t_kill.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/sys/t_link.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/sys/t_listen.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/sys/t_lwp_ctl.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/sys/t_lwp_create.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/sys/t_mincore.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/sys/t_mkdir.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/sys/t_mkfifo.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/sys/t_mknod.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/sys/t_mlock.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/sys/t_mmap.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/sys/t_mprotect.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/sys/t_msgctl.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/sys/t_msgget.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/sys/t_msgrcv.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/sys/t_msgsnd.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/sys/t_msync.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/sys/t_nanosleep.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/sys/t_pipe.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/sys/t_pipe2.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/sys/t_poll.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/sys/t_posix_fadvise.debug tests-lib-debug debug,atf,rump -./usr/libdata/debug/usr/tests/lib/libc/sys/t_recvmmsg.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/sys/t_revoke.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/sys/t_select.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/sys/t_setrlimit.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/sys/t_setuid.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/sys/t_sigaction.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/sys/t_sigqueue.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/sys/t_socketpair.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/sys/t_stat.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/sys/t_swapcontext.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/sys/t_timer_create.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/sys/t_truncate.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/sys/t_ucontext.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/sys/t_umask.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/sys/t_unlink.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/sys/t_write.debug tests-lib-debug debug,atf ./usr/libdata/debug/usr/tests/lib/libc/termios tests-lib-debug -./usr/libdata/debug/usr/tests/lib/libc/termios/t_tcsetpgrp.debug tests-lib-debug debug,atf ./usr/libdata/debug/usr/tests/lib/libc/tls tests-lib-debug -./usr/libdata/debug/usr/tests/lib/libc/tls/t_tls_static.debug tests-lib-debug debug,atf ./usr/libdata/debug/usr/tests/lib/libc/ttyio tests-lib-debug -./usr/libdata/debug/usr/tests/lib/libc/ttyio/t_ptm.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/ttyio/t_ttyio.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/t_cerror.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/lib/libc/t_clone.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/lib/libc/t_context.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/lib/libc/t_convfp.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/t_cdb.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/t_gdtoa.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/t_hsearch.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/lib/libc/t_inet.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/lib/libc/t_mktime.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/lib/libc/t_ptm.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/lib/libc/t_randomid.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/lib/libc/t_strptime.debug tests-obsolete obsolete ./usr/libdata/debug/usr/tests/lib/libc/time tests-lib-debug -./usr/libdata/debug/usr/tests/lib/libc/time/t_mktime.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/time/t_strptime.debug tests-lib-debug debug,atf ./usr/libdata/debug/usr/tests/lib/libcrypt tests-lib-debug -./usr/libdata/debug/usr/tests/lib/libcrypt/t_crypt.debug tests-lib-debug debug,atf ./usr/libdata/debug/usr/tests/lib/libcurses tests-lib-debug -./usr/libdata/debug/usr/tests/lib/libcurses/director.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libcurses/slave.debug tests-lib-debug debug,atf ./usr/libdata/debug/usr/tests/lib/libdes tests-lib-debug -./usr/libdata/debug/usr/tests/lib/libdes/t_des.debug tests-lib-debug debug,atf,crypto ./usr/libdata/debug/usr/tests/lib/semaphore tests-lib-debug ./usr/libdata/debug/usr/tests/lib/semaphore/pthread tests-lib-debug -./usr/libdata/debug/usr/tests/lib/semaphore/pthread/t_sem_pth.debug tests-lib-debug debug,atf,rump ./usr/libdata/debug/usr/tests/lib/libevent tests-lib-debug -./usr/libdata/debug/usr/tests/lib/libevent/h_event.debug tests-lib-debug debug,atf ./usr/libdata/debug/usr/tests/lib/libexecinfo tests-lib-debug -./usr/libdata/debug/usr/tests/lib/libexecinfo/t_backtrace.debug tests-lib-debug debug,atf +./usr/libdata/debug/usr/tests/lib/liblutok tests-lutok-debug ./usr/libdata/debug/usr/tests/lib/libm tests-lib-debug -./usr/libdata/debug/usr/tests/lib/libm/t_acos.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libm/t_asin.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libm/t_atan.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libm/t_cbrt.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libm/t_ceil.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libm/t_cos.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libm/t_cosh.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libm/t_erf.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libm/t_exp.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libm/t_floor.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/lib/libm/t_infinity.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libm/t_ldexp.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libm/t_log.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libm/t_libm.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/lib/libm/t_pow.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libm/t_round.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libm/t_scalbn.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libm/t_sin.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libm/t_sinh.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libm/t_sqrt.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libm/t_tan.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libm/t_tanh.debug tests-lib-debug debug,atf ./usr/libdata/debug/usr/tests/lib/libobjc tests-lib-debug -./usr/libdata/debug/usr/tests/lib/libobjc/t_threads.debug tests-lib-debug debug,atf,gcccmds ./usr/libdata/debug/usr/tests/lib/libposix tests-lib-debug ./usr/libdata/debug/usr/tests/lib/libposix/bsd tests-lib-debug -./usr/libdata/debug/usr/tests/lib/libposix/bsd/t_rename.debug tests-lib-debug debug,atf ./usr/libdata/debug/usr/tests/lib/libposix/posix1 tests-lib-debug -./usr/libdata/debug/usr/tests/lib/libposix/posix1/t_rename.debug tests-lib-debug debug,atf ./usr/libdata/debug/usr/tests/lib/libposix/posix2 tests-lib-debug -./usr/libdata/debug/usr/tests/lib/libposix/posix2/t_rename.debug tests-lib-debug debug,atf ./usr/libdata/debug/usr/tests/lib/libppath tests-lib-debug -./usr/libdata/debug/usr/tests/lib/libppath/t_ppath.debug tests-lib-debug debug,atf ./usr/libdata/debug/usr/tests/lib/libprop tests-lib-debug -./usr/libdata/debug/usr/tests/lib/libprop/t_basic.debug tests-lib-debug debug,atf ./usr/libdata/debug/usr/tests/lib/libpthread tests-lib-debug -./usr/libdata/debug/usr/tests/lib/libpthread/h_atexit.debug tests-lib-tests debug,atf -./usr/libdata/debug/usr/tests/lib/libpthread/h_cancel.debug tests-lib-tests debug,atf -./usr/libdata/debug/usr/tests/lib/libpthread/h_exit.debug tests-lib-tests debug,atf -./usr/libdata/debug/usr/tests/lib/libpthread/h_resolv.debug tests-lib-tests debug,atf -./usr/libdata/debug/usr/tests/lib/libpthread/t_barrier.debug tests-lib-tests debug,atf -./usr/libdata/debug/usr/tests/lib/libpthread/t_cond.debug tests-lib-tests debug,atf -./usr/libdata/debug/usr/tests/lib/libpthread/t_detach.debug tests-lib-tests debug,atf -./usr/libdata/debug/usr/tests/lib/libpthread/t_equal.debug tests-lib-tests debug,atf -./usr/libdata/debug/usr/tests/lib/libpthread/t_fork.debug tests-lib-tests debug,atf -./usr/libdata/debug/usr/tests/lib/libpthread/t_fpu.debug tests-lib-tests debug,atf -./usr/libdata/debug/usr/tests/lib/libpthread/t_join.debug tests-lib-tests debug,atf -./usr/libdata/debug/usr/tests/lib/libpthread/t_kill.debug tests-lib-tests debug,atf -./usr/libdata/debug/usr/tests/lib/libpthread/t_mutex.debug tests-lib-tests debug,atf -./usr/libdata/debug/usr/tests/lib/libpthread/t_name.debug tests-lib-tests debug,atf -./usr/libdata/debug/usr/tests/lib/libpthread/t_once.debug tests-lib-tests debug,atf -./usr/libdata/debug/usr/tests/lib/libpthread/t_preempt.debug tests-lib-tests debug,atf -./usr/libdata/debug/usr/tests/lib/libpthread/t_rwlock.debug tests-lib-tests debug,atf -./usr/libdata/debug/usr/tests/lib/libpthread/t_sem.debug tests-lib-tests debug,atf -./usr/libdata/debug/usr/tests/lib/libpthread/t_sigmask.debug tests-lib-tests debug,atf -./usr/libdata/debug/usr/tests/lib/libpthread/t_sigsuspend.debug tests-lib-tests debug,atf -./usr/libdata/debug/usr/tests/lib/libpthread/t_siglongjmp.debug tests-lib-tests debug,atf -./usr/libdata/debug/usr/tests/lib/libpthread/t_sleep.debug tests-lib-tests debug,atf -./usr/libdata/debug/usr/tests/lib/libpthread/t_status.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/lib/libpthread/t_swapcontext.debug tests-lib-tests debug,atf ./usr/libdata/debug/usr/tests/lib/librt tests-lib-debug -./usr/libdata/debug/usr/tests/lib/librt/t_sched.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/librt/t_sem.debug tests-lib-debug debug,atf ./usr/libdata/debug/usr/tests/lib/librumpclient tests-lib-debug -./usr/libdata/debug/usr/tests/lib/librumpclient/h_exec.debug tests-lib-debug debug,atf,rump -./usr/libdata/debug/usr/tests/lib/librumpclient/h_execthr.debug tests-lib-debug debug,atf,rump -./usr/libdata/debug/usr/tests/lib/librumpclient/h_ution.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/lib/librumpclient/t_fd.debug tests-lib-debug debug,atf,rump ./usr/libdata/debug/usr/tests/lib/librumphijack tests-lib-debug -./usr/libdata/debug/usr/tests/lib/librumphijack/h_client.debug tests-lib-debug debug,atf,rump -./usr/libdata/debug/usr/tests/lib/librumphijack/h_cwd.debug tests-lib-debug debug,atf,rump -./usr/libdata/debug/usr/tests/lib/librumphijack/h_netget.debug tests-lib-debug debug,atf,rump ./usr/libdata/debug/usr/tests/lib/libskey tests-lib-debug -./usr/libdata/debug/usr/tests/lib/libskey/t_algorithms.debug tests-lib-debug debug,atf,skey +./usr/libdata/debug/usr/tests/lib/libsljit tests-lib-debug ./usr/libdata/debug/usr/tests/lib/libtre tests-lib-debug -./usr/libdata/debug/usr/tests/lib/libtre/h_regex_att.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/lib/libtre/t_exhaust.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libtre/t_regex_att.debug tests-lib-debug debug,atf ./usr/libdata/debug/usr/tests/lib/libutil tests-lib-debug -./usr/libdata/debug/usr/tests/lib/libutil/t_efun.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libutil/t_parsedate.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libutil/t_pidfile.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libutil/t_snprintb.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libutil/t_sockaddr_snprintf.debug tests-lib-debug debug,atf ./usr/libdata/debug/usr/tests/libexec tests-lib-debug ./usr/libdata/debug/usr/tests/libexec/ld.elf_so tests-libexec-debug -./usr/libdata/debug/usr/tests/libexec/ld.elf_so/h_df_1_noopen1.debug tests-libexec-debug debug,atf -./usr/libdata/debug/usr/tests/libexec/ld.elf_so/h_df_1_noopen2.debug tests-libexec-debug debug,atf -./usr/libdata/debug/usr/tests/libexec/ld.elf_so/h_dl_symver_v0.debug tests-libexec-debug debug,atf -./usr/libdata/debug/usr/tests/libexec/ld.elf_so/h_dl_symver_v1.debug tests-libexec-debug debug,atf -./usr/libdata/debug/usr/tests/libexec/ld.elf_so/h_dl_symver_v2.debug tests-libexec-debug debug,atf ./usr/libdata/debug/usr/tests/libexec/ld.elf_so/h_helper_symver_dso0 tests-libexec-debug ./usr/libdata/debug/usr/tests/libexec/ld.elf_so/h_helper_symver_dso1 tests-libexec-debug ./usr/libdata/debug/usr/tests/libexec/ld.elf_so/h_helper_symver_dso2 tests-libexec-debug -./usr/libdata/debug/usr/tests/libexec/ld.elf_so/h_locking.debug tests-libexec-debug debug,atf -./usr/libdata/debug/usr/tests/libexec/ld.elf_so/t_dlerror-cleared.debug tests-libexec-debug debug,atf -./usr/libdata/debug/usr/tests/libexec/ld.elf_so/t_dlerror-false.debug tests-libexec-debug debug,atf -./usr/libdata/debug/usr/tests/libexec/ld.elf_so/t_dlinfo.debug tests-libexec-debug debug,atf -./usr/libdata/debug/usr/tests/libexec/ld.elf_so/t_dlvsym.debug tests-libexec-debug debug,atf ./usr/libdata/debug/usr/tests/modules tests-sys-debug ./usr/libdata/debug/usr/tests/net tests-net-debug ./usr/libdata/debug/usr/tests/net/bpf tests-net-debug -./usr/libdata/debug/usr/tests/net/bpf/t_bpf.debug tests-net-debug debug,atf,rump -./usr/libdata/debug/usr/tests/net/bpf/t_div-by-zero.debug tests-net-debug debug,atf,rump ./usr/libdata/debug/usr/tests/net/bpfilter tests-net-debug -./usr/libdata/debug/usr/tests/net/bpfilter/t_bpfilter.debug tests-net-debug debug,atf,rump ./usr/libdata/debug/usr/tests/net/carp tests-net-debug -./usr/libdata/debug/usr/tests/net/carp/t_basic.debug tests-net-debug debug,atf,rump ./usr/libdata/debug/usr/tests/net/fdpass tests-net-debug -./usr/libdata/debug/usr/tests/net/fdpass/fdpass32.debug tests-net-debug debug,atf,rump -./usr/libdata/debug/usr/tests/net/fdpass/fdpass64.debug tests-net-debug debug,atf,rump ./usr/libdata/debug/usr/tests/net/icmp tests-net-debug -./usr/libdata/debug/usr/tests/net/icmp/t_forward.debug tests-net-debug debug,atf,rump -./usr/libdata/debug/usr/tests/net/icmp/t_ping.debug tests-net-debug debug,atf,rump ./usr/libdata/debug/usr/tests/net/if tests-net-debug -./usr/libdata/debug/usr/tests/net/if/t_compat.debug tests-net-debug debug,atf,rump ./usr/libdata/debug/usr/tests/net/if_loop tests-net-debug -./usr/libdata/debug/usr/tests/net/if_loop/t_pr.debug tests-net-debug debug,atf,rump ./usr/libdata/debug/usr/tests/net/net tests-net-debug -./usr/libdata/debug/usr/tests/net/net/t_raw.debug tests-net-debug debug,atf,rump -./usr/libdata/debug/usr/tests/net/net/t_unix.debug tests-net-debug debug,atf,rump ./usr/libdata/debug/usr/tests/net/sys tests-net-debug -./usr/libdata/debug/usr/tests/net/sys/t_connect.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/net/sys/t_listen.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/net/sys/t_rfc6056.debug tests-net-debug debug,atf -./usr/libdata/debug/usr/tests/net/sys/t_socketpair.debug tests-obsolete obsolete ./usr/libdata/debug/usr/tests/rump tests-syscall-debug,rump ./usr/libdata/debug/usr/tests/rump/modautoload tests-syscall-debug,rump -./usr/libdata/debug/usr/tests/rump/modautoload/t_modautoload.debug tests-syscall-debug debug,atf,rump ./usr/libdata/debug/usr/tests/rump/rumpkern tests-syscall-debug,rump -./usr/libdata/debug/usr/tests/rump/rumpkern/t_copy.debug tests-syscall-debug debug,atf,rump -./usr/libdata/debug/usr/tests/rump/rumpkern/t_kern.debug tests-syscall-debug debug,atf,rump -./usr/libdata/debug/usr/tests/rump/rumpkern/t_lwproc.debug tests-syscall-debug debug,atf,rump -./usr/libdata/debug/usr/tests/rump/rumpkern/t_modcmd.debug tests-syscall-debug debug,atf,rump -./usr/libdata/debug/usr/tests/rump/rumpkern/t_modlinkset.debug tests-syscall-debug debug,atf,rump -./usr/libdata/debug/usr/tests/rump/rumpkern/t_signals.debug tests-syscall-debug debug,atf,rump -./usr/libdata/debug/usr/tests/rump/rumpkern/t_threads.debug tests-syscall-debug debug,atf,rump -./usr/libdata/debug/usr/tests/rump/rumpkern/t_tsleep.debug tests-syscall-debug debug,atf,rump -./usr/libdata/debug/usr/tests/rump/rumpkern/t_vm.debug tests-syscall-debug debug,atf,rump ./usr/libdata/debug/usr/tests/rump/rumpkern/h_client tests-syscall-debug,rump -./usr/libdata/debug/usr/tests/rump/rumpkern/h_client/h_reboot.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/rump/rumpkern/h_client/h_forkcli.debug tests-syscall-debug debug,atf,rump -./usr/libdata/debug/usr/tests/rump/rumpkern/h_client/h_reconcli.debug tests-syscall-debug debug,atf,rump -./usr/libdata/debug/usr/tests/rump/rumpkern/h_client/h_sigcli.debug tests-syscall-debug debug,atf,rump -./usr/libdata/debug/usr/tests/rump/rumpkern/h_client/h_simplecli.debug tests-syscall-debug debug,atf,rump -./usr/libdata/debug/usr/tests/rump/rumpkern/h_client/h_stresscli.debug tests-syscall-debug debug,atf,rump ./usr/libdata/debug/usr/tests/rump/rumpkern/h_server tests-syscall-debug,rump -./usr/libdata/debug/usr/tests/rump/rumpkern/h_server/h_simpleserver.debug tests-syscall-debug debug,atf,rump ./usr/libdata/debug/usr/tests/rump/rumpvfs tests-syscall-debug,rump -./usr/libdata/debug/usr/tests/rump/rumpvfs/t_basic.debug tests-syscall-debug debug,atf,rump -./usr/libdata/debug/usr/tests/rump/rumpvfs/t_etfs.debug tests-syscall-debug debug,atf,rump -./usr/libdata/debug/usr/tests/rump/rumpvfs/t_p2kifs.debug tests-syscall-debug debug,atf,rump ./usr/libdata/debug/usr/tests/sbin tests-sbin-tests ./usr/libdata/debug/usr/tests/sbin/resize_ffs tests-sbin-tests ./usr/libdata/debug/usr/tests/syscall tests-obsolete obsolete -./usr/libdata/debug/usr/tests/syscall/t_access.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/syscall/t_chroot.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/syscall/t_cmsg.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/syscall/t_dup.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/syscall/t_fsync.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/syscall/t_getgroups.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/syscall/t_getlogin.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/syscall/t_getpid.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/syscall/t_getrusage.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/syscall/t_getsid.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/syscall/t_gettimeofday.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/syscall/t_issetugid.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/syscall/t_itimer.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/syscall/t_kill.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/syscall/t_link.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/syscall/t_mincore.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/syscall/t_mkfifo.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/syscall/t_mknod.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/syscall/t_mmap.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/syscall/t_mprotect.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/syscall/t_msync.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/syscall/t_nanosleep.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/syscall/t_poll.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/syscall/t_pollts.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/syscall/t_pselect.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/syscall/t_recvmmsg.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/syscall/t_revoke.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/syscall/t_setrlimit.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/syscall/t_setuid.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/syscall/t_stat.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/syscall/t_timer.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/syscall/t_truncate.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/syscall/t_umask.debug tests-obsolete obsolete -./usr/libdata/debug/usr/tests/syscall/t_unlink.debug tests-obsolete obsolete ./usr/libdata/debug/usr/tests/usr.bin tests-usr.bin-debug ./usr/libdata/debug/usr/tests/usr.bin/id tests-usr.bin-debug -./usr/libdata/debug/usr/tests/usr.bin/id/h_id.debug tests-usr.bin-debug debug +./usr/libdata/debug/usr/tests/usr.bin/netpgpverify tests-usr.bin-debug ./usr/libdata/debug/usr/tests/usr.sbin tests-usr.sbin-debug ./usr/libdata/debug/usr/tests/util tests-obsolete obsolete ./usr/libdata/debug/usr/tests/util/df tests-obsolete obsolete -./usr/libdata/debug/usr/tests/util/df/h_df.debug tests-obsolete obsolete ./usr/libdata/debug/usr/tests/util/id tests-obsolete obsolete -./usr/libdata/debug/usr/tests/util/id/h_id.debug tests-obsolete obsolete ./usr/libdata/debug/usr/tests/util/systrace tests-obsolete obsolete -./usr/libdata/debug/usr/tests/util/systrace/h_have_systrace.debug tests-obsolete obsolete ./usr/tests tests-base-tests ./usr/tests/Atffile tests-base-tests +./usr/tests/Kyuafile tests-base-tests kyua ./usr/tests/atf tests-atf-tests ./usr/tests/atf/Atffile tests-atf-tests atf +./usr/tests/atf/Kyuafile tests-atf-tests atf,kyua ./usr/tests/atf/atf-c tests-atf-tests ./usr/tests/atf/atf-c/Atffile tests-atf-tests atf +./usr/tests/atf/atf-c/Kyuafile tests-atf-tests atf,kyua ./usr/tests/atf/atf-c/atf_c_test tests-atf-tests atf ./usr/tests/atf/atf-c/build_test tests-atf-tests atf ./usr/tests/atf/atf-c/check_test tests-atf-tests atf @@ -854,6 +203,7 @@ ./usr/tests/atf/atf-c/d_use_macros_h.c tests-obsolete obsolete ./usr/tests/atf/atf-c/detail tests-atf-tests ./usr/tests/atf/atf-c/detail/Atffile tests-atf-tests atf +./usr/tests/atf/atf-c/detail/Kyuafile tests-atf-tests atf,kyua ./usr/tests/atf/atf-c/detail/dynstr_test tests-atf-tests atf ./usr/tests/atf/atf-c/detail/env_test tests-atf-tests atf ./usr/tests/atf/atf-c/detail/fs_test tests-atf-tests atf @@ -862,7 +212,7 @@ ./usr/tests/atf/atf-c/detail/process_helpers tests-atf-tests atf ./usr/tests/atf/atf-c/detail/process_test tests-atf-tests atf ./usr/tests/atf/atf-c/detail/sanity_test tests-atf-tests atf -./usr/tests/atf/atf-c/detail/test_helpers_test tests-atf-tests atf +./usr/tests/atf/atf-c/detail/test_helpers_test tests-obsolete obsolete ./usr/tests/atf/atf-c/detail/text_test tests-atf-tests atf ./usr/tests/atf/atf-c/detail/user_test tests-atf-tests atf ./usr/tests/atf/atf-c/dynstr_test tests-obsolete obsolete @@ -912,6 +262,7 @@ ./usr/tests/atf/atf-c/utils_test tests-atf-tests atf ./usr/tests/atf/atf-c++ tests-atf-tests ./usr/tests/atf/atf-c++/Atffile tests-atf-tests atf +./usr/tests/atf/atf-c++/Kyuafile tests-atf-tests atf,kyua ./usr/tests/atf/atf-c++/application_test tests-obsolete obsolete ./usr/tests/atf/atf-c++/atf_c++_test tests-atf-tests atf ./usr/tests/atf/atf-c++/build_test tests-atf-tests atf @@ -942,6 +293,7 @@ ./usr/tests/atf/atf-c++/d_use_macros_hpp.cpp tests-obsolete obsolete ./usr/tests/atf/atf-c++/detail tests-atf-tests ./usr/tests/atf/atf-c++/detail/Atffile tests-atf-tests atf +./usr/tests/atf/atf-c++/detail/Kyuafile tests-atf-tests atf,kyua ./usr/tests/atf/atf-c++/detail/application_test tests-atf-tests atf ./usr/tests/atf/atf-c++/detail/env_test tests-atf-tests atf ./usr/tests/atf/atf-c++/detail/exceptions_test tests-atf-tests atf @@ -1005,50 +357,78 @@ ./usr/tests/atf/atf-compile/h_mode tests-obsolete obsolete ./usr/tests/atf/atf-compile/t_integration tests-obsolete obsolete ./usr/tests/atf/atf-config tests-atf-tests -./usr/tests/atf/atf-config/Atffile tests-atf-tests atf -./usr/tests/atf/atf-config/integration_test tests-atf-tests atf +./usr/tests/atf/atf-config/Atffile tests-atf-tests atf,!kyua +./usr/tests/atf/atf-config/Atffile tests-obsolete kyua,obsolete +./usr/tests/atf/atf-config/Kyuafile tests-obsolete obsolete +./usr/tests/atf/atf-config/integration_test tests-atf-tests atf,!kyua +./usr/tests/atf/atf-config/integration_test tests-obsolete kyua,obsolete ./usr/tests/atf/atf-config/t_integration tests-obsolete obsolete ./usr/tests/atf/atf-report tests-atf-tests -./usr/tests/atf/atf-report/Atffile tests-atf-tests atf -./usr/tests/atf/atf-report/fail_helper tests-atf-tests atf +./usr/tests/atf/atf-report/Atffile tests-atf-tests atf,!kyua +./usr/tests/atf/atf-report/Atffile tests-obsolete obsolete,kyua +./usr/tests/atf/atf-report/Kyuafile tests-obsolete obsolete +./usr/tests/atf/atf-report/fail_helper tests-atf-tests atf,!kyua +./usr/tests/atf/atf-report/fail_helper tests-obsolete obsolete,kyua ./usr/tests/atf/atf-report/h_fail tests-obsolete obsolete ./usr/tests/atf/atf-report/h_misc tests-obsolete obsolete ./usr/tests/atf/atf-report/h_pass tests-obsolete obsolete ./usr/tests/atf/atf-report/h_xfail tests-obsolete obsolete -./usr/tests/atf/atf-report/integration_test tests-atf-tests atf -./usr/tests/atf/atf-report/misc_helpers tests-atf-tests atf -./usr/tests/atf/atf-report/pass_helper tests-atf-tests atf -./usr/tests/atf/atf-report/reader_test tests-atf-tests atf +./usr/tests/atf/atf-report/integration_test tests-atf-tests atf,!kyua +./usr/tests/atf/atf-report/integration_test tests-obsolete obsolete,kyua +./usr/tests/atf/atf-report/misc_helpers tests-atf-tests atf,!kyua +./usr/tests/atf/atf-report/misc_helpers tests-obsolete obsolete,kyua +./usr/tests/atf/atf-report/pass_helper tests-atf-tests atf,!kyua +./usr/tests/atf/atf-report/pass_helper tests-obsolete obsolete,kyua +./usr/tests/atf/atf-report/reader_test tests-atf-tests atf,!kyua +./usr/tests/atf/atf-report/reader_test tests-obsolete obsolete,kyua ./usr/tests/atf/atf-report/t_integration tests-obsolete obsolete ./usr/tests/atf/atf-run tests-atf-tests -./usr/tests/atf/atf-run/Atffile tests-atf-tests atf -./usr/tests/atf/atf-run/atffile_test tests-atf-tests atf -./usr/tests/atf/atf-run/bad_metadata_helper tests-atf-tests atf -./usr/tests/atf/atf-run/config_test tests-atf-tests atf -./usr/tests/atf/atf-run/expect_helpers tests-atf-tests atf -./usr/tests/atf/atf-run/fs_test tests-atf-tests atf -./usr/tests/atf/atf-run/io_test tests-atf-tests atf +./usr/tests/atf/atf-run/Atffile tests-atf-tests atf,!kyua +./usr/tests/atf/atf-run/Atffile tests-obsolete obsolete,kyua +./usr/tests/atf/atf-run/Kyuafile tests-obsolete obsolete +./usr/tests/atf/atf-run/atffile_test tests-atf-tests atf,!kyua +./usr/tests/atf/atf-run/atffile_test tests-obsolete obsolete,kyua +./usr/tests/atf/atf-run/bad_metadata_helper tests-atf-tests atf,!kyua +./usr/tests/atf/atf-run/bad_metadata_helper tests-obsolete obsolete,kyua +./usr/tests/atf/atf-run/config_test tests-atf-tests atf,!kyua +./usr/tests/atf/atf-run/config_test tests-obsolete obsolete,kyua +./usr/tests/atf/atf-run/expect_helpers tests-atf-tests atf,!kyua +./usr/tests/atf/atf-run/expect_helpers tests-obsolete obsolete,kyua +./usr/tests/atf/atf-run/fs_test tests-atf-tests atf,!kyua +./usr/tests/atf/atf-run/fs_test tests-obsolete obsolete,kyua +./usr/tests/atf/atf-run/io_test tests-atf-tests atf,!kyua +./usr/tests/atf/atf-run/io_test tests-obsolete obsolete,kyua ./usr/tests/atf/atf-run/h_bad_metadata tests-obsolete obsolete ./usr/tests/atf/atf-run/h_fail tests-obsolete obsolete ./usr/tests/atf/atf-run/h_misc tests-obsolete obsolete ./usr/tests/atf/atf-run/h_pass tests-obsolete obsolete ./usr/tests/atf/atf-run/h_several_tcs tests-obsolete obsolete ./usr/tests/atf/atf-run/h_zero_tcs tests-obsolete obsolete -./usr/tests/atf/atf-run/integration_test tests-atf-tests atf -./usr/tests/atf/atf-run/misc_helpers tests-atf-tests atf -./usr/tests/atf/atf-run/pass_helper tests-atf-tests atf -./usr/tests/atf/atf-run/requirements_test tests-atf-tests atf -./usr/tests/atf/atf-run/several_tcs_helper tests-atf-tests atf -./usr/tests/atf/atf-run/signals_test tests-atf-tests atf +./usr/tests/atf/atf-run/integration_test tests-atf-tests atf,!kyua +./usr/tests/atf/atf-run/integration_test tests-obsolete obsolete,kyua +./usr/tests/atf/atf-run/misc_helpers tests-atf-tests atf,!kyua +./usr/tests/atf/atf-run/misc_helpers tests-obsolete obsolete,kyua +./usr/tests/atf/atf-run/pass_helper tests-atf-tests atf,!kyua +./usr/tests/atf/atf-run/pass_helper tests-obsolete obsolete,kyua +./usr/tests/atf/atf-run/requirements_test tests-atf-tests atf,!kyua +./usr/tests/atf/atf-run/requirements_test tests-obsolete obsolete,kyua +./usr/tests/atf/atf-run/several_tcs_helper tests-atf-tests atf,!kyua +./usr/tests/atf/atf-run/several_tcs_helper tests-obsolete obsolete,kyua +./usr/tests/atf/atf-run/signals_test tests-atf-tests atf,!kyua +./usr/tests/atf/atf-run/signals_test tests-obsolete obsolete,kyua ./usr/tests/atf/atf-run/t_config tests-obsolete obsolete ./usr/tests/atf/atf-run/t_integration tests-obsolete obsolete ./usr/tests/atf/atf-run/t_requirements tests-obsolete obsolete ./usr/tests/atf/atf-run/t_test_program tests-obsolete obsolete -./usr/tests/atf/atf-run/test_program_test tests-atf-tests atf -./usr/tests/atf/atf-run/user_test tests-atf-tests atf -./usr/tests/atf/atf-run/zero_tcs_helper tests-atf-tests atf +./usr/tests/atf/atf-run/test_program_test tests-atf-tests atf,!kyua +./usr/tests/atf/atf-run/test_program_test tests-obsolete obsolete,kyua +./usr/tests/atf/atf-run/user_test tests-atf-tests atf,!kyua +./usr/tests/atf/atf-run/user_test tests-obsolete obsolete,kyua +./usr/tests/atf/atf-run/zero_tcs_helper tests-atf-tests atf,!kyua +./usr/tests/atf/atf-run/zero_tcs_helper tests-obsolete obsolete,kyua ./usr/tests/atf/atf-sh tests-atf-tests ./usr/tests/atf/atf-sh/Atffile tests-atf-tests atf +./usr/tests/atf/atf-sh/Kyuafile tests-atf-tests atf,kyua ./usr/tests/atf/atf-sh/atf-check_test tests-atf-tests atf ./usr/tests/atf/atf-sh/atf_check_test tests-atf-tests atf ./usr/tests/atf/atf-sh/config_test tests-atf-tests atf @@ -1320,11 +700,12 @@ ./usr/tests/atf/sh_interface/t_tp tests-obsolete obsolete ./usr/tests/atf/test-programs tests-atf-tests ./usr/tests/atf/test-programs/Atffile tests-atf-tests atf +./usr/tests/atf/test-programs/Kyuafile tests-atf-tests atf,kyua ./usr/tests/atf/test-programs/c_helpers tests-atf-tests atf ./usr/tests/atf/test-programs/config_test tests-atf-tests atf ./usr/tests/atf/test-programs/cpp_helpers tests-atf-tests atf ./usr/tests/atf/test-programs/expect_test tests-atf-tests atf -./usr/tests/atf/test-programs/fork_test tests-atf-tests atf +./usr/tests/atf/test-programs/fork_test tests-obsolete obsolete ./usr/tests/atf/test-programs/meta_data_test tests-atf-tests atf ./usr/tests/atf/test-programs/result_test tests-atf-tests atf ./usr/tests/atf/test-programs/sh_helpers tests-atf-tests atf @@ -1372,36 +753,43 @@ ./usr/tests/atf/units/t_utils tests-obsolete obsolete ./usr/tests/bin tests-bin-tests ./usr/tests/bin/Atffile tests-bin-tests atf +./usr/tests/bin/Kyuafile tests-bin-tests atf,kyua ./usr/tests/bin/cat tests-bin-tests ./usr/tests/bin/cat/Atffile tests-bin-tests atf +./usr/tests/bin/cat/Kyuafile tests-bin-tests atf,kyua ./usr/tests/bin/cat/d_align.in tests-bin-tests atf ./usr/tests/bin/cat/d_align.out tests-bin-tests atf ./usr/tests/bin/cat/t_cat tests-bin-tests atf ./usr/tests/bin/cp tests-bin-tests ./usr/tests/bin/cp/Atffile tests-bin-tests atf +./usr/tests/bin/cp/Kyuafile tests-bin-tests atf,kyua ./usr/tests/bin/cp/t_cp tests-bin-tests atf ./usr/tests/bin/dd tests-bin-tests ./usr/tests/bin/dd/Atffile tests-bin-tests atf +./usr/tests/bin/dd/Kyuafile tests-bin-tests atf,kyua ./usr/tests/bin/dd/t_dd tests-bin-tests atf ./usr/tests/bin/df tests-bin-tests -./usr/tests/bin/df/Atffile tests-bin-tests atf -./usr/tests/bin/df/h_df tests-bin-tests atf -./usr/tests/bin/df/t_df tests-bin-tests atf +#LSC: Not on MINIX ./usr/tests/bin/df/Kyuafile tests-bin-tests atf,kyua ./usr/tests/bin/expr tests-bin-tests ./usr/tests/bin/expr/Atffile tests-bin-tests atf +./usr/tests/bin/expr/Kyuafile tests-bin-tests atf,kyua ./usr/tests/bin/expr/t_expr tests-bin-tests atf ./usr/tests/bin/pax tests-bin-tests ./usr/tests/bin/pax/Atffile tests-bin-tests atf +./usr/tests/bin/pax/Kyuafile tests-bin-tests atf,kyua ./usr/tests/bin/pax/t_pax tests-bin-tests atf ./usr/tests/bin/ps tests-bin-tests ./usr/tests/bin/ps/Atffile tests-bin-tests atf +./usr/tests/bin/ps/Kyuafile tests-bin-tests atf,kyua ./usr/tests/bin/ps/keywords tests-bin-tests atf ./usr/tests/bin/ps/t_ps tests-bin-tests atf ./usr/tests/bin/sleep tests-bin-tests ./usr/tests/bin/sleep/Atffile tests-bin-tests atf +./usr/tests/bin/sleep/Kyuafile tests-bin-tests atf,kyua ./usr/tests/bin/sleep/t_sleep tests-bin-tests atf ./usr/tests/bin/sh tests-bin-tests ./usr/tests/bin/sh/Atffile tests-bin-tests atf +./usr/tests/bin/sh/Kyuafile tests-bin-tests atf,kyua ./usr/tests/bin/sh/t_compexit tests-bin-tests atf ./usr/tests/bin/sh/t_evaltested tests-bin-tests atf ./usr/tests/bin/sh/t_exit tests-bin-tests atf @@ -1414,11 +802,13 @@ ./usr/tests/bin/sh/t_wait tests-bin-tests atf ./usr/tests/bin/tar tests-bin-tests ./usr/tests/bin/tar/Atffile tests-bin-tests atf +./usr/tests/bin/tar/Kyuafile tests-bin-tests atf,kyua ./usr/tests/bin/tar/t_tar tests-bin-tests atf ./usr/tests/crypto tests-crypto-tests -./usr/tests/crypto/Atffile tests-crypto-tests +#LSC: Not on MINIX ./usr/tests/crypto/Kyuafile tests-crypto-tests kyua ./usr/tests/crypto/libcrypto tests-crypto-tests ./usr/tests/crypto/libcrypto/Atffile tests-crypto-tests crypto +./usr/tests/crypto/libcrypto/Kyuafile tests-crypto-tests crypto,kyua ./usr/tests/crypto/libcrypto/d_conf.out tests-crypto-tests crypto ./usr/tests/crypto/libcrypto/d_conf_ssleay.cnf tests-crypto-tests crypto ./usr/tests/crypto/libcrypto/d_client.pem tests-crypto-tests crypto @@ -1463,13 +853,16 @@ ./usr/tests/crypto/libcrypto/t_pubkey tests-crypto-tests crypto ./usr/tests/dev tests-fs-tests ./usr/tests/dev/Atffile tests-fs-tests atf +./usr/tests/dev/Kyuafile tests-fs-tests atf,kyua ./usr/tests/dev/audio tests-fs-tests ./usr/tests/dev/audio/Atffile tests-fs-tests atf,rump +./usr/tests/dev/audio/Kyuafile tests-fs-tests atf,rump,kyua ./usr/tests/dev/audio/h_pad tests-fs-tests atf,rump ./usr/tests/dev/audio/t_pad tests-fs-tests atf,rump ./usr/tests/dev/audio/t_pad_output.bz2.uue tests-fs-tests atf,rump ./usr/tests/dev/cgd tests-fs-tests ./usr/tests/dev/cgd/Atffile tests-fs-tests atf +./usr/tests/dev/cgd/Kyuafile tests-fs-tests atf,kyua ./usr/tests/dev/cgd/t_cgd tests-fs-tests atf ./usr/tests/dev/cgd/paramsfile tests-fs-tests atf ./usr/tests/dev/cgd/h_img2cgd tests-obsolete obsolete @@ -1477,26 +870,32 @@ ./usr/tests/dev/cgd/h_img2cgd/cgd.conf tests-obsolete obsolete ./usr/tests/dev/md tests-fs-tests ./usr/tests/dev/md/Atffile tests-fs-tests atf,rump +./usr/tests/dev/md/Kyuafile tests-fs-tests atf,rump,kyua ./usr/tests/dev/md/h_mdserv tests-fs-tests atf,rump ./usr/tests/dev/md/t_md tests-fs-tests atf,rump ./usr/tests/dev/raidframe tests-fs-tests ./usr/tests/dev/raidframe/Atffile tests-fs-tests atf +./usr/tests/dev/raidframe/Kyuafile tests-fs-tests atf,kyua ./usr/tests/dev/raidframe/t_raid tests-fs-tests atf ./usr/tests/dev/scsipi tests-fs-tests ./usr/tests/dev/scsipi/Atffile tests-fs-tests atf,rump +./usr/tests/dev/scsipi/Kyuafile tests-fs-tests atf,rump,kyua ./usr/tests/dev/scsipi/t_cd tests-fs-tests atf,rump ./usr/tests/dev/sysmon tests-fs-tests ./usr/tests/dev/sysmon/Atffile tests-fs-tests atf,rump +./usr/tests/dev/sysmon/Kyuafile tests-fs-tests atf,rump,kyua ./usr/tests/dev/sysmon/t_swsensor tests-fs-tests atf,rump ./usr/tests/dev/sysmon/t_swwdog tests-fs-tests atf,rump -./usr/tests/examples tests-asm-tests -./usr/tests/examples/Atffile tests-asm-tests atf -./usr/tests/examples/t_asm tests-asm-tests atf +./usr/tests/examples tests-obsolete obsolete +./usr/tests/examples/Atffile tests-obsolete obsolete +./usr/tests/examples/t_asm tests-obsolete obsolete ./usr/tests/fs tests-fs-tests ./usr/tests/fs/Atffile tests-fs-tests atf,rump +./usr/tests/fs/Kyuafile tests-fs-tests atf,rump,kyua ./usr/tests/fs/h_funcs.subr tests-fs-tests atf,rump ./usr/tests/fs/ffs tests-fs-tests ./usr/tests/fs/ffs/Atffile tests-fs-tests atf,rump +./usr/tests/fs/ffs/Kyuafile tests-fs-tests atf,rump,kyua ./usr/tests/fs/ffs/h_ffs_server tests-fs-tests atf,rump ./usr/tests/fs/ffs/h_quota2_server tests-obsolete obsolete ./usr/tests/fs/ffs/h_quota2_tests tests-fs-tests atf,rump @@ -1519,22 +918,28 @@ ./usr/tests/fs/ffs/t_snapshot_v2 tests-fs-tests atf,rump ./usr/tests/fs/fifofs tests-fs-tests ./usr/tests/fs/fifofs/Atffile tests-fs-tests atf,rump +./usr/tests/fs/fifofs/Kyuafile tests-fs-tests atf,rump,kyua ./usr/tests/fs/fifofs/t_fifo tests-fs-tests atf,rump ./usr/tests/fs/hfs tests-fs-tests ./usr/tests/fs/hfs/Atffile tests-fs-tests atf,rump +./usr/tests/fs/hfs/Kyuafile tests-fs-tests atf,rump,kyua ./usr/tests/fs/hfs/colon.hfs.bz2.uue tests-fs-tests atf,rump ./usr/tests/fs/hfs/t_pathconvert tests-fs-tests atf,rump ./usr/tests/fs/kernfs tests-fs-tests ./usr/tests/fs/kernfs/Atffile tests-fs-tests atf,rump +./usr/tests/fs/kernfs/Kyuafile tests-fs-tests atf,rump,kyua ./usr/tests/fs/kernfs/t_basic tests-fs-tests atf,rump ./usr/tests/fs/lfs tests-fs-tests ./usr/tests/fs/lfs/Atffile tests-fs-tests atf,rump +./usr/tests/fs/lfs/Kyuafile tests-fs-tests atf,rump,kyua ./usr/tests/fs/lfs/t_pr tests-fs-tests atf,rump ./usr/tests/fs/msdosfs tests-fs-tests ./usr/tests/fs/msdosfs/Atffile tests-fs-tests atf,rump +./usr/tests/fs/msdosfs/Kyuafile tests-fs-tests atf,rump,kyua ./usr/tests/fs/msdosfs/t_snapshot tests-fs-tests atf,rump ./usr/tests/fs/nfs tests-fs-tests ./usr/tests/fs/nfs/Atffile tests-fs-tests atf,rump +./usr/tests/fs/nfs/Kyuafile tests-fs-tests atf,rump,kyua ./usr/tests/fs/nfs/t_mountd tests-fs-tests atf,rump ./usr/tests/fs/nfs/t_rquotad tests-fs-tests atf,rump ./usr/tests/fs/nfs/nfsservice tests-fs-tests @@ -1542,9 +947,11 @@ ./usr/tests/fs/nfs/nfsservice/rumpnfsd tests-fs-tests atf,rump ./usr/tests/fs/nullfs tests-fs-tests ./usr/tests/fs/nullfs/Atffile tests-fs-tests atf,rump +./usr/tests/fs/nullfs/Kyuafile tests-fs-tests atf,rump,kyua ./usr/tests/fs/nullfs/t_basic tests-fs-tests atf,rump ./usr/tests/fs/psshfs tests-fs-tests ./usr/tests/fs/psshfs/Atffile tests-fs-tests atf,rump +./usr/tests/fs/psshfs/Kyuafile tests-fs-tests atf,rump,kyua ./usr/tests/fs/psshfs/h_have_puffs tests-fs-tests atf,rump ./usr/tests/fs/psshfs/ssh_config.in tests-fs-tests atf,rump ./usr/tests/fs/psshfs/ssh_host_key tests-fs-tests atf,rump @@ -1553,10 +960,12 @@ ./usr/tests/fs/psshfs/t_psshfs tests-fs-tests atf,rump ./usr/tests/fs/ptyfs tests-fs-tests ./usr/tests/fs/ptyfs/Atffile tests-fs-tests atf,rump +./usr/tests/fs/ptyfs/Kyuafile tests-fs-tests atf,rump,kyua ./usr/tests/fs/ptyfs/t_ptyfs tests-fs-tests atf,rump ./usr/tests/fs/ptyfs/t_nullpts tests-fs-tests atf,rump ./usr/tests/fs/puffs tests-fs-tests ./usr/tests/fs/puffs/Atffile tests-fs-tests atf,rump +./usr/tests/fs/puffs/Kyuafile tests-fs-tests atf,rump,kyua ./usr/tests/fs/puffs/t_basic tests-fs-tests atf,rump ./usr/tests/fs/puffs/t_fuzz tests-fs-tests atf,rump ./usr/tests/fs/puffs/t_io tests-fs-tests atf,rump @@ -1570,6 +979,7 @@ ./usr/tests/fs/puffs/t_psshfs tests-obsolete obsolete ./usr/tests/fs/tmpfs tests-fs-tests ./usr/tests/fs/tmpfs/Atffile tests-fs-tests atf,rump +./usr/tests/fs/tmpfs/Kyuafile tests-fs-tests atf,rump,kyua ./usr/tests/fs/tmpfs/h_funcs.subr tests-fs-tests atf,rump ./usr/tests/fs/tmpfs/h_tools tests-fs-tests atf,rump ./usr/tests/fs/tmpfs/t_create tests-fs-tests atf,rump @@ -1600,13 +1010,16 @@ ./usr/tests/fs/tmpfs/t_vnode_leak tests-fs-tests atf,rump ./usr/tests/fs/umapfs tests-fs-tests ./usr/tests/fs/umapfs/Atffile tests-fs-tests atf,rump +./usr/tests/fs/umapfs/Kyuafile tests-fs-tests atf,rump,kyua ./usr/tests/fs/umapfs/t_basic tests-fs-tests atf,rump ./usr/tests/fs/union tests-fs-tests ./usr/tests/fs/union/Atffile tests-fs-tests atf,rump +./usr/tests/fs/union/Kyuafile tests-fs-tests atf,rump,kyua ./usr/tests/fs/union/t_basic tests-obsolete obsolete,rump ./usr/tests/fs/union/t_pr tests-fs-tests atf,rump ./usr/tests/fs/vfs tests-fs-tests ./usr/tests/fs/vfs/Atffile tests-fs-tests atf,rump +./usr/tests/fs/vfs/Kyuafile tests-fs-tests atf,rump,kyua ./usr/tests/fs/vfs/t_full tests-fs-tests atf,rump ./usr/tests/fs/vfs/t_io tests-fs-tests atf,rump ./usr/tests/fs/vfs/t_renamerace tests-fs-tests atf,rump @@ -1618,12 +1031,15 @@ ./usr/tests/fs/vfs/t_vnops tests-fs-tests atf,rump ./usr/tests/fs/zfs tests-fs-tests ./usr/tests/fs/zfs/Atffile tests-fs-tests atf,zfs,rump +./usr/tests/fs/zfs/Kyuafile tests-fs-tests atf,zfs,rump,kyua ./usr/tests/fs/zfs/t_zpool tests-fs-tests atf,zfs,rump ./usr/tests/games tests-games-tests ./usr/tests/games/Atffile tests-games-tests +./usr/tests/games/Kyuafile tests-games-tests kyua ./usr/tests/games/t_factor tests-games-tests ./usr/tests/include tests-include-tests ./usr/tests/include/Atffile tests-include-tests atf +./usr/tests/include/Kyuafile tests-include-tests atf,kyua ./usr/tests/include/d_bitstring_27.out tests-include-tests atf ./usr/tests/include/d_bitstring_32.out tests-include-tests atf ./usr/tests/include/d_bitstring_49.out tests-include-tests atf @@ -1632,10 +1048,11 @@ ./usr/tests/include/d_bitstring_8.out tests-include-tests atf ./usr/tests/include/machine tests-include-tests ./usr/tests/include/machine/Atffile tests-include-tests atf +./usr/tests/include/machine/Kyuafile tests-include-tests atf,kyua ./usr/tests/include/machine/t_bswap tests-include-tests atf ./usr/tests/include/sys tests-include-tests ./usr/tests/include/sys/Atffile tests-include-tests atf -./usr/tests/include/sys/t_bitops tests-include-tests atf +./usr/tests/include/sys/Kyuafile tests-include-tests atf,kyua ./usr/tests/include/sys/t_bootblock tests-include-tests atf ./usr/tests/include/sys/t_cdefs tests-include-tests atf ./usr/tests/include/sys/t_socket tests-include-tests atf,rump @@ -1653,6 +1070,7 @@ ./usr/tests/include/t_types tests-obsolete obsolete ./usr/tests/ipf tests-ipf-tests ./usr/tests/ipf/Atffile tests-ipf-tests ipfilter +./usr/tests/ipf/Kyuafile tests-ipf-tests ipfilter,kyua ./usr/tests/ipf/expected tests-ipf-tests ./usr/tests/ipf/expected/bpf-f1 tests-ipf-tests ipfilter ./usr/tests/ipf/expected/bpf1 tests-ipf-tests ipfilter @@ -2108,7 +1526,7 @@ ./usr/tests/ipf/regress/p7.pool tests-ipf-tests ipfilter ./usr/tests/ipf/regress/p9.nat tests-ipf-tests ipfilter ./usr/tests/ipf/regress/p9.pool tests-ipf-tests ipfilter -./usr/tests/ipf/t_bpf tests-ipf-tests atf,ipfilter +./usr/tests/ipf/t_bpf tests-obsolete obsolete ./usr/tests/ipf/t_filter_exec tests-ipf-tests atf,ipfilter ./usr/tests/ipf/t_filter_parse tests-ipf-tests atf,ipfilter ./usr/tests/ipf/t_ipf tests-obsolete obsolete @@ -2118,27 +1536,13 @@ ./usr/tests/ipf/t_nat_parse tests-ipf-tests atf,ipfilter ./usr/tests/ipf/t_pools tests-ipf-tests atf,ipfilter ./usr/tests/kernel tests-kernel-tests -./usr/tests/kernel/Atffile tests-kernel-tests atf -./usr/tests/kernel/h_ps_strings1 tests-kernel-tests atf -./usr/tests/kernel/h_ps_strings2 tests-kernel-tests atf +#LSC: Not on MINIX ./usr/tests/kernel/Kyuafile tests-kernel-tests atf,kyua ./usr/tests/kernel/kqueue tests-kernel-tests -./usr/tests/kernel/kqueue/Atffile tests-kernel-tests atf +#LSC: Not on MINIX ./usr/tests/kernel/kqueue/Kyuafile tests-kernel-tests atf,kyua ./usr/tests/kernel/kqueue/read tests-kernel-tests -./usr/tests/kernel/kqueue/read/Atffile tests-kernel-tests atf -./usr/tests/kernel/kqueue/read/t_fifo tests-kernel-tests atf -./usr/tests/kernel/kqueue/read/t_file tests-kernel-tests atf -./usr/tests/kernel/kqueue/read/t_file2 tests-kernel-tests atf -./usr/tests/kernel/kqueue/read/t_pipe tests-kernel-tests atf -./usr/tests/kernel/kqueue/read/t_ttypty tests-kernel-tests atf -./usr/tests/kernel/kqueue/t_ioctl tests-kernel-tests atf -./usr/tests/kernel/kqueue/t_proc1 tests-kernel-tests atf -./usr/tests/kernel/kqueue/t_proc2 tests-kernel-tests atf -./usr/tests/kernel/kqueue/t_sig tests-kernel-tests atf +#LSC: Not on MINIX ./usr/tests/kernel/kqueue/read/Kyuafile tests-kernel-tests atf,kyua ./usr/tests/kernel/kqueue/write tests-kernel-tests -./usr/tests/kernel/kqueue/write/Atffile tests-kernel-tests atf -./usr/tests/kernel/kqueue/write/t_fifo tests-kernel-tests atf -./usr/tests/kernel/kqueue/write/t_pipe tests-kernel-tests atf -./usr/tests/kernel/kqueue/write/t_ttypty tests-kernel-tests atf +#LSC: Not on MINIX ./usr/tests/kernel/kqueue/write/Kyuafile tests-kernel-tests atf,kyua ./usr/tests/kernel/posix_spawn tests-kernel-tests obsolete ./usr/tests/kernel/posix_spawn/Atffile tests-kernel-tests obsolete ./usr/tests/kernel/posix_spawn/t_spawn tests-kernel-tests obsolete @@ -2150,96 +1554,242 @@ ./usr/tests/kernel/posix_spawn/h_nonexec tests-kernel-tests obsolete ./usr/tests/kernel/posix_spawn/h_zero tests-kernel-tests obsolete ./usr/tests/kernel/t_extattrctl tests-kernel-tests atf,rump -./usr/tests/kernel/t_extent tests-kernel-tests atf ./usr/tests/kernel/t_filedesc tests-kernel-tests atf,rump -./usr/tests/kernel/t_lock tests-kernel-tests atf ./usr/tests/kernel/t_lwpctl tests-obsolete obsolete ./usr/tests/kernel/t_mkdir tests-obsolete obsolete ./usr/tests/kernel/t_pipe tests-obsolete obsolete ./usr/tests/kernel/t_poll3w tests-obsolete obsolete ./usr/tests/kernel/t_pollts tests-obsolete obsolete ./usr/tests/kernel/t_posix_fadvise tests-obsolete obsolete -./usr/tests/kernel/t_ps_strings tests-kernel-tests atf -./usr/tests/kernel/t_pty tests-kernel-tests atf ./usr/tests/kernel/t_rnd tests-kernel-tests atf,rump ./usr/tests/kernel/t_sigaction tests-obsolete obsolete -./usr/tests/kernel/t_subr_prf tests-kernel-tests atf ./usr/tests/kernel/t_time tests-obsolete obsolete ./usr/tests/kernel/t_ucontext tests-obsolete obsolete -./usr/tests/kernel/t_umount tests-kernel-tests atf ./usr/tests/kernel/t_writev tests-obsolete obsolete ./usr/tests/kernel/tty tests-kernel-tests ./usr/tests/kernel/tty/Atffile tests-kernel-tests atf,rump +./usr/tests/kernel/tty/Kyuafile tests-kernel-tests atf,rump,kyua ./usr/tests/kernel/tty/t_pr tests-kernel-tests atf,rump +./usr/tests/kyua-atf-compat tests-kyua-tests +./usr/tests/kyua-atf-compat/Atffile tests-kyua-tests atf,kyua +./usr/tests/kyua-atf-compat/Kyuafile tests-kyua-tests atf,kyua +./usr/tests/kyua-atf-compat/atf-report_test tests-kyua-tests atf,kyua +./usr/tests/kyua-atf-compat/atf-run_test tests-kyua-tests atf,kyua +./usr/tests/kyua-atf-compat/atf2kyua_test tests-kyua-tests atf,kyua +./usr/tests/kyua-atf-compat/helpers tests-kyua-tests atf,kyua +./usr/tests/kyua-cli tests-kyua-tests +./usr/tests/kyua-cli/Atffile tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/Kyuafile tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/bootstrap tests-kyua-tests +./usr/tests/kyua-cli/bootstrap/atf_helpers tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/bootstrap/plain_helpers tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/bootstrap/testsuite tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/cli tests-kyua-tests +./usr/tests/kyua-cli/cli/Atffile tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/cli/Kyuafile tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/cli/cmd_about_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/cli/cmd_config_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/cli/cmd_db_exec_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/cli/cmd_db_migrate_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/cli/cmd_debug_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/cli/cmd_help_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/cli/cmd_list_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/cli/cmd_report_html_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/cli/cmd_report_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/cli/cmd_test_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/cli/common_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/cli/config_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/cli/main_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/engine tests-kyua-tests +./usr/tests/kyua-cli/engine/Atffile tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/engine/Kyuafile tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/engine/action_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/engine/config_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/engine/context_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/engine/drivers tests-kyua-tests +./usr/tests/kyua-cli/engine/drivers/Atffile tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/engine/drivers/Kyuafile tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/engine/drivers/debug_test_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/engine/drivers/list_tests_helpers tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/engine/drivers/list_tests_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/engine/drivers/run_tests_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/engine/drivers/scan_action_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/engine/exceptions_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/engine/filters_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/engine/kyuafile_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/engine/metadata_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/engine/test_case_atf_helpers tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/engine/test_case_plain_helpers tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/engine/test_case_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/engine/test_program_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/engine/test_result_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/engine/testers_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/examples tests-kyua-tests +./usr/tests/kyua-cli/examples/Atffile tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/examples/Kyuafile tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/examples/syntax_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/integration tests-kyua-tests +./usr/tests/kyua-cli/integration/Atffile tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/integration/Kyuafile tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/integration/cmd_about_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/integration/cmd_config_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/integration/cmd_db_exec_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/integration/cmd_db_migrate_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/integration/cmd_debug_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/integration/cmd_help_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/integration/cmd_list_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/integration/cmd_report_html_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/integration/cmd_report_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/integration/cmd_test_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/integration/global_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/integration/helpers tests-kyua-tests +./usr/tests/kyua-cli/integration/helpers/bad_test_program tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/integration/helpers/bogus_test_cases tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/integration/helpers/config tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/integration/helpers/expect_all_pass tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/integration/helpers/expect_some_fail tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/integration/helpers/interrupts tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/integration/helpers/metadata tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/integration/helpers/simple_all_pass tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/integration/helpers/simple_some_fail tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/store tests-kyua-tests +./usr/tests/kyua-cli/store/Atffile tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/store/Kyuafile tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/store/backend_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/store/dbtypes_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/store/exceptions_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/store/metadata_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/store/schema_inttest tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/store/schema_v1.sql tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/store/testdata_v1.sql tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/store/testdata_v2.sql tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/store/transaction_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils tests-kyua-tests +./usr/tests/kyua-cli/utils/Atffile tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/Kyuafile tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/auto_array_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/cmdline tests-kyua-tests +./usr/tests/kyua-cli/utils/cmdline/Atffile tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/cmdline/Kyuafile tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/cmdline/base_command_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/cmdline/commands_map_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/cmdline/exceptions_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/cmdline/globals_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/cmdline/options_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/cmdline/parser_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/cmdline/ui_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/config tests-kyua-tests +./usr/tests/kyua-cli/utils/config/Atffile tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/config/Kyuafile tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/config/exceptions_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/config/keys_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/config/lua_module_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/config/nodes_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/config/parser_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/config/tree_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/datetime_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/env_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/format tests-kyua-tests +./usr/tests/kyua-cli/utils/format/Atffile tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/format/Kyuafile tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/format/exceptions_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/format/formatter_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/fs tests-kyua-tests +./usr/tests/kyua-cli/utils/fs/Atffile tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/fs/Kyuafile tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/fs/auto_cleaners_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/fs/exceptions_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/fs/lua_module_test tests-kyua-tests atf,kyua +#LSC: Not on MINIX ./usr/tests/kyua-cli/utils/fs/operations_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/fs/path_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/logging tests-kyua-tests +./usr/tests/kyua-cli/utils/logging/Atffile tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/logging/Kyuafile tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/logging/macros_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/logging/operations_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/memory_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/optional_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/passwd_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/process tests-kyua-tests +./usr/tests/kyua-cli/utils/process/Atffile tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/process/Kyuafile tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/process/child_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/process/exceptions_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/process/fdstream_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/process/helpers tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/process/status_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/process/systembuf_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/sanity_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/signals tests-kyua-tests +./usr/tests/kyua-cli/utils/signals/Atffile tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/signals/Kyuafile tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/signals/exceptions_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/signals/interrupts_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/signals/misc_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/signals/programmer_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/sqlite tests-kyua-tests +./usr/tests/kyua-cli/utils/sqlite/Atffile tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/sqlite/Kyuafile tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/sqlite/c_gate_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/sqlite/database_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/sqlite/exceptions_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/sqlite/statement_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/sqlite/transaction_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/stream_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/text tests-kyua-tests +./usr/tests/kyua-cli/utils/text/Atffile tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/text/Kyuafile tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/text/exceptions_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/text/operations_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/text/table_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/text/templates_test tests-kyua-tests atf,kyua +./usr/tests/kyua-cli/utils/units_test tests-kyua-tests atf,kyua +./usr/tests/kyua-testers tests-kyua-tests +./usr/tests/kyua-testers/Atffile tests-kyua-tests atf,kyua +./usr/tests/kyua-testers/Kyuafile tests-kyua-tests atf,kyua +./usr/tests/kyua-testers/atf_helpers tests-kyua-tests atf,kyua +./usr/tests/kyua-testers/atf_inttest tests-kyua-tests atf,kyua +./usr/tests/kyua-testers/atf_list_test tests-kyua-tests atf,kyua +./usr/tests/kyua-testers/atf_result_test tests-kyua-tests atf,kyua +./usr/tests/kyua-testers/cli_test tests-kyua-tests atf,kyua +./usr/tests/kyua-testers/env_test tests-kyua-tests atf,kyua +./usr/tests/kyua-testers/error_test tests-kyua-tests atf,kyua +#LSC: Not on MINIX ./usr/tests/kyua-testers/fs_test tests-kyua-tests atf,kyua +./usr/tests/kyua-testers/plain_helpers tests-kyua-tests atf,kyua +./usr/tests/kyua-testers/plain_inttest tests-kyua-tests atf,kyua +./usr/tests/kyua-testers/result_test tests-kyua-tests atf,kyua +./usr/tests/kyua-testers/run_test tests-kyua-tests atf,kyua +./usr/tests/kyua-testers/stacktrace_helper tests-kyua-tests atf,kyua +./usr/tests/kyua-testers/stacktrace_test tests-kyua-tests atf,kyua +./usr/tests/kyua-testers/text_test tests-kyua-tests atf,kyua ./usr/tests/lib tests-lib-tests ./usr/tests/lib/Atffile tests-lib-tests atf +./usr/tests/lib/Kyuafile tests-lib-tests atf,kyua ./usr/tests/lib/csu tests-lib-tests ./usr/tests/lib/csu/Atffile tests-lib-tests atf +./usr/tests/lib/csu/Kyuafile tests-lib-tests atf,kyua ./usr/tests/lib/csu/h_initfini tests-obsolete obsolete ./usr/tests/lib/csu/h_initfini1 tests-lib-tests atf ./usr/tests/lib/csu/h_initfini2 tests-lib-tests atf ./usr/tests/lib/csu/h_initfini3 tests-lib-tests atf ./usr/tests/lib/csu/t_crt0 tests-lib-tests atf ./usr/tests/lib/libbluetooth tests-lib-tests -./usr/tests/lib/libbluetooth/Atffile tests-lib-tests atf -./usr/tests/lib/libbluetooth/t_bluetooth tests-lib-tests atf -./usr/tests/lib/libbluetooth/t_sdp_data tests-lib-tests atf -./usr/tests/lib/libbluetooth/t_sdp_get tests-lib-tests atf -./usr/tests/lib/libbluetooth/t_sdp_match tests-lib-tests atf -./usr/tests/lib/libbluetooth/t_sdp_put tests-lib-tests atf -./usr/tests/lib/libbluetooth/t_sdp_set tests-lib-tests atf +#LSC: Not on MINIX ./usr/tests/lib/libbluetooth/Kyuafile tests-lib-tests atf,kyua ./usr/tests/lib/libc tests-lib-tests ./usr/tests/lib/libc/Atffile tests-lib-tests atf +./usr/tests/lib/libc/Kyuafile tests-lib-tests atf,kyua +./usr/tests/lib/libc/c063 tests-lib-tests +#LSC: Not on MINIX ./usr/tests/lib/libc/c063/Kyuafile tests-lib-tests atf,kyua ./usr/tests/lib/libc/db tests-lib-tests ./usr/tests/lib/libc/db/Atffile tests-lib-tests atf +./usr/tests/lib/libc/db/Kyuafile tests-lib-tests atf,kyua ./usr/tests/lib/libc/db/README tests-lib-tests atf ./usr/tests/lib/libc/db/h_db tests-lib-tests atf ./usr/tests/lib/libc/db/t_db tests-lib-tests atf ./usr/tests/lib/libc/gen tests-lib-tests -./usr/tests/lib/libc/gen/Atffile tests-lib-tests atf +#LSC: Not on MINIX ./usr/tests/lib/libc/gen/Kyuafile tests-lib-tests atf,kyua ./usr/tests/lib/libc/gen/posix_spawn tests-kernel-tests -./usr/tests/lib/libc/gen/posix_spawn/Atffile tests-kernel-tests atf -./usr/tests/lib/libc/gen/posix_spawn/t_spawn tests-kernel-tests atf -./usr/tests/lib/libc/gen/posix_spawn/t_spawnattr tests-kernel-tests atf -./usr/tests/lib/libc/gen/posix_spawn/t_fileactions tests-kernel-tests atf -./usr/tests/lib/libc/gen/posix_spawn/h_spawn tests-kernel-tests atf -./usr/tests/lib/libc/gen/posix_spawn/h_spawnattr tests-kernel-tests atf -./usr/tests/lib/libc/gen/posix_spawn/h_fileactions tests-kernel-tests atf -./usr/tests/lib/libc/gen/posix_spawn/h_nonexec tests-kernel-tests atf -./usr/tests/lib/libc/gen/posix_spawn/h_zero tests-kernel-tests atf -./usr/tests/lib/libc/gen/t_alarm tests-lib-tests atf -./usr/tests/lib/libc/gen/t_assert tests-lib-tests atf -./usr/tests/lib/libc/gen/t_basedirname tests-lib-tests atf -./usr/tests/lib/libc/gen/t_closefrom tests-lib-tests atf -./usr/tests/lib/libc/gen/t_cpuset tests-lib-tests atf -./usr/tests/lib/libc/gen/t_dir tests-lib-tests atf -./usr/tests/lib/libc/gen/t_fmtcheck tests-lib-tests atf -./usr/tests/lib/libc/gen/t_fnmatch tests-lib-tests atf -./usr/tests/lib/libc/gen/t_fpclassify tests-lib-tests atf -./usr/tests/lib/libc/gen/t_fpsetmask tests-lib-tests atf -./usr/tests/lib/libc/gen/t_fpsetround tests-lib-tests atf -./usr/tests/lib/libc/gen/t_ftok tests-lib-tests atf -./usr/tests/lib/libc/gen/t_getcwd tests-lib-tests atf -./usr/tests/lib/libc/gen/t_getgrent tests-lib-tests atf -./usr/tests/lib/libc/gen/t_glob tests-lib-tests atf -./usr/tests/lib/libc/gen/t_glob_star tests-obsolete obsolete -./usr/tests/lib/libc/gen/t_humanize_number tests-lib-tests atf -./usr/tests/lib/libc/gen/t_isnan tests-lib-tests atf -./usr/tests/lib/libc/gen/t_ldexp tests-obsolete obsolete -./usr/tests/lib/libc/gen/t_nice tests-lib-tests atf -./usr/tests/lib/libc/gen/t_pause tests-lib-tests atf -./usr/tests/lib/libc/gen/t_raise tests-lib-tests atf -./usr/tests/lib/libc/gen/t_randomid tests-lib-tests atf -./usr/tests/lib/libc/gen/t_realpath tests-lib-tests atf -./usr/tests/lib/libc/gen/t_rbstress tests-obsolete obsolete -./usr/tests/lib/libc/gen/t_setdomainname tests-lib-tests atf -./usr/tests/lib/libc/gen/t_sethostname tests-lib-tests atf -./usr/tests/lib/libc/gen/t_siginfo tests-lib-tests atf -./usr/tests/lib/libc/gen/t_syslog tests-lib-tests atf -./usr/tests/lib/libc/gen/t_syslog_pthread tests-obsolete obsolete -./usr/tests/lib/libc/gen/t_time tests-lib-tests atf -./usr/tests/lib/libc/gen/t_ttyname tests-lib-tests atf -./usr/tests/lib/libc/gen/t_vis tests-lib-tests atf +#LSC: Not on MINIX ./usr/tests/lib/libc/gen/posix_spawn/Kyuafile tests-kernel-tests atf,kyua ./usr/tests/lib/libc/getaddrinfo tests-obsolete obsolete ./usr/tests/lib/libc/getaddrinfo/Atffile tests-obsolete obsolete ./usr/tests/lib/libc/getaddrinfo/data tests-obsolete obsolete @@ -2263,6 +1813,7 @@ ./usr/tests/lib/libc/h_servent tests-obsolete obsolete ./usr/tests/lib/libc/hash tests-lib-tests ./usr/tests/lib/libc/hash/Atffile tests-lib-tests atf +./usr/tests/lib/libc/hash/Kyuafile tests-lib-tests atf,kyua ./usr/tests/lib/libc/hash/data tests-lib-tests ./usr/tests/lib/libc/hash/data/md5test-in tests-lib-tests atf ./usr/tests/lib/libc/hash/data/md5test-out tests-lib-tests atf @@ -2280,8 +1831,10 @@ ./usr/tests/lib/libc/ieeefp/t_subnormal tests-obsolete obsolete ./usr/tests/lib/libc/locale tests-lib-tests ./usr/tests/lib/libc/locale/Atffile tests-lib-tests atf +./usr/tests/lib/libc/locale/Kyuafile tests-lib-tests atf,kyua ./usr/tests/lib/libc/locale/t_ctype1 tests-obsolete obsolete ./usr/tests/lib/libc/locale/t_ctype2 tests-obsolete obsolete +./usr/tests/lib/libc/locale/t_io tests-lib-tests atf ./usr/tests/lib/libc/locale/t_mbrtowc tests-lib-tests atf ./usr/tests/lib/libc/locale/t_mbstowcs tests-lib-tests atf ./usr/tests/lib/libc/locale/t_mbtowc tests-lib-tests atf @@ -2292,36 +1845,23 @@ ./usr/tests/lib/libc/locale/t_wctomb tests-lib-tests atf ./usr/tests/lib/libc/inet tests-lib-tests ./usr/tests/lib/libc/inet/Atffile tests-lib-tests atf +./usr/tests/lib/libc/inet/Kyuafile tests-lib-tests atf,kyua ./usr/tests/lib/libc/inet/t_inet_network tests-lib-tests atf ./usr/tests/lib/libc/net tests-lib-tests ./usr/tests/lib/libc/net/Atffile tests-lib-tests atf +./usr/tests/lib/libc/net/Kyuafile tests-lib-tests atf,kyua ./usr/tests/lib/libc/net/getaddrinfo tests-lib-tests -./usr/tests/lib/libc/net/getaddrinfo/Atffile tests-lib-tests atf +#LSC: Not on MINIX ./usr/tests/lib/libc/net/getaddrinfo/Kyuafile tests-lib-tests atf,kyua ./usr/tests/lib/libc/net/getaddrinfo/data tests-lib-tests -./usr/tests/lib/libc/net/getaddrinfo/data/basics_v4.exp tests-lib-tests atf -./usr/tests/lib/libc/net/getaddrinfo/data/basics_v4v6.exp tests-lib-tests atf -./usr/tests/lib/libc/net/getaddrinfo/data/no_host_v4.exp tests-lib-tests atf -./usr/tests/lib/libc/net/getaddrinfo/data/no_host_v4v6.exp tests-lib-tests atf -./usr/tests/lib/libc/net/getaddrinfo/data/no_serv_v4.exp tests-lib-tests atf -./usr/tests/lib/libc/net/getaddrinfo/data/no_serv_v4v6.exp tests-lib-tests atf -./usr/tests/lib/libc/net/getaddrinfo/data/scoped.exp tests-lib-tests atf -./usr/tests/lib/libc/net/getaddrinfo/data/sock_raw_v4.exp tests-lib-tests atf -./usr/tests/lib/libc/net/getaddrinfo/data/sock_raw_v4v6.exp tests-lib-tests atf -./usr/tests/lib/libc/net/getaddrinfo/data/spec_fam_v4.exp tests-lib-tests atf -./usr/tests/lib/libc/net/getaddrinfo/data/spec_fam_v4v6.exp tests-lib-tests atf -./usr/tests/lib/libc/net/getaddrinfo/data/unsup_fam.exp tests-lib-tests atf -./usr/tests/lib/libc/net/getaddrinfo/h_gai tests-lib-tests atf -./usr/tests/lib/libc/net/getaddrinfo/t_getaddrinfo tests-lib-tests atf -./usr/tests/lib/libc/net/h_nsd_recurse tests-lib-tests atf ./usr/tests/lib/libc/net/h_protoent tests-lib-tests atf ./usr/tests/lib/libc/net/h_servent tests-lib-tests atf -./usr/tests/lib/libc/net/t_ether_aton tests-lib-tests atf ./usr/tests/lib/libc/net/t_getprotoent tests-lib-tests atf ./usr/tests/lib/libc/net/t_nsdispatch tests-lib-tests atf ./usr/tests/lib/libc/net/t_protoent tests-lib-tests atf ./usr/tests/lib/libc/net/t_servent tests-lib-tests atf ./usr/tests/lib/libc/regex tests-lib-tests ./usr/tests/lib/libc/regex/Atffile tests-lib-tests atf +./usr/tests/lib/libc/regex/Kyuafile tests-lib-tests atf,kyua ./usr/tests/lib/libc/regex/data tests-lib-tests ./usr/tests/lib/libc/regex/data/README tests-lib-tests atf ./usr/tests/lib/libc/regex/data/anchor.in tests-lib-tests atf @@ -2357,34 +1897,14 @@ ./usr/tests/lib/libc/regex/t_regex tests-lib-tests atf ./usr/tests/lib/libc/regex/t_regex_att tests-lib-tests atf ./usr/tests/lib/libc/rpc tests-lib-tests -./usr/tests/lib/libc/rpc/Atffile tests-lib-tests atf -./usr/tests/lib/libc/rpc/t_xdr tests-lib-tests atf +#LSC: Not on MINIX ./usr/tests/lib/libc/rpc/Kyuafile tests-lib-tests atf,kyua ./usr/tests/lib/libc/setjmp tests-lib-tests -./usr/tests/lib/libc/setjmp/Atffile tests-lib-tests atf -./usr/tests/lib/libc/setjmp/t_threadjmp tests-lib-tests atf -./usr/tests/lib/libc/setjmp/t_setjmp tests-lib-tests atf +#LSC: Not on MINIX ./usr/tests/lib/libc/setjmp/Kyuafile tests-lib-tests atf,kyua ./usr/tests/lib/libc/ssp tests-lib-tests -./usr/tests/lib/libc/ssp/Atffile tests-lib-tests atf,ssp -./usr/tests/lib/libc/ssp/h_fgets tests-lib-tests atf,ssp -./usr/tests/lib/libc/ssp/h_getcwd tests-lib-tests atf,ssp -./usr/tests/lib/libc/ssp/h_gets tests-lib-tests atf,ssp -./usr/tests/lib/libc/ssp/h_memcpy tests-lib-tests atf,ssp -./usr/tests/lib/libc/ssp/h_memmove tests-lib-tests atf,ssp -./usr/tests/lib/libc/ssp/h_memset tests-lib-tests atf,ssp -./usr/tests/lib/libc/ssp/h_raw tests-lib-tests atf,ssp -./usr/tests/lib/libc/ssp/h_read tests-lib-tests atf,ssp -./usr/tests/lib/libc/ssp/h_readlink tests-lib-tests atf,ssp -./usr/tests/lib/libc/ssp/h_snprintf tests-lib-tests atf,ssp -./usr/tests/lib/libc/ssp/h_sprintf tests-lib-tests atf,ssp -./usr/tests/lib/libc/ssp/h_strcat tests-lib-tests atf,ssp -./usr/tests/lib/libc/ssp/h_strcpy tests-lib-tests atf,ssp -./usr/tests/lib/libc/ssp/h_strncat tests-lib-tests atf,ssp -./usr/tests/lib/libc/ssp/h_strncpy tests-lib-tests atf,ssp -./usr/tests/lib/libc/ssp/h_vsnprintf tests-lib-tests atf,ssp -./usr/tests/lib/libc/ssp/h_vsprintf tests-lib-tests atf,ssp -./usr/tests/lib/libc/ssp/t_ssp tests-lib-tests atf,ssp +#LSC: Not on MINIX ./usr/tests/lib/libc/ssp/Kyuafile tests-lib-tests atf,ssp,kyua ./usr/tests/lib/libc/stdio tests-lib-tests ./usr/tests/lib/libc/stdio/Atffile tests-lib-tests atf +./usr/tests/lib/libc/stdio/Kyuafile tests-lib-tests atf,kyua ./usr/tests/lib/libc/stdio/t_clearerr tests-lib-tests atf ./usr/tests/lib/libc/stdio/t_fflush tests-lib-tests atf ./usr/tests/lib/libc/stdio/t_fmemopen tests-lib-tests atf @@ -2392,10 +1912,10 @@ ./usr/tests/lib/libc/stdio/t_fputc tests-lib-tests atf ./usr/tests/lib/libc/stdio/t_format tests-obsolete obsolete ./usr/tests/lib/libc/stdio/t_popen tests-lib-tests atf -./usr/tests/lib/libc/stdio/t_printf tests-lib-tests atf ./usr/tests/lib/libc/stdio/t_scanf tests-lib-tests atf ./usr/tests/lib/libc/stdlib tests-lib-tests ./usr/tests/lib/libc/stdlib/Atffile tests-lib-tests atf +./usr/tests/lib/libc/stdlib/Kyuafile tests-lib-tests atf,kyua ./usr/tests/lib/libc/stdlib/h_atexit tests-lib-tests atf ./usr/tests/lib/libc/stdlib/h_getopt tests-lib-tests atf ./usr/tests/lib/libc/stdlib/h_getopt_long tests-lib-tests atf @@ -2407,11 +1927,9 @@ ./usr/tests/lib/libc/stdlib/t_environment_pth tests-obsolete obsolete ./usr/tests/lib/libc/stdlib/t_exit tests-lib-tests atf ./usr/tests/lib/libc/stdlib/t_getenv tests-lib-tests atf -./usr/tests/lib/libc/stdlib/t_getenv_thread tests-lib-tests atf ./usr/tests/lib/libc/stdlib/t_getopt tests-lib-tests atf ./usr/tests/lib/libc/stdlib/t_hsearch tests-lib-tests atf ./usr/tests/lib/libc/stdlib/t_mi_vector_hash tests-lib-tests atf -./usr/tests/lib/libc/stdlib/t_posix_memalign tests-lib-tests atf ./usr/tests/lib/libc/stdlib/t_random tests-lib-tests atf ./usr/tests/lib/libc/stdlib/t_strtod tests-lib-tests atf ./usr/tests/lib/libc/stdlib/t_strtol tests-lib-tests atf @@ -2419,6 +1937,7 @@ ./usr/tests/lib/libc/stdlib/t_system tests-lib-tests atf ./usr/tests/lib/libc/string tests-lib-tests ./usr/tests/lib/libc/string/Atffile tests-lib-tests atf +./usr/tests/lib/libc/string/Kyuafile tests-lib-tests atf,kyua ./usr/tests/lib/libc/string/t_memchr tests-lib-tests atf ./usr/tests/lib/libc/string/t_memcpy tests-lib-tests atf ./usr/tests/lib/libc/string/t_memmem tests-lib-tests atf @@ -2438,74 +1957,15 @@ ./usr/tests/lib/libc/string/t_strspn tests-lib-tests atf ./usr/tests/lib/libc/string/t_swab tests-lib-tests atf ./usr/tests/lib/libc/sys tests-lib-tests -./usr/tests/lib/libc/sys/Atffile tests-lib-tests atf -./usr/tests/lib/libc/sys/t_access tests-lib-tests atf -./usr/tests/lib/libc/sys/t_cerror tests-obsolete obsolete -./usr/tests/lib/libc/sys/t_chroot tests-lib-tests atf -./usr/tests/lib/libc/sys/t_clock_gettime tests-lib-tests atf -./usr/tests/lib/libc/sys/t_clone tests-lib-tests atf -./usr/tests/lib/libc/sys/t_connect tests-lib-tests atf -./usr/tests/lib/libc/sys/t_context tests-obsolete obsolete -./usr/tests/lib/libc/sys/t_dup tests-lib-tests atf -./usr/tests/lib/libc/sys/t_fsync tests-lib-tests atf -./usr/tests/lib/libc/sys/t_getcontext tests-lib-tests atf -./usr/tests/lib/libc/sys/t_getgroups tests-lib-tests atf -./usr/tests/lib/libc/sys/t_getitimer tests-lib-tests atf -./usr/tests/lib/libc/sys/t_getlogin tests-lib-tests atf -./usr/tests/lib/libc/sys/t_getpid tests-lib-tests atf -./usr/tests/lib/libc/sys/t_getrusage tests-lib-tests atf -./usr/tests/lib/libc/sys/t_getsid tests-lib-tests atf -./usr/tests/lib/libc/sys/t_gettimeofday tests-lib-tests atf -./usr/tests/lib/libc/sys/t_issetugid tests-lib-tests atf -./usr/tests/lib/libc/sys/t_kevent tests-lib-tests atf -./usr/tests/lib/libc/sys/t_kill tests-lib-tests atf -./usr/tests/lib/libc/sys/t_link tests-lib-tests atf -./usr/tests/lib/libc/sys/t_listen tests-lib-tests atf -./usr/tests/lib/libc/sys/t_lwp_ctl tests-lib-tests atf -./usr/tests/lib/libc/sys/t_lwp_create tests-lib-tests atf -./usr/tests/lib/libc/sys/t_mincore tests-lib-tests atf -./usr/tests/lib/libc/sys/t_mkdir tests-lib-tests atf -./usr/tests/lib/libc/sys/t_mkfifo tests-lib-tests atf -./usr/tests/lib/libc/sys/t_mknod tests-lib-tests atf -./usr/tests/lib/libc/sys/t_mlock tests-lib-tests atf -./usr/tests/lib/libc/sys/t_mmap tests-lib-tests atf -./usr/tests/lib/libc/sys/t_mprotect tests-lib-tests atf -./usr/tests/lib/libc/sys/t_msgctl tests-lib-tests atf -./usr/tests/lib/libc/sys/t_msgget tests-lib-tests atf -./usr/tests/lib/libc/sys/t_msgrcv tests-lib-tests atf -./usr/tests/lib/libc/sys/t_msgsnd tests-lib-tests atf -./usr/tests/lib/libc/sys/t_msync tests-lib-tests atf -./usr/tests/lib/libc/sys/t_nanosleep tests-lib-tests atf -./usr/tests/lib/libc/sys/t_pipe tests-lib-tests atf -./usr/tests/lib/libc/sys/t_pipe2 tests-lib-tests atf -./usr/tests/lib/libc/sys/t_poll tests-lib-tests atf -./usr/tests/lib/libc/sys/t_posix_fadvise tests-lib-tests atf,rump -./usr/tests/lib/libc/sys/t_recvmmsg tests-lib-tests atf -./usr/tests/lib/libc/sys/t_revoke tests-lib-tests atf -./usr/tests/lib/libc/sys/t_select tests-lib-tests atf -./usr/tests/lib/libc/sys/t_setrlimit tests-lib-tests atf -./usr/tests/lib/libc/sys/t_setuid tests-lib-tests atf -./usr/tests/lib/libc/sys/t_sigaction tests-lib-tests atf -./usr/tests/lib/libc/sys/t_sigqueue tests-lib-tests atf -./usr/tests/lib/libc/sys/t_socketpair tests-lib-tests atf -./usr/tests/lib/libc/sys/t_stat tests-lib-tests atf -./usr/tests/lib/libc/sys/t_swapcontext tests-lib-tests atf -./usr/tests/lib/libc/sys/t_timer_create tests-lib-tests atf -./usr/tests/lib/libc/sys/t_truncate tests-lib-tests atf -./usr/tests/lib/libc/sys/t_ucontext tests-lib-tests atf -./usr/tests/lib/libc/sys/t_umask tests-lib-tests atf -./usr/tests/lib/libc/sys/t_unlink tests-lib-tests atf -./usr/tests/lib/libc/sys/t_write tests-lib-tests atf +#LSC: Not on MINIX ./usr/tests/lib/libc/sys/Kyuafile tests-lib-tests atf,kyua ./usr/tests/lib/libc/termios tests-lib-tests ./usr/tests/lib/libc/termios/Atffile tests-lib-tests atf +./usr/tests/lib/libc/termios/Kyuafile tests-lib-tests atf,kyua ./usr/tests/lib/libc/termios/t_tcsetpgrp tests-lib-tests atf ./usr/tests/lib/libc/tls tests-lib-tests -./usr/tests/lib/libc/tls/Atffile tests-lib-tests atf -./usr/tests/lib/libc/tls/t_tls_static tests-lib-tests atf +#LSC: Not on MINIX ./usr/tests/lib/libc/tls/Kyuafile tests-lib-tests atf,kyua ./usr/tests/lib/libc/ttyio tests-lib-tests -./usr/tests/lib/libc/ttyio/Atffile tests-lib-tests atf -./usr/tests/lib/libc/ttyio/t_ptm tests-lib-tests atf -./usr/tests/lib/libc/ttyio/t_ttyio tests-lib-tests atf +#LSC: Not on MINIX ./usr/tests/lib/libc/ttyio/Kyuafile tests-lib-tests atf,kyua ./usr/tests/lib/libc/t_atexit tests-obsolete obsolete ./usr/tests/lib/libc/t_cerror tests-obsolete obsolete ./usr/tests/lib/libc/t_clone tests-obsolete obsolete @@ -2525,12 +1985,13 @@ ./usr/tests/lib/libc/time tests-lib-tests ./usr/tests/lib/libcrypt tests-lib-tests ./usr/tests/lib/libcrypt/Atffile tests-lib-tests +./usr/tests/lib/libcrypt/Kyuafile tests-lib-tests kyua ./usr/tests/lib/libcrypt/t_crypt tests-lib-tests ./usr/tests/lib/libcurses tests-lib-tests ./usr/tests/lib/libcurses/.terminfo.db tests-obsolete obsolete -./usr/tests/lib/libcurses/terminfo.cdb tests-lib-tests atf ./usr/tests/lib/libcurses/terminfo.db tests-obsolete obsolete ./usr/tests/lib/libcurses/Atffile tests-lib-tests atf +./usr/tests/lib/libcurses/Kyuafile tests-lib-tests atf,kyua ./usr/tests/lib/libcurses/check_files tests-lib-tests ./usr/tests/lib/libcurses/check_files/addch.chk tests-lib-tests atf ./usr/tests/lib/libcurses/check_files/addchstr.chk tests-lib-tests atf @@ -2591,7 +2052,6 @@ ./usr/tests/lib/libcurses/check_files/wprintw_refresh.chk tests-lib-tests atf ./usr/tests/lib/libcurses/check_files/wscrl1.chk tests-lib-tests atf ./usr/tests/lib/libcurses/check_files/wscrl2.chk tests-lib-tests atf -./usr/tests/lib/libcurses/director tests-lib-tests atf ./usr/tests/lib/libcurses/slave tests-lib-tests atf ./usr/tests/lib/libcurses/t_curses tests-lib-tests atf ./usr/tests/lib/libcurses/tests tests-lib-tests @@ -2629,24 +2089,38 @@ ./usr/tests/lib/libcurses/tests/wscrl tests-lib-tests atf ./usr/tests/lib/libdes tests-lib-tests ./usr/tests/lib/libc/time/Atffile tests-lib-tests atf +./usr/tests/lib/libc/time/Kyuafile tests-lib-tests atf,kyua ./usr/tests/lib/libc/time/t_mktime tests-lib-tests atf ./usr/tests/lib/libc/time/t_strptime tests-lib-tests atf ./usr/tests/lib/libdes/Atffile tests-lib-tests atf,crypto +./usr/tests/lib/libdes/Kyuafile tests-lib-tests atf,crypto,kyua ./usr/tests/lib/libdes/t_des tests-lib-tests atf,crypto ./usr/tests/lib/semaphore tests-lib-tests -./usr/tests/lib/semaphore/Atffile tests-lib-tests atf +#LSC: Not on MINIX ./usr/tests/lib/semaphore/Kyuafile tests-lib-tests atf,kyua ./usr/tests/lib/semaphore/pthread tests-lib-tests ./usr/tests/lib/semaphore/pthread/Atffile tests-lib-tests atf,rump +./usr/tests/lib/semaphore/pthread/Kyuafile tests-lib-tests atf,rump,kyua ./usr/tests/lib/semaphore/pthread/t_sem_pth tests-lib-tests atf,rump +./usr/tests/lib/libbpfjit tests-lib-tests atf +./usr/tests/lib/libbpfjit/Atffile tests-lib-tests atf,sljit +./usr/tests/lib/libbpfjit/Kyuafile tests-lib-tests atf,sljit,kyua +./usr/tests/lib/libbpfjit/t_bpfjit tests-lib-tests atf,sljit ./usr/tests/lib/libevent tests-lib-tests -./usr/tests/lib/libevent/Atffile tests-lib-tests atf -./usr/tests/lib/libevent/h_event tests-lib-tests atf -./usr/tests/lib/libevent/t_event tests-lib-tests atf +#LSC: Not on MINIX ./usr/tests/lib/libevent/Kyuafile tests-lib-tests atf,kyua ./usr/tests/lib/libexecinfo tests-lib-tests -./usr/tests/lib/libexecinfo/Atffile tests-lib-tests atf -./usr/tests/lib/libexecinfo/t_backtrace tests-lib-tests atf +#LSC: Not on MINIX ./usr/tests/lib/libexecinfo/Kyuafile tests-lib-tests atf,kyua +./usr/tests/lib/liblutok tests-lutok-tests +./usr/tests/lib/liblutok/Atffile tests-lutok-tests atf,kyua +./usr/tests/lib/liblutok/Kyuafile tests-lutok-tests atf,kyua +./usr/tests/lib/liblutok/c_gate_test tests-lutok-tests atf,kyua +./usr/tests/lib/liblutok/debug_test tests-lutok-tests atf,kyua +./usr/tests/lib/liblutok/exceptions_test tests-lutok-tests atf,kyua +./usr/tests/lib/liblutok/operations_test tests-lutok-tests atf,kyua +./usr/tests/lib/liblutok/stack_cleaner_test tests-lutok-tests atf,kyua +./usr/tests/lib/liblutok/state_test tests-lutok-tests atf,kyua ./usr/tests/lib/libm tests-lib-tests atf ./usr/tests/lib/libm/Atffile tests-lib-tests atf +./usr/tests/lib/libm/Kyuafile tests-lib-tests atf,kyua ./usr/tests/lib/libm/t_acos tests-lib-tests atf ./usr/tests/lib/libm/t_asin tests-lib-tests atf ./usr/tests/lib/libm/t_atan tests-lib-tests atf @@ -2663,69 +2137,34 @@ ./usr/tests/lib/libm/t_libm tests-obsolete obsolete ./usr/tests/lib/libm/t_pow tests-lib-tests atf ./usr/tests/lib/libm/t_round tests-lib-tests atf -./usr/tests/lib/libm/t_scalbn tests-lib-tests atf ./usr/tests/lib/libm/t_sin tests-lib-tests atf ./usr/tests/lib/libm/t_sinh tests-lib-tests atf ./usr/tests/lib/libm/t_sqrt tests-lib-tests atf ./usr/tests/lib/libm/t_tan tests-lib-tests atf ./usr/tests/lib/libm/t_tanh tests-lib-tests atf ./usr/tests/lib/libobjc tests-lib-tests atf -./usr/tests/lib/libobjc/Atffile tests-lib-tests atf -./usr/tests/lib/libobjc/t_threads tests-lib-tests atf,gcccmds +#LSC: Not on MINIX ./usr/tests/lib/libobjc/Kyuafile tests-lib-tests atf,kyua ./usr/tests/lib/libposix tests-lib-tests atf -./usr/tests/lib/libposix/Atffile tests-lib-tests atf +#LSC: Not on MINIX ./usr/tests/lib/libposix/Kyuafile tests-lib-tests atf,kyua ./usr/tests/lib/libposix/bsd tests-lib-tests atf -./usr/tests/lib/libposix/bsd/Atffile tests-lib-tests atf -./usr/tests/lib/libposix/bsd/t_rename tests-lib-tests atf +#LSC: Not on MINIX ./usr/tests/lib/libposix/bsd/Kyuafile tests-lib-tests atf,kyua ./usr/tests/lib/libposix/posix1 tests-lib-tests atf -./usr/tests/lib/libposix/posix1/Atffile tests-lib-tests atf -./usr/tests/lib/libposix/posix1/t_rename tests-lib-tests atf +#LSC: Not on MINIX ./usr/tests/lib/libposix/posix1/Kyuafile tests-lib-tests atf,kyua ./usr/tests/lib/libposix/posix2 tests-lib-tests atf -./usr/tests/lib/libposix/posix2/Atffile tests-lib-tests atf -./usr/tests/lib/libposix/posix2/t_rename tests-lib-tests atf +#LSC: Not on MINIX ./usr/tests/lib/libposix/posix2/Kyuafile tests-lib-tests atf,kyua ./usr/tests/lib/libppath tests-lib-tests atf -./usr/tests/lib/libppath/Atffile tests-lib-tests atf -./usr/tests/lib/libppath/t_ppath tests-lib-tests atf +#LSC: Not on MINIX ./usr/tests/lib/libppath/Kyuafile tests-lib-tests atf,kyua ./usr/tests/lib/libprop tests-lib-tests atf ./usr/tests/lib/libprop/Atffile tests-lib-tests atf +./usr/tests/lib/libprop/Kyuafile tests-lib-tests atf,kyua ./usr/tests/lib/libprop/t_basic tests-lib-tests atf ./usr/tests/lib/libpthread tests-lib-tests -./usr/tests/lib/libpthread/Atffile tests-lib-tests atf -./usr/tests/lib/libpthread/d_mach tests-lib-tests atf -./usr/tests/lib/libpthread/h_atexit tests-lib-tests atf -./usr/tests/lib/libpthread/h_cancel tests-lib-tests atf -./usr/tests/lib/libpthread/h_exit tests-lib-tests atf -./usr/tests/lib/libpthread/h_resolv tests-lib-tests atf -./usr/tests/lib/libpthread/t_atexit tests-lib-tests atf -./usr/tests/lib/libpthread/t_barrier tests-lib-tests atf -./usr/tests/lib/libpthread/t_cancel tests-lib-tests atf -./usr/tests/lib/libpthread/t_cond tests-lib-tests atf -./usr/tests/lib/libpthread/t_detach tests-lib-tests atf -./usr/tests/lib/libpthread/t_equal tests-lib-tests atf -./usr/tests/lib/libpthread/t_exit tests-lib-tests atf -./usr/tests/lib/libpthread/t_fork tests-lib-tests atf -./usr/tests/lib/libpthread/t_fpu tests-lib-tests atf -./usr/tests/lib/libpthread/t_join tests-lib-tests atf -./usr/tests/lib/libpthread/t_kill tests-lib-tests atf -./usr/tests/lib/libpthread/t_mutex tests-lib-tests atf -./usr/tests/lib/libpthread/t_name tests-lib-tests atf -./usr/tests/lib/libpthread/t_once tests-lib-tests atf -./usr/tests/lib/libpthread/t_preempt tests-lib-tests atf -./usr/tests/lib/libpthread/t_resolv tests-lib-tests atf -./usr/tests/lib/libpthread/t_rwlock tests-lib-tests atf -./usr/tests/lib/libpthread/t_sem tests-lib-tests atf -./usr/tests/lib/libpthread/t_sigmask tests-lib-tests atf -./usr/tests/lib/libpthread/t_sigsuspend tests-lib-tests atf -./usr/tests/lib/libpthread/t_siglongjmp tests-lib-tests atf -./usr/tests/lib/libpthread/t_sleep tests-lib-tests atf -./usr/tests/lib/libpthread/t_status tests-obsolete obsolete -./usr/tests/lib/libpthread/t_swapcontext tests-lib-tests atf +#LSC: Not on MINIX ./usr/tests/lib/libpthread/Kyuafile tests-lib-tests atf,kyua ./usr/tests/lib/librt tests-lib-tests atf -./usr/tests/lib/librt/Atffile tests-lib-tests atf -./usr/tests/lib/librt/t_sched tests-lib-tests atf -./usr/tests/lib/librt/t_sem tests-lib-tests atf +#LSC: Not on MINIX ./usr/tests/lib/librt/Kyuafile tests-lib-tests atf,kyua ./usr/tests/lib/librumpclient tests-lib-tests atf ./usr/tests/lib/librumpclient/Atffile tests-lib-tests atf,rump +./usr/tests/lib/librumpclient/Kyuafile tests-lib-tests atf,rump,kyua ./usr/tests/lib/librumpclient/h_exec tests-lib-tests atf,rump ./usr/tests/lib/librumpclient/h_execthr tests-lib-tests atf,rump ./usr/tests/lib/librumpclient/h_ution tests-obsolete obsolete @@ -2733,6 +2172,7 @@ ./usr/tests/lib/librumpclient/t_fd tests-lib-tests atf,rump ./usr/tests/lib/librumphijack tests-lib-tests atf ./usr/tests/lib/librumphijack/Atffile tests-lib-tests atf,rump +./usr/tests/lib/librumphijack/Kyuafile tests-lib-tests atf,rump,kyua ./usr/tests/lib/librumphijack/h_client tests-lib-tests atf,rump ./usr/tests/lib/librumphijack/h_cwd tests-lib-tests atf,rump ./usr/tests/lib/librumphijack/h_netget tests-lib-tests atf,rump @@ -2750,139 +2190,99 @@ ./usr/tests/lib/librumphijack/sshd_config.in tests-lib-tests atf,rump ./usr/tests/lib/libskey tests-lib-tests atf ./usr/tests/lib/libskey/Atffile tests-lib-tests atf,skey +./usr/tests/lib/libskey/Kyuafile tests-lib-tests atf,skey,kyua ./usr/tests/lib/libskey/t_algorithms tests-lib-tests atf,skey +./usr/tests/lib/libsljit tests-lib-tests atf +./usr/tests/lib/libsljit/Atffile tests-lib-tests atf,sljit +./usr/tests/lib/libsljit/Kyuafile tests-lib-tests atf,sljit,kyua +./usr/tests/lib/libsljit/h_sljit tests-lib-tests atf,sljit +./usr/tests/lib/libsljit/t_sljit tests-lib-tests atf,sljit ./usr/tests/lib/libtre tests-lib-tests atf -./usr/tests/lib/libtre/Atffile tests-lib-tests atf +#LSC: Not on MINIX ./usr/tests/lib/libtre/Kyuafile tests-lib-tests atf,kyua ./usr/tests/lib/libtre/h_regex_att tests-obsolete obsolete -./usr/tests/lib/libtre/t_exhaust tests-lib-tests atf -./usr/tests/lib/libtre/t_regex_att tests-lib-tests atf ./usr/tests/lib/libtre/data tests-lib-tests atf -./usr/tests/lib/libtre/data/README tests-lib-tests atf -./usr/tests/lib/libtre/data/anchor.in tests-lib-tests atf -./usr/tests/lib/libtre/data/backref.in tests-lib-tests atf -./usr/tests/lib/libtre/data/basic.dat tests-lib-tests atf -./usr/tests/lib/libtre/data/basic.in tests-lib-tests atf -./usr/tests/lib/libtre/data/bracket.in tests-lib-tests atf -./usr/tests/lib/libtre/data/c_comments.in tests-lib-tests atf -./usr/tests/lib/libtre/data/categorization.dat tests-lib-tests atf -./usr/tests/lib/libtre/data/complex.in tests-lib-tests atf -./usr/tests/lib/libtre/data/error.in tests-lib-tests atf -./usr/tests/lib/libtre/data/forcedassoc.dat tests-lib-tests atf -./usr/tests/lib/libtre/data/leftassoc.dat tests-lib-tests atf -./usr/tests/lib/libtre/data/meta.in tests-lib-tests atf -./usr/tests/lib/libtre/data/nospec.in tests-lib-tests atf -./usr/tests/lib/libtre/data/nullsubexpr.dat tests-lib-tests atf -./usr/tests/lib/libtre/data/paren.in tests-lib-tests atf -./usr/tests/lib/libtre/data/regress.in tests-lib-tests atf -./usr/tests/lib/libtre/data/repet_bounded.in tests-lib-tests atf -./usr/tests/lib/libtre/data/repet_multi.in tests-lib-tests atf -./usr/tests/lib/libtre/data/repet_ordinary.in tests-lib-tests atf -./usr/tests/lib/libtre/data/repetition.dat tests-lib-tests atf -./usr/tests/lib/libtre/data/rightassoc.dat tests-lib-tests atf -./usr/tests/lib/libtre/data/startend.in tests-lib-tests atf -./usr/tests/lib/libtre/data/subexp.in tests-lib-tests atf -./usr/tests/lib/libtre/data/subtle.in tests-lib-tests atf -./usr/tests/lib/libtre/data/word_bound.in tests-lib-tests atf -./usr/tests/lib/libtre/data/zero.in tests-lib-tests atf ./usr/tests/lib/libutil tests-lib-tests atf ./usr/tests/lib/libutil/Atffile tests-lib-tests atf +./usr/tests/lib/libutil/Kyuafile tests-lib-tests atf,kyua ./usr/tests/lib/libutil/t_efun tests-lib-tests atf -./usr/tests/lib/libutil/t_parsedate tests-lib-tests atf ./usr/tests/lib/libutil/t_pidfile tests-lib-tests atf ./usr/tests/lib/libutil/t_snprintb tests-lib-tests atf -./usr/tests/lib/libutil/t_sockaddr_snprintf tests-lib-tests atf ./usr/tests/libexec tests-lib-tests -./usr/tests/libexec/Atffile tests-lib-tests atf +./usr/tests/libexec/Kyuafile tests-lib-tests atf,kyua ./usr/tests/libexec/ld.elf_so tests-libexec-tests -./usr/tests/libexec/ld.elf_so/Atffile tests-libexec-tests atf,pic +#LSC: Not on MINIX ./usr/tests/libexec/ld.elf_so/Kyuafile tests-libexec-tests atf,pic,kyua ./usr/tests/libexec/ld.elf_so/data tests-libexec-tests atf -./usr/tests/libexec/ld.elf_so/data/symver-output-ref-stderr.v0-v0 tests-libexec-tests atf,pic -./usr/tests/libexec/ld.elf_so/data/symver-output-ref-stderr.v0-v1 tests-libexec-tests atf,pic -./usr/tests/libexec/ld.elf_so/data/symver-output-ref-stderr.v0-v2 tests-libexec-tests atf,pic -./usr/tests/libexec/ld.elf_so/data/symver-output-ref-stderr.v1-v0 tests-libexec-tests atf,pic -./usr/tests/libexec/ld.elf_so/data/symver-output-ref-stderr.v1-v1 tests-libexec-tests atf,pic -./usr/tests/libexec/ld.elf_so/data/symver-output-ref-stderr.v1-v2 tests-libexec-tests atf,pic -./usr/tests/libexec/ld.elf_so/data/symver-output-ref-stderr.v2-v0 tests-libexec-tests atf,pic -./usr/tests/libexec/ld.elf_so/data/symver-output-ref-stderr.v2-v1 tests-libexec-tests atf,pic -./usr/tests/libexec/ld.elf_so/data/symver-output-ref-stderr.v2-v2 tests-libexec-tests atf,pic -./usr/tests/libexec/ld.elf_so/data/symver-output-ref-stdout.v0-v0 tests-libexec-tests atf,pic -./usr/tests/libexec/ld.elf_so/data/symver-output-ref-stdout.v0-v1 tests-libexec-tests atf,pic -./usr/tests/libexec/ld.elf_so/data/symver-output-ref-stdout.v0-v2 tests-libexec-tests atf,pic -./usr/tests/libexec/ld.elf_so/data/symver-output-ref-stdout.v1-v0 tests-libexec-tests atf,pic -./usr/tests/libexec/ld.elf_so/data/symver-output-ref-stdout.v1-v1 tests-libexec-tests atf,pic -./usr/tests/libexec/ld.elf_so/data/symver-output-ref-stdout.v1-v2 tests-libexec-tests atf,pic -./usr/tests/libexec/ld.elf_so/data/symver-output-ref-stdout.v2-v0 tests-libexec-tests atf,pic -./usr/tests/libexec/ld.elf_so/data/symver-output-ref-stdout.v2-v1 tests-libexec-tests atf,pic -./usr/tests/libexec/ld.elf_so/data/symver-output-ref-stdout.v2-v2 tests-libexec-tests atf,pic -./usr/tests/libexec/ld.elf_so/h_df_1_noopen1 tests-libexec-tests atf,pic -./usr/tests/libexec/ld.elf_so/h_df_1_noopen2 tests-libexec-tests atf,pic -./usr/tests/libexec/ld.elf_so/h_dl_symver_v0 tests-libexec-tests atf,pic -./usr/tests/libexec/ld.elf_so/h_dl_symver_v1 tests-libexec-tests atf,pic -./usr/tests/libexec/ld.elf_so/h_dl_symver_v2 tests-libexec-tests atf,pic ./usr/tests/libexec/ld.elf_so/h_helper_symver_dso0 tests-libexec-tests atf ./usr/tests/libexec/ld.elf_so/h_helper_symver_dso1 tests-libexec-tests atf ./usr/tests/libexec/ld.elf_so/h_helper_symver_dso2 tests-libexec-tests atf -./usr/tests/libexec/ld.elf_so/h_locking tests-libexec-tests atf,pic -./usr/tests/libexec/ld.elf_so/t_df_1_noopen tests-libexec-tests atf,pic -./usr/tests/libexec/ld.elf_so/t_dl_symver tests-libexec-tests atf,pic -./usr/tests/libexec/ld.elf_so/t_dlerror-cleared tests-libexec-tests atf,pic -./usr/tests/libexec/ld.elf_so/t_dlerror-false tests-libexec-tests atf,pic -./usr/tests/libexec/ld.elf_so/t_dlinfo tests-libexec-tests atf,pic -./usr/tests/libexec/ld.elf_so/t_dlvsym tests-libexec-tests atf,pic ./usr/tests/modules tests-sys-tests ./usr/tests/net tests-net-tests -./usr/tests/net/Atffile tests-net-tests atf +#LSC: Not on MINIX ./usr/tests/net/Atffile tests-net-tests atf +#LSC: Not on MINIX ./usr/tests/net/Kyuafile tests-net-tests atf,kyua ./usr/tests/net/bpf tests-net-tests ./usr/tests/net/bpf/Atffile tests-net-tests atf,rump +./usr/tests/net/bpf/Kyuafile tests-net-tests atf,rump,kyua ./usr/tests/net/bpf/t_bpf tests-net-tests atf,rump ./usr/tests/net/bpf/t_div-by-zero tests-net-tests atf,rump ./usr/tests/net/bpfilter tests-net-tests ./usr/tests/net/bpfilter/Atffile tests-net-tests atf,rump +./usr/tests/net/bpfilter/Kyuafile tests-net-tests atf,rump,kyua ./usr/tests/net/bpfilter/t_bpfilter tests-net-tests atf,rump ./usr/tests/net/carp tests-net-tests ./usr/tests/net/carp/Atffile tests-net-tests atf,rump +./usr/tests/net/carp/Kyuafile tests-net-tests atf,rump,kyua ./usr/tests/net/carp/t_basic tests-net-tests atf,rump ./usr/tests/net/fdpass tests-net-tests -./usr/tests/net/fdpass/Atffile tests-net-tests atf -./usr/tests/net/fdpass/fdpass32 tests-net-tests atf -./usr/tests/net/fdpass/fdpass64 tests-net-tests atf -./usr/tests/net/fdpass/t_fdpass tests-net-tests atf +#LSC: Not on MINIX ./usr/tests/net/fdpass/Atffile tests-net-tests atf +#LSC: Not on MINIX ./usr/tests/net/fdpass/Kyuafile tests-net-tests atf,kyua +#LSC: Not on MINIX ./usr/tests/net/fdpass/fdpass32 tests-net-tests atf +#LSC: Not on MINIX ./usr/tests/net/fdpass/fdpass64 tests-net-tests atf +#LSC: Not on MINIX ./usr/tests/net/fdpass/t_fdpass tests-net-tests atf ./usr/tests/net/icmp/t_forward tests-net-tests atf,rump ./usr/tests/net/icmp tests-net-tests ./usr/tests/net/icmp/Atffile tests-net-tests atf,rump +./usr/tests/net/icmp/Kyuafile tests-net-tests atf,rump,kyua ./usr/tests/net/icmp/t_forward tests-net-tests atf,rump ./usr/tests/net/icmp/t_ping tests-net-tests atf,rump ./usr/tests/net/icmp/t_ping2 tests-net-tests atf,rump ./usr/tests/net/if tests-net-tests ./usr/tests/net/if/Atffile tests-net-tests atf,rump +./usr/tests/net/if/Kyuafile tests-net-tests atf,rump,kyua ./usr/tests/net/if/t_compat tests-net-tests atf,rump ./usr/tests/net/if_loop tests-net-tests ./usr/tests/net/if_loop/Atffile tests-net-tests atf,rump +./usr/tests/net/if_loop/Kyuafile tests-net-tests atf,rump,kyua ./usr/tests/net/if_loop/t_pr tests-net-tests atf,rump ./usr/tests/net/net tests-net-tests ./usr/tests/net/net/Atffile tests-net-tests atf,rump +./usr/tests/net/net/Kyuafile tests-net-tests atf,rump,kyua ./usr/tests/net/net/t_raw tests-net-tests atf,rump +./usr/tests/net/net/t_udp tests-net-tests atf,rump ./usr/tests/net/net/t_unix tests-net-tests atf,rump ./usr/tests/net/npf tests-net-tests ./usr/tests/net/npf/Atffile tests-net-tests atf,rump +./usr/tests/net/npf/Kyuafile tests-net-tests atf,rump,kyua ./usr/tests/net/npf/npftest.conf tests-net-tests atf,rump ./usr/tests/net/npf/t_npf tests-net-tests atf,rump ./usr/tests/net/route tests-net-tests -./usr/tests/net/route/Atffile tests-net-tests atf -./usr/tests/net/route/t_change tests-net-tests atf +#LSC: Not on MINIX ./usr/tests/net/route/Atffile tests-net-tests atf +#LSC: Not on MINIX ./usr/tests/net/route/Kyuafile tests-net-tests atf,kyua +#LSC: Not on MINIX ./usr/tests/net/route/t_change tests-net-tests atf ./usr/tests/net/sys tests-net-tests -./usr/tests/net/sys/Atffile tests-net-tests atf +#LSC: Not on MINIX ./usr/tests/net/sys/Kyuafile tests-net-tests atf,kyua ./usr/tests/net/sys/t_connect tests-obsolete obsolete ./usr/tests/net/sys/t_listen tests-obsolete obsolete -./usr/tests/net/sys/t_rfc6056 tests-net-tests atf ./usr/tests/net/sys/t_socketpair tests-obsolete obsolete ./usr/tests/rump tests-rump-tests ./usr/tests/rump/Atffile tests-rump-tests atf,rump +./usr/tests/rump/Kyuafile tests-rump-tests atf,rump,kyua ./usr/tests/rump/modautoload tests-rump-tests ./usr/tests/rump/modautoload/Atffile tests-rump-tests atf,rump +./usr/tests/rump/modautoload/Kyuafile tests-rump-tests atf,rump,kyua ./usr/tests/rump/modautoload/t_modautoload tests-rump-tests atf,rump ./usr/tests/rump/rumpkern tests-rump-tests ./usr/tests/rump/rumpkern/Atffile tests-rump-tests atf,rump +./usr/tests/rump/rumpkern/Kyuafile tests-rump-tests atf,rump,kyua ./usr/tests/rump/rumpkern/t_copy tests-rump-tests atf,rump ./usr/tests/rump/rumpkern/t_kern tests-rump-tests atf,rump ./usr/tests/rump/rumpkern/t_lwproc tests-rump-tests atf,rump @@ -2904,29 +2304,37 @@ ./usr/tests/rump/rumpkern/h_server/h_simpleserver tests-rump-tests atf,rump ./usr/tests/rump/rumpnet tests-rump-tests ./usr/tests/rump/rumpnet/Atffile tests-rump-tests atf,rump +./usr/tests/rump/rumpnet/Kyuafile tests-rump-tests atf,rump,kyua ./usr/tests/rump/rumpnet/t_shmif tests-rump-tests atf,rump ./usr/tests/rump/rumpvfs tests-rump-tests ./usr/tests/rump/rumpvfs/Atffile tests-rump-tests atf,rump +./usr/tests/rump/rumpvfs/Kyuafile tests-rump-tests atf,rump,kyua ./usr/tests/rump/rumpvfs/t_basic tests-rump-tests atf,rump ./usr/tests/rump/rumpvfs/t_etfs tests-rump-tests atf,rump ./usr/tests/rump/rumpvfs/t_p2kifs tests-rump-tests atf,rump ./usr/tests/sbin tests-sbin-tests ./usr/tests/sbin/Atffile tests-sbin-tests atf +./usr/tests/sbin/Kyuafile tests-sbin-tests atf,kyua ./usr/tests/sbin/fsck_ffs tests-sbin-tests ./usr/tests/sbin/fsck_ffs/Atffile tests-sbin-tests atf +./usr/tests/sbin/fsck_ffs/Kyuafile tests-sbin-tests atf,kyua ./usr/tests/sbin/fsck_ffs/t_check_quotas tests-sbin-tests atf ./usr/tests/sbin/fsck_ffs/t_enable_quotas tests-sbin-tests atf ./usr/tests/sbin/ifconfig tests-sbin-tests ./usr/tests/sbin/ifconfig/Atffile tests-sbin-tests atf +./usr/tests/sbin/ifconfig/Kyuafile tests-sbin-tests atf,kyua ./usr/tests/sbin/ifconfig/t_nonexistent tests-sbin-tests atf ./usr/tests/sbin/newfs tests-sbin-tests ./usr/tests/sbin/newfs/Atffile tests-sbin-tests atf +./usr/tests/sbin/newfs/Kyuafile tests-sbin-tests atf,kyua ./usr/tests/sbin/newfs/t_enable_quotas tests-sbin-tests atf ./usr/tests/sbin/newfs_msdos tests-sbin-tests ./usr/tests/sbin/newfs_msdos/Atffile tests-sbin-tests atf +./usr/tests/sbin/newfs_msdos/Kyuafile tests-sbin-tests atf,kyua ./usr/tests/sbin/newfs_msdos/t_create tests-sbin-tests atf ./usr/tests/sbin/resize_ffs tests-sbin-tests ./usr/tests/sbin/resize_ffs/Atffile tests-sbin-tests atf +./usr/tests/sbin/resize_ffs/Kyuafile tests-sbin-tests atf,kyua ./usr/tests/sbin/resize_ffs/t_grow tests-sbin-tests atf ./usr/tests/sbin/resize_ffs/t_grow_swapped tests-sbin-tests atf ./usr/tests/sbin/resize_ffs/t_resize_ffs tests-obsolete obsolete @@ -2936,23 +2344,37 @@ ./usr/tests/sbin/resize_ffs/testdata.tar.gz.base64 tests-sbin-tests atf ./usr/tests/sbin/route tests-sbin-tests ./usr/tests/sbin/route/Atffile tests-sbin-tests atf +./usr/tests/sbin/route/Kyuafile tests-sbin-tests atf,kyua ./usr/tests/sbin/route/t_missing tests-sbin-tests atf ./usr/tests/sbin/sysctl tests-sbin-tests ./usr/tests/sbin/sysctl/Atffile tests-sbin-tests atf +./usr/tests/sbin/sysctl/Kyuafile tests-sbin-tests atf,kyua ./usr/tests/sbin/sysctl/t_perm tests-sbin-tests atf ./usr/tests/sbin/sysctl/t_sysctl tests-sbin-tests atf ./usr/tests/share tests-sys-tests +./usr/tests/share/examples tests-asm-tests +./usr/tests/share/examples/Atffile tests-asm-tests atf,share +./usr/tests/share/examples/Kyuafile tests-asm-tests atf,share,kyua +./usr/tests/share/examples/t_asm tests-asm-tests atf,share ./usr/tests/share/Atffile tests-sys-tests atf +./usr/tests/share/Kyuafile tests-sys-tests atf,kyua +./usr/tests/share/examples/lutok tests-lutok-tests +./usr/tests/share/examples/lutok/Atffile tests-lutok-tests atf,kyua,share +./usr/tests/share/examples/lutok/Kyuafile tests-lutok-tests atf,kyua,share,kyua +./usr/tests/share/examples/lutok/examples_test tests-lutok-tests atf,kyua,share ./usr/tests/share/mk tests-mk-tests ./usr/tests/share/mk/Atffile tests-mk-tests atf +./usr/tests/share/mk/Kyuafile tests-mk-tests atf,kyua ./usr/tests/share/mk/t_lib tests-mk-tests atf ./usr/tests/share/mk/t_own tests-mk-tests atf ./usr/tests/share/mk/t_prog tests-mk-tests atf ./usr/tests/share/mk/t_test tests-mk-tests atf ./usr/tests/sys tests-sys-tests ./usr/tests/sys/Atffile tests-sys-tests atf +./usr/tests/sys/Kyuafile tests-sys-tests atf,kyua ./usr/tests/sys/rc tests-sys-tests ./usr/tests/sys/rc/Atffile tests-sys-tests atf +./usr/tests/sys/rc/Kyuafile tests-sys-tests atf,kyua ./usr/tests/sys/rc/h_args tests-sys-tests atf ./usr/tests/sys/rc/h_simple tests-sys-tests atf ./usr/tests/sys/rc/t_rc_d_cli tests-sys-tests atf @@ -2999,8 +2421,10 @@ ./usr/tests/toolchain/cc/t_hello tests-obsolete obsolete ./usr/tests/usr.bin tests-usr.bin-tests ./usr/tests/usr.bin/Atffile tests-usr.bin-tests atf +./usr/tests/usr.bin/Kyuafile tests-usr.bin-tests atf,kyua ./usr/tests/usr.bin/awk tests-usr.bin-tests ./usr/tests/usr.bin/awk/Atffile tests-usr.bin-tests atf +./usr/tests/usr.bin/awk/Kyuafile tests-usr.bin-tests atf,kyua ./usr/tests/usr.bin/awk/t_awk tests-usr.bin-tests atf ./usr/tests/usr.bin/awk/d_assign_NF.awk tests-usr.bin-tests atf ./usr/tests/usr.bin/awk/d_assign_NF.in tests-usr.bin-tests atf @@ -3027,9 +2451,11 @@ ./usr/tests/usr.bin/awk/d_toupper.out tests-usr.bin-tests atf ./usr/tests/usr.bin/basename tests-usr.bin-tests ./usr/tests/usr.bin/basename/Atffile tests-usr.bin-tests atf +./usr/tests/usr.bin/basename/Kyuafile tests-usr.bin-tests atf,kyua ./usr/tests/usr.bin/basename/t_basename tests-usr.bin-tests atf ./usr/tests/usr.bin/bzip2 tests-usr.bin-tests ./usr/tests/usr.bin/bzip2/Atffile tests-usr.bin-tests atf +./usr/tests/usr.bin/bzip2/Kyuafile tests-usr.bin-tests atf,kyua ./usr/tests/usr.bin/bzip2/t_bzip2 tests-usr.bin-tests atf ./usr/tests/usr.bin/bzip2/d_sample1.bz2 tests-usr.bin-tests atf ./usr/tests/usr.bin/bzip2/d_sample1.ref tests-usr.bin-tests atf @@ -3039,12 +2465,15 @@ ./usr/tests/usr.bin/bzip2/d_sample3.ref tests-usr.bin-tests atf ./usr/tests/usr.bin/cc tests-usr.bin-tests ./usr/tests/usr.bin/cc/Atffile tests-usr.bin-tests atf +./usr/tests/usr.bin/cc/Kyuafile tests-usr.bin-tests atf,kyua ./usr/tests/usr.bin/cc/t_hello tests-usr.bin-tests atf ./usr/tests/usr.bin/cmp tests-usr.bin-tests ./usr/tests/usr.bin/cmp/Atffile tests-usr.bin-tests atf +./usr/tests/usr.bin/cmp/Kyuafile tests-usr.bin-tests atf,kyua ./usr/tests/usr.bin/cmp/t_cmp tests-usr.bin-tests atf ./usr/tests/usr.bin/config tests-usr.bin-tests ./usr/tests/usr.bin/config/Atffile tests-usr.bin-tests atf +./usr/tests/usr.bin/config/Kyuafile tests-usr.bin-tests atf,kyua ./usr/tests/usr.bin/config/Makefile.regress tests-usr.bin-tests atf ./usr/tests/usr.bin/config/t_config tests-usr.bin-tests atf ./usr/tests/usr.bin/config/d_deffs_redef tests-usr.bin-tests atf @@ -3068,6 +2497,7 @@ ./usr/tests/usr.bin/config/support/conf/files tests-usr.bin-tests atf ./usr/tests/usr.bin/cut tests-usr.bin-tests ./usr/tests/usr.bin/cut/Atffile tests-usr.bin-tests atf +./usr/tests/usr.bin/cut/Kyuafile tests-usr.bin-tests atf,kyua ./usr/tests/usr.bin/cut/d_basic.out tests-usr.bin-tests atf ./usr/tests/usr.bin/cut/d_cut.in tests-usr.bin-tests atf ./usr/tests/usr.bin/cut/d_dflag.out tests-usr.bin-tests atf @@ -3078,17 +2508,21 @@ ./usr/tests/usr.bin/cut/t_cut tests-usr.bin-tests atf ./usr/tests/usr.bin/diff tests-usr.bin-tests ./usr/tests/usr.bin/diff/Atffile tests-usr.bin-tests atf +./usr/tests/usr.bin/diff/Kyuafile tests-usr.bin-tests atf,kyua ./usr/tests/usr.bin/diff/d_mallocv1.in tests-usr.bin-tests atf ./usr/tests/usr.bin/diff/d_mallocv2.in tests-usr.bin-tests atf ./usr/tests/usr.bin/diff/t_diff tests-usr.bin-tests atf ./usr/tests/usr.bin/dirname tests-usr.bin-tests ./usr/tests/usr.bin/dirname/Atffile tests-usr.bin-tests atf +./usr/tests/usr.bin/dirname/Kyuafile tests-usr.bin-tests atf,kyua ./usr/tests/usr.bin/dirname/t_dirname tests-usr.bin-tests atf ./usr/tests/usr.bin/find tests-usr.bin-tests ./usr/tests/usr.bin/find/Atffile tests-usr.bin-tests atf +./usr/tests/usr.bin/find/Kyuafile tests-usr.bin-tests atf,kyua ./usr/tests/usr.bin/find/t_find tests-usr.bin-tests atf ./usr/tests/usr.bin/grep tests-usr.bin-tests ./usr/tests/usr.bin/grep/Atffile tests-usr.bin-tests atf +./usr/tests/usr.bin/grep/Kyuafile tests-usr.bin-tests atf,kyua ./usr/tests/usr.bin/grep/d_basic.out tests-usr.bin-tests atf ./usr/tests/usr.bin/grep/d_begin_end_a.out tests-usr.bin-tests atf ./usr/tests/usr.bin/grep/d_begin_end_b.out tests-usr.bin-tests atf @@ -3118,22 +2552,24 @@ ./usr/tests/usr.bin/grep/t_grep tests-usr.bin-tests atf ./usr/tests/usr.bin/gzip tests-usr.bin-tests ./usr/tests/usr.bin/gzip/Atffile tests-usr.bin-tests atf +./usr/tests/usr.bin/gzip/Kyuafile tests-usr.bin-tests atf,kyua ./usr/tests/usr.bin/gzip/t_gzip tests-usr.bin-tests atf ./usr/tests/usr.bin/id tests-usr.bin-tests ./usr/tests/usr.bin/id/Atffile tests-usr.bin-tests atf +./usr/tests/usr.bin/id/Kyuafile tests-usr.bin-tests atf,kyua ./usr/tests/usr.bin/id/h_id tests-usr.bin-tests atf ./usr/tests/usr.bin/id/t_groups tests-usr.bin-tests atf ./usr/tests/usr.bin/id/t_id tests-usr.bin-tests atf ./usr/tests/usr.bin/id/t_whoami tests-usr.bin-tests atf ./usr/tests/usr.bin/infocmp tests-usr.bin-tests ./usr/tests/usr.bin/infocmp/Atffile tests-usr.bin-tests atf +./usr/tests/usr.bin/infocmp/Kyuafile tests-usr.bin-tests atf,kyua ./usr/tests/usr.bin/infocmp/t_terminfo tests-usr.bin-tests atf ./usr/tests/usr.bin/jot tests-usr.bin-tests -./usr/tests/usr.bin/jot/Atffile tests-usr.bin-tests atf -./usr/tests/usr.bin/jot/d_basic.out tests-usr.bin-tests atf -./usr/tests/usr.bin/jot/t_jot tests-usr.bin-tests atf +./usr/tests/usr.bin/jot/Kyuafile tests-usr.bin-tests atf,kyua ./usr/tests/usr.bin/m4 tests-usr.bin-tests ./usr/tests/usr.bin/m4/Atffile tests-usr.bin-tests atf +./usr/tests/usr.bin/m4/Kyuafile tests-usr.bin-tests atf,kyua ./usr/tests/usr.bin/m4/d_ff_after_dnl.m4.uue tests-usr.bin-tests atf ./usr/tests/usr.bin/m4/d_ff_after_dnl.out tests-usr.bin-tests atf ./usr/tests/usr.bin/m4/d_m4wrap-P.m4 tests-usr.bin-tests atf @@ -3143,6 +2579,7 @@ ./usr/tests/usr.bin/m4/t_m4 tests-usr.bin-tests atf ./usr/tests/usr.bin/make tests-usr.bin-tests ./usr/tests/usr.bin/make/Atffile tests-usr.bin-tests atf +./usr/tests/usr.bin/make/Kyuafile tests-usr.bin-tests atf,kyua ./usr/tests/usr.bin/make/d_comment.mk tests-usr.bin-tests atf ./usr/tests/usr.bin/make/d_comment.out tests-usr.bin-tests atf ./usr/tests/usr.bin/make/d_cond1.mk tests-usr.bin-tests atf @@ -3178,22 +2615,31 @@ ./usr/tests/usr.bin/make/t_make tests-usr.bin-tests atf ./usr/tests/usr.bin/mkdep tests-usr.bin-tests ./usr/tests/usr.bin/mkdep/Atffile tests-usr.bin-tests atf +./usr/tests/usr.bin/mkdep/Kyuafile tests-usr.bin-tests atf,kyua ./usr/tests/usr.bin/mkdep/t_mkdep tests-usr.bin-tests atf ./usr/tests/usr.bin/nbperf tests-usr.bin-tests ./usr/tests/usr.bin/nbperf/Atffile tests-usr.bin-tests atf +./usr/tests/usr.bin/nbperf/Kyuafile tests-usr.bin-tests atf,kyua ./usr/tests/usr.bin/nbperf/h_nbperf tests-usr.bin-tests atf ./usr/tests/usr.bin/nbperf/hash_driver.c tests-usr.bin-tests atf ./usr/tests/usr.bin/nbperf/t_nbperf tests-usr.bin-tests atf +./usr/tests/usr.bin/netpgpverify tests-usr.bin-tests +./usr/tests/usr.bin/netpgpverify/Atffile tests-usr.bin-tests atf +./usr/tests/usr.bin/netpgpverify/Kyuafile tests-usr.bin-tests atf,kyua +./usr/tests/usr.bin/netpgpverify/t_netpgpverify tests-usr.bin-tests atf ./usr/tests/usr.bin/pr tests-usr.bin-tests ./usr/tests/usr.bin/pr/Atffile tests-usr.bin-tests atf +./usr/tests/usr.bin/pr/Kyuafile tests-usr.bin-tests atf,kyua ./usr/tests/usr.bin/pr/d_basic.in tests-usr.bin-tests atf ./usr/tests/usr.bin/pr/d_basic.out tests-usr.bin-tests atf ./usr/tests/usr.bin/pr/t_basic tests-usr.bin-tests atf ./usr/tests/usr.bin/rump_server tests-usr.bin-tests ./usr/tests/usr.bin/rump_server/Atffile tests-usr.bin-tests atf +./usr/tests/usr.bin/rump_server/Kyuafile tests-usr.bin-tests atf,kyua ./usr/tests/usr.bin/rump_server/t_disk tests-usr.bin-tests atf ./usr/tests/usr.bin/sdiff tests-usr.bin-tests ./usr/tests/usr.bin/sdiff/Atffile tests-usr.bin-tests atf +./usr/tests/usr.bin/sdiff/Kyuafile tests-usr.bin-tests atf,kyua ./usr/tests/usr.bin/sdiff/d_dot.in tests-usr.bin-tests atf ./usr/tests/usr.bin/sdiff/d_flags_l.out tests-usr.bin-tests atf ./usr/tests/usr.bin/sdiff/d_flags_s.out tests-usr.bin-tests atf @@ -3223,94 +2669,66 @@ ./usr/tests/usr.bin/sdiff/t_sdiff tests-usr.bin-tests atf ./usr/tests/usr.bin/sed tests-usr.bin-tests ./usr/tests/usr.bin/sed/Atffile tests-usr.bin-tests atf +./usr/tests/usr.bin/sed/Kyuafile tests-usr.bin-tests atf,kyua ./usr/tests/usr.bin/sed/d_c2048.in tests-usr.bin-tests atf ./usr/tests/usr.bin/sed/t_sed tests-usr.bin-tests atf ./usr/tests/usr.bin/shmif_dumpbus tests-usr.bin-tests ./usr/tests/usr.bin/shmif_dumpbus/Atffile tests-usr.bin-tests atf +./usr/tests/usr.bin/shmif_dumpbus/Kyuafile tests-usr.bin-tests atf,kyua ./usr/tests/usr.bin/shmif_dumpbus/d_pcap.out.bz2.uue tests-usr.bin-tests atf ./usr/tests/usr.bin/shmif_dumpbus/d_pkthdrs.out.bz2.uue tests-usr.bin-tests atf ./usr/tests/usr.bin/shmif_dumpbus/shmbus.bz2.uue tests-usr.bin-tests atf -./usr/tests/usr.bin/shmif_dumpbus/t_basic tests-usr.bin-tests atf atf +./usr/tests/usr.bin/shmif_dumpbus/t_basic tests-usr.bin-tests atf ./usr/tests/usr.bin/sort tests-usr.bin-tests ./usr/tests/usr.bin/sort/Atffile tests-usr.bin-tests atf +./usr/tests/usr.bin/sort/Kyuafile tests-usr.bin-tests atf,kyua ./usr/tests/usr.bin/sort/d_any_char_dflag_out.txt tests-usr.bin-tests atf ./usr/tests/usr.bin/sort/d_any_char_fflag_out.txt tests-usr.bin-tests atf ./usr/tests/usr.bin/sort/d_any_char_iflag_out.txt tests-usr.bin-tests atf ./usr/tests/usr.bin/sort/d_any_char_in.txt tests-usr.bin-tests atf ./usr/tests/usr.bin/sort/t_sort tests-usr.bin-tests atf ./usr/tests/usr.bin/tmux tests-usr.bin-tests -./usr/tests/usr.bin/tmux/Atffile tests-usr.bin-tests atf atf +./usr/tests/usr.bin/tmux/Atffile tests-usr.bin-tests atf +./usr/tests/usr.bin/tmux/Kyuafile tests-usr.bin-tests atf,kyua ./usr/tests/usr.bin/tmux/t_tmux tests-usr.bin-tests atf ./usr/tests/usr.bin/unifdef tests-usr.bin-tests -./usr/tests/usr.bin/unifdef/Atffile tests-usr.bin-tests atf atf +./usr/tests/usr.bin/unifdef/Atffile tests-usr.bin-tests atf +./usr/tests/usr.bin/unifdef/Kyuafile tests-usr.bin-tests atf,kyua ./usr/tests/usr.bin/unifdef/d_basic.in tests-usr.bin-tests atf ./usr/tests/usr.bin/unifdef/d_basic.out tests-usr.bin-tests atf ./usr/tests/usr.bin/unifdef/t_basic tests-usr.bin-tests atf ./usr/tests/usr.bin/xlint tests-usr.bin-tests -./usr/tests/usr.bin/xlint/Atffile tests-usr.bin-tests atf +./usr/tests/usr.bin/xlint/Kyuafile tests-usr.bin-tests atf,kyua ./usr/tests/usr.bin/xlint/lint1 tests-usr.bin-tests -./usr/tests/usr.bin/xlint/lint1/Atffile tests-usr.bin-tests atf -./usr/tests/usr.bin/xlint/lint1/d_alignof.c tests-usr.bin-tests atf -./usr/tests/usr.bin/xlint/lint1/d_c99_complex_num.c tests-usr.bin-tests atf -./usr/tests/usr.bin/xlint/lint1/d_c99_decls_after_stmt.c tests-usr.bin-tests atf -./usr/tests/usr.bin/xlint/lint1/d_c99_decls_after_stmt2.c tests-usr.bin-tests atf -./usr/tests/usr.bin/xlint/lint1/d_c99_for_loops.c tests-usr.bin-tests atf -./usr/tests/usr.bin/xlint/lint1/d_c99_func.c tests-usr.bin-tests atf -./usr/tests/usr.bin/xlint/lint1/d_c99_recursive_init.c tests-usr.bin-tests atf -./usr/tests/usr.bin/xlint/lint1/d_c99_struct_init.c tests-usr.bin-tests atf -./usr/tests/usr.bin/xlint/lint1/d_c99_union_init1.c tests-usr.bin-tests atf -./usr/tests/usr.bin/xlint/lint1/d_c99_union_init2.c tests-usr.bin-tests atf -./usr/tests/usr.bin/xlint/lint1/d_c99_union_init3.c tests-usr.bin-tests atf -./usr/tests/usr.bin/xlint/lint1/d_c9x_array_init.c tests-usr.bin-tests atf -./usr/tests/usr.bin/xlint/lint1/d_c9x_recursive_init.c tests-usr.bin-tests atf -./usr/tests/usr.bin/xlint/lint1/d_cast_init.c tests-usr.bin-tests atf -./usr/tests/usr.bin/xlint/lint1/d_cast_init2.c tests-usr.bin-tests atf -./usr/tests/usr.bin/xlint/lint1/d_cast_lhs.c tests-usr.bin-tests atf -./usr/tests/usr.bin/xlint/lint1/d_compound_literals1.c tests-usr.bin-tests atf -./usr/tests/usr.bin/xlint/lint1/d_compound_literals2.c tests-usr.bin-tests atf -./usr/tests/usr.bin/xlint/lint1/d_constant_conv1.c tests-usr.bin-tests atf -./usr/tests/usr.bin/xlint/lint1/d_constant_conv2.c tests-usr.bin-tests atf -./usr/tests/usr.bin/xlint/lint1/d_cvt_in_ternary.c tests-usr.bin-tests atf -./usr/tests/usr.bin/xlint/lint1/d_ellipsis_in_switch.c tests-usr.bin-tests atf -./usr/tests/usr.bin/xlint/lint1/d_gcc_compound_statements1.c tests-usr.bin-tests atf -./usr/tests/usr.bin/xlint/lint1/d_gcc_compound_statements2.c tests-usr.bin-tests atf -./usr/tests/usr.bin/xlint/lint1/d_gcc_compound_statements3.c tests-usr.bin-tests atf -./usr/tests/usr.bin/xlint/lint1/d_gcc_func.c tests-usr.bin-tests atf -./usr/tests/usr.bin/xlint/lint1/d_gcc_variable_array_init.c tests-usr.bin-tests atf -./usr/tests/usr.bin/xlint/lint1/d_incorrect_array_size.c tests-usr.bin-tests atf -./usr/tests/usr.bin/xlint/lint1/d_long_double_int.c tests-usr.bin-tests atf -./usr/tests/usr.bin/xlint/lint1/d_nested_structs.c tests-usr.bin-tests atf -./usr/tests/usr.bin/xlint/lint1/d_nolimit_init.c tests-usr.bin-tests atf -./usr/tests/usr.bin/xlint/lint1/d_packed_structs.c tests-usr.bin-tests atf -./usr/tests/usr.bin/xlint/lint1/d_shift_to_narrower_type.c tests-usr.bin-tests atf -./usr/tests/usr.bin/xlint/lint1/d_type_conv1.c tests-usr.bin-tests atf -./usr/tests/usr.bin/xlint/lint1/d_type_conv2.c tests-usr.bin-tests atf -./usr/tests/usr.bin/xlint/lint1/d_type_conv3.c tests-usr.bin-tests atf -./usr/tests/usr.bin/xlint/lint1/d_typename_as_var.c tests-usr.bin-tests atf -./usr/tests/usr.bin/xlint/lint1/d_zero_sized_arrays.c tests-usr.bin-tests atf -./usr/tests/usr.bin/xlint/lint1/t_integration tests-usr.bin-tests atf ./usr/tests/usr.sbin tests-usr.sbin-tests ./usr/tests/usr.sbin/Atffile tests-usr.sbin-tests atf +./usr/tests/usr.sbin/Kyuafile tests-usr.sbin-tests atf,kyua ./usr/tests/usr.sbin/mtree tests-usr.sbin-tests ./usr/tests/usr.sbin/mtree/Atffile tests-usr.sbin-tests atf +./usr/tests/usr.sbin/mtree/Kyuafile tests-usr.sbin-tests atf,kyua ./usr/tests/usr.sbin/mtree/d_convert.in tests-usr.sbin-tests atf ./usr/tests/usr.sbin/mtree/d_convert_C.out tests-usr.sbin-tests atf ./usr/tests/usr.sbin/mtree/d_convert_C_S.out tests-usr.sbin-tests atf ./usr/tests/usr.sbin/mtree/d_convert_D.out tests-usr.sbin-tests atf ./usr/tests/usr.sbin/mtree/d_convert_D_S.out tests-usr.sbin-tests atf -./usr/tests/usr.sbin/mtree/d_create.out tests-usr.sbin-tests atf +./usr/tests/usr.sbin/mtree/d_create.out tests-obsolete obsolete +./usr/tests/usr.sbin/mtree/mtree_d_create.out tests-usr.sbin-tests atf +./usr/tests/usr.sbin/mtree/netbsd6_d_create.out tests-usr.sbin-tests atf ./usr/tests/usr.sbin/mtree/d_merge.in tests-usr.sbin-tests atf ./usr/tests/usr.sbin/mtree/d_merge_C_M.out tests-usr.sbin-tests atf ./usr/tests/usr.sbin/mtree/d_merge_C_M_S.out tests-usr.sbin-tests atf ./usr/tests/usr.sbin/mtree/t_mtree tests-usr.sbin-tests atf ./usr/tests/usr.sbin/tcpdump tests-usr.sbin-tests ./usr/tests/usr.sbin/tcpdump/Atffile tests-usr.sbin-tests atf +./usr/tests/usr.sbin/tcpdump/Kyuafile tests-usr.sbin-tests atf,kyua ./usr/tests/usr.sbin/tcpdump/t_tcpdump tests-usr.sbin-tests atf ./usr/tests/usr.sbin/traceroute tests-usr.sbin-tests ./usr/tests/usr.sbin/traceroute/Atffile tests-usr.sbin-tests atf +./usr/tests/usr.sbin/traceroute/Kyuafile tests-usr.sbin-tests atf,kyua ./usr/tests/usr.sbin/traceroute/t_traceroute tests-usr.sbin-tests atf ./usr/tests/usr.sbin/useradd tests-usr.sbin-tests ./usr/tests/usr.sbin/useradd/Atffile tests-usr.sbin-tests atf +./usr/tests/usr.sbin/useradd/Kyuafile tests-usr.sbin-tests atf,kyua ./usr/tests/usr.sbin/useradd/t_useradd tests-usr.sbin-tests atf ./usr/tests/util tests-obsolete obsolete ./usr/tests/util/Atffile tests-obsolete obsolete diff --git a/distrib/sets/lists/tests/shl.mi b/distrib/sets/lists/tests/shl.mi index 249a27a09..bcf905c79 100644 --- a/distrib/sets/lists/tests/shl.mi +++ b/distrib/sets/lists/tests/shl.mi @@ -1,40 +1,10 @@ -# $NetBSD: shl.mi,v 1.6 2011/06/25 05:45:14 nonaka Exp $ +# $NetBSD: shl.mi,v 1.7 2013/01/16 16:01:08 christos Exp $ # -./usr/libdata/debug/usr/tests/lib/csu/libh_initfini3_dso.so.1.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/tls/libh_tls_dlopen.so.1.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/tls/libh_tls_dynamic.so.1.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/tls/t_tls_dlopen.debug tests-lib-debug debug,atf -./usr/libdata/debug/usr/tests/lib/libc/tls/t_tls_dynamic.debug tests-lib-debug debug,atf ./usr/tests/lib/csu/h_initfini3_dso.so tests-lib-tests atf ./usr/tests/lib/csu/h_initfini3_dso.so.1 tests-lib-tests atf ./usr/tests/lib/csu/libh_initfini3_dso.so tests-obsolete obsolete ./usr/tests/lib/csu/libh_initfini3_dso.so.1 tests-obsolete obsolete -./usr/tests/lib/libc/tls/h_tls_dlopen.so tests-lib-tests atf -./usr/tests/lib/libc/tls/h_tls_dlopen.so.1 tests-lib-tests atf -./usr/tests/lib/libc/tls/libh_tls_dynamic_g.a -unknown- atf,debuglib ./usr/tests/lib/libc/tls/libh_tls_dynamic.so tests-lib-tests atf ./usr/tests/lib/libc/tls/libh_tls_dynamic.so.1 tests-lib-tests atf -./usr/tests/lib/libc/tls/t_tls_dlopen tests-lib-tests atf -./usr/tests/lib/libc/tls/t_tls_dynamic tests-lib-tests atf ./usr/tests/util/id/libfake.so.0 tests-obsolete obsolete ./usr/tests/util/id/libfake.so.0.0 tests-obsolete obsolete -./usr/libdata/debug/usr/tests/libexec/ld.elf_so/h_helper_symver_dso0/libh_helper_symver_dso.so.1.debug tests-libexec-debug debug,atf -./usr/libdata/debug/usr/tests/libexec/ld.elf_so/h_helper_symver_dso1/libh_helper_symver_dso.so.1.debug tests-libexec-debug debug,atf -./usr/libdata/debug/usr/tests/libexec/ld.elf_so/h_helper_symver_dso2/libh_helper_symver_dso.so.1.debug tests-libexec-debug debug,atf -./usr/libdata/debug/usr/tests/libexec/ld.elf_so/libh_helper_dso1.so.1.debug tests-libexec-debug debug,atf -./usr/libdata/debug/usr/tests/libexec/ld.elf_so/libh_helper_dso2.so.1.debug tests-libexec-debug debug,atf -./usr/tests/libexec/ld.elf_so/h_helper_symver_dso0/libh_helper_symver_dso_g.a -unknown- atf,debuglib -./usr/tests/libexec/ld.elf_so/h_helper_symver_dso0/libh_helper_symver_dso.so tests-libexec-tests atf -./usr/tests/libexec/ld.elf_so/h_helper_symver_dso0/libh_helper_symver_dso.so.1 tests-libexec-tests atf -./usr/tests/libexec/ld.elf_so/h_helper_symver_dso1/libh_helper_symver_dso_g.a -unknown- atf,debuglib -./usr/tests/libexec/ld.elf_so/h_helper_symver_dso1/libh_helper_symver_dso.so tests-libexec-tests atf -./usr/tests/libexec/ld.elf_so/h_helper_symver_dso1/libh_helper_symver_dso.so.1 tests-libexec-tests atf -./usr/tests/libexec/ld.elf_so/h_helper_symver_dso2/libh_helper_symver_dso_g.a -unknown- atf,debuglib -./usr/tests/libexec/ld.elf_so/h_helper_symver_dso2/libh_helper_symver_dso.so tests-libexec-tests atf -./usr/tests/libexec/ld.elf_so/h_helper_symver_dso2/libh_helper_symver_dso.so.1 tests-libexec-tests atf -./usr/tests/libexec/ld.elf_so/libh_helper_dso1_g.a -unknown- atf,debuglib -./usr/tests/libexec/ld.elf_so/libh_helper_dso1.so tests-libexec-tests atf -./usr/tests/libexec/ld.elf_so/libh_helper_dso1.so.1 tests-libexec-tests atf -./usr/tests/libexec/ld.elf_so/libh_helper_dso2_g.a -unknown- atf,debuglib -./usr/tests/libexec/ld.elf_so/libh_helper_dso2.so tests-libexec-tests atf -./usr/tests/libexec/ld.elf_so/libh_helper_dso2.so.1 tests-libexec-tests atf diff --git a/distrib/sets/sets.subr b/distrib/sets/sets.subr index 901d4a89f..7ee0228ef 100644 --- a/distrib/sets/sets.subr +++ b/distrib/sets/sets.subr @@ -157,7 +157,7 @@ if [ "${MKPIC}" = "no" ]; then fi # LSC for Minix #nlists="base comp etc games man misc $modset $testset text" -nlists="minix" +nlists="minix $testset" xlists="xbase xcomp xetc xfont xserver" extlists="extbase extcomp extetc" @@ -220,6 +220,7 @@ SUBST="${SUBST};s#@MACHINE@#${MACHINE}#g" # iscsi ${MKISCSI} != no # kerberos ${MKKERBEROS} != no # kmod ${MKKMOD} != no +# kyua ${MKKYUA} != no # ldap ${MKLDAP} != no # lint ${MKLINT} != no # llvm ${MKLLVM} != no diff --git a/etc/Makefile b/etc/Makefile index 695b3a270..0092b03c3 100644 --- a/etc/Makefile +++ b/etc/Makefile @@ -434,6 +434,9 @@ install-etc-files-safe: .PHONY .MAKE check_DESTDIR MAKEDEV .if (${MKATF} != "no") ${MAKEDIRTARGET} ${NETBSDSRCDIR}/external/bsd/atf/etc/atf configinstall .endif +.if (${MKKYUA} != "no") + ${MAKEDIRTARGET} ${NETBSDSRCDIR}/external/bsd/kyua-cli/etc/kyua configinstall +.endif .else # LSC Minix Specific .for owner group mode sdir tdir files in \ ${BINOWN} ${BINGRP} ${BINMODE} ${NETBSDSRCDIR}/etc/usr/ ${DESTDIR}/usr/etc/ daily \ diff --git a/etc/mtree/NetBSD.dist.base b/etc/mtree/NetBSD.dist.base index bf2a102dd..01b9756cc 100644 --- a/etc/mtree/NetBSD.dist.base +++ b/etc/mtree/NetBSD.dist.base @@ -9,6 +9,7 @@ # LSC This file has been adapted for MINIX # +# Standard directories /set type=dir uid=0 gid=0 mode=0755 . ./bin @@ -50,6 +51,7 @@ ./usr/include/ddekit/minix ./usr/include/g++ ./usr/include/i386 +./usr/include/lutok ./usr/include/lzma ./usr/include/minix ./usr/include/net @@ -74,6 +76,7 @@ ./usr/lib/flex ./usr/lib/fonts ./usr/lib/keymaps +./usr/lib/pkgconfig ./usr/libexec ./usr/log ./usr/man diff --git a/etc/mtree/NetBSD.dist.tests b/etc/mtree/NetBSD.dist.tests new file mode 100644 index 000000000..6aeca1e3f --- /dev/null +++ b/etc/mtree/NetBSD.dist.tests @@ -0,0 +1,398 @@ +# $NetBSD: NetBSD.dist.tests,v 1.96 2013/03/21 19:17:51 christos Exp $ + +# LSC Do not take for granted that the last thing done in the previous file +# was standard directories... +/set type=dir uid=0 gid=0 mode=0755 + +./etc/atf +./usr/include/atf-c +./usr/include/atf-c++ +./usr/include/lutok +./usr/libdata +./usr/libdata/debug +./usr/libdata/debug/usr +./usr/libdata/debug/usr/tests +./usr/libdata/debug/usr/tests/atf +./usr/libdata/debug/usr/tests/atf/atf-c +./usr/libdata/debug/usr/tests/atf/atf-c/detail +./usr/libdata/debug/usr/tests/atf/atf-c++ +./usr/libdata/debug/usr/tests/atf/atf-c++/detail +./usr/libdata/debug/usr/tests/atf/atf-report +./usr/libdata/debug/usr/tests/atf/atf-run +./usr/libdata/debug/usr/tests/atf/formats +./usr/libdata/debug/usr/tests/atf/test-programs +./usr/libdata/debug/usr/tests/bin +./usr/libdata/debug/usr/tests/bin/df +./usr/libdata/debug/usr/tests/crypto +./usr/libdata/debug/usr/tests/crypto/libcrypto +./usr/libdata/debug/usr/tests/dev +./usr/libdata/debug/usr/tests/dev/audio +./usr/libdata/debug/usr/tests/dev/cgd +./usr/libdata/debug/usr/tests/dev/md +./usr/libdata/debug/usr/tests/dev/scsipi +./usr/libdata/debug/usr/tests/dev/sysmon +./usr/libdata/debug/usr/tests/fs +./usr/libdata/debug/usr/tests/fs/ffs +./usr/libdata/debug/usr/tests/fs/fifofs +./usr/libdata/debug/usr/tests/fs/hfs +./usr/libdata/debug/usr/tests/fs/kernfs +./usr/libdata/debug/usr/tests/fs/lfs +./usr/libdata/debug/usr/tests/fs/msdosfs +./usr/libdata/debug/usr/tests/fs/nfs +./usr/libdata/debug/usr/tests/fs/nfs/nfsservice +./usr/libdata/debug/usr/tests/fs/nullfs +./usr/libdata/debug/usr/tests/fs/psshfs +./usr/libdata/debug/usr/tests/fs/ptyfs +./usr/libdata/debug/usr/tests/fs/puffs +./usr/libdata/debug/usr/tests/fs/puffs/h_dtfs +./usr/libdata/debug/usr/tests/fs/tmpfs +./usr/libdata/debug/usr/tests/fs/umapfs +./usr/libdata/debug/usr/tests/fs/union +./usr/libdata/debug/usr/tests/fs/vfs +./usr/libdata/debug/usr/tests/include +./usr/libdata/debug/usr/tests/include/machine +./usr/libdata/debug/usr/tests/include/sys +./usr/libdata/debug/usr/tests/ipf +./usr/libdata/debug/usr/tests/kernel +./usr/libdata/debug/usr/tests/kernel/kqueue +./usr/libdata/debug/usr/tests/kernel/kqueue/read +./usr/libdata/debug/usr/tests/kernel/kqueue/write +./usr/libdata/debug/usr/tests/kernel/tty +./usr/libdata/debug/usr/tests/kyua-cli +./usr/libdata/debug/usr/tests/kyua-cli/bootstrap +./usr/libdata/debug/usr/tests/kyua-cli/cli +./usr/libdata/debug/usr/tests/kyua-cli/engine +./usr/libdata/debug/usr/tests/kyua-cli/engine/drivers +./usr/libdata/debug/usr/tests/kyua-cli/examples +./usr/libdata/debug/usr/tests/kyua-cli/integration +./usr/libdata/debug/usr/tests/kyua-cli/integration/helpers +./usr/libdata/debug/usr/tests/kyua-cli/store +./usr/libdata/debug/usr/tests/kyua-cli/utils +./usr/libdata/debug/usr/tests/kyua-cli/utils/cmdline +./usr/libdata/debug/usr/tests/kyua-cli/utils/config +./usr/libdata/debug/usr/tests/kyua-cli/utils/format +./usr/libdata/debug/usr/tests/kyua-cli/utils/fs +./usr/libdata/debug/usr/tests/kyua-cli/utils/logging +./usr/libdata/debug/usr/tests/kyua-cli/utils/process +./usr/libdata/debug/usr/tests/kyua-cli/utils/signals +./usr/libdata/debug/usr/tests/kyua-cli/utils/sqlite +./usr/libdata/debug/usr/tests/kyua-cli/utils/text +./usr/libdata/debug/usr/tests/kyua-testers +./usr/libdata/debug/usr/tests/lib +./usr/libdata/debug/usr/tests/lib/csu +./usr/libdata/debug/usr/tests/lib/libbluetooth +./usr/libdata/debug/usr/tests/lib/libbpfjit +./usr/libdata/debug/usr/tests/lib/libc +./usr/libdata/debug/usr/tests/lib/libc/c063 +./usr/libdata/debug/usr/tests/lib/libc/db +./usr/libdata/debug/usr/tests/lib/libc/gen +./usr/libdata/debug/usr/tests/lib/libc/gen/posix_spawn +./usr/libdata/debug/usr/tests/lib/libc/hash +./usr/libdata/debug/usr/tests/lib/libc/locale +./usr/libdata/debug/usr/tests/lib/libc/inet +./usr/libdata/debug/usr/tests/lib/libc/net +./usr/libdata/debug/usr/tests/lib/libc/net/getaddrinfo +./usr/libdata/debug/usr/tests/lib/libc/regex +./usr/libdata/debug/usr/tests/lib/libc/rpc +./usr/libdata/debug/usr/tests/lib/libc/setjmp +./usr/libdata/debug/usr/tests/lib/libc/ssp +./usr/libdata/debug/usr/tests/lib/libc/stdio +./usr/libdata/debug/usr/tests/lib/libc/stdlib +./usr/libdata/debug/usr/tests/lib/libc/string +./usr/libdata/debug/usr/tests/lib/libc/sys +./usr/libdata/debug/usr/tests/lib/libc/termios +./usr/libdata/debug/usr/tests/lib/libc/tls +./usr/libdata/debug/usr/tests/lib/libc/ttyio +./usr/libdata/debug/usr/tests/lib/libc/time +./usr/libdata/debug/usr/tests/lib/libcrypt +./usr/libdata/debug/usr/tests/lib/libcurses +./usr/libdata/debug/usr/tests/lib/libdes +./usr/libdata/debug/usr/tests/lib/libevent +./usr/libdata/debug/usr/tests/lib/libexecinfo +./usr/libdata/debug/usr/tests/lib/semaphore +./usr/libdata/debug/usr/tests/lib/semaphore/pthread +./usr/libdata/debug/usr/tests/lib/liblutok +./usr/libdata/debug/usr/tests/lib/libm +./usr/libdata/debug/usr/tests/lib/libobjc +./usr/libdata/debug/usr/tests/lib/libposix +./usr/libdata/debug/usr/tests/lib/libposix/bsd +./usr/libdata/debug/usr/tests/lib/libposix/posix1 +./usr/libdata/debug/usr/tests/lib/libposix/posix2 +./usr/libdata/debug/usr/tests/lib/libppath +./usr/libdata/debug/usr/tests/lib/libprop +./usr/libdata/debug/usr/tests/lib/libpthread +./usr/libdata/debug/usr/tests/lib/libpthread/dlopen +./usr/libdata/debug/usr/tests/lib/librt +./usr/libdata/debug/usr/tests/lib/librumpclient +./usr/libdata/debug/usr/tests/lib/librumphijack +./usr/libdata/debug/usr/tests/lib/libskey +./usr/libdata/debug/usr/tests/lib/libsljit +./usr/libdata/debug/usr/tests/lib/libtre +./usr/libdata/debug/usr/tests/lib/libutil +./usr/libdata/debug/usr/tests/libexec +./usr/libdata/debug/usr/tests/libexec/ld.elf_so +./usr/libdata/debug/usr/tests/libexec/ld.elf_so/h_helper_symver_dso0 +./usr/libdata/debug/usr/tests/libexec/ld.elf_so/h_helper_symver_dso1 +./usr/libdata/debug/usr/tests/libexec/ld.elf_so/h_helper_symver_dso2 +./usr/libdata/debug/usr/tests/modules +./usr/libdata/debug/usr/tests/net +./usr/libdata/debug/usr/tests/net/bpf +./usr/libdata/debug/usr/tests/net/bpfilter +./usr/libdata/debug/usr/tests/net/carp +./usr/libdata/debug/usr/tests/net/fdpass +./usr/libdata/debug/usr/tests/net/icmp +./usr/libdata/debug/usr/tests/net/if +./usr/libdata/debug/usr/tests/net/if_loop +./usr/libdata/debug/usr/tests/net/net +./usr/libdata/debug/usr/tests/net/sys +./usr/libdata/debug/usr/tests/rump +./usr/libdata/debug/usr/tests/rump/modautoload +./usr/libdata/debug/usr/tests/rump/rumpkern +./usr/libdata/debug/usr/tests/rump/rumpkern/h_client +./usr/libdata/debug/usr/tests/rump/rumpkern/h_server +./usr/libdata/debug/usr/tests/rump/rumpvfs +./usr/libdata/debug/usr/tests/sbin +./usr/libdata/debug/usr/tests/sbin/resize_ffs +./usr/libdata/debug/usr/tests/usr.bin +./usr/libdata/debug/usr/tests/usr.bin/id +./usr/libdata/debug/usr/tests/usr.bin/netpgpverify +./usr/libdata/debug/usr/tests/usr.sbin +./usr/share/atf +./usr/share/doc/atf +./usr/share/doc/kyua-atf-compat +./usr/share/doc/kyua-cli +./usr/share/doc/kyua-testers +./usr/share/examples +./usr/share/examples/atf +./usr/share/examples/kyua-cli +./usr/share/examples/lutok +./usr/share/kyua-atf-compat +./usr/share/kyua-cli +./usr/share/kyua-cli/misc +./usr/share/kyua-cli/store +./usr/share/xml +./usr/share/xml/atf +./usr/share/xsl +./usr/share/xsl/atf +./usr/tests +./usr/tests/atf +./usr/tests/atf/atf-c +./usr/tests/atf/atf-c/detail +./usr/tests/atf/atf-c++ +./usr/tests/atf/atf-c++/detail +./usr/tests/atf/atf-config +./usr/tests/atf/atf-report +./usr/tests/atf/atf-run +./usr/tests/atf/atf-sh +./usr/tests/atf/test-programs +./usr/tests/bin +./usr/tests/bin/cat +./usr/tests/bin/cp +./usr/tests/bin/dd +./usr/tests/bin/df +./usr/tests/bin/expr +./usr/tests/bin/pax +./usr/tests/bin/ps +./usr/tests/bin/sleep +./usr/tests/bin/sh +./usr/tests/bin/tar +./usr/tests/crypto +./usr/tests/crypto/libcrypto +./usr/tests/dev +./usr/tests/dev/audio +./usr/tests/dev/cgd +./usr/tests/dev/md +./usr/tests/dev/raidframe +./usr/tests/dev/scsipi +./usr/tests/dev/sysmon +./usr/tests/fs +./usr/tests/fs/ffs +./usr/tests/fs/fifofs +./usr/tests/fs/hfs +./usr/tests/fs/kernfs +./usr/tests/fs/lfs +./usr/tests/fs/msdosfs +./usr/tests/fs/nfs +./usr/tests/fs/nfs/nfsservice +./usr/tests/fs/nullfs +./usr/tests/fs/psshfs +./usr/tests/fs/ptyfs +./usr/tests/fs/puffs +./usr/tests/fs/puffs/h_dtfs +./usr/tests/fs/tmpfs +./usr/tests/fs/umapfs +./usr/tests/fs/union +./usr/tests/fs/vfs +./usr/tests/fs/zfs +./usr/tests/games +./usr/tests/include +./usr/tests/include/machine +./usr/tests/include/sys +./usr/tests/ipf +./usr/tests/ipf/expected +./usr/tests/ipf/input +./usr/tests/ipf/regress +./usr/tests/kernel +./usr/tests/kernel/kqueue +./usr/tests/kernel/kqueue/read +./usr/tests/kernel/kqueue/write +./usr/tests/kernel/tty +./usr/tests/kyua-atf-compat +./usr/tests/kyua-cli +./usr/tests/kyua-cli/bootstrap +./usr/tests/kyua-cli/cli +./usr/tests/kyua-cli/engine +./usr/tests/kyua-cli/engine/drivers +./usr/tests/kyua-cli/examples +./usr/tests/kyua-cli/integration +./usr/tests/kyua-cli/integration/helpers +./usr/tests/kyua-cli/store +./usr/tests/kyua-cli/utils +./usr/tests/kyua-cli/utils/cmdline +./usr/tests/kyua-cli/utils/config +./usr/tests/kyua-cli/utils/format +./usr/tests/kyua-cli/utils/fs +./usr/tests/kyua-cli/utils/logging +./usr/tests/kyua-cli/utils/process +./usr/tests/kyua-cli/utils/signals +./usr/tests/kyua-cli/utils/sqlite +./usr/tests/kyua-cli/utils/text +./usr/tests/kyua-testers +./usr/tests/lib +./usr/tests/lib/csu +./usr/tests/lib/libbluetooth +./usr/tests/lib/libc +./usr/tests/lib/libc/c063 +./usr/tests/lib/libc/db +./usr/tests/lib/libc/gen +./usr/tests/lib/libc/gen/posix_spawn +./usr/tests/lib/libc/hash +./usr/tests/lib/libc/hash/data +./usr/tests/lib/libc/locale +./usr/tests/lib/libc/inet +./usr/tests/lib/libc/net +./usr/tests/lib/libc/net/getaddrinfo +./usr/tests/lib/libc/net/getaddrinfo/data +./usr/tests/lib/libc/regex +./usr/tests/lib/libc/regex/data +./usr/tests/lib/libc/rpc +./usr/tests/lib/libc/setjmp +./usr/tests/lib/libc/ssp +./usr/tests/lib/libc/stdio +./usr/tests/lib/libc/stdlib +./usr/tests/lib/libc/string +./usr/tests/lib/libc/sys +./usr/tests/lib/libc/termios +./usr/tests/lib/libc/tls +./usr/tests/lib/libc/ttyio +./usr/tests/lib/libc/time +./usr/tests/lib/libcrypt +./usr/tests/lib/libcurses +./usr/tests/lib/libcurses/check_files +./usr/tests/lib/libcurses/tests +./usr/tests/lib/libdes +./usr/tests/lib/semaphore +./usr/tests/lib/semaphore/pthread +./usr/tests/lib/libbpfjit +./usr/tests/lib/libevent +./usr/tests/lib/libexecinfo +./usr/tests/lib/liblutok +./usr/tests/lib/libm +./usr/tests/lib/libobjc +./usr/tests/lib/libposix +./usr/tests/lib/libposix/bsd +./usr/tests/lib/libposix/posix1 +./usr/tests/lib/libposix/posix2 +./usr/tests/lib/libppath +./usr/tests/lib/libprop +./usr/tests/lib/libpthread +./usr/tests/lib/libpthread/dlopen +./usr/tests/lib/librt +./usr/tests/lib/librumpclient +./usr/tests/lib/librumphijack +./usr/tests/lib/libskey +./usr/tests/lib/libsljit +./usr/tests/lib/libtre +./usr/tests/lib/libtre/data +./usr/tests/lib/libutil +./usr/tests/libexec +./usr/tests/libexec/ld.elf_so +./usr/tests/libexec/ld.elf_so/data +./usr/tests/libexec/ld.elf_so/h_helper_symver_dso0 +./usr/tests/libexec/ld.elf_so/h_helper_symver_dso1 +./usr/tests/libexec/ld.elf_so/h_helper_symver_dso2 +./usr/tests/modules +./usr/tests/net +./usr/tests/net/bpf +./usr/tests/net/bpfilter +./usr/tests/net/carp +./usr/tests/net/fdpass +./usr/tests/net/icmp +./usr/tests/net/if +./usr/tests/net/if_loop +./usr/tests/net/net +./usr/tests/net/npf +./usr/tests/net/route +./usr/tests/net/sys +./usr/tests/rump +./usr/tests/rump/modautoload +./usr/tests/rump/rumpkern +./usr/tests/rump/rumpkern/h_client +./usr/tests/rump/rumpkern/h_server +./usr/tests/rump/rumpnet +./usr/tests/rump/rumpvfs +./usr/tests/sbin +./usr/tests/sbin/fsck_ffs +./usr/tests/sbin/ifconfig +./usr/tests/sbin/newfs +./usr/tests/sbin/newfs_msdos +./usr/tests/sbin/resize_ffs +./usr/tests/sbin/route +./usr/tests/sbin/sysctl +./usr/tests/share +./usr/tests/share/examples +./usr/tests/share/examples/lutok +./usr/tests/share/mk +./usr/tests/sys +./usr/tests/sys/rc +./usr/tests/usr.bin +./usr/tests/usr.bin/awk +./usr/tests/usr.bin/basename +./usr/tests/usr.bin/bzip2 +./usr/tests/usr.bin/cc +./usr/tests/usr.bin/cmp +./usr/tests/usr.bin/config +./usr/tests/usr.bin/config/support +./usr/tests/usr.bin/config/support/arch +./usr/tests/usr.bin/config/support/arch/regress +./usr/tests/usr.bin/config/support/arch/regress/conf +./usr/tests/usr.bin/config/support/conf +./usr/tests/usr.bin/cut +./usr/tests/usr.bin/diff +./usr/tests/usr.bin/dirname +./usr/tests/usr.bin/find +./usr/tests/usr.bin/grep +./usr/tests/usr.bin/gzip +./usr/tests/usr.bin/id +./usr/tests/usr.bin/netpgpverify +./usr/tests/usr.bin/infocmp +./usr/tests/usr.bin/jot +./usr/tests/usr.bin/m4 +./usr/tests/usr.bin/make +./usr/tests/usr.bin/mkdep +./usr/tests/usr.bin/nbperf +./usr/tests/usr.bin/pr +./usr/tests/usr.bin/rump_server +./usr/tests/usr.bin/sdiff +./usr/tests/usr.bin/sed +./usr/tests/usr.bin/shmif_dumpbus +./usr/tests/usr.bin/sort +./usr/tests/usr.bin/tmux +./usr/tests/usr.bin/unifdef +./usr/tests/usr.bin/xlint +./usr/tests/usr.bin/xlint/lint1 +./usr/tests/usr.sbin +./usr/tests/usr.sbin/mtree +./usr/tests/usr.sbin/tcpdump +./usr/tests/usr.sbin/traceroute +./usr/tests/usr.sbin/useradd diff --git a/external/Makefile b/external/Makefile index dca5fb3ec..330dfdcaa 100644 --- a/external/Makefile +++ b/external/Makefile @@ -1,5 +1,6 @@ # $NetBSD: Makefile,v 1.18 2012/06/14 04:14:36 riz Exp $ SUBDIR+= bsd gpl3 historical +SUBDIR+= mit public-domain .include diff --git a/external/bsd/Makefile b/external/bsd/Makefile index 972447b8d..b4d6c4ef1 100644 --- a/external/bsd/Makefile +++ b/external/bsd/Makefile @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.33 2012/10/08 01:45:11 jkoshy Exp $ +# $NetBSD: Makefile,v 1.43 2013/04/28 00:14:14 joerg Exp $ .include @@ -8,7 +8,7 @@ SUBDIR= byacc file flex mdocml \ SUBDIR+= atf .endif .if (${MKCRYPTO} != "no") -SUBDIR+= pkg_install ../../crypto/external/bsd +SUBDIR+= pkg_install .endif # IP Filter .if (${MKIPFILTER} != "no") @@ -17,6 +17,11 @@ SUBDIR+=ipf .if (${MKISCSI} != "no") SUBDIR+= iscsi .endif +.if (defined(__MINIX) && ${MKGCCCMDS} == "yes") +.if (${MKKYUA} != "no") +SUBDIR+= lutok kyua-testers kyua-cli kyua-atf-compat +.endif +.endif # (defined(__MINIX) && ${MKGCCCMDS} == "yes") .if (${MKLDAP} != "no") SUBDIR+= openldap .endif diff --git a/external/bsd/atf/Makefile b/external/bsd/atf/Makefile new file mode 100644 index 000000000..80317e1fa --- /dev/null +++ b/external/bsd/atf/Makefile @@ -0,0 +1,5 @@ +# $NetBSD: Makefile,v 1.3 2010/10/20 09:20:09 jmmv Exp $ + +SUBDIR= etc lib .WAIT libexec share usr.bin tests + +.include diff --git a/external/bsd/atf/Makefile.inc b/external/bsd/atf/Makefile.inc new file mode 100644 index 000000000..0cc453e41 --- /dev/null +++ b/external/bsd/atf/Makefile.inc @@ -0,0 +1,7 @@ +# $NetBSD: Makefile.inc,v 1.1 2013/03/14 07:10:05 jmmv Exp $ + +TOPDIR= ${NETBSDSRCDIR}/external/bsd/atf +SRCDIR= ${TOPDIR}/dist + +ATF_VERSION!= grep 'define VERSION' ${TOPDIR}/lib/libatf-c/bconfig.h \ + | cut -d '"' -f 2 diff --git a/external/bsd/atf/dist/AUTHORS b/external/bsd/atf/dist/AUTHORS new file mode 100644 index 000000000..a46576630 --- /dev/null +++ b/external/bsd/atf/dist/AUTHORS @@ -0,0 +1,30 @@ +Authors and contributors Automated Testing Framework +=========================================================================== + + +* Julio Merino + + Main developer. He started the work on this project when he took part in + the Google Summer of Code 2007 program as a student. + +* Martin Husemann + + Mentored this project during its development as part of the Google Summer + of Code 2007 program. + +* Lukasz Strzygowski + + Participant of the Google Summer of Code 2008 program. Mentored by The + NetBSD Foundation, he worked on the atfify NetBSD-SoC project and, as a + side-effect, he contributed to the ATF source code. He developed the + initial version of the atf-check utility and started the addition of the + ATF_REQUIRE family of macros in the C interface. + +* Paul Goyette + + Implemented timestamping of test programs and test cases so that + atf-report can provide timings for their execution. + + +=========================================================================== +vim: filetype=text:textwidth=75:expandtab:shiftwidth=2:softtabstop=2 diff --git a/external/bsd/atf/dist/Atffile b/external/bsd/atf/dist/Atffile new file mode 100644 index 000000000..9306a6c08 --- /dev/null +++ b/external/bsd/atf/dist/Atffile @@ -0,0 +1,12 @@ +Content-Type: application/X-atf-atffile; version="1" + +prop: test-suite = atf + +tp: atf-c +tp: atf-c++ +tp: atf-sh +tp: test-programs + +tp-glob: atf-config* +tp-glob: atf-report* +tp-glob: atf-run* diff --git a/external/bsd/atf/dist/COPYING b/external/bsd/atf/dist/COPYING new file mode 100644 index 000000000..6552cc35f --- /dev/null +++ b/external/bsd/atf/dist/COPYING @@ -0,0 +1,100 @@ +Redistribution terms Automated Testing Framework +=========================================================================== + + +License +******* + +Copyright (c) 2007, 2008, 2009, 2010, 2011, 2012 The NetBSD Foundation, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + + +Copyright 2011, 2012 Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +* Neither the name of Google Inc. nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + + +Relicensed code +*************** + +The following code snippets have been taken from other projects. Even +though they were not originally licensed under the terms above, the +original authors have agreed to relicense their work so that this project +can be distributed under a single license. This section is put here just to +clarify this fact. + +* configure.ac, Makefile.am: The original versions were derived from the + ones in the XML Catalog Manager project, version 2.2. + + Author: Julio Merino + +* atf-c/ui.c: The format_paragraph and format_text functions were + derived form the ones in the Monotone project, revision + 3a0982da308228d796df35f98d787c5cff2bb5b6. + + Author: Julio Merino + +* atf-c++/detail/io.hpp, atf-c++/detail/io.cpp, atf-c++/detail/io_test.cpp: + These files were derived from the file_handle, systembuf, pipe and pistream + classes and tests found in the Boost.Process library. + + Author: Julio Merino + +* admin/check-style.sh, admin/check-style-common.awk, + admin/check-style-cpp.awk, admin/check-style-shell.awk: These files, + except the first one, were first implemented in the Buildtool project. + They were later adapted to be part of Boost.Process and, during that + process, the shell script was created. + + Author: Julio Merino + + +=========================================================================== +vim: filetype=text:textwidth=75:expandtab:shiftwidth=2:softtabstop=2 diff --git a/external/bsd/atf/dist/Kyuafile b/external/bsd/atf/dist/Kyuafile new file mode 100644 index 000000000..54084cd9b --- /dev/null +++ b/external/bsd/atf/dist/Kyuafile @@ -0,0 +1,18 @@ +syntax("kyuafile", 1) + +test_suite("atf") + +include("atf-c/Kyuafile") +include("atf-c++/Kyuafile") +include("atf-sh/Kyuafile") +include("test-programs/Kyuafile") + +if fs.exists("atf-config/Kyuafile") then + include("atf-config/Kyuafile") +end +if fs.exists("atf-report/Kyuafile") then + include("atf-report/Kyuafile") +end +if fs.exists("atf-run/Kyuafile") then + include("atf-run/Kyuafile") +end diff --git a/external/bsd/atf/dist/NEWS b/external/bsd/atf/dist/NEWS new file mode 100644 index 000000000..5d05a2857 --- /dev/null +++ b/external/bsd/atf/dist/NEWS @@ -0,0 +1,604 @@ +Major changes between releases Automated Testing Framework +=========================================================================== + + +Changes in version 0.17 +*********************** + +Experimental version released on February 14th, 2013. + +* Added the atf_utils_cat_file, atf_utils_compare_file, + atf_utils_copy_file, atf_utils_create_file, atf_utils_file_exists, + atf_utils_fork, atf_utils_grep_file, atf_utils_grep_string, + atf_utils_readline, atf_utils_redirect and atf_utils_wait utility + functions to atf-c-api. Documented the already-public + atf_utils_free_charpp function. + +* Added the cat_file, compare_file, copy_file, create_file, file_exists, + fork, grep_collection, grep_file, grep_string, redirect and wait + functions to the atf::utils namespace of atf-c++-api. These are + wrappers around the same functions added to the atf-c-api library. + +* Added the ATF_CHECK_MATCH, ATF_CHECK_MATCH_MSG, ATF_REQUIRE_MATCH and + ATF_REQUIRE_MATCH_MSG macros to atf-c to simplify the validation of a + string against a regular expression. + +* Miscellaneous fixes for manpage typos and compilation problems with + clang. + +* Added caching of the results of those configure tests that rely on + executing a test program. This should help crossbuild systems by + providing a mechanism to pre-specify what the results should be. + +* PR bin/45690: Make atf-report convert any non-printable characters to + a plain-text representation (matching their corresponding hexadecimal + entities) in XML output files. This is to prevent the output of test + cases from breaking xsltproc later. + + +Changes in version 0.16 +*********************** + +Experimental version released on July 10th, 2012. + +* Added a --enable-tools flag to configure to request the build of the + deprecated ATF tools, whose build is now disabled by default. In order + to continue running tests, you should migrate to Kyua instead of enabling + the build of the deprecated tools. The kyua-atf-compat package provides + transitional compatibility versions of atf-run and atf-report built on + top of Kyua. + +* Tweaked the ATF_TEST_CASE macro of atf-c++ so that the compiler can + detect defined but unused test cases. + +* PR bin/45859: Fixed some XSLT bugs that resulted in the tc-time and + tp-time XML tags leaking into the generated HTML file. Also improved + the CSS file slightly to correct alignment and color issues with the + timestamps column. + +* Optimized atf-c++/macros.hpp so that GNU G++ consumes less memory during + compilation with GNU G++. + +* Flipped the default to building shared libraries for atf-c and atf-c++, + and started versioning them. As a side-effect, this removes the + --enable-unstable-shared flag from configure that appears to not work any + more (under NetBSD). Additionally, some distributions require the use of + shared libraries for proper dependency tracking (e.g. Fedora), so it is + better if we do the right versioning upstream. + +* Project hosting moved from an adhoc solution (custom web site and + Monotone repository) to Google Code (standard wiki and Git). ATF now + lives in a subcomponent of the Kyua project. + + +Changes in version 0.15 +*********************** + +Experimental version released on January 16th, 2012. + +* Respect stdin in atf-check. The previous release silenced stdin for any + processes spawned by atf, not only test programs, which caused breakage + in tests that pipe data through atf-check. + +* Performance improvements to atf-sh. + +* Enabled detection of unused parameters and variables in the code and + fixed all warnings. + +* Changed the behavior of "developer mode". Compiler warnings are now + enabled unconditionally regardless of whether we are in developer mode or + not; developer mode is now only used to perform strict warning checks and + to enable assertions. Additionally, developer mode is now only + automatically enabled when building from the repository, not for formal + releases. + +* Added new Autoconf M4 macros (ATF_ARG_WITH, ATF_CHECK_C and + ATF_CHECK_CXX) to provide a consistent way of defining a --with-arg flag + in configure scripts and detecting the presence of any of the ATF + bindings. Note that ATF_CHECK_SH was already introduced in 0.14, but it + has now been modified to also honor --with-atf if instantiated. + +* Added timing support to atf-run / atf-report. + +* Added support for a 'require.memory' property, to specify the minimum + amount of physical memory needed by the test case to yield valid results. + +* PR bin/45690: Force an ISO-8859-1 encoding in the XML files generated by + atf-report so that invalid data in the output of test cases does not + mangle our report. + + +Changes in version 0.14 +*********************** + +Experimental version released on June 14th, 2011. + +* Added a pkg-config file for atf-sh and an aclocal file to ease the + detection of atf-sh from autoconf scripts. + +* Made the default test case body defined by atf_sh fail. This is to + ensure that test cases are properly defined in test programs and helps + in catching typos in the names of the body functions. + +* PR bin/44882: Made atf-run connect the stdin of test cases to /dev/zero. + This provides more consistent results with "normal" execution (in + particular, when tests are executed detached from a terminal). + +* Made atf-run hardcode TZ=UTC for test cases. It used to undefine TZ, but + that does not take into account that libc determines the current timezone + from a configuration file. + +* All test programs will now print a warning when they are not run through + atf-run(1) stating that this is unsupported and may deliver incorrect + results. + +* Added support for the 'require.files' test-case property. This allows + test cases to specify installed files that must be present for the test + case to run. + + +Changes in version 0.13 +*********************** + +Experimental version released on March 31st, 2011. + +This is the first release after the creation of the Kyua project, a more +modular and reliable replacement for ATF. From now on, ATF will change to +accomodate the transition to this new codebase, but ATF will still continue +to see development in the short/medium term. Check out the project page at +http://code.google.com/p/kyua/ for more details. + +The changes in this release are: + +* Added support to run the tests with the Kyua runtime engine (kyua-cli), a + new package that aims to replace atf-run and atf-report. The ATF tests + can be run with the new system by issuing a 'make installcheck-kyua' from + the top-level directory of the project (assuming the 'kyua' binary is + available during the configuration stage of ATF). + +* atf-run and atf-report are now in maintenance mode (but *not* deprecated + yet!). Kyua already implements a new, much more reliable runtime engine + that provides similar features to these tools. That said, it is not + complete yet so all development efforts should go towards it. + +* If GDB is installed, atf-run dumps the stack trace of crashing test + programs in an attempt to aid debugging. Contributed by Antti Kantee. + +* Reverted default timeout change in previous release and reset its value + to 5 minutes. This was causing several issues, specially when running + the existing NetBSD test suite in qemu. + +* Fixed the 'match' output checker in atf-check to properly validate the + last line of a file even if it does not have a newline. + +* Added the ATF_REQUIRE_IN and ATF_REQUIRE_NOT_IN macros to atf-c++ to + check for the presence (or lack thereof) of an element in a collection. + +* PR bin/44176: Fixed a race condition in atf-run that would crash atf-run + when the cleanup of a test case triggered asynchronous modifications to + its work directory (e.g. killing a daemon process that cleans up a pid + file in the work directory). + +* PR bin/44301: Fixed the sample XSLT file to report bogus test programs + instead of just listing them as having 0 test cases. + + +Changes in version 0.12 +*********************** + +Experimental version released on November 7th, 2010. + +* Added the ATF_REQUIRE_THROW_RE to atf-c++, which is the same as + ATF_REQUIRE_THROW but allows checking for the validity of the exception's + error message by means of a regular expression. + +* Added the ATF_REQUIRE_MATCH to atf-c++, which allows checking for a + regular expression match in a string. + +* Changed the default timeout for test cases from 5 minutes to 30 seconds. + 30 seconds is long enough for virtually all tests to complete, and 5 + minutes is a way too long pause in a test suite where a single test case + stalls. + +* Deprecated the use.fs property. While this seemed like a good idea in + the first place to impose more control on what test cases can do, it + turns out to be bad. First, use.fs=false prevents bogus test cases + from dumping core so after-the-fact debugging is harder. Second, + supporting use.fs adds a lot of unnecessary complexity. atf-run will + now ignore any value provided to use.fs and will allow test cases to + freely access the file system if they wish to. + +* Added the atf_tc_get_config_var_as_{bool,long}{,_wd} functions to the atf-c + library. The 'text' module became private in 0.11 but was being used + externally to simplify the parsing of configuration variables. + +* Made atf-run recognize the 'unprivileged-user' configuration variable + and automatically drop root privileges when a test case sets + require.user=unprivileged. Note that this is, by no means, done for + security purposes; this is just for user convenience; tests should, in + general, not be blindly run as root in the first place. + + +Changes in version 0.11 +*********************** + +Experimental version released on October 20th, 2010. + +* The ATF_CHECK* macros in atf-c++ were renamed to ATF_REQUIRE* to match + their counterparts in atf-c. + +* Clearly separated the modules in atf-c that are supposed to be public + from those that are implementation details. The header files for the + internal modules are not installed any more. + +* Made the atf-check tool private. It is only required by atf-sh and being + public has the danger of causing confusion. Also, making it private + simplifies the public API of atf. + +* Changed atf-sh to enable per-command error checking (set -e) by default. + This catches many cases in which a test case is broken but it is not + reported as such because execution continues. + +* Fixed the XSTL and CSS stylesheets to support expected failures. + + +Changes in version 0.10 +*********************** + +Experimental version released on July 2nd, 2010. + +Miscellaneous features + +* Added expected failures support to test cases and atf-run. These + include, for example, expected clean exits, expected reception of fatal + signals, expected timeouts and expected errors in condition checks. + These statuses can be used to denote test cases that are known to fail + due to a bug in the code they are testing. atf-report reports these + tests separately but they do not count towards the failed test cases + amount. + +* Added the ATF_CHECK_ERRNO and ATF_REQUIRE_ERRNO to the C library to + allow easy checking of call failures that update errno. + +* Added the has.cleanup meta-data property to test caes that specifies + whether the test case has a cleanup routine or not; its value is + automatically set. This property is read by atf-run to know if it has to + run the cleanup routine; skipping this run for every test case + significantly speeds up the run time of test suites. + +* Reversed the order of the ATF_CHECK_THROW macro in the C++ binding to + take the expected exception as the first argument and the statement to + execute as the second argument. + +Changes in atf-check + +* Changed atf-check to support negating the status and output checks by + prefixing them with not- and added support to specify multiple checkers + for stdout and stderr, not only one. + +* Added the match output checker to atf-check to look for regular + expressions in the stdout and stderr of commands. + +* Modified the exit checks in atf-check to support checking for the + reception of signals. + +Code simplifications and cleanups + +* Removed usage messages from test programs to simplify the + implementation of every binding by a significant amount. They just now + refer the user to the appropriate manual page and do not attempt to wrap + lines on terminal boundaries. Test programs are not supposed to be run + by users directly so this minor interface regression is not important. + +* Removed the atf-format internal utility, which is unused after the + change documented above. + +* Removed the atf-cleanup internal utility. It has been unused since the + test case isolation was moved to atf-run in 0.8 + +* Splitted the Makefile.am into smaller files for easier maintenance and + dropped the use of M4. Only affects users building from the repository + sources. + +* Intermixed tests with the source files in the source tree to provide + them more visibility and easier access. The tests directory is gone from + the source tree and tests are now suffixed by _test, not prefixed by t_. + +* Simplifications to the atf-c library: removed the io, tcr and ui + modules as they had become unnecessary after all simplifications + introduced since the 0.8 release. + +* Removed the application/X-atf-tcr format introduced in 0.8 release. + Tests now print a much simplified format that is easy to parse and nicer + to read by end users. As a side effect, the default for test cases is + now to print their results to stdout unless otherwise stated by providing + the -r flag. + +* Removed XML distribution documents and replaced them with plain-text + documents. They provided little value and introduced a lot of complexity + to the build system. + +* Simplified the output of atf-version by not attempting to print a + revision number when building form a distfile. Makes the build system + easier to maintain. + + +Changes in version 0.9 +********************** + +Experimental version released on June 3rd, 2010. + +* Added atf-sh, an interpreter to process test programs written using + the shell API. This is not really a shell interpreter by itself though: + it is just a wrapper around the system shell that eases the loading of + the necessary ATF libraries. + +* Removed atf-compile in favour of atf-sh. + +* Added the use.fs metadata property to test case, which is used to + specify which test cases require file system access. This is to + highlight dependencies on external resources more clearly and to speed up + the execution of test suites by skipping the creation of many unnecessary + work directories. + +* Fixed test programs to get a sane default value for their source + directory. This means that it should not be necessary any more to pass + -s when running test programs that do not live in the current directory. + +* Defining test case headers became optional. This is trivial to achieve + in shell-based tests but a bit ugly in C and C++. In C, use the new + ATF_TC_WITHOUT_HEAD macro to define the test case, and in C++ use + ATF_TEST_CASE_WITHOUT_HEAD. + + +Changes in version 0.8 +********************** + +Experimental version released on May 7th, 2010. + +* Test programs no longer run several test cases in a row. The execution + of a test program now requires a test case name, and that single test + case is executed. To execute several test cases, use the atf-run utility + as usual. + +* Test programs no longer fork a subprocess to isolate the execution of + test cases. They run the test case code in-process, and a crash of the + test case will result in a crash of the test program. This is to ease + debugging of faulty test cases. + +* Test programs no longer isolate their test cases. This means that they + will not create temporary directories nor sanitize the environment any + more. Yes: running a test case that depends on system state by hand will + most likely yield different results depending on where (machine, + directory, user environment, etc.) it is run. Isolation has been moved + to atf-run. + +* Test programs no longer print a cryptic format (application/X-atf-tcs) + on a special file channel. They can now print whatever they want on the + screen. Because test programs can now only run one test case every time, + providing controlled output is not necessary any more. + +* Test programs no longer write their status into a special file + descriptor. Instead, they create a file with the results, which is later + parsed by atf-run. This changes the semantics of the -r flag. + +* atf-run has been adjusted to perform the test case isolation. As a + result, there is now a single canonical place that implements the + isolation of test caes. In previous releases, the three language + bindings (C, C++ and shell) had to be kept in sync with each other (read: + not a nice thing to do at all). As a side effect of this change, writing + bindings for other languages will be much, much easier from now on. + +* atf-run forks test programs on a test case basis, instead of on a test + program basis as it did before. This is to provide the test case + isolation that was before implemented by the test programs themselves. + +* Removed the atf-exec tool. This was used to implement test case + isolation in atf-sh, but it is now unnecessary. + +* It is now optional to define the descr meta-data property. It has been + proven to be mostly useless, because test cases often carry a descriptive + name of their own. + + +Changes in version 0.7 +********************** + +Experimental version released on December 22nd, 2009. + +* Added build-time checks to atf-c and atf-c++. A binding for atf-sh + will come later. + +* Migrated all build-time checks for header files to proper ATF tests. + This demonstrates the use of the new feature described above. + +* Added an internal API for child process management. + +* Converted all plain-text distribution documents to a Docbook canonical + version, and include pre-generated plain text and HTML copies in the + distribution file. + +* Simplified the contents of the Makefile.am by regenerating it from a + canonical Makefile.am.m4 source. As a side-effect, some dependency + specifications were fixed. + +* Migrated all checks from the check target to installcheck, as these + require ATF to be installed. + +* Fixed sign comparison mismatches triggered by the now-enabled + -Wsign-compare. + +* Fixed many memory and object leaks. + + +Changes in version 0.6 +********************** + +Experimental version released on January 18th, 2009. + +* Make atf-exec be able to kill its child process after a certain period + of time; this is controlled through the new -t option. + +* Change atf-sh to use atf-exec's -t option to control the test case's + timeouts, instead of doing it internally. Same behavior as before, but + noticeably faster. + +* atf-exec's -g option and atf-killpg are gone due to the previous + change. + +* Added the atf-check(1) tool, a program that executes a given command + and checks its exit code against a known value and allows the management + of stdout and stderr in multiple ways. This replaces the previous + atf_check function in the atf-sh library and exposes this functionality + to both atf-c and atf-c++. + +* Added the ATF_REQUIRE family of macros to the C interface. These help + in checking for fatal test conditions. The old ATF_CHECK macros now + perform non-fatal checks only. I.e. by using ATF_CHECK, the test case + can now continue its execution and the failures will not be reported + until the end of the whole run. + +* Extended the amount of ATF_CHECK_* C macros with new ones to provide + more features to the developer. These also have their corresponding + counterparts in the ATF_REQUIRE_* family. The new macros (listing the + suffixes only) are: _EQ (replaces _EQUAL), _EQ_MSG, _STREQ and + _STREQ_MSG. + + +Changes in version 0.5 +********************** + +Experimental version released on May 1st, 2008. + +* Clauses 3 and 4 of the BSD license used by the project were dropped. + All the code is now under a 2-clause BSD license compatible with the GNU + General Public License (GPL). + +* Added a C-only binding so that binary test programs do not need to be + tied to C++ at all. This binding is now known as the atf-c library. + +* Renamed the C++ binding to atf-c++ for consistency with the new atf-c. + +* Renamed the POSIX shell binding to atf-sh for consistency with the new + atf-c and atf-c++. + +* Added a -w flag to test programs through which it is possible to + specify the work directory to be used. This was possible in prior + releases by defining the workdir configuration variable (-v workdir=...), + but was a conceptually incorrect mechanism. + +* Test programs now preserve the execution order of test cases when they + are given in the command line. Even those mentioned more than once are + executed multiple times to comply with the user's requests. + + +Changes in version 0.4 +********************** + +Experimental version released on February 4th, 2008. + +* Added two new manual pages, atf-c++-api and atf-sh-api, describing the + C++ and POSIX shell interfaces used to write test programs. + +* Added a pkg-config file, useful to get the flags to build against the + C++ library or to easily detect the presence of ATF. + +* Added a way for test cases to require a specific architecture and/or + machine type through the new 'require.arch' and 'require.machine' + meta-data properties, respectively. + +* Added the 'timeout' property to test cases, useful to set an + upper-bound limit for the test's run time and thus prevent global test + program stalls due to the test case's misbehavior. + +* Added the atf-exec(1) internal utility, used to execute a command + after changing the process group it belongs to. + +* Added the atf-killpg(1) internal utility, used to kill process groups. + +* Multiple portability fixes. Of special interest, full support for + SunOS (Solaris Express Developer Edition 2007/09) using the Sun Studio 12 + C++ compiler. + +* Fixed a serious bug that prevented atf-run(1) from working at all + under Fedora 8 x86_64. Due to the nature of the bug, other platforms + were likely affected too. + + +Changes in version 0.3 +********************** + +Experimental version released on November 11th, 2007. + +* Added XML output support to atf-report. This is accompanied by a DTD + for the format's structure and sample XSLT/CSS files to post-process this + output and convert it to a plain HTML report. + +* Changed atf-run to add system information to the report it generates. + This is currently used by atf-report's XML output only, and is later + printed in the HTML reports in a nice and useful summary table. The user + and system administrator are allowed to tune this feature by means of + hooks. + +* Removed the test cases' 'isolated' property. This was intended to + avoid touching the file system at all when running the related test case, + but this has not been true for a long while: some control files are + unconditionally required for several purposes, and we cannot easily get + rid of them. This way we remove several critical and delicate pieces of + code. + +* Improved atf-report's CSV output format to include information about + test programs too. + +* Fixed the tests that used atf-compile to not require this tool as a + helper. Avoids systems without build-time utilities to skip many tests + that could otherwise be run. (E.g. NetBSD without the comp.tgz set + installed.) + +* Many general cleanups: Fixed many pieces of code marked as ugly and/or + incomplete. + + +Changes in version 0.2 +********************** + +Experimental version released on September 20th, 2007. + +* Test cases now get a known umask on entry. + +* atf-run now detects many unexpected failures caused by test programs and + reports them as bogus tests. atf-report is able to handle these new + errors and nicely reports them to the user. + +* All the data formats read and written by the tools have been + documented and cleaned up. These include those grammars that define how + the different components communicate with each other as well as the + format of files written by the developers and users: the Atffiles and the + configuration files. + +* Added the atf-version tool, a utility that displays information about + the currently installed version of ATF. + +* Test cases can now define an optional cleanup routine to undo their + actions regardless of their exit status. + +* atf-report now summarizes the list of failed (bogus) test programs + when using the ticker output format. + +* Test programs now capture some termination signals and clean up any + temporary files before exiting the program. + +* Multiple bug fixes and improvements all around. + + +Changes in version 0.1 +********************** + +Experimental version released on August 20th, 2007. + +* First public version. This was released coinciding with the end of the + Google Summer of Code 2007 program. + + +=========================================================================== +vim: filetype=text:textwidth=75:expandtab:shiftwidth=2:softtabstop=2 diff --git a/external/bsd/atf/dist/README b/external/bsd/atf/dist/README new file mode 100644 index 000000000..00caa122a --- /dev/null +++ b/external/bsd/atf/dist/README @@ -0,0 +1,40 @@ +Introductory information Automated Testing Framework +=========================================================================== + + +Introduction +************ + +The Automated Testing Framework (ATF) is a collection of libraries and +utilities designed to ease unattended application testing in the hands of +developers and end users of a specific piece of software. + +As regards developers, ATF provides the necessary means to easily create +test suites composed of multiple test programs, which in turn are a +collection of test cases. It also attempts to simplify the debugging of +problems when these test cases detect an error by providing as much +information as possible about the failure. + +As regards users, it simplifies the process of running the test suites and, +in special, encourages end users to run them often: they do not need to +have source trees around nor any other development tools installed to be +able to certify that a given piece of software works on their machine as +advertised. + + +Other documents +*************** + +* AUTHORS: List of authors and contributors for this project. + +* COPYING: License information. + +* INSTALL: Compilation and installation instructions. These is not the + standard document shipped with many packages, so be sure to read it for + things that are specific to ATF's build. + +* NEWS: List of major changes between formal, published releases. + + +=========================================================================== +vim: filetype=text:textwidth=75:expandtab:shiftwidth=2:softtabstop=2 diff --git a/external/bsd/atf/dist/atf-c++.hpp b/external/bsd/atf/dist/atf-c++.hpp new file mode 100644 index 000000000..e915aef20 --- /dev/null +++ b/external/bsd/atf/dist/atf-c++.hpp @@ -0,0 +1,36 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#if !defined(_ATF_CXX_HPP_) +#define _ATF_CXX_HPP_ + +#include +#include + +#endif // !defined(_ATF_CXX_HPP_) diff --git a/external/bsd/atf/dist/atf-c++/Atffile b/external/bsd/atf/dist/atf-c++/Atffile new file mode 100644 index 000000000..ba11f2181 --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/Atffile @@ -0,0 +1,14 @@ +Content-Type: application/X-atf-atffile; version="1" + +prop: test-suite = atf + +tp: detail + +tp: atf_c++_test +tp: build_test +tp: check_test +tp: config_test +tp: macros_test +tp: pkg_config_test +tp: tests_test +tp: utils_test diff --git a/external/bsd/atf/dist/atf-c++/Kyuafile b/external/bsd/atf/dist/atf-c++/Kyuafile new file mode 100644 index 000000000..6df836f27 --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/Kyuafile @@ -0,0 +1,14 @@ +syntax("kyuafile", 1) + +test_suite("atf") + +atf_test_program{name="atf_c++_test"} +atf_test_program{name="build_test"} +atf_test_program{name="check_test"} +atf_test_program{name="config_test"} +atf_test_program{name="macros_test"} +atf_test_program{name="pkg_config_test"} +atf_test_program{name="tests_test"} +atf_test_program{name="utils_test"} + +include("detail/Kyuafile") diff --git a/external/bsd/atf/dist/atf-c++/atf-c++-api.3 b/external/bsd/atf/dist/atf-c++/atf-c++-api.3 new file mode 100644 index 000000000..d0579a9a7 --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/atf-c++-api.3 @@ -0,0 +1,644 @@ +.\" +.\" Automated Testing Framework (atf) +.\" +.\" Copyright (c) 2008 The NetBSD Foundation, Inc. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +.\" CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +.\" IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +.\" GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +.\" IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.Dd November 30, 2012 +.Dt ATF-C++-API 3 +.Os +.Sh NAME +.Nm atf-c++-api , +.Nm ATF_ADD_TEST_CASE , +.Nm ATF_CHECK_ERRNO , +.Nm ATF_FAIL , +.Nm ATF_INIT_TEST_CASES , +.Nm ATF_PASS , +.Nm ATF_REQUIRE , +.Nm ATF_REQUIRE_EQ , +.Nm ATF_REQUIRE_ERRNO , +.Nm ATF_REQUIRE_IN , +.Nm ATF_REQUIRE_MATCH , +.Nm ATF_REQUIRE_NOT_IN , +.Nm ATF_REQUIRE_THROW , +.Nm ATF_REQUIRE_THROW_RE , +.Nm ATF_SKIP , +.Nm ATF_TEST_CASE , +.Nm ATF_TEST_CASE_BODY , +.Nm ATF_TEST_CASE_CLEANUP , +.Nm ATF_TEST_CASE_HEAD , +.Nm ATF_TEST_CASE_NAME , +.Nm ATF_TEST_CASE_USE , +.Nm ATF_TEST_CASE_WITH_CLEANUP , +.Nm ATF_TEST_CASE_WITHOUT_HEAD , +.Nm atf::utils::cat_file , +.Nm atf::utils::compare_file , +.Nm atf::utils::copy_file , +.Nm atf::utils::create_file , +.Nm atf::utils::file_exists , +.Nm atf::utils::fork , +.Nm atf::utils::grep_collection , +.Nm atf::utils::grep_file , +.Nm atf::utils::grep_string , +.Nm atf::utils::redirect , +.Nm atf::utils::wait +.Nd C++ API to write ATF-based test programs +.Sh SYNOPSIS +.In atf-c++.hpp +.Fn ATF_ADD_TEST_CASE "tcs" "name" +.Fn ATF_CHECK_ERRNO "exp_errno" "bool_expression" +.Fn ATF_FAIL "reason" +.Fn ATF_INIT_TEST_CASES "tcs" +.Fn ATF_PASS +.Fn ATF_REQUIRE "expression" +.Fn ATF_REQUIRE_EQ "expression_1" "expression_2" +.Fn ATF_REQUIRE_ERRNO "exp_errno" "bool_expression" +.Fn ATF_REQUIRE_IN "element" "collection" +.Fn ATF_REQUIRE_MATCH "regexp" "string_expression" +.Fn ATF_REQUIRE_NOT_IN "element" "collection" +.Fn ATF_REQUIRE_THROW "expected_exception" "statement" +.Fn ATF_REQUIRE_THROW_RE "expected_exception" "regexp" "statement" +.Fn ATF_SKIP "reason" +.Fn ATF_TEST_CASE "name" +.Fn ATF_TEST_CASE_BODY "name" +.Fn ATF_TEST_CASE_CLEANUP "name" +.Fn ATF_TEST_CASE_HEAD "name" +.Fn ATF_TEST_CASE_NAME "name" +.Fn ATF_TEST_CASE_USE "name" +.Fn ATF_TEST_CASE_WITH_CLEANUP "name" +.Fn ATF_TEST_CASE_WITHOUT_HEAD "name" +.Ft void +.Fo atf::utils::cat_file +.Fa "const std::string& path" +.Fa "const std::string& prefix" +.Fc +.Ft bool +.Fo atf::utils::compare_file +.Fa "const std::string& path" +.Fa "const std::string& contents" +.Fc +.Ft void +.Fo atf::utils::copy_file +.Fa "const std::string& source" +.Fa "const std::string& destination" +.Fc +.Ft void +.Fo atf::utils::create_file +.Fa "const std::string& path" +.Fa "const std::string& contents" +.Fc +.Ft void +.Fo atf::utils::file_exists +.Fa "const std::string& path" +.Fc +.Ft pid_t +.Fo atf::utils::fork +.Fa "void" +.Fc +.Ft bool +.Fo atf::utils::grep_collection +.Fa "const std::string& regexp" +.Fa "const Collection& collection" +.Fc +.Ft bool +.Fo atf::utils::grep_file +.Fa "const std::string& regexp" +.Fa "const std::string& path" +.Fc +.Ft bool +.Fo atf::utils::grep_string +.Fa "const std::string& regexp" +.Fa "const std::string& path" +.Fc +.Ft void +.Fo atf::utils::redirect +.Fa "const int fd" +.Fa "const std::string& path" +.Fc +.Ft void +.Fo atf::utils::wait +.Fa "const pid_t pid" +.Fa "const int expected_exit_status" +.Fa "const std::string& expected_stdout" +.Fa "const std::string& expected_stderr" +.Fc +.Sh DESCRIPTION +ATF provides a mostly-macro-based programming interface to implement test +programs in C or C++. +This interface is backed by a C++ implementation, but this fact is +hidden from the developer as much as possible through the use of +macros to simplify programming. +However, the use of C++ is not hidden everywhere and while you can +implement test cases without knowing anything at all about the object model +underneath the provided calls, you might need some minimum notions of the +language in very specific circumstances. +.Pp +C++-based test programs always follow this template: +.Bd -literal -offset indent +extern "C" { +.Ns ... C-specific includes go here ... +} + +.Ns ... C++-specific includes go here ... + +#include + +ATF_TEST_CASE(tc1); +ATF_TEST_CASE_HEAD(tc1) +{ + ... first test case's header ... +} +ATF_TEST_CASE_BODY(tc1) +{ + ... first test case's body ... +} + +ATF_TEST_CASE_WITH_CLEANUP(tc2); +ATF_TEST_CASE_HEAD(tc2) +{ + ... second test case's header ... +} +ATF_TEST_CASE_BODY(tc2) +{ + ... second test case's body ... +} +ATF_TEST_CASE_CLEANUP(tc2) +{ + ... second test case's cleanup ... +} + +ATF_TEST_CASE(tc3); +ATF_TEST_CASE_BODY(tc3) +{ + ... third test case's body ... +} + +.Ns ... additional test cases ... + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, tc1); + ATF_ADD_TEST_CASE(tcs, tc2); + ATF_ADD_TEST_CASE(tcs, tc3); + ... add additional test cases ... +} +.Ed +.Ss Definition of test cases +Test cases have an identifier and are composed of three different parts: +the header, the body and an optional cleanup routine, all of which are +described in +.Xr atf-test-case 4 . +To define test cases, one can use the +.Fn ATF_TEST_CASE , +.Fn ATF_TEST_CASE_WITH_CLEANUP +or the +.Fn ATF_TEST_CASE_WITHOUT_HEAD +macros, which take a single parameter specifiying the test case's +name. +.Fn ATF_TEST_CASE , +requires to define a head and a body for the test case, +.Fn ATF_TEST_CASE_WITH_CLEANUP +requires to define a head, a body and a cleanup for the test case and +.Fn ATF_TEST_CASE_WITHOUT_HEAD +requires only a body for the test case. +It is important to note that these +.Em do not +set the test case up for execution when the program is run. +In order to do so, a later registration is needed through the +.Fn ATF_ADD_TEST_CASE +macro detailed in +.Sx Program initialization . +.Pp +Later on, one must define the three parts of the body by means of three +functions. +Their headers are given by the +.Fn ATF_TEST_CASE_HEAD , +.Fn ATF_TEST_CASE_BODY +and +.Fn ATF_TEST_CASE_CLEANUP +macros, all of which take the test case's name. +Following each of these, a block of code is expected, surrounded by the +opening and closing brackets. +.Pp +Additionally, the +.Fn ATF_TEST_CASE_NAME +macro can be used to obtain the name of the class corresponding to a +particular test case, as the name is internally manged by the library to +prevent clashes with other user identifiers. +Similarly, the +.Fn ATF_TEST_CASE_USE +macro can be executed on a particular test case to mark it as "used" and +thus prevent compiler warnings regarding unused symbols. +Note that +.Em you should never have to use these macros during regular operation. +.Ss Program initialization +The library provides a way to easily define the test program's +.Fn main +function. +You should never define one on your own, but rely on the +library to do it for you. +This is done by using the +.Fn ATF_INIT_TEST_CASES +macro, which is passed the name of the list that will hold the test cases. +This name can be whatever you want as long as it is a valid variable value. +.Pp +After the macro, you are supposed to provide the body of a function, which +should only use the +.Fn ATF_ADD_TEST_CASE +macro to register the test cases the test program will execute. +The first parameter of this macro matches the name you provided in the +former call. +.Ss Header definitions +The test case's header can define the meta-data by using the +.Fn set_md_var +method, which takes two parameters: the first one specifies the +meta-data variable to be set and the second one specifies its value. +Both of them are strings. +.Ss Configuration variables +The test case has read-only access to the current configuration variables +by means of the +.Ft bool +.Fn has_config_var +and the +.Ft std::string +.Fn get_config_var +methods, which can be called in any of the three parts of a test case. +.Ss Access to the source directory +It is possible to get the path to the test case's source directory from any +of its three components by querying the +.Sq srcdir +configuration variable. +.Ss Requiring programs +Aside from the +.Va require.progs +meta-data variable available in the header only, one can also check for +additional programs in the test case's body by using the +.Fn require_prog +function, which takes the base name or full path of a single binary. +Relative paths are forbidden. +If it is not found, the test case will be automatically skipped. +.Ss Test case finalization +The test case finalizes either when the body reaches its end, at which +point the test is assumed to have +.Em passed , +or at any explicit call to +.Fn ATF_PASS , +.Fn ATF_FAIL +or +.Fn ATF_SKIP . +These three macros terminate the execution of the test case immediately. +The cleanup routine will be processed afterwards in a completely automated +way, regardless of the test case's termination reason. +.Pp +.Fn ATF_PASS +does not take any parameters. +.Fn ATF_FAIL +and +.Fn ATF_SKIP +take a single string that describes why the test case failed or +was skipped, respectively. +It is very important to provide a clear error message in both cases so that +the user can quickly know why the test did not pass. +.Ss Expectations +Everything explained in the previous section changes when the test case +expectations are redefined by the programmer. +.Pp +Each test case has an internal state called +.Sq expect +that describes what the test case expectations are at any point in time. +The value of this property can change during execution by any of: +.Bl -tag -width indent +.It Fn expect_death "reason" +Expects the test case to exit prematurely regardless of the nature of the +exit. +.It Fn expect_exit "exitcode" "reason" +Expects the test case to exit cleanly. +If +.Va exitcode +is not +.Sq -1 , +.Xr atf-run 1 +will validate that the exit code of the test case matches the one provided +in this call. +Otherwise, the exact value will be ignored. +.It Fn expect_fail "reason" +Any failure (be it fatal or non-fatal) raised in this mode is recorded. +However, such failures do not report the test case as failed; instead, the +test case finalizes cleanly and is reported as +.Sq expected failure ; +this report includes the provided +.Fa reason +as part of it. +If no error is raised while running in this mode, then the test case is +reported as +.Sq failed . +.Pp +This mode is useful to reproduce actual known bugs in tests. +Whenever the developer fixes the bug later on, the test case will start +reporting a failure, signaling the developer that the test case must be +adjusted to the new conditions. +In this situation, it is useful, for example, to set +.Fa reason +as the bug number for tracking purposes. +.It Fn expect_pass +This is the normal mode of execution. +In this mode, any failure is reported as such to the user and the test case +is marked as +.Sq failed . +.It Fn expect_race "reason" +Any failure or timeout during the execution of the test case will be +considered as if a race condition has been triggered and reported as such. +If no problems arise, the test will continue execution as usual. +.It Fn expect_signal "signo" "reason" +Expects the test case to terminate due to the reception of a signal. +If +.Va signo +is not +.Sq -1 , +.Xr atf-run 1 +will validate that the signal that terminated the test case matches the one +provided in this call. +Otherwise, the exact value will be ignored. +.It Fn expect_timeout "reason" +Expects the test case to execute for longer than its timeout. +.El +.Ss Helper macros for common checks +The library provides several macros that are very handy in multiple +situations. +These basically check some condition after executing a given statement or +processing a given expression and, if the condition is not met, they +automatically call +.Fn ATF_FAIL +with an appropriate error message. +.Pp +.Fn ATF_REQUIRE +takes an expression and raises a failure if it evaluates to false. +.Pp +.Fn ATF_REQUIRE_EQ +takes two expressions and raises a failure if the two do not evaluate to +the same exact value. +.Pp +.Fn ATF_REQUIRE_IN +takes an element and a collection and validates that the element is present in +the collection. +.Pp +.Fn ATF_REQUIRE_MATCH +takes a regular expression and a string and raises a failure if the regular +expression does not match the string. +.Pp +.Fn ATF_REQUIRE_NOT_IN +takes an element and a collection and validates that the element is not present +in the collection. +.Pp +.Fn ATF_REQUIRE_THROW +takes the name of an exception and a statement and raises a failure if +the statement does not throw the specified exception. +.Fn ATF_REQUIRE_THROW_RE +takes the name of an exception, a regular expresion and a statement and raises a +failure if the statement does not throw the specified exception and if the +message of the exception does not match the regular expression. +.Pp +.Fn ATF_CHECK_ERRNO +and +.Fn ATF_REQUIRE_ERRNO +take, first, the error code that the check is expecting to find in the +.Va errno +variable and, second, a boolean expression that, if evaluates to true, +means that a call failed and +.Va errno +has to be checked against the first value. +.Ss Utility functions +The following functions are provided as part of the +.Nm +API to simplify the creation of a variety of tests. +In particular, these are useful to write tests for command-line interfaces. +.Pp +.Ft void +.Fo atf::utils::cat_file +.Fa "const std::string& path" +.Fa "const std::string& prefix" +.Fc +.Bd -offset indent +Prints the contents of +.Fa path +to the standard output, prefixing every line with the string in +.Fa prefix . +.Ed +.Pp +.Ft bool +.Fo atf::utils::compare_file +.Fa "const std::string& path" +.Fa "const std::string& contents" +.Fc +.Bd -offset indent +Returns true if the given +.Fa path +matches exactly the expected inlined +.Fa contents . +.Ed +.Pp +.Ft void +.Fo atf::utils::copy_file +.Fa "const std::string& source" +.Fa "const std::string& destination" +.Fc +.Bd -offset indent +Copies the file +.Fa source +to +.Fa destination . +The permissions of the file are preserved during the code. +.Ed +.Pp +.Ft void +.Fo atf::utils::create_file +.Fa "const std::string& path" +.Fa "const std::string& contents" +.Fc +.Bd -offset indent +Creates +.Fa file +with the text given in +.Fa contents . +.Ed +.Pp +.Ft void +.Fo atf::utils::file_exists +.Fa "const std::string& path" +.Fc +.Bd -offset indent +Checks if +.Fa path +exists. +.Ed +.Pp +.Ft pid_t +.Fo atf::utils::fork +.Fa "void" +.Fc +.Bd -offset indent +Forks a process and redirects the standard output and standard error of the +child to files for later validation with +.Fn atf::utils::wait . +Fails the test case if the fork fails, so this does not return an error. +.Ed +.Pp +.Ft bool +.Fo atf::utils::grep_collection +.Fa "const std::string& regexp" +.Fa "const Collection& collection" +.Fc +.Bd -offset indent +Searches for the regular expression +.Fa regexp +in any of the strings contained in the +.Fa collection . +This is a template that accepts any one-dimensional container of strings. +.Ed +.Pp +.Ft bool +.Fo atf::utils::grep_file +.Fa "const std::string& regexp" +.Fa "const std::string& path" +.Fc +.Bd -offset indent +Searches for the regular expression +.Fa regexp +in the file +.Fa path . +The variable arguments are used to construct the regular expression. +.Ed +.Pp +.Ft bool +.Fo atf::utils::grep_string +.Fa "const std::string& regexp" +.Fa "const std::string& str" +.Fc +.Bd -offset indent +Searches for the regular expression +.Fa regexp +in the string +.Fa str . +.Ed +.Ft void +.Fo atf::utils::redirect +.Fa "const int fd" +.Fa "const std::string& path" +.Fc +.Bd -offset indent +Redirects the given file descriptor +.Fa fd +to the file +.Fa path . +This function exits the process in case of an error and does not properly mark +the test case as failed. +As a result, it should only be used in subprocesses of the test case; specially +those spawned by +.Fn atf::utils::fork . +.Ed +.Pp +.Ft void +.Fo atf::utils::wait +.Fa "const pid_t pid" +.Fa "const int expected_exit_status" +.Fa "const std::string& expected_stdout" +.Fa "const std::string& expected_stderr" +.Fc +.Bd -offset indent +Waits and validates the result of a subprocess spawned with +.Fn atf::utils::wait . +The validation involves checking that the subprocess exited cleanly and returned +the code specified in +.Fa expected_exit_status +and that its standard output and standard error match the strings given in +.Fa expected_stdout +and +.Fa expected_stderr . +.Pp +If any of the +.Fa expected_stdout +or +.Fa expected_stderr +strings are prefixed with +.Sq save: , +then they specify the name of the file into which to store the stdout or stderr +of the subprocess, and no comparison is performed. +.Ed +.Sh EXAMPLES +The following shows a complete test program with a single test case that +validates the addition operator: +.Bd -literal -offset indent +#include + +ATF_TEST_CASE(addition); +ATF_TEST_CASE_HEAD(addition) +{ + set_md_var("descr", "Sample tests for the addition operator"); +} +ATF_TEST_CASE_BODY(addition) +{ + ATF_REQUIRE_EQ(0 + 0, 0); + ATF_REQUIRE_EQ(0 + 1, 1); + ATF_REQUIRE_EQ(1 + 0, 1); + + ATF_REQUIRE_EQ(1 + 1, 2); + + ATF_REQUIRE_EQ(100 + 200, 300); +} + +ATF_TEST_CASE(open_failure); +ATF_TEST_CASE_HEAD(open_failure) +{ + set_md_var("descr", "Sample tests for the open function"); +} +ATF_TEST_CASE_BODY(open_failure) +{ + ATF_REQUIRE_ERRNO(ENOENT, open("non-existent", O_RDONLY) == -1); +} + +ATF_TEST_CASE(known_bug); +ATF_TEST_CASE_HEAD(known_bug) +{ + set_md_var("descr", "Reproduces a known bug"); +} +ATF_TEST_CASE_BODY(known_bug) +{ + expect_fail("See bug number foo/bar"); + ATF_REQUIRE_EQ(3, 1 + 1); + expect_pass(); + ATF_REQUIRE_EQ(3, 1 + 2); +} + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, addition); + ATF_ADD_TEST_CASE(tcs, open_failure); + ATF_ADD_TEST_CASE(tcs, known_bug); +} +.Ed +.Sh SEE ALSO +.Xr atf-test-program 1 , +.Xr atf-test-case 4 , +.Xr atf 7 diff --git a/external/bsd/atf/dist/atf-c++/atf-c++.pc.in b/external/bsd/atf/dist/atf-c++/atf-c++.pc.in new file mode 100644 index 000000000..f366bb016 --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/atf-c++.pc.in @@ -0,0 +1,11 @@ +# ATF pkg-config file + +cxx=__CXX__ +includedir=__INCLUDEDIR__ +libdir=__LIBDIR__ + +Name: atf-c++ +Description: Automated Testing Framework (C++ binding) +Version: __ATF_VERSION__ +Cflags: -I${includedir} +Libs: -L${libdir} -latf-c++ -latf-c diff --git a/external/bsd/atf/dist/atf-c++/atf_c++_test.cpp b/external/bsd/atf/dist/atf-c++/atf_c++_test.cpp new file mode 100644 index 000000000..c09e4b101 --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/atf_c++_test.cpp @@ -0,0 +1,48 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2009 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#include "macros.hpp" + +#include "detail/test_helpers.hpp" + +// ------------------------------------------------------------------------ +// Tests cases for the header file. +// ------------------------------------------------------------------------ + +HEADER_TC(include, "atf-c++.hpp"); + +// ------------------------------------------------------------------------ +// Main. +// ------------------------------------------------------------------------ + +ATF_INIT_TEST_CASES(tcs) +{ + // Add the test cases for the header file. + ATF_ADD_TEST_CASE(tcs, include); +} diff --git a/external/bsd/atf/dist/atf-c++/build.cpp b/external/bsd/atf/dist/atf-c++/build.cpp new file mode 100644 index 000000000..9ce134c8e --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/build.cpp @@ -0,0 +1,119 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2009 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +extern "C" { +#include "atf-c/build.h" +#include "atf-c/error.h" +#include "atf-c/utils.h" +} + +#include "build.hpp" + +#include "detail/exceptions.hpp" +#include "detail/process.hpp" + +namespace impl = atf::build; +#define IMPL_NAME "atf::build" + +// ------------------------------------------------------------------------ +// Auxiliary functions. +// ------------------------------------------------------------------------ + +inline +atf::process::argv_array +cargv_to_argv(const atf_list_t* l) +{ + std::vector< const char* > aux; + + atf_list_citer_t iter; + atf_list_for_each_c(iter, l) + aux.push_back(static_cast< const char* >(atf_list_citer_data(iter))); + + return atf::process::argv_array(aux); +} + +inline +atf::process::argv_array +cargv_to_argv_and_free(char** l) +{ + try { + atf::process::argv_array argv((const char* const*)l); + atf_utils_free_charpp(l); + return argv; + } catch (...) { + atf_utils_free_charpp(l); + throw; + } +} + +// ------------------------------------------------------------------------ +// Free functions. +// ------------------------------------------------------------------------ + +atf::process::argv_array +impl::c_o(const std::string& sfile, const std::string& ofile, + const atf::process::argv_array& optargs) +{ + char** l; + + atf_error_t err = atf_build_c_o(sfile.c_str(), ofile.c_str(), + optargs.exec_argv(), &l); + if (atf_is_error(err)) + throw_atf_error(err); + + return cargv_to_argv_and_free(l); +} + +atf::process::argv_array +impl::cpp(const std::string& sfile, const std::string& ofile, + const atf::process::argv_array& optargs) +{ + char** l; + + atf_error_t err = atf_build_cpp(sfile.c_str(), ofile.c_str(), + optargs.exec_argv(), &l); + if (atf_is_error(err)) + throw_atf_error(err); + + return cargv_to_argv_and_free(l); +} + +atf::process::argv_array +impl::cxx_o(const std::string& sfile, const std::string& ofile, + const atf::process::argv_array& optargs) +{ + char** l; + + atf_error_t err = atf_build_cxx_o(sfile.c_str(), ofile.c_str(), + optargs.exec_argv(), &l); + if (atf_is_error(err)) + throw_atf_error(err); + + return cargv_to_argv_and_free(l); +} diff --git a/external/bsd/atf/dist/atf-c++/build.hpp b/external/bsd/atf/dist/atf-c++/build.hpp new file mode 100644 index 000000000..5a291b4cc --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/build.hpp @@ -0,0 +1,57 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2009 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#if !defined(_ATF_CXX_BUILD_HPP_) +#define _ATF_CXX_BUILD_HPP_ + +#include + +namespace atf { + +namespace process { +class argv_array; +} // namespace process + +namespace build { + +// ------------------------------------------------------------------------ +// Free functions. +// ------------------------------------------------------------------------ + +process::argv_array c_o(const std::string&, const std::string&, + const process::argv_array&); +process::argv_array cpp(const std::string&, const std::string&, + const process::argv_array&); +process::argv_array cxx_o(const std::string&, const std::string&, + const process::argv_array&); + +} // namespace build +} // namespace atf + +#endif // !defined(_ATF_CXX_BUILD_HPP_) diff --git a/external/bsd/atf/dist/atf-c++/build_test.cpp b/external/bsd/atf/dist/atf-c++/build_test.cpp new file mode 100644 index 000000000..685290539 --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/build_test.cpp @@ -0,0 +1,247 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2009 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#include +#include + +#include "../atf-c/h_build.h" + +#include "build.hpp" +#include "config.hpp" +#include "macros.hpp" + +#include "detail/env.hpp" +#include "detail/process.hpp" +#include "detail/test_helpers.hpp" + +// ------------------------------------------------------------------------ +// Auxiliary functions. +// ------------------------------------------------------------------------ + +namespace atf { + namespace config { + void __reinit(void); + } +} + +template< class C > +void +print_col(const char* prefix, const C& c) +{ + std::cout << prefix << ":"; + for (typename C::const_iterator iter = c.begin(); iter != c.end(); + iter++) + std::cout << " '" << *iter << "'"; + std::cout << "\n"; +} + +static +void +print_array(const char* prefix, const char* const* a) +{ + std::cout << prefix << ":"; + for (; *a != NULL; a++) + std::cout << " '" << *a << "'"; + std::cout << "\n"; +} + +static +void +verbose_set_env(const char *var, const char *val) +{ + std::cout << "Setting " << var << " to '" << val << "'\n"; + atf::env::set(var, val); +} + +static +bool +equal_argvs(const atf::process::argv_array& aa, const char* const* array) +{ + bool equal = true; + + atf::process::argv_array::size_type i = 0; + while (equal && (i < aa.size() && array[i] != NULL)) { + if (std::strcmp(aa[i], array[i]) != 0) + equal = false; + else + i++; + } + + if (equal && (i < aa.size() || array[i] != NULL)) + equal = false; + + return equal; +} + +static +void +check_equal_argvs(const atf::process::argv_array& aa, const char* const* array) +{ + print_array("Expected arguments", array); + print_col("Arguments returned", aa); + + if (!equal_argvs(aa, array)) + ATF_FAIL("The constructed argv differs from the expected values"); +} + +// ------------------------------------------------------------------------ +// Internal test cases. +// ------------------------------------------------------------------------ + +ATF_TEST_CASE(equal_argvs); +ATF_TEST_CASE_HEAD(equal_argvs) +{ + set_md_var("descr", "Tests the test case internal equal_argvs function"); +} +ATF_TEST_CASE_BODY(equal_argvs) +{ + { + const char* const array[] = { NULL }; + const char* const argv[] = { NULL }; + + ATF_REQUIRE(equal_argvs(atf::process::argv_array(argv), array)); + } + + { + const char* const array[] = { NULL }; + const char* const argv[] = { "foo", NULL }; + + ATF_REQUIRE(!equal_argvs(atf::process::argv_array(argv), array)); + } + + { + const char* const array[] = { "foo", NULL }; + const char* const argv[] = { NULL }; + + ATF_REQUIRE(!equal_argvs(atf::process::argv_array(argv), array)); + } + + { + const char* const array[] = { "foo", NULL }; + const char* const argv[] = { "foo", NULL }; + + ATF_REQUIRE(equal_argvs(atf::process::argv_array(argv), array)); + } +} + +// ------------------------------------------------------------------------ +// Test cases for the free functions. +// ------------------------------------------------------------------------ + +ATF_TEST_CASE(c_o); +ATF_TEST_CASE_HEAD(c_o) +{ + set_md_var("descr", "Tests the c_o function"); +} +ATF_TEST_CASE_BODY(c_o) +{ + for (struct c_o_test* test = c_o_tests; test->expargv[0] != NULL; + test++) { + std::cout << "> Test: " << test->msg << "\n"; + + verbose_set_env("ATF_BUILD_CC", test->cc); + verbose_set_env("ATF_BUILD_CFLAGS", test->cflags); + verbose_set_env("ATF_BUILD_CPPFLAGS", test->cppflags); + atf::config::__reinit(); + + atf::process::argv_array argv = + atf::build::c_o(test->sfile, test->ofile, + atf::process::argv_array(test->optargs)); + check_equal_argvs(argv, test->expargv); + } +} + +ATF_TEST_CASE(cpp); +ATF_TEST_CASE_HEAD(cpp) +{ + set_md_var("descr", "Tests the cpp function"); +} +ATF_TEST_CASE_BODY(cpp) +{ + for (struct cpp_test* test = cpp_tests; test->expargv[0] != NULL; + test++) { + std::cout << "> Test: " << test->msg << "\n"; + + verbose_set_env("ATF_BUILD_CPP", test->cpp); + verbose_set_env("ATF_BUILD_CPPFLAGS", test->cppflags); + atf::config::__reinit(); + + atf::process::argv_array argv = + atf::build::cpp(test->sfile, test->ofile, + atf::process::argv_array(test->optargs)); + check_equal_argvs(argv, test->expargv); + } +} + +ATF_TEST_CASE(cxx_o); +ATF_TEST_CASE_HEAD(cxx_o) +{ + set_md_var("descr", "Tests the cxx_o function"); +} +ATF_TEST_CASE_BODY(cxx_o) +{ + for (struct cxx_o_test* test = cxx_o_tests; test->expargv[0] != NULL; + test++) { + std::cout << "> Test: " << test->msg << "\n"; + + verbose_set_env("ATF_BUILD_CXX", test->cxx); + verbose_set_env("ATF_BUILD_CXXFLAGS", test->cxxflags); + verbose_set_env("ATF_BUILD_CPPFLAGS", test->cppflags); + atf::config::__reinit(); + + atf::process::argv_array argv = + atf::build::cxx_o(test->sfile, test->ofile, + atf::process::argv_array(test->optargs)); + check_equal_argvs(argv, test->expargv); + } +} + +// ------------------------------------------------------------------------ +// Tests cases for the header file. +// ------------------------------------------------------------------------ + +HEADER_TC(include, "atf-c++/build.hpp"); + +// ------------------------------------------------------------------------ +// Main. +// ------------------------------------------------------------------------ + +ATF_INIT_TEST_CASES(tcs) +{ + // Add the internal test cases. + ATF_ADD_TEST_CASE(tcs, equal_argvs); + + // Add the test cases for the free functions. + ATF_ADD_TEST_CASE(tcs, c_o); + ATF_ADD_TEST_CASE(tcs, cpp); + ATF_ADD_TEST_CASE(tcs, cxx_o); + + // Add the test cases for the header file. + ATF_ADD_TEST_CASE(tcs, include); +} diff --git a/external/bsd/atf/dist/atf-c++/check.cpp b/external/bsd/atf/dist/atf-c++/check.cpp new file mode 100644 index 000000000..b099b07a7 --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/check.cpp @@ -0,0 +1,158 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#include + +extern "C" { +#include "atf-c/build.h" +#include "atf-c/error.h" +} + +#include "check.hpp" + +#include "detail/exceptions.hpp" +#include "detail/process.hpp" +#include "detail/sanity.hpp" + +namespace impl = atf::check; +#define IMPL_NAME "atf::check" + +// ------------------------------------------------------------------------ +// The "check_result" class. +// ------------------------------------------------------------------------ + +impl::check_result::check_result(const atf_check_result_t* result) +{ + std::memcpy(&m_result, result, sizeof(m_result)); +} + +impl::check_result::~check_result(void) +{ + atf_check_result_fini(&m_result); +} + +bool +impl::check_result::exited(void) + const +{ + return atf_check_result_exited(&m_result); +} + +int +impl::check_result::exitcode(void) + const +{ + PRE(exited()); + return atf_check_result_exitcode(&m_result); +} + +bool +impl::check_result::signaled(void) + const +{ + return atf_check_result_signaled(&m_result); +} + +int +impl::check_result::termsig(void) + const +{ + PRE(signaled()); + return atf_check_result_termsig(&m_result); +} + +const std::string +impl::check_result::stdout_path(void) const +{ + return atf_check_result_stdout(&m_result); +} + +const std::string +impl::check_result::stderr_path(void) const +{ + return atf_check_result_stderr(&m_result); +} + +// ------------------------------------------------------------------------ +// Free functions. +// ------------------------------------------------------------------------ + +bool +impl::build_c_o(const std::string& sfile, const std::string& ofile, + const atf::process::argv_array& optargs) +{ + bool success; + + atf_error_t err = atf_check_build_c_o(sfile.c_str(), ofile.c_str(), + optargs.exec_argv(), &success); + if (atf_is_error(err)) + throw_atf_error(err); + + return success; +} + +bool +impl::build_cpp(const std::string& sfile, const std::string& ofile, + const atf::process::argv_array& optargs) +{ + bool success; + + atf_error_t err = atf_check_build_cpp(sfile.c_str(), ofile.c_str(), + optargs.exec_argv(), &success); + if (atf_is_error(err)) + throw_atf_error(err); + + return success; +} + +bool +impl::build_cxx_o(const std::string& sfile, const std::string& ofile, + const atf::process::argv_array& optargs) +{ + bool success; + + atf_error_t err = atf_check_build_cxx_o(sfile.c_str(), ofile.c_str(), + optargs.exec_argv(), &success); + if (atf_is_error(err)) + throw_atf_error(err); + + return success; +} + +std::auto_ptr< impl::check_result > +impl::exec(const atf::process::argv_array& argva) +{ + atf_check_result_t result; + + atf_error_t err = atf_check_exec_array(argva.exec_argv(), &result); + if (atf_is_error(err)) + throw_atf_error(err); + + return std::auto_ptr< impl::check_result >(new impl::check_result(&result)); +} diff --git a/external/bsd/atf/dist/atf-c++/check.hpp b/external/bsd/atf/dist/atf-c++/check.hpp new file mode 100644 index 000000000..0623529c7 --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/check.hpp @@ -0,0 +1,133 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#if !defined(_ATF_CXX_CHECK_HPP_) +#define _ATF_CXX_CHECK_HPP_ + +extern "C" { +#include +} + +#include +#include +#include +#include + +#include + +namespace atf { + +namespace process { +class argv_array; +} // namespace process + +namespace check { + +// ------------------------------------------------------------------------ +// The "check_result" class. +// ------------------------------------------------------------------------ + +//! +//! \brief A class that contains results of executed command. +//! +//! The check_result class holds information about results +//! of executing arbitrary command and manages files containing +//! its output. +//! +class check_result : noncopyable { + //! + //! \brief Internal representation of a result. + //! + atf_check_result_t m_result; + + //! + //! \brief Constructs a results object and grabs ownership of the + //! parameter passed in. + //! + check_result(const atf_check_result_t* result); + + friend check_result test_constructor(const char* const*); + friend std::auto_ptr< check_result > exec(const atf::process::argv_array&); + +public: + //! + //! \brief Destroys object and removes all managed files. + //! + ~check_result(void); + + //! + //! \brief Returns whether the command exited correctly or not. + //! + bool exited(void) const; + + //! + //! \brief Returns command's exit status. + //! + int exitcode(void) const; + + //! + //! \brief Returns whether the command received a signal or not. + //! + bool signaled(void) const; + + //! + //! \brief Returns the signal that terminated the command. + //! + int termsig(void) const; + + //! + //! \brief Returns the path to file contaning command's stdout. + //! + const std::string stdout_path(void) const; + + //! + //! \brief Returns the path to file contaning command's stderr. + //! + const std::string stderr_path(void) const; +}; + +// ------------------------------------------------------------------------ +// Free functions. +// ------------------------------------------------------------------------ + +bool build_c_o(const std::string&, const std::string&, + const atf::process::argv_array&); +bool build_cpp(const std::string&, const std::string&, + const atf::process::argv_array&); +bool build_cxx_o(const std::string&, const std::string&, + const atf::process::argv_array&); +std::auto_ptr< check_result > exec(const atf::process::argv_array&); + +// Useful for testing only. +check_result test_constructor(void); + +} // namespace check +} // namespace atf + +#endif // !defined(_ATF_CXX_CHECK_HPP_) diff --git a/external/bsd/atf/dist/atf-c++/check_test.cpp b/external/bsd/atf/dist/atf-c++/check_test.cpp new file mode 100644 index 000000000..8e5983fdc --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/check_test.cpp @@ -0,0 +1,408 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +extern "C" { +#include +#include +#include +} + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "check.hpp" +#include "config.hpp" +#include "utils.hpp" + +#include "detail/fs.hpp" +#include "detail/process.hpp" +#include "detail/test_helpers.hpp" +#include "detail/text.hpp" + +// ------------------------------------------------------------------------ +// Auxiliary functions. +// ------------------------------------------------------------------------ + +static +std::auto_ptr< atf::check::check_result > +do_exec(const atf::tests::tc* tc, const char* helper_name) +{ + std::vector< std::string > argv; + argv.push_back(get_process_helpers_path(*tc).str()); + argv.push_back(helper_name); + std::cout << "Executing " << argv[0] << " " << argv[1] << "\n"; + + atf::process::argv_array argva(argv); + return atf::check::exec(argva); +} + +static +std::auto_ptr< atf::check::check_result > +do_exec(const atf::tests::tc* tc, const char* helper_name, const char *carg2) +{ + std::vector< std::string > argv; + argv.push_back(get_process_helpers_path(*tc).str()); + argv.push_back(helper_name); + argv.push_back(carg2); + std::cout << "Executing " << argv[0] << " " << argv[1] << " " + << argv[2] << "\n"; + + atf::process::argv_array argva(argv); + return atf::check::exec(argva); +} + +// ------------------------------------------------------------------------ +// Helper test cases for the free functions. +// ------------------------------------------------------------------------ + +ATF_TEST_CASE(h_build_c_o_ok); +ATF_TEST_CASE_HEAD(h_build_c_o_ok) +{ + set_md_var("descr", "Helper test case for build_c_o"); +} +ATF_TEST_CASE_BODY(h_build_c_o_ok) +{ + std::ofstream sfile("test.c"); + sfile << "#include \n"; + sfile.close(); + + ATF_REQUIRE(atf::check::build_c_o("test.c", "test.o", + atf::process::argv_array())); +} + +ATF_TEST_CASE(h_build_c_o_fail); +ATF_TEST_CASE_HEAD(h_build_c_o_fail) +{ + set_md_var("descr", "Helper test case for build_c_o"); +} +ATF_TEST_CASE_BODY(h_build_c_o_fail) +{ + std::ofstream sfile("test.c"); + sfile << "void foo(void) { int a = UNDEFINED_SYMBOL; }\n"; + sfile.close(); + + ATF_REQUIRE(!atf::check::build_c_o("test.c", "test.o", + atf::process::argv_array())); +} + +ATF_TEST_CASE(h_build_cpp_ok); +ATF_TEST_CASE_HEAD(h_build_cpp_ok) +{ + set_md_var("descr", "Helper test case for build_cpp"); +} +ATF_TEST_CASE_BODY(h_build_cpp_ok) +{ + std::ofstream sfile("test.c"); + sfile << "#define A foo\n"; + sfile << "#define B bar\n"; + sfile << "A B\n"; + sfile.close(); + + ATF_REQUIRE(atf::check::build_cpp("test.c", "test.p", + atf::process::argv_array())); +} + +ATF_TEST_CASE(h_build_cpp_fail); +ATF_TEST_CASE_HEAD(h_build_cpp_fail) +{ + set_md_var("descr", "Helper test case for build_cpp"); +} +ATF_TEST_CASE_BODY(h_build_cpp_fail) +{ + std::ofstream sfile("test.c"); + sfile << "#include \"./non-existent.h\"\n"; + sfile.close(); + + ATF_REQUIRE(!atf::check::build_cpp("test.c", "test.p", + atf::process::argv_array())); +} + +ATF_TEST_CASE(h_build_cxx_o_ok); +ATF_TEST_CASE_HEAD(h_build_cxx_o_ok) +{ + set_md_var("descr", "Helper test case for build_cxx_o"); +} +ATF_TEST_CASE_BODY(h_build_cxx_o_ok) +{ + std::ofstream sfile("test.cpp"); + sfile << "#include \n"; + sfile.close(); + + ATF_REQUIRE(atf::check::build_cxx_o("test.cpp", "test.o", + atf::process::argv_array())); +} + +ATF_TEST_CASE(h_build_cxx_o_fail); +ATF_TEST_CASE_HEAD(h_build_cxx_o_fail) +{ + set_md_var("descr", "Helper test case for build_cxx_o"); +} +ATF_TEST_CASE_BODY(h_build_cxx_o_fail) +{ + std::ofstream sfile("test.cpp"); + sfile << "void foo(void) { int a = UNDEFINED_SYMBOL; }\n"; + sfile.close(); + + ATF_REQUIRE(!atf::check::build_cxx_o("test.cpp", "test.o", + atf::process::argv_array())); +} + +// ------------------------------------------------------------------------ +// Test cases for the free functions. +// ------------------------------------------------------------------------ + +ATF_TEST_CASE(build_c_o); +ATF_TEST_CASE_HEAD(build_c_o) +{ + set_md_var("descr", "Tests the build_c_o function"); +} +ATF_TEST_CASE_BODY(build_c_o) +{ + ATF_TEST_CASE_USE(h_build_c_o_ok); + run_h_tc< ATF_TEST_CASE_NAME(h_build_c_o_ok) >(); + ATF_REQUIRE(atf::utils::grep_file("-o test.o", "stdout")); + ATF_REQUIRE(atf::utils::grep_file("-c test.c", "stdout")); + + ATF_TEST_CASE_USE(h_build_c_o_fail); + run_h_tc< ATF_TEST_CASE_NAME(h_build_c_o_fail) >(); + ATF_REQUIRE(atf::utils::grep_file("-o test.o", "stdout")); + ATF_REQUIRE(atf::utils::grep_file("-c test.c", "stdout")); + ATF_REQUIRE(atf::utils::grep_file("test.c", "stderr")); + ATF_REQUIRE(atf::utils::grep_file("UNDEFINED_SYMBOL", "stderr")); +} + +ATF_TEST_CASE(build_cpp); +ATF_TEST_CASE_HEAD(build_cpp) +{ + set_md_var("descr", "Tests the build_cpp function"); +} +ATF_TEST_CASE_BODY(build_cpp) +{ + ATF_TEST_CASE_USE(h_build_cpp_ok); + run_h_tc< ATF_TEST_CASE_NAME(h_build_cpp_ok) >(); + ATF_REQUIRE(atf::utils::grep_file("-o.*test.p", "stdout")); + ATF_REQUIRE(atf::utils::grep_file("test.c", "stdout")); + ATF_REQUIRE(atf::utils::grep_file("foo bar", "test.p")); + + ATF_TEST_CASE_USE(h_build_cpp_fail); + run_h_tc< ATF_TEST_CASE_NAME(h_build_cpp_fail) >(); + ATF_REQUIRE(atf::utils::grep_file("-o test.p", "stdout")); + ATF_REQUIRE(atf::utils::grep_file("test.c", "stdout")); + ATF_REQUIRE(atf::utils::grep_file("test.c", "stderr")); + ATF_REQUIRE(atf::utils::grep_file("non-existent.h", "stderr")); +} + +ATF_TEST_CASE(build_cxx_o); +ATF_TEST_CASE_HEAD(build_cxx_o) +{ + set_md_var("descr", "Tests the build_cxx_o function"); +} +ATF_TEST_CASE_BODY(build_cxx_o) +{ + ATF_TEST_CASE_USE(h_build_cxx_o_ok); + run_h_tc< ATF_TEST_CASE_NAME(h_build_cxx_o_ok) >(); + ATF_REQUIRE(atf::utils::grep_file("-o test.o", "stdout")); + ATF_REQUIRE(atf::utils::grep_file("-c test.cpp", "stdout")); + + ATF_TEST_CASE_USE(h_build_cxx_o_fail); + run_h_tc< ATF_TEST_CASE_NAME(h_build_cxx_o_fail) >(); + ATF_REQUIRE(atf::utils::grep_file("-o test.o", "stdout")); + ATF_REQUIRE(atf::utils::grep_file("-c test.cpp", "stdout")); + ATF_REQUIRE(atf::utils::grep_file("test.cpp", "stderr")); + ATF_REQUIRE(atf::utils::grep_file("UNDEFINED_SYMBOL", "stderr")); +} + +ATF_TEST_CASE(exec_cleanup); +ATF_TEST_CASE_HEAD(exec_cleanup) +{ + set_md_var("descr", "Tests that exec properly cleans up the temporary " + "files it creates"); +} +ATF_TEST_CASE_BODY(exec_cleanup) +{ + std::auto_ptr< atf::fs::path > out; + std::auto_ptr< atf::fs::path > err; + + { + std::auto_ptr< atf::check::check_result > r = + do_exec(this, "exit-success"); + out.reset(new atf::fs::path(r->stdout_path())); + err.reset(new atf::fs::path(r->stderr_path())); + ATF_REQUIRE(atf::fs::exists(*out.get())); + ATF_REQUIRE(atf::fs::exists(*err.get())); + } + ATF_REQUIRE(!atf::fs::exists(*out.get())); + ATF_REQUIRE(!atf::fs::exists(*err.get())); +} + +ATF_TEST_CASE(exec_exitstatus); +ATF_TEST_CASE_HEAD(exec_exitstatus) +{ + set_md_var("descr", "Tests that exec properly captures the exit " + "status of the executed command"); +} +ATF_TEST_CASE_BODY(exec_exitstatus) +{ + { + std::auto_ptr< atf::check::check_result > r = + do_exec(this, "exit-success"); + ATF_REQUIRE(r->exited()); + ATF_REQUIRE(!r->signaled()); + ATF_REQUIRE_EQ(r->exitcode(), EXIT_SUCCESS); + } + + { + std::auto_ptr< atf::check::check_result > r = + do_exec(this, "exit-failure"); + ATF_REQUIRE(r->exited()); + ATF_REQUIRE(!r->signaled()); + ATF_REQUIRE_EQ(r->exitcode(), EXIT_FAILURE); + } + + { + std::auto_ptr< atf::check::check_result > r = + do_exec(this, "exit-signal"); + ATF_REQUIRE(!r->exited()); + ATF_REQUIRE(r->signaled()); + ATF_REQUIRE_EQ(r->termsig(), SIGKILL); + } +} + +static +void +check_lines(const std::string& path, const char* outname, + const char* resname) +{ + std::ifstream f(path.c_str()); + ATF_REQUIRE(f); + + std::string line; + std::getline(f, line); + ATF_REQUIRE_EQ(line, std::string("Line 1 to ") + outname + " for " + + resname); + std::getline(f, line); + ATF_REQUIRE_EQ(line, std::string("Line 2 to ") + outname + " for " + + resname); +} + +ATF_TEST_CASE(exec_stdout_stderr); +ATF_TEST_CASE_HEAD(exec_stdout_stderr) +{ + set_md_var("descr", "Tests that exec properly captures the stdout " + "and stderr streams of the child process"); +} +ATF_TEST_CASE_BODY(exec_stdout_stderr) +{ + std::auto_ptr< atf::check::check_result > r1 = + do_exec(this, "stdout-stderr", "result1"); + ATF_REQUIRE(r1->exited()); + ATF_REQUIRE_EQ(r1->exitcode(), EXIT_SUCCESS); + + std::auto_ptr< atf::check::check_result > r2 = + do_exec(this, "stdout-stderr", "result2"); + ATF_REQUIRE(r2->exited()); + ATF_REQUIRE_EQ(r2->exitcode(), EXIT_SUCCESS); + + const std::string out1 = r1->stdout_path(); + const std::string out2 = r2->stdout_path(); + const std::string err1 = r1->stderr_path(); + const std::string err2 = r2->stderr_path(); + + ATF_REQUIRE(out1.find("check.XXXXXX") == std::string::npos); + ATF_REQUIRE(out2.find("check.XXXXXX") == std::string::npos); + ATF_REQUIRE(err1.find("check.XXXXXX") == std::string::npos); + ATF_REQUIRE(err2.find("check.XXXXXX") == std::string::npos); + + ATF_REQUIRE(out1.find("/check") != std::string::npos); + ATF_REQUIRE(out2.find("/check") != std::string::npos); + ATF_REQUIRE(err1.find("/check") != std::string::npos); + ATF_REQUIRE(err2.find("/check") != std::string::npos); + + ATF_REQUIRE(out1.find("/stdout") != std::string::npos); + ATF_REQUIRE(out2.find("/stdout") != std::string::npos); + ATF_REQUIRE(err1.find("/stderr") != std::string::npos); + ATF_REQUIRE(err2.find("/stderr") != std::string::npos); + + ATF_REQUIRE(out1 != out2); + ATF_REQUIRE(err1 != err2); + + check_lines(out1, "stdout", "result1"); + check_lines(out2, "stdout", "result2"); + check_lines(err1, "stderr", "result1"); + check_lines(err2, "stderr", "result2"); +} + +ATF_TEST_CASE(exec_unknown); +ATF_TEST_CASE_HEAD(exec_unknown) +{ + set_md_var("descr", "Tests that running a non-existing binary " + "is handled correctly"); +} +ATF_TEST_CASE_BODY(exec_unknown) +{ + std::vector< std::string > argv; + argv.push_back(atf::config::get("atf_workdir") + "/non-existent"); + + atf::process::argv_array argva(argv); + std::auto_ptr< atf::check::check_result > r = atf::check::exec(argva); + ATF_REQUIRE(r->exited()); + ATF_REQUIRE_EQ(r->exitcode(), 127); +} + +// ------------------------------------------------------------------------ +// Tests cases for the header file. +// ------------------------------------------------------------------------ + +HEADER_TC(include, "atf-c++/check.hpp"); + +// ------------------------------------------------------------------------ +// Main. +// ------------------------------------------------------------------------ + +ATF_INIT_TEST_CASES(tcs) +{ + // Add the test cases for the free functions. + ATF_ADD_TEST_CASE(tcs, build_c_o); + ATF_ADD_TEST_CASE(tcs, build_cpp); + ATF_ADD_TEST_CASE(tcs, build_cxx_o); + ATF_ADD_TEST_CASE(tcs, exec_cleanup); + ATF_ADD_TEST_CASE(tcs, exec_exitstatus); + ATF_ADD_TEST_CASE(tcs, exec_stdout_stderr); + ATF_ADD_TEST_CASE(tcs, exec_unknown); + + // Add the test cases for the header file. + ATF_ADD_TEST_CASE(tcs, include); +} diff --git a/external/bsd/atf/dist/atf-c++/config.cpp b/external/bsd/atf/dist/atf-c++/config.cpp new file mode 100644 index 000000000..7b7d6416c --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/config.cpp @@ -0,0 +1,123 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#include + +extern "C" { +#include "atf-c/config.h" +} + +#include "config.hpp" + +#include "detail/env.hpp" +#include "detail/sanity.hpp" + +static std::map< std::string, std::string > m_variables; + +// +// Adds all predefined standard build-time variables to the m_variables +// map, considering the values a user may have provided in the environment. +// +// Can only be called once during the program's lifetime. +// +static +void +init_variables(void) +{ + PRE(m_variables.empty()); + + m_variables["atf_arch"] = atf_config_get("atf_arch"); + m_variables["atf_build_cc"] = atf_config_get("atf_build_cc"); + m_variables["atf_build_cflags"] = atf_config_get("atf_build_cflags"); + m_variables["atf_build_cpp"] = atf_config_get("atf_build_cpp"); + m_variables["atf_build_cppflags"] = atf_config_get("atf_build_cppflags"); + m_variables["atf_build_cxx"] = atf_config_get("atf_build_cxx"); + m_variables["atf_build_cxxflags"] = atf_config_get("atf_build_cxxflags"); + m_variables["atf_confdir"] = atf_config_get("atf_confdir"); + m_variables["atf_includedir"] = atf_config_get("atf_includedir"); + m_variables["atf_libdir"] = atf_config_get("atf_libdir"); + m_variables["atf_libexecdir"] = atf_config_get("atf_libexecdir"); + m_variables["atf_machine"] = atf_config_get("atf_machine"); + m_variables["atf_pkgdatadir"] = atf_config_get("atf_pkgdatadir"); + m_variables["atf_shell"] = atf_config_get("atf_shell"); + m_variables["atf_workdir"] = atf_config_get("atf_workdir"); + + POST(!m_variables.empty()); +} + +const std::string& +atf::config::get(const std::string& varname) +{ + if (m_variables.empty()) + init_variables(); + + PRE(has(varname)); + return m_variables[varname]; +} + +const std::map< std::string, std::string >& +atf::config::get_all(void) +{ + if (m_variables.empty()) + init_variables(); + + return m_variables; +} + +bool +atf::config::has(const std::string& varname) +{ + if (m_variables.empty()) + init_variables(); + + return m_variables.find(varname) != m_variables.end(); +} + +extern "C" { +void __atf_config_reinit(void); +} + +namespace atf { +namespace config { +// +// Auxiliary function for the t_config test program so that it can +// revert the configuration's global status to an empty state and +// do new tests from there on. +// +// Ideally this shouldn't be part of the production library... but +// this is so small that it does not matter. +// +void +__reinit(void) +{ + __atf_config_reinit(); + m_variables.clear(); +} +} // namespace config +} // namespace atf diff --git a/external/bsd/atf/dist/atf-c++/config.hpp b/external/bsd/atf/dist/atf-c++/config.hpp new file mode 100644 index 000000000..e11b9bb21 --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/config.hpp @@ -0,0 +1,75 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#if !defined(_ATF_CXX_CONFIG_HPP_) +#define _ATF_CXX_CONFIG_HPP_ + +#include +#include + +namespace atf { + +namespace config { + +//! +//! \brief Gets a build-time configuration variable's value. +//! +//! Given the name of a build-time configuration variable, returns its +//! textual value. The user is free to override these by setting their +//! corresponding environment variables. Therefore always use this +//! interface to get the value of these variables. +//! +//! \pre The variable must exist. +//! +const std::string& get(const std::string&); + +//! +//! \brief Returns all the build-time configuration variables. +//! +//! Returns a name to value map containing all build-time configuration +//! variables. +//! +const std::map< std::string, std::string >& get_all(void); + +//! +//! \brief Checks whether a build-time configuration variable exists. +//! +//! Given the name of a build-time configuration variable, checks +//! whether it is defined and returns a boolean indicating this +//! condition. The program only has to use this function to sanity-check +//! a variable name provided by the user. Otherwise it can assume that +//! the variables are defined. +//! +bool has(const std::string&); + +} // namespace config + +} // namespace atf + +#endif // !defined(_ATF_CXX_CONFIG_HPP_) diff --git a/external/bsd/atf/dist/atf-c++/config_test.cpp b/external/bsd/atf/dist/atf-c++/config_test.cpp new file mode 100644 index 000000000..a3cd2bb51 --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/config_test.cpp @@ -0,0 +1,231 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#include +#include + +#include "config.hpp" +#include "macros.hpp" + +#include "detail/env.hpp" +#include "detail/exceptions.hpp" +#include "detail/test_helpers.hpp" + +static const char *test_value = "env-value"; + +static struct varnames { + const char *lc; + const char *uc; + bool can_be_empty; +} all_vars[] = { + { "atf_arch", "ATF_ARCH", false }, + { "atf_build_cc", "ATF_BUILD_CC", false }, + { "atf_build_cflags", "ATF_BUILD_CFLAGS", true }, + { "atf_build_cpp", "ATF_BUILD_CPP", false }, + { "atf_build_cppflags", "ATF_BUILD_CPPFLAGS", true }, + { "atf_build_cxx", "ATF_BUILD_CXX", false }, + { "atf_build_cxxflags", "ATF_BUILD_CXXFLAGS", true }, + { "atf_confdir", "ATF_CONFDIR", false }, + { "atf_includedir", "ATF_INCLUDEDIR", false }, + { "atf_libdir", "ATF_LIBDIR", false }, + { "atf_libexecdir", "ATF_LIBEXECDIR", false }, + { "atf_machine", "ATF_MACHINE", false }, + { "atf_pkgdatadir", "ATF_PKGDATADIR", false }, + { "atf_shell", "ATF_SHELL", false }, + { "atf_workdir", "ATF_WORKDIR", false }, + { NULL, NULL, false } +}; + +// ------------------------------------------------------------------------ +// Auxiliary functions. +// ------------------------------------------------------------------------ + +namespace atf { + namespace config { + void __reinit(void); + } +} + +static +void +set_env_var(const char* name, const char* val) +{ + try { + atf::env::set(name, val); + } catch (const atf::system_error&) { + ATF_FAIL(std::string("set_env_var(") + name + ", " + val + + ") failed"); + } +} + +static +void +unset_env_var(const char* name) +{ + try { + atf::env::unset(name); + } catch (const atf::system_error&) { + ATF_FAIL(std::string("unset_env_var(") + name + ") failed"); + } +} + +static +size_t +all_vars_count(void) +{ + size_t count = 0; + for (const struct varnames* v = all_vars; v->lc != NULL; v++) + count++; + return count; +} + +static +void +unset_all(void) +{ + for (const struct varnames* v = all_vars; v->lc != NULL; v++) + unset_env_var(v->uc); +} + +static +void +compare_one(const char* var, const char* expvalue) +{ + std::cout << "Checking that " << var << " is set to " << expvalue << "\n"; + + for (const struct varnames* v = all_vars; v->lc != NULL; v++) { + if (std::strcmp(v->lc, var) == 0) + ATF_REQUIRE_EQ(atf::config::get(v->lc), test_value); + else + ATF_REQUIRE(atf::config::get(v->lc) != test_value); + } +} + +// ------------------------------------------------------------------------ +// Test cases for the free functions. +// ------------------------------------------------------------------------ + +ATF_TEST_CASE(get); +ATF_TEST_CASE_HEAD(get) +{ + set_md_var("descr", "Tests the config::get function"); +} +ATF_TEST_CASE_BODY(get) +{ + // Unset all known environment variables and make sure the built-in + // values do not match the bogus value we will use for testing. + unset_all(); + atf::config::__reinit(); + for (const struct varnames* v = all_vars; v->lc != NULL; v++) + ATF_REQUIRE(atf::config::get(v->lc) != test_value); + + // Test the behavior of empty values. + for (const struct varnames* v = all_vars; v->lc != NULL; v++) { + unset_all(); + if (!atf::config::get(v->lc).empty()) { + set_env_var(v->uc, ""); + atf::config::__reinit(); + if (v->can_be_empty) + ATF_REQUIRE(atf::config::get(v->lc).empty()); + else + ATF_REQUIRE(!atf::config::get(v->lc).empty()); + } + } + + // Check if the ATF_ARCH variable is recognized. + for (const struct varnames* v = all_vars; v->lc != NULL; v++) { + unset_all(); + set_env_var(v->uc, test_value); + atf::config::__reinit(); + compare_one(v->lc, test_value); + } +} + +ATF_TEST_CASE(get_all); +ATF_TEST_CASE_HEAD(get_all) +{ + set_md_var("descr", "Tests the config::get_all function"); +} +ATF_TEST_CASE_BODY(get_all) +{ + atf::config::__reinit(); + + // Check that the valid variables, and only those, are returned. + std::map< std::string, std::string > vars = atf::config::get_all(); + ATF_REQUIRE_EQ(vars.size(), all_vars_count()); + for (const struct varnames* v = all_vars; v->lc != NULL; v++) + ATF_REQUIRE(vars.find(v->lc) != vars.end()); +} + +ATF_TEST_CASE(has); +ATF_TEST_CASE_HEAD(has) +{ + set_md_var("descr", "Tests the config::has function"); +} +ATF_TEST_CASE_BODY(has) +{ + atf::config::__reinit(); + + // Check for all the variables that must exist. + for (const struct varnames* v = all_vars; v->lc != NULL; v++) + ATF_REQUIRE(atf::config::has(v->lc)); + + // Same as above, but using uppercase (which is incorrect). + for (const struct varnames* v = all_vars; v->lc != NULL; v++) + ATF_REQUIRE(!atf::config::has(v->uc)); + + // Check for some other variables that cannot exist. + ATF_REQUIRE(!atf::config::has("foo")); + ATF_REQUIRE(!atf::config::has("BAR")); + ATF_REQUIRE(!atf::config::has("atf_foo")); + ATF_REQUIRE(!atf::config::has("ATF_BAR")); + ATF_REQUIRE(!atf::config::has("atf_shel")); + ATF_REQUIRE(!atf::config::has("atf_shells")); +} + +// ------------------------------------------------------------------------ +// Tests cases for the header file. +// ------------------------------------------------------------------------ + +HEADER_TC(include, "atf-c++/config.hpp"); + +// ------------------------------------------------------------------------ +// Main. +// ------------------------------------------------------------------------ + +ATF_INIT_TEST_CASES(tcs) +{ + // Add the test cases for the free functions. + ATF_ADD_TEST_CASE(tcs, has); + ATF_ADD_TEST_CASE(tcs, get); + ATF_ADD_TEST_CASE(tcs, get_all); + + // Add the test cases for the header file. + ATF_ADD_TEST_CASE(tcs, include); +} diff --git a/external/bsd/atf/dist/atf-c++/detail/Atffile b/external/bsd/atf/dist/atf-c++/detail/Atffile new file mode 100644 index 000000000..2d53514bd --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/detail/Atffile @@ -0,0 +1,14 @@ +Content-Type: application/X-atf-atffile; version="1" + +prop: test-suite = atf + +tp: application_test +tp: auto_array_test +tp: env_test +tp: exceptions_test +tp: expand_test +tp: fs_test +tp: parser_test +tp: sanity_test +tp: text_test +tp: ui_test diff --git a/external/bsd/atf/dist/atf-c++/detail/Kyuafile b/external/bsd/atf/dist/atf-c++/detail/Kyuafile new file mode 100644 index 000000000..fd0d7abe8 --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/detail/Kyuafile @@ -0,0 +1,14 @@ +syntax("kyuafile", 1) + +test_suite("atf") + +atf_test_program{name="application_test"} +atf_test_program{name="auto_array_test"} +atf_test_program{name="env_test"} +atf_test_program{name="exceptions_test"} +atf_test_program{name="expand_test"} +atf_test_program{name="fs_test"} +atf_test_program{name="parser_test"} +atf_test_program{name="sanity_test"} +atf_test_program{name="text_test"} +atf_test_program{name="ui_test"} diff --git a/external/bsd/atf/dist/atf-c++/detail/application.cpp b/external/bsd/atf/dist/atf-c++/detail/application.cpp new file mode 100644 index 000000000..878b010bc --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/detail/application.cpp @@ -0,0 +1,345 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#if defined(HAVE_CONFIG_H) +#include "bconfig.h" +#endif + +extern "C" { +#include +} + +#include +#include +#include +#include +#include + +extern "C" { +#include "atf-c/defs.h" +} + +#include "application.hpp" +#include "sanity.hpp" +#include "ui.hpp" + +#if !defined(HAVE_VSNPRINTF_IN_STD) +namespace std { +using ::vsnprintf; +} +#endif // !defined(HAVE_VSNPRINTF_IN_STD) + +namespace impl = atf::application; +#define IMPL_NAME "atf::application" + +// ------------------------------------------------------------------------ +// The "usage_error" class. +// ------------------------------------------------------------------------ + +impl::usage_error::usage_error(const char *fmt, ...) + throw() : + std::runtime_error("usage_error; message unformatted") +{ + va_list ap; + + va_start(ap, fmt); + std::vsnprintf(m_text, sizeof(m_text), fmt, ap); + va_end(ap); +} + +impl::usage_error::~usage_error(void) + throw() +{ +} + +const char* +impl::usage_error::what(void) + const throw() +{ + return m_text; +} + +// ------------------------------------------------------------------------ +// The "application" class. +// ------------------------------------------------------------------------ + +impl::option::option(char ch, + const std::string& a, + const std::string& desc) : + m_character(ch), + m_argument(a), + m_description(desc) +{ +} + +bool +impl::option::operator<(const impl::option& o) + const +{ + return m_character < o.m_character; +} + +impl::app::app(const std::string& description, + const std::string& manpage, + const std::string& global_manpage, + const bool use_ui) : + m_hflag(false), + m_argc(-1), + m_argv(NULL), + m_prog_name(NULL), + m_description(description), + m_manpage(manpage), + m_global_manpage(global_manpage), + m_use_ui(use_ui) +{ +} + +impl::app::~app(void) +{ +} + +bool +impl::app::inited(void) +{ + return m_argc != -1; +} + +impl::app::options_set +impl::app::options(void) +{ + options_set opts = specific_options(); + if (m_use_ui) { + opts.insert(option('h', "", "Shows this help message")); + } + return opts; +} + +std::string +impl::app::specific_args(void) + const +{ + return ""; +} + +impl::app::options_set +impl::app::specific_options(void) + const +{ + return options_set(); +} + +void +impl::app::process_option(int ch ATF_DEFS_ATTRIBUTE_UNUSED, + const char* arg ATF_DEFS_ATTRIBUTE_UNUSED) +{ +} + +void +impl::app::process_options(void) +{ + PRE(inited()); + + std::string optstr; +#if defined(HAVE_GNU_GETOPT) + optstr += '+'; // Turn on POSIX behavior. +#endif + optstr += ':'; + { + options_set opts = options(); + for (options_set::const_iterator iter = opts.begin(); + iter != opts.end(); iter++) { + const option& opt = (*iter); + + optstr += opt.m_character; + if (!opt.m_argument.empty()) + optstr += ':'; + } + } + + int ch; + const int old_opterr = ::opterr; + ::opterr = 0; + while ((ch = ::getopt(m_argc, m_argv, optstr.c_str())) != -1) { + switch (ch) { + case 'h': + INV(m_use_ui); + m_hflag = true; + break; + + case ':': + throw usage_error("Option -%c requires an argument.", + ::optopt); + + case '?': + throw usage_error("Unknown option -%c.", ::optopt); + + default: + process_option(ch, ::optarg); + } + } + m_argc -= ::optind; + m_argv += ::optind; + + // Clear getopt state just in case the test wants to use it. + opterr = old_opterr; + optind = 1; +#if defined(HAVE_OPTRESET) + optreset = 1; +#endif +} + +void +impl::app::usage(std::ostream& os) +{ + PRE(inited()); + + std::string args = specific_args(); + if (!args.empty()) + args = " " + args; + os << ui::format_text_with_tag(std::string(m_prog_name) + " [options]" + + args, "Usage: ", false) << "\n\n" + << ui::format_text(m_description) << "\n\n"; + + options_set opts = options(); + INV(!opts.empty()); + os << "Available options:\n"; + size_t coldesc = 0; + for (options_set::const_iterator iter = opts.begin(); + iter != opts.end(); iter++) { + const option& opt = (*iter); + + if (opt.m_argument.length() + 1 > coldesc) + coldesc = opt.m_argument.length() + 1; + } + for (options_set::const_iterator iter = opts.begin(); + iter != opts.end(); iter++) { + const option& opt = (*iter); + + std::string tag = std::string(" -") + opt.m_character; + if (opt.m_argument.empty()) + tag += " "; + else + tag += " " + opt.m_argument + " "; + os << ui::format_text_with_tag(opt.m_description, tag, false, + coldesc + 10) << "\n"; + } + os << "\n"; + + std::string gmp; + if (!m_global_manpage.empty()) + gmp = " and " + m_global_manpage; + os << ui::format_text("For more details please see " + m_manpage + + gmp + ".") + << "\n"; +} + +int +impl::app::run(int argc, char* const* argv) +{ + PRE(argc > 0); + PRE(argv != NULL); + + m_argc = argc; + m_argv = argv; + + m_argv0 = m_argv[0]; + + m_prog_name = std::strrchr(m_argv[0], '/'); + if (m_prog_name == NULL) + m_prog_name = m_argv[0]; + else + m_prog_name++; + + // Libtool workaround: if running from within the source tree (binaries + // that are not installed yet), skip the "lt-" prefix added to files in + // the ".libs" directory to show the real (not temporary) name. + if (std::strncmp(m_prog_name, "lt-", 3) == 0) + m_prog_name += 3; + + const std::string bug = + std::string("This is probably a bug in ") + m_prog_name + + " or one of the libraries it uses. Please report this problem to " + PACKAGE_BUGREPORT " and provide as many details as possible " + "describing how you got to this condition."; + + int errcode; + try { + int oldargc = m_argc; + + process_options(); + + if (m_hflag) { + INV(m_use_ui); + if (oldargc != 2) + throw usage_error("-h must be given alone."); + + usage(std::cout); + errcode = EXIT_SUCCESS; + } else + errcode = main(); + } catch (const usage_error& e) { + if (m_use_ui) { + std::cerr << ui::format_error(m_prog_name, e.what()) << "\n" + << ui::format_info(m_prog_name, std::string("Type `") + + m_prog_name + " -h' for more details.") + << "\n"; + } else { + std::cerr << m_prog_name << ": ERROR: " << e.what() << "\n"; + std::cerr << m_prog_name << ": See " << m_manpage << " for usage " + "details.\n"; + } + errcode = EXIT_FAILURE; + } catch (const std::runtime_error& e) { + if (m_use_ui) { + std::cerr << ui::format_error(m_prog_name, std::string(e.what())) + << "\n"; + } else { + std::cerr << m_prog_name << ": ERROR: " << e.what() << "\n"; + } + errcode = EXIT_FAILURE; + } catch (const std::exception& e) { + if (m_use_ui) { + std::cerr << ui::format_error(m_prog_name, std::string("Caught " + "unexpected error: ") + e.what() + "\n" + bug) << "\n"; + } else { + std::cerr << m_prog_name << ": ERROR: Caught unexpected error: " + << e.what() << "\n"; + } + errcode = EXIT_FAILURE; + } catch (...) { + if (m_use_ui) { + std::cerr << ui::format_error(m_prog_name, std::string("Caught " + "unknown error\n") + bug) << "\n"; + } else { + std::cerr << m_prog_name << ": ERROR: Caught unknown error\n"; + } + errcode = EXIT_FAILURE; + } + return errcode; +} diff --git a/external/bsd/atf/dist/atf-c++/detail/application.hpp b/external/bsd/atf/dist/atf-c++/detail/application.hpp new file mode 100644 index 000000000..9d1f24200 --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/detail/application.hpp @@ -0,0 +1,115 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#if !defined(_ATF_CXX_APPLICATION_HPP_) +#define _ATF_CXX_APPLICATION_HPP_ + +#include +#include +#include +#include + +namespace atf { +namespace application { + +// ------------------------------------------------------------------------ +// The "usage_error" class. +// ------------------------------------------------------------------------ + +class usage_error : public std::runtime_error { + char m_text[4096]; + +public: + usage_error(const char*, ...) throw(); + ~usage_error(void) throw(); + + const char* what(void) const throw(); +}; + +// ------------------------------------------------------------------------ +// The "option" class. +// ------------------------------------------------------------------------ + +class option { + char m_character; + std::string m_argument; + std::string m_description; + + friend class app; + +public: + option(char, const std::string&, const std::string&); + + bool operator<(const option&) const; +}; + +// ------------------------------------------------------------------------ +// The "app" class. +// ------------------------------------------------------------------------ + +class app { + bool m_hflag; + + void process_options(void); + void usage(std::ostream&); + + bool inited(void); + +protected: + typedef std::set< option > options_set; + + int m_argc; + char* const* m_argv; + + const char* m_argv0; + const char* m_prog_name; + std::string m_description; + std::string m_manpage, m_global_manpage; + const bool m_use_ui; + + options_set options(void); + + // To be redefined. + virtual std::string specific_args(void) const; + virtual options_set specific_options(void) const; + virtual void process_option(int, const char*); + virtual int main(void) = 0; + +public: + app(const std::string&, const std::string&, const std::string&, + bool = true); + virtual ~app(void); + + int run(int, char* const*); +}; + +} // namespace application +} // namespace atf + +#endif // !defined(_ATF_CXX_APPLICATION_HPP_) diff --git a/external/bsd/atf/dist/atf-c++/detail/application_test.cpp b/external/bsd/atf/dist/atf-c++/detail/application_test.cpp new file mode 100644 index 000000000..2a788bfb2 --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/detail/application_test.cpp @@ -0,0 +1,94 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2009 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +extern "C" { +#include +} + +#include "application.hpp" + +#include "../macros.hpp" + +class getopt_app : public atf::application::app { +public: + getopt_app(void) : app("description", "manpage", "other") {} + + int main(void) + { + // Provide an option that is unknown to the application driver and + // one that is, together with an argument that would be swallowed by + // the test program option if it were recognized. + int argc = 4; + char arg1[] = "progname"; + char arg2[] = "-Z"; + char arg3[] = "-s"; + char arg4[] = "foo"; + char *const argv[] = { arg1, arg2, arg3, arg4, NULL }; + + int ch; + bool zflag; + + // Given that this obviously is an application, and that we used the + // same driver to start, we can test getopt(3) right here without doing + // any fancy stuff. + zflag = false; + while ((ch = ::getopt(argc, argv, ":Z")) != -1) { + switch (ch) { + case 'Z': + zflag = true; + break; + + case '?': + default: + if (optopt != 's') + ATF_FAIL("Unexpected unknown option found"); + } + } + + ATF_REQUIRE(zflag); + ATF_REQUIRE_EQ(1, argc - optind); + ATF_REQUIRE_EQ(std::string("foo"), argv[optind]); + + return 0; + } +}; + +ATF_TEST_CASE_WITHOUT_HEAD(getopt); +ATF_TEST_CASE_BODY(getopt) +{ + int argc = 1; + char arg1[] = "progname"; + char *const argv[] = { arg1, NULL }; + ATF_REQUIRE_EQ(0, getopt_app().run(argc, argv)); +} + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, getopt); +} diff --git a/external/bsd/atf/dist/atf-c++/detail/auto_array.hpp b/external/bsd/atf/dist/atf-c++/detail/auto_array.hpp new file mode 100644 index 000000000..1459284e3 --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/detail/auto_array.hpp @@ -0,0 +1,179 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#if !defined(_ATF_CXX_AUTO_ARRAY_HPP_) +#define _ATF_CXX_AUTO_ARRAY_HPP_ + +#include + +namespace atf { + +// ------------------------------------------------------------------------ +// The "auto_array" class. +// ------------------------------------------------------------------------ + +template< class T > +struct auto_array_ref { + T* m_ptr; + + explicit auto_array_ref(T*); +}; + +template< class T > +auto_array_ref< T >::auto_array_ref(T* ptr) : + m_ptr(ptr) +{ +} + +template< class T > +class auto_array { + T* m_ptr; + +public: + auto_array(T* = NULL) throw(); + auto_array(auto_array< T >&) throw(); + auto_array(auto_array_ref< T >) throw(); + ~auto_array(void) throw(); + + T* get(void) throw(); + const T* get(void) const throw(); + T* release(void) throw(); + void reset(T* = NULL) throw(); + + auto_array< T >& operator=(auto_array< T >&) throw(); + auto_array< T >& operator=(auto_array_ref< T >) throw(); + + T& operator[](int) throw(); + operator auto_array_ref< T >(void) throw(); +}; + +template< class T > +auto_array< T >::auto_array(T* ptr) + throw() : + m_ptr(ptr) +{ +} + +template< class T > +auto_array< T >::auto_array(auto_array< T >& ptr) + throw() : + m_ptr(ptr.release()) +{ +} + +template< class T > +auto_array< T >::auto_array(auto_array_ref< T > ref) + throw() : + m_ptr(ref.m_ptr) +{ +} + +template< class T > +auto_array< T >::~auto_array(void) + throw() +{ + if (m_ptr != NULL) + delete [] m_ptr; +} + +template< class T > +T* +auto_array< T >::get(void) + throw() +{ + return m_ptr; +} + +template< class T > +const T* +auto_array< T >::get(void) + const throw() +{ + return m_ptr; +} + +template< class T > +T* +auto_array< T >::release(void) + throw() +{ + T* ptr = m_ptr; + m_ptr = NULL; + return ptr; +} + +template< class T > +void +auto_array< T >::reset(T* ptr) + throw() +{ + if (m_ptr != NULL) + delete [] m_ptr; + m_ptr = ptr; +} + +template< class T > +auto_array< T >& +auto_array< T >::operator=(auto_array< T >& ptr) + throw() +{ + reset(ptr.release()); + return *this; +} + +template< class T > +auto_array< T >& +auto_array< T >::operator=(auto_array_ref< T > ref) + throw() +{ + if (m_ptr != ref.m_ptr) { + delete [] m_ptr; + m_ptr = ref.m_ptr; + } + return *this; +} + +template< class T > +T& +auto_array< T >::operator[](int pos) + throw() +{ + return m_ptr[pos]; +} + +template< class T > +auto_array< T >::operator auto_array_ref< T >(void) + throw() +{ + return auto_array_ref< T >(release()); +} + +} // namespace atf + +#endif // !defined(_ATF_CXX_AUTO_ARRAY_HPP_) diff --git a/external/bsd/atf/dist/atf-c++/detail/auto_array_test.cpp b/external/bsd/atf/dist/atf-c++/detail/auto_array_test.cpp new file mode 100644 index 000000000..dcfe41551 --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/detail/auto_array_test.cpp @@ -0,0 +1,304 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +extern "C" { +#include +} + +#include + +#include "atf-c/defs.h" + +#include "../macros.hpp" + +#include "auto_array.hpp" + +// ------------------------------------------------------------------------ +// Tests for the "auto_array" class. +// ------------------------------------------------------------------------ + +class test_array { +public: + int m_value; + + static ssize_t m_nblocks; + + static + atf::auto_array< test_array > + do_copy(atf::auto_array< test_array >& ta) + { + return atf::auto_array< test_array >(ta); + } + + void* operator new(size_t size ATF_DEFS_ATTRIBUTE_UNUSED) + { + ATF_FAIL("New called but should have been new[]"); + return new int(5); + } + + void* operator new[](size_t size) + { + m_nblocks++; + void* mem = ::operator new(size); + std::cout << "Allocated 'test_array' object " << mem << "\n"; + return mem; + } + + void operator delete(void* mem ATF_DEFS_ATTRIBUTE_UNUSED) + { + ATF_FAIL("Delete called but should have been delete[]"); + } + + void operator delete[](void* mem) + { + std::cout << "Releasing 'test_array' object " << mem << "\n"; + if (m_nblocks == 0) + ATF_FAIL("Unbalanced delete[]"); + m_nblocks--; + ::operator delete(mem); + } +}; + +ssize_t test_array::m_nblocks = 0; + +ATF_TEST_CASE(auto_array_scope); +ATF_TEST_CASE_HEAD(auto_array_scope) +{ + set_md_var("descr", "Tests the automatic scope handling in the " + "auto_array smart pointer class"); +} +ATF_TEST_CASE_BODY(auto_array_scope) +{ + using atf::auto_array; + + ATF_REQUIRE_EQ(test_array::m_nblocks, 0); + { + auto_array< test_array > t(new test_array[10]); + ATF_REQUIRE_EQ(test_array::m_nblocks, 1); + } + ATF_REQUIRE_EQ(test_array::m_nblocks, 0); +} + +ATF_TEST_CASE(auto_array_copy); +ATF_TEST_CASE_HEAD(auto_array_copy) +{ + set_md_var("descr", "Tests the auto_array smart pointer class' copy " + "constructor"); +} +ATF_TEST_CASE_BODY(auto_array_copy) +{ + using atf::auto_array; + + ATF_REQUIRE_EQ(test_array::m_nblocks, 0); + { + auto_array< test_array > t1(new test_array[10]); + ATF_REQUIRE_EQ(test_array::m_nblocks, 1); + + { + auto_array< test_array > t2(t1); + ATF_REQUIRE_EQ(test_array::m_nblocks, 1); + } + ATF_REQUIRE_EQ(test_array::m_nblocks, 0); + } + ATF_REQUIRE_EQ(test_array::m_nblocks, 0); +} + +ATF_TEST_CASE(auto_array_copy_ref); +ATF_TEST_CASE_HEAD(auto_array_copy_ref) +{ + set_md_var("descr", "Tests the auto_array smart pointer class' copy " + "constructor through the auxiliary auto_array_ref object"); +} +ATF_TEST_CASE_BODY(auto_array_copy_ref) +{ + using atf::auto_array; + + ATF_REQUIRE_EQ(test_array::m_nblocks, 0); + { + auto_array< test_array > t1(new test_array[10]); + ATF_REQUIRE_EQ(test_array::m_nblocks, 1); + + { + auto_array< test_array > t2 = test_array::do_copy(t1); + ATF_REQUIRE_EQ(test_array::m_nblocks, 1); + } + ATF_REQUIRE_EQ(test_array::m_nblocks, 0); + } + ATF_REQUIRE_EQ(test_array::m_nblocks, 0); +} + +ATF_TEST_CASE(auto_array_get); +ATF_TEST_CASE_HEAD(auto_array_get) +{ + set_md_var("descr", "Tests the auto_array smart pointer class' get " + "method"); +} +ATF_TEST_CASE_BODY(auto_array_get) +{ + using atf::auto_array; + + test_array* ta = new test_array[10]; + auto_array< test_array > t(ta); + ATF_REQUIRE_EQ(t.get(), ta); +} + +ATF_TEST_CASE(auto_array_release); +ATF_TEST_CASE_HEAD(auto_array_release) +{ + set_md_var("descr", "Tests the auto_array smart pointer class' release " + "method"); +} +ATF_TEST_CASE_BODY(auto_array_release) +{ + using atf::auto_array; + + test_array* ta1 = new test_array[10]; + { + auto_array< test_array > t(ta1); + ATF_REQUIRE_EQ(test_array::m_nblocks, 1); + test_array* ta2 = t.release(); + ATF_REQUIRE_EQ(ta2, ta1); + ATF_REQUIRE_EQ(test_array::m_nblocks, 1); + } + ATF_REQUIRE_EQ(test_array::m_nblocks, 1); + delete [] ta1; +} + +ATF_TEST_CASE(auto_array_reset); +ATF_TEST_CASE_HEAD(auto_array_reset) +{ + set_md_var("descr", "Tests the auto_array smart pointer class' reset " + "method"); +} +ATF_TEST_CASE_BODY(auto_array_reset) +{ + using atf::auto_array; + + test_array* ta1 = new test_array[10]; + test_array* ta2 = new test_array[10]; + ATF_REQUIRE_EQ(test_array::m_nblocks, 2); + + { + auto_array< test_array > t(ta1); + ATF_REQUIRE_EQ(test_array::m_nblocks, 2); + t.reset(ta2); + ATF_REQUIRE_EQ(test_array::m_nblocks, 1); + t.reset(); + ATF_REQUIRE_EQ(test_array::m_nblocks, 0); + } + ATF_REQUIRE_EQ(test_array::m_nblocks, 0); +} + +ATF_TEST_CASE(auto_array_assign); +ATF_TEST_CASE_HEAD(auto_array_assign) +{ + set_md_var("descr", "Tests the auto_array smart pointer class' " + "assignment operator"); +} +ATF_TEST_CASE_BODY(auto_array_assign) +{ + using atf::auto_array; + + ATF_REQUIRE_EQ(test_array::m_nblocks, 0); + { + auto_array< test_array > t1(new test_array[10]); + ATF_REQUIRE_EQ(test_array::m_nblocks, 1); + + { + auto_array< test_array > t2; + t2 = t1; + ATF_REQUIRE_EQ(test_array::m_nblocks, 1); + } + ATF_REQUIRE_EQ(test_array::m_nblocks, 0); + } + ATF_REQUIRE_EQ(test_array::m_nblocks, 0); +} + +ATF_TEST_CASE(auto_array_assign_ref); +ATF_TEST_CASE_HEAD(auto_array_assign_ref) +{ + set_md_var("descr", "Tests the auto_array smart pointer class' " + "assignment operator through the auxiliary auto_array_ref " + "object"); +} +ATF_TEST_CASE_BODY(auto_array_assign_ref) +{ + using atf::auto_array; + + ATF_REQUIRE_EQ(test_array::m_nblocks, 0); + { + auto_array< test_array > t1(new test_array[10]); + ATF_REQUIRE_EQ(test_array::m_nblocks, 1); + + { + auto_array< test_array > t2; + t2 = test_array::do_copy(t1); + ATF_REQUIRE_EQ(test_array::m_nblocks, 1); + } + ATF_REQUIRE_EQ(test_array::m_nblocks, 0); + } + ATF_REQUIRE_EQ(test_array::m_nblocks, 0); +} + +ATF_TEST_CASE(auto_array_access); +ATF_TEST_CASE_HEAD(auto_array_access) +{ + set_md_var("descr", "Tests the auto_array smart pointer class' access " + "operator"); +} +ATF_TEST_CASE_BODY(auto_array_access) +{ + using atf::auto_array; + + auto_array< test_array > t(new test_array[10]); + + for (int i = 0; i < 10; i++) + t[i].m_value = i * 2; + + for (int i = 0; i < 10; i++) + ATF_REQUIRE_EQ(t[i].m_value, i * 2); +} + +// ------------------------------------------------------------------------ +// Main. +// ------------------------------------------------------------------------ + +ATF_INIT_TEST_CASES(tcs) +{ + // Add the test for the "auto_array" class. + ATF_ADD_TEST_CASE(tcs, auto_array_scope); + ATF_ADD_TEST_CASE(tcs, auto_array_copy); + ATF_ADD_TEST_CASE(tcs, auto_array_copy_ref); + ATF_ADD_TEST_CASE(tcs, auto_array_get); + ATF_ADD_TEST_CASE(tcs, auto_array_release); + ATF_ADD_TEST_CASE(tcs, auto_array_reset); + ATF_ADD_TEST_CASE(tcs, auto_array_assign); + ATF_ADD_TEST_CASE(tcs, auto_array_assign_ref); + ATF_ADD_TEST_CASE(tcs, auto_array_access); +} diff --git a/external/bsd/atf/dist/atf-c++/detail/env.cpp b/external/bsd/atf/dist/atf-c++/detail/env.cpp new file mode 100644 index 000000000..5ca7f09c4 --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/detail/env.cpp @@ -0,0 +1,73 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +extern "C" { +#include "../../atf-c/error.h" + +#include "../../atf-c/detail/env.h" +} + +#include "env.hpp" +#include "exceptions.hpp" +#include "sanity.hpp" + +namespace impl = atf::env; +#define IMPL_NAME "atf::env" + +// ------------------------------------------------------------------------ +// Free functions. +// ------------------------------------------------------------------------ + +std::string +impl::get(const std::string& name) +{ + return atf_env_get(name.c_str()); +} + +bool +impl::has(const std::string& name) +{ + return atf_env_has(name.c_str()); +} + +void +impl::set(const std::string& name, const std::string& val) +{ + atf_error_t err = atf_env_set(name.c_str(), val.c_str()); + if (atf_is_error(err)) + throw_atf_error(err); +} + +void +impl::unset(const std::string& name) +{ + atf_error_t err = atf_env_unset(name.c_str()); + if (atf_is_error(err)) + throw_atf_error(err); +} diff --git a/external/bsd/atf/dist/atf-c++/detail/env.hpp b/external/bsd/atf/dist/atf-c++/detail/env.hpp new file mode 100644 index 000000000..afdf69be5 --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/detail/env.hpp @@ -0,0 +1,84 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#if !defined(_ATF_CXX_ENV_HPP_) +#define _ATF_CXX_ENV_HPP_ + +#include + +namespace atf { +namespace env { + +// ------------------------------------------------------------------------ +// Free functions. +// ------------------------------------------------------------------------ + +//! +//! \brief Returns the value of an environment variable. +//! +//! Returns the value of the specified environment variable. The variable +//! must be defined. +//! +std::string get(const std::string&); + +//! +//! \brief Checks if the environment has a variable. +//! +//! Checks if the environment has a given variable. +//! +bool has(const std::string&); + +//! +//! \brief Sets an environment variable to a given value. +//! +//! Sets the specified environment variable to the given value. Note that +//! variables set to the empty string are different to undefined ones. +//! +//! Be aware that this alters the program's global status, which in general +//! is a bad thing to do due to the side-effects it may have. There are +//! some legitimate usages for this function, though. +//! +void set(const std::string&, const std::string&); + +//! +//! \brief Unsets an environment variable. +//! +//! Unsets the specified environment variable Note that undefined +//! variables are different to those defined but set to an empty value. +//! +//! Be aware that this alters the program's global status, which in general +//! is a bad thing to do due to the side-effects it may have. There are +//! some legitimate usages for this function, though. +//! +void unset(const std::string&); + +} // namespace env +} // namespace atf + +#endif // !defined(_ATF_CXX_ENV_HPP_) diff --git a/external/bsd/atf/dist/atf-c++/detail/env_test.cpp b/external/bsd/atf/dist/atf-c++/detail/env_test.cpp new file mode 100644 index 000000000..a7b681d14 --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/detail/env_test.cpp @@ -0,0 +1,91 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#include "../macros.hpp" + +#include "env.hpp" + +// ------------------------------------------------------------------------ +// Test cases for the free functions. +// ------------------------------------------------------------------------ + +ATF_TEST_CASE(has_get); +ATF_TEST_CASE_HEAD(has_get) +{ + set_md_var("descr", "Tests the has and get functions"); +} +ATF_TEST_CASE_BODY(has_get) +{ + ATF_REQUIRE(atf::env::has("PATH")); + ATF_REQUIRE(!atf::env::get("PATH").empty()); + + ATF_REQUIRE(!atf::env::has("_UNDEFINED_VARIABLE_")); +} + +ATF_TEST_CASE(set); +ATF_TEST_CASE_HEAD(set) +{ + set_md_var("descr", "Tests the set function"); +} +ATF_TEST_CASE_BODY(set) +{ + ATF_REQUIRE(atf::env::has("PATH")); + const std::string& oldval = atf::env::get("PATH"); + atf::env::set("PATH", "foo-bar"); + ATF_REQUIRE(atf::env::get("PATH") != oldval); + ATF_REQUIRE_EQ(atf::env::get("PATH"), "foo-bar"); + + ATF_REQUIRE(!atf::env::has("_UNDEFINED_VARIABLE_")); + atf::env::set("_UNDEFINED_VARIABLE_", "foo2-bar2"); + ATF_REQUIRE_EQ(atf::env::get("_UNDEFINED_VARIABLE_"), "foo2-bar2"); +} + +ATF_TEST_CASE(unset); +ATF_TEST_CASE_HEAD(unset) +{ + set_md_var("descr", "Tests the unset function"); +} +ATF_TEST_CASE_BODY(unset) +{ + ATF_REQUIRE(atf::env::has("PATH")); + atf::env::unset("PATH"); + ATF_REQUIRE(!atf::env::has("PATH")); +} + +// ------------------------------------------------------------------------ +// Main. +// ------------------------------------------------------------------------ + +ATF_INIT_TEST_CASES(tcs) +{ + // Add the test cases for the free functions. + ATF_ADD_TEST_CASE(tcs, has_get); + ATF_ADD_TEST_CASE(tcs, set); + ATF_ADD_TEST_CASE(tcs, unset); +} diff --git a/external/bsd/atf/dist/atf-c++/detail/exceptions.cpp b/external/bsd/atf/dist/atf-c++/detail/exceptions.cpp new file mode 100644 index 000000000..79c5b489e --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/detail/exceptions.cpp @@ -0,0 +1,157 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#if defined(HAVE_CONFIG_H) +#include "bconfig.h" +#endif + +#include +#include +#include +#include + +extern "C" { +#include "../../atf-c/error.h" +}; + +#include "exceptions.hpp" +#include "sanity.hpp" + +// ------------------------------------------------------------------------ +// The "system_error" type. +// ------------------------------------------------------------------------ + +atf::system_error::system_error(const std::string& who, + const std::string& message, + int sys_err) : + std::runtime_error(who + ": " + message), + m_sys_err(sys_err) +{ +} + +atf::system_error::~system_error(void) + throw() +{ +} + +int +atf::system_error::code(void) + const + throw() +{ + return m_sys_err; +} + +const char* +atf::system_error::what(void) + const + throw() +{ + try { + if (m_message.length() == 0) { + m_message = std::string(std::runtime_error::what()) + ": "; + m_message += ::strerror(m_sys_err); + } + + return m_message.c_str(); + } catch (...) { + return "Unable to format system_error message"; + } +} + +// ------------------------------------------------------------------------ +// Free functions. +// ------------------------------------------------------------------------ + +static +void +throw_libc_error(atf_error_t err) +{ + PRE(atf_error_is(err, "libc")); + + const int ecode = atf_libc_error_code(err); + const std::string msg = atf_libc_error_msg(err); + atf_error_free(err); + throw atf::system_error("XXX", msg, ecode); +} + +static +void +throw_no_memory_error(atf_error_t err) +{ + PRE(atf_error_is(err, "no_memory")); + + atf_error_free(err); + throw std::bad_alloc(); +} + +static +void +throw_unknown_error(atf_error_t err) +{ + PRE(atf_is_error(err)); + + static char buf[4096]; + atf_error_format(err, buf, sizeof(buf)); + atf_error_free(err); + throw std::runtime_error(buf); +} + +void +atf::throw_atf_error(atf_error_t err) +{ + static struct handler { + const char* m_name; + void (*m_func)(atf_error_t); + } handlers[] = { + { "libc", throw_libc_error }, + { "no_memory", throw_no_memory_error }, + { NULL, throw_unknown_error }, + }; + + PRE(atf_is_error(err)); + + handler* h = handlers; + while (h->m_name != NULL) { + if (atf_error_is(err, h->m_name)) { + h->m_func(err); + UNREACHABLE; + } else + h++; + } + // XXX: I'm not sure that raising an "unknown" error is a wise thing + // to do here. The C++ binding is supposed to have feature parity + // with the C one, so all possible errors raised by the C library + // should have their counterpart in the C++ library. Still, removing + // this will require some code auditing that I can't afford at the + // moment. + INV(h->m_name == NULL && h->m_func != NULL); + h->m_func(err); + UNREACHABLE; +} diff --git a/external/bsd/atf/dist/atf-c++/detail/exceptions.hpp b/external/bsd/atf/dist/atf-c++/detail/exceptions.hpp new file mode 100644 index 000000000..f655a84d8 --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/detail/exceptions.hpp @@ -0,0 +1,99 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#if !defined(_ATF_CXX_EXCEPTIONS_HPP_) +#define _ATF_CXX_EXCEPTIONS_HPP_ + +#include +#include + +extern "C" { +struct atf_error; +} + +namespace atf { + +template< class T > +class not_found_error : + public std::runtime_error +{ + T m_value; + +public: + not_found_error(const std::string& message, const T& value) throw(); + + virtual ~not_found_error(void) throw(); + + const T& get_value(void) const throw(); +}; + +template< class T > +inline +not_found_error< T >::not_found_error(const std::string& message, + const T& value) + throw() : + std::runtime_error(message), + m_value(value) +{ +} + +template< class T > +inline +not_found_error< T >::~not_found_error(void) + throw() +{ +} + +template< class T > +inline +const T& +not_found_error< T >::get_value(void) + const + throw() +{ + return m_value; +} + +class system_error : public std::runtime_error { + int m_sys_err; + mutable std::string m_message; + +public: + system_error(const std::string&, const std::string&, int); + ~system_error(void) throw(); + + int code(void) const throw(); + const char* what(void) const throw(); +}; + +void throw_atf_error(struct atf_error *); + +} // namespace atf + +#endif // !defined(_ATF_CXX_EXCEPTIONS_HPP_) diff --git a/external/bsd/atf/dist/atf-c++/detail/exceptions_test.cpp b/external/bsd/atf/dist/atf-c++/detail/exceptions_test.cpp new file mode 100644 index 000000000..821c192dd --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/detail/exceptions_test.cpp @@ -0,0 +1,148 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2009 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +extern "C" { +#include "../../atf-c/error.h" +} + +#include +#include + +#include "../macros.hpp" + +#include "exceptions.hpp" +#include "sanity.hpp" + +// ------------------------------------------------------------------------ +// The "test" error. +// ------------------------------------------------------------------------ + +extern "C" { + +struct test_error_data { + const char* m_msg; +}; +typedef struct test_error_data test_error_data_t; + +static +void +test_format(const atf_error_t err, char *buf, size_t buflen) +{ + const test_error_data_t* data; + + PRE(atf_error_is(err, "test")); + + data = static_cast< const test_error_data_t * >(atf_error_data(err)); + snprintf(buf, buflen, "Message: %s", data->m_msg); +} + +static +atf_error_t +test_error(const char* msg) +{ + atf_error_t err; + test_error_data_t data; + + data.m_msg = msg; + + err = atf_error_new("test", &data, sizeof(data), test_format); + + return err; +} + +} // extern + +// ------------------------------------------------------------------------ +// Tests cases for the free functions. +// ------------------------------------------------------------------------ + +ATF_TEST_CASE(throw_atf_error_libc); +ATF_TEST_CASE_HEAD(throw_atf_error_libc) +{ + set_md_var("descr", "Tests the throw_atf_error function when raising " + "a libc error"); +} +ATF_TEST_CASE_BODY(throw_atf_error_libc) +{ + try { + atf::throw_atf_error(atf_libc_error(1, "System error 1")); + } catch (const atf::system_error& e) { + ATF_REQUIRE(e.code() == 1); + ATF_REQUIRE(std::string(e.what()).find("System error 1") != + std::string::npos); + } catch (const std::exception& e) { + ATF_FAIL(std::string("Got unexpected exception: ") + e.what()); + } +} + +ATF_TEST_CASE(throw_atf_error_no_memory); +ATF_TEST_CASE_HEAD(throw_atf_error_no_memory) +{ + set_md_var("descr", "Tests the throw_atf_error function when raising " + "a no_memory error"); +} +ATF_TEST_CASE_BODY(throw_atf_error_no_memory) +{ + try { + atf::throw_atf_error(atf_no_memory_error()); + } catch (const std::bad_alloc&) { + } catch (const std::exception& e) { + ATF_FAIL(std::string("Got unexpected exception: ") + e.what()); + } +} + +ATF_TEST_CASE(throw_atf_error_unknown); +ATF_TEST_CASE_HEAD(throw_atf_error_unknown) +{ + set_md_var("descr", "Tests the throw_atf_error function when raising " + "an unknown error"); +} +ATF_TEST_CASE_BODY(throw_atf_error_unknown) +{ + try { + atf::throw_atf_error(test_error("The message")); + } catch (const std::runtime_error& e) { + const std::string msg = e.what(); + ATF_REQUIRE(msg.find("The message") != std::string::npos); + } catch (const std::exception& e) { + ATF_FAIL(std::string("Got unexpected exception: ") + e.what()); + } +} + +// ------------------------------------------------------------------------ +// Main. +// ------------------------------------------------------------------------ + +ATF_INIT_TEST_CASES(tcs) +{ + // Add the test cases for the free functions. + ATF_ADD_TEST_CASE(tcs, throw_atf_error_libc); + ATF_ADD_TEST_CASE(tcs, throw_atf_error_no_memory); + ATF_ADD_TEST_CASE(tcs, throw_atf_error_unknown); +} diff --git a/external/bsd/atf/dist/atf-c++/detail/expand.cpp b/external/bsd/atf/dist/atf-c++/detail/expand.cpp new file mode 100644 index 000000000..f6f9b6882 --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/detail/expand.cpp @@ -0,0 +1,81 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#include + +#include "expand.hpp" +#include "text.hpp" + +namespace impl = atf::expand; +#define IMPL_NAME "atf::expand" + +// ------------------------------------------------------------------------ +// Auxiliary functions. +// ------------------------------------------------------------------------ + +namespace { + +std::string +glob_to_regex(const std::string& glob) +{ + std::string regex; + regex.reserve(glob.length() * 2); + + regex += '^'; + for (std::string::const_iterator iter = glob.begin(); iter != glob.end(); + iter++) { + switch (*iter) { + case '*': regex += ".*"; break; + case '?': regex += "."; break; + default: regex += *iter; + } + } + regex += '$'; + + return regex; +} + +} // anonymous namespace + +// ------------------------------------------------------------------------ +// Free functions. +// ------------------------------------------------------------------------ + +bool +impl::is_glob(const std::string& glob) +{ + // NOTE: Keep this in sync with glob_to_regex! + return glob.find_first_of("*?") != std::string::npos; +} + +bool +impl::matches_glob(const std::string& glob, const std::string& candidate) +{ + return atf::text::match(candidate, glob_to_regex(glob)); +} diff --git a/external/bsd/atf/dist/atf-c++/detail/expand.hpp b/external/bsd/atf/dist/atf-c++/detail/expand.hpp new file mode 100644 index 000000000..7f4071ee8 --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/detail/expand.hpp @@ -0,0 +1,82 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#if !defined(_ATF_CXX_EXPAND_HPP_) +#define _ATF_CXX_EXPAND_HPP_ + +#include +#include + +namespace atf { +namespace expand { + +// ------------------------------------------------------------------------ +// Free functions. +// ------------------------------------------------------------------------ + +//! +//! \brief Checks if the given string is a glob pattern. +//! +//! Returns true if the given string is a glob pattern; i.e. if it contains +//! any character that will be expanded by expand_glob. +//! +bool is_glob(const std::string&); + +//! +//! \brief Checks if a given string matches a glob pattern. +//! +//! Given a glob pattern and a string, checks whether the former matches +//! the latter. Returns a boolean indicating this condition. +//! +bool matches_glob(const std::string&, const std::string&); + +//! +//! \brief Expands a glob pattern among multiple candidates. +//! +//! Given a glob pattern and a set of candidate strings, checks which of +//! those strings match the glob pattern and returns them. +//! +template< class T > +std::vector< std::string > expand_glob(const std::string& glob, + const T& candidates) +{ + std::vector< std::string > exps; + + for (typename T::const_iterator iter = candidates.begin(); + iter != candidates.end(); iter++) + if (matches_glob(glob, *iter)) + exps.push_back(*iter); + + return exps; +} + +} // namespace expand +} // namespace atf + +#endif // !defined(_ATF_CXX_EXPAND_HPP_) diff --git a/external/bsd/atf/dist/atf-c++/detail/expand_test.cpp b/external/bsd/atf/dist/atf-c++/detail/expand_test.cpp new file mode 100644 index 000000000..222ab3a92 --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/detail/expand_test.cpp @@ -0,0 +1,272 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#include + +#include "../macros.hpp" + +#include "expand.hpp" + +// XXX Many of the tests here are duplicated in atf-c/t_expand. Should +// find a way to easily share them, or maybe remove the ones here. + +// ------------------------------------------------------------------------ +// Test cases for the free functions. +// ------------------------------------------------------------------------ + +ATF_TEST_CASE(is_glob); +ATF_TEST_CASE_HEAD(is_glob) +{ + set_md_var("descr", "Tests the is_glob function."); +} +ATF_TEST_CASE_BODY(is_glob) +{ + using atf::expand::is_glob; + + ATF_REQUIRE(!is_glob("")); + ATF_REQUIRE(!is_glob("a")); + ATF_REQUIRE(!is_glob("foo")); + + ATF_REQUIRE( is_glob("*")); + ATF_REQUIRE( is_glob("a*")); + ATF_REQUIRE( is_glob("*a")); + ATF_REQUIRE( is_glob("a*b")); + + ATF_REQUIRE( is_glob("?")); + ATF_REQUIRE( is_glob("a?")); + ATF_REQUIRE( is_glob("?a")); + ATF_REQUIRE( is_glob("a?b")); +} + +ATF_TEST_CASE(matches_glob_plain); +ATF_TEST_CASE_HEAD(matches_glob_plain) +{ + set_md_var("descr", "Tests the matches_glob function by using plain " + "text strings as patterns only."); +} +ATF_TEST_CASE_BODY(matches_glob_plain) +{ + using atf::expand::matches_glob; + + ATF_REQUIRE( matches_glob("", "")); + ATF_REQUIRE(!matches_glob("a", "")); + ATF_REQUIRE(!matches_glob("", "a")); + + ATF_REQUIRE( matches_glob("ab", "ab")); + ATF_REQUIRE(!matches_glob("abc", "ab")); + ATF_REQUIRE(!matches_glob("ab", "abc")); +} + +ATF_TEST_CASE(matches_glob_star); +ATF_TEST_CASE_HEAD(matches_glob_star) +{ + set_md_var("descr", "Tests the matches_glob function by using the '*' " + "meta-character as part of the pattern."); +} +ATF_TEST_CASE_BODY(matches_glob_star) +{ + using atf::expand::matches_glob; + + ATF_REQUIRE( matches_glob("*", "")); + ATF_REQUIRE( matches_glob("*", "a")); + ATF_REQUIRE( matches_glob("*", "ab")); + + ATF_REQUIRE(!matches_glob("a*", "")); + ATF_REQUIRE( matches_glob("a*", "a")); + ATF_REQUIRE( matches_glob("a*", "aa")); + ATF_REQUIRE( matches_glob("a*", "ab")); + ATF_REQUIRE( matches_glob("a*", "abc")); + ATF_REQUIRE(!matches_glob("a*", "ba")); + + ATF_REQUIRE( matches_glob("*a", "a")); + ATF_REQUIRE( matches_glob("*a", "ba")); + ATF_REQUIRE(!matches_glob("*a", "bc")); + ATF_REQUIRE(!matches_glob("*a", "bac")); + + ATF_REQUIRE( matches_glob("*ab", "ab")); + ATF_REQUIRE( matches_glob("*ab", "aab")); + ATF_REQUIRE( matches_glob("*ab", "aaab")); + ATF_REQUIRE( matches_glob("*ab", "bab")); + ATF_REQUIRE(!matches_glob("*ab", "bcb")); + ATF_REQUIRE(!matches_glob("*ab", "bacb")); + + ATF_REQUIRE( matches_glob("a*b", "ab")); + ATF_REQUIRE( matches_glob("a*b", "acb")); + ATF_REQUIRE( matches_glob("a*b", "acdeb")); + ATF_REQUIRE(!matches_glob("a*b", "acdebz")); + ATF_REQUIRE(!matches_glob("a*b", "zacdeb")); +} + +ATF_TEST_CASE(matches_glob_question); +ATF_TEST_CASE_HEAD(matches_glob_question) +{ + set_md_var("descr", "Tests the matches_glob function by using the '?' " + "meta-character as part of the pattern."); +} +ATF_TEST_CASE_BODY(matches_glob_question) +{ + using atf::expand::matches_glob; + + ATF_REQUIRE(!matches_glob("?", "")); + ATF_REQUIRE( matches_glob("?", "a")); + ATF_REQUIRE(!matches_glob("?", "ab")); + + ATF_REQUIRE( matches_glob("?", "b")); + ATF_REQUIRE( matches_glob("?", "c")); + + ATF_REQUIRE( matches_glob("a?", "ab")); + ATF_REQUIRE( matches_glob("a?", "ac")); + ATF_REQUIRE(!matches_glob("a?", "ca")); + + ATF_REQUIRE( matches_glob("???", "abc")); + ATF_REQUIRE( matches_glob("???", "def")); + ATF_REQUIRE(!matches_glob("???", "a")); + ATF_REQUIRE(!matches_glob("???", "ab")); + ATF_REQUIRE(!matches_glob("???", "abcd")); +} + +ATF_TEST_CASE(expand_glob_base); +ATF_TEST_CASE_HEAD(expand_glob_base) +{ + set_md_var("descr", "Tests the expand_glob function with random " + "patterns."); +} +ATF_TEST_CASE_BODY(expand_glob_base) +{ + using atf::expand::expand_glob; + + std::vector< std::string > candidates; + candidates.push_back("foo"); + candidates.push_back("bar"); + candidates.push_back("baz"); + candidates.push_back("foobar"); + candidates.push_back("foobarbaz"); + candidates.push_back("foobarbazfoo"); + + std::vector< std::string > exps; + + exps = expand_glob("foo", candidates); + ATF_REQUIRE_EQ(exps.size(), 1); + ATF_REQUIRE(exps[0] == "foo"); + + exps = expand_glob("bar", candidates); + ATF_REQUIRE_EQ(exps.size(), 1); + ATF_REQUIRE(exps[0] == "bar"); + + exps = expand_glob("foo*", candidates); + ATF_REQUIRE_EQ(exps.size(), 4); + ATF_REQUIRE(exps[0] == "foo"); + ATF_REQUIRE(exps[1] == "foobar"); + ATF_REQUIRE(exps[2] == "foobarbaz"); + ATF_REQUIRE(exps[3] == "foobarbazfoo"); + + exps = expand_glob("*foo", candidates); + ATF_REQUIRE_EQ(exps.size(), 2); + ATF_REQUIRE(exps[0] == "foo"); + ATF_REQUIRE(exps[1] == "foobarbazfoo"); + + exps = expand_glob("*foo*", candidates); + ATF_REQUIRE_EQ(exps.size(), 4); + ATF_REQUIRE(exps[0] == "foo"); + ATF_REQUIRE(exps[1] == "foobar"); + ATF_REQUIRE(exps[2] == "foobarbaz"); + ATF_REQUIRE(exps[3] == "foobarbazfoo"); + + exps = expand_glob("ba", candidates); + ATF_REQUIRE_EQ(exps.size(), 0); + + exps = expand_glob("ba*", candidates); + ATF_REQUIRE_EQ(exps.size(), 2); + ATF_REQUIRE(exps[0] == "bar"); + ATF_REQUIRE(exps[1] == "baz"); + + exps = expand_glob("*ba", candidates); + ATF_REQUIRE_EQ(exps.size(), 0); + + exps = expand_glob("*ba*", candidates); + ATF_REQUIRE_EQ(exps.size(), 5); + ATF_REQUIRE(exps[0] == "bar"); + ATF_REQUIRE(exps[1] == "baz"); + ATF_REQUIRE(exps[2] == "foobar"); + ATF_REQUIRE(exps[3] == "foobarbaz"); + ATF_REQUIRE(exps[4] == "foobarbazfoo"); +} + +ATF_TEST_CASE(expand_glob_tps); +ATF_TEST_CASE_HEAD(expand_glob_tps) +{ + set_md_var("descr", "Tests the expand_glob function with patterns that " + "match typical test program names. This is just a subcase " + "of expand_base, but it is nice to make sure that it really " + "works."); +} +ATF_TEST_CASE_BODY(expand_glob_tps) +{ + using atf::expand::expand_glob; + + std::vector< std::string > candidates; + candidates.push_back("Atffile"); + candidates.push_back("h_foo"); + candidates.push_back("t_foo"); + candidates.push_back("t_bar"); + candidates.push_back("t_baz"); + candidates.push_back("foo_helper"); + candidates.push_back("foo_test"); + candidates.push_back("bar_test"); + candidates.push_back("baz_test"); + + std::vector< std::string > exps; + + exps = expand_glob("t_*", candidates); + ATF_REQUIRE_EQ(exps.size(), 3); + ATF_REQUIRE(exps[0] == "t_foo"); + ATF_REQUIRE(exps[1] == "t_bar"); + ATF_REQUIRE(exps[2] == "t_baz"); + + exps = expand_glob("*_test", candidates); + ATF_REQUIRE_EQ(exps.size(), 3); + ATF_REQUIRE(exps[0] == "foo_test"); + ATF_REQUIRE(exps[1] == "bar_test"); + ATF_REQUIRE(exps[2] == "baz_test"); +} + +// ------------------------------------------------------------------------ +// Main. +// ------------------------------------------------------------------------ + +ATF_INIT_TEST_CASES(tcs) +{ + // Add the tests for the free functions. + ATF_ADD_TEST_CASE(tcs, is_glob); + ATF_ADD_TEST_CASE(tcs, matches_glob_plain); + ATF_ADD_TEST_CASE(tcs, matches_glob_star); + ATF_ADD_TEST_CASE(tcs, matches_glob_question); + ATF_ADD_TEST_CASE(tcs, expand_glob_base); + ATF_ADD_TEST_CASE(tcs, expand_glob_tps); +} diff --git a/external/bsd/atf/dist/atf-c++/detail/fs.cpp b/external/bsd/atf/dist/atf-c++/detail/fs.cpp new file mode 100644 index 000000000..3517e261f --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/detail/fs.cpp @@ -0,0 +1,517 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#if defined(HAVE_CONFIG_H) +#include "bconfig.h" +#endif + +extern "C" { +#include +#include +#include +#include +#include +#include +#include +#include +} + +#include +#include +#include + +extern "C" { +#include "../../atf-c/error.h" +} + +#include "../utils.hpp" + +#include "exceptions.hpp" +#include "env.hpp" +#include "fs.hpp" +#include "process.hpp" +#include "sanity.hpp" +#include "text.hpp" + +namespace impl = atf::fs; +#define IMPL_NAME "atf::fs" + +// ------------------------------------------------------------------------ +// Auxiliary functions. +// ------------------------------------------------------------------------ + +static bool safe_access(const impl::path&, int, int); + +//! +//! \brief A controlled version of access(2). +//! +//! This function reimplements the standard access(2) system call to +//! safely control its exit status and raise an exception in case of +//! failure. +//! +static +bool +safe_access(const impl::path& p, int mode, int experr) +{ + bool ok; + + atf_error_t err = atf_fs_eaccess(p.c_path(), mode); + if (atf_is_error(err)) { + if (atf_error_is(err, "libc")) { + if (atf_libc_error_code(err) == experr) { + atf_error_free(err); + ok = false; + } else { + atf::throw_atf_error(err); + // XXX Silence warning; maybe throw_atf_error should be + // an exception and not a function. + ok = false; + } + } else { + atf::throw_atf_error(err); + // XXX Silence warning; maybe throw_atf_error should be + // an exception and not a function. + ok = false; + } + } else + ok = true; + + return ok; +} + +// ------------------------------------------------------------------------ +// The "path" class. +// ------------------------------------------------------------------------ + +impl::path::path(const std::string& s) +{ + atf_error_t err = atf_fs_path_init_fmt(&m_path, "%s", s.c_str()); + if (atf_is_error(err)) + throw_atf_error(err); +} + +impl::path::path(const path& p) +{ + atf_error_t err = atf_fs_path_copy(&m_path, &p.m_path); + if (atf_is_error(err)) + throw_atf_error(err); +} + +impl::path::path(const atf_fs_path_t *p) +{ + atf_error_t err = atf_fs_path_copy(&m_path, p); + if (atf_is_error(err)) + throw_atf_error(err); +} + +impl::path::~path(void) +{ + atf_fs_path_fini(&m_path); +} + +const char* +impl::path::c_str(void) + const +{ + return atf_fs_path_cstring(&m_path); +} + +const atf_fs_path_t* +impl::path::c_path(void) + const +{ + return &m_path; +} + +std::string +impl::path::str(void) + const +{ + return c_str(); +} + +bool +impl::path::is_absolute(void) + const +{ + return atf_fs_path_is_absolute(&m_path); +} + +bool +impl::path::is_root(void) + const +{ + return atf_fs_path_is_root(&m_path); +} + +impl::path +impl::path::branch_path(void) + const +{ + atf_fs_path_t bp; + atf_error_t err; + + err = atf_fs_path_branch_path(&m_path, &bp); + if (atf_is_error(err)) + throw_atf_error(err); + + path p(atf_fs_path_cstring(&bp)); + atf_fs_path_fini(&bp); + return p; +} + +std::string +impl::path::leaf_name(void) + const +{ + atf_dynstr_t ln; + atf_error_t err; + + err = atf_fs_path_leaf_name(&m_path, &ln); + if (atf_is_error(err)) + throw_atf_error(err); + + std::string s(atf_dynstr_cstring(&ln)); + atf_dynstr_fini(&ln); + return s; +} + +impl::path +impl::path::to_absolute(void) + const +{ + atf_fs_path_t pa; + + atf_error_t err = atf_fs_path_to_absolute(&m_path, &pa); + if (atf_is_error(err)) + throw_atf_error(err); + + path p(atf_fs_path_cstring(&pa)); + atf_fs_path_fini(&pa); + return p; +} + +impl::path& +impl::path::operator=(const path& p) +{ + atf_fs_path_t tmp; + + atf_error_t err = atf_fs_path_init_fmt(&tmp, "%s", p.c_str()); + if (atf_is_error(err)) + throw_atf_error(err); + else { + atf_fs_path_fini(&m_path); + m_path = tmp; + } + + return *this; +} + +bool +impl::path::operator==(const path& p) + const +{ + return atf_equal_fs_path_fs_path(&m_path, &p.m_path); +} + +bool +impl::path::operator!=(const path& p) + const +{ + return !atf_equal_fs_path_fs_path(&m_path, &p.m_path); +} + +impl::path +impl::path::operator/(const std::string& p) + const +{ + path p2 = *this; + + atf_error_t err = atf_fs_path_append_fmt(&p2.m_path, "%s", p.c_str()); + if (atf_is_error(err)) + throw_atf_error(err); + + return p2; +} + +impl::path +impl::path::operator/(const path& p) + const +{ + path p2 = *this; + + atf_error_t err = atf_fs_path_append_fmt(&p2.m_path, "%s", + atf_fs_path_cstring(&p.m_path)); + if (atf_is_error(err)) + throw_atf_error(err); + + return p2; +} + +bool +impl::path::operator<(const path& p) + const +{ + const char *s1 = atf_fs_path_cstring(&m_path); + const char *s2 = atf_fs_path_cstring(&p.m_path); + return std::strcmp(s1, s2) < 0; +} + +// ------------------------------------------------------------------------ +// The "file_info" class. +// ------------------------------------------------------------------------ + +const int impl::file_info::blk_type = atf_fs_stat_blk_type; +const int impl::file_info::chr_type = atf_fs_stat_chr_type; +const int impl::file_info::dir_type = atf_fs_stat_dir_type; +const int impl::file_info::fifo_type = atf_fs_stat_fifo_type; +const int impl::file_info::lnk_type = atf_fs_stat_lnk_type; +const int impl::file_info::reg_type = atf_fs_stat_reg_type; +const int impl::file_info::sock_type = atf_fs_stat_sock_type; +const int impl::file_info::wht_type = atf_fs_stat_wht_type; + +impl::file_info::file_info(const path& p) +{ + atf_error_t err; + + err = atf_fs_stat_init(&m_stat, p.c_path()); + if (atf_is_error(err)) + throw_atf_error(err); +} + +impl::file_info::file_info(const file_info& fi) +{ + atf_fs_stat_copy(&m_stat, &fi.m_stat); +} + +impl::file_info::~file_info(void) +{ + atf_fs_stat_fini(&m_stat); +} + +dev_t +impl::file_info::get_device(void) + const +{ + return atf_fs_stat_get_device(&m_stat); +} + +ino_t +impl::file_info::get_inode(void) + const +{ + return atf_fs_stat_get_inode(&m_stat); +} + +mode_t +impl::file_info::get_mode(void) + const +{ + return atf_fs_stat_get_mode(&m_stat); +} + +off_t +impl::file_info::get_size(void) + const +{ + return atf_fs_stat_get_size(&m_stat); +} + +int +impl::file_info::get_type(void) + const +{ + return atf_fs_stat_get_type(&m_stat); +} + +bool +impl::file_info::is_owner_readable(void) + const +{ + return atf_fs_stat_is_owner_readable(&m_stat); +} + +bool +impl::file_info::is_owner_writable(void) + const +{ + return atf_fs_stat_is_owner_writable(&m_stat); +} + +bool +impl::file_info::is_owner_executable(void) + const +{ + return atf_fs_stat_is_owner_executable(&m_stat); +} + +bool +impl::file_info::is_group_readable(void) + const +{ + return atf_fs_stat_is_group_readable(&m_stat); +} + +bool +impl::file_info::is_group_writable(void) + const +{ + return atf_fs_stat_is_group_writable(&m_stat); +} + +bool +impl::file_info::is_group_executable(void) + const +{ + return atf_fs_stat_is_group_executable(&m_stat); +} + +bool +impl::file_info::is_other_readable(void) + const +{ + return atf_fs_stat_is_other_readable(&m_stat); +} + +bool +impl::file_info::is_other_writable(void) + const +{ + return atf_fs_stat_is_other_writable(&m_stat); +} + +bool +impl::file_info::is_other_executable(void) + const +{ + return atf_fs_stat_is_other_executable(&m_stat); +} + +// ------------------------------------------------------------------------ +// The "directory" class. +// ------------------------------------------------------------------------ + +impl::directory::directory(const path& p) +{ + DIR* dp = ::opendir(p.c_str()); + if (dp == NULL) + throw system_error(IMPL_NAME "::directory::directory(" + + p.str() + ")", "opendir(3) failed", errno); + + struct dirent* dep; + while ((dep = ::readdir(dp)) != NULL) { + path entryp = p / dep->d_name; + insert(value_type(dep->d_name, file_info(entryp))); + } + + if (::closedir(dp) == -1) + throw system_error(IMPL_NAME "::directory::directory(" + + p.str() + ")", "closedir(3) failed", errno); +} + +std::set< std::string > +impl::directory::names(void) + const +{ + std::set< std::string > ns; + + for (const_iterator iter = begin(); iter != end(); iter++) + ns.insert((*iter).first); + + return ns; +} + +// ------------------------------------------------------------------------ +// Free functions. +// ------------------------------------------------------------------------ + +bool +impl::exists(const path& p) +{ + atf_error_t err; + bool b; + + err = atf_fs_exists(p.c_path(), &b); + if (atf_is_error(err)) + throw_atf_error(err); + + return b; +} + +bool +impl::have_prog_in_path(const std::string& prog) +{ + PRE(prog.find('/') == std::string::npos); + + // Do not bother to provide a default value for PATH. If it is not + // there something is broken in the user's environment. + if (!atf::env::has("PATH")) + throw std::runtime_error("PATH not defined in the environment"); + std::vector< std::string > dirs = + atf::text::split(atf::env::get("PATH"), ":"); + + bool found = false; + for (std::vector< std::string >::const_iterator iter = dirs.begin(); + !found && iter != dirs.end(); iter++) { + const path& dir = path(*iter); + + if (is_executable(dir / prog)) + found = true; + } + return found; +} + +bool +impl::is_executable(const path& p) +{ + if (!exists(p)) + return false; + return safe_access(p, atf_fs_access_x, EACCES); +} + +void +impl::remove(const path& p) +{ + if (file_info(p).get_type() == file_info::dir_type) + throw atf::system_error(IMPL_NAME "::remove(" + p.str() + ")", + "Is a directory", + EPERM); + if (::unlink(p.c_str()) == -1) + throw atf::system_error(IMPL_NAME "::remove(" + p.str() + ")", + "unlink(" + p.str() + ") failed", + errno); +} + +void +impl::rmdir(const path& p) +{ + atf_error_t err = atf_fs_rmdir(p.c_path()); + if (atf_is_error(err)) + throw_atf_error(err); +} diff --git a/external/bsd/atf/dist/atf-c++/detail/fs.hpp b/external/bsd/atf/dist/atf-c++/detail/fs.hpp new file mode 100644 index 000000000..4ffb39b2a --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/detail/fs.hpp @@ -0,0 +1,391 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#if !defined(_ATF_CXX_FS_HPP_) +#define _ATF_CXX_FS_HPP_ + +extern "C" { +#include +} + +#include +#include +#include +#include +#include +#include + +extern "C" { +#include "../../atf-c/detail/fs.h" +} + +namespace atf { + +namespace io { +class systembuf; +} // namespace io + +namespace fs { + +// ------------------------------------------------------------------------ +// The "path" class. +// ------------------------------------------------------------------------ + +//! +//! \brief A class to represent a path to a file. +//! +//! The path class represents the route to a file or directory in the +//! file system. All file manipulation operations use this class to +//! represent their arguments as it takes care of normalizing user-provided +//! strings and ensures they are valid. +//! +//! It is important to note that the file pointed to by a path need not +//! exist. +//! +class path { + //! + //! \brief Internal representation of a path. + //! + atf_fs_path_t m_path; + +public: + //! \brief Constructs a new path from a user-provided string. + //! + //! This constructor takes a string, either provided by the program's + //! code or by the user and constructs a new path object. The string + //! is normalized to not contain multiple delimiters together and to + //! remove any trailing one. + //! + //! The input string cannot be empty. + //! + explicit path(const std::string&); + + //! + //! \brief Copy constructor. + //! + path(const path&); + + //! + //! \brief Copy constructor. + //! + path(const atf_fs_path_t *); + + //! + //! \brief Destructor for the path class. + //! + ~path(void); + + //! + //! \brief Returns a pointer to a C-style string representing this path. + //! + const char* c_str(void) const; + + //! + //! \brief Returns a pointer to the implementation data. + //! + const atf_fs_path_t* c_path(void) const; + + //! + //! \brief Returns a string representing this path. + //! XXX Really needed? + //! + std::string str(void) const; + + //! + //! \brief Returns the branch path of this path. + //! + //! Calculates and returns the branch path of this path. In other + //! words, it returns what the standard ::dirname function would return. + //! + path branch_path(void) const; + + //! + //! \brief Returns the leaf name of this path. + //! + //! Calculates and returns the leaf name of this path. In other words, + //! it returns what the standard ::basename function would return. + //! + std::string leaf_name(void) const; + + //! + //! \brief Checks whether this path is absolute or not. + //! + //! Returns a boolean indicating if this is an absolute path or not; + //! i.e. if it starts with a slash. + //! + bool is_absolute(void) const; + + //! + //! \brief Checks whether this path points to the root directory or not. + //! + //! Returns a boolean indicating if this is path points to the root + //! directory or not. The checks made by this are extremely simple (so + //! the results cannot always be trusted) but they are enough for our + //! modest sanity-checking needs. I.e. "/../" could return false. + //! + bool is_root(void) const; + + //! + //! \brief Converts the path to be absolute. + //! + //! \pre The path was not absolute. + //! + path to_absolute(void) const; + + //! + //! \brief Assignment operator. + //! + path& operator=(const path&); + + //! + //! \brief Checks if two paths are equal. + //! + bool operator==(const path&) const; + + //! + //! \brief Checks if two paths are different. + //! + bool operator!=(const path&) const; + + //! + //! \brief Concatenates a path with a string. + //! + //! Constructs a new path object that is the concatenation of the + //! left-hand path with the right-hand string. The string is normalized + //! before the concatenation, and a path delimiter is introduced between + //! the two components if needed. + //! + path operator/(const std::string&) const; + + //! + //! \brief Concatenates a path with another path. + //! + //! Constructs a new path object that is the concatenation of the + //! left-hand path with the right-hand one. A path delimiter is + //! introduced between the two components if needed. + //! + path operator/(const path&) const; + + //! + //! \brief Checks if a path has to be sorted before another one + //! lexicographically. + //! + bool operator<(const path&) const; +}; + +// ------------------------------------------------------------------------ +// The "file_info" class. +// ------------------------------------------------------------------------ + +class directory; + +//! +//! \brief A class that contains information about a file. +//! +//! The file_info class holds information about an specific file that +//! exists in the file system. +//! +class file_info { + atf_fs_stat_t m_stat; + +public: + //! + //! \brief The file's type. + //! + static const int blk_type; + static const int chr_type; + static const int dir_type; + static const int fifo_type; + static const int lnk_type; + static const int reg_type; + static const int sock_type; + static const int wht_type; + + //! + //! \brief Constructs a new file_info based on a given file. + //! + //! This constructor creates a new file_info object and fills it with + //! the data returned by ::stat when run on the given file, which must + //! exist. + //! + explicit file_info(const path&); + + //! + //! \brief The copy constructor. + //! + file_info(const file_info&); + + //! + //! \brief The destructor. + //! + ~file_info(void); + + //! + //! \brief Returns the device containing the file. + //! + dev_t get_device(void) const; + + //! + //! \brief Returns the file's inode. + //! + ino_t get_inode(void) const; + + //! + //! \brief Returns the file's permissions. + //! + mode_t get_mode(void) const; + + //! + //! \brief Returns the file's size. + //! + off_t get_size(void) const; + + //! + //! \brief Returns the file's type. + //! + int get_type(void) const; + + //! + //! \brief Returns whether the file is readable by its owner or not. + //! + bool is_owner_readable(void) const; + + //! + //! \brief Returns whether the file is writable by its owner or not. + //! + bool is_owner_writable(void) const; + + //! + //! \brief Returns whether the file is executable by its owner or not. + //! + bool is_owner_executable(void) const; + + //! + //! \brief Returns whether the file is readable by the users belonging + //! to its group or not. + //! + bool is_group_readable(void) const; + + //! + //! \brief Returns whether the file is writable the users belonging to + //! its group or not. + //! + bool is_group_writable(void) const; + + //! + //! \brief Returns whether the file is executable by the users + //! belonging to its group or not. + //! + bool is_group_executable(void) const; + + //! + //! \brief Returns whether the file is readable by people different + //! than the owner and those belonging to the group or not. + //! + bool is_other_readable(void) const; + + //! + //! \brief Returns whether the file is write by people different + //! than the owner and those belonging to the group or not. + //! + bool is_other_writable(void) const; + + //! + //! \brief Returns whether the file is executable by people different + //! than the owner and those belonging to the group or not. + //! + bool is_other_executable(void) const; +}; + +// ------------------------------------------------------------------------ +// The "directory" class. +// ------------------------------------------------------------------------ + +//! +//! \brief A class representing a file system directory. +//! +//! The directory class represents a group of files in the file system and +//! corresponds to exactly one directory. +//! +class directory : public std::map< std::string, file_info > { +public: + //! + //! \brief Constructs a new directory. + //! + //! Constructs a new directory object representing the given path. + //! The directory must exist at creation time as the contents of the + //! class are gathered from it. + //! + directory(const path&); + + //! + //! \brief Returns the file names of the files in the directory. + //! + //! Returns the leaf names of all files contained in the directory. + //! I.e. the keys of the directory map. + //! + std::set< std::string > names(void) const; +}; + +// ------------------------------------------------------------------------ +// Free functions. +// ------------------------------------------------------------------------ + +//! +//! \brief Checks if the given path exists. +//! +bool exists(const path&); + +//! +//! \brief Looks for the given program in the PATH. +//! +//! Given a program name (without slashes) looks for it in the path and +//! returns its full path name if found, otherwise an empty path. +//! +bool have_prog_in_path(const std::string&); + +//! +//! \brief Checks if the given path exists, is accessible and is executable. +//! +bool is_executable(const path&); + +//! +//! \brief Removes a given file. +//! +void remove(const path&); + +//! +//! \brief Removes an empty directory. +//! +void rmdir(const path&); + +} // namespace fs +} // namespace atf + +#endif // !defined(_ATF_CXX_FS_HPP_) diff --git a/external/bsd/atf/dist/atf-c++/detail/fs_test.cpp b/external/bsd/atf/dist/atf-c++/detail/fs_test.cpp new file mode 100644 index 000000000..6cf9bf6c6 --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/detail/fs_test.cpp @@ -0,0 +1,545 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +extern "C" { +#include +#include +} + +#include +#include +#include + +#include "../macros.hpp" + +#include "exceptions.hpp" +#include "fs.hpp" + +// ------------------------------------------------------------------------ +// Auxiliary functions. +// ------------------------------------------------------------------------ + +static +void +create_files(void) +{ + ::mkdir("files", 0755); + ::mkdir("files/dir", 0755); + + std::ofstream os("files/reg"); + os.close(); + + // TODO: Should create all other file types (blk, chr, fifo, lnk, sock) + // and test for them... but the underlying file system may not support + // most of these. Specially as we are working on /tmp, which can be + // mounted with flags such as "nodev". See how to deal with this + // situation. +} + +// ------------------------------------------------------------------------ +// Test cases for the "path" class. +// ------------------------------------------------------------------------ + +ATF_TEST_CASE(path_normalize); +ATF_TEST_CASE_HEAD(path_normalize) +{ + set_md_var("descr", "Tests the path's normalization"); +} +ATF_TEST_CASE_BODY(path_normalize) +{ + using atf::fs::path; + + ATF_REQUIRE_EQ(path(".").str(), "."); + ATF_REQUIRE_EQ(path("..").str(), ".."); + + ATF_REQUIRE_EQ(path("foo").str(), "foo"); + ATF_REQUIRE_EQ(path("foo/bar").str(), "foo/bar"); + ATF_REQUIRE_EQ(path("foo/bar/").str(), "foo/bar"); + + ATF_REQUIRE_EQ(path("/foo").str(), "/foo"); + ATF_REQUIRE_EQ(path("/foo/bar").str(), "/foo/bar"); + ATF_REQUIRE_EQ(path("/foo/bar/").str(), "/foo/bar"); + + ATF_REQUIRE_EQ(path("///foo").str(), "/foo"); + ATF_REQUIRE_EQ(path("///foo///bar").str(), "/foo/bar"); + ATF_REQUIRE_EQ(path("///foo///bar///").str(), "/foo/bar"); +} + +ATF_TEST_CASE(path_is_absolute); +ATF_TEST_CASE_HEAD(path_is_absolute) +{ + set_md_var("descr", "Tests the path::is_absolute function"); +} +ATF_TEST_CASE_BODY(path_is_absolute) +{ + using atf::fs::path; + + ATF_REQUIRE( path("/").is_absolute()); + ATF_REQUIRE( path("////").is_absolute()); + ATF_REQUIRE( path("////a").is_absolute()); + ATF_REQUIRE( path("//a//").is_absolute()); + ATF_REQUIRE(!path("a////").is_absolute()); + ATF_REQUIRE(!path("../foo").is_absolute()); +} + +ATF_TEST_CASE(path_is_root); +ATF_TEST_CASE_HEAD(path_is_root) +{ + set_md_var("descr", "Tests the path::is_root function"); +} +ATF_TEST_CASE_BODY(path_is_root) +{ + using atf::fs::path; + + ATF_REQUIRE( path("/").is_root()); + ATF_REQUIRE( path("////").is_root()); + ATF_REQUIRE(!path("////a").is_root()); + ATF_REQUIRE(!path("//a//").is_root()); + ATF_REQUIRE(!path("a////").is_root()); + ATF_REQUIRE(!path("../foo").is_root()); +} + +ATF_TEST_CASE(path_branch_path); +ATF_TEST_CASE_HEAD(path_branch_path) +{ + set_md_var("descr", "Tests the path::branch_path function"); +} +ATF_TEST_CASE_BODY(path_branch_path) +{ + using atf::fs::path; + + ATF_REQUIRE_EQ(path(".").branch_path().str(), "."); + ATF_REQUIRE_EQ(path("foo").branch_path().str(), "."); + ATF_REQUIRE_EQ(path("foo/bar").branch_path().str(), "foo"); + ATF_REQUIRE_EQ(path("/foo").branch_path().str(), "/"); + ATF_REQUIRE_EQ(path("/foo/bar").branch_path().str(), "/foo"); +} + +ATF_TEST_CASE(path_leaf_name); +ATF_TEST_CASE_HEAD(path_leaf_name) +{ + set_md_var("descr", "Tests the path::leaf_name function"); +} +ATF_TEST_CASE_BODY(path_leaf_name) +{ + using atf::fs::path; + + ATF_REQUIRE_EQ(path(".").leaf_name(), "."); + ATF_REQUIRE_EQ(path("foo").leaf_name(), "foo"); + ATF_REQUIRE_EQ(path("foo/bar").leaf_name(), "bar"); + ATF_REQUIRE_EQ(path("/foo").leaf_name(), "foo"); + ATF_REQUIRE_EQ(path("/foo/bar").leaf_name(), "bar"); +} + +ATF_TEST_CASE(path_compare_equal); +ATF_TEST_CASE_HEAD(path_compare_equal) +{ + set_md_var("descr", "Tests the comparison for equality between paths"); +} +ATF_TEST_CASE_BODY(path_compare_equal) +{ + using atf::fs::path; + + ATF_REQUIRE(path("/") == path("///")); + ATF_REQUIRE(path("/a") == path("///a")); + ATF_REQUIRE(path("/a") == path("///a///")); + + ATF_REQUIRE(path("a/b/c") == path("a//b//c")); + ATF_REQUIRE(path("a/b/c") == path("a//b//c///")); +} + +ATF_TEST_CASE(path_compare_different); +ATF_TEST_CASE_HEAD(path_compare_different) +{ + set_md_var("descr", "Tests the comparison for difference between paths"); +} +ATF_TEST_CASE_BODY(path_compare_different) +{ + using atf::fs::path; + + ATF_REQUIRE(path("/") != path("//a/")); + ATF_REQUIRE(path("/a") != path("a///")); + + ATF_REQUIRE(path("a/b/c") != path("a/b")); + ATF_REQUIRE(path("a/b/c") != path("a//b")); + ATF_REQUIRE(path("a/b/c") != path("/a/b/c")); + ATF_REQUIRE(path("a/b/c") != path("/a//b//c")); +} + +ATF_TEST_CASE(path_concat); +ATF_TEST_CASE_HEAD(path_concat) +{ + set_md_var("descr", "Tests the concatenation of multiple paths"); +} +ATF_TEST_CASE_BODY(path_concat) +{ + using atf::fs::path; + + ATF_REQUIRE_EQ((path("foo") / "bar").str(), "foo/bar"); + ATF_REQUIRE_EQ((path("foo/") / "/bar").str(), "foo/bar"); + ATF_REQUIRE_EQ((path("foo/") / "/bar/baz").str(), "foo/bar/baz"); + ATF_REQUIRE_EQ((path("foo/") / "///bar///baz").str(), "foo/bar/baz"); +} + +ATF_TEST_CASE(path_to_absolute); +ATF_TEST_CASE_HEAD(path_to_absolute) +{ + set_md_var("descr", "Tests the conversion of a relative path to an " + "absolute one"); +} +ATF_TEST_CASE_BODY(path_to_absolute) +{ + using atf::fs::file_info; + using atf::fs::path; + + create_files(); + + { + const path p("."); + path pa = p.to_absolute(); + ATF_REQUIRE(pa.is_absolute()); + + file_info fi(p); + file_info fia(pa); + ATF_REQUIRE_EQ(fi.get_device(), fia.get_device()); + ATF_REQUIRE_EQ(fi.get_inode(), fia.get_inode()); + } + + { + const path p("files/reg"); + path pa = p.to_absolute(); + ATF_REQUIRE(pa.is_absolute()); + + file_info fi(p); + file_info fia(pa); + ATF_REQUIRE_EQ(fi.get_device(), fia.get_device()); + ATF_REQUIRE_EQ(fi.get_inode(), fia.get_inode()); + } +} + +ATF_TEST_CASE(path_op_less); +ATF_TEST_CASE_HEAD(path_op_less) +{ + set_md_var("descr", "Tests that the path's less-than operator works"); +} +ATF_TEST_CASE_BODY(path_op_less) +{ + using atf::fs::path; + + create_files(); + + ATF_REQUIRE(!(path("aaa") < path("aaa"))); + + ATF_REQUIRE( path("aab") < path("abc")); + ATF_REQUIRE(!(path("abc") < path("aab"))); +} + +// ------------------------------------------------------------------------ +// Test cases for the "directory" class. +// ------------------------------------------------------------------------ + +ATF_TEST_CASE(directory_read); +ATF_TEST_CASE_HEAD(directory_read) +{ + set_md_var("descr", "Tests the directory class creation, which reads " + "the contents of a directory"); +} +ATF_TEST_CASE_BODY(directory_read) +{ + using atf::fs::directory; + using atf::fs::path; + + create_files(); + + directory d(path("files")); + ATF_REQUIRE_EQ(d.size(), 4); + ATF_REQUIRE(d.find(".") != d.end()); + ATF_REQUIRE(d.find("..") != d.end()); + ATF_REQUIRE(d.find("dir") != d.end()); + ATF_REQUIRE(d.find("reg") != d.end()); +} + +ATF_TEST_CASE(directory_file_info); +ATF_TEST_CASE_HEAD(directory_file_info) +{ + set_md_var("descr", "Tests that the file_info objects attached to the " + "directory are valid"); +} +ATF_TEST_CASE_BODY(directory_file_info) +{ + using atf::fs::directory; + using atf::fs::file_info; + using atf::fs::path; + + create_files(); + + directory d(path("files")); + + { + directory::const_iterator iter = d.find("dir"); + ATF_REQUIRE(iter != d.end()); + const file_info& fi = (*iter).second; + ATF_REQUIRE(fi.get_type() == file_info::dir_type); + } + + { + directory::const_iterator iter = d.find("reg"); + ATF_REQUIRE(iter != d.end()); + const file_info& fi = (*iter).second; + ATF_REQUIRE(fi.get_type() == file_info::reg_type); + } +} + +ATF_TEST_CASE(directory_names); +ATF_TEST_CASE_HEAD(directory_names) +{ + set_md_var("descr", "Tests the directory's names method"); +} +ATF_TEST_CASE_BODY(directory_names) +{ + using atf::fs::directory; + using atf::fs::path; + + create_files(); + + directory d(path("files")); + std::set< std::string > ns = d.names(); + ATF_REQUIRE_EQ(ns.size(), 4); + ATF_REQUIRE(ns.find(".") != ns.end()); + ATF_REQUIRE(ns.find("..") != ns.end()); + ATF_REQUIRE(ns.find("dir") != ns.end()); + ATF_REQUIRE(ns.find("reg") != ns.end()); +} + +// ------------------------------------------------------------------------ +// Test cases for the "file_info" class. +// ------------------------------------------------------------------------ + +ATF_TEST_CASE(file_info_stat); +ATF_TEST_CASE_HEAD(file_info_stat) +{ + set_md_var("descr", "Tests the file_info creation and its basic contents"); +} +ATF_TEST_CASE_BODY(file_info_stat) +{ + using atf::fs::file_info; + using atf::fs::path; + + create_files(); + + { + path p("files/dir"); + file_info fi(p); + ATF_REQUIRE(fi.get_type() == file_info::dir_type); + } + + { + path p("files/reg"); + file_info fi(p); + ATF_REQUIRE(fi.get_type() == file_info::reg_type); + } +} + +ATF_TEST_CASE(file_info_perms); +ATF_TEST_CASE_HEAD(file_info_perms) +{ + set_md_var("descr", "Tests the file_info methods to get the file's " + "permissions"); +} +ATF_TEST_CASE_BODY(file_info_perms) +{ + using atf::fs::file_info; + using atf::fs::path; + + path p("file"); + + std::ofstream os(p.c_str()); + os.close(); + +#define perms(ur, uw, ux, gr, gw, gx, othr, othw, othx) \ + { \ + file_info fi(p); \ + ATF_REQUIRE(fi.is_owner_readable() == ur); \ + ATF_REQUIRE(fi.is_owner_writable() == uw); \ + ATF_REQUIRE(fi.is_owner_executable() == ux); \ + ATF_REQUIRE(fi.is_group_readable() == gr); \ + ATF_REQUIRE(fi.is_group_writable() == gw); \ + ATF_REQUIRE(fi.is_group_executable() == gx); \ + ATF_REQUIRE(fi.is_other_readable() == othr); \ + ATF_REQUIRE(fi.is_other_writable() == othw); \ + ATF_REQUIRE(fi.is_other_executable() == othx); \ + } + + ::chmod(p.c_str(), 0000); + perms(false, false, false, false, false, false, false, false, false); + + ::chmod(p.c_str(), 0001); + perms(false, false, false, false, false, false, false, false, true); + + ::chmod(p.c_str(), 0010); + perms(false, false, false, false, false, true, false, false, false); + + ::chmod(p.c_str(), 0100); + perms(false, false, true, false, false, false, false, false, false); + + ::chmod(p.c_str(), 0002); + perms(false, false, false, false, false, false, false, true, false); + + ::chmod(p.c_str(), 0020); + perms(false, false, false, false, true, false, false, false, false); + + ::chmod(p.c_str(), 0200); + perms(false, true, false, false, false, false, false, false, false); + + ::chmod(p.c_str(), 0004); + perms(false, false, false, false, false, false, true, false, false); + + ::chmod(p.c_str(), 0040); + perms(false, false, false, true, false, false, false, false, false); + + ::chmod(p.c_str(), 0400); + perms(true, false, false, false, false, false, false, false, false); + + ::chmod(p.c_str(), 0644); + perms(true, true, false, true, false, false, true, false, false); + + ::chmod(p.c_str(), 0755); + perms(true, true, true, true, false, true, true, false, true); + + ::chmod(p.c_str(), 0777); + perms(true, true, true, true, true, true, true, true, true); + +#undef perms +} + +// ------------------------------------------------------------------------ +// Test cases for the free functions. +// ------------------------------------------------------------------------ + +ATF_TEST_CASE(exists); +ATF_TEST_CASE_HEAD(exists) +{ + set_md_var("descr", "Tests the exists function"); +} +ATF_TEST_CASE_BODY(exists) +{ + using atf::fs::exists; + using atf::fs::path; + + create_files(); + + ATF_REQUIRE( exists(path("files"))); + ATF_REQUIRE(!exists(path("file"))); + ATF_REQUIRE(!exists(path("files2"))); + + ATF_REQUIRE( exists(path("files/."))); + ATF_REQUIRE( exists(path("files/.."))); + ATF_REQUIRE( exists(path("files/dir"))); + ATF_REQUIRE( exists(path("files/reg"))); + ATF_REQUIRE(!exists(path("files/foo"))); +} + +ATF_TEST_CASE(is_executable); +ATF_TEST_CASE_HEAD(is_executable) +{ + set_md_var("descr", "Tests the is_executable function"); +} +ATF_TEST_CASE_BODY(is_executable) +{ + using atf::fs::is_executable; + using atf::fs::path; + + create_files(); + + ATF_REQUIRE( is_executable(path("files"))); + ATF_REQUIRE( is_executable(path("files/."))); + ATF_REQUIRE( is_executable(path("files/.."))); + ATF_REQUIRE( is_executable(path("files/dir"))); + + ATF_REQUIRE(!is_executable(path("non-existent"))); + + ATF_REQUIRE(!is_executable(path("files/reg"))); + ATF_REQUIRE(::chmod("files/reg", 0755) != -1); + ATF_REQUIRE( is_executable(path("files/reg"))); +} + +ATF_TEST_CASE(remove); +ATF_TEST_CASE_HEAD(remove) +{ + set_md_var("descr", "Tests the remove function"); +} +ATF_TEST_CASE_BODY(remove) +{ + using atf::fs::exists; + using atf::fs::path; + using atf::fs::remove; + + create_files(); + + ATF_REQUIRE( exists(path("files/reg"))); + remove(path("files/reg")); + ATF_REQUIRE(!exists(path("files/reg"))); + + ATF_REQUIRE( exists(path("files/dir"))); + ATF_REQUIRE_THROW(atf::system_error, remove(path("files/dir"))); + ATF_REQUIRE( exists(path("files/dir"))); +} + +// ------------------------------------------------------------------------ +// Main. +// ------------------------------------------------------------------------ + +ATF_INIT_TEST_CASES(tcs) +{ + // Add the tests for the "path" class. + ATF_ADD_TEST_CASE(tcs, path_normalize); + ATF_ADD_TEST_CASE(tcs, path_is_absolute); + ATF_ADD_TEST_CASE(tcs, path_is_root); + ATF_ADD_TEST_CASE(tcs, path_branch_path); + ATF_ADD_TEST_CASE(tcs, path_leaf_name); + ATF_ADD_TEST_CASE(tcs, path_compare_equal); + ATF_ADD_TEST_CASE(tcs, path_compare_different); + ATF_ADD_TEST_CASE(tcs, path_concat); + ATF_ADD_TEST_CASE(tcs, path_to_absolute); + ATF_ADD_TEST_CASE(tcs, path_op_less); + + // Add the tests for the "file_info" class. + ATF_ADD_TEST_CASE(tcs, file_info_stat); + ATF_ADD_TEST_CASE(tcs, file_info_perms); + + // Add the tests for the "directory" class. + ATF_ADD_TEST_CASE(tcs, directory_read); + ATF_ADD_TEST_CASE(tcs, directory_names); + ATF_ADD_TEST_CASE(tcs, directory_file_info); + + // Add the tests for the free functions. + ATF_ADD_TEST_CASE(tcs, exists); + ATF_ADD_TEST_CASE(tcs, is_executable); + ATF_ADD_TEST_CASE(tcs, remove); +} diff --git a/external/bsd/atf/dist/atf-c++/detail/parser.cpp b/external/bsd/atf/dist/atf-c++/detail/parser.cpp new file mode 100644 index 000000000..7e7f680c5 --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/detail/parser.cpp @@ -0,0 +1,384 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#include + +#include "parser.hpp" +#include "sanity.hpp" +#include "text.hpp" + +namespace impl = atf::parser; +#define IMPL_NAME "atf::parser" + +// ------------------------------------------------------------------------ +// The "parse_error" class. +// ------------------------------------------------------------------------ + +impl::parse_error::parse_error(size_t line, std::string msg) : + std::runtime_error(msg), + std::pair< size_t, std::string >(line, msg) +{ +} + +impl::parse_error::~parse_error(void) + throw() +{ +} + +const char* +impl::parse_error::what(void) + const throw() +{ + try { + std::ostringstream oss; + oss << "LONELY PARSE ERROR: " << first << ": " << second; + m_msg = oss.str(); + return m_msg.c_str(); + } catch (...) { + return "Could not format message for parsing error."; + } +} + +impl::parse_error::operator std::string(void) + const +{ + return atf::text::to_string(first) + ": " + second; +} + +// ------------------------------------------------------------------------ +// The "parse_errors" class. +// ------------------------------------------------------------------------ + +impl::parse_errors::parse_errors(void) : + std::runtime_error("No parsing errors yet") +{ + m_msg.clear(); +} + +impl::parse_errors::~parse_errors(void) + throw() +{ +} + +const char* +impl::parse_errors::what(void) + const throw() +{ + try { + m_msg = atf::text::join(*this, "\n"); + return m_msg.c_str(); + } catch (...) { + return "Could not format messages for parsing errors."; + } +} + +// ------------------------------------------------------------------------ +// The "format_error" class. +// ------------------------------------------------------------------------ + +impl::format_error::format_error(const std::string& w) : + std::runtime_error(w.c_str()) +{ +} + +// ------------------------------------------------------------------------ +// The "token" class. +// ------------------------------------------------------------------------ + +impl::token::token(void) : + m_inited(false) +{ +} + +impl::token::token(size_t p_line, + const token_type& p_type, + const std::string& p_text) : + m_inited(true), + m_line(p_line), + m_type(p_type), + m_text(p_text) +{ +} + +size_t +impl::token::lineno(void) + const +{ + return m_line; +} + +const impl::token_type& +impl::token::type(void) + const +{ + return m_type; +} + +const std::string& +impl::token::text(void) + const +{ + return m_text; +} + +impl::token::operator bool(void) + const +{ + return m_inited; +} + +bool +impl::token::operator!(void) + const +{ + return !m_inited; +} + +// ------------------------------------------------------------------------ +// The "header_entry" class. +// ------------------------------------------------------------------------ + +impl::header_entry::header_entry(void) +{ +} + +impl::header_entry::header_entry(const std::string& n, const std::string& v, + attrs_map as) : + m_name(n), + m_value(v), + m_attrs(as) +{ +} + +const std::string& +impl::header_entry::name(void) const +{ + return m_name; +} + +const std::string& +impl::header_entry::value(void) const +{ + return m_value; +} + +const impl::attrs_map& +impl::header_entry::attrs(void) const +{ + return m_attrs; +} + +bool +impl::header_entry::has_attr(const std::string& n) const +{ + return m_attrs.find(n) != m_attrs.end(); +} + +const std::string& +impl::header_entry::get_attr(const std::string& n) const +{ + attrs_map::const_iterator iter = m_attrs.find(n); + PRE(iter != m_attrs.end()); + return (*iter).second; +} + +// ------------------------------------------------------------------------ +// The header tokenizer. +// ------------------------------------------------------------------------ + +namespace header { + +static const impl::token_type eof_type = 0; +static const impl::token_type nl_type = 1; +static const impl::token_type text_type = 2; +static const impl::token_type colon_type = 3; +static const impl::token_type semicolon_type = 4; +static const impl::token_type dblquote_type = 5; +static const impl::token_type equal_type = 6; + +class tokenizer : public impl::tokenizer< std::istream > { +public: + tokenizer(std::istream& is, size_t curline) : + impl::tokenizer< std::istream > + (is, true, eof_type, nl_type, text_type, curline) + { + add_delim(';', semicolon_type); + add_delim(':', colon_type); + add_delim('=', equal_type); + add_quote('"', dblquote_type); + } +}; + +static +impl::parser< header::tokenizer >& +read(impl::parser< header::tokenizer >& p, impl::header_entry& he) +{ + using namespace header; + + impl::token t = p.expect(text_type, nl_type, "a header name"); + if (t.type() == nl_type) { + he = impl::header_entry(); + return p; + } + std::string hdr_name = t.text(); + + t = p.expect(colon_type, "`:'"); + + t = p.expect(text_type, "a textual value"); + std::string hdr_value = t.text(); + + impl::attrs_map attrs; + + for (;;) { + t = p.expect(eof_type, semicolon_type, nl_type, + "eof, `;' or new line"); + if (t.type() == eof_type || t.type() == nl_type) + break; + + t = p.expect(text_type, "an attribute name"); + std::string attr_name = t.text(); + + t = p.expect(equal_type, "`='"); + + t = p.expect(text_type, "word or quoted string"); + std::string attr_value = t.text(); + attrs[attr_name] = attr_value; + } + + he = impl::header_entry(hdr_name, hdr_value, attrs); + + return p; +} + +static +std::ostream& +write(std::ostream& os, const impl::header_entry& he) +{ + std::string line = he.name() + ": " + he.value(); + impl::attrs_map as = he.attrs(); + for (impl::attrs_map::const_iterator iter = as.begin(); iter != as.end(); + iter++) { + PRE((*iter).second.find('\"') == std::string::npos); + line += "; " + (*iter).first + "=\"" + (*iter).second + "\""; + } + + os << line << "\n"; + + return os; +} + +} // namespace header + +// ------------------------------------------------------------------------ +// Free functions. +// ------------------------------------------------------------------------ + +std::pair< size_t, impl::headers_map > +impl::read_headers(std::istream& is, size_t curline) +{ + using impl::format_error; + + headers_map hm; + + // + // Grammar + // + // header = entry+ nl + // entry = line nl + // line = text colon text + // (semicolon (text equal (text | dblquote string dblquote)))* + // string = quoted_string + // + + header::tokenizer tkz(is, curline); + impl::parser< header::tokenizer > p(tkz); + + bool first = true; + for (;;) { + try { + header_entry he; + if (!header::read(p, he).good() || he.name().empty()) + break; + + if (first && he.name() != "Content-Type") + throw format_error("Could not determine content type"); + else + first = false; + + hm[he.name()] = he; + } catch (const impl::parse_error& pe) { + p.add_error(pe); + p.reset(header::nl_type); + } + } + + if (!is.good()) + throw format_error("Unexpected end of stream"); + + return std::pair< size_t, headers_map >(tkz.lineno(), hm); +} + +void +impl::write_headers(const impl::headers_map& hm, std::ostream& os) +{ + PRE(!hm.empty()); + headers_map::const_iterator ct = hm.find("Content-Type"); + PRE(ct != hm.end()); + header::write(os, (*ct).second); + for (headers_map::const_iterator iter = hm.begin(); iter != hm.end(); + iter++) { + if ((*iter).first != "Content-Type") + header::write(os, (*iter).second); + } + os << "\n"; +} + +void +impl::validate_content_type(const impl::headers_map& hm, const std::string& fmt, + int version) +{ + using impl::format_error; + + headers_map::const_iterator iter = hm.find("Content-Type"); + if (iter == hm.end()) + throw format_error("Could not determine content type"); + + const header_entry& he = (*iter).second; + if (he.value() != fmt) + throw format_error("Mismatched content type: expected `" + fmt + + "' but got `" + he.value() + "'"); + + if (!he.has_attr("version")) + throw format_error("Could not determine version"); + const std::string& vstr = atf::text::to_string(version); + if (he.get_attr("version") != vstr) + throw format_error("Mismatched version: expected `" + + vstr + "' but got `" + + he.get_attr("version") + "'"); +} diff --git a/external/bsd/atf/dist/atf-c++/detail/parser.hpp b/external/bsd/atf/dist/atf-c++/detail/parser.hpp new file mode 100644 index 000000000..f55973f50 --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/detail/parser.hpp @@ -0,0 +1,607 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#if !defined(_ATF_CXX_PARSER_HPP_) +#define _ATF_CXX_PARSER_HPP_ + +#include +#include +#include +#include +#include +#include +#include + +namespace atf { +namespace parser { + +// ------------------------------------------------------------------------ +// The "parse_error" class. +// ------------------------------------------------------------------------ + +class parse_error : public std::runtime_error, + public std::pair< size_t, std::string > { + mutable std::string m_msg; + +public: + parse_error(size_t, std::string); + ~parse_error(void) throw(); + + const char* what(void) const throw(); + + operator std::string(void) const; +}; + +// ------------------------------------------------------------------------ +// The "parse_errors" class. +// ------------------------------------------------------------------------ + +class parse_errors : public std::runtime_error, + public std::vector< parse_error > { + std::vector< parse_error > m_errors; + mutable std::string m_msg; + +public: + parse_errors(void); + ~parse_errors(void) throw(); + + const char* what(void) const throw(); +}; + +// ------------------------------------------------------------------------ +// The "format_error" class. +// ------------------------------------------------------------------------ + +class format_error : public std::runtime_error { +public: + format_error(const std::string&); +}; + +// ------------------------------------------------------------------------ +// The "token" class. +// ------------------------------------------------------------------------ + +typedef int token_type; + +//! +//! \brief Representation of a read token. +//! +//! A pair that contains the information of a token read from a stream. +//! It contains the token's type and its associated data, if any. +//! +struct token { + bool m_inited; + size_t m_line; + token_type m_type; + std::string m_text; + +public: + token(void); + token(size_t, const token_type&, const std::string& = ""); + + size_t lineno(void) const; + const token_type& type(void) const; + const std::string& text(void) const; + + operator bool(void) const; + bool operator!(void) const; +}; + +// ------------------------------------------------------------------------ +// The "tokenizer" class. +// ------------------------------------------------------------------------ + +//! +//! \brief A stream tokenizer. +//! +//! This template implements an extremely simple, line-oriented stream +//! tokenizer. It is only able to recognize one character-long delimiters, +//! random-length keywords, skip whitespace and, anything that does not +//! match these rules is supposed to be a word. +//! +//! Parameter IS: The input stream's type. +//! +template< class IS > +class tokenizer { + IS& m_is; + size_t m_lineno; + token m_la; + + bool m_skipws; + token_type m_eof_type, m_nl_type, m_text_type; + + std::map< char, token_type > m_delims_map; + std::string m_delims_str; + + char m_quotech; + token_type m_quotetype; + + std::map< std::string, token_type > m_keywords_map; + + token_type alloc_type(void); + + template< class TKZ > + friend + class parser; + +public: + tokenizer(IS&, bool, const token_type&, const token_type&, + const token_type&, size_t = 1); + + size_t lineno(void) const; + + void add_delim(char, const token_type&); + void add_keyword(const std::string&, const token_type&); + void add_quote(char, const token_type&); + + token next(void); + std::string rest_of_line(void); +}; + +template< class IS > +tokenizer< IS >::tokenizer(IS& p_is, + bool p_skipws, + const token_type& p_eof_type, + const token_type& p_nl_type, + const token_type& p_text_type, + size_t p_lineno) : + m_is(p_is), + m_lineno(p_lineno), + m_skipws(p_skipws), + m_eof_type(p_eof_type), + m_nl_type(p_nl_type), + m_text_type(p_text_type), + m_quotech(-1) +{ +} + +template< class IS > +size_t +tokenizer< IS >::lineno(void) + const +{ + return m_lineno; +} + +template< class IS > +void +tokenizer< IS >::add_delim(char delim, const token_type& type) +{ + m_delims_map[delim] = type; + m_delims_str += delim; +} + +template< class IS > +void +tokenizer< IS >::add_keyword(const std::string& keyword, + const token_type& type) +{ + m_keywords_map[keyword] = type; +} + +template< class IS > +void +tokenizer< IS >::add_quote(char ch, const token_type& type) +{ + m_quotech = ch; + m_quotetype = type; +} + +template< class IS > +token +tokenizer< IS >::next(void) +{ + if (m_la) { + token t = m_la; + m_la = token(); + if (t.type() == m_nl_type) + m_lineno++; + return t; + } + + char ch; + std::string text; + + bool done = false, quoted = false; + token t(m_lineno, m_eof_type, "<>"); + while (!done && m_is.get(ch).good()) { + if (ch == m_quotech) { + if (text.empty()) { + bool escaped = false; + while (!done && m_is.get(ch).good()) { + if (!escaped) { + if (ch == '\\') + escaped = true; + else if (ch == '\n') { + m_la = token(m_lineno, m_nl_type, "<>"); + throw parse_error(t.lineno(), + "Missing double quotes before " + "end of line"); + } else if (ch == m_quotech) + done = true; + else + text += ch; + } else { + text += ch; + escaped = false; + } + } + if (!m_is.good()) + throw parse_error(t.lineno(), + "Missing double quotes before " + "end of file"); + t = token(m_lineno, m_text_type, text); + quoted = true; + } else { + m_is.putback(ch); + done = true; + } + } else { + typename std::map< char, token_type >::const_iterator idelim; + idelim = m_delims_map.find(ch); + if (idelim != m_delims_map.end()) { + done = true; + if (text.empty()) + t = token(m_lineno, (*idelim).second, + std::string("") + ch); + else + m_is.putback(ch); + } else if (ch == '\n') { + done = true; + if (text.empty()) + t = token(m_lineno, m_nl_type, "<>"); + else + m_is.putback(ch); + } else if (m_skipws && (ch == ' ' || ch == '\t')) { + if (!text.empty()) + done = true; + } else + text += ch; + } + } + + if (!quoted && !text.empty()) { + typename std::map< std::string, token_type >::const_iterator ikw; + ikw = m_keywords_map.find(text); + if (ikw != m_keywords_map.end()) + t = token(m_lineno, (*ikw).second, text); + else + t = token(m_lineno, m_text_type, text); + } + + if (t.type() == m_nl_type) + m_lineno++; + + return t; +} + +template< class IS > +std::string +tokenizer< IS >::rest_of_line(void) +{ + std::string str; + while (m_is.good() && m_is.peek() != '\n') + str += m_is.get(); + return str; +} + +// ------------------------------------------------------------------------ +// The "parser" class. +// ------------------------------------------------------------------------ + +template< class TKZ > +class parser { + TKZ& m_tkz; + token m_last; + parse_errors m_errors; + bool m_thrown; + +public: + parser(TKZ& tkz); + ~parser(void); + + bool good(void) const; + void add_error(const parse_error&); + bool has_errors(void) const; + + token next(void); + std::string rest_of_line(void); + token reset(const token_type&); + + token + expect(const token_type&, + const std::string&); + + token + expect(const token_type&, + const token_type&, + const std::string&); + + token + expect(const token_type&, + const token_type&, + const token_type&, + const std::string&); + + token + expect(const token_type&, + const token_type&, + const token_type&, + const token_type&, + const std::string&); + + token + expect(const token_type&, + const token_type&, + const token_type&, + const token_type&, + const token_type&, + const token_type&, + const token_type&, + const std::string&); + + token + expect(const token_type&, + const token_type&, + const token_type&, + const token_type&, + const token_type&, + const token_type&, + const token_type&, + const token_type&, + const std::string&); +}; + +template< class TKZ > +parser< TKZ >::parser(TKZ& tkz) : + m_tkz(tkz), + m_thrown(false) +{ +} + +template< class TKZ > +parser< TKZ >::~parser(void) +{ + if (!m_errors.empty() && !m_thrown) + throw m_errors; +} + +template< class TKZ > +bool +parser< TKZ >::good(void) + const +{ + return m_tkz.m_is.good(); +} + +template< class TKZ > +void +parser< TKZ >::add_error(const parse_error& pe) +{ + m_errors.push_back(pe); +} + +template< class TKZ > +bool +parser< TKZ >::has_errors(void) + const +{ + return !m_errors.empty(); +} + +template< class TKZ > +token +parser< TKZ >::next(void) +{ + token t = m_tkz.next(); + + m_last = t; + + if (t.type() == m_tkz.m_eof_type) { + if (!m_errors.empty()) { + m_thrown = true; + throw m_errors; + } + } + + return t; +} + +template< class TKZ > +std::string +parser< TKZ >::rest_of_line(void) +{ + return m_tkz.rest_of_line(); +} + +template< class TKZ > +token +parser< TKZ >::reset(const token_type& stop) +{ + token t = m_last; + + while (t.type() != m_tkz.m_eof_type && t.type() != stop) + t = next(); + + return t; +} + +template< class TKZ > +token +parser< TKZ >::expect(const token_type& t1, + const std::string& textual) +{ + token t = next(); + + if (t.type() != t1) + throw parse_error(t.lineno(), + "Unexpected token `" + t.text() + + "'; expected " + textual); + + return t; +} + +template< class TKZ > +token +parser< TKZ >::expect(const token_type& t1, + const token_type& t2, + const std::string& textual) +{ + token t = next(); + + if (t.type() != t1 && t.type() != t2) + throw parse_error(t.lineno(), + "Unexpected token `" + t.text() + + "'; expected " + textual); + + return t; +} + +template< class TKZ > +token +parser< TKZ >::expect(const token_type& t1, + const token_type& t2, + const token_type& t3, + const std::string& textual) +{ + token t = next(); + + if (t.type() != t1 && t.type() != t2 && t.type() != t3) + throw parse_error(t.lineno(), + "Unexpected token `" + t.text() + + "'; expected " + textual); + + return t; +} + +template< class TKZ > +token +parser< TKZ >::expect(const token_type& t1, + const token_type& t2, + const token_type& t3, + const token_type& t4, + const std::string& textual) +{ + token t = next(); + + if (t.type() != t1 && t.type() != t2 && t.type() != t3 && + t.type() != t4) + throw parse_error(t.lineno(), + "Unexpected token `" + t.text() + + "'; expected " + textual); + + return t; +} + +template< class TKZ > +token +parser< TKZ >::expect(const token_type& t1, + const token_type& t2, + const token_type& t3, + const token_type& t4, + const token_type& t5, + const token_type& t6, + const token_type& t7, + const std::string& textual) +{ + token t = next(); + + if (t.type() != t1 && t.type() != t2 && t.type() != t3 && + t.type() != t4 && t.type() != t5 && t.type() != t6 && + t.type() != t7) + throw parse_error(t.lineno(), + "Unexpected token `" + t.text() + + "'; expected " + textual); + + return t; +} + +template< class TKZ > +token +parser< TKZ >::expect(const token_type& t1, + const token_type& t2, + const token_type& t3, + const token_type& t4, + const token_type& t5, + const token_type& t6, + const token_type& t7, + const token_type& t8, + const std::string& textual) +{ + token t = next(); + + if (t.type() != t1 && t.type() != t2 && t.type() != t3 && + t.type() != t4 && t.type() != t5 && t.type() != t6 && + t.type() != t7 && t.type() != t8) + throw parse_error(t.lineno(), + "Unexpected token `" + t.text() + + "'; expected " + textual); + + return t; +} + +#define ATF_PARSER_CALLBACK(parser, func) \ + do { \ + if (!(parser).has_errors()) \ + func; \ + } while (false) + +// ------------------------------------------------------------------------ +// Header parsing. +// ------------------------------------------------------------------------ + +typedef std::map< std::string, std::string > attrs_map; + +class header_entry { + std::string m_name; + std::string m_value; + attrs_map m_attrs; + +public: + header_entry(void); + header_entry(const std::string&, const std::string&, + attrs_map = attrs_map()); + + const std::string& name(void) const; + const std::string& value(void) const; + const attrs_map& attrs(void) const; + bool has_attr(const std::string&) const; + const std::string& get_attr(const std::string&) const; +}; + +typedef std::map< std::string, header_entry > headers_map; + +std::pair< size_t, headers_map > read_headers(std::istream&, size_t); +void write_headers(const headers_map&, std::ostream&); +void validate_content_type(const headers_map&, const std::string&, int); + +} // namespace parser +} // namespace atf + +#endif // !defined(_ATF_CXX_PARSER_HPP_) diff --git a/external/bsd/atf/dist/atf-c++/detail/parser_test.cpp b/external/bsd/atf/dist/atf-c++/detail/parser_test.cpp new file mode 100644 index 000000000..491c01457 --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/detail/parser_test.cpp @@ -0,0 +1,1043 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#include + +#include "../macros.hpp" + +#include "parser.hpp" +#include "test_helpers.hpp" + +// ------------------------------------------------------------------------ +// Tests for the "parse_error" class. +// ------------------------------------------------------------------------ + +ATF_TEST_CASE(parse_error_to_string); +ATF_TEST_CASE_HEAD(parse_error_to_string) +{ + set_md_var("descr", "Tests the parse_error conversion to strings"); +} +ATF_TEST_CASE_BODY(parse_error_to_string) +{ + using atf::parser::parse_error; + + const parse_error e(123, "This is the message"); + ATF_REQUIRE_EQ("123: This is the message", std::string(e)); +} + +// ------------------------------------------------------------------------ +// Tests for the "parse_errors" class. +// ------------------------------------------------------------------------ + +ATF_TEST_CASE(parse_errors_what); +ATF_TEST_CASE_HEAD(parse_errors_what) +{ + set_md_var("descr", "Tests the parse_errors description"); +} +ATF_TEST_CASE_BODY(parse_errors_what) +{ + using atf::parser::parse_error; + using atf::parser::parse_errors; + + parse_errors es; + es.push_back(parse_error(2, "Second error")); + es.push_back(parse_error(1, "First error")); + + ATF_REQUIRE_EQ("2: Second error\n1: First error", std::string(es.what())); +} + +// ------------------------------------------------------------------------ +// Tests for the "token" class. +// ------------------------------------------------------------------------ + +ATF_TEST_CASE(token_getters); +ATF_TEST_CASE_HEAD(token_getters) +{ + set_md_var("descr", "Tests the token getters"); +} +ATF_TEST_CASE_BODY(token_getters) +{ + using atf::parser::token; + + { + token t(10, 0); + ATF_REQUIRE_EQ(t.lineno(), 10); + ATF_REQUIRE_EQ(t.type(), 0); + ATF_REQUIRE(t.text().empty()); + } + + { + token t(10, 0, "foo"); + ATF_REQUIRE_EQ(t.lineno(), 10); + ATF_REQUIRE_EQ(t.type(), 0); + ATF_REQUIRE_EQ(t.text(), "foo"); + } + + { + token t(20, 1); + ATF_REQUIRE_EQ(t.lineno(), 20); + ATF_REQUIRE_EQ(t.type(), 1); + ATF_REQUIRE(t.text().empty()); + } + + { + token t(20, 1, "bar"); + ATF_REQUIRE_EQ(t.lineno(), 20); + ATF_REQUIRE_EQ(t.type(), 1); + ATF_REQUIRE_EQ(t.text(), "bar"); + } +} + +// ------------------------------------------------------------------------ +// Tests for the "tokenizer" class. +// ------------------------------------------------------------------------ + +#define EXPECT(tkz, ttype, ttext) \ + do { \ + atf::parser::token t = tkz.next(); \ + ATF_REQUIRE(t.type() == ttype); \ + ATF_REQUIRE_EQ(t.text(), ttext); \ + } while (false); + +namespace minimal { + + static const atf::parser::token_type eof_type = 0; + static const atf::parser::token_type nl_type = 1; + static const atf::parser::token_type word_type = 2; + + class tokenizer : public atf::parser::tokenizer< std::istream > { + public: + tokenizer(std::istream& is, bool skipws) : + atf::parser::tokenizer< std::istream > + (is, skipws, eof_type, nl_type, word_type) + { + } + }; + +} + +namespace delims { + + static const atf::parser::token_type eof_type = 0; + static const atf::parser::token_type nl_type = 1; + static const atf::parser::token_type word_type = 2; + static const atf::parser::token_type plus_type = 3; + static const atf::parser::token_type minus_type = 4; + static const atf::parser::token_type equal_type = 5; + + class tokenizer : public atf::parser::tokenizer< std::istream > { + public: + tokenizer(std::istream& is, bool skipws) : + atf::parser::tokenizer< std::istream > + (is, skipws, eof_type, nl_type, word_type) + { + add_delim('+', plus_type); + add_delim('-', minus_type); + add_delim('=', equal_type); + } + }; + +} + +namespace keywords { + + static const atf::parser::token_type eof_type = 0; + static const atf::parser::token_type nl_type = 1; + static const atf::parser::token_type word_type = 2; + static const atf::parser::token_type var_type = 3; + static const atf::parser::token_type loop_type = 4; + static const atf::parser::token_type endloop_type = 5; + + class tokenizer : public atf::parser::tokenizer< std::istream > { + public: + tokenizer(std::istream& is, bool skipws) : + atf::parser::tokenizer< std::istream > + (is, skipws, eof_type, nl_type, word_type) + { + add_keyword("var", var_type); + add_keyword("loop", loop_type); + add_keyword("endloop", endloop_type); + } + }; + +} + +namespace quotes { + + static const atf::parser::token_type eof_type = 0; + static const atf::parser::token_type nl_type = 1; + static const atf::parser::token_type word_type = 2; + static const atf::parser::token_type dblquote_type = 3; + + class tokenizer : public atf::parser::tokenizer< std::istream > { + public: + tokenizer(std::istream& is, bool skipws) : + atf::parser::tokenizer< std::istream > + (is, skipws, eof_type, nl_type, word_type) + { + add_quote('"', dblquote_type); + } + }; + +} + +ATF_TEST_CASE(tokenizer_minimal_nows); +ATF_TEST_CASE_HEAD(tokenizer_minimal_nows) +{ + set_md_var("descr", "Tests the tokenizer class using a minimal parser " + "and not skipping whitespace"); +} +ATF_TEST_CASE_BODY(tokenizer_minimal_nows) +{ + using namespace minimal; + + { + std::istringstream iss(""); + tokenizer mt(iss, false); + + EXPECT(mt, eof_type, "<>"); + EXPECT(mt, eof_type, "<>"); + } + + { + std::istringstream iss("\n"); + tokenizer mt(iss, false); + + EXPECT(mt, nl_type, "<>"); + EXPECT(mt, eof_type, "<>"); + EXPECT(mt, eof_type, "<>"); + } + + { + std::istringstream iss("\n\n\n"); + tokenizer mt(iss, false); + + EXPECT(mt, nl_type, "<>"); + EXPECT(mt, nl_type, "<>"); + EXPECT(mt, nl_type, "<>"); + EXPECT(mt, eof_type, "<>"); + EXPECT(mt, eof_type, "<>"); + } + + { + std::istringstream iss("line 1"); + tokenizer mt(iss, false); + + EXPECT(mt, word_type, "line 1"); + EXPECT(mt, eof_type, "<>"); + EXPECT(mt, eof_type, "<>"); + } + + { + std::istringstream iss("line 1\n"); + tokenizer mt(iss, false); + + EXPECT(mt, word_type, "line 1"); + EXPECT(mt, nl_type, "<>"); + EXPECT(mt, eof_type, "<>"); + EXPECT(mt, eof_type, "<>"); + } + + { + std::istringstream iss("line 1\nline 2"); + tokenizer mt(iss, false); + + EXPECT(mt, word_type, "line 1"); + EXPECT(mt, nl_type, "<>"); + EXPECT(mt, word_type, "line 2"); + EXPECT(mt, eof_type, "<>"); + EXPECT(mt, eof_type, "<>"); + } + + { + std::istringstream iss("line 1\nline 2\nline 3\n"); + tokenizer mt(iss, false); + + EXPECT(mt, word_type, "line 1"); + EXPECT(mt, nl_type, "<>"); + EXPECT(mt, word_type, "line 2"); + EXPECT(mt, nl_type, "<>"); + EXPECT(mt, word_type, "line 3"); + EXPECT(mt, nl_type, "<>"); + EXPECT(mt, eof_type, "<>"); + EXPECT(mt, eof_type, "<>"); + } +} + +ATF_TEST_CASE(tokenizer_minimal_ws); +ATF_TEST_CASE_HEAD(tokenizer_minimal_ws) +{ + set_md_var("descr", "Tests the tokenizer class using a minimal parser " + "and skipping whitespace"); +} +ATF_TEST_CASE_BODY(tokenizer_minimal_ws) +{ + using namespace minimal; + + { + std::istringstream iss(""); + minimal::tokenizer mt(iss, true); + + EXPECT(mt, eof_type, "<>"); + EXPECT(mt, eof_type, "<>"); + } + + { + std::istringstream iss(" \t "); + tokenizer mt(iss, true); + + EXPECT(mt, eof_type, "<>"); + EXPECT(mt, eof_type, "<>"); + } + + { + std::istringstream iss("\n"); + tokenizer mt(iss, true); + + EXPECT(mt, nl_type, "<>"); + EXPECT(mt, eof_type, "<>"); + EXPECT(mt, eof_type, "<>"); + } + + { + std::istringstream iss(" \t \n \t "); + tokenizer mt(iss, true); + + EXPECT(mt, nl_type, "<>"); + EXPECT(mt, eof_type, "<>"); + EXPECT(mt, eof_type, "<>"); + } + + { + std::istringstream iss("\n\n\n"); + tokenizer mt(iss, true); + + EXPECT(mt, nl_type, "<>"); + EXPECT(mt, nl_type, "<>"); + EXPECT(mt, nl_type, "<>"); + EXPECT(mt, eof_type, "<>"); + EXPECT(mt, eof_type, "<>"); + } + + { + std::istringstream iss("line 1"); + tokenizer mt(iss, true); + + EXPECT(mt, word_type, "line"); + EXPECT(mt, word_type, "1"); + EXPECT(mt, eof_type, "<>"); + EXPECT(mt, eof_type, "<>"); + } + + { + std::istringstream iss(" \tline\t 1\t"); + tokenizer mt(iss, true); + + EXPECT(mt, word_type, "line"); + EXPECT(mt, word_type, "1"); + EXPECT(mt, eof_type, "<>"); + EXPECT(mt, eof_type, "<>"); + } + + { + std::istringstream iss("line 1\n"); + tokenizer mt(iss, true); + + EXPECT(mt, word_type, "line"); + EXPECT(mt, word_type, "1"); + EXPECT(mt, nl_type, "<>"); + EXPECT(mt, eof_type, "<>"); + EXPECT(mt, eof_type, "<>"); + } + + { + std::istringstream iss("line 1\nline 2"); + tokenizer mt(iss, true); + + EXPECT(mt, word_type, "line"); + EXPECT(mt, word_type, "1"); + EXPECT(mt, nl_type, "<>"); + EXPECT(mt, word_type, "line"); + EXPECT(mt, word_type, "2"); + EXPECT(mt, eof_type, "<>"); + EXPECT(mt, eof_type, "<>"); + } + + { + std::istringstream iss("line 1\nline 2\nline 3\n"); + tokenizer mt(iss, true); + + EXPECT(mt, word_type, "line"); + EXPECT(mt, word_type, "1"); + EXPECT(mt, nl_type, "<>"); + EXPECT(mt, word_type, "line"); + EXPECT(mt, word_type, "2"); + EXPECT(mt, nl_type, "<>"); + EXPECT(mt, word_type, "line"); + EXPECT(mt, word_type, "3"); + EXPECT(mt, nl_type, "<>"); + EXPECT(mt, eof_type, "<>"); + EXPECT(mt, eof_type, "<>"); + } + + { + std::istringstream iss(" \t line \t 1\n\tline\t2\n line 3 \n"); + tokenizer mt(iss, true); + + EXPECT(mt, word_type, "line"); + EXPECT(mt, word_type, "1"); + EXPECT(mt, nl_type, "<>"); + EXPECT(mt, word_type, "line"); + EXPECT(mt, word_type, "2"); + EXPECT(mt, nl_type, "<>"); + EXPECT(mt, word_type, "line"); + EXPECT(mt, word_type, "3"); + EXPECT(mt, nl_type, "<>"); + EXPECT(mt, eof_type, "<>"); + EXPECT(mt, eof_type, "<>"); + } +} + +ATF_TEST_CASE(tokenizer_delims_nows); +ATF_TEST_CASE_HEAD(tokenizer_delims_nows) +{ + set_md_var("descr", "Tests the tokenizer class using a parser with some " + "additional delimiters and not skipping whitespace"); +} +ATF_TEST_CASE_BODY(tokenizer_delims_nows) +{ + using namespace delims; + + { + std::istringstream iss("+-="); + tokenizer mt(iss, false); + + EXPECT(mt, plus_type, "+"); + EXPECT(mt, minus_type, "-"); + EXPECT(mt, equal_type, "="); + EXPECT(mt, eof_type, "<>"); + EXPECT(mt, eof_type, "<>"); + } + + { + std::istringstream iss("+++"); + tokenizer mt(iss, false); + + EXPECT(mt, plus_type, "+"); + EXPECT(mt, plus_type, "+"); + EXPECT(mt, plus_type, "+"); + EXPECT(mt, eof_type, "<>"); + EXPECT(mt, eof_type, "<>"); + } + + { + std::istringstream iss("\n+\n++\n"); + tokenizer mt(iss, false); + + EXPECT(mt, nl_type, "<>"); + EXPECT(mt, plus_type, "+"); + EXPECT(mt, nl_type, "<>"); + EXPECT(mt, plus_type, "+"); + EXPECT(mt, plus_type, "+"); + EXPECT(mt, nl_type, "<>"); + EXPECT(mt, eof_type, "<>"); + EXPECT(mt, eof_type, "<>"); + } + + { + std::istringstream iss("foo+bar=baz"); + tokenizer mt(iss, false); + + EXPECT(mt, word_type, "foo"); + EXPECT(mt, plus_type, "+"); + EXPECT(mt, word_type, "bar"); + EXPECT(mt, equal_type, "="); + EXPECT(mt, word_type, "baz"); + EXPECT(mt, eof_type, "<>"); + EXPECT(mt, eof_type, "<>"); + } + + { + std::istringstream iss(" foo\t+\tbar = baz "); + tokenizer mt(iss, false); + + EXPECT(mt, word_type, " foo\t"); + EXPECT(mt, plus_type, "+"); + EXPECT(mt, word_type, "\tbar "); + EXPECT(mt, equal_type, "="); + EXPECT(mt, word_type, " baz "); + EXPECT(mt, eof_type, "<>"); + EXPECT(mt, eof_type, "<>"); + } +} + +ATF_TEST_CASE(tokenizer_delims_ws); +ATF_TEST_CASE_HEAD(tokenizer_delims_ws) +{ + set_md_var("descr", "Tests the tokenizer class using a parser with some " + "additional delimiters and skipping whitespace"); +} +ATF_TEST_CASE_BODY(tokenizer_delims_ws) +{ + using namespace delims; + + { + std::istringstream iss(" foo\t+\tbar = baz "); + tokenizer mt(iss, true); + + EXPECT(mt, word_type, "foo"); + EXPECT(mt, plus_type, "+"); + EXPECT(mt, word_type, "bar"); + EXPECT(mt, equal_type, "="); + EXPECT(mt, word_type, "baz"); + EXPECT(mt, eof_type, "<>"); + EXPECT(mt, eof_type, "<>"); + } +} + +ATF_TEST_CASE(tokenizer_keywords_nows); +ATF_TEST_CASE_HEAD(tokenizer_keywords_nows) +{ + set_md_var("descr", "Tests the tokenizer class using a parser with some " + "additional keywords and not skipping whitespace"); +} +ATF_TEST_CASE_BODY(tokenizer_keywords_nows) +{ + using namespace keywords; + + { + std::istringstream iss("var"); + tokenizer mt(iss, false); + + EXPECT(mt, var_type, "var"); + EXPECT(mt, eof_type, "<>"); + EXPECT(mt, eof_type, "<>"); + } + + { + std::istringstream iss("va"); + tokenizer mt(iss, false); + + EXPECT(mt, word_type, "va"); + EXPECT(mt, eof_type, "<>"); + EXPECT(mt, eof_type, "<>"); + } + + { + std::istringstream iss("vara"); + tokenizer mt(iss, false); + + EXPECT(mt, word_type, "vara"); + EXPECT(mt, eof_type, "<>"); + EXPECT(mt, eof_type, "<>"); + } + + { + std::istringstream iss("var "); + tokenizer mt(iss, false); + + EXPECT(mt, word_type, "var "); + EXPECT(mt, eof_type, "<>"); + EXPECT(mt, eof_type, "<>"); + } + + { + std::istringstream iss("var\nloop\nendloop"); + tokenizer mt(iss, false); + + EXPECT(mt, var_type, "var"); + EXPECT(mt, nl_type, "<>"); + EXPECT(mt, loop_type, "loop"); + EXPECT(mt, nl_type, "<>"); + EXPECT(mt, endloop_type, "endloop"); + EXPECT(mt, eof_type, "<>"); + EXPECT(mt, eof_type, "<>"); + } +} + +ATF_TEST_CASE(tokenizer_keywords_ws); +ATF_TEST_CASE_HEAD(tokenizer_keywords_ws) +{ + set_md_var("descr", "Tests the tokenizer class using a parser with some " + "additional keywords and not skipping whitespace"); +} +ATF_TEST_CASE_BODY(tokenizer_keywords_ws) +{ + using namespace keywords; + + { + std::istringstream iss("var "); + tokenizer mt(iss, true); + + EXPECT(mt, var_type, "var"); + EXPECT(mt, eof_type, "<>"); + EXPECT(mt, eof_type, "<>"); + } + + { + std::istringstream iss(" var \n\tloop\t\n \tendloop \t"); + tokenizer mt(iss, true); + + EXPECT(mt, var_type, "var"); + EXPECT(mt, nl_type, "<>"); + EXPECT(mt, loop_type, "loop"); + EXPECT(mt, nl_type, "<>"); + EXPECT(mt, endloop_type, "endloop"); + EXPECT(mt, eof_type, "<>"); + EXPECT(mt, eof_type, "<>"); + } + + { + std::istringstream iss("var loop endloop"); + tokenizer mt(iss, true); + + EXPECT(mt, var_type, "var"); + EXPECT(mt, loop_type, "loop"); + EXPECT(mt, endloop_type, "endloop"); + EXPECT(mt, eof_type, "<>"); + EXPECT(mt, eof_type, "<>"); + } +} + +ATF_TEST_CASE(tokenizer_quotes_nows); +ATF_TEST_CASE_HEAD(tokenizer_quotes_nows) +{ + set_md_var("descr", "Tests the tokenizer class using a parser with " + "quoted strings and not skipping whitespace"); +} +ATF_TEST_CASE_BODY(tokenizer_quotes_nows) +{ + using namespace quotes; + + { + std::istringstream iss("var"); + tokenizer mt(iss, false); + + EXPECT(mt, word_type, "var"); + EXPECT(mt, eof_type, "<>"); + EXPECT(mt, eof_type, "<>"); + } + + { + std::istringstream iss("\"var\""); + tokenizer mt(iss, false); + + EXPECT(mt, word_type, "var"); + EXPECT(mt, eof_type, "<>"); + EXPECT(mt, eof_type, "<>"); + } + + { + std::istringstream iss("var1\"var2\""); + tokenizer mt(iss, false); + + EXPECT(mt, word_type, "var1"); + EXPECT(mt, word_type, "var2"); + EXPECT(mt, eof_type, "<>"); + EXPECT(mt, eof_type, "<>"); + } + + { + std::istringstream iss("var1\" var2 \""); + tokenizer mt(iss, false); + + EXPECT(mt, word_type, "var1"); + EXPECT(mt, word_type, " var2 "); + EXPECT(mt, eof_type, "<>"); + EXPECT(mt, eof_type, "<>"); + } +} + +ATF_TEST_CASE(tokenizer_quotes_ws); +ATF_TEST_CASE_HEAD(tokenizer_quotes_ws) +{ + set_md_var("descr", "Tests the tokenizer class using a parser with " + "quoted strings and skipping whitespace"); +} +ATF_TEST_CASE_BODY(tokenizer_quotes_ws) +{ + using namespace quotes; + + { + std::istringstream iss(" var "); + tokenizer mt(iss, true); + + EXPECT(mt, word_type, "var"); + EXPECT(mt, eof_type, "<>"); + EXPECT(mt, eof_type, "<>"); + } + + { + std::istringstream iss(" \"var\" "); + tokenizer mt(iss, true); + + EXPECT(mt, word_type, "var"); + EXPECT(mt, eof_type, "<>"); + EXPECT(mt, eof_type, "<>"); + } + + { + std::istringstream iss(" var1 \"var2\" "); + tokenizer mt(iss, true); + + EXPECT(mt, word_type, "var1"); + EXPECT(mt, word_type, "var2"); + EXPECT(mt, eof_type, "<>"); + EXPECT(mt, eof_type, "<>"); + } + + { + std::istringstream iss(" var1 \" var2 \" "); + tokenizer mt(iss, true); + + EXPECT(mt, word_type, "var1"); + EXPECT(mt, word_type, " var2 "); + EXPECT(mt, eof_type, "<>"); + EXPECT(mt, eof_type, "<>"); + } +} + +// ------------------------------------------------------------------------ +// Tests for the headers parser. +// ------------------------------------------------------------------------ + +class header_reader { + std::istream& m_is; + +public: + header_reader(std::istream& is) : + m_is(is) + { + } + + void + read(void) + { + std::pair< size_t, atf::parser::headers_map > hml = + atf::parser::read_headers(m_is, 1); + atf::parser::validate_content_type(hml.second, + "application/X-atf-headers-test", 1234); + } + + std::vector< std::string > m_calls; +}; + +ATF_TEST_CASE_WITHOUT_HEAD(headers_1); +ATF_TEST_CASE_BODY(headers_1) +{ + const char* input = + "" + ; + + const char* exp_calls[] = { + NULL + }; + + const char* exp_errors[] = { + "1: Unexpected token `<>'; expected a header name", + NULL + }; + + do_parser_test< header_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(headers_2); +ATF_TEST_CASE_BODY(headers_2) +{ + const char* input = + "Content-Type\n" + ; + + const char* exp_calls[] = { + NULL + }; + + const char* exp_errors[] = { + "1: Unexpected token `<>'; expected `:'", + NULL + }; + + do_parser_test< header_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(headers_3); +ATF_TEST_CASE_BODY(headers_3) +{ + const char* input = + "Content-Type:\n" + ; + + const char* exp_calls[] = { + NULL + }; + + const char* exp_errors[] = { + "1: Unexpected token `<>'; expected a textual value", + NULL + }; + + do_parser_test< header_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(headers_4); +ATF_TEST_CASE_BODY(headers_4) +{ + const char* input = + "Content-Type: application/X-atf-headers-test\n" + ; + + const char* exp_calls[] = { + NULL + }; + + const char* exp_errors[] = { + "2: Unexpected token `<>'; expected a header name", + NULL + }; + + do_parser_test< header_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(headers_5); +ATF_TEST_CASE_BODY(headers_5) +{ + const char* input = + "Content-Type: application/X-atf-headers-test;\n" + ; + + const char* exp_calls[] = { + NULL + }; + + const char* exp_errors[] = { + "1: Unexpected token `<>'; expected an attribute name", + NULL + }; + + do_parser_test< header_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(headers_6); +ATF_TEST_CASE_BODY(headers_6) +{ + const char* input = + "Content-Type: application/X-atf-headers-test; version\n" + ; + + const char* exp_calls[] = { + NULL + }; + + const char* exp_errors[] = { + "1: Unexpected token `<>'; expected `='", + NULL + }; + + do_parser_test< header_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(headers_7); +ATF_TEST_CASE_BODY(headers_7) +{ + const char* input = + "Content-Type: application/X-atf-headers-test; version=\n" + ; + + const char* exp_calls[] = { + NULL + }; + + const char* exp_errors[] = { + "1: Unexpected token `<>'; expected word or quoted string", + NULL + }; + + do_parser_test< header_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(headers_8); +ATF_TEST_CASE_BODY(headers_8) +{ + const char* input = + "Content-Type: application/X-atf-headers-test; version=\"1234\n" + ; + + const char* exp_calls[] = { + NULL + }; + + const char* exp_errors[] = { + "1: Missing double quotes before end of line", + NULL + }; + + do_parser_test< header_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(headers_9); +ATF_TEST_CASE_BODY(headers_9) +{ + const char* input = + "Content-Type: application/X-atf-headers-test; version=1234\"\n" + ; + + const char* exp_calls[] = { + NULL + }; + + const char* exp_errors[] = { + "1: Missing double quotes before end of line", + NULL + }; + + do_parser_test< header_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(headers_10); +ATF_TEST_CASE_BODY(headers_10) +{ + const char* input = + "Content-Type: application/X-atf-headers-test; version=1234\n" + ; + + const char* exp_calls[] = { + NULL + }; + + const char* exp_errors[] = { + "2: Unexpected token `<>'; expected a header name", + NULL + }; + + do_parser_test< header_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(headers_11); +ATF_TEST_CASE_BODY(headers_11) +{ + const char* input = + "Content-Type: application/X-atf-headers-test; version=\"1234\"\n" + ; + + const char* exp_calls[] = { + NULL + }; + + const char* exp_errors[] = { + "2: Unexpected token `<>'; expected a header name", + NULL + }; + + do_parser_test< header_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(headers_12); +ATF_TEST_CASE_BODY(headers_12) +{ + const char* input = + "Content-Type: application/X-atf-headers-test; version=\"1234\"\n" + "a b\n" + "a-b:\n" + "a-b: foo;\n" + "a-b: foo; var\n" + "a-b: foo; var=\n" + "a-b: foo; var=\"a\n" + "a-b: foo; var=a\"\n" + "a-b: foo; var=\"a\";\n" + "a-b: foo; var=\"a\"; second\n" + "a-b: foo; var=\"a\"; second=\n" + "a-b: foo; var=\"a\"; second=\"b\n" + "a-b: foo; var=\"a\"; second=b\"\n" + "a-b: foo; var=\"a\"; second=\"b\"\n" + ; + + const char* exp_calls[] = { + NULL + }; + + const char* exp_errors[] = { + "2: Unexpected token `b'; expected `:'", + "3: Unexpected token `<>'; expected a textual value", + "4: Unexpected token `<>'; expected an attribute name", + "5: Unexpected token `<>'; expected `='", + "6: Unexpected token `<>'; expected word or quoted string", + "7: Missing double quotes before end of line", + "8: Missing double quotes before end of line", + "9: Unexpected token `<>'; expected an attribute name", + "10: Unexpected token `<>'; expected `='", + "11: Unexpected token `<>'; expected word or quoted string", + "12: Missing double quotes before end of line", + "13: Missing double quotes before end of line", + NULL + }; + + do_parser_test< header_reader >(input, exp_calls, exp_errors); +} + +// ------------------------------------------------------------------------ +// Main. +// ------------------------------------------------------------------------ + +ATF_INIT_TEST_CASES(tcs) +{ + // Add test cases for the "parse_error" class. + ATF_ADD_TEST_CASE(tcs, parse_error_to_string); + + // Add test cases for the "parse_errors" class. + ATF_ADD_TEST_CASE(tcs, parse_errors_what); + + // Add test cases for the "token" class. + ATF_ADD_TEST_CASE(tcs, token_getters); + + // Add test cases for the "tokenizer" class. + ATF_ADD_TEST_CASE(tcs, tokenizer_minimal_nows); + ATF_ADD_TEST_CASE(tcs, tokenizer_minimal_ws); + ATF_ADD_TEST_CASE(tcs, tokenizer_delims_nows); + ATF_ADD_TEST_CASE(tcs, tokenizer_delims_ws); + ATF_ADD_TEST_CASE(tcs, tokenizer_keywords_nows); + ATF_ADD_TEST_CASE(tcs, tokenizer_keywords_ws); + ATF_ADD_TEST_CASE(tcs, tokenizer_quotes_nows); + ATF_ADD_TEST_CASE(tcs, tokenizer_quotes_ws); + + // Add the tests for the headers parser. + + // Add the test cases for the header file. + ATF_ADD_TEST_CASE(tcs, headers_1); + ATF_ADD_TEST_CASE(tcs, headers_2); + ATF_ADD_TEST_CASE(tcs, headers_3); + ATF_ADD_TEST_CASE(tcs, headers_4); + ATF_ADD_TEST_CASE(tcs, headers_5); + ATF_ADD_TEST_CASE(tcs, headers_6); + ATF_ADD_TEST_CASE(tcs, headers_7); + ATF_ADD_TEST_CASE(tcs, headers_8); + ATF_ADD_TEST_CASE(tcs, headers_9); + ATF_ADD_TEST_CASE(tcs, headers_10); + ATF_ADD_TEST_CASE(tcs, headers_11); + ATF_ADD_TEST_CASE(tcs, headers_12); +} diff --git a/external/bsd/atf/dist/atf-c++/detail/process.cpp b/external/bsd/atf/dist/atf-c++/detail/process.cpp new file mode 100644 index 000000000..f7ae6d49d --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/detail/process.cpp @@ -0,0 +1,355 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2008 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +extern "C" { +#include + +#include "../../atf-c/error.h" + +#include "../../atf-c/detail/process.h" +} + +#include + +#include "exceptions.hpp" +#include "process.hpp" +#include "sanity.hpp" + +namespace detail = atf::process::detail; +namespace impl = atf::process; +#define IMPL_NAME "atf::process" + +// ------------------------------------------------------------------------ +// Auxiliary functions. +// ------------------------------------------------------------------------ + +template< class C > +atf::auto_array< const char* > +collection_to_argv(const C& c) +{ + atf::auto_array< const char* > argv(new const char*[c.size() + 1]); + + std::size_t pos = 0; + for (typename C::const_iterator iter = c.begin(); iter != c.end(); + iter++) { + argv[pos] = (*iter).c_str(); + pos++; + } + INV(pos == c.size()); + argv[pos] = NULL; + + return argv; +} + +template< class C > +C +argv_to_collection(const char* const* argv) +{ + C c; + + for (const char* const* iter = argv; *iter != NULL; iter++) + c.push_back(std::string(*iter)); + + return c; +} + +// ------------------------------------------------------------------------ +// The "argv_array" type. +// ------------------------------------------------------------------------ + +impl::argv_array::argv_array(void) : + m_exec_argv(collection_to_argv(m_args)) +{ +} + +impl::argv_array::argv_array(const char* arg1, ...) +{ + m_args.push_back(arg1); + + { + va_list ap; + const char* nextarg; + + va_start(ap, arg1); + while ((nextarg = va_arg(ap, const char*)) != NULL) + m_args.push_back(nextarg); + va_end(ap); + } + + ctor_init_exec_argv(); +} + +impl::argv_array::argv_array(const char* const* ca) : + m_args(argv_to_collection< args_vector >(ca)), + m_exec_argv(collection_to_argv(m_args)) +{ +} + +impl::argv_array::argv_array(const argv_array& a) : + m_args(a.m_args), + m_exec_argv(collection_to_argv(m_args)) +{ +} + +void +impl::argv_array::ctor_init_exec_argv(void) +{ + m_exec_argv = collection_to_argv(m_args); +} + +const char* const* +impl::argv_array::exec_argv(void) + const +{ + return m_exec_argv.get(); +} + +impl::argv_array::size_type +impl::argv_array::size(void) + const +{ + return m_args.size(); +} + +const char* +impl::argv_array::operator[](int idx) + const +{ + return m_args[idx].c_str(); +} + +impl::argv_array::const_iterator +impl::argv_array::begin(void) + const +{ + return m_args.begin(); +} + +impl::argv_array::const_iterator +impl::argv_array::end(void) + const +{ + return m_args.end(); +} + +impl::argv_array& +impl::argv_array::operator=(const argv_array& a) +{ + if (this != &a) { + m_args = a.m_args; + m_exec_argv = collection_to_argv(m_args); + } + return *this; +} + +// ------------------------------------------------------------------------ +// The "stream" types. +// ------------------------------------------------------------------------ + +impl::basic_stream::basic_stream(void) : + m_inited(false) +{ +} + +impl::basic_stream::~basic_stream(void) +{ + if (m_inited) + atf_process_stream_fini(&m_sb); +} + +const atf_process_stream_t* +impl::basic_stream::get_sb(void) + const +{ + INV(m_inited); + return &m_sb; +} + +impl::stream_capture::stream_capture(void) +{ + atf_error_t err = atf_process_stream_init_capture(&m_sb); + if (atf_is_error(err)) + throw_atf_error(err); + m_inited = true; +} + +impl::stream_connect::stream_connect(const int src_fd, const int tgt_fd) +{ + atf_error_t err = atf_process_stream_init_connect(&m_sb, src_fd, tgt_fd); + if (atf_is_error(err)) + throw_atf_error(err); + m_inited = true; +} + +impl::stream_inherit::stream_inherit(void) +{ + atf_error_t err = atf_process_stream_init_inherit(&m_sb); + if (atf_is_error(err)) + throw_atf_error(err); + m_inited = true; +} + +impl::stream_redirect_fd::stream_redirect_fd(const int fd) +{ + atf_error_t err = atf_process_stream_init_redirect_fd(&m_sb, fd); + if (atf_is_error(err)) + throw_atf_error(err); + m_inited = true; +} + +impl::stream_redirect_path::stream_redirect_path(const fs::path& p) +{ + atf_error_t err = atf_process_stream_init_redirect_path(&m_sb, p.c_path()); + if (atf_is_error(err)) + throw_atf_error(err); + m_inited = true; +} + +// ------------------------------------------------------------------------ +// The "status" type. +// ------------------------------------------------------------------------ + +impl::status::status(atf_process_status_t& s) : + m_status(s) +{ +} + +impl::status::~status(void) +{ + atf_process_status_fini(&m_status); +} + +bool +impl::status::exited(void) + const +{ + return atf_process_status_exited(&m_status); +} + +int +impl::status::exitstatus(void) + const +{ + return atf_process_status_exitstatus(&m_status); +} + +bool +impl::status::signaled(void) + const +{ + return atf_process_status_signaled(&m_status); +} + +int +impl::status::termsig(void) + const +{ + return atf_process_status_termsig(&m_status); +} + +bool +impl::status::coredump(void) + const +{ + return atf_process_status_coredump(&m_status); +} + +// ------------------------------------------------------------------------ +// The "child" type. +// ------------------------------------------------------------------------ + +impl::child::child(atf_process_child_t& c) : + m_child(c), + m_waited(false) +{ +} + +impl::child::~child(void) +{ + if (!m_waited) { + ::kill(atf_process_child_pid(&m_child), SIGTERM); + + atf_process_status_t s; + atf_error_t err = atf_process_child_wait(&m_child, &s); + INV(!atf_is_error(err)); + atf_process_status_fini(&s); + } +} + +impl::status +impl::child::wait(void) +{ + atf_process_status_t s; + + atf_error_t err = atf_process_child_wait(&m_child, &s); + if (atf_is_error(err)) + throw_atf_error(err); + + m_waited = true; + return status(s); +} + +pid_t +impl::child::pid(void) + const +{ + return atf_process_child_pid(&m_child); +} + +int +impl::child::stdout_fd(void) +{ + return atf_process_child_stdout(&m_child); +} + +int +impl::child::stderr_fd(void) +{ + return atf_process_child_stderr(&m_child); +} + +// ------------------------------------------------------------------------ +// Free functions. +// ------------------------------------------------------------------------ + +void +detail::flush_streams(void) +{ + // This is a weird hack to ensure that the output of the parent process + // is flushed before executing a child which prevents, for example, the + // output of the atf-run hooks to appear before the output of atf-run + // itself. + // + // TODO: This should only be executed when inheriting the stdout or + // stderr file descriptors. However, the flushing is specific to the + // iostreams, so we cannot do it from the C library where all the process + // logic is performed. Come up with a better design. + std::cout.flush(); + std::cerr.flush(); +} diff --git a/external/bsd/atf/dist/atf-c++/detail/process.hpp b/external/bsd/atf/dist/atf-c++/detail/process.hpp new file mode 100644 index 000000000..bc55a5721 --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/detail/process.hpp @@ -0,0 +1,279 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2008 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#if !defined(_ATF_CXX_PROCESS_HPP_) +#define _ATF_CXX_PROCESS_HPP_ + +extern "C" { +#include + +#include "../../atf-c/error.h" + +#include "../../atf-c/detail/process.h" +} + +#include +#include + +#include "auto_array.hpp" +#include "exceptions.hpp" +#include "fs.hpp" + +namespace atf { +namespace process { + +class child; +class status; + +// ------------------------------------------------------------------------ +// The "argv_array" type. +// ------------------------------------------------------------------------ + +class argv_array { + typedef std::vector< std::string > args_vector; + args_vector m_args; + + // TODO: This is immutable, so we should be able to use + // std::tr1::shared_array instead when it becomes widely available. + // The reason would be to remove all copy constructors and assignment + // operators from this class. + auto_array< const char* > m_exec_argv; + void ctor_init_exec_argv(void); + +public: + typedef args_vector::const_iterator const_iterator; + typedef args_vector::size_type size_type; + + argv_array(void); + argv_array(const char*, ...); + explicit argv_array(const char* const*); + template< class C > explicit argv_array(const C&); + argv_array(const argv_array&); + + const char* const* exec_argv(void) const; + size_type size(void) const; + const char* operator[](int) const; + + const_iterator begin(void) const; + const_iterator end(void) const; + + argv_array& operator=(const argv_array&); +}; + +template< class C > +argv_array::argv_array(const C& c) +{ + for (typename C::const_iterator iter = c.begin(); iter != c.end(); + iter++) + m_args.push_back(*iter); + ctor_init_exec_argv(); +} + +// ------------------------------------------------------------------------ +// The "stream" types. +// ------------------------------------------------------------------------ + +class basic_stream { +protected: + atf_process_stream_t m_sb; + bool m_inited; + + const atf_process_stream_t* get_sb(void) const; + +public: + basic_stream(void); + ~basic_stream(void); +}; + +class stream_capture : basic_stream { + // Allow access to the getters. + template< class OutStream, class ErrStream > friend + child fork(void (*)(void*), const OutStream&, const ErrStream&, void*); + template< class OutStream, class ErrStream > friend + status exec(const atf::fs::path&, const argv_array&, + const OutStream&, const ErrStream&, void (*)(void)); + +public: + stream_capture(void); +}; + +class stream_connect : basic_stream { + // Allow access to the getters. + template< class OutStream, class ErrStream > friend + child fork(void (*)(void*), const OutStream&, const ErrStream&, void*); + template< class OutStream, class ErrStream > friend + status exec(const atf::fs::path&, const argv_array&, + const OutStream&, const ErrStream&, void (*)(void)); + +public: + stream_connect(const int, const int); +}; + +class stream_inherit : basic_stream { + // Allow access to the getters. + template< class OutStream, class ErrStream > friend + child fork(void (*)(void*), const OutStream&, const ErrStream&, void*); + template< class OutStream, class ErrStream > friend + status exec(const atf::fs::path&, const argv_array&, + const OutStream&, const ErrStream&, void (*)(void)); + +public: + stream_inherit(void); +}; + +class stream_redirect_fd : basic_stream { + // Allow access to the getters. + template< class OutStream, class ErrStream > friend + child fork(void (*)(void*), const OutStream&, const ErrStream&, void*); + template< class OutStream, class ErrStream > friend + status exec(const atf::fs::path&, const argv_array&, + const OutStream&, const ErrStream&, void (*)(void)); + +public: + stream_redirect_fd(const int); +}; + +class stream_redirect_path : basic_stream { + // Allow access to the getters. + template< class OutStream, class ErrStream > friend + child fork(void (*)(void*), const OutStream&, const ErrStream&, void*); + template< class OutStream, class ErrStream > friend + status exec(const atf::fs::path&, const argv_array&, + const OutStream&, const ErrStream&, void (*)(void)); + +public: + stream_redirect_path(const fs::path&); +}; + +// ------------------------------------------------------------------------ +// The "status" type. +// ------------------------------------------------------------------------ + +class status { + atf_process_status_t m_status; + + friend class child; + template< class OutStream, class ErrStream > friend + status exec(const atf::fs::path&, const argv_array&, + const OutStream&, const ErrStream&, void (*)(void)); + + status(atf_process_status_t&); + +public: + ~status(void); + + bool exited(void) const; + int exitstatus(void) const; + + bool signaled(void) const; + int termsig(void) const; + bool coredump(void) const; +}; + +// ------------------------------------------------------------------------ +// The "child" type. +// ------------------------------------------------------------------------ + +class child { + atf_process_child_t m_child; + bool m_waited; + + template< class OutStream, class ErrStream > friend + child fork(void (*)(void*), const OutStream&, const ErrStream&, void*); + + child(atf_process_child_t& c); + +public: + ~child(void); + + status wait(void); + + pid_t pid(void) const; + int stdout_fd(void); + int stderr_fd(void); +}; + +// ------------------------------------------------------------------------ +// Free functions. +// ------------------------------------------------------------------------ + +namespace detail { +void flush_streams(void); +} // namespace detail + +// TODO: The void* cookie can probably be templatized, thus also allowing +// const data structures. +template< class OutStream, class ErrStream > +child +fork(void (*start)(void*), const OutStream& outsb, + const ErrStream& errsb, void* v) +{ + atf_process_child_t c; + + detail::flush_streams(); + atf_error_t err = atf_process_fork(&c, start, outsb.get_sb(), + errsb.get_sb(), v); + if (atf_is_error(err)) + throw_atf_error(err); + + return child(c); +} + +template< class OutStream, class ErrStream > +status +exec(const atf::fs::path& prog, const argv_array& argv, + const OutStream& outsb, const ErrStream& errsb, + void (*prehook)(void)) +{ + atf_process_status_t s; + + detail::flush_streams(); + atf_error_t err = atf_process_exec_array(&s, prog.c_path(), + argv.exec_argv(), + outsb.get_sb(), + errsb.get_sb(), + prehook); + if (atf_is_error(err)) + throw_atf_error(err); + + return status(s); +} + +template< class OutStream, class ErrStream > +status +exec(const atf::fs::path& prog, const argv_array& argv, + const OutStream& outsb, const ErrStream& errsb) +{ + return exec(prog, argv, outsb, errsb, NULL); +} + +} // namespace process +} // namespace atf + +#endif // !defined(_ATF_CXX_PROCESS_HPP_) diff --git a/external/bsd/atf/dist/atf-c++/detail/process_test.cpp b/external/bsd/atf/dist/atf-c++/detail/process_test.cpp new file mode 100644 index 000000000..d13ab9453 --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/detail/process_test.cpp @@ -0,0 +1,357 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2008 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#include +#include + +#include "../macros.hpp" + +#include "process.hpp" +#include "test_helpers.hpp" + +// TODO: Testing the fork function is a huge task and I'm afraid of +// copy/pasting tons of stuff from the C version. I'd rather not do that +// until some code can be shared, which cannot happen until the C++ binding +// is cleaned by a fair amount. Instead... just rely (at the moment) on +// the system tests for the tools using this module. + +// ------------------------------------------------------------------------ +// Auxiliary functions. +// ------------------------------------------------------------------------ + +static +std::size_t +array_size(const char* const* array) +{ + std::size_t size = 0; + + for (const char* const* ptr = array; *ptr != NULL; ptr++) + size++; + + return size; +} + +static +atf::process::status +exec_process_helpers(const atf::tests::tc& tc, const char* helper_name) +{ + using atf::process::exec; + + std::vector< std::string > argv; + argv.push_back(get_process_helpers_path(tc).leaf_name()); + argv.push_back(helper_name); + + return exec(get_process_helpers_path(tc), + atf::process::argv_array(argv), + atf::process::stream_inherit(), + atf::process::stream_inherit()); +} + +// ------------------------------------------------------------------------ +// Tests for the "argv_array" type. +// ------------------------------------------------------------------------ + +ATF_TEST_CASE(argv_array_init_carray); +ATF_TEST_CASE_HEAD(argv_array_init_carray) +{ + set_md_var("descr", "Tests that argv_array is correctly constructed " + "from a C-style array of strings"); +} +ATF_TEST_CASE_BODY(argv_array_init_carray) +{ + { + const char* const carray[] = { NULL }; + atf::process::argv_array argv(carray); + + ATF_REQUIRE_EQ(argv.size(), 0); + } + + { + const char* const carray[] = { "arg0", NULL }; + atf::process::argv_array argv(carray); + + ATF_REQUIRE_EQ(argv.size(), 1); + ATF_REQUIRE(std::strcmp(argv[0], carray[0]) == 0); + } + + { + const char* const carray[] = { "arg0", "arg1", "arg2", NULL }; + atf::process::argv_array argv(carray); + + ATF_REQUIRE_EQ(argv.size(), 3); + ATF_REQUIRE(std::strcmp(argv[0], carray[0]) == 0); + ATF_REQUIRE(std::strcmp(argv[1], carray[1]) == 0); + ATF_REQUIRE(std::strcmp(argv[2], carray[2]) == 0); + } +} + +ATF_TEST_CASE(argv_array_init_col); +ATF_TEST_CASE_HEAD(argv_array_init_col) +{ + set_md_var("descr", "Tests that argv_array is correctly constructed " + "from a string collection"); +} +ATF_TEST_CASE_BODY(argv_array_init_col) +{ + { + std::vector< std::string > col; + atf::process::argv_array argv(col); + + ATF_REQUIRE_EQ(argv.size(), 0); + } + + { + std::vector< std::string > col; + col.push_back("arg0"); + atf::process::argv_array argv(col); + + ATF_REQUIRE_EQ(argv.size(), 1); + ATF_REQUIRE_EQ(argv[0], col[0]); + } + + { + std::vector< std::string > col; + col.push_back("arg0"); + col.push_back("arg1"); + col.push_back("arg2"); + atf::process::argv_array argv(col); + + ATF_REQUIRE_EQ(argv.size(), 3); + ATF_REQUIRE_EQ(argv[0], col[0]); + ATF_REQUIRE_EQ(argv[1], col[1]); + ATF_REQUIRE_EQ(argv[2], col[2]); + } +} + +ATF_TEST_CASE(argv_array_init_empty); +ATF_TEST_CASE_HEAD(argv_array_init_empty) +{ + set_md_var("descr", "Tests that argv_array is correctly constructed " + "by the default constructor"); +} +ATF_TEST_CASE_BODY(argv_array_init_empty) +{ + atf::process::argv_array argv; + + ATF_REQUIRE_EQ(argv.size(), 0); +} + +ATF_TEST_CASE(argv_array_init_varargs); +ATF_TEST_CASE_HEAD(argv_array_init_varargs) +{ + set_md_var("descr", "Tests that argv_array is correctly constructed " + "from a variable list of arguments"); +} +ATF_TEST_CASE_BODY(argv_array_init_varargs) +{ + { + atf::process::argv_array argv("arg0", NULL); + + ATF_REQUIRE_EQ(argv.size(), 1); + ATF_REQUIRE_EQ(argv[0], std::string("arg0")); + } + + { + atf::process::argv_array argv("arg0", "arg1", "arg2", NULL); + + ATF_REQUIRE_EQ(argv.size(), 3); + ATF_REQUIRE_EQ(argv[0], std::string("arg0")); + ATF_REQUIRE_EQ(argv[1], std::string("arg1")); + ATF_REQUIRE_EQ(argv[2], std::string("arg2")); + } +} + +ATF_TEST_CASE(argv_array_assign); +ATF_TEST_CASE_HEAD(argv_array_assign) +{ + set_md_var("descr", "Tests that assigning an argv_array works"); +} +ATF_TEST_CASE_BODY(argv_array_assign) +{ + using atf::process::argv_array; + + const char* const carray1[] = { "arg1", NULL }; + const char* const carray2[] = { "arg1", "arg2", NULL }; + + std::auto_ptr< argv_array > argv1(new argv_array(carray1)); + std::auto_ptr< argv_array > argv2(new argv_array(carray2)); + + *argv2 = *argv1; + ATF_REQUIRE_EQ(argv2->size(), argv1->size()); + ATF_REQUIRE(std::strcmp((*argv2)[0], (*argv1)[0]) == 0); + + ATF_REQUIRE(argv2->exec_argv() != argv1->exec_argv()); + argv1.release(); + { + const char* const* eargv2 = argv2->exec_argv(); + ATF_REQUIRE(std::strcmp(eargv2[0], carray1[0]) == 0); + ATF_REQUIRE_EQ(eargv2[1], static_cast< const char* >(NULL)); + } + + argv2.release(); +} + +ATF_TEST_CASE(argv_array_copy); +ATF_TEST_CASE_HEAD(argv_array_copy) +{ + set_md_var("descr", "Tests that copying an argv_array constructed from " + "a C-style array of strings works"); +} +ATF_TEST_CASE_BODY(argv_array_copy) +{ + using atf::process::argv_array; + + const char* const carray[] = { "arg0", NULL }; + + std::auto_ptr< argv_array > argv1(new argv_array(carray)); + std::auto_ptr< argv_array > argv2(new argv_array(*argv1)); + + ATF_REQUIRE_EQ(argv2->size(), argv1->size()); + ATF_REQUIRE(std::strcmp((*argv2)[0], (*argv1)[0]) == 0); + + ATF_REQUIRE(argv2->exec_argv() != argv1->exec_argv()); + argv1.release(); + { + const char* const* eargv2 = argv2->exec_argv(); + ATF_REQUIRE(std::strcmp(eargv2[0], carray[0]) == 0); + ATF_REQUIRE_EQ(eargv2[1], static_cast< const char* >(NULL)); + } + + argv2.release(); +} + +ATF_TEST_CASE(argv_array_exec_argv); +ATF_TEST_CASE_HEAD(argv_array_exec_argv) +{ + set_md_var("descr", "Tests that the exec argv provided by an argv_array " + "is correct"); +} +ATF_TEST_CASE_BODY(argv_array_exec_argv) +{ + using atf::process::argv_array; + + { + argv_array argv; + const char* const* eargv = argv.exec_argv(); + ATF_REQUIRE_EQ(array_size(eargv), 0); + ATF_REQUIRE_EQ(eargv[0], static_cast< const char* >(NULL)); + } + + { + const char* const carray[] = { "arg0", NULL }; + argv_array argv(carray); + const char* const* eargv = argv.exec_argv(); + ATF_REQUIRE_EQ(array_size(eargv), 1); + ATF_REQUIRE(std::strcmp(eargv[0], "arg0") == 0); + ATF_REQUIRE_EQ(eargv[1], static_cast< const char* >(NULL)); + } + + { + std::vector< std::string > col; + col.push_back("arg0"); + argv_array argv(col); + const char* const* eargv = argv.exec_argv(); + ATF_REQUIRE_EQ(array_size(eargv), 1); + ATF_REQUIRE(std::strcmp(eargv[0], "arg0") == 0); + ATF_REQUIRE_EQ(eargv[1], static_cast< const char* >(NULL)); + } +} + +ATF_TEST_CASE(argv_array_iter); +ATF_TEST_CASE_HEAD(argv_array_iter) +{ + set_md_var("descr", "Tests that an argv_array can be iterated"); +} +ATF_TEST_CASE_BODY(argv_array_iter) +{ + using atf::process::argv_array; + + std::vector< std::string > vector; + vector.push_back("arg0"); + vector.push_back("arg1"); + vector.push_back("arg2"); + + argv_array argv(vector); + ATF_REQUIRE_EQ(argv.size(), 3); + std::vector< std::string >::size_type pos = 0; + for (argv_array::const_iterator iter = argv.begin(); iter != argv.end(); + iter++) { + ATF_REQUIRE_EQ(*iter, vector[pos]); + pos++; + } +} + +// ------------------------------------------------------------------------ +// Tests cases for the free functions. +// ------------------------------------------------------------------------ + +ATF_TEST_CASE(exec_failure); +ATF_TEST_CASE_HEAD(exec_failure) +{ + set_md_var("descr", "Tests execing a command that reports failure"); +} +ATF_TEST_CASE_BODY(exec_failure) +{ + const atf::process::status s = exec_process_helpers(*this, "exit-failure"); + ATF_REQUIRE(s.exited()); + ATF_REQUIRE_EQ(s.exitstatus(), EXIT_FAILURE); +} + +ATF_TEST_CASE(exec_success); +ATF_TEST_CASE_HEAD(exec_success) +{ + set_md_var("descr", "Tests execing a command that reports success"); +} +ATF_TEST_CASE_BODY(exec_success) +{ + const atf::process::status s = exec_process_helpers(*this, "exit-success"); + ATF_REQUIRE(s.exited()); + ATF_REQUIRE_EQ(s.exitstatus(), EXIT_SUCCESS); +} + +// ------------------------------------------------------------------------ +// Main. +// ------------------------------------------------------------------------ + +ATF_INIT_TEST_CASES(tcs) +{ + // Add the test cases for the "argv_array" type. + ATF_ADD_TEST_CASE(tcs, argv_array_assign); + ATF_ADD_TEST_CASE(tcs, argv_array_copy); + ATF_ADD_TEST_CASE(tcs, argv_array_exec_argv); + ATF_ADD_TEST_CASE(tcs, argv_array_init_carray); + ATF_ADD_TEST_CASE(tcs, argv_array_init_col); + ATF_ADD_TEST_CASE(tcs, argv_array_init_empty); + ATF_ADD_TEST_CASE(tcs, argv_array_init_varargs); + ATF_ADD_TEST_CASE(tcs, argv_array_iter); + + // Add the test cases for the free functions. + ATF_ADD_TEST_CASE(tcs, exec_failure); + ATF_ADD_TEST_CASE(tcs, exec_success); +} diff --git a/external/bsd/atf/dist/atf-c++/detail/sanity.hpp b/external/bsd/atf/dist/atf-c++/detail/sanity.hpp new file mode 100644 index 000000000..6021a6e68 --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/detail/sanity.hpp @@ -0,0 +1,37 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#if !defined(_ATF_CXX_SANITY_HPP_) +#define _ATF_CXX_SANITY_HPP_ + +extern "C" { +#include "../../atf-c/detail/sanity.h" +} + +#endif // !defined(_ATF_CXX_SANITY_HPP_) diff --git a/external/bsd/atf/dist/atf-c++/detail/sanity_test.cpp b/external/bsd/atf/dist/atf-c++/detail/sanity_test.cpp new file mode 100644 index 000000000..8d3a07eb8 --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/detail/sanity_test.cpp @@ -0,0 +1,41 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2009 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#include "../macros.hpp" + +ATF_TEST_CASE_WITHOUT_HEAD(nothing); +ATF_TEST_CASE_BODY(nothing) +{ + // TODO +} + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, nothing); +} diff --git a/external/bsd/atf/dist/atf-c++/detail/test_helpers.cpp b/external/bsd/atf/dist/atf-c++/detail/test_helpers.cpp new file mode 100644 index 000000000..191649d03 --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/detail/test_helpers.cpp @@ -0,0 +1,119 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2009 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#include +#include +#include +#include + +#include "../check.hpp" +#include "../config.hpp" +#include "../macros.hpp" + +#include "fs.hpp" +#include "process.hpp" +#include "test_helpers.hpp" + +void +build_check_cxx_o_aux(const atf::fs::path& sfile, const char* failmsg, + const bool expect_pass) +{ + std::vector< std::string > optargs; + optargs.push_back("-I" + atf::config::get("atf_includedir")); + optargs.push_back("-Wall"); + optargs.push_back("-Werror"); + + const bool result = atf::check::build_cxx_o( + sfile.str(), "test.o", atf::process::argv_array(optargs)); + if ((expect_pass && !result) || (!expect_pass && result)) + ATF_FAIL(failmsg); +} + +void +build_check_cxx_o(const atf::tests::tc& tc, const char* sfile, + const char* failmsg, const bool expect_pass) +{ + const atf::fs::path sfilepath = + atf::fs::path(tc.get_config_var("srcdir")) / sfile; + build_check_cxx_o_aux(sfilepath, failmsg, expect_pass); +} + +void +header_check(const char *hdrname) +{ + std::ofstream srcfile("test.c"); + ATF_REQUIRE(srcfile); + srcfile << "#include <" << hdrname << ">\n"; + srcfile.close(); + + const std::string failmsg = std::string("Header check failed; ") + + hdrname + " is not self-contained"; + build_check_cxx_o_aux(atf::fs::path("test.c"), failmsg.c_str(), true); +} + +atf::fs::path +get_process_helpers_path(const atf::tests::tc& tc) +{ + return atf::fs::path(tc.get_config_var("srcdir")) / + ".." / "atf-c" / "detail" / "process_helpers"; +} + +void +test_helpers_detail::check_equal(const char* expected[], + const string_vector& actual) +{ + const char** expected_iter = expected; + string_vector::const_iterator actual_iter = actual.begin(); + + bool equals = true; + while (equals && *expected_iter != NULL && actual_iter != actual.end()) { + if (*expected_iter != *actual_iter) { + equals = false; + } else { + expected_iter++; + actual_iter++; + } + } + if (equals && ((*expected_iter == NULL && actual_iter != actual.end()) || + (*expected_iter != NULL && actual_iter == actual.end()))) + equals = false; + + if (!equals) { + std::cerr << "EXPECTED:\n"; + for (expected_iter = expected; *expected_iter != NULL; expected_iter++) + std::cerr << *expected_iter << "\n"; + + std::cerr << "ACTUAL:\n"; + for (actual_iter = actual.begin(); actual_iter != actual.end(); + actual_iter++) + std::cerr << *actual_iter << "\n"; + + ATF_FAIL("Expected results differ to actual values"); + } +} diff --git a/external/bsd/atf/dist/atf-c++/detail/test_helpers.hpp b/external/bsd/atf/dist/atf-c++/detail/test_helpers.hpp new file mode 100644 index 000000000..4a39331de --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/detail/test_helpers.hpp @@ -0,0 +1,164 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2009 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#if defined(TESTS_ATF_ATF_CXX_TEST_HELPERS_H) +# error "Cannot include test_helpers.hpp more than once." +#else +# define TESTS_ATF_ATF_CXX_TEST_HELPERS_H +#endif + +#include +#include +#include +#include + +#include "../macros.hpp" +#include "../tests.hpp" +#include "parser.hpp" +#include "process.hpp" +#include "text.hpp" + +#define HEADER_TC(name, hdrname) \ + ATF_TEST_CASE(name); \ + ATF_TEST_CASE_HEAD(name) \ + { \ + set_md_var("descr", "Tests that the " hdrname " file can be " \ + "included on its own, without any prerequisites"); \ + } \ + ATF_TEST_CASE_BODY(name) \ + { \ + header_check(hdrname); \ + } + +#define BUILD_TC(name, sfile, descr, failmsg) \ + ATF_TEST_CASE(name); \ + ATF_TEST_CASE_HEAD(name) \ + { \ + set_md_var("descr", descr); \ + } \ + ATF_TEST_CASE_BODY(name) \ + { \ + build_check_cxx_o(*this, sfile, failmsg, true); \ + } + +#define BUILD_TC_FAIL(name, sfile, descr, failmsg) \ + ATF_TEST_CASE(name); \ + ATF_TEST_CASE_HEAD(name) \ + { \ + set_md_var("descr", descr); \ + } \ + ATF_TEST_CASE_BODY(name) \ + { \ + build_check_cxx_o(*this, sfile, failmsg, false); \ + } + +namespace atf { +namespace tests { +class tc; +} +} + +void header_check(const char*); +void build_check_cxx_o(const atf::tests::tc&, const char*, const char*, bool); +atf::fs::path get_process_helpers_path(const atf::tests::tc&); + +struct run_h_tc_data { + const atf::tests::vars_map& m_config; + + run_h_tc_data(const atf::tests::vars_map& config) : + m_config(config) {} +}; + +template< class TestCase > +void +run_h_tc_child(void* v) +{ + run_h_tc_data* data = static_cast< run_h_tc_data* >(v); + + TestCase tc; + tc.init(data->m_config); + tc.run("result"); + std::exit(EXIT_SUCCESS); +} + +template< class TestCase > +void +run_h_tc(atf::tests::vars_map config = atf::tests::vars_map()) +{ + run_h_tc_data data(config); + atf::process::child c = atf::process::fork( + run_h_tc_child< TestCase >, + atf::process::stream_redirect_path(atf::fs::path("stdout")), + atf::process::stream_redirect_path(atf::fs::path("stderr")), + &data); + const atf::process::status s = c.wait(); + ATF_REQUIRE(s.exited()); +} + +namespace test_helpers_detail { + +typedef std::vector< std::string > string_vector; + +template< class Reader > +std::pair< string_vector, string_vector > +do_read(const char* input) +{ + string_vector errors; + + std::istringstream is(input); + Reader reader(is); + try { + reader.read(); + } catch (const atf::parser::parse_errors& pes) { + for (std::vector< atf::parser::parse_error >::const_iterator iter = + pes.begin(); iter != pes.end(); iter++) + errors.push_back(*iter); + } catch (const atf::parser::parse_error& pe) { + ATF_FAIL("Raised a lonely parse error: " + + atf::text::to_string(pe.first) + ": " + pe.second); + } + + return std::make_pair(reader.m_calls, errors); +} + +void check_equal(const char*[], const string_vector&); + +} // namespace test_helpers_detail + +template< class Reader > +void +do_parser_test(const char* input, const char* exp_calls[], + const char* exp_errors[]) +{ + const std::pair< test_helpers_detail::string_vector, + test_helpers_detail::string_vector > + actual = test_helpers_detail::do_read< Reader >(input); + test_helpers_detail::check_equal(exp_calls, actual.first); + test_helpers_detail::check_equal(exp_errors, actual.second); +} diff --git a/external/bsd/atf/dist/atf-c++/detail/text.cpp b/external/bsd/atf/dist/atf-c++/detail/text.cpp new file mode 100644 index 000000000..66eebf0a7 --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/detail/text.cpp @@ -0,0 +1,160 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +extern "C" { +#include +} + +#include +#include + +extern "C" { +#include "../../atf-c/error.h" + +#include "../../atf-c/detail/text.h" +} + +#include "exceptions.hpp" +#include "text.hpp" + +namespace impl = atf::text; +#define IMPL_NAME "atf::text" + +char* +impl::duplicate(const char* str) +{ + char* copy = new char[std::strlen(str) + 1]; + std::strcpy(copy, str); + return copy; +} + +bool +impl::match(const std::string& str, const std::string& regex) +{ + bool found; + + // Special case: regcomp does not like empty regular expressions. + if (regex.empty()) { + found = str.empty(); + } else { + ::regex_t preg; + + if (::regcomp(&preg, regex.c_str(), REG_EXTENDED) != 0) + throw std::runtime_error("Invalid regular expression '" + regex + + "'"); + + const int res = ::regexec(&preg, str.c_str(), 0, NULL, 0); + regfree(&preg); + if (res != 0 && res != REG_NOMATCH) + throw std::runtime_error("Invalid regular expression " + regex); + + found = res == 0; + } + + return found; +} + +std::string +impl::to_lower(const std::string& str) +{ + std::string lc; + for (std::string::const_iterator iter = str.begin(); iter != str.end(); + iter++) + lc += std::tolower(*iter); + return lc; +} + +std::vector< std::string > +impl::split(const std::string& str, const std::string& delim) +{ + std::vector< std::string > words; + + std::string::size_type pos = 0, newpos = 0; + while (pos < str.length() && newpos != std::string::npos) { + newpos = str.find(delim, pos); + if (newpos != pos) + words.push_back(str.substr(pos, newpos - pos)); + pos = newpos + delim.length(); + } + + return words; +} + +std::string +impl::trim(const std::string& str) +{ + std::string::size_type pos1 = str.find_first_not_of(" \t"); + std::string::size_type pos2 = str.find_last_not_of(" \t"); + + if (pos1 == std::string::npos && pos2 == std::string::npos) + return ""; + else if (pos1 == std::string::npos) + return str.substr(0, str.length() - pos2); + else if (pos2 == std::string::npos) + return str.substr(pos1); + else + return str.substr(pos1, pos2 - pos1 + 1); +} + +bool +impl::to_bool(const std::string& str) +{ + bool b; + + atf_error_t err = atf_text_to_bool(str.c_str(), &b); + if (atf_is_error(err)) + throw_atf_error(err); + + return b; +} + +int64_t +impl::to_bytes(std::string str) +{ + if (str.empty()) + throw std::runtime_error("Empty value"); + + const char unit = str[str.length() - 1]; + int64_t multiplier; + switch (unit) { + case 'k': case 'K': multiplier = 1 << 10; break; + case 'm': case 'M': multiplier = 1 << 20; break; + case 'g': case 'G': multiplier = 1 << 30; break; + case 't': case 'T': multiplier = int64_t(1) << 40; break; + default: + if (!std::isdigit(unit)) + throw std::runtime_error(std::string("Unknown size unit '") + unit + + "'"); + multiplier = 1; + } + if (multiplier != 1) + str.erase(str.length() - 1); + + return to_type< int64_t >(str) * multiplier; +} diff --git a/external/bsd/atf/dist/atf-c++/detail/text.hpp b/external/bsd/atf/dist/atf-c++/detail/text.hpp new file mode 100644 index 000000000..6a1b027c1 --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/detail/text.hpp @@ -0,0 +1,153 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#if !defined(_ATF_CXX_TEXT_HPP_) +#define _ATF_CXX_TEXT_HPP_ + +extern "C" { +#include +} + +#include +#include +#include +#include + +namespace atf { +namespace text { + +//! +//! \brief Duplicates a C string using the new[] allocator. +//! +//! Replaces the functionality of strdup by using the new[] allocator and +//! thus allowing the resulting memory to be managed by utils::auto_array. +//! +char* duplicate(const char*); + +//! +//! \brief Joins multiple words into a string. +//! +//! Joins a list of words into a string, separating them using the provided +//! separator. Empty words are not omitted. +//! +template< class T > +std::string +join(const T& words, const std::string& separator) +{ + std::string str; + + typename T::const_iterator iter = words.begin(); + bool done = iter == words.end(); + while (!done) { + str += *iter; + iter++; + if (iter != words.end()) + str += separator; + else + done = true; + } + + return str; +} + +//! +//! \brief Checks if the string matches a regular expression. +//! +bool match(const std::string&, const std::string&); + +//! +//! \brief Splits a string into words. +//! +//! Splits the given string into multiple words, all separated by the +//! given delimiter. Multiple occurrences of the same delimiter are +//! not condensed so that rejoining the words later on using the same +//! delimiter results in the original string. +//! +std::vector< std::string > split(const std::string&, const std::string&); + +//! +//! \brief Removes whitespace from the beginning and end of a string. +//! +std::string trim(const std::string&); + +//! +//! \brief Converts a string to a boolean value. +//! +bool to_bool(const std::string&); + +//! +//! \brief Converts the given string to a bytes size. +//! +int64_t to_bytes(std::string); + +//! +//! \brief Changes the case of a string to lowercase. +//! +//! Returns a new string that is a lowercased version of the original +//! one. +//! +std::string to_lower(const std::string&); + +//! +//! \brief Converts the given object to a string. +//! +//! Returns a string with the representation of the given object. There +//! must exist an operator<< method for that object. +//! +template< class T > +std::string +to_string(const T& ob) +{ + std::ostringstream ss; + ss << ob; + return ss.str(); +} + +//! +//! \brief Converts the given string to another type. +//! +//! Attempts to convert the given string to the requested type. Throws +//! an exception if the conversion failed. +//! +template< class T > +T +to_type(const std::string& str) +{ + std::istringstream ss(str); + T value; + ss >> value; + if (!ss.eof() || (ss.eof() && (ss.fail() || ss.bad()))) + throw std::runtime_error("Cannot convert string to requested type"); + return value; +} + +} // namespace text +} // namespace atf + +#endif // !defined(_ATF_CXX_TEXT_HPP_) diff --git a/external/bsd/atf/dist/atf-c++/detail/text_test.cpp b/external/bsd/atf/dist/atf-c++/detail/text_test.cpp new file mode 100644 index 000000000..b7c0ba1af --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/detail/text_test.cpp @@ -0,0 +1,390 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#include +#include +#include + +#include "../macros.hpp" + +#include "text.hpp" + +// ------------------------------------------------------------------------ +// Test cases for the free functions. +// ------------------------------------------------------------------------ + +ATF_TEST_CASE(duplicate); +ATF_TEST_CASE_HEAD(duplicate) +{ + set_md_var("descr", "Tests the duplicate function"); +} +ATF_TEST_CASE_BODY(duplicate) +{ + using atf::text::duplicate; + + const char* orig = "foo"; + + char* copy = duplicate(orig); + ATF_REQUIRE_EQ(std::strlen(copy), 3); + ATF_REQUIRE(std::strcmp(copy, "foo") == 0); + + std::strcpy(copy, "bar"); + ATF_REQUIRE(std::strcmp(copy, "bar") == 0); + ATF_REQUIRE(std::strcmp(orig, "foo") == 0); +} + +ATF_TEST_CASE(join); +ATF_TEST_CASE_HEAD(join) +{ + set_md_var("descr", "Tests the join function"); +} +ATF_TEST_CASE_BODY(join) +{ + using atf::text::join; + + // First set of tests using a non-sorted collection, std::vector. + { + std::vector< std::string > words; + std::string str; + + words.clear(); + str = join(words, ","); + ATF_REQUIRE_EQ(str, ""); + + words.clear(); + words.push_back(""); + str = join(words, ","); + ATF_REQUIRE_EQ(str, ""); + + words.clear(); + words.push_back(""); + words.push_back(""); + str = join(words, ","); + ATF_REQUIRE_EQ(str, ","); + + words.clear(); + words.push_back("foo"); + words.push_back(""); + words.push_back("baz"); + str = join(words, ","); + ATF_REQUIRE_EQ(str, "foo,,baz"); + + words.clear(); + words.push_back("foo"); + words.push_back("bar"); + words.push_back("baz"); + str = join(words, ","); + ATF_REQUIRE_EQ(str, "foo,bar,baz"); + } + + // Second set of tests using a sorted collection, std::set. + { + std::set< std::string > words; + std::string str; + + words.clear(); + str = join(words, ","); + ATF_REQUIRE_EQ(str, ""); + + words.clear(); + words.insert(""); + str = join(words, ","); + ATF_REQUIRE_EQ(str, ""); + + words.clear(); + words.insert("foo"); + words.insert(""); + words.insert("baz"); + str = join(words, ","); + ATF_REQUIRE_EQ(str, ",baz,foo"); + + words.clear(); + words.insert("foo"); + words.insert("bar"); + words.insert("baz"); + str = join(words, ","); + ATF_REQUIRE_EQ(str, "bar,baz,foo"); + } +} + +ATF_TEST_CASE(match); +ATF_TEST_CASE_HEAD(match) +{ + set_md_var("descr", "Tests the match function"); +} +ATF_TEST_CASE_BODY(match) +{ + using atf::text::match; + + ATF_REQUIRE_THROW(std::runtime_error, match("", "[")); + + ATF_REQUIRE(match("", "")); + ATF_REQUIRE(!match("foo", "")); + + ATF_REQUIRE(match("", ".*")); + ATF_REQUIRE(match("", "[a-z]*")); + + ATF_REQUIRE(match("hello", "hello")); + ATF_REQUIRE(match("hello", "[a-z]+")); + ATF_REQUIRE(match("hello", "^[a-z]+$")); + + ATF_REQUIRE(!match("hello", "helooo")); + ATF_REQUIRE(!match("hello", "[a-z]+5")); + ATF_REQUIRE(!match("hello", "^ [a-z]+$")); +} + +ATF_TEST_CASE(split); +ATF_TEST_CASE_HEAD(split) +{ + set_md_var("descr", "Tests the split function"); +} +ATF_TEST_CASE_BODY(split) +{ + using atf::text::split; + + std::vector< std::string > words; + + words = split("", " "); + ATF_REQUIRE_EQ(words.size(), 0); + + words = split(" ", " "); + ATF_REQUIRE_EQ(words.size(), 0); + + words = split(" ", " "); + ATF_REQUIRE_EQ(words.size(), 0); + + words = split("a b", " "); + ATF_REQUIRE_EQ(words.size(), 2); + ATF_REQUIRE_EQ(words[0], "a"); + ATF_REQUIRE_EQ(words[1], "b"); + + words = split("a b c d", " "); + ATF_REQUIRE_EQ(words.size(), 4); + ATF_REQUIRE_EQ(words[0], "a"); + ATF_REQUIRE_EQ(words[1], "b"); + ATF_REQUIRE_EQ(words[2], "c"); + ATF_REQUIRE_EQ(words[3], "d"); + + words = split("foo bar", " "); + ATF_REQUIRE_EQ(words.size(), 2); + ATF_REQUIRE_EQ(words[0], "foo"); + ATF_REQUIRE_EQ(words[1], "bar"); + + words = split("foo bar baz foobar", " "); + ATF_REQUIRE_EQ(words.size(), 4); + ATF_REQUIRE_EQ(words[0], "foo"); + ATF_REQUIRE_EQ(words[1], "bar"); + ATF_REQUIRE_EQ(words[2], "baz"); + ATF_REQUIRE_EQ(words[3], "foobar"); + + words = split(" foo bar", " "); + ATF_REQUIRE_EQ(words.size(), 2); + ATF_REQUIRE_EQ(words[0], "foo"); + ATF_REQUIRE_EQ(words[1], "bar"); + + words = split("foo bar", " "); + ATF_REQUIRE_EQ(words.size(), 2); + ATF_REQUIRE_EQ(words[0], "foo"); + ATF_REQUIRE_EQ(words[1], "bar"); + + words = split("foo bar ", " "); + ATF_REQUIRE_EQ(words.size(), 2); + ATF_REQUIRE_EQ(words[0], "foo"); + ATF_REQUIRE_EQ(words[1], "bar"); + + words = split(" foo bar ", " "); + ATF_REQUIRE_EQ(words.size(), 2); + ATF_REQUIRE_EQ(words[0], "foo"); + ATF_REQUIRE_EQ(words[1], "bar"); +} + +ATF_TEST_CASE(split_delims); +ATF_TEST_CASE_HEAD(split_delims) +{ + set_md_var("descr", "Tests the split function using different delimiters"); +} +ATF_TEST_CASE_BODY(split_delims) +{ + using atf::text::split; + + std::vector< std::string > words; + + words = split("", "/"); + ATF_REQUIRE_EQ(words.size(), 0); + + words = split(" ", "/"); + ATF_REQUIRE_EQ(words.size(), 1); + ATF_REQUIRE_EQ(words[0], " "); + + words = split(" ", "/"); + ATF_REQUIRE_EQ(words.size(), 1); + ATF_REQUIRE_EQ(words[0], " "); + + words = split("a/b", "/"); + ATF_REQUIRE_EQ(words.size(), 2); + ATF_REQUIRE_EQ(words[0], "a"); + ATF_REQUIRE_EQ(words[1], "b"); + + words = split("aLONGDELIMbcdLONGDELIMef", "LONGDELIM"); + ATF_REQUIRE_EQ(words.size(), 3); + ATF_REQUIRE_EQ(words[0], "a"); + ATF_REQUIRE_EQ(words[1], "bcd"); + ATF_REQUIRE_EQ(words[2], "ef"); +} + +ATF_TEST_CASE(trim); +ATF_TEST_CASE_HEAD(trim) +{ + set_md_var("descr", "Tests the trim function"); +} +ATF_TEST_CASE_BODY(trim) +{ + using atf::text::trim; + + ATF_REQUIRE_EQ(trim(""), ""); + ATF_REQUIRE_EQ(trim(" "), ""); + ATF_REQUIRE_EQ(trim("\t"), ""); + + ATF_REQUIRE_EQ(trim(" foo"), "foo"); + ATF_REQUIRE_EQ(trim("\t foo"), "foo"); + ATF_REQUIRE_EQ(trim(" \tfoo"), "foo"); + ATF_REQUIRE_EQ(trim("foo\t "), "foo"); + ATF_REQUIRE_EQ(trim("foo \t"), "foo"); + + ATF_REQUIRE_EQ(trim("foo bar"), "foo bar"); + ATF_REQUIRE_EQ(trim("\t foo bar"), "foo bar"); + ATF_REQUIRE_EQ(trim(" \tfoo bar"), "foo bar"); + ATF_REQUIRE_EQ(trim("foo bar\t "), "foo bar"); + ATF_REQUIRE_EQ(trim("foo bar \t"), "foo bar"); +} + +ATF_TEST_CASE(to_bool); +ATF_TEST_CASE_HEAD(to_bool) +{ + set_md_var("descr", "Tests the to_string function"); +} +ATF_TEST_CASE_BODY(to_bool) +{ + using atf::text::to_bool; + + ATF_REQUIRE(to_bool("true")); + ATF_REQUIRE(to_bool("TRUE")); + ATF_REQUIRE(to_bool("yes")); + ATF_REQUIRE(to_bool("YES")); + + ATF_REQUIRE(!to_bool("false")); + ATF_REQUIRE(!to_bool("FALSE")); + ATF_REQUIRE(!to_bool("no")); + ATF_REQUIRE(!to_bool("NO")); + + ATF_REQUIRE_THROW(std::runtime_error, to_bool("")); + ATF_REQUIRE_THROW(std::runtime_error, to_bool("tru")); + ATF_REQUIRE_THROW(std::runtime_error, to_bool("true2")); + ATF_REQUIRE_THROW(std::runtime_error, to_bool("fals")); + ATF_REQUIRE_THROW(std::runtime_error, to_bool("false2")); +} + +ATF_TEST_CASE(to_bytes); +ATF_TEST_CASE_HEAD(to_bytes) +{ + set_md_var("descr", "Tests the to_bytes function"); +} +ATF_TEST_CASE_BODY(to_bytes) +{ + using atf::text::to_bytes; + + ATF_REQUIRE_EQ(0, to_bytes("0")); + ATF_REQUIRE_EQ(12345, to_bytes("12345")); + ATF_REQUIRE_EQ(2 * 1024, to_bytes("2k")); + ATF_REQUIRE_EQ(4 * 1024 * 1024, to_bytes("4m")); + ATF_REQUIRE_EQ(int64_t(8) * 1024 * 1024 * 1024, to_bytes("8g")); + ATF_REQUIRE_EQ(int64_t(16) * 1024 * 1024 * 1024 * 1024, to_bytes("16t")); + + ATF_REQUIRE_THROW_RE(std::runtime_error, "Empty", to_bytes("")); + ATF_REQUIRE_THROW_RE(std::runtime_error, "Unknown size unit 'd'", + to_bytes("12d")); + ATF_REQUIRE_THROW(std::runtime_error, to_bytes(" ")); + ATF_REQUIRE_THROW(std::runtime_error, to_bytes(" k")); +} + +ATF_TEST_CASE(to_string); +ATF_TEST_CASE_HEAD(to_string) +{ + set_md_var("descr", "Tests the to_string function"); +} +ATF_TEST_CASE_BODY(to_string) +{ + using atf::text::to_string; + + ATF_REQUIRE_EQ(to_string('a'), "a"); + ATF_REQUIRE_EQ(to_string("a"), "a"); + ATF_REQUIRE_EQ(to_string(5), "5"); +} + +ATF_TEST_CASE(to_type); +ATF_TEST_CASE_HEAD(to_type) +{ + set_md_var("descr", "Tests the to_type function"); +} +ATF_TEST_CASE_BODY(to_type) +{ + using atf::text::to_type; + + ATF_REQUIRE_EQ(to_type< int >("0"), 0); + ATF_REQUIRE_EQ(to_type< int >("1234"), 1234); + ATF_REQUIRE_THROW(std::runtime_error, to_type< int >(" ")); + ATF_REQUIRE_THROW(std::runtime_error, to_type< int >("0 a")); + ATF_REQUIRE_THROW(std::runtime_error, to_type< int >("a")); + + ATF_REQUIRE_EQ(to_type< float >("0.5"), 0.5); + ATF_REQUIRE_EQ(to_type< float >("1234.5"), 1234.5); + ATF_REQUIRE_THROW(std::runtime_error, to_type< float >("0.5 a")); + ATF_REQUIRE_THROW(std::runtime_error, to_type< float >("a")); + + ATF_REQUIRE_EQ(to_type< std::string >("a"), "a"); +} + +// ------------------------------------------------------------------------ +// Main. +// ------------------------------------------------------------------------ + +ATF_INIT_TEST_CASES(tcs) +{ + // Add the test cases for the free functions. + ATF_ADD_TEST_CASE(tcs, duplicate); + ATF_ADD_TEST_CASE(tcs, join); + ATF_ADD_TEST_CASE(tcs, match); + ATF_ADD_TEST_CASE(tcs, split); + ATF_ADD_TEST_CASE(tcs, split_delims); + ATF_ADD_TEST_CASE(tcs, trim); + ATF_ADD_TEST_CASE(tcs, to_bool); + ATF_ADD_TEST_CASE(tcs, to_bytes); + ATF_ADD_TEST_CASE(tcs, to_string); + ATF_ADD_TEST_CASE(tcs, to_type); +} diff --git a/external/bsd/atf/dist/atf-c++/detail/ui.cpp b/external/bsd/atf/dist/atf-c++/detail/ui.cpp new file mode 100644 index 000000000..07bde4f87 --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/detail/ui.cpp @@ -0,0 +1,173 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +extern "C" { +#include + +#include +#include +} + +#include + +#include "env.hpp" +#include "text.hpp" +#include "sanity.hpp" +#include "text.hpp" +#include "ui.hpp" + +namespace impl = atf::ui; +#define IMPL_NAME "atf::ui" + +static +size_t +terminal_width(void) +{ + static bool done = false; + static size_t width = 0; + + if (!done) { + if (atf::env::has("COLUMNS")) { + const std::string cols = atf::env::get("COLUMNS"); + if (cols.length() > 0) { + width = atf::text::to_type< size_t >(cols); + } + } else { + struct winsize ws; + if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) != -1) + width = ws.ws_col; + } + + if (width >= 80) + width -= 5; + + done = true; + } + + return width; +} + +static +std::string +format_paragraph(const std::string& text, + const std::string& tag, + const bool first, + const bool repeat, + const size_t col) +{ + PRE(text.find('\n') == std::string::npos); + + const std::string pad(col - tag.length(), ' '); + const std::string fullpad(col, ' '); + + std::string formatted; + if (first || repeat) + formatted = tag + pad; + else + formatted = fullpad; + INV(formatted.length() == col); + size_t curcol = col; + + const size_t maxcol = terminal_width(); + + std::vector< std::string > words = atf::text::split(text, " "); + for (std::vector< std::string >::const_iterator iter = words.begin(); + iter != words.end(); iter++) { + const std::string& word = *iter; + + if (iter != words.begin() && maxcol > 0 && + curcol + word.length() + 1 > maxcol) { + if (repeat) + formatted += '\n' + tag + pad; + else + formatted += '\n' + fullpad; + curcol = col; + } else if (iter != words.begin()) { + formatted += ' '; + curcol++; + } + + formatted += word; + curcol += word.length(); + } + + return formatted; +} + +std::string +impl::format_error(const std::string& prog_name, const std::string& error) +{ + return format_text_with_tag("ERROR: " + error, prog_name + ": ", true); +} + +std::string +impl::format_info(const std::string& prog_name, const std::string& msg) +{ + return format_text_with_tag(msg, prog_name + ": ", true); +} + +std::string +impl::format_text(const std::string& text) +{ + return format_text_with_tag(text, "", false, 0); +} + +std::string +impl::format_text_with_tag(const std::string& text, const std::string& tag, + bool repeat, size_t col) +{ + PRE(col == 0 || col >= tag.length()); + if (col == 0) + col = tag.length(); + + std::string formatted; + + std::vector< std::string > lines = atf::text::split(text, "\n"); + for (std::vector< std::string >::const_iterator iter = lines.begin(); + iter != lines.end(); iter++) { + const std::string& line = *iter; + + formatted += format_paragraph(line, tag, iter == lines.begin(), + repeat, col); + if (iter + 1 != lines.end()) { + if (repeat) + formatted += "\n" + tag + "\n"; + else + formatted += "\n\n"; + } + } + + return formatted; +} + +std::string +impl::format_warning(const std::string& prog_name, const std::string& error) +{ + return format_text_with_tag("WARNING: " + error, prog_name + ": ", true); +} diff --git a/external/bsd/atf/dist/atf-c++/detail/ui.hpp b/external/bsd/atf/dist/atf-c++/detail/ui.hpp new file mode 100644 index 000000000..1c81c56a9 --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/detail/ui.hpp @@ -0,0 +1,105 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#if !defined(_ATF_CXX_UI_HPP_) +#define _ATF_CXX_UI_HPP_ + +#include + +namespace atf { +namespace ui { + +//! +//! \brief Formats an error message to fit on screen. +//! +//! Given the program's name and an error message, properly formats it to +//! fit on screen. +//! +//! The program's name is not stored globally to prevent the usage of this +//! function from inside the library. Making it a explicit parameter +//! restricts its usage to the frontend. +//! +std::string format_error(const std::string&, const std::string&); + +//! +//! \brief Formats an informational message to fit on screen. +//! +//! Given the program's name and an informational message, properly formats +//! it to fit on screen. +//! +//! The program's name is not stored globally to prevent the usage of this +//! function from inside the library. Making it a explicit parameter +//! restricts its usage to the frontend. +//! +std::string format_info(const std::string&, const std::string&); + +//! +//! \brief Formats a block of text to fit nicely on screen. +//! +//! Given a text, which is composed of multiple paragraphs separated by +//! a single '\n' character, reformats it to fill on the current screen's +//! width with proper line wrapping. +//! +//! This is just a special case of format_text_with_tag, provided for +//! simplicity. +//! +std::string format_text(const std::string&); + +//! +//! \brief Formats a block of text to fit nicely on screen, prepending a +//! tag to it. +//! +//! Given a text, which is composed of multiple paragraphs separated by +//! a single '\n' character, reformats it to fill on the current screen's +//! width with proper line wrapping. The text is prepended with a tag; +//! i.e. a word that is printed at the beginning of the first paragraph and +//! optionally repeated at the beginning of each word. The last parameter +//! specifies the column on which the text should start, and that position +//! must be greater than the tag's length or 0, in which case it +//! automatically takes the correct value. +//! +std::string format_text_with_tag(const std::string&, const std::string&, + bool, size_t = 0); + +//! +//! \brief Formats a warning message to fit on screen. +//! +//! Given the program's name and a warning message, properly formats it to +//! fit on screen. +//! +//! The program's name is not stored globally to prevent the usage of this +//! function from inside the library. Making it a explicit parameter +//! restricts its usage to the frontend. +//! +std::string format_warning(const std::string&, const std::string&); + +} // namespace ui +} // namespace atf + +#endif // !defined(_ATF_CXX_UI_HPP_) diff --git a/external/bsd/atf/dist/atf-c++/detail/ui_test.cpp b/external/bsd/atf/dist/atf-c++/detail/ui_test.cpp new file mode 100644 index 000000000..918d028de --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/detail/ui_test.cpp @@ -0,0 +1,462 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2009 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#include +#include + +#include "../macros.hpp" + +#include "env.hpp" +#include "ui.hpp" + +// ------------------------------------------------------------------------ +// Test cases for the free functions. +// ------------------------------------------------------------------------ + +struct test { + const char *tc; + const char *tag; + bool repeat; + size_t col; + const char *fmt; + const char *result; +} tests[] = { + // + // wo_tag + // + + { + "wo_tag", + "", + false, + 0, + "12345", + "12345", + }, + + { + "wo_tag", + "", + false, + 0, + "12345 ", + "12345", + }, + + { + "wo_tag", + "", + false, + 0, + "12345 7890", + "12345 7890", + }, + + { + "wo_tag", + "", + false, + 0, + "12345 789012 45", + "12345 789012 45", + }, + + { + "wo_tag", + "", + false, + 0, + "12345 789012 456", + "12345 789012\n456", + }, + + { + "wo_tag", + "", + false, + 0, + "1234567890123456", + "1234567890123456", + }, + + // TODO(jmmv): Fix the code to pass this test... +// { +// "wo_tag", +// "", +// false, +// 0, +// " 2345678901234567", +// "\n2345678901234567", +// }, + + { + "wo_tag", + "", + false, + 0, + "12345 789012345 78", + "12345 789012345\n78", + }, + + // + // wo_tag_col + // + + { + "wo_tag_col", + "", + false, + 10, + "12345", + " 12345", + }, + + { + "wo_tag_col", + "", + false, + 10, + "12345 7890", + " 12345\n" + " 7890", + }, + + { + "wo_tag_col", + "", + false, + 10, + "1 3 5 7 9", + " 1 3 5\n" + " 7 9", + }, + + // + // w_tag_no_repeat + // + + { + "w_tag_no_repeat", + "1234: ", + false, + 0, + "789012345", + "1234: 789012345", + }, + + { + "w_tag_no_repeat", + "1234: ", + false, + 0, + "789 1234 56789", + "1234: 789 1234\n" + " 56789", + }, + + { + "w_tag_no_repeat", + "1234: ", + false, + 0, + "789012345", + "1234: 789012345", + }, + + { + "w_tag_no_repeat", + "1234: ", + false, + 0, + "789012345 7890", + "1234: 789012345\n" + " 7890", + }, + + // + // w_tag_repeat + // + + { + "w_tag_repeat", + "1234: ", + true, + 0, + "789012345", + "1234: 789012345", + }, + + { + "w_tag_repeat", + "1234: ", + true, + 0, + "789 1234 56789", + "1234: 789 1234\n" + "1234: 56789", + }, + + { + "w_tag_repeat", + "1234: ", + true, + 0, + "789012345", + "1234: 789012345", + }, + + { + "w_tag_no_repeat", + "1234: ", + true, + 0, + "789012345 7890", + "1234: 789012345\n" + "1234: 7890", + }, + + // + // w_tag_col + // + + { + "w_tag_col", + "1234:", + false, + 10, + "1 3 5", + "1234: 1 3 5", + }, + + { + "w_tag_col", + "1234:", + false, + 10, + "1 3 5 7 9", + "1234: 1 3 5\n" + " 7 9", + }, + + { + "w_tag_col", + "1234:", + true, + 10, + "1 3 5 7 9", + "1234: 1 3 5\n" + "1234: 7 9", + }, + + // + // paragraphs + // + + { + "paragraphs", + "", + false, + 0, + "1 3 5\n\n", + "1 3 5" + }, + + { + "paragraphs", + "", + false, + 0, + "1 3 5\n2 4 6", + "1 3 5\n\n2 4 6" + }, + + { + "paragraphs", + "", + false, + 0, + "1234 6789 123456\n2 4 6", + "1234 6789\n123456\n\n2 4 6" + }, + + { + "paragraphs", + "12: ", + false, + 0, + "56789 123456\n2 4 6", + "12: 56789\n 123456\n\n 2 4 6" + }, + + { + "paragraphs", + "12: ", + true, + 0, + "56789 123456\n2 4 6", + "12: 56789\n12: 123456\n12: \n12: 2 4 6" + }, + + { + "paragraphs", + "12:", + false, + 4, + "56789 123456\n2 4 6", + "12: 56789\n 123456\n\n 2 4 6" + }, + + { + "paragraphs", + "12:", + true, + 4, + "56789 123456\n2 4 6", + "12: 56789\n12: 123456\n12:\n12: 2 4 6" + }, + + // + // end + // + + { + NULL, + NULL, + false, + 0, + NULL, + NULL, + }, +}; + +static +void +run_tests(const char *tc) +{ + struct test *t; + + std::cout << "Running tests for " << tc << "\n"; + + atf::env::set("COLUMNS", "15"); + + for (t = &tests[0]; t->tc != NULL; t++) { + if (std::strcmp(t->tc, tc) == 0) { + std::cout << "\n"; + std::cout << "Testing with tag '" << t->tag << "', '" + << (t->repeat ? "repeat" : "no repeat") << "', col " + << t->col << "\n"; + std::cout << "Input: >>>" << t->fmt << "<<<\n"; + std::cout << "Expected output: >>>" << t->result << "<<<\n"; + + std::string result = atf::ui::format_text_with_tag(t->fmt, t->tag, + t->repeat, t->col); + std::cout << "Output : >>>" << result << "<<<\n"; + ATF_REQUIRE_EQ(t->result, result); + } + } +} + +ATF_TEST_CASE(wo_tag); +ATF_TEST_CASE_HEAD(wo_tag) +{ + set_md_var("descr", "Checks formatting without tags"); +} +ATF_TEST_CASE_BODY(wo_tag) +{ + run_tests("wo_tag"); +} + +ATF_TEST_CASE(wo_tag_col); +ATF_TEST_CASE_HEAD(wo_tag_col) +{ + set_md_var("descr", "Checks formatting without tags and with a non-zero " + "starting column"); +} +ATF_TEST_CASE_BODY(wo_tag_col) +{ + run_tests("wo_tag_col"); +} + +ATF_TEST_CASE(w_tag_no_repeat); +ATF_TEST_CASE_HEAD(w_tag_no_repeat) +{ + set_md_var("descr", "Checks formatting with a tag"); +} +ATF_TEST_CASE_BODY(w_tag_no_repeat) +{ + run_tests("w_tag_no_repeat"); +} + +ATF_TEST_CASE(w_tag_repeat); +ATF_TEST_CASE_HEAD(w_tag_repeat) +{ + set_md_var("descr", "Checks formatting with a tag and repeating it on " + "each line"); +} +ATF_TEST_CASE_BODY(w_tag_repeat) +{ + run_tests("w_tag_repeat"); +} + +ATF_TEST_CASE(w_tag_col); +ATF_TEST_CASE_HEAD(w_tag_col) +{ + set_md_var("descr", "Checks formatting with a tag and starting at a " + "column greater than its length"); +} +ATF_TEST_CASE_BODY(w_tag_col) +{ + run_tests("w_tag_col"); +} + +ATF_TEST_CASE(paragraphs); +ATF_TEST_CASE_HEAD(paragraphs) +{ + set_md_var("descr", "Checks formatting a string that contains multiple " + "paragraphs"); +} +ATF_TEST_CASE_BODY(paragraphs) +{ + run_tests("paragraphs"); +} + +// ------------------------------------------------------------------------ +// Main. +// ------------------------------------------------------------------------ + +ATF_INIT_TEST_CASES(tcs) +{ + // Add the test cases for the free functions. + ATF_ADD_TEST_CASE(tcs, wo_tag); + ATF_ADD_TEST_CASE(tcs, wo_tag_col); + ATF_ADD_TEST_CASE(tcs, w_tag_no_repeat); + ATF_ADD_TEST_CASE(tcs, w_tag_repeat); + ATF_ADD_TEST_CASE(tcs, w_tag_col); + ATF_ADD_TEST_CASE(tcs, paragraphs); +} diff --git a/external/bsd/atf/dist/atf-c++/macros.hpp b/external/bsd/atf/dist/atf-c++/macros.hpp new file mode 100644 index 000000000..c6ce9c2be --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/macros.hpp @@ -0,0 +1,222 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#if !defined(_ATF_CXX_MACROS_HPP_) +#define _ATF_CXX_MACROS_HPP_ + +#include +#include +#include + +#include + +// Do not define inline methods for the test case classes. Doing so +// significantly increases the memory requirements of GNU G++ during +// compilation. + +#define ATF_TEST_CASE_WITHOUT_HEAD(name) \ + namespace { \ + class atfu_tc_ ## name : public atf::tests::tc { \ + void body(void) const; \ + public: \ + atfu_tc_ ## name(void); \ + }; \ + static atfu_tc_ ## name* atfu_tcptr_ ## name; \ + atfu_tc_ ## name::atfu_tc_ ## name(void) : atf::tests::tc(#name, false) {} \ + } + +#define ATF_TEST_CASE(name) \ + namespace { \ + class atfu_tc_ ## name : public atf::tests::tc { \ + void head(void); \ + void body(void) const; \ + public: \ + atfu_tc_ ## name(void); \ + }; \ + static atfu_tc_ ## name* atfu_tcptr_ ## name; \ + atfu_tc_ ## name::atfu_tc_ ## name(void) : atf::tests::tc(#name, false) {} \ + } + +#define ATF_TEST_CASE_WITH_CLEANUP(name) \ + namespace { \ + class atfu_tc_ ## name : public atf::tests::tc { \ + void head(void); \ + void body(void) const; \ + void cleanup(void) const; \ + public: \ + atfu_tc_ ## name(void); \ + }; \ + static atfu_tc_ ## name* atfu_tcptr_ ## name; \ + atfu_tc_ ## name::atfu_tc_ ## name(void) : atf::tests::tc(#name, true) {} \ + } + +#define ATF_TEST_CASE_NAME(name) atfu_tc_ ## name +#define ATF_TEST_CASE_USE(name) (atfu_tcptr_ ## name) = NULL + +#define ATF_TEST_CASE_HEAD(name) \ + void \ + atfu_tc_ ## name::head(void) + +#define ATF_TEST_CASE_BODY(name) \ + void \ + atfu_tc_ ## name::body(void) \ + const + +#define ATF_TEST_CASE_CLEANUP(name) \ + void \ + atfu_tc_ ## name::cleanup(void) \ + const + +#define ATF_FAIL(reason) atf::tests::tc::fail(reason) + +#define ATF_SKIP(reason) atf::tests::tc::skip(reason) + +#define ATF_PASS() atf::tests::tc::pass() + +#define ATF_REQUIRE(x) \ + do { \ + if (!(x)) { \ + std::ostringstream atfu_ss; \ + atfu_ss << "Line " << __LINE__ << ": " << #x << " not met"; \ + atf::tests::tc::fail(atfu_ss.str()); \ + } \ + } while (false) + +#define ATF_REQUIRE_EQ(x, y) \ + do { \ + if ((x) != (y)) { \ + std::ostringstream atfu_ss; \ + atfu_ss << "Line " << __LINE__ << ": " << #x << " != " << #y \ + << " (" << (x) << " != " << (y) << ")"; \ + atf::tests::tc::fail(atfu_ss.str()); \ + } \ + } while (false) + +#define ATF_REQUIRE_IN(element, collection) \ + ATF_REQUIRE((collection).find(element) != (collection).end()) + +#define ATF_REQUIRE_NOT_IN(element, collection) \ + ATF_REQUIRE((collection).find(element) == (collection).end()) + +#define ATF_REQUIRE_MATCH(regexp, string) \ + do { \ + if (!atf::tests::detail::match(regexp, string)) { \ + std::ostringstream atfu_ss; \ + atfu_ss << "Line " << __LINE__ << ": '" << string << "' does not " \ + << "match regexp '" << regexp << "'"; \ + atf::tests::tc::fail(atfu_ss.str()); \ + } \ + } while (false) + +#define ATF_REQUIRE_THROW(e, x) \ + do { \ + try { \ + x; \ + std::ostringstream atfu_ss; \ + atfu_ss << "Line " << __LINE__ << ": " #x " did not throw " \ + #e " as expected"; \ + atf::tests::tc::fail(atfu_ss.str()); \ + } catch (const e&) { \ + } catch (const std::exception& atfu_e) { \ + std::ostringstream atfu_ss; \ + atfu_ss << "Line " << __LINE__ << ": " #x " threw an " \ + "unexpected error (not " #e "): " << atfu_e.what(); \ + atf::tests::tc::fail(atfu_ss.str()); \ + } catch (...) { \ + std::ostringstream atfu_ss; \ + atfu_ss << "Line " << __LINE__ << ": " #x " threw an " \ + "unexpected error (not " #e ")"; \ + atf::tests::tc::fail(atfu_ss.str()); \ + } \ + } while (false) + +#define ATF_REQUIRE_THROW_RE(type, regexp, x) \ + do { \ + try { \ + x; \ + std::ostringstream atfu_ss; \ + atfu_ss << "Line " << __LINE__ << ": " #x " did not throw " \ + #type " as expected"; \ + atf::tests::tc::fail(atfu_ss.str()); \ + } catch (const type& e) { \ + if (!atf::tests::detail::match(regexp, e.what())) { \ + std::ostringstream atfu_ss; \ + atfu_ss << "Line " << __LINE__ << ": " #x " threw " #type "(" \ + << e.what() << "), but does not match '" << regexp \ + << "'"; \ + atf::tests::tc::fail(atfu_ss.str()); \ + } \ + } catch (const std::exception& atfu_e) { \ + std::ostringstream atfu_ss; \ + atfu_ss << "Line " << __LINE__ << ": " #x " threw an " \ + "unexpected error (not " #type "): " << atfu_e.what(); \ + atf::tests::tc::fail(atfu_ss.str()); \ + } catch (...) { \ + std::ostringstream atfu_ss; \ + atfu_ss << "Line " << __LINE__ << ": " #x " threw an " \ + "unexpected error (not " #type ")"; \ + atf::tests::tc::fail(atfu_ss.str()); \ + } \ + } while (false) + +#define ATF_CHECK_ERRNO(exp_errno, bool_expr) \ + atf::tests::tc::check_errno(__FILE__, __LINE__, exp_errno, #bool_expr, \ + bool_expr) + +#define ATF_REQUIRE_ERRNO(exp_errno, bool_expr) \ + atf::tests::tc::require_errno(__FILE__, __LINE__, exp_errno, #bool_expr, \ + bool_expr) + +#define ATF_INIT_TEST_CASES(tcs) \ + namespace atf { \ + namespace tests { \ + int run_tp(int, char* const*, \ + void (*)(std::vector< atf::tests::tc * >&)); \ + } \ + } \ + \ + static void atfu_init_tcs(std::vector< atf::tests::tc * >&); \ + \ + int \ + main(int argc, char* const* argv) \ + { \ + return atf::tests::run_tp(argc, argv, atfu_init_tcs); \ + } \ + \ + static \ + void \ + atfu_init_tcs(std::vector< atf::tests::tc * >& tcs) + +#define ATF_ADD_TEST_CASE(tcs, tcname) \ + do { \ + atfu_tcptr_ ## tcname = new atfu_tc_ ## tcname(); \ + (tcs).push_back(atfu_tcptr_ ## tcname); \ + } while (0); + +#endif // !defined(_ATF_CXX_MACROS_HPP_) diff --git a/external/bsd/atf/dist/atf-c++/macros_hpp_test.cpp b/external/bsd/atf/dist/atf-c++/macros_hpp_test.cpp new file mode 100644 index 000000000..2cb75360a --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/macros_hpp_test.cpp @@ -0,0 +1,130 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2008 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#include + +#include + +void +atf_check_errno_semicolons(void) +{ + // Check that ATF_CHECK_ERRNO does not contain a semicolon that would + // cause an empty-statement that confuses some compilers. + ATF_CHECK_ERRNO(1, 1 == 1); + ATF_CHECK_ERRNO(2, 2 == 2); +} + +void +atf_require_inside_if(void) +{ + // Make sure that ATF_REQUIRE can be used inside an if statement that + // does not have braces. Earlier versions of it generated an error + // if there was an else clause because they confused the compiler + // by defining an unprotected nested if. + if (true) + ATF_REQUIRE(true); + else + ATF_REQUIRE(true); +} + +void +atf_require_eq_inside_if(void) +{ + // Make sure that ATF_REQUIRE_EQ can be used inside an if statement + // that does not have braces. Earlier versions of it generated an + // error if there was an else clause because they confused the + // compiler by defining an unprotected nested if. + if (true) + ATF_REQUIRE_EQ(true, true); + else + ATF_REQUIRE_EQ(true, true); +} + +void +atf_require_throw_runtime_error(void) +{ + // Check that we can pass std::runtime_error to ATF_REQUIRE_THROW. + // Earlier versions generated a warning because the macro's code also + // attempted to capture this exception, and thus we had a duplicate + // catch clause. + ATF_REQUIRE_THROW(std::runtime_error, (void)0); +} + +void +atf_require_throw_inside_if(void) +{ + // Make sure that ATF_REQUIRE_THROW can be used inside an if statement + // that does not have braces. Earlier versions of it generated an + // error because a trailing ; after a catch block was not allowed. + if (true) + ATF_REQUIRE_THROW(std::runtime_error, (void)0); + else + ATF_REQUIRE_THROW(std::runtime_error, (void)1); +} + +void +atf_require_errno_semicolons(void) +{ + // Check that ATF_REQUIRE_ERRNO does not contain a semicolon that would + // cause an empty-statement that confuses some compilers. + ATF_REQUIRE_ERRNO(1, 1 == 1); + ATF_REQUIRE_ERRNO(2, 2 == 2); +} + +// Test case names should not be expanded during instatiation so that they +// can have the exact same name as macros. +#define TEST_MACRO_1 invalid + name +#define TEST_MACRO_2 invalid + name +#define TEST_MACRO_3 invalid + name +ATF_TEST_CASE(TEST_MACRO_1); +ATF_TEST_CASE_HEAD(TEST_MACRO_1) { } +ATF_TEST_CASE_BODY(TEST_MACRO_1) { } +void instantiate_1(void) { + ATF_TEST_CASE_USE(TEST_MACRO_1); + atf::tests::tc* the_test = new ATF_TEST_CASE_NAME(TEST_MACRO_1)(); + delete the_test; +} +ATF_TEST_CASE_WITH_CLEANUP(TEST_MACRO_2); +ATF_TEST_CASE_HEAD(TEST_MACRO_2) { } +ATF_TEST_CASE_BODY(TEST_MACRO_2) { } +ATF_TEST_CASE_CLEANUP(TEST_MACRO_2) { } +void instatiate_2(void) { + ATF_TEST_CASE_USE(TEST_MACRO_2); + atf::tests::tc* the_test = new ATF_TEST_CASE_NAME(TEST_MACRO_2)(); + delete the_test; +} +ATF_TEST_CASE_WITH_CLEANUP(TEST_MACRO_3); +ATF_TEST_CASE_HEAD(TEST_MACRO_3) { } +ATF_TEST_CASE_BODY(TEST_MACRO_3) { } +ATF_TEST_CASE_CLEANUP(TEST_MACRO_3) { } +void instatiate_3(void) { + ATF_TEST_CASE_USE(TEST_MACRO_3); + atf::tests::tc* the_test = new ATF_TEST_CASE_NAME(TEST_MACRO_3)(); + delete the_test; +} diff --git a/external/bsd/atf/dist/atf-c++/macros_test.cpp b/external/bsd/atf/dist/atf-c++/macros_test.cpp new file mode 100644 index 000000000..67e41061c --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/macros_test.cpp @@ -0,0 +1,796 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2008 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +extern "C" { +#include +#include +} + +#include +#include +#include +#include + +#include "macros.hpp" +#include "utils.hpp" + +#include "detail/fs.hpp" +#include "detail/process.hpp" +#include "detail/sanity.hpp" +#include "detail/test_helpers.hpp" +#include "detail/text.hpp" + +// ------------------------------------------------------------------------ +// Auxiliary functions. +// ------------------------------------------------------------------------ + +static +void +create_ctl_file(const char *name) +{ + ATF_REQUIRE(open(name, O_CREAT | O_WRONLY | O_TRUNC, 0644) != -1); +} + +// ------------------------------------------------------------------------ +// Auxiliary test cases. +// ------------------------------------------------------------------------ + +ATF_TEST_CASE(h_pass); +ATF_TEST_CASE_HEAD(h_pass) +{ + set_md_var("descr", "Helper test case"); +} +ATF_TEST_CASE_BODY(h_pass) +{ + create_ctl_file("before"); + ATF_PASS(); + create_ctl_file("after"); +} + +ATF_TEST_CASE(h_fail); +ATF_TEST_CASE_HEAD(h_fail) +{ + set_md_var("descr", "Helper test case"); +} +ATF_TEST_CASE_BODY(h_fail) +{ + create_ctl_file("before"); + ATF_FAIL("Failed on purpose"); + create_ctl_file("after"); +} + +ATF_TEST_CASE(h_skip); +ATF_TEST_CASE_HEAD(h_skip) +{ + set_md_var("descr", "Helper test case"); +} +ATF_TEST_CASE_BODY(h_skip) +{ + create_ctl_file("before"); + ATF_SKIP("Skipped on purpose"); + create_ctl_file("after"); +} + +ATF_TEST_CASE(h_require); +ATF_TEST_CASE_HEAD(h_require) +{ + set_md_var("descr", "Helper test case"); +} +ATF_TEST_CASE_BODY(h_require) +{ + bool condition = atf::text::to_bool(get_config_var("condition")); + + create_ctl_file("before"); + ATF_REQUIRE(condition); + create_ctl_file("after"); +} + +ATF_TEST_CASE(h_require_eq); +ATF_TEST_CASE_HEAD(h_require_eq) +{ + set_md_var("descr", "Helper test case"); +} +ATF_TEST_CASE_BODY(h_require_eq) +{ + long v1 = atf::text::to_type< long >(get_config_var("v1")); + long v2 = atf::text::to_type< long >(get_config_var("v2")); + + create_ctl_file("before"); + ATF_REQUIRE_EQ(v1, v2); + create_ctl_file("after"); +} + +ATF_TEST_CASE(h_require_in); +ATF_TEST_CASE_HEAD(h_require_in) +{ + set_md_var("descr", "Helper test case"); +} +ATF_TEST_CASE_BODY(h_require_in) +{ + const std::string element = get_config_var("value"); + + std::set< std::string > collection; + collection.insert("foo"); + collection.insert("bar"); + collection.insert("baz"); + + create_ctl_file("before"); + ATF_REQUIRE_IN(element, collection); + create_ctl_file("after"); +} + +ATF_TEST_CASE(h_require_match); +ATF_TEST_CASE_HEAD(h_require_match) +{ + set_md_var("descr", "Helper test case"); +} +ATF_TEST_CASE_BODY(h_require_match) +{ + const std::string regexp = get_config_var("regexp"); + const std::string string = get_config_var("string"); + + create_ctl_file("before"); + ATF_REQUIRE_MATCH(regexp, string); + create_ctl_file("after"); +} + +ATF_TEST_CASE(h_require_not_in); +ATF_TEST_CASE_HEAD(h_require_not_in) +{ + set_md_var("descr", "Helper test case"); +} +ATF_TEST_CASE_BODY(h_require_not_in) +{ + const std::string element = get_config_var("value"); + + std::set< std::string > collection; + collection.insert("foo"); + collection.insert("bar"); + collection.insert("baz"); + + create_ctl_file("before"); + ATF_REQUIRE_NOT_IN(element, collection); + create_ctl_file("after"); +} + +ATF_TEST_CASE(h_require_throw); +ATF_TEST_CASE_HEAD(h_require_throw) +{ + set_md_var("descr", "Helper test case"); +} +ATF_TEST_CASE_BODY(h_require_throw) +{ + create_ctl_file("before"); + + if (get_config_var("what") == "throw_int") + ATF_REQUIRE_THROW(std::runtime_error, if (1) throw int(5)); + else if (get_config_var("what") == "throw_rt") + ATF_REQUIRE_THROW(std::runtime_error, + if (1) throw std::runtime_error("e")); + else if (get_config_var("what") == "no_throw_rt") + ATF_REQUIRE_THROW(std::runtime_error, + if (0) throw std::runtime_error("e")); + + create_ctl_file("after"); +} + +ATF_TEST_CASE(h_require_throw_re); +ATF_TEST_CASE_HEAD(h_require_throw_re) +{ + set_md_var("descr", "Helper test case"); +} +ATF_TEST_CASE_BODY(h_require_throw_re) +{ + create_ctl_file("before"); + + if (get_config_var("what") == "throw_int") + ATF_REQUIRE_THROW_RE(std::runtime_error, "5", if (1) throw int(5)); + else if (get_config_var("what") == "throw_rt_match") + ATF_REQUIRE_THROW_RE(std::runtime_error, "foo.*baz", + if (1) throw std::runtime_error("a foo bar baz")); + else if (get_config_var("what") == "throw_rt_no_match") + ATF_REQUIRE_THROW_RE(std::runtime_error, "foo.*baz", + if (1) throw std::runtime_error("baz foo bar a")); + else if (get_config_var("what") == "no_throw_rt") + ATF_REQUIRE_THROW_RE(std::runtime_error, "e", + if (0) throw std::runtime_error("e")); + + create_ctl_file("after"); +} + +static int +errno_fail_stub(const int raised_errno) +{ + errno = raised_errno; + return -1; +} + +static int +errno_ok_stub(void) +{ + return 0; +} + +ATF_TEST_CASE(h_check_errno); +ATF_TEST_CASE_HEAD(h_check_errno) +{ + set_md_var("descr", "Helper test case"); +} +ATF_TEST_CASE_BODY(h_check_errno) +{ + create_ctl_file("before"); + + if (get_config_var("what") == "no_error") + ATF_CHECK_ERRNO(-1, errno_ok_stub() == -1); + else if (get_config_var("what") == "errno_ok") + ATF_CHECK_ERRNO(2, errno_fail_stub(2) == -1); + else if (get_config_var("what") == "errno_fail") + ATF_CHECK_ERRNO(3, errno_fail_stub(4) == -1); + else + UNREACHABLE; + + create_ctl_file("after"); +} + +ATF_TEST_CASE(h_require_errno); +ATF_TEST_CASE_HEAD(h_require_errno) +{ + set_md_var("descr", "Helper test case"); +} +ATF_TEST_CASE_BODY(h_require_errno) +{ + create_ctl_file("before"); + + if (get_config_var("what") == "no_error") + ATF_REQUIRE_ERRNO(-1, errno_ok_stub() == -1); + else if (get_config_var("what") == "errno_ok") + ATF_REQUIRE_ERRNO(2, errno_fail_stub(2) == -1); + else if (get_config_var("what") == "errno_fail") + ATF_REQUIRE_ERRNO(3, errno_fail_stub(4) == -1); + else + UNREACHABLE; + + create_ctl_file("after"); +} + +// ------------------------------------------------------------------------ +// Test cases for the macros. +// ------------------------------------------------------------------------ + +ATF_TEST_CASE(pass); +ATF_TEST_CASE_HEAD(pass) +{ + set_md_var("descr", "Tests the ATF_PASS macro"); +} +ATF_TEST_CASE_BODY(pass) +{ + ATF_TEST_CASE_USE(h_pass); + run_h_tc< ATF_TEST_CASE_NAME(h_pass) >(); + ATF_REQUIRE(atf::utils::grep_file("^passed", "result")); + ATF_REQUIRE(atf::fs::exists(atf::fs::path("before"))); + ATF_REQUIRE(!atf::fs::exists(atf::fs::path("after"))); +} + +ATF_TEST_CASE(fail); +ATF_TEST_CASE_HEAD(fail) +{ + set_md_var("descr", "Tests the ATF_FAIL macro"); +} +ATF_TEST_CASE_BODY(fail) +{ + ATF_TEST_CASE_USE(h_fail); + run_h_tc< ATF_TEST_CASE_NAME(h_fail) >(); + ATF_REQUIRE(atf::utils::grep_file("^failed: Failed on purpose", "result")); + ATF_REQUIRE(atf::fs::exists(atf::fs::path("before"))); + ATF_REQUIRE(!atf::fs::exists(atf::fs::path("after"))); +} + +ATF_TEST_CASE(skip); +ATF_TEST_CASE_HEAD(skip) +{ + set_md_var("descr", "Tests the ATF_SKIP macro"); +} +ATF_TEST_CASE_BODY(skip) +{ + ATF_TEST_CASE_USE(h_skip); + run_h_tc< ATF_TEST_CASE_NAME(h_skip) >(); + ATF_REQUIRE(atf::utils::grep_file("^skipped: Skipped on purpose", + "result")); + ATF_REQUIRE(atf::fs::exists(atf::fs::path("before"))); + ATF_REQUIRE(!atf::fs::exists(atf::fs::path("after"))); +} + +ATF_TEST_CASE(require); +ATF_TEST_CASE_HEAD(require) +{ + set_md_var("descr", "Tests the ATF_REQUIRE macro"); +} +ATF_TEST_CASE_BODY(require) +{ + struct test { + const char *cond; + bool ok; + } *t, tests[] = { + { "false", false }, + { "true", true }, + { NULL, false } + }; + + const atf::fs::path before("before"); + const atf::fs::path after("after"); + + for (t = &tests[0]; t->cond != NULL; t++) { + atf::tests::vars_map config; + config["condition"] = t->cond; + + std::cout << "Checking with a " << t->cond << " value\n"; + + ATF_TEST_CASE_USE(h_require); + run_h_tc< ATF_TEST_CASE_NAME(h_require) >(config); + + ATF_REQUIRE(atf::fs::exists(before)); + if (t->ok) { + ATF_REQUIRE(atf::utils::grep_file("^passed", "result")); + ATF_REQUIRE(atf::fs::exists(after)); + } else { + ATF_REQUIRE(atf::utils::grep_file( + "^failed: .*condition not met", "result")); + ATF_REQUIRE(!atf::fs::exists(after)); + } + + atf::fs::remove(before); + if (t->ok) + atf::fs::remove(after); + } +} + +ATF_TEST_CASE(require_eq); +ATF_TEST_CASE_HEAD(require_eq) +{ + set_md_var("descr", "Tests the ATF_REQUIRE_EQ macro"); +} +ATF_TEST_CASE_BODY(require_eq) +{ + struct test { + const char *v1; + const char *v2; + bool ok; + } *t, tests[] = { + { "1", "1", true }, + { "1", "2", false }, + { "2", "1", false }, + { "2", "2", true }, + { NULL, NULL, false } + }; + + const atf::fs::path before("before"); + const atf::fs::path after("after"); + + for (t = &tests[0]; t->v1 != NULL; t++) { + atf::tests::vars_map config; + config["v1"] = t->v1; + config["v2"] = t->v2; + + std::cout << "Checking with " << t->v1 << ", " << t->v2 + << " and expecting " << (t->ok ? "true" : "false") + << "\n"; + + ATF_TEST_CASE_USE(h_require_eq); + run_h_tc< ATF_TEST_CASE_NAME(h_require_eq) >(config); + + ATF_REQUIRE(atf::fs::exists(before)); + if (t->ok) { + ATF_REQUIRE(atf::utils::grep_file("^passed", "result")); + ATF_REQUIRE(atf::fs::exists(after)); + } else { + ATF_REQUIRE(atf::utils::grep_file("^failed: .*v1 != v2", "result")); + ATF_REQUIRE(!atf::fs::exists(after)); + } + + atf::fs::remove(before); + if (t->ok) + atf::fs::remove(after); + } +} + +ATF_TEST_CASE(require_in); +ATF_TEST_CASE_HEAD(require_in) +{ + set_md_var("descr", "Tests the ATF_REQUIRE_IN macro"); +} +ATF_TEST_CASE_BODY(require_in) +{ + struct test { + const char *value; + bool ok; + } *t, tests[] = { + { "foo", true }, + { "bar", true }, + { "baz", true }, + { "xxx", false }, + { "fooa", false }, + { "foo ", false }, + { NULL, false } + }; + + const atf::fs::path before("before"); + const atf::fs::path after("after"); + + for (t = &tests[0]; t->value != NULL; t++) { + atf::tests::vars_map config; + config["value"] = t->value; + + ATF_TEST_CASE_USE(h_require_in); + run_h_tc< ATF_TEST_CASE_NAME(h_require_in) >(config); + + ATF_REQUIRE(atf::fs::exists(before)); + if (t->ok) { + ATF_REQUIRE(atf::utils::grep_file("^passed", "result")); + ATF_REQUIRE(atf::fs::exists(after)); + } else { + ATF_REQUIRE(atf::utils::grep_file("^failed: ", "result")); + ATF_REQUIRE(!atf::fs::exists(after)); + } + + atf::fs::remove(before); + if (t->ok) + atf::fs::remove(after); + } +} + +ATF_TEST_CASE(require_match); +ATF_TEST_CASE_HEAD(require_match) +{ + set_md_var("descr", "Tests the ATF_REQUIRE_MATCH macro"); +} +ATF_TEST_CASE_BODY(require_match) +{ + struct test { + const char *regexp; + const char *string; + bool ok; + } *t, tests[] = { + { "foo.*bar", "this is a foo, bar, baz", true }, + { "bar.*baz", "this is a baz, bar, foo", false }, + { NULL, NULL, false } + }; + + const atf::fs::path before("before"); + const atf::fs::path after("after"); + + for (t = &tests[0]; t->regexp != NULL; t++) { + atf::tests::vars_map config; + config["regexp"] = t->regexp; + config["string"] = t->string; + + std::cout << "Checking with " << t->regexp << ", " << t->string + << " and expecting " << (t->ok ? "true" : "false") + << "\n"; + + ATF_TEST_CASE_USE(h_require_match); + run_h_tc< ATF_TEST_CASE_NAME(h_require_match) >(config); + + ATF_REQUIRE(atf::fs::exists(before)); + if (t->ok) { + ATF_REQUIRE(atf::utils::grep_file("^passed", "result")); + ATF_REQUIRE(atf::fs::exists(after)); + } else { + ATF_REQUIRE(atf::utils::grep_file("^failed: ", "result")); + ATF_REQUIRE(!atf::fs::exists(after)); + } + + atf::fs::remove(before); + if (t->ok) + atf::fs::remove(after); + } +} + +ATF_TEST_CASE(require_not_in); +ATF_TEST_CASE_HEAD(require_not_in) +{ + set_md_var("descr", "Tests the ATF_REQUIRE_NOT_IN macro"); +} +ATF_TEST_CASE_BODY(require_not_in) +{ + struct test { + const char *value; + bool ok; + } *t, tests[] = { + { "foo", false }, + { "bar", false }, + { "baz", false }, + { "xxx", true }, + { "fooa", true }, + { "foo ", true }, + { NULL, false } + }; + + const atf::fs::path before("before"); + const atf::fs::path after("after"); + + for (t = &tests[0]; t->value != NULL; t++) { + atf::tests::vars_map config; + config["value"] = t->value; + + ATF_TEST_CASE_USE(h_require_not_in); + run_h_tc< ATF_TEST_CASE_NAME(h_require_not_in) >(config); + + ATF_REQUIRE(atf::fs::exists(before)); + if (t->ok) { + ATF_REQUIRE(atf::utils::grep_file("^passed", "result")); + ATF_REQUIRE(atf::fs::exists(after)); + } else { + ATF_REQUIRE(atf::utils::grep_file("^failed: ", "result")); + ATF_REQUIRE(!atf::fs::exists(after)); + } + + atf::fs::remove(before); + if (t->ok) + atf::fs::remove(after); + } +} + +ATF_TEST_CASE(require_throw); +ATF_TEST_CASE_HEAD(require_throw) +{ + set_md_var("descr", "Tests the ATF_REQUIRE_THROW macro"); +} +ATF_TEST_CASE_BODY(require_throw) +{ + struct test { + const char *what; + bool ok; + const char *msg; + } *t, tests[] = { + { "throw_int", false, "unexpected error" }, + { "throw_rt", true, NULL }, + { "no_throw_rt", false, "did not throw" }, + { NULL, false, NULL } + }; + + const atf::fs::path before("before"); + const atf::fs::path after("after"); + + for (t = &tests[0]; t->what != NULL; t++) { + atf::tests::vars_map config; + config["what"] = t->what; + + std::cout << "Checking with " << t->what << " and expecting " + << (t->ok ? "true" : "false") << "\n"; + + ATF_TEST_CASE_USE(h_require_throw); + run_h_tc< ATF_TEST_CASE_NAME(h_require_throw) >(config); + + ATF_REQUIRE(atf::fs::exists(before)); + if (t->ok) { + ATF_REQUIRE(atf::utils::grep_file("^passed", "result")); + ATF_REQUIRE(atf::fs::exists(after)); + } else { + std::cout << "Checking that message contains '" << t->msg + << "'\n"; + std::string exp_result = std::string("^failed: .*") + t->msg; + ATF_REQUIRE(atf::utils::grep_file(exp_result.c_str(), "result")); + ATF_REQUIRE(!atf::fs::exists(after)); + } + + atf::fs::remove(before); + if (t->ok) + atf::fs::remove(after); + } +} + +ATF_TEST_CASE(require_throw_re); +ATF_TEST_CASE_HEAD(require_throw_re) +{ + set_md_var("descr", "Tests the ATF_REQUIRE_THROW_RE macro"); +} +ATF_TEST_CASE_BODY(require_throw_re) +{ + struct test { + const char *what; + bool ok; + const char *msg; + } *t, tests[] = { + { "throw_int", false, "unexpected error" }, + { "throw_rt_match", true, NULL }, + { "throw_rt_no_match", false, + "threw.*runtime_error\\(baz foo bar a\\).*" + "does not match 'foo\\.\\*baz'" }, + { "no_throw_rt", false, "did not throw" }, + { NULL, false, NULL } + }; + + const atf::fs::path before("before"); + const atf::fs::path after("after"); + + for (t = &tests[0]; t->what != NULL; t++) { + atf::tests::vars_map config; + config["what"] = t->what; + + std::cout << "Checking with " << t->what << " and expecting " + << (t->ok ? "true" : "false") << "\n"; + + ATF_TEST_CASE_USE(h_require_throw_re); + run_h_tc< ATF_TEST_CASE_NAME(h_require_throw_re) >(config); + + ATF_REQUIRE(atf::fs::exists(before)); + if (t->ok) { + ATF_REQUIRE(atf::utils::grep_file("^passed", "result")); + ATF_REQUIRE(atf::fs::exists(after)); + } else { + std::cout << "Checking that message contains '" << t->msg + << "'\n"; + std::string exp_result = std::string("^failed: .*") + t->msg; + ATF_REQUIRE(atf::utils::grep_file(exp_result.c_str(), "result")); + ATF_REQUIRE(!atf::fs::exists(after)); + } + + atf::fs::remove(before); + if (t->ok) + atf::fs::remove(after); + } +} + +ATF_TEST_CASE(check_errno); +ATF_TEST_CASE_HEAD(check_errno) +{ + set_md_var("descr", "Tests the ATF_CHECK_ERRNO macro"); +} +ATF_TEST_CASE_BODY(check_errno) +{ + struct test { + const char *what; + bool ok; + const char *msg; + } *t, tests[] = { + { "no_error", false, + "Expected true value in errno_ok_stub\\(\\) == -1" }, + { "errno_ok", true, NULL }, + { "errno_fail", false, + "Expected errno 3, got 4, in errno_fail_stub\\(4\\) == -1" }, + { NULL, false, NULL } + }; + + const atf::fs::path before("before"); + const atf::fs::path after("after"); + + for (t = &tests[0]; t->what != NULL; t++) { + atf::tests::vars_map config; + config["what"] = t->what; + + ATF_TEST_CASE_USE(h_check_errno); + run_h_tc< ATF_TEST_CASE_NAME(h_check_errno) >(config); + + ATF_REQUIRE(atf::fs::exists(before)); + ATF_REQUIRE(atf::fs::exists(after)); + + if (t->ok) { + ATF_REQUIRE(atf::utils::grep_file("^passed", "result")); + } else { + ATF_REQUIRE(atf::utils::grep_file("^failed", "result")); + + std::string exp_result = "macros_test.cpp:[0-9]+: " + + std::string(t->msg) + "$"; + ATF_REQUIRE(atf::utils::grep_file(exp_result.c_str(), "stderr")); + } + + atf::fs::remove(before); + atf::fs::remove(after); + } +} + +ATF_TEST_CASE(require_errno); +ATF_TEST_CASE_HEAD(require_errno) +{ + set_md_var("descr", "Tests the ATF_REQUIRE_ERRNO macro"); +} +ATF_TEST_CASE_BODY(require_errno) +{ + struct test { + const char *what; + bool ok; + const char *msg; + } *t, tests[] = { + { "no_error", false, + "Expected true value in errno_ok_stub\\(\\) == -1" }, + { "errno_ok", true, NULL }, + { "errno_fail", false, + "Expected errno 3, got 4, in errno_fail_stub\\(4\\) == -1" }, + { NULL, false, NULL } + }; + + const atf::fs::path before("before"); + const atf::fs::path after("after"); + + for (t = &tests[0]; t->what != NULL; t++) { + atf::tests::vars_map config; + config["what"] = t->what; + + ATF_TEST_CASE_USE(h_require_errno); + run_h_tc< ATF_TEST_CASE_NAME(h_require_errno) >(config); + + ATF_REQUIRE(atf::fs::exists(before)); + if (t->ok) { + ATF_REQUIRE(atf::utils::grep_file("^passed", "result")); + ATF_REQUIRE(atf::fs::exists(after)); + } else { + std::string exp_result = "^failed: .*macros_test.cpp:[0-9]+: " + + std::string(t->msg) + "$"; + ATF_REQUIRE(atf::utils::grep_file(exp_result.c_str(), "result")); + + ATF_REQUIRE(!atf::fs::exists(after)); + } + + atf::fs::remove(before); + if (t->ok) + atf::fs::remove(after); + } +} + +// ------------------------------------------------------------------------ +// Tests cases for the header file. +// ------------------------------------------------------------------------ + +HEADER_TC(include, "atf-c++/macros.hpp"); +BUILD_TC(use, "macros_hpp_test.cpp", + "Tests that the macros provided by the atf-c++/macros.hpp file " + "do not cause syntax errors when used", + "Build of macros_hpp_test.cpp failed; some macros in " + "atf-c++/macros.hpp are broken"); +BUILD_TC_FAIL(detect_unused_tests, "unused_test.cpp", + "Tests that defining an unused test case raises a warning (and thus " + "an error)", + "Build of unused_test.cpp passed; unused test cases are not properly " + "detected"); + +// ------------------------------------------------------------------------ +// Main. +// ------------------------------------------------------------------------ + +ATF_INIT_TEST_CASES(tcs) +{ + // Add the test cases for the macros. + ATF_ADD_TEST_CASE(tcs, pass); + ATF_ADD_TEST_CASE(tcs, fail); + ATF_ADD_TEST_CASE(tcs, skip); + ATF_ADD_TEST_CASE(tcs, check_errno); + ATF_ADD_TEST_CASE(tcs, require); + ATF_ADD_TEST_CASE(tcs, require_eq); + ATF_ADD_TEST_CASE(tcs, require_in); + ATF_ADD_TEST_CASE(tcs, require_match); + ATF_ADD_TEST_CASE(tcs, require_not_in); + ATF_ADD_TEST_CASE(tcs, require_throw); + ATF_ADD_TEST_CASE(tcs, require_throw_re); + ATF_ADD_TEST_CASE(tcs, require_errno); + + // Add the test cases for the header file. + ATF_ADD_TEST_CASE(tcs, include); + ATF_ADD_TEST_CASE(tcs, use); + ATF_ADD_TEST_CASE(tcs, detect_unused_tests); +} diff --git a/external/bsd/atf/dist/atf-c++/noncopyable.hpp b/external/bsd/atf/dist/atf-c++/noncopyable.hpp new file mode 100644 index 000000000..a885a668c --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/noncopyable.hpp @@ -0,0 +1,56 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#if !defined(_ATF_CXX_NONCOPYABLE_HPP_) +#define _ATF_CXX_NONCOPYABLE_HPP_ + +namespace atf { + +// ------------------------------------------------------------------------ +// The "noncopyable" class. +// ------------------------------------------------------------------------ + +class noncopyable { + // The class cannot be empty; otherwise we get ABI-stability warnings + // during the build, which will break it due to strict checking. + int m_noncopyable_dummy; + + noncopyable(const noncopyable& nc); + noncopyable& operator=(const noncopyable& nc); + +protected: + // Explicitly needed to provide some non-private functions. Otherwise + // we also get some warnings during the build. + noncopyable(void) {} + ~noncopyable(void) {} +}; + +} // namespace atf + +#endif // !defined(_ATF_CXX_NONCOPYABLE_HPP_) diff --git a/external/bsd/atf/dist/atf-c++/pkg_config_test.sh b/external/bsd/atf/dist/atf-c++/pkg_config_test.sh new file mode 100644 index 000000000..d99f0104f --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/pkg_config_test.sh @@ -0,0 +1,149 @@ +# +# Automated Testing Framework (atf) +# +# Copyright (c) 2008 The NetBSD Foundation, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +# CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# The following tests assume that the atfc++.pc file is installed in a +# directory that is known by pkg-config. Otherwise they will fail, +# and you will be required to adjust PKG_CONFIG_PATH accordingly. +# +# It would be possible to bypass this requirement by setting the path +# explicitly during the tests, but then this would not do a real check +# to ensure that the installation is working. + +require_pc() +{ + pkg-config ${1} || atf_fail "pkg-config could not locate ${1}.pc;" \ + "maybe need to set PKG_CONFIG_PATH?" +} + +check_version() +{ + atf_check -s eq:0 -o save:stdout -e empty -x \ + "atf-version | head -n 1 | cut -d ' ' -f 4" + ver1=$(cat stdout) + echo "Version reported by atf-version: ${ver1}" + + atf_check -s eq:0 -o save:stdout -e empty pkg-config --modversion "${1}" + ver2=$(cat stdout) + echo "Version reported by pkg-config: ${ver2}" + + atf_check_equal ${ver1} ${ver2} +} + +atf_test_case version +version_head() +{ + atf_set "descr" "Checks that the version in atf-c++ is correct" + atf_set "require.progs" "atf-version pkg-config" +} +version_body() +{ + require_pc "atf-c++" + + check_version "atf-c++" +} + +atf_test_case build +build_head() +{ + atf_set "descr" "Checks that a test program can be built against" \ + "the C++ library based on the pkg-config information" + atf_set "require.progs" "pkg-config" +} +build_body() +{ + require_pc "atf-c++" + + atf_check -s eq:0 -o save:stdout -e empty \ + pkg-config --variable=cxx atf-c++ + cxx=$(cat stdout) + echo "Compiler is: ${cxx}" + atf_require_prog ${cxx} + + cat >tp.cpp < + +#include + +ATF_TEST_CASE(tc); +ATF_TEST_CASE_HEAD(tc) { + set_md_var("descr", "A test case"); +} +ATF_TEST_CASE_BODY(tc) { + std::cout << "Running\n"; +} + +ATF_INIT_TEST_CASES(tcs) { + ATF_ADD_TEST_CASE(tcs, tc); +} +EOF + + atf_check -s eq:0 -o save:stdout -e empty pkg-config --cflags atf-c++ + cxxflags=$(cat stdout) + echo "CXXFLAGS are: ${cxxflags}" + + atf_check -s eq:0 -o save:stdout -e empty \ + pkg-config --libs-only-L --libs-only-other atf-c++ + ldflags=$(cat stdout) + atf_check -s eq:0 -o save:stdout -e empty \ + pkg-config --libs-only-l atf-c++ + libs=$(cat stdout) + echo "LDFLAGS are: ${ldflags}" + echo "LIBS are: ${libs}" + + atf_check -s eq:0 -o empty -e empty ${cxx} ${cxxflags} -o tp.o -c tp.cpp + atf_check -s eq:0 -o empty -e empty ${cxx} ${ldflags} -o tp tp.o ${libs} + + libpath= + for f in ${ldflags}; do + case ${f} in + -L*) + dir=$(echo ${f} | sed -e 's,^-L,,') + if [ -z "${libpath}" ]; then + libpath="${dir}" + else + libpath="${libpath}:${dir}" + fi + ;; + *) + ;; + esac + done + + atf_check -s eq:0 -o empty -e empty test -x tp + atf_check -s eq:0 -o match:'Running' -e empty -x \ + "LD_LIBRARY_PATH=${libpath} ./tp tc" +} + +atf_init_test_cases() +{ + atf_add_test_case version + atf_add_test_case build +} + +# vim: syntax=sh:expandtab:shiftwidth=4:softtabstop=4 diff --git a/external/bsd/atf/dist/atf-c++/tests.cpp b/external/bsd/atf/dist/atf-c++/tests.cpp new file mode 100644 index 000000000..2c351fcb3 --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/tests.cpp @@ -0,0 +1,711 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +extern "C" { +#include +#include +#include +#include +#include +#include +} + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern "C" { +#include "atf-c/error.h" +#include "atf-c/tc.h" +#include "atf-c/utils.h" +} + +#include "noncopyable.hpp" +#include "tests.hpp" + +#include "detail/application.hpp" +#include "detail/auto_array.hpp" +#include "detail/env.hpp" +#include "detail/exceptions.hpp" +#include "detail/fs.hpp" +#include "detail/parser.hpp" +#include "detail/sanity.hpp" +#include "detail/text.hpp" + +namespace impl = atf::tests; +namespace detail = atf::tests::detail; +#define IMPL_NAME "atf::tests" + +// ------------------------------------------------------------------------ +// The "atf_tp_writer" class. +// ------------------------------------------------------------------------ + +detail::atf_tp_writer::atf_tp_writer(std::ostream& os) : + m_os(os), + m_is_first(true) +{ + atf::parser::headers_map hm; + atf::parser::attrs_map ct_attrs; + ct_attrs["version"] = "1"; + hm["Content-Type"] = atf::parser::header_entry("Content-Type", + "application/X-atf-tp", ct_attrs); + atf::parser::write_headers(hm, m_os); +} + +void +detail::atf_tp_writer::start_tc(const std::string& ident) +{ + if (!m_is_first) + m_os << "\n"; + m_os << "ident: " << ident << "\n"; + m_os.flush(); +} + +void +detail::atf_tp_writer::end_tc(void) +{ + if (m_is_first) + m_is_first = false; +} + +void +detail::atf_tp_writer::tc_meta_data(const std::string& name, + const std::string& value) +{ + PRE(name != "ident"); + m_os << name << ": " << value << "\n"; + m_os.flush(); +} + +// ------------------------------------------------------------------------ +// Free helper functions. +// ------------------------------------------------------------------------ + +bool +detail::match(const std::string& regexp, const std::string& str) +{ + return atf::text::match(str, regexp); +} + +// ------------------------------------------------------------------------ +// The "tc" class. +// ------------------------------------------------------------------------ + +static std::map< atf_tc_t*, impl::tc* > wraps; +static std::map< const atf_tc_t*, const impl::tc* > cwraps; + +struct impl::tc_impl : atf::noncopyable { + std::string m_ident; + atf_tc_t m_tc; + bool m_has_cleanup; + + tc_impl(const std::string& ident, const bool has_cleanup) : + m_ident(ident), + m_has_cleanup(has_cleanup) + { + } + + static void + wrap_head(atf_tc_t *tc) + { + std::map< atf_tc_t*, impl::tc* >::iterator iter = wraps.find(tc); + INV(iter != wraps.end()); + (*iter).second->head(); + } + + static void + wrap_body(const atf_tc_t *tc) + { + std::map< const atf_tc_t*, const impl::tc* >::const_iterator iter = + cwraps.find(tc); + INV(iter != cwraps.end()); + try { + (*iter).second->body(); + } catch (const std::exception& e) { + (*iter).second->fail("Caught unhandled exception: " + std::string( + e.what())); + } catch (...) { + (*iter).second->fail("Caught unknown exception"); + } + } + + static void + wrap_cleanup(const atf_tc_t *tc) + { + std::map< const atf_tc_t*, const impl::tc* >::const_iterator iter = + cwraps.find(tc); + INV(iter != cwraps.end()); + (*iter).second->cleanup(); + } +}; + +impl::tc::tc(const std::string& ident, const bool has_cleanup) : + pimpl(new tc_impl(ident, has_cleanup)) +{ +} + +impl::tc::~tc(void) +{ + cwraps.erase(&pimpl->m_tc); + wraps.erase(&pimpl->m_tc); + + atf_tc_fini(&pimpl->m_tc); +} + +void +impl::tc::init(const vars_map& config) +{ + atf_error_t err; + + auto_array< const char * > array(new const char*[(config.size() * 2) + 1]); + const char **ptr = array.get(); + for (vars_map::const_iterator iter = config.begin(); + iter != config.end(); iter++) { + *ptr = (*iter).first.c_str(); + *(ptr + 1) = (*iter).second.c_str(); + ptr += 2; + } + *ptr = NULL; + + wraps[&pimpl->m_tc] = this; + cwraps[&pimpl->m_tc] = this; + + err = atf_tc_init(&pimpl->m_tc, pimpl->m_ident.c_str(), pimpl->wrap_head, + pimpl->wrap_body, pimpl->m_has_cleanup ? pimpl->wrap_cleanup : NULL, + array.get()); + if (atf_is_error(err)) + throw_atf_error(err); +} + +bool +impl::tc::has_config_var(const std::string& var) + const +{ + return atf_tc_has_config_var(&pimpl->m_tc, var.c_str()); +} + +bool +impl::tc::has_md_var(const std::string& var) + const +{ + return atf_tc_has_md_var(&pimpl->m_tc, var.c_str()); +} + +const std::string +impl::tc::get_config_var(const std::string& var) + const +{ + return atf_tc_get_config_var(&pimpl->m_tc, var.c_str()); +} + +const std::string +impl::tc::get_config_var(const std::string& var, const std::string& defval) + const +{ + return atf_tc_get_config_var_wd(&pimpl->m_tc, var.c_str(), defval.c_str()); +} + +const std::string +impl::tc::get_md_var(const std::string& var) + const +{ + return atf_tc_get_md_var(&pimpl->m_tc, var.c_str()); +} + +const impl::vars_map +impl::tc::get_md_vars(void) + const +{ + vars_map vars; + + char **array = atf_tc_get_md_vars(&pimpl->m_tc); + try { + char **ptr; + for (ptr = array; *ptr != NULL; ptr += 2) + vars[*ptr] = *(ptr + 1); + } catch (...) { + atf_utils_free_charpp(array); + throw; + } + + return vars; +} + +void +impl::tc::set_md_var(const std::string& var, const std::string& val) +{ + atf_error_t err = atf_tc_set_md_var(&pimpl->m_tc, var.c_str(), val.c_str()); + if (atf_is_error(err)) + throw_atf_error(err); +} + +void +impl::tc::run(const std::string& resfile) + const +{ + atf_error_t err = atf_tc_run(&pimpl->m_tc, resfile.c_str()); + if (atf_is_error(err)) + throw_atf_error(err); +} + +void +impl::tc::run_cleanup(void) + const +{ + atf_error_t err = atf_tc_cleanup(&pimpl->m_tc); + if (atf_is_error(err)) + throw_atf_error(err); +} + +void +impl::tc::head(void) +{ +} + +void +impl::tc::cleanup(void) + const +{ +} + +void +impl::tc::require_prog(const std::string& prog) + const +{ + atf_tc_require_prog(prog.c_str()); +} + +void +impl::tc::pass(void) +{ + atf_tc_pass(); +} + +void +impl::tc::fail(const std::string& reason) +{ + atf_tc_fail("%s", reason.c_str()); +} + +void +impl::tc::fail_nonfatal(const std::string& reason) +{ + atf_tc_fail_nonfatal("%s", reason.c_str()); +} + +void +impl::tc::skip(const std::string& reason) +{ + atf_tc_skip("%s", reason.c_str()); +} + +void +impl::tc::check_errno(const char* file, const int line, const int exp_errno, + const char* expr_str, const bool result) +{ + atf_tc_check_errno(file, line, exp_errno, expr_str, result); +} + +void +impl::tc::require_errno(const char* file, const int line, const int exp_errno, + const char* expr_str, const bool result) +{ + atf_tc_require_errno(file, line, exp_errno, expr_str, result); +} + +void +impl::tc::expect_pass(void) +{ + atf_tc_expect_pass(); +} + +void +impl::tc::expect_fail(const std::string& reason) +{ + atf_tc_expect_fail("%s", reason.c_str()); +} + +void +impl::tc::expect_exit(const int exitcode, const std::string& reason) +{ + atf_tc_expect_exit(exitcode, "%s", reason.c_str()); +} + +void +impl::tc::expect_signal(const int signo, const std::string& reason) +{ + atf_tc_expect_signal(signo, "%s", reason.c_str()); +} + +void +impl::tc::expect_death(const std::string& reason) +{ + atf_tc_expect_death("%s", reason.c_str()); +} + +void +impl::tc::expect_timeout(const std::string& reason) +{ + atf_tc_expect_timeout("%s", reason.c_str()); +} + +// ------------------------------------------------------------------------ +// The "tp" class. +// ------------------------------------------------------------------------ + +class tp : public atf::application::app { +public: + typedef std::vector< impl::tc * > tc_vector; + +private: + static const char* m_description; + + bool m_lflag; + atf::fs::path m_resfile; + std::string m_srcdir_arg; + atf::fs::path m_srcdir; + + atf::tests::vars_map m_vars; + + std::string specific_args(void) const; + options_set specific_options(void) const; + void process_option(int, const char*); + + void (*m_add_tcs)(tc_vector&); + tc_vector m_tcs; + + void parse_vflag(const std::string&); + void handle_srcdir(void); + + tc_vector init_tcs(void); + + enum tc_part { + BODY, + CLEANUP, + }; + + void list_tcs(void); + impl::tc* find_tc(tc_vector, const std::string&); + static std::pair< std::string, tc_part > process_tcarg(const std::string&); + int run_tc(const std::string&); + +public: + tp(void (*)(tc_vector&)); + ~tp(void); + + int main(void); +}; + +const char* tp::m_description = + "This is an independent atf test program."; + +tp::tp(void (*add_tcs)(tc_vector&)) : + app(m_description, "atf-test-program(1)", "atf(7)", false), + m_lflag(false), + m_resfile("/dev/stdout"), + m_srcdir("."), + m_add_tcs(add_tcs) +{ +} + +tp::~tp(void) +{ + for (tc_vector::iterator iter = m_tcs.begin(); + iter != m_tcs.end(); iter++) { + impl::tc* tc = *iter; + + delete tc; + } +} + +std::string +tp::specific_args(void) + const +{ + return "test_case"; +} + +tp::options_set +tp::specific_options(void) + const +{ + using atf::application::option; + options_set opts; + opts.insert(option('l', "", "List test cases and their purpose")); + opts.insert(option('r', "resfile", "The file to which the test program " + "will write the results of the " + "executed test case")); + opts.insert(option('s', "srcdir", "Directory where the test's data " + "files are located")); + opts.insert(option('v', "var=value", "Sets the configuration variable " + "`var' to `value'")); + return opts; +} + +void +tp::process_option(int ch, const char* arg) +{ + switch (ch) { + case 'l': + m_lflag = true; + break; + + case 'r': + m_resfile = atf::fs::path(arg); + break; + + case 's': + m_srcdir_arg = arg; + break; + + case 'v': + parse_vflag(arg); + break; + + default: + UNREACHABLE; + } +} + +void +tp::parse_vflag(const std::string& str) +{ + if (str.empty()) + throw std::runtime_error("-v requires a non-empty argument"); + + std::vector< std::string > ws = atf::text::split(str, "="); + if (ws.size() == 1 && str[str.length() - 1] == '=') { + m_vars[ws[0]] = ""; + } else { + if (ws.size() != 2) + throw std::runtime_error("-v requires an argument of the form " + "var=value"); + + m_vars[ws[0]] = ws[1]; + } +} + +void +tp::handle_srcdir(void) +{ + if (m_srcdir_arg.empty()) { + m_srcdir = atf::fs::path(m_argv0).branch_path(); + if (m_srcdir.leaf_name() == ".libs") + m_srcdir = m_srcdir.branch_path(); + } else + m_srcdir = atf::fs::path(m_srcdir_arg); + + if (!atf::fs::exists(m_srcdir / m_prog_name)) + throw std::runtime_error("Cannot find the test program in the " + "source directory `" + m_srcdir.str() + "'"); + + if (!m_srcdir.is_absolute()) + m_srcdir = m_srcdir.to_absolute(); + + m_vars["srcdir"] = m_srcdir.str(); +} + +tp::tc_vector +tp::init_tcs(void) +{ + m_add_tcs(m_tcs); + for (tc_vector::iterator iter = m_tcs.begin(); + iter != m_tcs.end(); iter++) { + impl::tc* tc = *iter; + + tc->init(m_vars); + } + return m_tcs; +} + +// +// An auxiliary unary predicate that compares the given test case's +// identifier to the identifier stored in it. +// +class tc_equal_to_ident { + const std::string& m_ident; + +public: + tc_equal_to_ident(const std::string& i) : + m_ident(i) + { + } + + bool operator()(const impl::tc* tc) + { + return tc->get_md_var("ident") == m_ident; + } +}; + +void +tp::list_tcs(void) +{ + tc_vector tcs = init_tcs(); + detail::atf_tp_writer writer(std::cout); + + for (tc_vector::const_iterator iter = tcs.begin(); + iter != tcs.end(); iter++) { + const impl::vars_map vars = (*iter)->get_md_vars(); + + { + impl::vars_map::const_iterator iter2 = vars.find("ident"); + INV(iter2 != vars.end()); + writer.start_tc((*iter2).second); + } + + for (impl::vars_map::const_iterator iter2 = vars.begin(); + iter2 != vars.end(); iter2++) { + const std::string& key = (*iter2).first; + if (key != "ident") + writer.tc_meta_data(key, (*iter2).second); + } + + writer.end_tc(); + } +} + +impl::tc* +tp::find_tc(tc_vector tcs, const std::string& name) +{ + std::vector< std::string > ids; + for (tc_vector::iterator iter = tcs.begin(); + iter != tcs.end(); iter++) { + impl::tc* tc = *iter; + + if (tc->get_md_var("ident") == name) + return tc; + } + throw atf::application::usage_error("Unknown test case `%s'", + name.c_str()); +} + +std::pair< std::string, tp::tc_part > +tp::process_tcarg(const std::string& tcarg) +{ + const std::string::size_type pos = tcarg.find(':'); + if (pos == std::string::npos) { + return std::make_pair(tcarg, BODY); + } else { + const std::string tcname = tcarg.substr(0, pos); + + const std::string partname = tcarg.substr(pos + 1); + if (partname == "body") + return std::make_pair(tcname, BODY); + else if (partname == "cleanup") + return std::make_pair(tcname, CLEANUP); + else { + using atf::application::usage_error; + throw usage_error("Invalid test case part `%s'", partname.c_str()); + } + } +} + +int +tp::run_tc(const std::string& tcarg) +{ + const std::pair< std::string, tc_part > fields = process_tcarg(tcarg); + + impl::tc* tc = find_tc(init_tcs(), fields.first); + + if (!atf::env::has("__RUNNING_INSIDE_ATF_RUN") || atf::env::get( + "__RUNNING_INSIDE_ATF_RUN") != "internal-yes-value") + { + std::cerr << m_prog_name << ": WARNING: Running test cases without " + "atf-run(1) is unsupported\n"; + std::cerr << m_prog_name << ": WARNING: No isolation nor timeout " + "control is being applied; you may get unexpected failures; see " + "atf-test-case(4)\n"; + } + + try { + switch (fields.second) { + case BODY: + tc->run(m_resfile.str()); + break; + case CLEANUP: + tc->run_cleanup(); + break; + default: + UNREACHABLE; + } + return EXIT_SUCCESS; + } catch (const std::runtime_error& e) { + std::cerr << "ERROR: " << e.what() << "\n"; + return EXIT_FAILURE; + } +} + +int +tp::main(void) +{ + using atf::application::usage_error; + + int errcode; + + handle_srcdir(); + + if (m_lflag) { + if (m_argc > 0) + throw usage_error("Cannot provide test case names with -l"); + + list_tcs(); + errcode = EXIT_SUCCESS; + } else { + if (m_argc == 0) + throw usage_error("Must provide a test case name"); + else if (m_argc > 1) + throw usage_error("Cannot provide more than one test case name"); + INV(m_argc == 1); + + errcode = run_tc(m_argv[0]); + } + + return errcode; +} + +namespace atf { + namespace tests { + int run_tp(int, char* const*, void (*)(tp::tc_vector&)); + } +} + +int +impl::run_tp(int argc, char* const* argv, void (*add_tcs)(tp::tc_vector&)) +{ + return tp(add_tcs).run(argc, argv); +} diff --git a/external/bsd/atf/dist/atf-c++/tests.hpp b/external/bsd/atf/dist/atf-c++/tests.hpp new file mode 100644 index 000000000..22a2a8706 --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/tests.hpp @@ -0,0 +1,127 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#if !defined(_ATF_CXX_TESTS_HPP_) +#define _ATF_CXX_TESTS_HPP_ + +#include +#include +#include + +extern "C" { +#include +} + +#include + +namespace atf { +namespace tests { + +namespace detail { + +class atf_tp_writer { + std::ostream& m_os; + + bool m_is_first; + +public: + atf_tp_writer(std::ostream&); + + void start_tc(const std::string&); + void end_tc(void); + void tc_meta_data(const std::string&, const std::string&); +}; + +bool match(const std::string&, const std::string&); + +} // namespace + +// ------------------------------------------------------------------------ +// The "vars_map" class. +// ------------------------------------------------------------------------ + +typedef std::map< std::string, std::string > vars_map; + +// ------------------------------------------------------------------------ +// The "tc" class. +// ------------------------------------------------------------------------ + +struct tc_impl; + +class tc : noncopyable { + std::auto_ptr< tc_impl > pimpl; + +protected: + virtual void head(void); + virtual void body(void) const = 0; + virtual void cleanup(void) const; + + void require_prog(const std::string&) const; + + friend struct tc_impl; + +public: + tc(const std::string&, const bool); + virtual ~tc(void); + + void init(const vars_map&); + + const std::string get_config_var(const std::string&) const; + const std::string get_config_var(const std::string&, const std::string&) + const; + const std::string get_md_var(const std::string&) const; + const vars_map get_md_vars(void) const; + bool has_config_var(const std::string&) const; + bool has_md_var(const std::string&) const; + void set_md_var(const std::string&, const std::string&); + + void run(const std::string&) const; + void run_cleanup(void) const; + + // To be called from the child process only. + static void pass(void) ATF_DEFS_ATTRIBUTE_NORETURN; + static void fail(const std::string&) ATF_DEFS_ATTRIBUTE_NORETURN; + static void fail_nonfatal(const std::string&); + static void skip(const std::string&) ATF_DEFS_ATTRIBUTE_NORETURN; + static void check_errno(const char*, const int, const int, const char*, + const bool); + static void require_errno(const char*, const int, const int, const char*, + const bool); + static void expect_pass(void); + static void expect_fail(const std::string&); + static void expect_exit(const int, const std::string&); + static void expect_signal(const int, const std::string&); + static void expect_death(const std::string&); + static void expect_timeout(const std::string&); +}; + +} // namespace tests +} // namespace atf + +#endif // !defined(_ATF_CXX_TESTS_HPP_) diff --git a/external/bsd/atf/dist/atf-c++/tests_test.cpp b/external/bsd/atf/dist/atf-c++/tests_test.cpp new file mode 100644 index 000000000..63ab2ef91 --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/tests_test.cpp @@ -0,0 +1,201 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +extern "C" { +#include +#include + +#include +#include +} + +#include +#include + +#include "macros.hpp" + +#include "detail/parser.hpp" +#include "detail/test_helpers.hpp" + +// ------------------------------------------------------------------------ +// Tests for the "atf_tp_writer" class. +// ------------------------------------------------------------------------ + +static +void +print_indented(const std::string& str) +{ + std::vector< std::string > ws = atf::text::split(str, "\n"); + for (std::vector< std::string >::const_iterator iter = ws.begin(); + iter != ws.end(); iter++) + std::cout << ">>" << *iter << "<<\n"; +} + +// XXX Should this string handling and verbosity level be part of the +// ATF_REQUIRE_EQ macro? It may be hard to predict sometimes that a +// string can have newlines in it, and so the error message generated +// at the moment will be bogus if there are some. +static +void +check_equal(const atf::tests::tc& tc, const std::string& str, + const std::string& exp) +{ + if (str != exp) { + std::cout << "String equality check failed.\n" + "Adding >> and << to delimit the string boundaries below.\n"; + std::cout << "GOT:\n"; + print_indented(str); + std::cout << "EXPECTED:\n"; + print_indented(exp); + tc.fail("Constructed string differs from the expected one"); + } +} + +ATF_TEST_CASE(atf_tp_writer); +ATF_TEST_CASE_HEAD(atf_tp_writer) +{ + set_md_var("descr", "Verifies the application/X-atf-tp writer"); +} +ATF_TEST_CASE_BODY(atf_tp_writer) +{ + std::ostringstream expss; + std::ostringstream ss; + +#define RESET \ + expss.str(""); \ + ss.str("") + +#define CHECK \ + check_equal(*this, ss.str(), expss.str()) + + { + RESET; + + atf::tests::detail::atf_tp_writer w(ss); + expss << "Content-Type: application/X-atf-tp; version=\"1\"\n\n"; + CHECK; + } + + { + RESET; + + atf::tests::detail::atf_tp_writer w(ss); + expss << "Content-Type: application/X-atf-tp; version=\"1\"\n\n"; + CHECK; + + w.start_tc("test1"); + expss << "ident: test1\n"; + CHECK; + + w.end_tc(); + CHECK; + } + + { + RESET; + + atf::tests::detail::atf_tp_writer w(ss); + expss << "Content-Type: application/X-atf-tp; version=\"1\"\n\n"; + CHECK; + + w.start_tc("test1"); + expss << "ident: test1\n"; + CHECK; + + w.end_tc(); + CHECK; + + w.start_tc("test2"); + expss << "\nident: test2\n"; + CHECK; + + w.end_tc(); + CHECK; + } + + { + RESET; + + atf::tests::detail::atf_tp_writer w(ss); + expss << "Content-Type: application/X-atf-tp; version=\"1\"\n\n"; + CHECK; + + w.start_tc("test1"); + expss << "ident: test1\n"; + CHECK; + + w.tc_meta_data("descr", "the description"); + expss << "descr: the description\n"; + CHECK; + + w.end_tc(); + CHECK; + + w.start_tc("test2"); + expss << "\nident: test2\n"; + CHECK; + + w.tc_meta_data("descr", "second test case"); + expss << "descr: second test case\n"; + CHECK; + + w.tc_meta_data("require.progs", "/bin/cp"); + expss << "require.progs: /bin/cp\n"; + CHECK; + + w.tc_meta_data("X-custom", "foo bar baz"); + expss << "X-custom: foo bar baz\n"; + CHECK; + + w.end_tc(); + CHECK; + } + +#undef CHECK +#undef RESET +} + +// ------------------------------------------------------------------------ +// Tests cases for the header file. +// ------------------------------------------------------------------------ + +HEADER_TC(include, "atf-c++/tests.hpp"); + +// ------------------------------------------------------------------------ +// Main. +// ------------------------------------------------------------------------ + +ATF_INIT_TEST_CASES(tcs) +{ + // Add tests for the "atf_tp_writer" class. + ATF_ADD_TEST_CASE(tcs, atf_tp_writer); + + // Add the test cases for the header file. + ATF_ADD_TEST_CASE(tcs, include); +} diff --git a/external/bsd/atf/dist/atf-c++/unused_test.cpp b/external/bsd/atf/dist/atf-c++/unused_test.cpp new file mode 100644 index 000000000..2a18a455a --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/unused_test.cpp @@ -0,0 +1,52 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2012 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#include + +ATF_TEST_CASE(this_is_used); +ATF_TEST_CASE_HEAD(this_is_used) +{ +} +ATF_TEST_CASE_BODY(this_is_used) +{ +} + +ATF_TEST_CASE(this_is_unused); +ATF_TEST_CASE_HEAD(this_is_unused) +{ +} +ATF_TEST_CASE_BODY(this_is_unused) +{ +} + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, this_is_used); + //ATF_ADD_TEST_CASE(tcs, this_is_unused); +} diff --git a/external/bsd/atf/dist/atf-c++/utils.cpp b/external/bsd/atf/dist/atf-c++/utils.cpp new file mode 100644 index 000000000..cc338bb89 --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/utils.cpp @@ -0,0 +1,104 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +extern "C" { +#include "atf-c/utils.h" +} + +#include +#include + +#include "utils.hpp" + +void +atf::utils::cat_file(const std::string& path, const std::string& prefix) +{ + atf_utils_cat_file(path.c_str(), prefix.c_str()); +} + +void +atf::utils::copy_file(const std::string& source, const std::string& destination) +{ + atf_utils_copy_file(source.c_str(), destination.c_str()); +} + +bool +atf::utils::compare_file(const std::string& path, const std::string& contents) +{ + return atf_utils_compare_file(path.c_str(), contents.c_str()); +} + +void +atf::utils::create_file(const std::string& path, const std::string& contents) +{ + atf_utils_create_file(path.c_str(), "%s", contents.c_str()); +} + +bool +atf::utils::file_exists(const std::string& path) +{ + return atf_utils_file_exists(path.c_str()); +} + +pid_t +atf::utils::fork(void) +{ + std::cout.flush(); + std::cerr.flush(); + return atf_utils_fork(); +} + +bool +atf::utils::grep_file(const std::string& regex, const std::string& path) +{ + return atf_utils_grep_file("%s", path.c_str(), regex.c_str()); +} + +bool +atf::utils::grep_string(const std::string& regex, const std::string& str) +{ + return atf_utils_grep_string("%s", str.c_str(), regex.c_str()); +} + +void +atf::utils::redirect(const int fd, const std::string& path) +{ + if (fd == STDOUT_FILENO) + std::cout.flush(); + else if (fd == STDERR_FILENO) + std::cerr.flush(); + atf_utils_redirect(fd, path.c_str()); +} + +void +atf::utils::wait(const pid_t pid, const int exitstatus, + const std::string& expout, const std::string& experr) +{ + atf_utils_wait(pid, exitstatus, expout.c_str(), experr.c_str()); +} diff --git a/external/bsd/atf/dist/atf-c++/utils.hpp b/external/bsd/atf/dist/atf-c++/utils.hpp new file mode 100644 index 000000000..b8596aecd --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/utils.hpp @@ -0,0 +1,68 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#if !defined(_ATF_CXX_UTILS_HPP_) +#define _ATF_CXX_UTILS_HPP_ + +extern "C" { +#include +} + +#include + +namespace atf { +namespace utils { + +void cat_file(const std::string&, const std::string&); +bool compare_file(const std::string&, const std::string&); +void copy_file(const std::string&, const std::string&); +void create_file(const std::string&, const std::string&); +bool file_exists(const std::string&); +pid_t fork(void); +bool grep_file(const std::string&, const std::string&); +bool grep_string(const std::string&, const std::string&); +void redirect(const int, const std::string&); +void wait(const pid_t, const int, const std::string&, const std::string&); + +template< typename Collection > +bool +grep_collection(const std::string& regexp, const Collection& collection) +{ + for (typename Collection::const_iterator iter = collection.begin(); + iter != collection.end(); ++iter) { + if (grep_string(regexp, *iter)) + return true; + } + return false; +} + +} // namespace utils +} // namespace atf + +#endif // !defined(_ATF_CXX_UTILS_HPP_) diff --git a/external/bsd/atf/dist/atf-c++/utils_test.cpp b/external/bsd/atf/dist/atf-c++/utils_test.cpp new file mode 100644 index 000000000..37457ff2b --- /dev/null +++ b/external/bsd/atf/dist/atf-c++/utils_test.cpp @@ -0,0 +1,487 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +extern "C" { +#include +#include + +#include +#include +} + +#include +#include +#include +#include +#include + +#include "macros.hpp" +#include "utils.hpp" + +#include "detail/test_helpers.hpp" + +static std::string +read_file(const char *path) +{ + char buffer[1024]; + + const int fd = open(path, O_RDONLY); + if (fd == -1) + ATF_FAIL("Cannot open " + std::string(path)); + const ssize_t length = read(fd, buffer, sizeof(buffer) - 1); + close(fd); + ATF_REQUIRE(length != -1); + if (length == sizeof(buffer) - 1) + ATF_FAIL("Internal buffer not long enough to read temporary file"); + ((char *)buffer)[length] = '\0'; + + return buffer; +} + +// ------------------------------------------------------------------------ +// Tests cases for the free functions. +// ------------------------------------------------------------------------ + +ATF_TEST_CASE_WITHOUT_HEAD(cat_file__empty); +ATF_TEST_CASE_BODY(cat_file__empty) +{ + atf::utils::create_file("file.txt", ""); + atf::utils::redirect(STDOUT_FILENO, "captured.txt"); + atf::utils::cat_file("file.txt", "PREFIX"); + std::cout.flush(); + close(STDOUT_FILENO); + + ATF_REQUIRE_EQ("", read_file("captured.txt")); +} + +ATF_TEST_CASE_WITHOUT_HEAD(cat_file__one_line); +ATF_TEST_CASE_BODY(cat_file__one_line) +{ + atf::utils::create_file("file.txt", "This is a single line\n"); + atf::utils::redirect(STDOUT_FILENO, "captured.txt"); + atf::utils::cat_file("file.txt", "PREFIX"); + std::cout.flush(); + close(STDOUT_FILENO); + + ATF_REQUIRE_EQ("PREFIXThis is a single line\n", read_file("captured.txt")); +} + +ATF_TEST_CASE_WITHOUT_HEAD(cat_file__several_lines); +ATF_TEST_CASE_BODY(cat_file__several_lines) +{ + atf::utils::create_file("file.txt", "First\nSecond line\nAnd third\n"); + atf::utils::redirect(STDOUT_FILENO, "captured.txt"); + atf::utils::cat_file("file.txt", ">"); + std::cout.flush(); + close(STDOUT_FILENO); + + ATF_REQUIRE_EQ(">First\n>Second line\n>And third\n", + read_file("captured.txt")); +} + +ATF_TEST_CASE_WITHOUT_HEAD(cat_file__no_newline_eof); +ATF_TEST_CASE_BODY(cat_file__no_newline_eof) +{ + atf::utils::create_file("file.txt", "Foo\n bar baz"); + atf::utils::redirect(STDOUT_FILENO, "captured.txt"); + atf::utils::cat_file("file.txt", "PREFIX"); + std::cout.flush(); + close(STDOUT_FILENO); + + ATF_REQUIRE_EQ("PREFIXFoo\nPREFIX bar baz", read_file("captured.txt")); +} + +ATF_TEST_CASE_WITHOUT_HEAD(compare_file__empty__match); +ATF_TEST_CASE_BODY(compare_file__empty__match) +{ + atf::utils::create_file("test.txt", ""); + ATF_REQUIRE(atf::utils::compare_file("test.txt", "")); +} + +ATF_TEST_CASE_WITHOUT_HEAD(compare_file__empty__not_match); +ATF_TEST_CASE_BODY(compare_file__empty__not_match) +{ + atf::utils::create_file("test.txt", ""); + ATF_REQUIRE(!atf::utils::compare_file("test.txt", "\n")); + ATF_REQUIRE(!atf::utils::compare_file("test.txt", "foo")); + ATF_REQUIRE(!atf::utils::compare_file("test.txt", " ")); +} + +ATF_TEST_CASE_WITHOUT_HEAD(compare_file__short__match); +ATF_TEST_CASE_BODY(compare_file__short__match) +{ + atf::utils::create_file("test.txt", "this is a short file"); + ATF_REQUIRE(atf::utils::compare_file("test.txt", "this is a short file")); +} + +ATF_TEST_CASE_WITHOUT_HEAD(compare_file__short__not_match); +ATF_TEST_CASE_BODY(compare_file__short__not_match) +{ + atf::utils::create_file("test.txt", "this is a short file"); + ATF_REQUIRE(!atf::utils::compare_file("test.txt", "")); + ATF_REQUIRE(!atf::utils::compare_file("test.txt", "\n")); + ATF_REQUIRE(!atf::utils::compare_file("test.txt", "this is a Short file")); + ATF_REQUIRE(!atf::utils::compare_file("test.txt", "this is a short fil")); + ATF_REQUIRE(!atf::utils::compare_file("test.txt", "this is a short file ")); +} + +ATF_TEST_CASE_WITHOUT_HEAD(compare_file__long__match); +ATF_TEST_CASE_BODY(compare_file__long__match) +{ + char long_contents[3456]; + size_t i = 0; + for (; i < sizeof(long_contents) - 1; i++) + long_contents[i] = '0' + (i % 10); + long_contents[i] = '\0'; + atf::utils::create_file("test.txt", long_contents); + + ATF_REQUIRE(atf::utils::compare_file("test.txt", long_contents)); +} + +ATF_TEST_CASE_WITHOUT_HEAD(compare_file__long__not_match); +ATF_TEST_CASE_BODY(compare_file__long__not_match) +{ + char long_contents[3456]; + size_t i = 0; + for (; i < sizeof(long_contents) - 1; i++) + long_contents[i] = '0' + (i % 10); + long_contents[i] = '\0'; + atf::utils::create_file("test.txt", long_contents); + + ATF_REQUIRE(!atf::utils::compare_file("test.txt", "")); + ATF_REQUIRE(!atf::utils::compare_file("test.txt", "\n")); + ATF_REQUIRE(!atf::utils::compare_file("test.txt", "0123456789")); + long_contents[i - 1] = 'Z'; + ATF_REQUIRE(!atf::utils::compare_file("test.txt", long_contents)); +} + +ATF_TEST_CASE_WITHOUT_HEAD(copy_file__empty); +ATF_TEST_CASE_BODY(copy_file__empty) +{ + atf::utils::create_file("src.txt", ""); + ATF_REQUIRE(chmod("src.txt", 0520) != -1); + + atf::utils::copy_file("src.txt", "dest.txt"); + ATF_REQUIRE(atf::utils::compare_file("dest.txt", "")); + struct stat sb; + ATF_REQUIRE(stat("dest.txt", &sb) != -1); + ATF_REQUIRE_EQ(0520, sb.st_mode & 0xfff); +} + +ATF_TEST_CASE_WITHOUT_HEAD(copy_file__some_contents); +ATF_TEST_CASE_BODY(copy_file__some_contents) +{ + atf::utils::create_file("src.txt", "This is a\ntest file\n"); + atf::utils::copy_file("src.txt", "dest.txt"); + ATF_REQUIRE(atf::utils::compare_file("dest.txt", "This is a\ntest file\n")); +} + +ATF_TEST_CASE_WITHOUT_HEAD(create_file); +ATF_TEST_CASE_BODY(create_file) +{ + atf::utils::create_file("test.txt", "This is a %d test"); + + ATF_REQUIRE_EQ("This is a %d test", read_file("test.txt")); +} + +ATF_TEST_CASE_WITHOUT_HEAD(file_exists); +ATF_TEST_CASE_BODY(file_exists) +{ + atf::utils::create_file("test.txt", "foo"); + + ATF_REQUIRE( atf::utils::file_exists("test.txt")); + ATF_REQUIRE( atf::utils::file_exists("./test.txt")); + ATF_REQUIRE(!atf::utils::file_exists("./test.tx")); + ATF_REQUIRE(!atf::utils::file_exists("test.txt2")); +} + +ATF_TEST_CASE_WITHOUT_HEAD(fork); +ATF_TEST_CASE_BODY(fork) +{ + std::cout << "Should not get into child\n"; + std::cerr << "Should not get into child\n"; + pid_t pid = atf::utils::fork(); + if (pid == 0) { + std::cout << "Child stdout\n"; + std::cerr << "Child stderr\n"; + exit(EXIT_SUCCESS); + } + + int status; + ATF_REQUIRE(waitpid(pid, &status, 0) != -1); + ATF_REQUIRE(WIFEXITED(status)); + ATF_REQUIRE_EQ(EXIT_SUCCESS, WEXITSTATUS(status)); + + ATF_REQUIRE_EQ("Child stdout\n", read_file("atf_utils_fork_out.txt")); + ATF_REQUIRE_EQ("Child stderr\n", read_file("atf_utils_fork_err.txt")); +} + +ATF_TEST_CASE_WITHOUT_HEAD(grep_collection__set); +ATF_TEST_CASE_BODY(grep_collection__set) +{ + std::set< std::string > strings; + strings.insert("First"); + strings.insert("Second"); + + ATF_REQUIRE( atf::utils::grep_collection("irs", strings)); + ATF_REQUIRE( atf::utils::grep_collection("cond", strings)); + ATF_REQUIRE(!atf::utils::grep_collection("Third", strings)); +} + +ATF_TEST_CASE_WITHOUT_HEAD(grep_collection__vector); +ATF_TEST_CASE_BODY(grep_collection__vector) +{ + std::vector< std::string > strings; + strings.push_back("First"); + strings.push_back("Second"); + + ATF_REQUIRE( atf::utils::grep_collection("irs", strings)); + ATF_REQUIRE( atf::utils::grep_collection("cond", strings)); + ATF_REQUIRE(!atf::utils::grep_collection("Third", strings)); +} + +ATF_TEST_CASE_WITHOUT_HEAD(grep_file); +ATF_TEST_CASE_BODY(grep_file) +{ + atf::utils::create_file("test.txt", "line1\nthe second line\naaaabbbb\n"); + + ATF_REQUIRE(atf::utils::grep_file("line1", "test.txt")); + ATF_REQUIRE(atf::utils::grep_file("second line", "test.txt")); + ATF_REQUIRE(atf::utils::grep_file("aa.*bb", "test.txt")); + ATF_REQUIRE(!atf::utils::grep_file("foo", "test.txt")); + ATF_REQUIRE(!atf::utils::grep_file("bar", "test.txt")); + ATF_REQUIRE(!atf::utils::grep_file("aaaaa", "test.txt")); +} + +ATF_TEST_CASE_WITHOUT_HEAD(grep_string); +ATF_TEST_CASE_BODY(grep_string) +{ + const char *str = "a string - aaaabbbb"; + ATF_REQUIRE(atf::utils::grep_string("a string", str)); + ATF_REQUIRE(atf::utils::grep_string("^a string", str)); + ATF_REQUIRE(atf::utils::grep_string("aaaabbbb$", str)); + ATF_REQUIRE(atf::utils::grep_string("aa.*bb", str)); + ATF_REQUIRE(!atf::utils::grep_string("foo", str)); + ATF_REQUIRE(!atf::utils::grep_string("bar", str)); + ATF_REQUIRE(!atf::utils::grep_string("aaaaa", str)); +} + +ATF_TEST_CASE_WITHOUT_HEAD(redirect__stdout); +ATF_TEST_CASE_BODY(redirect__stdout) +{ + std::cout << "Buffer this"; + atf::utils::redirect(STDOUT_FILENO, "captured.txt"); + std::cout << "The printed message"; + std::cout.flush(); + + ATF_REQUIRE_EQ("The printed message", read_file("captured.txt")); +} + +ATF_TEST_CASE_WITHOUT_HEAD(redirect__stderr); +ATF_TEST_CASE_BODY(redirect__stderr) +{ + std::cerr << "Buffer this"; + atf::utils::redirect(STDERR_FILENO, "captured.txt"); + std::cerr << "The printed message"; + std::cerr.flush(); + + ATF_REQUIRE_EQ("The printed message", read_file("captured.txt")); +} + +ATF_TEST_CASE_WITHOUT_HEAD(redirect__other); +ATF_TEST_CASE_BODY(redirect__other) +{ + const std::string message = "Foo bar\nbaz\n"; + atf::utils::redirect(15, "captured.txt"); + ATF_REQUIRE(write(15, message.c_str(), message.length()) != -1); + close(15); + + ATF_REQUIRE_EQ(message, read_file("captured.txt")); +} + +static void +fork_and_wait(const int exitstatus, const char* expout, const char* experr) +{ + const pid_t pid = atf::utils::fork(); + if (pid == 0) { + std::cout << "Some output\n"; + std::cerr << "Some error\n"; + exit(123); + } + atf::utils::wait(pid, exitstatus, expout, experr); + exit(EXIT_SUCCESS); +} + +ATF_TEST_CASE_WITHOUT_HEAD(wait__ok); +ATF_TEST_CASE_BODY(wait__ok) +{ + const pid_t control = fork(); + ATF_REQUIRE(control != -1); + if (control == 0) + fork_and_wait(123, "Some output\n", "Some error\n"); + else { + int status; + ATF_REQUIRE(waitpid(control, &status, 0) != -1); + ATF_REQUIRE(WIFEXITED(status)); + ATF_REQUIRE_EQ(EXIT_SUCCESS, WEXITSTATUS(status)); + } +} + +ATF_TEST_CASE_WITHOUT_HEAD(wait__invalid_exitstatus); +ATF_TEST_CASE_BODY(wait__invalid_exitstatus) +{ + const pid_t control = fork(); + ATF_REQUIRE(control != -1); + if (control == 0) + fork_and_wait(120, "Some output\n", "Some error\n"); + else { + int status; + ATF_REQUIRE(waitpid(control, &status, 0) != -1); + ATF_REQUIRE(WIFEXITED(status)); + ATF_REQUIRE_EQ(EXIT_FAILURE, WEXITSTATUS(status)); + } +} + +ATF_TEST_CASE_WITHOUT_HEAD(wait__invalid_stdout); +ATF_TEST_CASE_BODY(wait__invalid_stdout) +{ + const pid_t control = fork(); + ATF_REQUIRE(control != -1); + if (control == 0) + fork_and_wait(123, "Some output foo\n", "Some error\n"); + else { + int status; + ATF_REQUIRE(waitpid(control, &status, 0) != -1); + ATF_REQUIRE(WIFEXITED(status)); + ATF_REQUIRE_EQ(EXIT_FAILURE, WEXITSTATUS(status)); + } +} + +ATF_TEST_CASE_WITHOUT_HEAD(wait__invalid_stderr); +ATF_TEST_CASE_BODY(wait__invalid_stderr) +{ + const pid_t control = fork(); + ATF_REQUIRE(control != -1); + if (control == 0) + fork_and_wait(123, "Some output\n", "Some error foo\n"); + else { + int status; + ATF_REQUIRE(waitpid(control, &status, 0) != -1); + ATF_REQUIRE(WIFEXITED(status)); + ATF_REQUIRE_EQ(EXIT_FAILURE, WEXITSTATUS(status)); + } +} + +ATF_TEST_CASE_WITHOUT_HEAD(wait__save_stdout); +ATF_TEST_CASE_BODY(wait__save_stdout) +{ + const pid_t control = fork(); + ATF_REQUIRE(control != -1); + if (control == 0) + fork_and_wait(123, "save:my-output.txt", "Some error\n"); + else { + int status; + ATF_REQUIRE(waitpid(control, &status, 0) != -1); + ATF_REQUIRE(WIFEXITED(status)); + ATF_REQUIRE_EQ(EXIT_SUCCESS, WEXITSTATUS(status)); + + ATF_REQUIRE(atf::utils::compare_file("my-output.txt", "Some output\n")); + } +} + +ATF_TEST_CASE_WITHOUT_HEAD(wait__save_stderr); +ATF_TEST_CASE_BODY(wait__save_stderr) +{ + const pid_t control = fork(); + ATF_REQUIRE(control != -1); + if (control == 0) + fork_and_wait(123, "Some output\n", "save:my-output.txt"); + else { + int status; + ATF_REQUIRE(waitpid(control, &status, 0) != -1); + ATF_REQUIRE(WIFEXITED(status)); + ATF_REQUIRE_EQ(EXIT_SUCCESS, WEXITSTATUS(status)); + + ATF_REQUIRE(atf::utils::compare_file("my-output.txt", "Some error\n")); + } +} + +// ------------------------------------------------------------------------ +// Tests cases for the header file. +// ------------------------------------------------------------------------ + +HEADER_TC(include, "atf-c++/utils.hpp"); + +// ------------------------------------------------------------------------ +// Main. +// ------------------------------------------------------------------------ + +ATF_INIT_TEST_CASES(tcs) +{ + // Add the test for the free functions. + ATF_ADD_TEST_CASE(tcs, cat_file__empty); + ATF_ADD_TEST_CASE(tcs, cat_file__one_line); + ATF_ADD_TEST_CASE(tcs, cat_file__several_lines); + ATF_ADD_TEST_CASE(tcs, cat_file__no_newline_eof); + + ATF_ADD_TEST_CASE(tcs, compare_file__empty__match); + ATF_ADD_TEST_CASE(tcs, compare_file__empty__not_match); + ATF_ADD_TEST_CASE(tcs, compare_file__short__match); + ATF_ADD_TEST_CASE(tcs, compare_file__short__not_match); + ATF_ADD_TEST_CASE(tcs, compare_file__long__match); + ATF_ADD_TEST_CASE(tcs, compare_file__long__not_match); + + ATF_ADD_TEST_CASE(tcs, copy_file__empty); + ATF_ADD_TEST_CASE(tcs, copy_file__some_contents); + + ATF_ADD_TEST_CASE(tcs, create_file); + + ATF_ADD_TEST_CASE(tcs, file_exists); + + ATF_ADD_TEST_CASE(tcs, fork); + + ATF_ADD_TEST_CASE(tcs, grep_collection__set); + ATF_ADD_TEST_CASE(tcs, grep_collection__vector); + ATF_ADD_TEST_CASE(tcs, grep_file); + ATF_ADD_TEST_CASE(tcs, grep_string); + + ATF_ADD_TEST_CASE(tcs, redirect__stdout); + ATF_ADD_TEST_CASE(tcs, redirect__stderr); + ATF_ADD_TEST_CASE(tcs, redirect__other); + + ATF_ADD_TEST_CASE(tcs, wait__ok); + ATF_ADD_TEST_CASE(tcs, wait__invalid_exitstatus); + ATF_ADD_TEST_CASE(tcs, wait__invalid_stdout); + ATF_ADD_TEST_CASE(tcs, wait__invalid_stderr); + ATF_ADD_TEST_CASE(tcs, wait__save_stdout); + ATF_ADD_TEST_CASE(tcs, wait__save_stderr); + + // Add the test cases for the header file. + ATF_ADD_TEST_CASE(tcs, include); +} diff --git a/external/bsd/atf/dist/atf-c.h b/external/bsd/atf/dist/atf-c.h new file mode 100644 index 000000000..86606df3f --- /dev/null +++ b/external/bsd/atf/dist/atf-c.h @@ -0,0 +1,37 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if !defined(ATF_C_H) +#define ATF_C_H + +#include +#include +#include + +#endif /* !defined(ATF_C_H) */ diff --git a/external/bsd/atf/dist/atf-c/Atffile b/external/bsd/atf/dist/atf-c/Atffile new file mode 100644 index 000000000..522e6f4c5 --- /dev/null +++ b/external/bsd/atf/dist/atf-c/Atffile @@ -0,0 +1,16 @@ +Content-Type: application/X-atf-atffile; version="1" + +prop: test-suite = atf + +tp: detail + +tp: atf_c_test +tp: build_test +tp: check_test +tp: config_test +tp: error_test +tp: macros_test +tp: pkg_config_test +tp: tc_test +tp: tp_test +tp: utils_test diff --git a/external/bsd/atf/dist/atf-c/Kyuafile b/external/bsd/atf/dist/atf-c/Kyuafile new file mode 100644 index 000000000..2f3b82e10 --- /dev/null +++ b/external/bsd/atf/dist/atf-c/Kyuafile @@ -0,0 +1,16 @@ +syntax("kyuafile", 1) + +test_suite("atf") + +atf_test_program{name="atf_c_test"} +atf_test_program{name="build_test"} +atf_test_program{name="check_test"} +atf_test_program{name="config_test"} +atf_test_program{name="error_test"} +atf_test_program{name="macros_test"} +atf_test_program{name="pkg_config_test"} +atf_test_program{name="tc_test"} +atf_test_program{name="tp_test"} +atf_test_program{name="utils_test"} + +include("detail/Kyuafile") diff --git a/external/bsd/atf/dist/atf-c/atf-c-api.3 b/external/bsd/atf/dist/atf-c/atf-c-api.3 new file mode 100644 index 000000000..0ef47a49c --- /dev/null +++ b/external/bsd/atf/dist/atf-c/atf-c-api.3 @@ -0,0 +1,776 @@ +.\" +.\" Automated Testing Framework (atf) +.\" +.\" Copyright (c) 2008 The NetBSD Foundation, Inc. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +.\" CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +.\" IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +.\" GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +.\" IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.Dd November 30, 2012 +.Dt ATF-C-API 3 +.Os +.Sh NAME +.Nm atf-c-api , +.Nm ATF_CHECK , +.Nm ATF_CHECK_MSG , +.Nm ATF_CHECK_EQ , +.Nm ATF_CHECK_EQ_MSG , +.Nm ATF_CHECK_MATCH , +.Nm ATF_CHECK_MATCH_MSG , +.Nm ATF_CHECK_STREQ , +.Nm ATF_CHECK_STREQ_MSG , +.Nm ATF_CHECK_ERRNO , +.Nm ATF_REQUIRE , +.Nm ATF_REQUIRE_MSG , +.Nm ATF_REQUIRE_EQ , +.Nm ATF_REQUIRE_EQ_MSG , +.Nm ATF_REQUIRE_MATCH , +.Nm ATF_REQUIRE_MATCH_MSG , +.Nm ATF_REQUIRE_STREQ , +.Nm ATF_REQUIRE_STREQ_MSG , +.Nm ATF_REQUIRE_ERRNO , +.Nm ATF_TC , +.Nm ATF_TC_BODY , +.Nm ATF_TC_BODY_NAME , +.Nm ATF_TC_CLEANUP , +.Nm ATF_TC_CLEANUP_NAME , +.Nm ATF_TC_HEAD , +.Nm ATF_TC_HEAD_NAME , +.Nm ATF_TC_NAME , +.Nm ATF_TC_WITH_CLEANUP , +.Nm ATF_TC_WITHOUT_HEAD , +.Nm ATF_TP_ADD_TC , +.Nm ATF_TP_ADD_TCS , +.Nm atf_tc_get_config_var , +.Nm atf_tc_get_config_var_wd , +.Nm atf_tc_get_config_var_as_bool , +.Nm atf_tc_get_config_var_as_bool_wd , +.Nm atf_tc_get_config_var_as_long , +.Nm atf_tc_get_config_var_as_long_wd , +.Nm atf_no_error , +.Nm atf_tc_expect_death , +.Nm atf_tc_expect_exit , +.Nm atf_tc_expect_fail , +.Nm atf_tc_expect_pass , +.Nm atf_tc_expect_signal , +.Nm atf_tc_expect_timeout , +.Nm atf_tc_fail , +.Nm atf_tc_fail_nonfatal , +.Nm atf_tc_pass , +.Nm atf_tc_skip , +.Nm atf_utils_cat_file , +.Nm atf_utils_compare_file , +.Nm atf_utils_copy_file , +.Nm atf_utils_create_file , +.Nm atf_utils_file_exists , +.Nm atf_utils_fork , +.Nm atf_utils_free_charpp , +.Nm atf_utils_grep_file , +.Nm atf_utils_grep_string , +.Nm atf_utils_readline , +.Nm atf_utils_redirect , +.Nm atf_utils_wait +.Nd C API to write ATF-based test programs +.Sh SYNOPSIS +.In atf-c.h +.Fn ATF_CHECK "expression" +.Fn ATF_CHECK_MSG "expression" "fail_msg_fmt" ... +.Fn ATF_CHECK_EQ "expression_1" "expression_2" +.Fn ATF_CHECK_EQ_MSG "expression_1" "expression_2" "fail_msg_fmt" ... +.Fn ATF_CHECK_MATCH "regexp" "string" +.Fn ATF_CHECK_MATCH_MSG "regexp" "string" "fail_msg_fmt" ... +.Fn ATF_CHECK_STREQ "string_1" "string_2" +.Fn ATF_CHECK_STREQ_MSG "string_1" "string_2" "fail_msg_fmt" ... +.Fn ATF_CHECK_ERRNO "exp_errno" "bool_expression" +.Fn ATF_REQUIRE "expression" +.Fn ATF_REQUIRE_MSG "expression" "fail_msg_fmt" ... +.Fn ATF_REQUIRE_EQ "expression_1" "expression_2" +.Fn ATF_REQUIRE_EQ_MSG "expression_1" "expression_2" "fail_msg_fmt" ... +.Fn ATF_REQUIRE_MATCH "regexp" "string" +.Fn ATF_REQUIRE_MATCH_MSG "regexp" "string" "fail_msg_fmt" ... +.Fn ATF_REQUIRE_STREQ "string_1" "string_2" +.Fn ATF_REQUIRE_STREQ_MSG "string_1" "string_2" "fail_msg_fmt" ... +.Fn ATF_REQUIRE_ERRNO "exp_errno" "bool_expression" +.Fn ATF_TC "name" +.Fn ATF_TC_BODY "name" "tc" +.Fn ATF_TC_BODY_NAME "name" +.Fn ATF_TC_CLEANUP "name" "tc" +.Fn ATF_TC_CLEANUP_NAME "name" +.Fn ATF_TC_HEAD "name" "tc" +.Fn ATF_TC_HEAD_NAME "name" +.Fn ATF_TC_NAME "name" +.Fn ATF_TC_WITH_CLEANUP "name" +.Fn ATF_TC_WITHOUT_HEAD "name" +.Fn ATF_TP_ADD_TC "tp_name" "tc_name" +.Fn ATF_TP_ADD_TCS "tp_name" +.Fn atf_tc_get_config_var "tc" "varname" +.Fn atf_tc_get_config_var_wd "tc" "variable_name" "default_value" +.Fn atf_tc_get_config_var_as_bool "tc" "variable_name" +.Fn atf_tc_get_config_var_as_bool_wd "tc" "variable_name" "default_value" +.Fn atf_tc_get_config_var_as_long "tc" "variable_name" +.Fn atf_tc_get_config_var_as_long_wd "tc" "variable_name" "default_value" +.Fn atf_no_error +.Fn atf_tc_expect_death "reason" "..." +.Fn atf_tc_expect_exit "exitcode" "reason" "..." +.Fn atf_tc_expect_fail "reason" "..." +.Fn atf_tc_expect_pass +.Fn atf_tc_expect_signal "signo" "reason" "..." +.Fn atf_tc_expect_timeout "reason" "..." +.Fn atf_tc_fail "reason" +.Fn atf_tc_fail_nonfatal "reason" +.Fn atf_tc_pass +.Fn atf_tc_skip "reason" +.Ft void +.Fo atf_utils_cat_file +.Fa "const char *file" +.Fa "const char *prefix" +.Fc +.Ft bool +.Fo atf_utils_compare_file +.Fa "const char *file" +.Fa "const char *contents" +.Fc +.Ft void +.Fo atf_utils_copy_file +.Fa "const char *source" +.Fa "const char *destination" +.Fc +.Ft void +.Fo atf_utils_create_file +.Fa "const char *file" +.Fa "const char *contents" +.Fa "..." +.Fc +.Ft void +.Fo atf_utils_file_exists +.Fa "const char *file" +.Fc +.Ft pid_t +.Fo atf_utils_fork +.Fa "void" +.Fc +.Ft void +.Fo atf_utils_free_charpp +.Fa "char **argv" +.Fc +.Ft bool +.Fo atf_utils_grep_file +.Fa "const char *regexp" +.Fa "const char *file" +.Fa "..." +.Fc +.Ft bool +.Fo atf_utils_grep_string +.Fa "const char *regexp" +.Fa "const char *str" +.Fa "..." +.Fc +.Ft char * +.Fo atf_utils_readline +.Fa "int fd" +.Fc +.Ft void +.Fo atf_utils_redirect +.Fa "const int fd" +.Fa "const char *file" +.Fc +.Ft void +.Fo atf_utils_wait +.Fa "const pid_t pid" +.Fa "const int expected_exit_status" +.Fa "const char *expected_stdout" +.Fa "const char *expected_stderr" +.Fc +.Sh DESCRIPTION +The ATF +.Pp +C-based test programs always follow this template: +.Bd -literal -offset indent +.Ns ... C-specific includes go here ... + +#include + +ATF_TC(tc1); +ATF_TC_HEAD(tc1, tc) +{ + ... first test case's header ... +} +ATF_TC_BODY(tc1, tc) +{ + ... first test case's body ... +} + +ATF_TC_WITH_CLEANUP(tc2); +ATF_TC_HEAD(tc2, tc) +{ + ... second test case's header ... +} +ATF_TC_BODY(tc2, tc) +{ + ... second test case's body ... +} +ATF_TC_CLEANUP(tc2, tc) +{ + ... second test case's cleanup ... +} + +ATF_TC_WITHOUT_HEAD(tc3); +ATF_TC_BODY(tc3, tc) +{ + ... third test case's body ... +} + +.Ns ... additional test cases ... + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tcs, tc1); + ATF_TP_ADD_TC(tcs, tc2); + ATF_TP_ADD_TC(tcs, tc3); + ... add additional test cases ... + + return atf_no_error(); +} +.Ed +.Ss Definition of test cases +Test cases have an identifier and are composed of three different parts: +the header, the body and an optional cleanup routine, all of which are +described in +.Xr atf-test-case 4 . +To define test cases, one can use the +.Fn ATF_TC , +.Fn ATF_TC_WITH_CLEANUP +or the +.Fn ATF_TC_WITHOUT_HEAD +macros, which take a single parameter specifiying the test case's name. +.Fn ATF_TC , +requires to define a head and a body for the test case, +.Fn ATF_TC_WITH_CLEANUP +requires to define a head, a body and a cleanup for the test case and +.Fn ATF_TC_WITHOUT_HEAD +requires only a body for the test case. +It is important to note that these +.Em do not +set the test case up for execution when the program is run. +In order to do so, a later registration is needed with the +.Fn ATF_TP_ADD_TC +macro detailed in +.Sx Program initialization . +.Pp +Later on, one must define the three parts of the body by means of three +functions. +Their headers are given by the +.Fn ATF_TC_HEAD , +.Fn ATF_TC_BODY +and +.Fn ATF_TC_CLEANUP +macros, all of which take the test case name provided to the +.Fn ATF_TC +.Fn ATF_TC_WITH_CLEANUP , +or +.Fn ATF_TC_WITHOUT_HEAD +macros and the name of the variable that will hold a pointer to the +test case data. +Following each of these, a block of code is expected, surrounded by the +opening and closing brackets. +.Ss Program initialization +The library provides a way to easily define the test program's +.Fn main +function. +You should never define one on your own, but rely on the +library to do it for you. +This is done by using the +.Fn ATF_TP_ADD_TCS +macro, which is passed the name of the object that will hold the test +cases; i.e. the test program instance. +This name can be whatever you want as long as it is a valid variable +identifier. +.Pp +After the macro, you are supposed to provide the body of a function, which +should only use the +.Fn ATF_TP_ADD_TC +macro to register the test cases the test program will execute and return +a success error code. +The first parameter of this macro matches the name you provided in the +former call. +The success status can be returned using the +.Fn atf_no_error +function. +.Ss Header definitions +The test case's header can define the meta-data by using the +.Fn atf_tc_set_md_var +method, which takes three parameters: the first one points to the test +case data, the second one specifies the meta-data variable to be set +and the third one specifies its value. +Both of them are strings. +.Ss Configuration variables +The test case has read-only access to the current configuration variables +by means of the +.Ft bool +.Fn atf_tc_has_config_var , +.Ft const char * +.Fn atf_tc_get_config_var , +.Ft const char * +.Fn atf_tc_get_config_var_wd , +.Ft bool +.Fn atf_tc_get_config_var_as_bool , +.Ft bool +.Fn atf_tc_get_config_var_as_bool_wd , +.Ft long +.Fn atf_tc_get_config_var_as_long , +and the +.Ft long +.Fn atf_tc_get_config_var_as_long_wd +functions, which can be called in any of the three parts of a test case. +.Pp +The +.Sq _wd +variants take a default value for the variable which is returned if the +variable is not defined. +The other functions without the +.Sq _wd +suffix +.Em require +the variable to be defined. +.Ss Access to the source directory +It is possible to get the path to the test case's source directory from any +of its three components by querying the +.Sq srcdir +configuration variable. +.Ss Requiring programs +Aside from the +.Va require.progs +meta-data variable available in the header only, one can also check for +additional programs in the test case's body by using the +.Fn atf_tc_require_prog +function, which takes the base name or full path of a single binary. +Relative paths are forbidden. +If it is not found, the test case will be automatically skipped. +.Ss Test case finalization +The test case finalizes either when the body reaches its end, at which +point the test is assumed to have +.Em passed , +unless any non-fatal errors were raised using +.Fn atf_tc_fail_nonfatal , +or at any explicit call to +.Fn atf_tc_pass , +.Fn atf_tc_fail +or +.Fn atf_tc_skip . +These three functions terminate the execution of the test case immediately. +The cleanup routine will be processed afterwards in a completely automated +way, regardless of the test case's termination reason. +.Pp +.Fn atf_tc_pass +does not take any parameters. +.Fn atf_tc_fail , +.Fn atf_tc_fail_nonfatal +and +.Fn atf_tc_skip +take a format string and a variable list of parameters, which describe, in +a user-friendly manner, why the test case failed or was skipped, +respectively. +It is very important to provide a clear error message in both cases so that +the user can quickly know why the test did not pass. +.Ss Expectations +Everything explained in the previous section changes when the test case +expectations are redefined by the programmer. +.Pp +Each test case has an internal state called +.Sq expect +that describes what the test case expectations are at any point in time. +The value of this property can change during execution by any of: +.Bl -tag -width indent +.It Fn atf_tc_expect_death "reason" "..." +Expects the test case to exit prematurely regardless of the nature of the +exit. +.It Fn atf_tc_expect_exit "exitcode" "reason" "..." +Expects the test case to exit cleanly. +If +.Va exitcode +is not +.Sq -1 , +.Xr atf-run 1 +will validate that the exit code of the test case matches the one provided +in this call. +Otherwise, the exact value will be ignored. +.It Fn atf_tc_expect_fail "reason" "..." +Any failure (be it fatal or non-fatal) raised in this mode is recorded. +However, such failures do not report the test case as failed; instead, the +test case finalizes cleanly and is reported as +.Sq expected failure ; +this report includes the provided +.Fa reason +as part of it. +If no error is raised while running in this mode, then the test case is +reported as +.Sq failed . +.Pp +This mode is useful to reproduce actual known bugs in tests. +Whenever the developer fixes the bug later on, the test case will start +reporting a failure, signaling the developer that the test case must be +adjusted to the new conditions. +In this situation, it is useful, for example, to set +.Fa reason +as the bug number for tracking purposes. +.It Fn atf_tc_expect_pass +This is the normal mode of execution. +In this mode, any failure is reported as such to the user and the test case +is marked as +.Sq failed . +.It Fn atf_tc_expect_signal "signo" "reason" "..." +Expects the test case to terminate due to the reception of a signal. +If +.Va signo +is not +.Sq -1 , +.Xr atf-run 1 +will validate that the signal that terminated the test case matches the one +provided in this call. +Otherwise, the exact value will be ignored. +.It Fn atf_tc_expect_timeout "reason" "..." +Expects the test case to execute for longer than its timeout. +.El +.Ss Helper macros for common checks +The library provides several macros that are very handy in multiple +situations. +These basically check some condition after executing a given statement or +processing a given expression and, if the condition is not met, they +report the test case as failed. +.Pp +The +.Sq REQUIRE +variant of the macros immediately abort the test case as soon as an error +condition is detected by calling the +.Fn atf_tc_fail +function. +Use this variant whenever it makes no sense to continue the execution of a +test case when the checked condition is not met. +The +.Sq CHECK +variant, on the other hand, reports a failure as soon as it is encountered +using the +.Fn atf_tc_fail_nonfatal +function, but the execution of the test case continues as if nothing had +happened. +Use this variant whenever the checked condition is important as a result of +the test case, but there are other conditions that can be subsequently +checked on the same run without aborting. +.Pp +Additionally, the +.Sq MSG +variants take an extra set of parameters to explicitly specify the failure +message. +This failure message is formatted according to the +.Xr printf 3 +formatters. +.Pp +.Fn ATF_CHECK , +.Fn ATF_CHECK_MSG , +.Fn ATF_REQUIRE +and +.Fn ATF_REQUIRE_MSG +take an expression and fail if the expression evaluates to false. +.Pp +.Fn ATF_CHECK_EQ , +.Fn ATF_CHECK_EQ_MSG , +.Fn ATF_REQUIRE_EQ +and +.Fn ATF_REQUIRE_EQ_MSG +take two expressions and fail if the two evaluated values are not equal. +.Pp +.Fn ATF_CHECK_MATCH , +.Fn ATF_CHECK_MATCH_MSG , +.Fn ATF_REQUIRE_MATCH +and +.Fn ATF_REQUIRE_MATCH_MSG +take a regular expression and a string and fail if the regular expression does +not match the given string. +Note that the regular expression is not anchored, so it will match anywhere in +the string. +.Pp +.Fn ATF_CHECK_STREQ , +.Fn ATF_CHECK_STREQ_MSG , +.Fn ATF_REQUIRE_STREQ +and +.Fn ATF_REQUIRE_STREQ_MSG +take two strings and fail if the two are not equal character by character. +.Pp +.Fn ATF_CHECK_ERRNO +and +.Fn ATF_REQUIRE_ERRNO +take, first, the error code that the check is expecting to find in the +.Va errno +variable and, second, a boolean expression that, if evaluates to true, +means that a call failed and +.Va errno +has to be checked against the first value. +.Ss Utility functions +The following functions are provided as part of the +.Nm +API to simplify the creation of a variety of tests. +In particular, these are useful to write tests for command-line interfaces. +.Pp +.Ft void +.Fo atf_utils_cat_file +.Fa "const char *file" +.Fa "const char *prefix" +.Fc +.Bd -offset indent +Prints the contents of +.Fa file +to the standard output, prefixing every line with the string in +.Fa prefix . +.Ed +.Pp +.Ft bool +.Fo atf_utils_compare_file +.Fa "const char *file" +.Fa "const char *contents" +.Fc +.Bd -offset indent +Returns true if the given +.Fa file +matches exactly the expected inlined +.Fa contents . +.Ed +.Pp +.Ft void +.Fo atf_utils_copy_file +.Fa "const char *source" +.Fa "const char *destination" +.Fc +.Bd -offset indent +Copies the file +.Fa source +to +.Fa destination . +The permissions of the file are preserved during the code. +.Ed +.Pp +.Ft void +.Fo atf_utils_create_file +.Fa "const char *file" +.Fa "const char *contents" +.Fa "..." +.Fc +.Bd -offset indent +Creates +.Fa file +with the text given in +.Fa contents , +which is a formatting string that uses the rest of the variable arguments. +.Ed +.Pp +.Ft void +.Fo atf_utils_file_exists +.Fa "const char *file" +.Fc +.Bd -offset indent +Checks if +.Fa file +exists. +.Ed +.Pp +.Ft pid_t +.Fo atf_utils_fork +.Fa "void" +.Fc +.Bd -offset indent +Forks a process and redirects the standard output and standard error of the +child to files for later validation with +.Fn atf_utils_wait . +Fails the test case if the fork fails, so this does not return an error. +.Ed +.Pp +.Ft void +.Fo atf_utils_free_charpp +.Fa "char **argv" +.Fc +.Bd -offset indent +Frees a dynamically-allocated array of dynamically-allocated strings. +.Ed +.Pp +.Ft bool +.Fo atf_utils_grep_file +.Fa "const char *regexp" +.Fa "const char *file" +.Fa "..." +.Fc +.Bd -offset indent +Searches for the +.Fa regexp , +which is a formatting string representing the regular expression, +in the +.Fa file . +The variable arguments are used to construct the regular expression. +.Ed +.Pp +.Ft bool +.Fo atf_utils_grep_string +.Fa "const char *regexp" +.Fa "const char *str" +.Fa "..." +.Fc +.Bd -offset indent +Searches for the +.Fa regexp , +which is a formatting string representing the regular expression, +in the literal string +.Fa str . +The variable arguments are used to construct the regular expression. +.Ed +.Pp +.Ft char * +.Fo atf_utils_readline +.Fa "int fd" +.Fc +.Bd -offset indent +Reads a line from the file descriptor +.Fa fd . +The line, if any, is returned as a dynamically-allocated buffer that must be +released with +.Xr free 3 . +If there was nothing to read, returns +.Sq NULL . +.Ed +.Pp +.Ft void +.Fo atf_utils_redirect +.Fa "const int fd" +.Fa "const char *file" +.Fc +.Bd -offset indent +Redirects the given file descriptor +.Fa fd +to +.Fa file . +This function exits the process in case of an error and does not properly mark +the test case as failed. +As a result, it should only be used in subprocesses of the test case; specially +those spawned by +.Fn atf_utils_fork . +.Ed +.Pp +.Ft void +.Fo atf_utils_wait +.Fa "const pid_t pid" +.Fa "const int expected_exit_status" +.Fa "const char *expected_stdout" +.Fa "const char *expected_stderr" +.Fc +.Bd -offset indent +Waits and validates the result of a subprocess spawned with +.Fn atf_utils_wait . +The validation involves checking that the subprocess exited cleanly and returned +the code specified in +.Fa expected_exit_status +and that its standard output and standard error match the strings given in +.Fa expected_stdout +and +.Fa expected_stderr . +.Pp +If any of the +.Fa expected_stdout +or +.Fa expected_stderr +strings are prefixed with +.Sq save: , +then they specify the name of the file into which to store the stdout or stderr +of the subprocess, and no comparison is performed. +.Ed +.Sh EXAMPLES +The following shows a complete test program with a single test case that +validates the addition operator: +.Bd -literal -offset indent +#include + +ATF_TC(addition); +ATF_TC_HEAD(addition, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Sample tests for the addition operator"); +} +ATF_TC_BODY(addition, tc) +{ + ATF_CHECK_EQ(0 + 0, 0); + ATF_CHECK_EQ(0 + 1, 1); + ATF_CHECK_EQ(1 + 0, 1); + + ATF_CHECK_EQ(1 + 1, 2); + + ATF_CHECK_EQ(100 + 200, 300); +} + +ATF_TC(string_formatting); +ATF_TC_HEAD(string_formatting, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Sample tests for the snprintf"); +} +ATF_TC_BODY(string_formatting, tc) +{ + char buf[1024]; + snprintf(buf, sizeof(buf), "a %s", "string"); + ATF_CHECK_STREQ_MSG("a string", buf, "%s is not working"); +} + +ATF_TC(open_failure); +ATF_TC_HEAD(open_failure, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Sample tests for the open function"); +} +ATF_TC_BODY(open_failure, tc) +{ + ATF_CHECK_ERRNO(ENOENT, open("non-existent", O_RDONLY) == -1); +} + +ATF_TC(known_bug); +ATF_TC_HEAD(known_bug, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Reproduces a known bug"); +} +ATF_TC_BODY(known_bug, tc) +{ + atf_tc_expect_fail("See bug number foo/bar"); + ATF_CHECK_EQ(3, 1 + 1); + atf_tc_expect_pass(); + ATF_CHECK_EQ(3, 1 + 2); +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, addition); + ATF_TP_ADD_TC(tp, string_formatting); + ATF_TP_ADD_TC(tp, open_failure); + ATF_TP_ADD_TC(tp, known_bug); + + return atf_no_error(); +} +.Ed +.Sh SEE ALSO +.Xr atf-test-program 1 , +.Xr atf-test-case 4 , +.Xr atf 7 diff --git a/external/bsd/atf/dist/atf-c/atf-c.pc.in b/external/bsd/atf/dist/atf-c/atf-c.pc.in new file mode 100644 index 000000000..6fd52740b --- /dev/null +++ b/external/bsd/atf/dist/atf-c/atf-c.pc.in @@ -0,0 +1,11 @@ +# ATF pkg-config file + +cc=__CC__ +includedir=__INCLUDEDIR__ +libdir=__LIBDIR__ + +Name: atf-c +Description: Automated Testing Framework (C binding) +Version: __ATF_VERSION__ +Cflags: -I${includedir} +Libs: -L${libdir} -latf-c diff --git a/external/bsd/atf/dist/atf-c/atf_c_test.c b/external/bsd/atf/dist/atf-c/atf_c_test.c new file mode 100644 index 000000000..f44d87fb0 --- /dev/null +++ b/external/bsd/atf/dist/atf-c/atf_c_test.c @@ -0,0 +1,50 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include "detail/test_helpers.h" + +/* --------------------------------------------------------------------- + * Tests cases for the header file. + * --------------------------------------------------------------------- */ + +HEADER_TC(include, "atf-c.h"); + +/* --------------------------------------------------------------------- + * Main. + * --------------------------------------------------------------------- */ + +ATF_TP_ADD_TCS(tp) +{ + /* Add the test cases for the header file. */ + ATF_TP_ADD_TC(tp, include); + + return atf_no_error(); +} diff --git a/external/bsd/atf/dist/atf-c/build.c b/external/bsd/atf/dist/atf-c/build.c new file mode 100644 index 000000000..248330373 --- /dev/null +++ b/external/bsd/atf/dist/atf-c/build.c @@ -0,0 +1,281 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2009 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include "atf-c/build.h" +#include "atf-c/config.h" +#include "atf-c/error.h" + +#include "detail/sanity.h" +#include "detail/text.h" + +/* --------------------------------------------------------------------- + * Auxiliary functions. + * --------------------------------------------------------------------- */ + +static +atf_error_t +append_config_var(const char *var, atf_list_t *argv) +{ + atf_error_t err; + atf_list_t words; + + err = atf_text_split(atf_config_get(var), " ", &words); + if (atf_is_error(err)) + goto out; + + atf_list_append_list(argv, &words); + +out: + return err; +} + +static +atf_error_t +append_arg1(const char *arg, atf_list_t *argv) +{ + return atf_list_append(argv, strdup(arg), true); +} + +static +atf_error_t +append_arg2(const char *flag, const char *arg, atf_list_t *argv) +{ + atf_error_t err; + + err = append_arg1(flag, argv); + if (!atf_is_error(err)) + err = append_arg1(arg, argv); + + return err; +} + +static +atf_error_t +append_optargs(const char *const optargs[], atf_list_t *argv) +{ + atf_error_t err; + + err = atf_no_error(); + while (*optargs != NULL && !atf_is_error(err)) { + err = append_arg1(strdup(*optargs), argv); + optargs++; + } + + return err; +} + +static +atf_error_t +append_src_out(const char *src, const char *obj, atf_list_t *argv) +{ + atf_error_t err; + + err = append_arg2("-o", obj, argv); + if (atf_is_error(err)) + goto out; + + err = append_arg1("-c", argv); + if (atf_is_error(err)) + goto out; + + err = append_arg1(src, argv); + +out: + return err; +} + +static +atf_error_t +list_to_array(const atf_list_t *l, char ***ap) +{ + atf_error_t err; + char **a; + + a = (char **)malloc((atf_list_size(l) + 1) * sizeof(char *)); + if (a == NULL) + err = atf_no_memory_error(); + else { + char **aiter; + atf_list_citer_t liter; + + aiter = a; + atf_list_for_each_c(liter, l) { + *aiter = strdup((const char *)atf_list_citer_data(liter)); + aiter++; + } + *aiter = NULL; + + err = atf_no_error(); + } + *ap = a; /* Shut up warnings in the caller about uninitialized *ap. */ + + return err; +} + +/* --------------------------------------------------------------------- + * Free functions. + * --------------------------------------------------------------------- */ + +atf_error_t +atf_build_c_o(const char *sfile, + const char *ofile, + const char *const optargs[], + char ***argv) +{ + atf_error_t err; + atf_list_t argv_list; + + err = atf_list_init(&argv_list); + if (atf_is_error(err)) + goto out; + + err = append_config_var("atf_build_cc", &argv_list); + if (atf_is_error(err)) + goto out_list; + + err = append_config_var("atf_build_cppflags", &argv_list); + if (atf_is_error(err)) + goto out_list; + + err = append_config_var("atf_build_cflags", &argv_list); + if (atf_is_error(err)) + goto out_list; + + if (optargs != NULL) { + err = append_optargs(optargs, &argv_list); + if (atf_is_error(err)) + goto out_list; + } + + err = append_src_out(sfile, ofile, &argv_list); + if (atf_is_error(err)) + goto out_list; + + err = list_to_array(&argv_list, argv); + if (atf_is_error(err)) + goto out_list; + +out_list: + atf_list_fini(&argv_list); +out: + return err; +} + +atf_error_t +atf_build_cpp(const char *sfile, + const char *ofile, + const char *const optargs[], + char ***argv) +{ + atf_error_t err; + atf_list_t argv_list; + + err = atf_list_init(&argv_list); + if (atf_is_error(err)) + goto out; + + err = append_config_var("atf_build_cpp", &argv_list); + if (atf_is_error(err)) + goto out_list; + + err = append_config_var("atf_build_cppflags", &argv_list); + if (atf_is_error(err)) + goto out_list; + + if (optargs != NULL) { + err = append_optargs(optargs, &argv_list); + if (atf_is_error(err)) + goto out_list; + } + + err = append_arg2("-o", ofile, &argv_list); + if (atf_is_error(err)) + goto out_list; + + err = append_arg1(sfile, &argv_list); + if (atf_is_error(err)) + goto out_list; + + err = list_to_array(&argv_list, argv); + if (atf_is_error(err)) + goto out_list; + +out_list: + atf_list_fini(&argv_list); +out: + return err; +} + +atf_error_t +atf_build_cxx_o(const char *sfile, + const char *ofile, + const char *const optargs[], + char ***argv) +{ + atf_error_t err; + atf_list_t argv_list; + + err = atf_list_init(&argv_list); + if (atf_is_error(err)) + goto out; + + err = append_config_var("atf_build_cxx", &argv_list); + if (atf_is_error(err)) + goto out_list; + + err = append_config_var("atf_build_cppflags", &argv_list); + if (atf_is_error(err)) + goto out_list; + + err = append_config_var("atf_build_cxxflags", &argv_list); + if (atf_is_error(err)) + goto out_list; + + if (optargs != NULL) { + err = append_optargs(optargs, &argv_list); + if (atf_is_error(err)) + goto out_list; + } + + err = append_src_out(sfile, ofile, &argv_list); + if (atf_is_error(err)) + goto out_list; + + err = list_to_array(&argv_list, argv); + if (atf_is_error(err)) + goto out_list; + +out_list: + atf_list_fini(&argv_list); +out: + return err; +} diff --git a/external/bsd/atf/dist/atf-c/build.h b/external/bsd/atf/dist/atf-c/build.h new file mode 100644 index 000000000..2e981cfda --- /dev/null +++ b/external/bsd/atf/dist/atf-c/build.h @@ -0,0 +1,42 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2009 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if !defined(ATF_C_BUILD_H) +#define ATF_C_BUILD_H + +#include + +atf_error_t atf_build_c_o(const char *, const char *, const char *const [], + char ***); +atf_error_t atf_build_cpp(const char *, const char *, const char *const [], + char ***); +atf_error_t atf_build_cxx_o(const char *, const char *, const char *const [], + char ***); + +#endif /* ATF_C_BUILD_H */ diff --git a/external/bsd/atf/dist/atf-c/build_test.c b/external/bsd/atf/dist/atf-c/build_test.c new file mode 100644 index 000000000..b08c9a549 --- /dev/null +++ b/external/bsd/atf/dist/atf-c/build_test.c @@ -0,0 +1,268 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2009 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +#include + +#include "atf-c/build.h" +#include "atf-c/config.h" +#include "atf-c/utils.h" + +#include "detail/env.h" +#include "detail/test_helpers.h" +#include "h_build.h" + +/* --------------------------------------------------------------------- + * Auxiliary functions. + * --------------------------------------------------------------------- */ + +void __atf_config_reinit(void); + +static +bool +equal_arrays(const char *const *exp_array, char **actual_array) +{ + bool equal; + + if (*exp_array == NULL && *actual_array == NULL) + equal = true; + else if (*exp_array == NULL || *actual_array == NULL) + equal = false; + else { + equal = true; + while (*actual_array != NULL) { + if (*exp_array == NULL || strcmp(*exp_array, *actual_array) != 0) { + equal = false; + break; + } + exp_array++; + actual_array++; + } + } + + return equal; +} + +static +void +check_equal_array(const char *const *exp_array, char **actual_array) +{ + { + const char *const *exp_ptr; + printf("Expected arguments:"); + for (exp_ptr = exp_array; *exp_ptr != NULL; exp_ptr++) + printf(" '%s'", *exp_ptr); + printf("\n"); + } + + { + char **actual_ptr; + printf("Returned arguments:"); + for (actual_ptr = actual_array; *actual_ptr != NULL; actual_ptr++) + printf(" '%s'", *actual_ptr); + printf("\n"); + } + + if (!equal_arrays(exp_array, actual_array)) + atf_tc_fail_nonfatal("The constructed argv differs from the " + "expected values"); +} + +static +void +verbose_set_env(const char *var, const char *val) +{ + printf("Setting %s to '%s'\n", var, val); + RE(atf_env_set(var, val)); +} + +/* --------------------------------------------------------------------- + * Internal test cases. + * --------------------------------------------------------------------- */ + +ATF_TC(equal_arrays); +ATF_TC_HEAD(equal_arrays, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the test case internal " + "equal_arrays function"); +} +ATF_TC_BODY(equal_arrays, tc) +{ + { + const char *const exp[] = { NULL }; + char *actual[] = { NULL }; + + ATF_CHECK(equal_arrays(exp, actual)); + } + + { + const char *const exp[] = { NULL }; + char *actual[2] = { strdup("foo"), NULL }; + + ATF_CHECK(!equal_arrays(exp, actual)); + free(actual[0]); + } + + { + const char *const exp[] = { "foo", NULL }; + char *actual[] = { NULL }; + + ATF_CHECK(!equal_arrays(exp, actual)); + } + + { + const char *const exp[] = { "foo", NULL }; + char *actual[2] = { strdup("foo"), NULL }; + + ATF_CHECK(equal_arrays(exp, actual)); + free(actual[0]); + } +} + +/* --------------------------------------------------------------------- + * Test cases for the free functions. + * --------------------------------------------------------------------- */ + +ATF_TC(c_o); +ATF_TC_HEAD(c_o, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the atf_build_c_o function"); +} +ATF_TC_BODY(c_o, tc) +{ + struct c_o_test *test; + + for (test = c_o_tests; test->expargv[0] != NULL; test++) { + printf("> Test: %s\n", test->msg); + + verbose_set_env("ATF_BUILD_CC", test->cc); + verbose_set_env("ATF_BUILD_CFLAGS", test->cflags); + verbose_set_env("ATF_BUILD_CPPFLAGS", test->cppflags); + __atf_config_reinit(); + + { + char **argv; + if (test->hasoptargs) + RE(atf_build_c_o(test->sfile, test->ofile, test->optargs, + &argv)); + else + RE(atf_build_c_o(test->sfile, test->ofile, NULL, &argv)); + check_equal_array(test->expargv, argv); + atf_utils_free_charpp(argv); + } + } +} + +ATF_TC(cpp); +ATF_TC_HEAD(cpp, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the atf_build_cpp function"); +} +ATF_TC_BODY(cpp, tc) +{ + struct cpp_test *test; + + for (test = cpp_tests; test->expargv[0] != NULL; test++) { + printf("> Test: %s\n", test->msg); + + verbose_set_env("ATF_BUILD_CPP", test->cpp); + verbose_set_env("ATF_BUILD_CPPFLAGS", test->cppflags); + __atf_config_reinit(); + + { + char **argv; + if (test->hasoptargs) + RE(atf_build_cpp(test->sfile, test->ofile, test->optargs, + &argv)); + else + RE(atf_build_cpp(test->sfile, test->ofile, NULL, &argv)); + check_equal_array(test->expargv, argv); + atf_utils_free_charpp(argv); + } + } +} + +ATF_TC(cxx_o); +ATF_TC_HEAD(cxx_o, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the atf_build_cxx_o function"); +} +ATF_TC_BODY(cxx_o, tc) +{ + struct cxx_o_test *test; + + for (test = cxx_o_tests; test->expargv[0] != NULL; test++) { + printf("> Test: %s\n", test->msg); + + verbose_set_env("ATF_BUILD_CXX", test->cxx); + verbose_set_env("ATF_BUILD_CXXFLAGS", test->cxxflags); + verbose_set_env("ATF_BUILD_CPPFLAGS", test->cppflags); + __atf_config_reinit(); + + { + char **argv; + if (test->hasoptargs) + RE(atf_build_cxx_o(test->sfile, test->ofile, test->optargs, + &argv)); + else + RE(atf_build_cxx_o(test->sfile, test->ofile, NULL, &argv)); + check_equal_array(test->expargv, argv); + atf_utils_free_charpp(argv); + } + } +} + +/* --------------------------------------------------------------------- + * Tests cases for the header file. + * --------------------------------------------------------------------- */ + +HEADER_TC(include, "atf-c/build.h"); + +/* --------------------------------------------------------------------- + * Main. + * --------------------------------------------------------------------- */ + +ATF_TP_ADD_TCS(tp) +{ + /* Add the internal test cases. */ + ATF_TP_ADD_TC(tp, equal_arrays); + + /* Add the test cases for the free functions. */ + ATF_TP_ADD_TC(tp, c_o); + ATF_TP_ADD_TC(tp, cpp); + ATF_TP_ADD_TC(tp, cxx_o); + + /* Add the test cases for the header file. */ + ATF_TP_ADD_TC(tp, include); + + return atf_no_error(); +} diff --git a/external/bsd/atf/dist/atf-c/check.c b/external/bsd/atf/dist/atf-c/check.c new file mode 100644 index 000000000..d7a908d3c --- /dev/null +++ b/external/bsd/atf/dist/atf-c/check.c @@ -0,0 +1,488 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include "atf-c/build.h" +#include "atf-c/check.h" +#include "atf-c/config.h" +#include "atf-c/defs.h" +#include "atf-c/error.h" +#include "atf-c/utils.h" + +#include "detail/dynstr.h" +#include "detail/fs.h" +#include "detail/list.h" +#include "detail/process.h" +#include "detail/sanity.h" + +/* --------------------------------------------------------------------- + * Auxiliary functions. + * --------------------------------------------------------------------- */ + +static +atf_error_t +create_tmpdir(atf_fs_path_t *dir) +{ + atf_error_t err; + + err = atf_fs_path_init_fmt(dir, "%s/check.XXXXXX", + atf_config_get("atf_workdir")); + if (atf_is_error(err)) + goto out; + + err = atf_fs_mkdtemp(dir); + if (atf_is_error(err)) { + atf_fs_path_fini(dir); + goto out; + } + + INV(!atf_is_error(err)); +out: + return err; +} + +static +void +cleanup_tmpdir(const atf_fs_path_t *dir, const atf_fs_path_t *outfile, + const atf_fs_path_t *errfile) +{ + { + atf_error_t err = atf_fs_unlink(outfile); + if (atf_is_error(err)) { + INV(atf_error_is(err, "libc") && + atf_libc_error_code(err) == ENOENT); + atf_error_free(err); + } else + INV(!atf_is_error(err)); + } + + { + atf_error_t err = atf_fs_unlink(errfile); + if (atf_is_error(err)) { + INV(atf_error_is(err, "libc") && + atf_libc_error_code(err) == ENOENT); + atf_error_free(err); + } else + INV(!atf_is_error(err)); + } + + { + atf_error_t err = atf_fs_rmdir(dir); + INV(!atf_is_error(err)); + } +} + +static +int +const_execvp(const char *file, const char *const *argv) +{ +#define UNCONST(a) ((void *)(unsigned long)(const void *)(a)) + return execvp(file, UNCONST(argv)); +#undef UNCONST +} + +static +atf_error_t +init_sb(const atf_fs_path_t *path, atf_process_stream_t *sb) +{ + atf_error_t err; + + if (path == NULL) + err = atf_process_stream_init_inherit(sb); + else + err = atf_process_stream_init_redirect_path(sb, path); + + return err; +} + +static +atf_error_t +init_sbs(const atf_fs_path_t *outfile, atf_process_stream_t *outsb, + const atf_fs_path_t *errfile, atf_process_stream_t *errsb) +{ + atf_error_t err; + + err = init_sb(outfile, outsb); + if (atf_is_error(err)) + goto out; + + err = init_sb(errfile, errsb); + if (atf_is_error(err)) { + atf_process_stream_fini(outsb); + goto out; + } + +out: + return err; +} + +struct exec_data { + const char *const *m_argv; +}; + +static void exec_child(void *) ATF_DEFS_ATTRIBUTE_NORETURN; + +static +void +exec_child(void *v) +{ + struct exec_data *ea = v; + + const_execvp(ea->m_argv[0], ea->m_argv); + fprintf(stderr, "execvp(%s) failed: %s\n", ea->m_argv[0], strerror(errno)); + exit(127); +} + +static +atf_error_t +fork_and_wait(const char *const *argv, const atf_fs_path_t *outfile, + const atf_fs_path_t *errfile, atf_process_status_t *status) +{ + atf_error_t err; + atf_process_child_t child; + atf_process_stream_t outsb, errsb; + struct exec_data ea = { argv }; + + err = init_sbs(outfile, &outsb, errfile, &errsb); + if (atf_is_error(err)) + goto out; + + err = atf_process_fork(&child, exec_child, &outsb, &errsb, &ea); + if (atf_is_error(err)) + goto out_sbs; + + err = atf_process_child_wait(&child, status); + +out_sbs: + atf_process_stream_fini(&errsb); + atf_process_stream_fini(&outsb); +out: + return err; +} + +static +void +update_success_from_status(const char *progname, + const atf_process_status_t *status, bool *success) +{ + bool s = atf_process_status_exited(status) && + atf_process_status_exitstatus(status) == EXIT_SUCCESS; + + if (atf_process_status_exited(status)) { + if (atf_process_status_exitstatus(status) == EXIT_SUCCESS) + INV(s); + else { + INV(!s); + fprintf(stderr, "%s failed with exit code %d\n", progname, + atf_process_status_exitstatus(status)); + } + } else if (atf_process_status_signaled(status)) { + INV(!s); + fprintf(stderr, "%s failed due to signal %d%s\n", progname, + atf_process_status_termsig(status), + atf_process_status_coredump(status) ? " (core dumped)" : ""); + } else { + INV(!s); + fprintf(stderr, "%s failed due to unknown reason\n", progname); + } + + *success = s; +} + +static +atf_error_t +array_to_list(const char *const *a, atf_list_t *l) +{ + atf_error_t err; + + err = atf_list_init(l); + if (atf_is_error(err)) + goto out; + + while (*a != NULL) { + char *item = strdup(*a); + if (item == NULL) { + err = atf_no_memory_error(); + goto out; + } + + err = atf_list_append(l, item, true); + if (atf_is_error(err)) + goto out; + + a++; + } + +out: + return err; +} + +static void +print_array(const char *const *array, const char *pfx) +{ + const char *const *ptr; + + printf("%s", pfx); + for (ptr = array; *ptr != NULL; ptr++) + printf(" %s", *ptr); + printf("\n"); +} + +static +atf_error_t +check_build_run(const char *const *argv, bool *success) +{ + atf_error_t err; + atf_process_status_t status; + + print_array(argv, ">"); + + err = fork_and_wait(argv, NULL, NULL, &status); + if (atf_is_error(err)) + goto out; + + update_success_from_status(argv[0], &status, success); + atf_process_status_fini(&status); + + INV(!atf_is_error(err)); +out: + return err; +} + +/* --------------------------------------------------------------------- + * The "atf_check_result" type. + * --------------------------------------------------------------------- */ + +struct atf_check_result_impl { + atf_list_t m_argv; + atf_fs_path_t m_dir; + atf_fs_path_t m_stdout; + atf_fs_path_t m_stderr; + atf_process_status_t m_status; +}; + +static +atf_error_t +atf_check_result_init(atf_check_result_t *r, const char *const *argv, + const atf_fs_path_t *dir) +{ + atf_error_t err; + + r->pimpl = malloc(sizeof(struct atf_check_result_impl)); + if (r->pimpl == NULL) + return atf_no_memory_error(); + + err = array_to_list(argv, &r->pimpl->m_argv); + if (atf_is_error(err)) + goto out; + + err = atf_fs_path_copy(&r->pimpl->m_dir, dir); + if (atf_is_error(err)) + goto err_argv; + + err = atf_fs_path_init_fmt(&r->pimpl->m_stdout, "%s/stdout", + atf_fs_path_cstring(dir)); + if (atf_is_error(err)) + goto err_dir; + + err = atf_fs_path_init_fmt(&r->pimpl->m_stderr, "%s/stderr", + atf_fs_path_cstring(dir)); + if (atf_is_error(err)) + goto err_stdout; + + INV(!atf_is_error(err)); + goto out; + +err_stdout: + atf_fs_path_fini(&r->pimpl->m_stdout); +err_dir: + atf_fs_path_fini(&r->pimpl->m_dir); +err_argv: + atf_list_fini(&r->pimpl->m_argv); +out: + return err; +} + +void +atf_check_result_fini(atf_check_result_t *r) +{ + atf_process_status_fini(&r->pimpl->m_status); + + cleanup_tmpdir(&r->pimpl->m_dir, &r->pimpl->m_stdout, + &r->pimpl->m_stderr); + atf_fs_path_fini(&r->pimpl->m_stdout); + atf_fs_path_fini(&r->pimpl->m_stderr); + atf_fs_path_fini(&r->pimpl->m_dir); + + atf_list_fini(&r->pimpl->m_argv); + + free(r->pimpl); +} + +const char * +atf_check_result_stdout(const atf_check_result_t *r) +{ + return atf_fs_path_cstring(&r->pimpl->m_stdout); +} + +const char * +atf_check_result_stderr(const atf_check_result_t *r) +{ + return atf_fs_path_cstring(&r->pimpl->m_stderr); +} + +bool +atf_check_result_exited(const atf_check_result_t *r) +{ + return atf_process_status_exited(&r->pimpl->m_status); +} + +int +atf_check_result_exitcode(const atf_check_result_t *r) +{ + return atf_process_status_exitstatus(&r->pimpl->m_status); +} + +bool +atf_check_result_signaled(const atf_check_result_t *r) +{ + return atf_process_status_signaled(&r->pimpl->m_status); +} + +int +atf_check_result_termsig(const atf_check_result_t *r) +{ + return atf_process_status_termsig(&r->pimpl->m_status); +} + +/* --------------------------------------------------------------------- + * Free functions. + * --------------------------------------------------------------------- */ + +/* XXX: This function shouldn't be in this module. It messes with stdout + * and stderr, and it provides a very high-end interface. This belongs, + * probably, somewhere related to test cases (such as in the tc module). */ +atf_error_t +atf_check_build_c_o(const char *sfile, + const char *ofile, + const char *const optargs[], + bool *success) +{ + atf_error_t err; + char **argv; + + err = atf_build_c_o(sfile, ofile, optargs, &argv); + if (atf_is_error(err)) + goto out; + + err = check_build_run((const char *const *)argv, success); + + atf_utils_free_charpp(argv); +out: + return err; +} + +atf_error_t +atf_check_build_cpp(const char *sfile, + const char *ofile, + const char *const optargs[], + bool *success) +{ + atf_error_t err; + char **argv; + + err = atf_build_cpp(sfile, ofile, optargs, &argv); + if (atf_is_error(err)) + goto out; + + err = check_build_run((const char *const *)argv, success); + + atf_utils_free_charpp(argv); +out: + return err; +} + +atf_error_t +atf_check_build_cxx_o(const char *sfile, + const char *ofile, + const char *const optargs[], + bool *success) +{ + atf_error_t err; + char **argv; + + err = atf_build_cxx_o(sfile, ofile, optargs, &argv); + if (atf_is_error(err)) + goto out; + + err = check_build_run((const char *const *)argv, success); + + atf_utils_free_charpp(argv); +out: + return err; +} + +atf_error_t +atf_check_exec_array(const char *const *argv, atf_check_result_t *r) +{ + atf_error_t err; + atf_fs_path_t dir; + + err = create_tmpdir(&dir); + if (atf_is_error(err)) + goto out; + + err = atf_check_result_init(r, argv, &dir); + if (atf_is_error(err)) { + atf_error_t err2 = atf_fs_rmdir(&dir); + INV(!atf_is_error(err2)); + goto out; + } + + err = fork_and_wait(argv, &r->pimpl->m_stdout, &r->pimpl->m_stderr, + &r->pimpl->m_status); + if (atf_is_error(err)) { + atf_check_result_fini(r); + goto out; + } + + INV(!atf_is_error(err)); + + atf_fs_path_fini(&dir); +out: + return err; +} diff --git a/external/bsd/atf/dist/atf-c/check.h b/external/bsd/atf/dist/atf-c/check.h new file mode 100644 index 000000000..f36aa3eae --- /dev/null +++ b/external/bsd/atf/dist/atf-c/check.h @@ -0,0 +1,73 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if !defined(ATF_C_CHECK_H) +#define ATF_C_CHECK_H + +#include + +#include + +/* --------------------------------------------------------------------- + * The "atf_check_result" type. + * --------------------------------------------------------------------- */ + +struct atf_check_result_impl; +struct atf_check_result { + struct atf_check_result_impl *pimpl; +}; +typedef struct atf_check_result atf_check_result_t; + +/* Construtors and destructors */ +void atf_check_result_fini(atf_check_result_t *); + +/* Getters */ +const char *atf_check_result_stdout(const atf_check_result_t *); +const char *atf_check_result_stderr(const atf_check_result_t *); +bool atf_check_result_exited(const atf_check_result_t *); +int atf_check_result_exitcode(const atf_check_result_t *); +bool atf_check_result_signaled(const atf_check_result_t *); +int atf_check_result_termsig(const atf_check_result_t *); + +/* --------------------------------------------------------------------- + * Free functions. + * --------------------------------------------------------------------- */ + +atf_error_t atf_check_build_c_o(const char *, const char *, + const char *const [], + bool *); +atf_error_t atf_check_build_cpp(const char *, const char *, + const char *const [], + bool *); +atf_error_t atf_check_build_cxx_o(const char *, const char *, + const char *const [], + bool *); +atf_error_t atf_check_exec_array(const char *const *, atf_check_result_t *); + +#endif /* ATF_C_CHECK_H */ diff --git a/external/bsd/atf/dist/atf-c/check_test.c b/external/bsd/atf/dist/atf-c/check_test.c new file mode 100644 index 000000000..a26e032e1 --- /dev/null +++ b/external/bsd/atf/dist/atf-c/check_test.c @@ -0,0 +1,539 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include "atf-c/check.h" +#include "atf-c/config.h" + +#include "detail/fs.h" +#include "detail/map.h" +#include "detail/process.h" +#include "detail/test_helpers.h" + +/* --------------------------------------------------------------------- + * Auxiliary functions. + * --------------------------------------------------------------------- */ + +static +void +do_exec(const atf_tc_t *tc, const char *helper_name, atf_check_result_t *r) +{ + atf_fs_path_t process_helpers; + const char *argv[3]; + + get_process_helpers_path(tc, false, &process_helpers); + + argv[0] = atf_fs_path_cstring(&process_helpers); + argv[1] = helper_name; + argv[2] = NULL; + printf("Executing %s %s\n", argv[0], argv[1]); + RE(atf_check_exec_array(argv, r)); + + atf_fs_path_fini(&process_helpers); +} + +static +void +do_exec_with_arg(const atf_tc_t *tc, const char *helper_name, const char *arg, + atf_check_result_t *r) +{ + atf_fs_path_t process_helpers; + const char *argv[4]; + + get_process_helpers_path(tc, false, &process_helpers); + + argv[0] = atf_fs_path_cstring(&process_helpers); + argv[1] = helper_name; + argv[2] = arg; + argv[3] = NULL; + printf("Executing %s %s %s\n", argv[0], argv[1], argv[2]); + RE(atf_check_exec_array(argv, r)); + + atf_fs_path_fini(&process_helpers); +} + +static +void +check_line(int fd, const char *exp) +{ + char *line = atf_utils_readline(fd); + ATF_CHECK(line != NULL); + ATF_CHECK_STREQ_MSG(exp, line, "read: '%s', expected: '%s'", line, exp); + free(line); +} + +/* --------------------------------------------------------------------- + * Helper test cases for the free functions. + * --------------------------------------------------------------------- */ + +ATF_TC(h_build_c_o_ok); +ATF_TC_HEAD(h_build_c_o_ok, tc) +{ + atf_tc_set_md_var(tc, "descr", "Helper test case for build_c_o"); +} +ATF_TC_BODY(h_build_c_o_ok, tc) +{ + FILE *sfile; + bool success; + + ATF_REQUIRE((sfile = fopen("test.c", "w")) != NULL); + fprintf(sfile, "#include \n"); + fclose(sfile); + + RE(atf_check_build_c_o("test.c", "test.o", NULL, &success)); + ATF_REQUIRE(success); +} + +ATF_TC(h_build_c_o_fail); +ATF_TC_HEAD(h_build_c_o_fail, tc) +{ + atf_tc_set_md_var(tc, "descr", "Helper test case for build_c_o"); +} +ATF_TC_BODY(h_build_c_o_fail, tc) +{ + FILE *sfile; + bool success; + + ATF_REQUIRE((sfile = fopen("test.c", "w")) != NULL); + fprintf(sfile, "void foo(void) { int a = UNDEFINED_SYMBOL; }\n"); + fclose(sfile); + + RE(atf_check_build_c_o("test.c", "test.o", NULL, &success)); + ATF_REQUIRE(!success); +} + +ATF_TC(h_build_cpp_ok); +ATF_TC_HEAD(h_build_cpp_ok, tc) +{ + atf_tc_set_md_var(tc, "descr", "Helper test case for build_cpp"); +} +ATF_TC_BODY(h_build_cpp_ok, tc) +{ + FILE *sfile; + bool success; + atf_fs_path_t test_p; + + RE(atf_fs_path_init_fmt(&test_p, "test.p")); + + ATF_REQUIRE((sfile = fopen("test.c", "w")) != NULL); + fprintf(sfile, "#define A foo\n"); + fprintf(sfile, "#define B bar\n"); + fprintf(sfile, "A B\n"); + fclose(sfile); + + RE(atf_check_build_cpp("test.c", atf_fs_path_cstring(&test_p), NULL, + &success)); + ATF_REQUIRE(success); + + atf_fs_path_fini(&test_p); +} + +ATF_TC(h_build_cpp_fail); +ATF_TC_HEAD(h_build_cpp_fail, tc) +{ + atf_tc_set_md_var(tc, "descr", "Helper test case for build_cpp"); +} +ATF_TC_BODY(h_build_cpp_fail, tc) +{ + FILE *sfile; + bool success; + + ATF_REQUIRE((sfile = fopen("test.c", "w")) != NULL); + fprintf(sfile, "#include \"./non-existent.h\"\n"); + fclose(sfile); + + RE(atf_check_build_cpp("test.c", "test.p", NULL, &success)); + ATF_REQUIRE(!success); +} + +ATF_TC(h_build_cxx_o_ok); +ATF_TC_HEAD(h_build_cxx_o_ok, tc) +{ + atf_tc_set_md_var(tc, "descr", "Helper test case for build_cxx_o"); +} +ATF_TC_BODY(h_build_cxx_o_ok, tc) +{ + FILE *sfile; + bool success; + + ATF_REQUIRE((sfile = fopen("test.cpp", "w")) != NULL); + fprintf(sfile, "#include \n"); + fclose(sfile); + + RE(atf_check_build_cxx_o("test.cpp", "test.o", NULL, &success)); + ATF_REQUIRE(success); +} + +ATF_TC(h_build_cxx_o_fail); +ATF_TC_HEAD(h_build_cxx_o_fail, tc) +{ + atf_tc_set_md_var(tc, "descr", "Helper test case for build_cxx_o"); +} +ATF_TC_BODY(h_build_cxx_o_fail, tc) +{ + FILE *sfile; + bool success; + + ATF_REQUIRE((sfile = fopen("test.cpp", "w")) != NULL); + fprintf(sfile, "void foo(void) { int a = UNDEFINED_SYMBOL; }\n"); + fclose(sfile); + + RE(atf_check_build_cxx_o("test.cpp", "test.o", NULL, &success)); + ATF_REQUIRE(!success); +} + +/* --------------------------------------------------------------------- + * Test cases for the free functions. + * --------------------------------------------------------------------- */ + +static +void +init_and_run_h_tc(atf_tc_t *tc, const atf_tc_pack_t *tcpack, + const char *outname, const char *errname) +{ + const char *const config[] = { NULL }; + + RE(atf_tc_init_pack(tc, tcpack, config)); + run_h_tc(tc, outname, errname, "result"); + atf_tc_fini(tc); +} + +ATF_TC(build_c_o); +ATF_TC_HEAD(build_c_o, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks the atf_check_build_c_o " + "function"); +} +ATF_TC_BODY(build_c_o, tc) +{ + init_and_run_h_tc(&ATF_TC_NAME(h_build_c_o_ok), + &ATF_TC_PACK_NAME(h_build_c_o_ok), "stdout", "stderr"); + ATF_CHECK(atf_utils_grep_file("-o test.o", "stdout")); + ATF_CHECK(atf_utils_grep_file("-c test.c", "stdout")); + + init_and_run_h_tc(&ATF_TC_NAME(h_build_c_o_fail), + &ATF_TC_PACK_NAME(h_build_c_o_fail), "stdout", "stderr"); + ATF_CHECK(atf_utils_grep_file("-o test.o", "stdout")); + ATF_CHECK(atf_utils_grep_file("-c test.c", "stdout")); + ATF_CHECK(atf_utils_grep_file("test.c", "stderr")); + ATF_CHECK(atf_utils_grep_file("UNDEFINED_SYMBOL", "stderr")); +} + +ATF_TC(build_cpp); +ATF_TC_HEAD(build_cpp, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks the atf_check_build_cpp " + "function"); +} +ATF_TC_BODY(build_cpp, tc) +{ + init_and_run_h_tc(&ATF_TC_NAME(h_build_cpp_ok), + &ATF_TC_PACK_NAME(h_build_cpp_ok), "stdout", "stderr"); + ATF_CHECK(atf_utils_grep_file("-o.*test.p", "stdout")); + ATF_CHECK(atf_utils_grep_file("test.c", "stdout")); + ATF_CHECK(atf_utils_grep_file("foo bar", "test.p")); + + init_and_run_h_tc(&ATF_TC_NAME(h_build_cpp_fail), + &ATF_TC_PACK_NAME(h_build_cpp_fail), "stdout", "stderr"); + ATF_CHECK(atf_utils_grep_file("-o test.p", "stdout")); + ATF_CHECK(atf_utils_grep_file("test.c", "stdout")); + ATF_CHECK(atf_utils_grep_file("test.c", "stderr")); + ATF_CHECK(atf_utils_grep_file("non-existent.h", "stderr")); +} + +ATF_TC(build_cxx_o); +ATF_TC_HEAD(build_cxx_o, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks the atf_check_build_cxx_o " + "function"); +} +ATF_TC_BODY(build_cxx_o, tc) +{ + init_and_run_h_tc(&ATF_TC_NAME(h_build_cxx_o_ok), + &ATF_TC_PACK_NAME(h_build_cxx_o_ok), "stdout", "stderr"); + ATF_CHECK(atf_utils_grep_file("-o test.o", "stdout")); + ATF_CHECK(atf_utils_grep_file("-c test.cpp", "stdout")); + + init_and_run_h_tc(&ATF_TC_NAME(h_build_cxx_o_fail), + &ATF_TC_PACK_NAME(h_build_cxx_o_fail), "stdout", "stderr"); + ATF_CHECK(atf_utils_grep_file("-o test.o", "stdout")); + ATF_CHECK(atf_utils_grep_file("-c test.cpp", "stdout")); + ATF_CHECK(atf_utils_grep_file("test.cpp", "stderr")); + ATF_CHECK(atf_utils_grep_file("UNDEFINED_SYMBOL", "stderr")); +} + +ATF_TC(exec_array); +ATF_TC_HEAD(exec_array, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks that atf_check_exec_array " + "works properly"); +} +ATF_TC_BODY(exec_array, tc) +{ + atf_fs_path_t process_helpers; + atf_check_result_t result; + + get_process_helpers_path(tc, false, &process_helpers); + + const char *argv[4]; + argv[0] = atf_fs_path_cstring(&process_helpers); + argv[1] = "echo"; + argv[2] = "test-message"; + argv[3] = NULL; + + RE(atf_check_exec_array(argv, &result)); + + ATF_CHECK(atf_check_result_exited(&result)); + ATF_CHECK(atf_check_result_exitcode(&result) == EXIT_SUCCESS); + + { + const char *path = atf_check_result_stdout(&result); + int fd = open(path, O_RDONLY); + ATF_CHECK(fd != -1); + check_line(fd, "test-message"); + close(fd); + } + + atf_check_result_fini(&result); + atf_fs_path_fini(&process_helpers); +} + +ATF_TC(exec_cleanup); +ATF_TC_HEAD(exec_cleanup, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks that atf_check_exec_array " + "properly cleans up the temporary files it creates"); +} +ATF_TC_BODY(exec_cleanup, tc) +{ + atf_fs_path_t out, err; + atf_check_result_t result; + bool exists; + + do_exec(tc, "exit-success", &result); + RE(atf_fs_path_init_fmt(&out, "%s", atf_check_result_stdout(&result))); + RE(atf_fs_path_init_fmt(&err, "%s", atf_check_result_stderr(&result))); + + RE(atf_fs_exists(&out, &exists)); ATF_CHECK(exists); + RE(atf_fs_exists(&err, &exists)); ATF_CHECK(exists); + atf_check_result_fini(&result); + RE(atf_fs_exists(&out, &exists)); ATF_CHECK(!exists); + RE(atf_fs_exists(&err, &exists)); ATF_CHECK(!exists); + + atf_fs_path_fini(&err); + atf_fs_path_fini(&out); +} + +ATF_TC(exec_exitstatus); +ATF_TC_HEAD(exec_exitstatus, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks that atf_check_exec_array " + "properly captures the exit status of the executed " + "command"); +} +ATF_TC_BODY(exec_exitstatus, tc) +{ + { + atf_check_result_t result; + do_exec(tc, "exit-success", &result); + ATF_CHECK(atf_check_result_exited(&result)); + ATF_CHECK(!atf_check_result_signaled(&result)); + ATF_CHECK(atf_check_result_exitcode(&result) == EXIT_SUCCESS); + atf_check_result_fini(&result); + } + + { + atf_check_result_t result; + do_exec(tc, "exit-failure", &result); + ATF_CHECK(atf_check_result_exited(&result)); + ATF_CHECK(!atf_check_result_signaled(&result)); + ATF_CHECK(atf_check_result_exitcode(&result) == EXIT_FAILURE); + atf_check_result_fini(&result); + } + + { + atf_check_result_t result; + do_exec(tc, "exit-signal", &result); + ATF_CHECK(!atf_check_result_exited(&result)); + ATF_CHECK(atf_check_result_signaled(&result)); + ATF_CHECK(atf_check_result_termsig(&result) == SIGKILL); + atf_check_result_fini(&result); + } +} + +ATF_TC(exec_stdout_stderr); +ATF_TC_HEAD(exec_stdout_stderr, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks that atf_check_exec_array " + "properly captures the stdout and stderr streams " + "of the child process"); +} +ATF_TC_BODY(exec_stdout_stderr, tc) +{ + atf_check_result_t result1, result2; + const char *out1, *out2; + const char *err1, *err2; + + do_exec_with_arg(tc, "stdout-stderr", "result1", &result1); + ATF_CHECK(atf_check_result_exited(&result1)); + ATF_CHECK(atf_check_result_exitcode(&result1) == EXIT_SUCCESS); + + do_exec_with_arg(tc, "stdout-stderr", "result2", &result2); + ATF_CHECK(atf_check_result_exited(&result2)); + ATF_CHECK(atf_check_result_exitcode(&result2) == EXIT_SUCCESS); + + out1 = atf_check_result_stdout(&result1); + out2 = atf_check_result_stdout(&result2); + err1 = atf_check_result_stderr(&result1); + err2 = atf_check_result_stderr(&result2); + + ATF_CHECK(strstr(out1, "check.XXXXXX") == NULL); + ATF_CHECK(strstr(out2, "check.XXXXXX") == NULL); + ATF_CHECK(strstr(err1, "check.XXXXXX") == NULL); + ATF_CHECK(strstr(err2, "check.XXXXXX") == NULL); + + ATF_CHECK(strstr(out1, "/check") != NULL); + ATF_CHECK(strstr(out2, "/check") != NULL); + ATF_CHECK(strstr(err1, "/check") != NULL); + ATF_CHECK(strstr(err2, "/check") != NULL); + + ATF_CHECK(strstr(out1, "/stdout") != NULL); + ATF_CHECK(strstr(out2, "/stdout") != NULL); + ATF_CHECK(strstr(err1, "/stderr") != NULL); + ATF_CHECK(strstr(err2, "/stderr") != NULL); + + ATF_CHECK(strcmp(out1, out2) != 0); + ATF_CHECK(strcmp(err1, err2) != 0); + +#define CHECK_LINES(path, outname, resname) \ + do { \ + int fd = open(path, O_RDONLY); \ + ATF_CHECK(fd != -1); \ + check_line(fd, "Line 1 to " outname " for " resname); \ + check_line(fd, "Line 2 to " outname " for " resname); \ + close(fd); \ + } while (false) + + CHECK_LINES(out1, "stdout", "result1"); + CHECK_LINES(out2, "stdout", "result2"); + CHECK_LINES(err1, "stderr", "result1"); + CHECK_LINES(err2, "stderr", "result2"); + +#undef CHECK_LINES + + atf_check_result_fini(&result2); + atf_check_result_fini(&result1); +} + +ATF_TC(exec_umask); +ATF_TC_HEAD(exec_umask, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks that atf_check_exec_array " + "correctly reports an error if the umask is too " + "restrictive to create temporary files"); +} +ATF_TC_BODY(exec_umask, tc) +{ + atf_check_result_t result; + atf_fs_path_t process_helpers; + const char *argv[3]; + + get_process_helpers_path(tc, false, &process_helpers); + argv[0] = atf_fs_path_cstring(&process_helpers); + argv[1] = "exit-success"; + argv[2] = NULL; + + umask(0222); + atf_error_t err = atf_check_exec_array(argv, &result); + ATF_CHECK(atf_is_error(err)); + ATF_CHECK(atf_error_is(err, "invalid_umask")); + atf_error_free(err); + + atf_fs_path_fini(&process_helpers); +} + +ATF_TC(exec_unknown); +ATF_TC_HEAD(exec_unknown, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks that running a non-existing " + "binary is handled correctly"); +} +ATF_TC_BODY(exec_unknown, tc) +{ + char buf[1024]; + snprintf(buf, sizeof(buf), "%s/non-existent", + atf_config_get("atf_workdir")); + + const char *argv[2]; + argv[0] = buf; + argv[1] = NULL; + + atf_check_result_t result; + RE(atf_check_exec_array(argv, &result)); + ATF_CHECK(atf_check_result_exited(&result)); + ATF_CHECK(atf_check_result_exitcode(&result) == 127); + atf_check_result_fini(&result); +} + +/* --------------------------------------------------------------------- + * Tests cases for the header file. + * --------------------------------------------------------------------- */ + +HEADER_TC(include, "atf-c/check.h"); + +/* --------------------------------------------------------------------- + * Main. + * --------------------------------------------------------------------- */ + +ATF_TP_ADD_TCS(tp) +{ + /* Add the test cases for the free functions. */ + ATF_TP_ADD_TC(tp, build_c_o); + ATF_TP_ADD_TC(tp, build_cpp); + ATF_TP_ADD_TC(tp, build_cxx_o); + ATF_TP_ADD_TC(tp, exec_array); + ATF_TP_ADD_TC(tp, exec_cleanup); + ATF_TP_ADD_TC(tp, exec_exitstatus); + ATF_TP_ADD_TC(tp, exec_stdout_stderr); + ATF_TP_ADD_TC(tp, exec_umask); + ATF_TP_ADD_TC(tp, exec_unknown); + + /* Add the test cases for the header file. */ + ATF_TP_ADD_TC(tp, include); + + return atf_no_error(); +} diff --git a/external/bsd/atf/dist/atf-c/config.c b/external/bsd/atf/dist/atf-c/config.c new file mode 100644 index 000000000..f1047f055 --- /dev/null +++ b/external/bsd/atf/dist/atf-c/config.c @@ -0,0 +1,164 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include + +#include "atf-c/config.h" + +#include "detail/env.h" +#include "detail/sanity.h" + +static bool initialized = false; + +static struct var { + const char *name; + const char *default_value; + const char *value; + bool can_be_empty; +} vars[] = { + { "atf_arch", ATF_ARCH, NULL, false, }, + { "atf_build_cc", ATF_BUILD_CC, NULL, false, }, + { "atf_build_cflags", ATF_BUILD_CFLAGS, NULL, true, }, + { "atf_build_cpp", ATF_BUILD_CPP, NULL, false, }, + { "atf_build_cppflags", ATF_BUILD_CPPFLAGS, NULL, true, }, + { "atf_build_cxx", ATF_BUILD_CXX, NULL, false, }, + { "atf_build_cxxflags", ATF_BUILD_CXXFLAGS, NULL, true, }, + { "atf_confdir", ATF_CONFDIR, NULL, false, }, + { "atf_includedir", ATF_INCLUDEDIR, NULL, false, }, + { "atf_libdir", ATF_LIBDIR, NULL, false, }, + { "atf_libexecdir", ATF_LIBEXECDIR, NULL, false, }, + { "atf_machine", ATF_MACHINE, NULL, false, }, + { "atf_pkgdatadir", ATF_PKGDATADIR, NULL, false, }, + { "atf_shell", ATF_SHELL, NULL, false, }, + { "atf_workdir", ATF_WORKDIR, NULL, false, }, + { NULL, NULL, NULL, false, }, +}; + +/* Only used for unit testing, so this prototype is private. */ +void __atf_config_reinit(void); + +/* --------------------------------------------------------------------- + * Auxiliary functions. + * --------------------------------------------------------------------- */ + +static +char * +string_to_upper(const char *str) +{ + char *uc; + + uc = (char *)malloc(strlen(str) + 1); + if (uc != NULL) { + char *ucptr = uc; + while (*str != '\0') { + *ucptr = toupper((int)*str); + + str++; + ucptr++; + } + *ucptr = '\0'; + } + + return uc; +} + +static +void +initialize_var(struct var *var, const char *envname) +{ + PRE(var->value == NULL); + + if (atf_env_has(envname)) { + const char *val = atf_env_get(envname); + if (strlen(val) > 0 || var->can_be_empty) + var->value = val; + else + var->value = var->default_value; + } else + var->value = var->default_value; + + POST(var->value != NULL); +} + +static +void +initialize(void) +{ + struct var *var; + + PRE(!initialized); + + for (var = vars; var->name != NULL; var++) { + char *envname; + + envname = string_to_upper(var->name); + initialize_var(var, envname); + free(envname); + } + + initialized = true; +} + +/* --------------------------------------------------------------------- + * Free functions. + * --------------------------------------------------------------------- */ + +const char * +atf_config_get(const char *name) +{ + const struct var *var; + const char *value; + + if (!initialized) { + initialize(); + INV(initialized); + } + + value = NULL; + for (var = vars; value == NULL && var->name != NULL; var++) + if (strcmp(var->name, name) == 0) + value = var->value; + INV(value != NULL); + + return value; +} + +void +__atf_config_reinit(void) +{ + struct var *var; + + initialized = false; + + for (var = vars; var->name != NULL; var++) + var->value = NULL; +} diff --git a/external/bsd/atf/dist/atf-c/config.h b/external/bsd/atf/dist/atf-c/config.h new file mode 100644 index 000000000..19b86e2c2 --- /dev/null +++ b/external/bsd/atf/dist/atf-c/config.h @@ -0,0 +1,37 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if !defined(ATF_C_CONFIG_H) +#define ATF_C_CONFIG_H + +#include + +const char *atf_config_get(const char *); + +#endif /* !defined(ATF_C_CONFIG_H) */ diff --git a/external/bsd/atf/dist/atf-c/config_test.c b/external/bsd/atf/dist/atf-c/config_test.c new file mode 100644 index 000000000..a21d68fe5 --- /dev/null +++ b/external/bsd/atf/dist/atf-c/config_test.c @@ -0,0 +1,156 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2007 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include + +#include "atf-c/config.h" + +#include "detail/env.h" +#include "detail/test_helpers.h" + +static const char *test_value = "env-value"; + +static struct varnames { + const char *lc; + const char *uc; + bool can_be_empty; +} all_vars[] = { + { "atf_arch", "ATF_ARCH", false }, + { "atf_build_cc", "ATF_BUILD_CC", false }, + { "atf_build_cflags", "ATF_BUILD_CFLAGS", true }, + { "atf_build_cpp", "ATF_BUILD_CPP", false }, + { "atf_build_cppflags", "ATF_BUILD_CPPFLAGS", true }, + { "atf_build_cxx", "ATF_BUILD_CXX", false }, + { "atf_build_cxxflags", "ATF_BUILD_CXXFLAGS", true }, + { "atf_confdir", "ATF_CONFDIR", false }, + { "atf_includedir", "ATF_INCLUDEDIR", false }, + { "atf_libdir", "ATF_LIBDIR", false }, + { "atf_libexecdir", "ATF_LIBEXECDIR", false }, + { "atf_machine", "ATF_MACHINE", false }, + { "atf_pkgdatadir", "ATF_PKGDATADIR", false }, + { "atf_shell", "ATF_SHELL", false }, + { "atf_workdir", "ATF_WORKDIR", false }, + { NULL, NULL, false } +}; + +/* --------------------------------------------------------------------- + * Auxiliary functions. + * --------------------------------------------------------------------- */ + +void __atf_config_reinit(void); + +static +void +unset_all(void) +{ + const struct varnames *v; + for (v = all_vars; v->lc != NULL; v++) + RE(atf_env_unset(v->uc)); +} + +static +void +compare_one(const char *var, const char *expvalue) +{ + const struct varnames *v; + + printf("Checking that %s is set to %s\n", var, expvalue); + + for (v = all_vars; v->lc != NULL; v++) { + if (strcmp(v->lc, var) == 0) + ATF_CHECK_STREQ(atf_config_get(v->lc), test_value); + else + ATF_CHECK(strcmp(atf_config_get(v->lc), test_value) != 0); + } +} + +/* --------------------------------------------------------------------- + * Test cases for the free functions. + * --------------------------------------------------------------------- */ + +ATF_TC(get); +ATF_TC_HEAD(get, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the atf_config_get function"); +} +ATF_TC_BODY(get, tc) +{ + const struct varnames *v; + + /* Unset all known environment variables and make sure the built-in + * values do not match the bogus value we will use for testing. */ + unset_all(); + __atf_config_reinit(); + for (v = all_vars; v->lc != NULL; v++) + ATF_CHECK(strcmp(atf_config_get(v->lc), test_value) != 0); + + /* Test the behavior of empty values. */ + for (v = all_vars; v->lc != NULL; v++) { + unset_all(); + if (strcmp(atf_config_get(v->lc), "") != 0) { + RE(atf_env_set(v->uc, "")); + __atf_config_reinit(); + if (v->can_be_empty) + ATF_CHECK(strlen(atf_config_get(v->lc)) == 0); + else + ATF_CHECK(strlen(atf_config_get(v->lc)) > 0); + } + } + + /* Check if every variable is recognized individually. */ + for (v = all_vars; v->lc != NULL; v++) { + unset_all(); + RE(atf_env_set(v->uc, test_value)); + __atf_config_reinit(); + compare_one(v->lc, test_value); + } +} + +/* --------------------------------------------------------------------- + * Tests cases for the header file. + * --------------------------------------------------------------------- */ + +HEADER_TC(include, "atf-c/config.h"); + +/* --------------------------------------------------------------------- + * Main. + * --------------------------------------------------------------------- */ + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, get); + + /* Add the test cases for the header file. */ + ATF_TP_ADD_TC(tp, include); + + return atf_no_error(); +} diff --git a/external/bsd/atf/dist/atf-c/defs.h.in b/external/bsd/atf/dist/atf-c/defs.h.in new file mode 100644 index 000000000..7925107cf --- /dev/null +++ b/external/bsd/atf/dist/atf-c/defs.h.in @@ -0,0 +1,37 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if !defined(ATF_C_DEFS_H) +#define ATF_C_DEFS_H + +#define ATF_DEFS_ATTRIBUTE_FORMAT_PRINTF(a, b) @ATTRIBUTE_FORMAT_PRINTF@ +#define ATF_DEFS_ATTRIBUTE_NORETURN @ATTRIBUTE_NORETURN@ +#define ATF_DEFS_ATTRIBUTE_UNUSED @ATTRIBUTE_UNUSED@ + +#endif /* !defined(ATF_C_DEFS_H) */ diff --git a/external/bsd/atf/dist/atf-c/detail/Atffile b/external/bsd/atf/dist/atf-c/detail/Atffile new file mode 100644 index 000000000..5fd859382 --- /dev/null +++ b/external/bsd/atf/dist/atf-c/detail/Atffile @@ -0,0 +1,13 @@ +Content-Type: application/X-atf-atffile; version="1" + +prop: test-suite = atf + +tp: dynstr_test +tp: env_test +tp: fs_test +tp: list_test +tp: map_test +tp: process_test +tp: sanity_test +tp: text_test +tp: user_test diff --git a/external/bsd/atf/dist/atf-c/detail/Kyuafile b/external/bsd/atf/dist/atf-c/detail/Kyuafile new file mode 100644 index 000000000..bb741da4d --- /dev/null +++ b/external/bsd/atf/dist/atf-c/detail/Kyuafile @@ -0,0 +1,13 @@ +syntax("kyuafile", 1) + +test_suite("atf") + +atf_test_program{name="dynstr_test"} +atf_test_program{name="env_test"} +atf_test_program{name="fs_test"} +atf_test_program{name="list_test"} +atf_test_program{name="map_test"} +atf_test_program{name="process_test"} +atf_test_program{name="sanity_test"} +atf_test_program{name="text_test"} +atf_test_program{name="user_test"} diff --git a/external/bsd/atf/dist/atf-c/detail/dynstr.c b/external/bsd/atf/dist/atf-c/detail/dynstr.c new file mode 100644 index 000000000..e533a811f --- /dev/null +++ b/external/bsd/atf/dist/atf-c/detail/dynstr.c @@ -0,0 +1,398 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include + +#include "atf-c/error.h" + +#include "dynstr.h" +#include "sanity.h" +#include "text.h" + +/* --------------------------------------------------------------------- + * Auxiliary functions. + * --------------------------------------------------------------------- */ + +static +atf_error_t +resize(atf_dynstr_t *ad, size_t newsize) +{ + char *newdata; + atf_error_t err; + + PRE(newsize > ad->m_datasize); + + newdata = (char *)malloc(newsize); + if (newdata == NULL) { + err = atf_no_memory_error(); + } else { + strcpy(newdata, ad->m_data); + free(ad->m_data); + ad->m_data = newdata; + ad->m_datasize = newsize; + err = atf_no_error(); + } + + return err; +} + +static +atf_error_t +prepend_or_append(atf_dynstr_t *ad, const char *fmt, va_list ap, + bool prepend) +{ + char *aux; + atf_error_t err; + size_t newlen; + va_list ap2; + + va_copy(ap2, ap); + err = atf_text_format_ap(&aux, fmt, ap2); + va_end(ap2); + if (atf_is_error(err)) + goto out; + newlen = ad->m_length + strlen(aux); + + if (newlen + sizeof(char) > ad->m_datasize) { + err = resize(ad, newlen + sizeof(char)); + if (atf_is_error(err)) + goto out_free; + } + + if (prepend) { + memmove(ad->m_data + strlen(aux), ad->m_data, ad->m_length + 1); + memcpy(ad->m_data, aux, strlen(aux)); + } else + strcpy(ad->m_data + ad->m_length, aux); + ad->m_length = newlen; + err = atf_no_error(); + +out_free: + free(aux); +out: + return err; +} + +/* --------------------------------------------------------------------- + * The "atf_dynstr" type. + * --------------------------------------------------------------------- */ + +/* + * Constants. + */ + +const size_t atf_dynstr_npos = SIZE_MAX; + +/* + * Constructors and destructors. + */ + +atf_error_t +atf_dynstr_init(atf_dynstr_t *ad) +{ + atf_error_t err; + + ad->m_data = (char *)malloc(sizeof(char)); + if (ad->m_data == NULL) { + err = atf_no_memory_error(); + goto out; + } + + ad->m_data[0] = '\0'; + ad->m_datasize = 1; + ad->m_length = 0; + err = atf_no_error(); + +out: + return err; +} + +atf_error_t +atf_dynstr_init_ap(atf_dynstr_t *ad, const char *fmt, va_list ap) +{ + atf_error_t err; + + ad->m_datasize = strlen(fmt) + 1; + ad->m_length = 0; + + do { + va_list ap2; + int ret; + + ad->m_datasize *= 2; + ad->m_data = (char *)malloc(ad->m_datasize); + if (ad->m_data == NULL) { + err = atf_no_memory_error(); + goto out; + } + + va_copy(ap2, ap); + ret = vsnprintf(ad->m_data, ad->m_datasize, fmt, ap2); + va_end(ap2); + if (ret < 0) { + free(ad->m_data); + err = atf_libc_error(errno, "Cannot format string"); + goto out; + } + + INV(ret >= 0); + if ((size_t)ret >= ad->m_datasize) { + free(ad->m_data); + ad->m_data = NULL; + } + ad->m_length = ret; + } while (ad->m_length >= ad->m_datasize); + + err = atf_no_error(); +out: + POST(atf_is_error(err) || ad->m_data != NULL); + return err; +} + +atf_error_t +atf_dynstr_init_fmt(atf_dynstr_t *ad, const char *fmt, ...) +{ + va_list ap; + atf_error_t err; + + va_start(ap, fmt); + err = atf_dynstr_init_ap(ad, fmt, ap); + va_end(ap); + + return err; +} + +atf_error_t +atf_dynstr_init_raw(atf_dynstr_t *ad, const void *mem, size_t memlen) +{ + atf_error_t err; + + if (memlen >= SIZE_MAX - 1) { + err = atf_no_memory_error(); + goto out; + } + + ad->m_data = (char *)malloc(memlen + 1); + if (ad->m_data == NULL) { + err = atf_no_memory_error(); + goto out; + } + + ad->m_datasize = memlen + 1; + memcpy(ad->m_data, mem, memlen); + ad->m_data[memlen] = '\0'; + ad->m_length = strlen(ad->m_data); + INV(ad->m_length <= memlen); + err = atf_no_error(); + +out: + return err; +} + +atf_error_t +atf_dynstr_init_rep(atf_dynstr_t *ad, size_t len, char ch) +{ + atf_error_t err; + + if (len == SIZE_MAX) { + err = atf_no_memory_error(); + goto out; + } + + ad->m_datasize = (len + 1) * sizeof(char); + ad->m_data = (char *)malloc(ad->m_datasize); + if (ad->m_data == NULL) { + err = atf_no_memory_error(); + goto out; + } + + memset(ad->m_data, ch, len); + ad->m_data[len] = '\0'; + ad->m_length = len; + err = atf_no_error(); + +out: + return err; +} + +atf_error_t +atf_dynstr_init_substr(atf_dynstr_t *ad, const atf_dynstr_t *src, + size_t beg, size_t end) +{ + if (beg > src->m_length) + beg = src->m_length; + + if (end == atf_dynstr_npos || end > src->m_length) + end = src->m_length; + + return atf_dynstr_init_raw(ad, src->m_data + beg, end - beg); +} + +atf_error_t +atf_dynstr_copy(atf_dynstr_t *dest, const atf_dynstr_t *src) +{ + atf_error_t err; + + dest->m_data = (char *)malloc(src->m_datasize); + if (dest->m_data == NULL) + err = atf_no_memory_error(); + else { + memcpy(dest->m_data, src->m_data, src->m_datasize); + dest->m_datasize = src->m_datasize; + dest->m_length = src->m_length; + err = atf_no_error(); + } + + return err; +} + +void +atf_dynstr_fini(atf_dynstr_t *ad) +{ + INV(ad->m_data != NULL); + free(ad->m_data); +} + +char * +atf_dynstr_fini_disown(atf_dynstr_t *ad) +{ + INV(ad->m_data != NULL); + return ad->m_data; +} + +/* + * Getters. + */ + +const char * +atf_dynstr_cstring(const atf_dynstr_t *ad) +{ + return ad->m_data; +} + +size_t +atf_dynstr_length(const atf_dynstr_t *ad) +{ + return ad->m_length; +} + +size_t +atf_dynstr_rfind_ch(const atf_dynstr_t *ad, char ch) +{ + size_t pos; + + for (pos = ad->m_length; pos > 0 && ad->m_data[pos - 1] != ch; pos--) + ; + + return pos == 0 ? atf_dynstr_npos : pos - 1; +} + +/* + * Modifiers. + */ + +atf_error_t +atf_dynstr_append_ap(atf_dynstr_t *ad, const char *fmt, va_list ap) +{ + atf_error_t err; + va_list ap2; + + va_copy(ap2, ap); + err = prepend_or_append(ad, fmt, ap2, false); + va_end(ap2); + + return err; +} + +atf_error_t +atf_dynstr_append_fmt(atf_dynstr_t *ad, const char *fmt, ...) +{ + va_list ap; + atf_error_t err; + + va_start(ap, fmt); + err = prepend_or_append(ad, fmt, ap, false); + va_end(ap); + + return err; +} + +void +atf_dynstr_clear(atf_dynstr_t *ad) +{ + ad->m_data[0] = '\0'; + ad->m_length = 0; +} + +atf_error_t +atf_dynstr_prepend_ap(atf_dynstr_t *ad, const char *fmt, va_list ap) +{ + atf_error_t err; + va_list ap2; + + va_copy(ap2, ap); + err = prepend_or_append(ad, fmt, ap2, true); + va_end(ap2); + + return err; +} + +atf_error_t +atf_dynstr_prepend_fmt(atf_dynstr_t *ad, const char *fmt, ...) +{ + va_list ap; + atf_error_t err; + + va_start(ap, fmt); + err = prepend_or_append(ad, fmt, ap, true); + va_end(ap); + + return err; +} + +/* + * Operators. + */ + +bool +atf_equal_dynstr_cstring(const atf_dynstr_t *ad, const char *str) +{ + return strcmp(ad->m_data, str) == 0; +} + +bool +atf_equal_dynstr_dynstr(const atf_dynstr_t *s1, const atf_dynstr_t *s2) +{ + return strcmp(s1->m_data, s2->m_data) == 0; +} diff --git a/external/bsd/atf/dist/atf-c/detail/dynstr.h b/external/bsd/atf/dist/atf-c/detail/dynstr.h new file mode 100644 index 000000000..c82209a48 --- /dev/null +++ b/external/bsd/atf/dist/atf-c/detail/dynstr.h @@ -0,0 +1,81 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if !defined(ATF_C_DYNSTR_H) +#define ATF_C_DYNSTR_H + +#include +#include +#include + +#include + +/* --------------------------------------------------------------------- + * The "atf_dynstr" type. + * --------------------------------------------------------------------- */ + +struct atf_dynstr { + char *m_data; + size_t m_datasize; + size_t m_length; +}; +typedef struct atf_dynstr atf_dynstr_t; + +/* Constants */ +extern const size_t atf_dynstr_npos; + +/* Constructors and destructors */ +atf_error_t atf_dynstr_init(atf_dynstr_t *); +atf_error_t atf_dynstr_init_ap(atf_dynstr_t *, const char *, va_list); +atf_error_t atf_dynstr_init_fmt(atf_dynstr_t *, const char *, ...); +atf_error_t atf_dynstr_init_raw(atf_dynstr_t *, const void *, size_t); +atf_error_t atf_dynstr_init_rep(atf_dynstr_t *, size_t, char); +atf_error_t atf_dynstr_init_substr(atf_dynstr_t *, const atf_dynstr_t *, + size_t, size_t); +atf_error_t atf_dynstr_copy(atf_dynstr_t *, const atf_dynstr_t *); +void atf_dynstr_fini(atf_dynstr_t *); +char *atf_dynstr_fini_disown(atf_dynstr_t *); + +/* Getters */ +const char *atf_dynstr_cstring(const atf_dynstr_t *); +size_t atf_dynstr_length(const atf_dynstr_t *); +size_t atf_dynstr_rfind_ch(const atf_dynstr_t *, char); + +/* Modifiers */ +atf_error_t atf_dynstr_append_ap(atf_dynstr_t *, const char *, va_list); +atf_error_t atf_dynstr_append_fmt(atf_dynstr_t *, const char *, ...); +void atf_dynstr_clear(atf_dynstr_t *); +atf_error_t atf_dynstr_prepend_ap(atf_dynstr_t *, const char *, va_list); +atf_error_t atf_dynstr_prepend_fmt(atf_dynstr_t *, const char *, ...); + +/* Operators */ +bool atf_equal_dynstr_cstring(const atf_dynstr_t *, const char *); +bool atf_equal_dynstr_dynstr(const atf_dynstr_t *, const atf_dynstr_t *); + +#endif /* ATF_C_DYNSTR_H */ diff --git a/external/bsd/atf/dist/atf-c/detail/dynstr_test.c b/external/bsd/atf/dist/atf-c/detail/dynstr_test.c new file mode 100644 index 000000000..1b68d38b7 --- /dev/null +++ b/external/bsd/atf/dist/atf-c/detail/dynstr_test.c @@ -0,0 +1,637 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include + +#include + +#include "dynstr.h" +#include "test_helpers.h" + +/* --------------------------------------------------------------------- + * Tests for the "atf_dynstr" type. + * --------------------------------------------------------------------- */ + +/* + * Constructors and destructors. + */ + +ATF_TC(init); +ATF_TC_HEAD(init, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks the empty constructor"); +} +ATF_TC_BODY(init, tc) +{ + atf_dynstr_t str; + + RE(atf_dynstr_init(&str)); + ATF_REQUIRE_EQ(atf_dynstr_length(&str), 0); + ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "") == 0); + atf_dynstr_fini(&str); +} + +static +void +init_fmt(atf_dynstr_t *str, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + RE(atf_dynstr_init_ap(str, fmt, ap)); + va_end(ap); +} + +ATF_TC(init_ap); +ATF_TC_HEAD(init_ap, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks the formatted constructor using " + "a va_list argument"); +} +ATF_TC_BODY(init_ap, tc) +{ + atf_dynstr_t str; + + init_fmt(&str, "String 1"); + ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "String 1") == 0); + atf_dynstr_fini(&str); + + init_fmt(&str, "String %d", 2); + ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "String 2") == 0); + atf_dynstr_fini(&str); + + init_fmt(&str, "%s %d", "String", 3); + ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "String 3") == 0); + atf_dynstr_fini(&str); + + init_fmt(&str, "%s%s%s%s%s%s%s", "This ", "should ", "be ", "a ", + "large ", "string ", "aaaabbbbccccdddd"); + ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), + "This should be a large string " + "aaaabbbbccccdddd") == 0); + atf_dynstr_fini(&str); +} + +ATF_TC(init_fmt); +ATF_TC_HEAD(init_fmt, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks the formatted constructor using " + "a variable list of parameters"); +} +ATF_TC_BODY(init_fmt, tc) +{ + atf_dynstr_t str; + + RE(atf_dynstr_init_fmt(&str, "String 1")); + ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "String 1") == 0); + atf_dynstr_fini(&str); + + RE(atf_dynstr_init_fmt(&str, "String %d", 2)); + ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "String 2") == 0); + atf_dynstr_fini(&str); + + RE(atf_dynstr_init_fmt(&str, "%s %d", "String", 3)); + ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "String 3") == 0); + atf_dynstr_fini(&str); + + RE(atf_dynstr_init_fmt(&str, "%s%s%s%s%s%s%s", "This ", "should ", + "be ", "a ", "large ", "string ", + "aaaabbbbccccdddd")); + ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), + "This should be a large string " + "aaaabbbbccccdddd") == 0); + atf_dynstr_fini(&str); +} + +ATF_TC(init_raw); +ATF_TC_HEAD(init_raw, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks the construction of a string " + "using a raw memory pointer"); +} +ATF_TC_BODY(init_raw, tc) +{ + const char *src = "String 1, String 2"; + atf_dynstr_t str; + + RE(atf_dynstr_init_raw(&str, src, 0)); + ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "") == 0); + atf_dynstr_fini(&str); + + RE(atf_dynstr_init_raw(&str, src, 8)); + ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "String 1") == 0); + atf_dynstr_fini(&str); + + RE(atf_dynstr_init_raw(&str, src + 10, 8)); + ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "String 2") == 0); + atf_dynstr_fini(&str); + + RE(atf_dynstr_init_raw(&str, "String\0Lost", 11)); + ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "String") == 0); + atf_dynstr_fini(&str); + + { + atf_error_t err = atf_dynstr_init_raw(&str, "NULL", SIZE_MAX - 1); + ATF_REQUIRE(atf_is_error(err)); + ATF_REQUIRE(atf_error_is(err, "no_memory")); + atf_error_free(err); + } +} + +ATF_TC(init_rep); +ATF_TC_HEAD(init_rep, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks the construction of a string by " + "repeating characters"); +} +ATF_TC_BODY(init_rep, tc) +{ + const size_t maxlen = 8192; + char buf[maxlen + 1]; + size_t i; + + buf[0] = '\0'; + + for (i = 0; i < maxlen; i++) { + atf_dynstr_t str; + + RE(atf_dynstr_init_rep(&str, i, 'a')); + + if (strcmp(atf_dynstr_cstring(&str), buf) != 0) { + fprintf(stderr, "Failed at iteration %zd\n", i); + atf_tc_fail("Failed to construct dynstr by repeating %zd " + "times the '%c' character", i, 'a'); + } + + atf_dynstr_fini(&str); + + strcat(buf, "a"); + } + + { + atf_dynstr_t str; + atf_error_t err; + + err = atf_dynstr_init_rep(&str, SIZE_MAX, 'a'); + ATF_REQUIRE(atf_is_error(err)); + ATF_REQUIRE(atf_error_is(err, "no_memory")); + atf_error_free(err); + + err = atf_dynstr_init_rep(&str, SIZE_MAX - 1, 'a'); + ATF_REQUIRE(atf_is_error(err)); + ATF_REQUIRE(atf_error_is(err, "no_memory")); + atf_error_free(err); + } +} + +ATF_TC(init_substr); +ATF_TC_HEAD(init_substr, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks the construction of a string " + "using a substring of another one"); +} +ATF_TC_BODY(init_substr, tc) +{ + atf_dynstr_t src; + atf_dynstr_t str; + + RE(atf_dynstr_init_fmt(&src, "Str 1, Str 2")); + + RE(atf_dynstr_init_substr(&str, &src, 0, 0)); + ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "") == 0); + atf_dynstr_fini(&str); + + RE(atf_dynstr_init_substr(&str, &src, 0, atf_dynstr_npos)); + ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "Str 1, Str 2") == 0); + atf_dynstr_fini(&str); + + RE(atf_dynstr_init_substr(&str, &src, 0, 100)); + ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "Str 1, Str 2") == 0); + atf_dynstr_fini(&str); + + RE(atf_dynstr_init_substr(&str, &src, 0, 5)); + ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "Str 1") == 0); + atf_dynstr_fini(&str); + + RE(atf_dynstr_init_substr(&str, &src, 100, atf_dynstr_npos)); + ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "") == 0); + atf_dynstr_fini(&str); + + RE(atf_dynstr_init_substr(&str, &src, 7, atf_dynstr_npos)); + ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "Str 2") == 0); + atf_dynstr_fini(&str); + + atf_dynstr_fini(&src); +} + +ATF_TC(copy); +ATF_TC_HEAD(copy, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks the atf_dynstr_copy constructor"); +} +ATF_TC_BODY(copy, tc) +{ + atf_dynstr_t str, str2; + + RE(atf_dynstr_init_fmt(&str, "Test string")); + RE(atf_dynstr_copy(&str2, &str)); + + ATF_REQUIRE(atf_equal_dynstr_dynstr(&str, &str2)); + + RE(atf_dynstr_append_fmt(&str2, " non-shared text")); + + ATF_REQUIRE(!atf_equal_dynstr_dynstr(&str, &str2)); + + atf_dynstr_fini(&str2); + atf_dynstr_fini(&str); +} + +ATF_TC(fini_disown); +ATF_TC_HEAD(fini_disown, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks grabbing ownership of the " + "internal plain C string"); +} +ATF_TC_BODY(fini_disown, tc) +{ + const char *cstr; + char *cstr2; + atf_dynstr_t str; + + RE(atf_dynstr_init_fmt(&str, "Test string 1")); + cstr = atf_dynstr_cstring(&str); + cstr2 = atf_dynstr_fini_disown(&str); + + ATF_REQUIRE_EQ(cstr, cstr2); + free(cstr2); +} + +/* + * Getters. + */ + +ATF_TC(cstring); +ATF_TC_HEAD(cstring, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks the method to obtain a plain C " + "string"); +} +ATF_TC_BODY(cstring, tc) +{ + const char *cstr; + atf_dynstr_t str; + + RE(atf_dynstr_init_fmt(&str, "Test string 1")); + cstr = atf_dynstr_cstring(&str); + ATF_REQUIRE(cstr != NULL); + ATF_REQUIRE(strcmp(cstr, "Test string 1") == 0); + atf_dynstr_fini(&str); + + RE(atf_dynstr_init_fmt(&str, "Test string 2")); + cstr = atf_dynstr_cstring(&str); + ATF_REQUIRE(cstr != NULL); + ATF_REQUIRE(strcmp(cstr, "Test string 2") == 0); + atf_dynstr_fini(&str); +} + +ATF_TC(length); +ATF_TC_HEAD(length, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks the method to obtain the length"); +} +ATF_TC_BODY(length, tc) +{ + size_t i; + + for (i = 0; i < 8192; i++) { + atf_dynstr_t str; + RE(atf_dynstr_init_rep(&str, i, 'a')); + ATF_REQUIRE_EQ(atf_dynstr_length(&str), i); + atf_dynstr_fini(&str); + } +} + +ATF_TC(rfind_ch); +ATF_TC_HEAD(rfind_ch, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks the method to locate the first " + "occurrence of a character starting from the end"); +} +ATF_TC_BODY(rfind_ch, tc) +{ + atf_dynstr_t str; + + RE(atf_dynstr_init_fmt(&str, "Foo1/Bar2/,.Baz")); + + ATF_REQUIRE_EQ(atf_dynstr_rfind_ch(&str, '\0'), atf_dynstr_npos); + + ATF_REQUIRE_EQ(atf_dynstr_rfind_ch(&str, '0'), atf_dynstr_npos); + ATF_REQUIRE_EQ(atf_dynstr_rfind_ch(&str, 'b'), atf_dynstr_npos); + + ATF_REQUIRE_EQ(atf_dynstr_rfind_ch(&str, 'F'), 0); + ATF_REQUIRE_EQ(atf_dynstr_rfind_ch(&str, '/'), 9); + ATF_REQUIRE_EQ(atf_dynstr_rfind_ch(&str, 'a'), 13); + ATF_REQUIRE_EQ(atf_dynstr_rfind_ch(&str, 'z'), 14); + + atf_dynstr_fini(&str); +} + +/* + * Modifiers. + */ + +static +void +check_append(atf_error_t (*append)(atf_dynstr_t *, const char *, ...)) +{ + const size_t maxlen = 8192; + char buf[maxlen + 1]; + size_t i; + atf_dynstr_t str; + + printf("Appending with plain string\n"); + buf[0] = '\0'; + RE(atf_dynstr_init(&str)); + for (i = 0; i < maxlen; i++) { + if (strcmp(atf_dynstr_cstring(&str), buf) != 0) { + fprintf(stderr, "Failed at iteration %zd\n", i); + atf_tc_fail("Failed to append character at iteration %zd", i); + } + + RE(append(&str, "a")); + strcat(buf, "a"); + } + atf_dynstr_fini(&str); + + printf("Appending with formatted string\n"); + buf[0] = '\0'; + RE(atf_dynstr_init(&str)); + for (i = 0; i < maxlen; i++) { + if (strcmp(atf_dynstr_cstring(&str), buf) != 0) { + fprintf(stderr, "Failed at iteration %zd\n", i); + atf_tc_fail("Failed to append character at iteration %zd", i); + } + + RE(append(&str, "%s", "a")); + strcat(buf, "a"); + } + atf_dynstr_fini(&str); +} + +static +atf_error_t +append_ap_aux(atf_dynstr_t *str, const char *fmt, ...) +{ + va_list ap; + atf_error_t err; + + va_start(ap, fmt); + err = atf_dynstr_append_ap(str, fmt, ap); + va_end(ap); + + return err; +} + +ATF_TC(append_ap); +ATF_TC_HEAD(append_ap, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks that appending a string to " + "another one works"); +} +ATF_TC_BODY(append_ap, tc) +{ + check_append(append_ap_aux); +} + +ATF_TC(append_fmt); +ATF_TC_HEAD(append_fmt, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks that appending a string to " + "another one works"); +} +ATF_TC_BODY(append_fmt, tc) +{ + check_append(atf_dynstr_append_fmt); +} + +ATF_TC(clear); +ATF_TC_HEAD(clear, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks clearing a string"); +} +ATF_TC_BODY(clear, tc) +{ + atf_dynstr_t str; + + printf("Clear an empty string\n"); + RE(atf_dynstr_init(&str)); + atf_dynstr_clear(&str); + ATF_REQUIRE_EQ(atf_dynstr_length(&str), 0); + ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "") == 0); + atf_dynstr_fini(&str); + + printf("Clear a non-empty string\n"); + RE(atf_dynstr_init_fmt(&str, "Not empty")); + ATF_REQUIRE_EQ(atf_dynstr_length(&str), strlen("Not empty")); + ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "Not empty") == 0); + atf_dynstr_clear(&str); + ATF_REQUIRE_EQ(atf_dynstr_length(&str), 0); + ATF_REQUIRE(strcmp(atf_dynstr_cstring(&str), "") == 0); + atf_dynstr_fini(&str); +} + +static +void +check_prepend(atf_error_t (*prepend)(atf_dynstr_t *, const char *, ...)) +{ + const size_t maxlen = 8192; + char buf[maxlen + 1]; + size_t i; + atf_dynstr_t str; + + printf("Prepending with plain string\n"); + buf[0] = '\0'; + RE(atf_dynstr_init(&str)); + for (i = 0; i < maxlen; i++) { + if (strcmp(atf_dynstr_cstring(&str), buf) != 0) { + fprintf(stderr, "Failed at iteration %zd\n", i); + atf_tc_fail("Failed to prepend character at iteration %zd", i); + } + + memmove(buf + 1, buf, i + 1); + if (i % 2 == 0) { + RE(prepend(&str, "%s", "a")); + buf[0] = 'a'; + } else { + RE(prepend(&str, "%s", "b")); + buf[0] = 'b'; + } + } + atf_dynstr_fini(&str); + + printf("Prepending with formatted string\n"); + buf[0] = '\0'; + RE(atf_dynstr_init(&str)); + for (i = 0; i < maxlen; i++) { + if (strcmp(atf_dynstr_cstring(&str), buf) != 0) { + fprintf(stderr, "Failed at iteration %zd\n", i); + atf_tc_fail("Failed to prepend character at iteration %zd", i); + } + + memmove(buf + 1, buf, i + 1); + if (i % 2 == 0) { + RE(prepend(&str, "%s", "a")); + buf[0] = 'a'; + } else { + RE(prepend(&str, "%s", "b")); + buf[0] = 'b'; + } + } + atf_dynstr_fini(&str); +} + +static +atf_error_t +prepend_ap_aux(atf_dynstr_t *str, const char *fmt, ...) +{ + va_list ap; + atf_error_t err; + + va_start(ap, fmt); + err = atf_dynstr_prepend_ap(str, fmt, ap); + va_end(ap); + + return err; +} + +ATF_TC(prepend_ap); +ATF_TC_HEAD(prepend_ap, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks that prepending a string to " + "another one works"); +} +ATF_TC_BODY(prepend_ap, tc) +{ + check_prepend(prepend_ap_aux); +} + +ATF_TC(prepend_fmt); +ATF_TC_HEAD(prepend_fmt, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks that prepending a string to " + "another one works"); +} +ATF_TC_BODY(prepend_fmt, tc) +{ + check_prepend(atf_dynstr_prepend_fmt); +} + +/* + * Operators. + */ + +ATF_TC(equal_cstring); +ATF_TC_HEAD(equal_cstring, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks the atf_equal_dynstr_cstring " + "function"); +} +ATF_TC_BODY(equal_cstring, tc) +{ + atf_dynstr_t str; + + RE(atf_dynstr_init(&str)); + ATF_REQUIRE( atf_equal_dynstr_cstring(&str, "")); + ATF_REQUIRE(!atf_equal_dynstr_cstring(&str, "Test")); + atf_dynstr_fini(&str); + + RE(atf_dynstr_init_fmt(&str, "Test")); + ATF_REQUIRE( atf_equal_dynstr_cstring(&str, "Test")); + ATF_REQUIRE(!atf_equal_dynstr_cstring(&str, "")); + ATF_REQUIRE(!atf_equal_dynstr_cstring(&str, "Tes")); + ATF_REQUIRE(!atf_equal_dynstr_cstring(&str, "Test ")); + atf_dynstr_fini(&str); +} + +ATF_TC(equal_dynstr); +ATF_TC_HEAD(equal_dynstr, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks the atf_equal_dynstr_dynstr " + "function"); +} +ATF_TC_BODY(equal_dynstr, tc) +{ + atf_dynstr_t str, str2; + + RE(atf_dynstr_init(&str)); + RE(atf_dynstr_init_fmt(&str2, "Test")); + ATF_REQUIRE( atf_equal_dynstr_dynstr(&str, &str)); + ATF_REQUIRE(!atf_equal_dynstr_dynstr(&str, &str2)); + atf_dynstr_fini(&str2); + atf_dynstr_fini(&str); +} + +/* --------------------------------------------------------------------- + * Main. + * --------------------------------------------------------------------- */ + +ATF_TP_ADD_TCS(tp) +{ + /* Constructors and destructors. */ + ATF_TP_ADD_TC(tp, init); + ATF_TP_ADD_TC(tp, init_ap); + ATF_TP_ADD_TC(tp, init_fmt); + ATF_TP_ADD_TC(tp, init_raw); + ATF_TP_ADD_TC(tp, init_rep); + ATF_TP_ADD_TC(tp, init_substr); + ATF_TP_ADD_TC(tp, copy); + ATF_TP_ADD_TC(tp, fini_disown); + + /* Getters. */ + ATF_TP_ADD_TC(tp, cstring); + ATF_TP_ADD_TC(tp, length); + ATF_TP_ADD_TC(tp, rfind_ch); + + /* Modifiers. */ + ATF_TP_ADD_TC(tp, append_ap); + ATF_TP_ADD_TC(tp, append_fmt); + ATF_TP_ADD_TC(tp, clear); + ATF_TP_ADD_TC(tp, prepend_ap); + ATF_TP_ADD_TC(tp, prepend_fmt); + + /* Operators. */ + ATF_TP_ADD_TC(tp, equal_cstring); + ATF_TP_ADD_TC(tp, equal_dynstr); + + return atf_no_error(); +} diff --git a/external/bsd/atf/dist/atf-c/detail/env.c b/external/bsd/atf/dist/atf-c/detail/env.c new file mode 100644 index 000000000..feb4ee53e --- /dev/null +++ b/external/bsd/atf/dist/atf-c/detail/env.c @@ -0,0 +1,108 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2007 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if defined(HAVE_CONFIG_H) +#include "bconfig.h" +#endif + +#include +#include + +#include "atf-c/error.h" + +#include "env.h" +#include "sanity.h" +#include "text.h" + +const char * +atf_env_get(const char *name) +{ + const char* val = getenv(name); + PRE(val != NULL); + return val; +} + +bool +atf_env_has(const char *name) +{ + return getenv(name) != NULL; +} + +atf_error_t +atf_env_set(const char *name, const char *val) +{ + atf_error_t err; + +#if defined(HAVE_SETENV) + if (setenv(name, val, 1) == -1) + err = atf_libc_error(errno, "Cannot set environment variable " + "'%s' to '%s'", name, val); + else + err = atf_no_error(); +#elif defined(HAVE_PUTENV) + char *buf; + + err = atf_text_format(&buf, "%s=%s", name, val); + if (!atf_is_error(err)) { + if (putenv(buf) == -1) + err = atf_libc_error(errno, "Cannot set environment variable " + "'%s' to '%s'", name, val); + free(buf); + } +#else +# error "Don't know how to set an environment variable." +#endif + + return err; +} + +atf_error_t +atf_env_unset(const char *name) +{ + atf_error_t err; + +#if defined(HAVE_UNSETENV) + unsetenv(name); + err = atf_no_error(); +#elif defined(HAVE_PUTENV) + char *buf; + + err = atf_text_format(&buf, "%s=", name); + if (!atf_is_error(err)) { + if (putenv(buf) == -1) + err = atf_libc_error(errno, "Cannot unset environment variable" + " '%s'", name); + free(buf); + } +#else +# error "Don't know how to unset an environment variable." +#endif + + return err; +} diff --git a/external/bsd/atf/dist/atf-c/detail/env.h b/external/bsd/atf/dist/atf-c/detail/env.h new file mode 100644 index 000000000..c0d07a3a3 --- /dev/null +++ b/external/bsd/atf/dist/atf-c/detail/env.h @@ -0,0 +1,42 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if !defined(ATF_C_ENV_H) +#define ATF_C_ENV_H + +#include + +#include + +const char *atf_env_get(const char *); +bool atf_env_has(const char *); +atf_error_t atf_env_set(const char *, const char *); +atf_error_t atf_env_unset(const char *); + +#endif /* !defined(ATF_C_ENV_H) */ diff --git a/external/bsd/atf/dist/atf-c/detail/env_test.c b/external/bsd/atf/dist/atf-c/detail/env_test.c new file mode 100644 index 000000000..6ebf36c8b --- /dev/null +++ b/external/bsd/atf/dist/atf-c/detail/env_test.c @@ -0,0 +1,116 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2007 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include + +#include "env.h" +#include "test_helpers.h" +#include "text.h" + +/* --------------------------------------------------------------------- + * Test cases for the free functions. + * --------------------------------------------------------------------- */ + +ATF_TC(has); +ATF_TC_HEAD(has, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the atf_env_has function"); +} +ATF_TC_BODY(has, tc) +{ + ATF_REQUIRE(atf_env_has("PATH")); + ATF_REQUIRE(!atf_env_has("_UNDEFINED_VARIABLE_")); +} + +ATF_TC(get); +ATF_TC_HEAD(get, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the atf_env_get function"); +} +ATF_TC_BODY(get, tc) +{ + const char *val; + + ATF_REQUIRE(atf_env_has("PATH")); + + val = atf_env_get("PATH"); + ATF_REQUIRE(strlen(val) > 0); + ATF_REQUIRE(strchr(val, ':') != NULL); +} + +ATF_TC(set); +ATF_TC_HEAD(set, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the atf_env_set function"); +} +ATF_TC_BODY(set, tc) +{ + char *oldval; + + ATF_REQUIRE(atf_env_has("PATH")); + RE(atf_text_format(&oldval, "%s", atf_env_get("PATH"))); + RE(atf_env_set("PATH", "foo-bar")); + ATF_REQUIRE(strcmp(atf_env_get("PATH"), oldval) != 0); + ATF_REQUIRE(strcmp(atf_env_get("PATH"), "foo-bar") == 0); + free(oldval); + + ATF_REQUIRE(!atf_env_has("_UNDEFINED_VARIABLE_")); + RE(atf_env_set("_UNDEFINED_VARIABLE_", "foo2-bar2")); + ATF_REQUIRE(strcmp(atf_env_get("_UNDEFINED_VARIABLE_"), + "foo2-bar2") == 0); +} + +ATF_TC(unset); +ATF_TC_HEAD(unset, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the atf_env_unset function"); +} +ATF_TC_BODY(unset, tc) +{ + ATF_REQUIRE(atf_env_has("PATH")); + RE(atf_env_unset("PATH")); + ATF_REQUIRE(!atf_env_has("PATH")); +} + +/* --------------------------------------------------------------------- + * Main. + * --------------------------------------------------------------------- */ + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, has); + ATF_TP_ADD_TC(tp, get); + ATF_TP_ADD_TC(tp, set); + ATF_TP_ADD_TC(tp, unset); + + return atf_no_error(); +} diff --git a/external/bsd/atf/dist/atf-c/detail/fs.c b/external/bsd/atf/dist/atf-c/detail/fs.c new file mode 100644 index 000000000..22cbca439 --- /dev/null +++ b/external/bsd/atf/dist/atf-c/detail/fs.c @@ -0,0 +1,888 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2007 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if defined(HAVE_CONFIG_H) +#include "bconfig.h" +#endif + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "atf-c/defs.h" +#include "atf-c/error.h" + +#include "fs.h" +#include "sanity.h" +#include "text.h" +#include "user.h" + +/* --------------------------------------------------------------------- + * Prototypes for auxiliary functions. + * --------------------------------------------------------------------- */ + +static bool check_umask(const mode_t, const mode_t); +static atf_error_t copy_contents(const atf_fs_path_t *, char **); +static mode_t current_umask(void); +static atf_error_t do_mkdtemp(char *); +static atf_error_t normalize(atf_dynstr_t *, char *); +static atf_error_t normalize_ap(atf_dynstr_t *, const char *, va_list); +static void replace_contents(atf_fs_path_t *, const char *); +static const char *stat_type_to_string(const int); + +/* --------------------------------------------------------------------- + * The "invalid_umask" error type. + * --------------------------------------------------------------------- */ + +struct invalid_umask_error_data { + /* One of atf_fs_stat_*_type. */ + int m_type; + + /* The original path causing the error. */ + /* XXX: Ideally this would be an atf_fs_path_t, but if we create it + * from the error constructor, we cannot delete the path later on. + * Can't remember why atf_error_new does not take a hook for + * deletion. */ + char m_path[1024]; + + /* The umask that caused the error. */ + mode_t m_umask; +}; +typedef struct invalid_umask_error_data invalid_umask_error_data_t; + +static +void +invalid_umask_format(const atf_error_t err, char *buf, size_t buflen) +{ + const invalid_umask_error_data_t *data; + + PRE(atf_error_is(err, "invalid_umask")); + + data = atf_error_data(err); + snprintf(buf, buflen, "Could not create the temporary %s %s because " + "it will not have enough access rights due to the current " + "umask %05o", stat_type_to_string(data->m_type), + data->m_path, (unsigned int)data->m_umask); +} + +static +atf_error_t +invalid_umask_error(const atf_fs_path_t *path, const int type, + const mode_t failing_mask) +{ + atf_error_t err; + invalid_umask_error_data_t data; + + data.m_type = type; + + strncpy(data.m_path, atf_fs_path_cstring(path), sizeof(data.m_path)); + data.m_path[sizeof(data.m_path) - 1] = '\0'; + + data.m_umask = failing_mask; + + err = atf_error_new("invalid_umask", &data, sizeof(data), + invalid_umask_format); + + return err; +} + +/* --------------------------------------------------------------------- + * The "unknown_file_type" error type. + * --------------------------------------------------------------------- */ + +struct unknown_type_error_data { + const char *m_path; + int m_type; +}; +typedef struct unknown_type_error_data unknown_type_error_data_t; + +static +void +unknown_type_format(const atf_error_t err, char *buf, size_t buflen) +{ + const unknown_type_error_data_t *data; + + PRE(atf_error_is(err, "unknown_type")); + + data = atf_error_data(err); + snprintf(buf, buflen, "Unknown file type %d of %s", data->m_type, + data->m_path); +} + +static +atf_error_t +unknown_type_error(const char *path, int type) +{ + atf_error_t err; + unknown_type_error_data_t data; + + data.m_path = path; + data.m_type = type; + + err = atf_error_new("unknown_type", &data, sizeof(data), + unknown_type_format); + + return err; +} + +/* --------------------------------------------------------------------- + * Auxiliary functions. + * --------------------------------------------------------------------- */ + +static +bool +check_umask(const mode_t exp_mode, const mode_t min_mode) +{ + const mode_t actual_mode = (~current_umask() & exp_mode); + return (actual_mode & min_mode) == min_mode; +} + +static +atf_error_t +copy_contents(const atf_fs_path_t *p, char **buf) +{ + atf_error_t err; + char *str; + + str = (char *)malloc(atf_dynstr_length(&p->m_data) + 1); + if (str == NULL) + err = atf_no_memory_error(); + else { + strcpy(str, atf_dynstr_cstring(&p->m_data)); + *buf = str; + err = atf_no_error(); + } + + return err; +} + +static +mode_t +current_umask(void) +{ + const mode_t current = umask(0); + (void)umask(current); + return current; +} + +static +atf_error_t +do_mkdtemp(char *tmpl) +{ + atf_error_t err; + + PRE(strstr(tmpl, "XXXXXX") != NULL); + + if (mkdtemp(tmpl) == NULL) + err = atf_libc_error(errno, "Cannot create temporary directory " + "with template '%s'", tmpl); + else + err = atf_no_error(); + + return err; +} + +static +atf_error_t +do_mkstemp(char *tmpl, int *fdout) +{ + atf_error_t err; + + PRE(strstr(tmpl, "XXXXXX") != NULL); + + *fdout = mkstemp(tmpl); + if (*fdout == -1) + err = atf_libc_error(errno, "Cannot create temporary file " + "with template '%s'", tmpl); + + else + err = atf_no_error(); + + return err; +} + +static +atf_error_t +normalize(atf_dynstr_t *d, char *p) +{ + const char *ptr; + char *last; + atf_error_t err; + bool first; + + PRE(strlen(p) > 0); + PRE(atf_dynstr_length(d) == 0); + + if (p[0] == '/') + err = atf_dynstr_append_fmt(d, "/"); + else + err = atf_no_error(); + + first = true; + last = NULL; /* Silence GCC warning. */ + ptr = strtok_r(p, "/", &last); + while (!atf_is_error(err) && ptr != NULL) { + if (strlen(ptr) > 0) { + err = atf_dynstr_append_fmt(d, "%s%s", first ? "" : "/", ptr); + first = false; + } + + ptr = strtok_r(NULL, "/", &last); + } + + return err; +} + +static +atf_error_t +normalize_ap(atf_dynstr_t *d, const char *p, va_list ap) +{ + char *str; + atf_error_t err; + va_list ap2; + + err = atf_dynstr_init(d); + if (atf_is_error(err)) + goto out; + + va_copy(ap2, ap); + err = atf_text_format_ap(&str, p, ap2); + va_end(ap2); + if (atf_is_error(err)) + atf_dynstr_fini(d); + else { + err = normalize(d, str); + free(str); + } + +out: + return err; +} + +static +void +replace_contents(atf_fs_path_t *p, const char *buf) +{ + atf_error_t err; + + PRE(atf_dynstr_length(&p->m_data) == strlen(buf)); + + atf_dynstr_clear(&p->m_data); + err = atf_dynstr_append_fmt(&p->m_data, "%s", buf); + + INV(!atf_is_error(err)); +} + +static +const char * +stat_type_to_string(const int type) +{ + const char *str; + + if (type == atf_fs_stat_blk_type) + str = "block device"; + else if (type == atf_fs_stat_chr_type) + str = "character device"; + else if (type == atf_fs_stat_dir_type) + str = "directory"; + else if (type == atf_fs_stat_fifo_type) + str = "named pipe"; + else if (type == atf_fs_stat_lnk_type) + str = "symbolic link"; + else if (type == atf_fs_stat_reg_type) + str = "regular file"; + else if (type == atf_fs_stat_sock_type) + str = "socket"; + else if (type == atf_fs_stat_wht_type) + str = "whiteout"; + else { + UNREACHABLE; + str = NULL; + } + + return str; +} + +/* --------------------------------------------------------------------- + * The "atf_fs_path" type. + * --------------------------------------------------------------------- */ + +/* + * Constructors/destructors. + */ + +atf_error_t +atf_fs_path_init_ap(atf_fs_path_t *p, const char *fmt, va_list ap) +{ + atf_error_t err; + va_list ap2; + + va_copy(ap2, ap); + err = normalize_ap(&p->m_data, fmt, ap2); + va_end(ap2); + + return err; +} + +atf_error_t +atf_fs_path_init_fmt(atf_fs_path_t *p, const char *fmt, ...) +{ + va_list ap; + atf_error_t err; + + va_start(ap, fmt); + err = atf_fs_path_init_ap(p, fmt, ap); + va_end(ap); + + return err; +} + +atf_error_t +atf_fs_path_copy(atf_fs_path_t *dest, const atf_fs_path_t *src) +{ + return atf_dynstr_copy(&dest->m_data, &src->m_data); +} + +void +atf_fs_path_fini(atf_fs_path_t *p) +{ + atf_dynstr_fini(&p->m_data); +} + +/* + * Getters. + */ + +atf_error_t +atf_fs_path_branch_path(const atf_fs_path_t *p, atf_fs_path_t *bp) +{ + const size_t endpos = atf_dynstr_rfind_ch(&p->m_data, '/'); + atf_error_t err; + + if (endpos == atf_dynstr_npos) + err = atf_fs_path_init_fmt(bp, "."); + else if (endpos == 0) + err = atf_fs_path_init_fmt(bp, "/"); + else + err = atf_dynstr_init_substr(&bp->m_data, &p->m_data, 0, endpos); + +#if defined(HAVE_CONST_DIRNAME) + INV(atf_equal_dynstr_cstring(&bp->m_data, + dirname(atf_dynstr_cstring(&p->m_data)))); +#endif /* defined(HAVE_CONST_DIRNAME) */ + + return err; +} + +const char * +atf_fs_path_cstring(const atf_fs_path_t *p) +{ + return atf_dynstr_cstring(&p->m_data); +} + +atf_error_t +atf_fs_path_leaf_name(const atf_fs_path_t *p, atf_dynstr_t *ln) +{ + size_t begpos = atf_dynstr_rfind_ch(&p->m_data, '/'); + atf_error_t err; + + if (begpos == atf_dynstr_npos) + begpos = 0; + else + begpos++; + + err = atf_dynstr_init_substr(ln, &p->m_data, begpos, atf_dynstr_npos); + +#if defined(HAVE_CONST_BASENAME) + INV(atf_equal_dynstr_cstring(ln, + basename(atf_dynstr_cstring(&p->m_data)))); +#endif /* defined(HAVE_CONST_BASENAME) */ + + return err; +} + +bool +atf_fs_path_is_absolute(const atf_fs_path_t *p) +{ + return atf_dynstr_cstring(&p->m_data)[0] == '/'; +} + +bool +atf_fs_path_is_root(const atf_fs_path_t *p) +{ + return atf_equal_dynstr_cstring(&p->m_data, "/"); +} + +/* + * Modifiers. + */ + +atf_error_t +atf_fs_path_append_ap(atf_fs_path_t *p, const char *fmt, va_list ap) +{ + atf_dynstr_t aux; + atf_error_t err; + va_list ap2; + + va_copy(ap2, ap); + err = normalize_ap(&aux, fmt, ap2); + va_end(ap2); + if (!atf_is_error(err)) { + const char *auxstr = atf_dynstr_cstring(&aux); + const bool needslash = auxstr[0] != '/'; + + err = atf_dynstr_append_fmt(&p->m_data, "%s%s", + needslash ? "/" : "", auxstr); + + atf_dynstr_fini(&aux); + } + + return err; +} + +atf_error_t +atf_fs_path_append_fmt(atf_fs_path_t *p, const char *fmt, ...) +{ + va_list ap; + atf_error_t err; + + va_start(ap, fmt); + err = atf_fs_path_append_ap(p, fmt, ap); + va_end(ap); + + return err; +} + +atf_error_t +atf_fs_path_append_path(atf_fs_path_t *p, const atf_fs_path_t *p2) +{ + return atf_fs_path_append_fmt(p, "%s", atf_dynstr_cstring(&p2->m_data)); +} + +atf_error_t +atf_fs_path_to_absolute(const atf_fs_path_t *p, atf_fs_path_t *pa) +{ + atf_error_t err; + + PRE(!atf_fs_path_is_absolute(p)); + + err = atf_fs_getcwd(pa); + if (atf_is_error(err)) + goto out; + + err = atf_fs_path_append_path(pa, p); + if (atf_is_error(err)) + atf_fs_path_fini(pa); + +out: + return err; +} + +/* + * Operators. + */ + +bool atf_equal_fs_path_fs_path(const atf_fs_path_t *p1, + const atf_fs_path_t *p2) +{ + return atf_equal_dynstr_dynstr(&p1->m_data, &p2->m_data); +} + +/* --------------------------------------------------------------------- + * The "atf_fs_path" type. + * --------------------------------------------------------------------- */ + +/* + * Constants. + */ + +const int atf_fs_stat_blk_type = 1; +const int atf_fs_stat_chr_type = 2; +const int atf_fs_stat_dir_type = 3; +const int atf_fs_stat_fifo_type = 4; +const int atf_fs_stat_lnk_type = 5; +const int atf_fs_stat_reg_type = 6; +const int atf_fs_stat_sock_type = 7; +const int atf_fs_stat_wht_type = 8; + +/* + * Constructors/destructors. + */ + +atf_error_t +atf_fs_stat_init(atf_fs_stat_t *st, const atf_fs_path_t *p) +{ + atf_error_t err; + const char *pstr = atf_fs_path_cstring(p); + + if (lstat(pstr, &st->m_sb) == -1) { + err = atf_libc_error(errno, "Cannot get information of %s; " + "lstat(2) failed", pstr); + } else { + int type = st->m_sb.st_mode & S_IFMT; + err = atf_no_error(); + switch (type) { + case S_IFBLK: st->m_type = atf_fs_stat_blk_type; break; + case S_IFCHR: st->m_type = atf_fs_stat_chr_type; break; + case S_IFDIR: st->m_type = atf_fs_stat_dir_type; break; + case S_IFIFO: st->m_type = atf_fs_stat_fifo_type; break; + case S_IFLNK: st->m_type = atf_fs_stat_lnk_type; break; + case S_IFREG: st->m_type = atf_fs_stat_reg_type; break; + case S_IFSOCK: st->m_type = atf_fs_stat_sock_type; break; +#if defined(S_IFWHT) + case S_IFWHT: st->m_type = atf_fs_stat_wht_type; break; +#endif + default: + err = unknown_type_error(pstr, type); + } + } + + return err; +} + +void +atf_fs_stat_copy(atf_fs_stat_t *dest, const atf_fs_stat_t *src) +{ + dest->m_type = src->m_type; + dest->m_sb = src->m_sb; +} + +void +atf_fs_stat_fini(atf_fs_stat_t *st ATF_DEFS_ATTRIBUTE_UNUSED) +{ +} + +/* + * Getters. + */ + +dev_t +atf_fs_stat_get_device(const atf_fs_stat_t *st) +{ + return st->m_sb.st_dev; +} + +ino_t +atf_fs_stat_get_inode(const atf_fs_stat_t *st) +{ + return st->m_sb.st_ino; +} + +mode_t +atf_fs_stat_get_mode(const atf_fs_stat_t *st) +{ + return st->m_sb.st_mode & ~S_IFMT; +} + +off_t +atf_fs_stat_get_size(const atf_fs_stat_t *st) +{ + return st->m_sb.st_size; +} + +int +atf_fs_stat_get_type(const atf_fs_stat_t *st) +{ + return st->m_type; +} + +bool +atf_fs_stat_is_owner_readable(const atf_fs_stat_t *st) +{ + return st->m_sb.st_mode & S_IRUSR; +} + +bool +atf_fs_stat_is_owner_writable(const atf_fs_stat_t *st) +{ + return st->m_sb.st_mode & S_IWUSR; +} + +bool +atf_fs_stat_is_owner_executable(const atf_fs_stat_t *st) +{ + return st->m_sb.st_mode & S_IXUSR; +} + +bool +atf_fs_stat_is_group_readable(const atf_fs_stat_t *st) +{ + return st->m_sb.st_mode & S_IRGRP; +} + +bool +atf_fs_stat_is_group_writable(const atf_fs_stat_t *st) +{ + return st->m_sb.st_mode & S_IWGRP; +} + +bool +atf_fs_stat_is_group_executable(const atf_fs_stat_t *st) +{ + return st->m_sb.st_mode & S_IXGRP; +} + +bool +atf_fs_stat_is_other_readable(const atf_fs_stat_t *st) +{ + return st->m_sb.st_mode & S_IROTH; +} + +bool +atf_fs_stat_is_other_writable(const atf_fs_stat_t *st) +{ + return st->m_sb.st_mode & S_IWOTH; +} + +bool +atf_fs_stat_is_other_executable(const atf_fs_stat_t *st) +{ + return st->m_sb.st_mode & S_IXOTH; +} + +/* --------------------------------------------------------------------- + * Free functions. + * --------------------------------------------------------------------- */ + +const int atf_fs_access_f = 1 << 0; +const int atf_fs_access_r = 1 << 1; +const int atf_fs_access_w = 1 << 2; +const int atf_fs_access_x = 1 << 3; + +/* + * An implementation of access(2) but using the effective user value + * instead of the real one. Also avoids false positives for root when + * asking for execute permissions, which appear in SunOS. + */ +atf_error_t +atf_fs_eaccess(const atf_fs_path_t *p, int mode) +{ + atf_error_t err; + struct stat st; + bool ok; + + PRE(mode & atf_fs_access_f || mode & atf_fs_access_r || + mode & atf_fs_access_w || mode & atf_fs_access_x); + + if (lstat(atf_fs_path_cstring(p), &st) == -1) { + err = atf_libc_error(errno, "Cannot get information from file %s", + atf_fs_path_cstring(p)); + goto out; + } + + err = atf_no_error(); + + /* Early return if we are only checking for existence and the file + * exists (stat call returned). */ + if (mode & atf_fs_access_f) + goto out; + + ok = false; + if (atf_user_is_root()) { + if (!ok && !(mode & atf_fs_access_x)) { + /* Allow root to read/write any file. */ + ok = true; + } + + if (!ok && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) { + /* Allow root to execute the file if any of its execution bits + * are set. */ + ok = true; + } + } else { + if (!ok && (atf_user_euid() == st.st_uid)) { + ok = ((mode & atf_fs_access_r) && (st.st_mode & S_IRUSR)) || + ((mode & atf_fs_access_w) && (st.st_mode & S_IWUSR)) || + ((mode & atf_fs_access_x) && (st.st_mode & S_IXUSR)); + } + if (!ok && atf_user_is_member_of_group(st.st_gid)) { + ok = ((mode & atf_fs_access_r) && (st.st_mode & S_IRGRP)) || + ((mode & atf_fs_access_w) && (st.st_mode & S_IWGRP)) || + ((mode & atf_fs_access_x) && (st.st_mode & S_IXGRP)); + } + if (!ok && ((atf_user_euid() != st.st_uid) && + !atf_user_is_member_of_group(st.st_gid))) { + ok = ((mode & atf_fs_access_r) && (st.st_mode & S_IROTH)) || + ((mode & atf_fs_access_w) && (st.st_mode & S_IWOTH)) || + ((mode & atf_fs_access_x) && (st.st_mode & S_IXOTH)); + } + } + + if (!ok) + err = atf_libc_error(EACCES, "Access check failed"); + +out: + return err; +} + +atf_error_t +atf_fs_exists(const atf_fs_path_t *p, bool *b) +{ + atf_error_t err; + + err = atf_fs_eaccess(p, atf_fs_access_f); + if (atf_is_error(err)) { + if (atf_error_is(err, "libc") && atf_libc_error_code(err) == ENOENT) { + atf_error_free(err); + err = atf_no_error(); + *b = false; + } + } else + *b = true; + + return err; +} + +atf_error_t +atf_fs_getcwd(atf_fs_path_t *p) +{ + atf_error_t err; + char *cwd; + +#if defined(HAVE_GETCWD_DYN) + cwd = getcwd(NULL, 0); +#else + cwd = getcwd(NULL, MAXPATHLEN); +#endif + if (cwd == NULL) { + err = atf_libc_error(errno, "Cannot determine current directory"); + goto out; + } + + err = atf_fs_path_init_fmt(p, "%s", cwd); + free(cwd); + +out: + return err; +} + +atf_error_t +atf_fs_mkdtemp(atf_fs_path_t *p) +{ + atf_error_t err; + char *buf; + + if (!check_umask(S_IRWXU, S_IRWXU)) { + err = invalid_umask_error(p, atf_fs_stat_dir_type, current_umask()); + goto out; + } + + err = copy_contents(p, &buf); + if (atf_is_error(err)) + goto out; + + err = do_mkdtemp(buf); + if (atf_is_error(err)) + goto out_buf; + + replace_contents(p, buf); + + INV(!atf_is_error(err)); +out_buf: + free(buf); +out: + return err; +} + +atf_error_t +atf_fs_mkstemp(atf_fs_path_t *p, int *fdout) +{ + atf_error_t err; + char *buf; + int fd; + + if (!check_umask(S_IRWXU, S_IRWXU)) { + err = invalid_umask_error(p, atf_fs_stat_reg_type, current_umask()); + goto out; + } + + err = copy_contents(p, &buf); + if (atf_is_error(err)) + goto out; + + err = do_mkstemp(buf, &fd); + if (atf_is_error(err)) + goto out_buf; + + replace_contents(p, buf); + *fdout = fd; + + INV(!atf_is_error(err)); +out_buf: + free(buf); +out: + return err; +} + +atf_error_t +atf_fs_rmdir(const atf_fs_path_t *p) +{ + atf_error_t err; + + if (rmdir(atf_fs_path_cstring(p))) { + if (errno == EEXIST) { + /* Some operating systems (e.g. OpenSolaris 200906) return + * EEXIST instead of ENOTEMPTY for non-empty directories. + * Homogenize the return value so that callers don't need + * to bother about differences in operating systems. */ + errno = ENOTEMPTY; + } + err = atf_libc_error(errno, "Cannot remove directory"); + } else + err = atf_no_error(); + + return err; +} + +atf_error_t +atf_fs_unlink(const atf_fs_path_t *p) +{ + atf_error_t err; + const char *path; + + path = atf_fs_path_cstring(p); + + if (unlink(path) != 0) + err = atf_libc_error(errno, "Cannot unlink file: '%s'", path); + else + err = atf_no_error(); + + return err; +} diff --git a/external/bsd/atf/dist/atf-c/detail/fs.h b/external/bsd/atf/dist/atf-c/detail/fs.h new file mode 100644 index 000000000..ec77c3bb7 --- /dev/null +++ b/external/bsd/atf/dist/atf-c/detail/fs.h @@ -0,0 +1,133 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if !defined(ATF_C_FS_H) +#define ATF_C_FS_H + +#include +#include + +#include +#include + +#include + +#include "dynstr.h" + +/* --------------------------------------------------------------------- + * The "atf_fs_path" type. + * --------------------------------------------------------------------- */ + +struct atf_fs_path { + atf_dynstr_t m_data; +}; +typedef struct atf_fs_path atf_fs_path_t; + +/* Constructors/destructors. */ +atf_error_t atf_fs_path_init_ap(atf_fs_path_t *, const char *, va_list); +atf_error_t atf_fs_path_init_fmt(atf_fs_path_t *, const char *, ...); +atf_error_t atf_fs_path_copy(atf_fs_path_t *, const atf_fs_path_t *); +void atf_fs_path_fini(atf_fs_path_t *); + +/* Getters. */ +atf_error_t atf_fs_path_branch_path(const atf_fs_path_t *, atf_fs_path_t *); +const char *atf_fs_path_cstring(const atf_fs_path_t *); +atf_error_t atf_fs_path_leaf_name(const atf_fs_path_t *, atf_dynstr_t *); +bool atf_fs_path_is_absolute(const atf_fs_path_t *); +bool atf_fs_path_is_root(const atf_fs_path_t *); + +/* Modifiers. */ +atf_error_t atf_fs_path_append_ap(atf_fs_path_t *, const char *, va_list); +atf_error_t atf_fs_path_append_fmt(atf_fs_path_t *, const char *, ...); +atf_error_t atf_fs_path_append_path(atf_fs_path_t *, const atf_fs_path_t *); +atf_error_t atf_fs_path_to_absolute(const atf_fs_path_t *, atf_fs_path_t *); + +/* Operators. */ +bool atf_equal_fs_path_fs_path(const atf_fs_path_t *, + const atf_fs_path_t *); + +/* --------------------------------------------------------------------- + * The "atf_fs_stat" type. + * --------------------------------------------------------------------- */ + +struct atf_fs_stat { + int m_type; + struct stat m_sb; +}; +typedef struct atf_fs_stat atf_fs_stat_t; + +/* Constants. */ +extern const int atf_fs_stat_blk_type; +extern const int atf_fs_stat_chr_type; +extern const int atf_fs_stat_dir_type; +extern const int atf_fs_stat_fifo_type; +extern const int atf_fs_stat_lnk_type; +extern const int atf_fs_stat_reg_type; +extern const int atf_fs_stat_sock_type; +extern const int atf_fs_stat_wht_type; + +/* Constructors/destructors. */ +atf_error_t atf_fs_stat_init(atf_fs_stat_t *, const atf_fs_path_t *); +void atf_fs_stat_copy(atf_fs_stat_t *, const atf_fs_stat_t *); +void atf_fs_stat_fini(atf_fs_stat_t *); + +/* Getters. */ +dev_t atf_fs_stat_get_device(const atf_fs_stat_t *); +ino_t atf_fs_stat_get_inode(const atf_fs_stat_t *); +mode_t atf_fs_stat_get_mode(const atf_fs_stat_t *); +off_t atf_fs_stat_get_size(const atf_fs_stat_t *); +int atf_fs_stat_get_type(const atf_fs_stat_t *); +bool atf_fs_stat_is_owner_readable(const atf_fs_stat_t *); +bool atf_fs_stat_is_owner_writable(const atf_fs_stat_t *); +bool atf_fs_stat_is_owner_executable(const atf_fs_stat_t *); +bool atf_fs_stat_is_group_readable(const atf_fs_stat_t *); +bool atf_fs_stat_is_group_writable(const atf_fs_stat_t *); +bool atf_fs_stat_is_group_executable(const atf_fs_stat_t *); +bool atf_fs_stat_is_other_readable(const atf_fs_stat_t *); +bool atf_fs_stat_is_other_writable(const atf_fs_stat_t *); +bool atf_fs_stat_is_other_executable(const atf_fs_stat_t *); + +/* --------------------------------------------------------------------- + * Free functions. + * --------------------------------------------------------------------- */ + +extern const int atf_fs_access_f; +extern const int atf_fs_access_r; +extern const int atf_fs_access_w; +extern const int atf_fs_access_x; + +atf_error_t atf_fs_eaccess(const atf_fs_path_t *, int); +atf_error_t atf_fs_exists(const atf_fs_path_t *, bool *); +atf_error_t atf_fs_getcwd(atf_fs_path_t *); +atf_error_t atf_fs_mkdtemp(atf_fs_path_t *); +atf_error_t atf_fs_mkstemp(atf_fs_path_t *, int *); +atf_error_t atf_fs_rmdir(const atf_fs_path_t *); +atf_error_t atf_fs_unlink(const atf_fs_path_t *); + +#endif /* !defined(ATF_C_FS_H) */ diff --git a/external/bsd/atf/dist/atf-c/detail/fs_test.c b/external/bsd/atf/dist/atf-c/detail/fs_test.c new file mode 100644 index 000000000..043304a0c --- /dev/null +++ b/external/bsd/atf/dist/atf-c/detail/fs_test.c @@ -0,0 +1,1082 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2007 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include "fs.h" +#include "test_helpers.h" +#include "user.h" + +/* --------------------------------------------------------------------- + * Auxiliary functions. + * --------------------------------------------------------------------- */ + +static +void +create_dir(const char *p, int mode) +{ + int ret; + + ret = mkdir(p, mode); + if (ret == -1) + atf_tc_fail("Could not create helper directory %s", p); +} + +static +void +create_file(const char *p, int mode) +{ + int fd; + + fd = open(p, O_CREAT | O_WRONLY | O_TRUNC, mode); + if (fd == -1) + atf_tc_fail("Could not create helper file %s", p); + close(fd); +} + +static +bool +exists(const atf_fs_path_t *p) +{ + return access(atf_fs_path_cstring(p), F_OK) == 0; +} + +static +atf_error_t +mkstemp_discard_fd(atf_fs_path_t *p) +{ + int fd; + atf_error_t err = atf_fs_mkstemp(p, &fd); + if (!atf_is_error(err)) + close(fd); + return err; +} + +/* --------------------------------------------------------------------- + * Test cases for the "atf_fs_path" type. + * --------------------------------------------------------------------- */ + +ATF_TC(path_normalize); +ATF_TC_HEAD(path_normalize, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the path's normalization"); +} +ATF_TC_BODY(path_normalize, tc) +{ + struct test { + const char *in; + const char *out; + } tests[] = { + { ".", ".", }, + { "..", "..", }, + + { "/", "/", }, + { "//", "/", }, /* NO_CHECK_STYLE */ + { "///", "/", }, /* NO_CHECK_STYLE */ + + { "foo", "foo", }, + { "foo/", "foo", }, + { "foo/bar", "foo/bar", }, + { "foo/bar/", "foo/bar", }, + + { "/foo", "/foo", }, + { "/foo/bar", "/foo/bar", }, + { "/foo/bar/", "/foo/bar", }, + + { "///foo", "/foo", }, /* NO_CHECK_STYLE */ + { "///foo///bar", "/foo/bar", }, /* NO_CHECK_STYLE */ + { "///foo///bar///", "/foo/bar", }, /* NO_CHECK_STYLE */ + + { NULL, NULL } + }; + struct test *t; + + for (t = &tests[0]; t->in != NULL; t++) { + atf_fs_path_t p; + + printf("Input : >%s<\n", t->in); + printf("Expected output: >%s<\n", t->out); + + RE(atf_fs_path_init_fmt(&p, "%s", t->in)); + printf("Output : >%s<\n", atf_fs_path_cstring(&p)); + ATF_REQUIRE(strcmp(atf_fs_path_cstring(&p), t->out) == 0); + atf_fs_path_fini(&p); + + printf("\n"); + } +} + +ATF_TC(path_copy); +ATF_TC_HEAD(path_copy, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_path_copy constructor"); +} +ATF_TC_BODY(path_copy, tc) +{ + atf_fs_path_t str, str2; + + RE(atf_fs_path_init_fmt(&str, "foo")); + RE(atf_fs_path_copy(&str2, &str)); + + ATF_REQUIRE(atf_equal_fs_path_fs_path(&str, &str2)); + + RE(atf_fs_path_append_fmt(&str2, "bar")); + + ATF_REQUIRE(!atf_equal_fs_path_fs_path(&str, &str2)); + + atf_fs_path_fini(&str2); + atf_fs_path_fini(&str); +} + +ATF_TC(path_is_absolute); +ATF_TC_HEAD(path_is_absolute, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the path::is_absolute function"); +} +ATF_TC_BODY(path_is_absolute, tc) +{ + struct test { + const char *in; + bool abs; + } tests[] = { + { "/", true }, + { "////", true }, /* NO_CHECK_STYLE */ + { "////a", true }, /* NO_CHECK_STYLE */ + { "//a//", true }, /* NO_CHECK_STYLE */ + { "a////", false }, /* NO_CHECK_STYLE */ + { "../foo", false }, + { NULL, false }, + }; + struct test *t; + + for (t = &tests[0]; t->in != NULL; t++) { + atf_fs_path_t p; + + printf("Input : %s\n", t->in); + printf("Expected result: %s\n", t->abs ? "true" : "false"); + + RE(atf_fs_path_init_fmt(&p, "%s", t->in)); + printf("Result : %s\n", + atf_fs_path_is_absolute(&p) ? "true" : "false"); + if (t->abs) + ATF_REQUIRE(atf_fs_path_is_absolute(&p)); + else + ATF_REQUIRE(!atf_fs_path_is_absolute(&p)); + atf_fs_path_fini(&p); + + printf("\n"); + } +} + +ATF_TC(path_is_root); +ATF_TC_HEAD(path_is_root, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the path::is_root function"); +} +ATF_TC_BODY(path_is_root, tc) +{ + struct test { + const char *in; + bool root; + } tests[] = { + { "/", true }, + { "////", true }, /* NO_CHECK_STYLE */ + { "////a", false }, /* NO_CHECK_STYLE */ + { "//a//", false }, /* NO_CHECK_STYLE */ + { "a////", false }, /* NO_CHECK_STYLE */ + { "../foo", false }, + { NULL, false }, + }; + struct test *t; + + for (t = &tests[0]; t->in != NULL; t++) { + atf_fs_path_t p; + + printf("Input : %s\n", t->in); + printf("Expected result: %s\n", t->root ? "true" : "false"); + + RE(atf_fs_path_init_fmt(&p, "%s", t->in)); + printf("Result : %s\n", + atf_fs_path_is_root(&p) ? "true" : "false"); + if (t->root) + ATF_REQUIRE(atf_fs_path_is_root(&p)); + else + ATF_REQUIRE(!atf_fs_path_is_root(&p)); + atf_fs_path_fini(&p); + + printf("\n"); + } +} + +ATF_TC(path_branch_path); +ATF_TC_HEAD(path_branch_path, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_path_branch_path " + "function"); +} +ATF_TC_BODY(path_branch_path, tc) +{ + struct test { + const char *in; + const char *branch; + } tests[] = { + { ".", "." }, + { "foo", "." }, + { "foo/bar", "foo" }, + { "/foo", "/" }, + { "/foo/bar", "/foo" }, + { NULL, NULL }, + }; + struct test *t; + + for (t = &tests[0]; t->in != NULL; t++) { + atf_fs_path_t p, bp; + + printf("Input : %s\n", t->in); + printf("Expected output: %s\n", t->branch); + + RE(atf_fs_path_init_fmt(&p, "%s", t->in)); + RE(atf_fs_path_branch_path(&p, &bp)); + printf("Output : %s\n", atf_fs_path_cstring(&bp)); + ATF_REQUIRE(strcmp(atf_fs_path_cstring(&bp), t->branch) == 0); + atf_fs_path_fini(&bp); + atf_fs_path_fini(&p); + + printf("\n"); + } +} + +ATF_TC(path_leaf_name); +ATF_TC_HEAD(path_leaf_name, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_path_leaf_name " + "function"); +} +ATF_TC_BODY(path_leaf_name, tc) +{ + struct test { + const char *in; + const char *leaf; + } tests[] = { + { ".", "." }, + { "foo", "foo" }, + { "foo/bar", "bar" }, + { "/foo", "foo" }, + { "/foo/bar", "bar" }, + { NULL, NULL }, + }; + struct test *t; + + for (t = &tests[0]; t->in != NULL; t++) { + atf_fs_path_t p; + atf_dynstr_t ln; + + printf("Input : %s\n", t->in); + printf("Expected output: %s\n", t->leaf); + + RE(atf_fs_path_init_fmt(&p, "%s", t->in)); + RE(atf_fs_path_leaf_name(&p, &ln)); + printf("Output : %s\n", atf_dynstr_cstring(&ln)); + ATF_REQUIRE(atf_equal_dynstr_cstring(&ln, t->leaf)); + atf_dynstr_fini(&ln); + atf_fs_path_fini(&p); + + printf("\n"); + } +} + +ATF_TC(path_append); +ATF_TC_HEAD(path_append, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the concatenation of multiple " + "paths"); +} +ATF_TC_BODY(path_append, tc) +{ + struct test { + const char *in; + const char *ap; + const char *out; + } tests[] = { + { "foo", "bar", "foo/bar" }, + { "foo/", "/bar", "foo/bar" }, + { "foo/", "/bar/baz", "foo/bar/baz" }, + { "foo/", "///bar///baz", "foo/bar/baz" }, /* NO_CHECK_STYLE */ + + { NULL, NULL, NULL } + }; + struct test *t; + + for (t = &tests[0]; t->in != NULL; t++) { + atf_fs_path_t p; + + printf("Input : >%s<\n", t->in); + printf("Append : >%s<\n", t->ap); + printf("Expected output: >%s<\n", t->out); + + RE(atf_fs_path_init_fmt(&p, "%s", t->in)); + + RE(atf_fs_path_append_fmt(&p, "%s", t->ap)); + + printf("Output : >%s<\n", atf_fs_path_cstring(&p)); + ATF_REQUIRE(strcmp(atf_fs_path_cstring(&p), t->out) == 0); + + atf_fs_path_fini(&p); + + printf("\n"); + } +} + +ATF_TC(path_to_absolute); +ATF_TC_HEAD(path_to_absolute, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_path_to_absolute " + "function"); +} +ATF_TC_BODY(path_to_absolute, tc) +{ + const char *names[] = { ".", "dir", NULL }; + const char **n; + + ATF_REQUIRE(mkdir("dir", 0755) != -1); + + for (n = names; *n != NULL; n++) { + atf_fs_path_t p, p2; + atf_fs_stat_t st1, st2; + + RE(atf_fs_path_init_fmt(&p, "%s", *n)); + RE(atf_fs_stat_init(&st1, &p)); + printf("Relative path: %s\n", atf_fs_path_cstring(&p)); + + RE(atf_fs_path_to_absolute(&p, &p2)); + printf("Absolute path: %s\n", atf_fs_path_cstring(&p2)); + + ATF_REQUIRE(atf_fs_path_is_absolute(&p2)); + RE(atf_fs_stat_init(&st2, &p2)); + + ATF_REQUIRE_EQ(atf_fs_stat_get_device(&st1), + atf_fs_stat_get_device(&st2)); + ATF_REQUIRE_EQ(atf_fs_stat_get_inode(&st1), + atf_fs_stat_get_inode(&st2)); + + atf_fs_stat_fini(&st2); + atf_fs_stat_fini(&st1); + atf_fs_path_fini(&p2); + atf_fs_path_fini(&p); + + printf("\n"); + } +} + +ATF_TC(path_equal); +ATF_TC_HEAD(path_equal, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the equality operators for paths"); +} +ATF_TC_BODY(path_equal, tc) +{ + atf_fs_path_t p1, p2; + + RE(atf_fs_path_init_fmt(&p1, "foo")); + + RE(atf_fs_path_init_fmt(&p2, "foo")); + ATF_REQUIRE(atf_equal_fs_path_fs_path(&p1, &p2)); + atf_fs_path_fini(&p2); + + RE(atf_fs_path_init_fmt(&p2, "bar")); + ATF_REQUIRE(!atf_equal_fs_path_fs_path(&p1, &p2)); + atf_fs_path_fini(&p2); + + atf_fs_path_fini(&p1); +} + +/* --------------------------------------------------------------------- + * Test cases for the "atf_fs_stat" type. + * --------------------------------------------------------------------- */ + +ATF_TC(stat_mode); +ATF_TC_HEAD(stat_mode, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_stat_get_mode function " + "and, indirectly, the constructor"); +} +ATF_TC_BODY(stat_mode, tc) +{ + atf_fs_path_t p; + atf_fs_stat_t st; + + create_file("f1", 0400); + create_file("f2", 0644); + + RE(atf_fs_path_init_fmt(&p, "f1")); + RE(atf_fs_stat_init(&st, &p)); + ATF_CHECK_EQ(0400, atf_fs_stat_get_mode(&st)); + atf_fs_stat_fini(&st); + atf_fs_path_fini(&p); + + RE(atf_fs_path_init_fmt(&p, "f2")); + RE(atf_fs_stat_init(&st, &p)); + ATF_CHECK_EQ(0644, atf_fs_stat_get_mode(&st)); + atf_fs_stat_fini(&st); + atf_fs_path_fini(&p); +} + +ATF_TC(stat_type); +ATF_TC_HEAD(stat_type, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_stat_get_type function " + "and, indirectly, the constructor"); +} +ATF_TC_BODY(stat_type, tc) +{ + atf_fs_path_t p; + atf_fs_stat_t st; + + create_dir("dir", 0755); + create_file("reg", 0644); + + RE(atf_fs_path_init_fmt(&p, "dir")); + RE(atf_fs_stat_init(&st, &p)); + ATF_REQUIRE_EQ(atf_fs_stat_get_type(&st), atf_fs_stat_dir_type); + atf_fs_stat_fini(&st); + atf_fs_path_fini(&p); + + RE(atf_fs_path_init_fmt(&p, "reg")); + RE(atf_fs_stat_init(&st, &p)); + ATF_REQUIRE_EQ(atf_fs_stat_get_type(&st), atf_fs_stat_reg_type); + atf_fs_stat_fini(&st); + atf_fs_path_fini(&p); +} + +ATF_TC(stat_perms); +ATF_TC_HEAD(stat_perms, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_stat_is_* functions"); +} +ATF_TC_BODY(stat_perms, tc) +{ + atf_fs_path_t p; + atf_fs_stat_t st; + + create_file("reg", 0); + + RE(atf_fs_path_init_fmt(&p, "reg")); + +#define perms(ur, uw, ux, gr, gw, gx, othr, othw, othx) \ + { \ + RE(atf_fs_stat_init(&st, &p)); \ + ATF_REQUIRE(atf_fs_stat_is_owner_readable(&st) == ur); \ + ATF_REQUIRE(atf_fs_stat_is_owner_writable(&st) == uw); \ + ATF_REQUIRE(atf_fs_stat_is_owner_executable(&st) == ux); \ + ATF_REQUIRE(atf_fs_stat_is_group_readable(&st) == gr); \ + ATF_REQUIRE(atf_fs_stat_is_group_writable(&st) == gw); \ + ATF_REQUIRE(atf_fs_stat_is_group_executable(&st) == gx); \ + ATF_REQUIRE(atf_fs_stat_is_other_readable(&st) == othr); \ + ATF_REQUIRE(atf_fs_stat_is_other_writable(&st) == othw); \ + ATF_REQUIRE(atf_fs_stat_is_other_executable(&st) == othx); \ + atf_fs_stat_fini(&st); \ + } + + chmod("reg", 0000); + perms(false, false, false, false, false, false, false, false, false); + + chmod("reg", 0001); + perms(false, false, false, false, false, false, false, false, true); + + chmod("reg", 0010); + perms(false, false, false, false, false, true, false, false, false); + + chmod("reg", 0100); + perms(false, false, true, false, false, false, false, false, false); + + chmod("reg", 0002); + perms(false, false, false, false, false, false, false, true, false); + + chmod("reg", 0020); + perms(false, false, false, false, true, false, false, false, false); + + chmod("reg", 0200); + perms(false, true, false, false, false, false, false, false, false); + + chmod("reg", 0004); + perms(false, false, false, false, false, false, true, false, false); + + chmod("reg", 0040); + perms(false, false, false, true, false, false, false, false, false); + + chmod("reg", 0400); + perms(true, false, false, false, false, false, false, false, false); + + chmod("reg", 0644); + perms(true, true, false, true, false, false, true, false, false); + + chmod("reg", 0755); + perms(true, true, true, true, false, true, true, false, true); + + chmod("reg", 0777); + perms(true, true, true, true, true, true, true, true, true); + +#undef perms + + atf_fs_path_fini(&p); +} + +/* --------------------------------------------------------------------- + * Test cases for the free functions. + * --------------------------------------------------------------------- */ + +ATF_TC(exists); +ATF_TC_HEAD(exists, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_exists function"); +} +ATF_TC_BODY(exists, tc) +{ + atf_error_t err; + atf_fs_path_t pdir, pfile; + bool b; + + RE(atf_fs_path_init_fmt(&pdir, "dir")); + RE(atf_fs_path_init_fmt(&pfile, "dir/file")); + + create_dir(atf_fs_path_cstring(&pdir), 0755); + create_file(atf_fs_path_cstring(&pfile), 0644); + + printf("Checking existence of a directory\n"); + RE(atf_fs_exists(&pdir, &b)); + ATF_REQUIRE(b); + + printf("Checking existence of a file\n"); + RE(atf_fs_exists(&pfile, &b)); + ATF_REQUIRE(b); + + /* XXX: This should probably be a separate test case to let the user + * be aware that some tests were skipped because privileges were not + * correct. */ + if (!atf_user_is_root()) { + printf("Checking existence of a file inside a directory without " + "permissions\n"); + ATF_REQUIRE(chmod(atf_fs_path_cstring(&pdir), 0000) != -1); + err = atf_fs_exists(&pfile, &b); + ATF_REQUIRE(atf_is_error(err)); + ATF_REQUIRE(atf_error_is(err, "libc")); + ATF_REQUIRE(chmod(atf_fs_path_cstring(&pdir), 0755) != -1); + atf_error_free(err); + } + + printf("Checking existence of a non-existent file\n"); + ATF_REQUIRE(unlink(atf_fs_path_cstring(&pfile)) != -1); + RE(atf_fs_exists(&pfile, &b)); + ATF_REQUIRE(!b); + + atf_fs_path_fini(&pfile); + atf_fs_path_fini(&pdir); +} + +ATF_TC(eaccess); +ATF_TC_HEAD(eaccess, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_eaccess function"); +} +ATF_TC_BODY(eaccess, tc) +{ + const int modes[] = { atf_fs_access_f, atf_fs_access_r, atf_fs_access_w, + atf_fs_access_x, 0 }; + const int *m; + struct tests { + mode_t fmode; + int amode; + int uerror; + int rerror; + } tests[] = { + { 0000, atf_fs_access_r, EACCES, 0 }, + { 0000, atf_fs_access_w, EACCES, 0 }, + { 0000, atf_fs_access_x, EACCES, EACCES }, + + { 0001, atf_fs_access_r, EACCES, 0 }, + { 0001, atf_fs_access_w, EACCES, 0 }, + { 0001, atf_fs_access_x, EACCES, 0 }, + { 0002, atf_fs_access_r, EACCES, 0 }, + { 0002, atf_fs_access_w, EACCES, 0 }, + { 0002, atf_fs_access_x, EACCES, EACCES }, + { 0004, atf_fs_access_r, EACCES, 0 }, + { 0004, atf_fs_access_w, EACCES, 0 }, + { 0004, atf_fs_access_x, EACCES, EACCES }, + + { 0010, atf_fs_access_r, EACCES, 0 }, + { 0010, atf_fs_access_w, EACCES, 0 }, + { 0010, atf_fs_access_x, 0, 0 }, + { 0020, atf_fs_access_r, EACCES, 0 }, + { 0020, atf_fs_access_w, 0, 0 }, + { 0020, atf_fs_access_x, EACCES, EACCES }, + { 0040, atf_fs_access_r, 0, 0 }, + { 0040, atf_fs_access_w, EACCES, 0 }, + { 0040, atf_fs_access_x, EACCES, EACCES }, + + { 0100, atf_fs_access_r, EACCES, 0 }, + { 0100, atf_fs_access_w, EACCES, 0 }, + { 0100, atf_fs_access_x, 0, 0 }, + { 0200, atf_fs_access_r, EACCES, 0 }, + { 0200, atf_fs_access_w, 0, 0 }, + { 0200, atf_fs_access_x, EACCES, EACCES }, + { 0400, atf_fs_access_r, 0, 0 }, + { 0400, atf_fs_access_w, EACCES, 0 }, + { 0400, atf_fs_access_x, EACCES, EACCES }, + + { 0, 0, 0, 0 } + }; + struct tests *t; + atf_fs_path_t p; + atf_error_t err; + + RE(atf_fs_path_init_fmt(&p, "the-file")); + + printf("Non-existent file checks\n"); + for (m = &modes[0]; *m != 0; m++) { + err = atf_fs_eaccess(&p, *m); + ATF_REQUIRE(atf_is_error(err)); + ATF_REQUIRE(atf_error_is(err, "libc")); + ATF_REQUIRE_EQ(atf_libc_error_code(err), ENOENT); + atf_error_free(err); + } + + create_file(atf_fs_path_cstring(&p), 0000); + ATF_REQUIRE(chown(atf_fs_path_cstring(&p), geteuid(), getegid()) != -1); + + for (t = &tests[0]; t->amode != 0; t++) { + const int experr = atf_user_is_root() ? t->rerror : t->uerror; + + printf("\n"); + printf("File mode : %04o\n", (unsigned int)t->fmode); + printf("Access mode : 0x%02x\n", t->amode); + + ATF_REQUIRE(chmod(atf_fs_path_cstring(&p), t->fmode) != -1); + + /* First, existence check. */ + err = atf_fs_eaccess(&p, atf_fs_access_f); + ATF_REQUIRE(!atf_is_error(err)); + + /* Now do the specific test case. */ + printf("Expected error: %d\n", experr); + err = atf_fs_eaccess(&p, t->amode); + if (atf_is_error(err)) { + if (atf_error_is(err, "libc")) + printf("Error : %d\n", atf_libc_error_code(err)); + else + printf("Error : Non-libc error\n"); + } else + printf("Error : None\n"); + if (experr == 0) { + ATF_REQUIRE(!atf_is_error(err)); + } else { + ATF_REQUIRE(atf_is_error(err)); + ATF_REQUIRE(atf_error_is(err, "libc")); + ATF_REQUIRE_EQ(atf_libc_error_code(err), experr); + atf_error_free(err); + } + } + + atf_fs_path_fini(&p); +} + +ATF_TC(getcwd); +ATF_TC_HEAD(getcwd, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_getcwd function"); +} +ATF_TC_BODY(getcwd, tc) +{ + atf_fs_path_t cwd1, cwd2; + + create_dir ("root", 0755); + + RE(atf_fs_getcwd(&cwd1)); + ATF_REQUIRE(chdir("root") != -1); + RE(atf_fs_getcwd(&cwd2)); + + RE(atf_fs_path_append_fmt(&cwd1, "root")); + + ATF_REQUIRE(atf_equal_fs_path_fs_path(&cwd1, &cwd2)); + + atf_fs_path_fini(&cwd2); + atf_fs_path_fini(&cwd1); +} + +ATF_TC(rmdir_empty); +ATF_TC_HEAD(rmdir_empty, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_rmdir function"); +} +ATF_TC_BODY(rmdir_empty, tc) +{ + atf_fs_path_t p; + + RE(atf_fs_path_init_fmt(&p, "test-dir")); + + ATF_REQUIRE(mkdir("test-dir", 0755) != -1); + ATF_REQUIRE(exists(&p)); + RE(atf_fs_rmdir(&p)); + ATF_REQUIRE(!exists(&p)); + + atf_fs_path_fini(&p); +} + +ATF_TC(rmdir_enotempty); +ATF_TC_HEAD(rmdir_enotempty, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_rmdir function"); +} +ATF_TC_BODY(rmdir_enotempty, tc) +{ + atf_fs_path_t p; + atf_error_t err; + + RE(atf_fs_path_init_fmt(&p, "test-dir")); + + ATF_REQUIRE(mkdir("test-dir", 0755) != -1); + ATF_REQUIRE(exists(&p)); + create_file("test-dir/foo", 0644); + + err = atf_fs_rmdir(&p); + ATF_REQUIRE(atf_is_error(err)); + ATF_REQUIRE(atf_error_is(err, "libc")); + ATF_REQUIRE_EQ(atf_libc_error_code(err), ENOTEMPTY); + atf_error_free(err); + + atf_fs_path_fini(&p); +} + +ATF_TC(rmdir_eperm); +ATF_TC_HEAD(rmdir_eperm, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_rmdir function"); +} +ATF_TC_BODY(rmdir_eperm, tc) +{ + atf_fs_path_t p; + atf_error_t err; + + RE(atf_fs_path_init_fmt(&p, "test-dir/foo")); + + ATF_REQUIRE(mkdir("test-dir", 0755) != -1); + ATF_REQUIRE(mkdir("test-dir/foo", 0755) != -1); + ATF_REQUIRE(chmod("test-dir", 0555) != -1); + ATF_REQUIRE(exists(&p)); + + err = atf_fs_rmdir(&p); + if (atf_user_is_root()) { + ATF_REQUIRE(!atf_is_error(err)); + } else { + ATF_REQUIRE(atf_is_error(err)); + ATF_REQUIRE(atf_error_is(err, "libc")); + ATF_REQUIRE_EQ(atf_libc_error_code(err), EACCES); + atf_error_free(err); + } + + atf_fs_path_fini(&p); +} + +ATF_TC(mkdtemp_ok); +ATF_TC_HEAD(mkdtemp_ok, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_mkdtemp function, " + "successful execution"); +} +ATF_TC_BODY(mkdtemp_ok, tc) +{ + atf_fs_path_t p1, p2; + atf_fs_stat_t s1, s2; + + RE(atf_fs_path_init_fmt(&p1, "testdir.XXXXXX")); + RE(atf_fs_path_init_fmt(&p2, "testdir.XXXXXX")); + RE(atf_fs_mkdtemp(&p1)); + RE(atf_fs_mkdtemp(&p2)); + ATF_REQUIRE(!atf_equal_fs_path_fs_path(&p1, &p2)); + ATF_REQUIRE(exists(&p1)); + ATF_REQUIRE(exists(&p2)); + + RE(atf_fs_stat_init(&s1, &p1)); + ATF_REQUIRE_EQ(atf_fs_stat_get_type(&s1), atf_fs_stat_dir_type); + ATF_REQUIRE( atf_fs_stat_is_owner_readable(&s1)); + ATF_REQUIRE( atf_fs_stat_is_owner_writable(&s1)); + ATF_REQUIRE( atf_fs_stat_is_owner_executable(&s1)); + ATF_REQUIRE(!atf_fs_stat_is_group_readable(&s1)); + ATF_REQUIRE(!atf_fs_stat_is_group_writable(&s1)); + ATF_REQUIRE(!atf_fs_stat_is_group_executable(&s1)); + ATF_REQUIRE(!atf_fs_stat_is_other_readable(&s1)); + ATF_REQUIRE(!atf_fs_stat_is_other_writable(&s1)); + ATF_REQUIRE(!atf_fs_stat_is_other_executable(&s1)); + + RE(atf_fs_stat_init(&s2, &p2)); + ATF_REQUIRE_EQ(atf_fs_stat_get_type(&s2), atf_fs_stat_dir_type); + ATF_REQUIRE( atf_fs_stat_is_owner_readable(&s2)); + ATF_REQUIRE( atf_fs_stat_is_owner_writable(&s2)); + ATF_REQUIRE( atf_fs_stat_is_owner_executable(&s2)); + ATF_REQUIRE(!atf_fs_stat_is_group_readable(&s2)); + ATF_REQUIRE(!atf_fs_stat_is_group_writable(&s2)); + ATF_REQUIRE(!atf_fs_stat_is_group_executable(&s2)); + ATF_REQUIRE(!atf_fs_stat_is_other_readable(&s2)); + ATF_REQUIRE(!atf_fs_stat_is_other_writable(&s2)); + ATF_REQUIRE(!atf_fs_stat_is_other_executable(&s2)); + + atf_fs_stat_fini(&s2); + atf_fs_stat_fini(&s1); + atf_fs_path_fini(&p2); + atf_fs_path_fini(&p1); +} + +ATF_TC(mkdtemp_err); +ATF_TC_HEAD(mkdtemp_err, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_mkdtemp function, " + "error conditions"); + atf_tc_set_md_var(tc, "require.user", "unprivileged"); +} +ATF_TC_BODY(mkdtemp_err, tc) +{ + atf_error_t err; + atf_fs_path_t p; + + ATF_REQUIRE(mkdir("dir", 0555) != -1); + + RE(atf_fs_path_init_fmt(&p, "dir/testdir.XXXXXX")); + + err = atf_fs_mkdtemp(&p); + ATF_REQUIRE(atf_is_error(err)); + ATF_REQUIRE(atf_error_is(err, "libc")); + ATF_CHECK_EQ(atf_libc_error_code(err), EACCES); + atf_error_free(err); + + ATF_CHECK(!exists(&p)); + ATF_CHECK(strcmp(atf_fs_path_cstring(&p), "dir/testdir.XXXXXX") == 0); + + atf_fs_path_fini(&p); +} + +static +void +do_umask_check(atf_error_t (*const mk_func)(atf_fs_path_t *), + atf_fs_path_t *path, const mode_t test_mask, + const char *str_mask, const char *exp_name) +{ + char buf[1024]; + int old_umask; + atf_error_t err; + + printf("Creating temporary %s with umask %s\n", exp_name, str_mask); + + old_umask = umask(test_mask); + err = mk_func(path); + (void)umask(old_umask); + + ATF_REQUIRE(atf_is_error(err)); + ATF_REQUIRE(atf_error_is(err, "invalid_umask")); + atf_error_format(err, buf, sizeof(buf)); + ATF_CHECK(strstr(buf, exp_name) != NULL); + ATF_CHECK(strstr(buf, str_mask) != NULL); + atf_error_free(err); +} + +ATF_TC(mkdtemp_umask); +ATF_TC_HEAD(mkdtemp_umask, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_mkdtemp function " + "causing an error due to a too strict umask"); +} +ATF_TC_BODY(mkdtemp_umask, tc) +{ + atf_fs_path_t p; + + RE(atf_fs_path_init_fmt(&p, "testdir.XXXXXX")); + + do_umask_check(atf_fs_mkdtemp, &p, 00100, "00100", "directory"); + do_umask_check(atf_fs_mkdtemp, &p, 00200, "00200", "directory"); + do_umask_check(atf_fs_mkdtemp, &p, 00400, "00400", "directory"); + do_umask_check(atf_fs_mkdtemp, &p, 00500, "00500", "directory"); + do_umask_check(atf_fs_mkdtemp, &p, 00600, "00600", "directory"); + + atf_fs_path_fini(&p); +} + +ATF_TC(mkstemp_ok); +ATF_TC_HEAD(mkstemp_ok, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_mkstemp function, " + "successful execution"); +} +ATF_TC_BODY(mkstemp_ok, tc) +{ + int fd1, fd2; + atf_fs_path_t p1, p2; + atf_fs_stat_t s1, s2; + + RE(atf_fs_path_init_fmt(&p1, "testfile.XXXXXX")); + RE(atf_fs_path_init_fmt(&p2, "testfile.XXXXXX")); + fd1 = fd2 = -1; + RE(atf_fs_mkstemp(&p1, &fd1)); + RE(atf_fs_mkstemp(&p2, &fd2)); + ATF_REQUIRE(!atf_equal_fs_path_fs_path(&p1, &p2)); + ATF_REQUIRE(exists(&p1)); + ATF_REQUIRE(exists(&p2)); + + ATF_CHECK(fd1 != -1); + ATF_CHECK(fd2 != -1); + ATF_CHECK(write(fd1, "foo", 3) == 3); + ATF_CHECK(write(fd2, "bar", 3) == 3); + close(fd1); + close(fd2); + + RE(atf_fs_stat_init(&s1, &p1)); + ATF_CHECK_EQ(atf_fs_stat_get_type(&s1), atf_fs_stat_reg_type); + ATF_CHECK( atf_fs_stat_is_owner_readable(&s1)); + ATF_CHECK( atf_fs_stat_is_owner_writable(&s1)); + ATF_CHECK(!atf_fs_stat_is_owner_executable(&s1)); + ATF_CHECK(!atf_fs_stat_is_group_readable(&s1)); + ATF_CHECK(!atf_fs_stat_is_group_writable(&s1)); + ATF_CHECK(!atf_fs_stat_is_group_executable(&s1)); + ATF_CHECK(!atf_fs_stat_is_other_readable(&s1)); + ATF_CHECK(!atf_fs_stat_is_other_writable(&s1)); + ATF_CHECK(!atf_fs_stat_is_other_executable(&s1)); + + RE(atf_fs_stat_init(&s2, &p2)); + ATF_CHECK_EQ(atf_fs_stat_get_type(&s2), atf_fs_stat_reg_type); + ATF_CHECK( atf_fs_stat_is_owner_readable(&s2)); + ATF_CHECK( atf_fs_stat_is_owner_writable(&s2)); + ATF_CHECK(!atf_fs_stat_is_owner_executable(&s2)); + ATF_CHECK(!atf_fs_stat_is_group_readable(&s2)); + ATF_CHECK(!atf_fs_stat_is_group_writable(&s2)); + ATF_CHECK(!atf_fs_stat_is_group_executable(&s2)); + ATF_CHECK(!atf_fs_stat_is_other_readable(&s2)); + ATF_CHECK(!atf_fs_stat_is_other_writable(&s2)); + ATF_CHECK(!atf_fs_stat_is_other_executable(&s2)); + + atf_fs_stat_fini(&s2); + atf_fs_stat_fini(&s1); + atf_fs_path_fini(&p2); + atf_fs_path_fini(&p1); +} + +ATF_TC(mkstemp_err); +ATF_TC_HEAD(mkstemp_err, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_mkstemp function, " + "error conditions"); + atf_tc_set_md_var(tc, "require.user", "unprivileged"); +} +ATF_TC_BODY(mkstemp_err, tc) +{ + int fd; + atf_error_t err; + atf_fs_path_t p; + + ATF_REQUIRE(mkdir("dir", 0555) != -1); + + RE(atf_fs_path_init_fmt(&p, "dir/testfile.XXXXXX")); + fd = 1234; + + err = atf_fs_mkstemp(&p, &fd); + ATF_REQUIRE(atf_is_error(err)); + ATF_REQUIRE(atf_error_is(err, "libc")); + ATF_CHECK_EQ(atf_libc_error_code(err), EACCES); + atf_error_free(err); + + ATF_CHECK(!exists(&p)); + ATF_CHECK(strcmp(atf_fs_path_cstring(&p), "dir/testfile.XXXXXX") == 0); + ATF_CHECK_EQ(fd, 1234); + + atf_fs_path_fini(&p); +} + +ATF_TC(mkstemp_umask); +ATF_TC_HEAD(mkstemp_umask, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the atf_fs_mkstemp function " + "causing an error due to a too strict umask"); +} +ATF_TC_BODY(mkstemp_umask, tc) +{ + atf_fs_path_t p; + + RE(atf_fs_path_init_fmt(&p, "testfile.XXXXXX")); + + do_umask_check(mkstemp_discard_fd, &p, 00100, "00100", "regular file"); + do_umask_check(mkstemp_discard_fd, &p, 00200, "00200", "regular file"); + do_umask_check(mkstemp_discard_fd, &p, 00400, "00400", "regular file"); + + atf_fs_path_fini(&p); +} + +/* --------------------------------------------------------------------- + * Main. + * --------------------------------------------------------------------- */ + +ATF_TP_ADD_TCS(tp) +{ + /* Add the tests for the "atf_fs_path" type. */ + ATF_TP_ADD_TC(tp, path_normalize); + ATF_TP_ADD_TC(tp, path_copy); + ATF_TP_ADD_TC(tp, path_is_absolute); + ATF_TP_ADD_TC(tp, path_is_root); + ATF_TP_ADD_TC(tp, path_branch_path); + ATF_TP_ADD_TC(tp, path_leaf_name); + ATF_TP_ADD_TC(tp, path_append); + ATF_TP_ADD_TC(tp, path_to_absolute); + ATF_TP_ADD_TC(tp, path_equal); + + /* Add the tests for the "atf_fs_stat" type. */ + ATF_TP_ADD_TC(tp, stat_mode); + ATF_TP_ADD_TC(tp, stat_type); + ATF_TP_ADD_TC(tp, stat_perms); + + /* Add the tests for the free functions. */ + ATF_TP_ADD_TC(tp, eaccess); + ATF_TP_ADD_TC(tp, exists); + ATF_TP_ADD_TC(tp, getcwd); + ATF_TP_ADD_TC(tp, rmdir_empty); + ATF_TP_ADD_TC(tp, rmdir_enotempty); + ATF_TP_ADD_TC(tp, rmdir_eperm); + ATF_TP_ADD_TC(tp, mkdtemp_ok); + ATF_TP_ADD_TC(tp, mkdtemp_err); + ATF_TP_ADD_TC(tp, mkdtemp_umask); + ATF_TP_ADD_TC(tp, mkstemp_ok); + ATF_TP_ADD_TC(tp, mkstemp_err); + ATF_TP_ADD_TC(tp, mkstemp_umask); + + return atf_no_error(); +} diff --git a/external/bsd/atf/dist/atf-c/detail/list.c b/external/bsd/atf/dist/atf-c/detail/list.c new file mode 100644 index 000000000..0d005ad05 --- /dev/null +++ b/external/bsd/atf/dist/atf-c/detail/list.c @@ -0,0 +1,392 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include "atf-c/error.h" +#include "atf-c/utils.h" + +#include "list.h" +#include "sanity.h" + +/* --------------------------------------------------------------------- + * Auxiliary functions. + * --------------------------------------------------------------------- */ + +struct list_entry { + struct list_entry *m_prev; + struct list_entry *m_next; + void *m_object; + bool m_managed; +}; + +static +atf_list_citer_t +entry_to_citer(const atf_list_t *l, const struct list_entry *le) +{ + atf_list_citer_t iter; + iter.m_list = l; + iter.m_entry = le; + return iter; +} + +static +atf_list_iter_t +entry_to_iter(atf_list_t *l, struct list_entry *le) +{ + atf_list_iter_t iter; + iter.m_list = l; + iter.m_entry = le; + return iter; +} + +static +struct list_entry * +new_entry(void *object, bool managed) +{ + struct list_entry *le; + + le = (struct list_entry *)malloc(sizeof(*le)); + if (le != NULL) { + le->m_prev = le->m_next = NULL; + le->m_object = object; + le->m_managed = managed; + } else + free(object); + + return le; +} + +static +void +delete_entry(struct list_entry *le) +{ + if (le->m_managed) + free(le->m_object); + + free(le); +} + +static +struct list_entry * +new_entry_and_link(void *object, bool managed, struct list_entry *prev, + struct list_entry *next) +{ + struct list_entry *le; + + le = new_entry(object, managed); + if (le != NULL) { + le->m_prev = prev; + le->m_next = next; + + prev->m_next = le; + next->m_prev = le; + } + + return le; +} + +/* --------------------------------------------------------------------- + * The "atf_list_citer" type. + * --------------------------------------------------------------------- */ + +/* + * Getters. + */ + +const void * +atf_list_citer_data(const atf_list_citer_t citer) +{ + const struct list_entry *le = citer.m_entry; + PRE(le != NULL); + return le->m_object; +} + +atf_list_citer_t +atf_list_citer_next(const atf_list_citer_t citer) +{ + const struct list_entry *le = citer.m_entry; + atf_list_citer_t newciter; + + PRE(le != NULL); + + newciter = citer; + newciter.m_entry = le->m_next; + + return newciter; +} + +bool +atf_equal_list_citer_list_citer(const atf_list_citer_t i1, + const atf_list_citer_t i2) +{ + return i1.m_list == i2.m_list && i1.m_entry == i2.m_entry; +} + +/* --------------------------------------------------------------------- + * The "atf_list_iter" type. + * --------------------------------------------------------------------- */ + +/* + * Getters. + */ + +void * +atf_list_iter_data(const atf_list_iter_t iter) +{ + const struct list_entry *le = iter.m_entry; + PRE(le != NULL); + return le->m_object; +} + +atf_list_iter_t +atf_list_iter_next(const atf_list_iter_t iter) +{ + const struct list_entry *le = iter.m_entry; + atf_list_iter_t newiter; + + PRE(le != NULL); + + newiter = iter; + newiter.m_entry = le->m_next; + + return newiter; +} + +bool +atf_equal_list_iter_list_iter(const atf_list_iter_t i1, + const atf_list_iter_t i2) +{ + return i1.m_list == i2.m_list && i1.m_entry == i2.m_entry; +} + +/* --------------------------------------------------------------------- + * The "atf_list" type. + * --------------------------------------------------------------------- */ + +/* + * Constructors and destructors. + */ + +atf_error_t +atf_list_init(atf_list_t *l) +{ + struct list_entry *lebeg, *leend; + + lebeg = new_entry(NULL, false); + if (lebeg == NULL) { + return atf_no_memory_error(); + } + + leend = new_entry(NULL, false); + if (leend == NULL) { + free(lebeg); + return atf_no_memory_error(); + } + + lebeg->m_next = leend; + lebeg->m_prev = NULL; + + leend->m_next = NULL; + leend->m_prev = lebeg; + + l->m_size = 0; + l->m_begin = lebeg; + l->m_end = leend; + + return atf_no_error(); +} + +void +atf_list_fini(atf_list_t *l) +{ + struct list_entry *le; + size_t freed; + + le = (struct list_entry *)l->m_begin; + freed = 0; + while (le != NULL) { + struct list_entry *lenext; + + lenext = le->m_next; + delete_entry(le); + le = lenext; + + freed++; + } + INV(freed == l->m_size + 2); +} + +/* + * Getters. + */ + +atf_list_iter_t +atf_list_begin(atf_list_t *l) +{ + struct list_entry *le = l->m_begin; + return entry_to_iter(l, le->m_next); +} + +atf_list_citer_t +atf_list_begin_c(const atf_list_t *l) +{ + const struct list_entry *le = l->m_begin; + return entry_to_citer(l, le->m_next); +} + +atf_list_iter_t +atf_list_end(atf_list_t *l) +{ + return entry_to_iter(l, l->m_end); +} + +atf_list_citer_t +atf_list_end_c(const atf_list_t *l) +{ + return entry_to_citer(l, l->m_end); +} + +void * +atf_list_index(atf_list_t *list, const size_t idx) +{ + atf_list_iter_t iter; + + PRE(idx < atf_list_size(list)); + + iter = atf_list_begin(list); + { + size_t pos = 0; + while (pos < idx && + !atf_equal_list_iter_list_iter((iter), atf_list_end(list))) { + iter = atf_list_iter_next(iter); + pos++; + } + } + return atf_list_iter_data(iter); +} + +const void * +atf_list_index_c(const atf_list_t *list, const size_t idx) +{ + atf_list_citer_t iter; + + PRE(idx < atf_list_size(list)); + + iter = atf_list_begin_c(list); + { + size_t pos = 0; + while (pos < idx && + !atf_equal_list_citer_list_citer((iter), + atf_list_end_c(list))) { + iter = atf_list_citer_next(iter); + pos++; + } + } + return atf_list_citer_data(iter); +} + +size_t +atf_list_size(const atf_list_t *l) +{ + return l->m_size; +} + +char ** +atf_list_to_charpp(const atf_list_t *l) +{ + char **array; + atf_list_citer_t iter; + size_t i; + + array = malloc(sizeof(char *) * (atf_list_size(l) + 1)); + if (array == NULL) + goto out; + + i = 0; + atf_list_for_each_c(iter, l) { + array[i] = strdup((const char *)atf_list_citer_data(iter)); + if (array[i] == NULL) { + atf_utils_free_charpp(array); + array = NULL; + goto out; + } + + i++; + } + array[i] = NULL; + +out: + return array; +} + +/* + * Modifiers. + */ + +atf_error_t +atf_list_append(atf_list_t *l, void *data, bool managed) +{ + struct list_entry *le, *next, *prev; + atf_error_t err; + + next = (struct list_entry *)l->m_end; + prev = next->m_prev; + le = new_entry_and_link(data, managed, prev, next); + if (le == NULL) + err = atf_no_memory_error(); + else { + l->m_size++; + err = atf_no_error(); + } + + return err; +} + +void +atf_list_append_list(atf_list_t *l, atf_list_t *src) +{ + struct list_entry *e1, *e2, *ghost1, *ghost2; + + ghost1 = (struct list_entry *)l->m_end; + ghost2 = (struct list_entry *)src->m_begin; + + e1 = ghost1->m_prev; + e2 = ghost2->m_next; + + delete_entry(ghost1); + delete_entry(ghost2); + + e1->m_next = e2; + e2->m_prev = e1; + + l->m_end = src->m_end; + l->m_size += src->m_size; +} diff --git a/external/bsd/atf/dist/atf-c/detail/list.h b/external/bsd/atf/dist/atf-c/detail/list.h new file mode 100644 index 000000000..2c0fbcba1 --- /dev/null +++ b/external/bsd/atf/dist/atf-c/detail/list.h @@ -0,0 +1,115 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if !defined(ATF_C_LIST_H) +#define ATF_C_LIST_H + +#include +#include +#include + +#include + +/* --------------------------------------------------------------------- + * The "atf_list_citer" type. + * --------------------------------------------------------------------- */ + +struct atf_list_citer { + const struct atf_list *m_list; + const void *m_entry; +}; +typedef struct atf_list_citer atf_list_citer_t; + +/* Getters. */ +const void *atf_list_citer_data(const atf_list_citer_t); +atf_list_citer_t atf_list_citer_next(const atf_list_citer_t); + +/* Operators. */ +bool atf_equal_list_citer_list_citer(const atf_list_citer_t, + const atf_list_citer_t); + +/* --------------------------------------------------------------------- + * The "atf_list_iter" type. + * --------------------------------------------------------------------- */ + +struct atf_list_iter { + struct atf_list *m_list; + void *m_entry; +}; +typedef struct atf_list_iter atf_list_iter_t; + +/* Getters. */ +void *atf_list_iter_data(const atf_list_iter_t); +atf_list_iter_t atf_list_iter_next(const atf_list_iter_t); + +/* Operators. */ +bool atf_equal_list_iter_list_iter(const atf_list_iter_t, + const atf_list_iter_t); + +/* --------------------------------------------------------------------- + * The "atf_list" type. + * --------------------------------------------------------------------- */ + +struct atf_list { + void *m_begin; + void *m_end; + + size_t m_size; +}; +typedef struct atf_list atf_list_t; + +/* Constructors and destructors */ +atf_error_t atf_list_init(atf_list_t *); +void atf_list_fini(atf_list_t *); + +/* Getters. */ +atf_list_iter_t atf_list_begin(atf_list_t *); +atf_list_citer_t atf_list_begin_c(const atf_list_t *); +atf_list_iter_t atf_list_end(atf_list_t *); +atf_list_citer_t atf_list_end_c(const atf_list_t *); +void *atf_list_index(atf_list_t *, const size_t); +const void *atf_list_index_c(const atf_list_t *, const size_t); +size_t atf_list_size(const atf_list_t *); +char **atf_list_to_charpp(const atf_list_t *); + +/* Modifiers. */ +atf_error_t atf_list_append(atf_list_t *, void *, bool); +void atf_list_append_list(atf_list_t *, atf_list_t *); + +/* Macros. */ +#define atf_list_for_each(iter, list) \ + for (iter = atf_list_begin(list); \ + !atf_equal_list_iter_list_iter((iter), atf_list_end(list)); \ + iter = atf_list_iter_next(iter)) +#define atf_list_for_each_c(iter, list) \ + for (iter = atf_list_begin_c(list); \ + !atf_equal_list_citer_list_citer((iter), atf_list_end_c(list)); \ + iter = atf_list_citer_next(iter)) + +#endif /* ATF_C_LIST_H */ diff --git a/external/bsd/atf/dist/atf-c/detail/list_test.c b/external/bsd/atf/dist/atf-c/detail/list_test.c new file mode 100644 index 000000000..3aa576cae --- /dev/null +++ b/external/bsd/atf/dist/atf-c/detail/list_test.c @@ -0,0 +1,369 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include + +#include "atf-c/utils.h" + +#include "list.h" +#include "test_helpers.h" + +/* --------------------------------------------------------------------- + * Tests for the "atf_list" type. + * --------------------------------------------------------------------- */ + +/* + * Constructors and destructors. + */ + +ATF_TC(list_init); +ATF_TC_HEAD(list_init, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks the atf_list_init function"); +} +ATF_TC_BODY(list_init, tc) +{ + atf_list_t list; + + RE(atf_list_init(&list)); + ATF_REQUIRE_EQ(atf_list_size(&list), 0); + atf_list_fini(&list); +} + +/* + * Getters. + */ + +ATF_TC(list_index); +ATF_TC_HEAD(list_index, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks the atf_list_index function"); +} +ATF_TC_BODY(list_index, tc) +{ + atf_list_t list; + int i1 = 1; + int i2 = 5; + int i3 = 9; + + RE(atf_list_init(&list)); + RE(atf_list_append(&list, &i1, false)); + RE(atf_list_append(&list, &i2, false)); + RE(atf_list_append(&list, &i3, false)); + + ATF_CHECK_EQ(*(int *)atf_list_index(&list, 0), 1); + ATF_CHECK_EQ(*(int *)atf_list_index(&list, 1), 5); + ATF_CHECK_EQ(*(int *)atf_list_index(&list, 2), 9); + + atf_list_fini(&list); +} + +ATF_TC(list_index_c); +ATF_TC_HEAD(list_index_c, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks the atf_list_index_c function"); +} +ATF_TC_BODY(list_index_c, tc) +{ + atf_list_t list; + int i1 = 1; + int i2 = 5; + int i3 = 9; + + RE(atf_list_init(&list)); + RE(atf_list_append(&list, &i1, false)); + RE(atf_list_append(&list, &i2, false)); + RE(atf_list_append(&list, &i3, false)); + + ATF_CHECK_EQ(*(const int *)atf_list_index_c(&list, 0), 1); + ATF_CHECK_EQ(*(const int *)atf_list_index_c(&list, 1), 5); + ATF_CHECK_EQ(*(const int *)atf_list_index_c(&list, 2), 9); + + atf_list_fini(&list); +} + +ATF_TC_WITHOUT_HEAD(list_to_charpp_empty); +ATF_TC_BODY(list_to_charpp_empty, tc) +{ + atf_list_t list; + char **array; + + RE(atf_list_init(&list)); + ATF_REQUIRE((array = atf_list_to_charpp(&list)) != NULL); + atf_list_fini(&list); + + ATF_CHECK_EQ(NULL, array[0]); + atf_utils_free_charpp(array); +} + +ATF_TC_WITHOUT_HEAD(list_to_charpp_some); +ATF_TC_BODY(list_to_charpp_some, tc) +{ + atf_list_t list; + char **array; + + char s1[] = "one"; + char s2[] = "two"; + char s3[] = "three"; + + RE(atf_list_init(&list)); + RE(atf_list_append(&list, s1, false)); + RE(atf_list_append(&list, s2, false)); + RE(atf_list_append(&list, s3, false)); + ATF_REQUIRE((array = atf_list_to_charpp(&list)) != NULL); + atf_list_fini(&list); + + ATF_CHECK_STREQ("one", array[0]); + ATF_CHECK_STREQ("two", array[1]); + ATF_CHECK_STREQ("three", array[2]); + ATF_CHECK_EQ(NULL, array[3]); + atf_utils_free_charpp(array); +} + +/* + * Modifiers. + */ + +ATF_TC(list_append); +ATF_TC_HEAD(list_append, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks the atf_list_append function"); +} +ATF_TC_BODY(list_append, tc) +{ + atf_list_t list; + size_t i; + char buf[] = "Test string"; + + RE(atf_list_init(&list)); + for (i = 0; i < 1024; i++) { + ATF_REQUIRE_EQ(atf_list_size(&list), i); + RE(atf_list_append(&list, buf, false)); + } + atf_list_fini(&list); +} + +ATF_TC(list_append_list); +ATF_TC_HEAD(list_append_list, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks the atf_list_append_list " + "function"); +} +ATF_TC_BODY(list_append_list, tc) +{ + { + atf_list_t l1, l2; + + RE(atf_list_init(&l1)); + RE(atf_list_init(&l2)); + + atf_list_append_list(&l1, &l2); + ATF_CHECK_EQ(atf_list_size(&l1), 0); + + atf_list_fini(&l1); + } + + { + atf_list_t l1, l2; + int item = 5; + + RE(atf_list_init(&l1)); + RE(atf_list_append(&l1, &item, false)); + RE(atf_list_init(&l2)); + + atf_list_append_list(&l1, &l2); + ATF_CHECK_EQ(atf_list_size(&l1), 1); + ATF_CHECK_EQ(*(int *)atf_list_index(&l1, 0), item); + + atf_list_fini(&l1); + } + + { + atf_list_t l1, l2; + int item = 5; + + RE(atf_list_init(&l1)); + RE(atf_list_init(&l2)); + RE(atf_list_append(&l2, &item, false)); + + atf_list_append_list(&l1, &l2); + ATF_CHECK_EQ(atf_list_size(&l1), 1); + ATF_CHECK_EQ(*(int *)atf_list_index(&l1, 0), item); + + atf_list_fini(&l1); + } + + { + atf_list_t l1, l2; + int item1 = 5; + int item2 = 9; + + RE(atf_list_init(&l1)); + RE(atf_list_append(&l1, &item1, false)); + RE(atf_list_init(&l2)); + RE(atf_list_append(&l2, &item2, false)); + + atf_list_append_list(&l1, &l2); + ATF_CHECK_EQ(atf_list_size(&l1), 2); + ATF_CHECK_EQ(*(int *)atf_list_index(&l1, 0), item1); + ATF_CHECK_EQ(*(int *)atf_list_index(&l1, 1), item2); + + atf_list_fini(&l1); + } + + { + atf_list_t l1, l2; + atf_list_citer_t end1, end2; + + RE(atf_list_init(&l1)); + RE(atf_list_init(&l2)); + + end1 = atf_list_end_c(&l1); + end2 = atf_list_end_c(&l2); + /* XXX Shouldn't query m_entry here. */ + ATF_CHECK(end1.m_entry != end2.m_entry); + + atf_list_append_list(&l1, &l2); + ATF_CHECK(atf_list_end_c(&l1).m_entry == end2.m_entry); + + atf_list_fini(&l1); + } +} + +/* + * Macros. + */ + +ATF_TC(list_for_each); +ATF_TC_HEAD(list_for_each, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks the atf_list_for_each macro"); +} +ATF_TC_BODY(list_for_each, tc) +{ + atf_list_t list; + atf_list_iter_t iter; + size_t count, i, size; + int nums[10]; + + printf("Iterating over empty list\n"); + RE(atf_list_init(&list)); + count = 0; + atf_list_for_each(iter, &list) { + count++; + printf("Item count is now %zd\n", count); + } + ATF_REQUIRE_EQ(count, 0); + atf_list_fini(&list); + + for (size = 0; size <= 10; size++) { + printf("Iterating over list of %zd elements\n", size); + RE(atf_list_init(&list)); + for (i = 0; i < size; i++) { + nums[i] = i + 1; + RE(atf_list_append(&list, &nums[i], false)); + } + count = 0; + atf_list_for_each(iter, &list) { + printf("Retrieved item: %d\n", *(int *)atf_list_iter_data(iter)); + count++; + } + ATF_REQUIRE_EQ(count, size); + atf_list_fini(&list); + } +} + +ATF_TC(list_for_each_c); +ATF_TC_HEAD(list_for_each_c, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks the atf_list_for_each_c macro"); +} +ATF_TC_BODY(list_for_each_c, tc) +{ + atf_list_t list; + atf_list_citer_t iter; + size_t count, i, size; + int nums[10]; + + printf("Iterating over empty list\n"); + RE(atf_list_init(&list)); + count = 0; + atf_list_for_each_c(iter, &list) { + count++; + printf("Item count is now %zd\n", count); + } + ATF_REQUIRE_EQ(count, 0); + atf_list_fini(&list); + + for (size = 0; size <= 10; size++) { + printf("Iterating over list of %zd elements\n", size); + RE(atf_list_init(&list)); + for (i = 0; i < size; i++) { + nums[i] = i + 1; + RE(atf_list_append(&list, &nums[i], false)); + } + count = 0; + atf_list_for_each_c(iter, &list) { + printf("Retrieved item: %d\n", + *(const int *)atf_list_citer_data(iter)); + count++; + } + ATF_REQUIRE_EQ(count, size); + atf_list_fini(&list); + } +} + +/* --------------------------------------------------------------------- + * Main. + * --------------------------------------------------------------------- */ + +ATF_TP_ADD_TCS(tp) +{ + /* Constructors and destructors. */ + ATF_TP_ADD_TC(tp, list_init); + + /* Getters. */ + ATF_TP_ADD_TC(tp, list_index); + ATF_TP_ADD_TC(tp, list_index_c); + ATF_TP_ADD_TC(tp, list_to_charpp_empty); + ATF_TP_ADD_TC(tp, list_to_charpp_some); + + /* Modifiers. */ + ATF_TP_ADD_TC(tp, list_append); + ATF_TP_ADD_TC(tp, list_append_list); + + /* Macros. */ + ATF_TP_ADD_TC(tp, list_for_each); + ATF_TP_ADD_TC(tp, list_for_each_c); + + return atf_no_error(); +} diff --git a/external/bsd/atf/dist/atf-c/detail/map.c b/external/bsd/atf/dist/atf-c/detail/map.c new file mode 100644 index 000000000..7395adfeb --- /dev/null +++ b/external/bsd/atf/dist/atf-c/detail/map.c @@ -0,0 +1,383 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +#include "atf-c/error.h" +#include "atf-c/utils.h" + +#include "map.h" +#include "sanity.h" + +/* --------------------------------------------------------------------- + * Auxiliary functions. + * --------------------------------------------------------------------- */ + +struct map_entry { + char *m_key; + void *m_value; + bool m_managed; +}; + +static +struct map_entry * +new_entry(const char *key, void *value, bool managed) +{ + struct map_entry *me; + + me = (struct map_entry *)malloc(sizeof(*me)); + if (me != NULL) { + me->m_key = strdup(key); + if (me->m_key == NULL) { + free(me); + me = NULL; + } else { + me->m_value = value; + me->m_managed = managed; + } + } + + return me; +} + +/* --------------------------------------------------------------------- + * The "atf_map_citer" type. + * --------------------------------------------------------------------- */ + +/* + * Getters. + */ + +const char * +atf_map_citer_key(const atf_map_citer_t citer) +{ + const struct map_entry *me = citer.m_entry; + PRE(me != NULL); + return me->m_key; +} + +const void * +atf_map_citer_data(const atf_map_citer_t citer) +{ + const struct map_entry *me = citer.m_entry; + PRE(me != NULL); + return me->m_value; +} + +atf_map_citer_t +atf_map_citer_next(const atf_map_citer_t citer) +{ + atf_map_citer_t newciter; + + newciter = citer; + newciter.m_listiter = atf_list_citer_next(citer.m_listiter); + newciter.m_entry = ((const struct map_entry *) + atf_list_citer_data(newciter.m_listiter)); + + return newciter; +} + +bool +atf_equal_map_citer_map_citer(const atf_map_citer_t i1, + const atf_map_citer_t i2) +{ + return i1.m_map == i2.m_map && i1.m_entry == i2.m_entry; +} + +/* --------------------------------------------------------------------- + * The "atf_map_iter" type. + * --------------------------------------------------------------------- */ + +/* + * Getters. + */ + +const char * +atf_map_iter_key(const atf_map_iter_t iter) +{ + const struct map_entry *me = iter.m_entry; + PRE(me != NULL); + return me->m_key; +} + +void * +atf_map_iter_data(const atf_map_iter_t iter) +{ + const struct map_entry *me = iter.m_entry; + PRE(me != NULL); + return me->m_value; +} + +atf_map_iter_t +atf_map_iter_next(const atf_map_iter_t iter) +{ + atf_map_iter_t newiter; + + newiter = iter; + newiter.m_listiter = atf_list_iter_next(iter.m_listiter); + newiter.m_entry = ((struct map_entry *) + atf_list_iter_data(newiter.m_listiter)); + + return newiter; +} + +bool +atf_equal_map_iter_map_iter(const atf_map_iter_t i1, + const atf_map_iter_t i2) +{ + return i1.m_map == i2.m_map && i1.m_entry == i2.m_entry; +} + +/* --------------------------------------------------------------------- + * The "atf_map" type. + * --------------------------------------------------------------------- */ + +/* + * Constructors and destructors. + */ + +atf_error_t +atf_map_init(atf_map_t *m) +{ + return atf_list_init(&m->m_list); +} + +atf_error_t +atf_map_init_charpp(atf_map_t *m, const char *const *array) +{ + atf_error_t err; + const char *const *ptr = array; + + err = atf_map_init(m); + if (array != NULL) { + while (!atf_is_error(err) && *ptr != NULL) { + const char *key, *value; + + key = *ptr; + INV(key != NULL); + ptr++; + + if ((value = *ptr) == NULL) { + err = atf_libc_error(EINVAL, "List too short; no value for " + "key '%s' provided", key); /* XXX: Not really libc_error */ + break; + } + ptr++; + + err = atf_map_insert(m, key, strdup(value), true); + } + } + + if (atf_is_error(err)) + atf_map_fini(m); + + return err; +} + +void +atf_map_fini(atf_map_t *m) +{ + atf_list_iter_t iter; + + atf_list_for_each(iter, &m->m_list) { + struct map_entry *me = atf_list_iter_data(iter); + + if (me->m_managed) + free(me->m_value); + free(me->m_key); + free(me); + } + atf_list_fini(&m->m_list); +} + +/* + * Getters. + */ + +atf_map_iter_t +atf_map_begin(atf_map_t *m) +{ + atf_map_iter_t iter; + iter.m_map = m; + iter.m_listiter = atf_list_begin(&m->m_list); + iter.m_entry = atf_list_iter_data(iter.m_listiter); + return iter; +} + +atf_map_citer_t +atf_map_begin_c(const atf_map_t *m) +{ + atf_map_citer_t citer; + citer.m_map = m; + citer.m_listiter = atf_list_begin_c(&m->m_list); + citer.m_entry = atf_list_citer_data(citer.m_listiter); + return citer; +} + +atf_map_iter_t +atf_map_end(atf_map_t *m) +{ + atf_map_iter_t iter; + iter.m_map = m; + iter.m_entry = NULL; + iter.m_listiter = atf_list_end(&m->m_list); + return iter; +} + +atf_map_citer_t +atf_map_end_c(const atf_map_t *m) +{ + atf_map_citer_t iter; + iter.m_map = m; + iter.m_entry = NULL; + iter.m_listiter = atf_list_end_c(&m->m_list); + return iter; +} + +atf_map_iter_t +atf_map_find(atf_map_t *m, const char *key) +{ + atf_list_iter_t iter; + + atf_list_for_each(iter, &m->m_list) { + struct map_entry *me = atf_list_iter_data(iter); + + if (strcmp(me->m_key, key) == 0) { + atf_map_iter_t i; + i.m_map = m; + i.m_entry = me; + i.m_listiter = iter; + return i; + } + } + + return atf_map_end(m); +} + +atf_map_citer_t +atf_map_find_c(const atf_map_t *m, const char *key) +{ + atf_list_citer_t iter; + + atf_list_for_each_c(iter, &m->m_list) { + const struct map_entry *me = atf_list_citer_data(iter); + + if (strcmp(me->m_key, key) == 0) { + atf_map_citer_t i; + i.m_map = m; + i.m_entry = me; + i.m_listiter = iter; + return i; + } + } + + return atf_map_end_c(m); +} + +size_t +atf_map_size(const atf_map_t *m) +{ + return atf_list_size(&m->m_list); +} + +char ** +atf_map_to_charpp(const atf_map_t *l) +{ + char **array; + atf_map_citer_t iter; + size_t i; + + array = malloc(sizeof(char *) * (atf_map_size(l) * 2 + 1)); + if (array == NULL) + goto out; + + i = 0; + atf_map_for_each_c(iter, l) { + array[i] = strdup(atf_map_citer_key(iter)); + if (array[i] == NULL) { + atf_utils_free_charpp(array); + array = NULL; + goto out; + } + + array[i + 1] = strdup((const char *)atf_map_citer_data(iter)); + if (array[i + 1] == NULL) { + atf_utils_free_charpp(array); + array = NULL; + goto out; + } + + i += 2; + } + array[i] = NULL; + +out: + return array; +} + +/* + * Modifiers. + */ + +atf_error_t +atf_map_insert(atf_map_t *m, const char *key, void *value, bool managed) +{ + struct map_entry *me; + atf_error_t err; + atf_map_iter_t iter; + + iter = atf_map_find(m, key); + if (atf_equal_map_iter_map_iter(iter, atf_map_end(m))) { + me = new_entry(key, value, managed); + if (me == NULL) + err = atf_no_memory_error(); + else { + err = atf_list_append(&m->m_list, me, false); + if (atf_is_error(err)) { + if (managed) + free(value); + free(me); + } + } + } else { + me = iter.m_entry; + if (me->m_managed) + free(me->m_value); + + INV(strcmp(me->m_key, key) == 0); + me->m_value = value; + me->m_managed = managed; + + err = atf_no_error(); + } + + return err; +} diff --git a/external/bsd/atf/dist/atf-c/detail/map.h b/external/bsd/atf/dist/atf-c/detail/map.h new file mode 100644 index 000000000..a3ed7a227 --- /dev/null +++ b/external/bsd/atf/dist/atf-c/detail/map.h @@ -0,0 +1,119 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if !defined(ATF_C_MAP_H) +#define ATF_C_MAP_H + +#include +#include + +#include + +#include "list.h" + +/* --------------------------------------------------------------------- + * The "atf_map_citer" type. + * --------------------------------------------------------------------- */ + +struct atf_map_citer { + const struct atf_map *m_map; + const void *m_entry; + atf_list_citer_t m_listiter; +}; +typedef struct atf_map_citer atf_map_citer_t; + +/* Getters. */ +const char *atf_map_citer_key(const atf_map_citer_t); +const void *atf_map_citer_data(const atf_map_citer_t); +atf_map_citer_t atf_map_citer_next(const atf_map_citer_t); + +/* Operators. */ +bool atf_equal_map_citer_map_citer(const atf_map_citer_t, + const atf_map_citer_t); + +/* --------------------------------------------------------------------- + * The "atf_map_iter" type. + * --------------------------------------------------------------------- */ + +struct atf_map_iter { + struct atf_map *m_map; + void *m_entry; + atf_list_iter_t m_listiter; +}; +typedef struct atf_map_iter atf_map_iter_t; + +/* Getters. */ +const char *atf_map_iter_key(const atf_map_iter_t); +void *atf_map_iter_data(const atf_map_iter_t); +atf_map_iter_t atf_map_iter_next(const atf_map_iter_t); + +/* Operators. */ +bool atf_equal_map_iter_map_iter(const atf_map_iter_t, + const atf_map_iter_t); + +/* --------------------------------------------------------------------- + * The "atf_map" type. + * --------------------------------------------------------------------- */ + +/* A list-based map. Typically very inefficient, but our maps are small + * enough. */ +struct atf_map { + atf_list_t m_list; +}; +typedef struct atf_map atf_map_t; + +/* Constructors and destructors */ +atf_error_t atf_map_init(atf_map_t *); +atf_error_t atf_map_init_charpp(atf_map_t *, const char *const *); +void atf_map_fini(atf_map_t *); + +/* Getters. */ +atf_map_iter_t atf_map_begin(atf_map_t *); +atf_map_citer_t atf_map_begin_c(const atf_map_t *); +atf_map_iter_t atf_map_end(atf_map_t *); +atf_map_citer_t atf_map_end_c(const atf_map_t *); +atf_map_iter_t atf_map_find(atf_map_t *, const char *); +atf_map_citer_t atf_map_find_c(const atf_map_t *, const char *); +size_t atf_map_size(const atf_map_t *); +char **atf_map_to_charpp(const atf_map_t *); + +/* Modifiers. */ +atf_error_t atf_map_insert(atf_map_t *, const char *, void *, bool); + +/* Macros. */ +#define atf_map_for_each(iter, map) \ + for (iter = atf_map_begin(map); \ + !atf_equal_map_iter_map_iter((iter), atf_map_end(map)); \ + iter = atf_map_iter_next(iter)) +#define atf_map_for_each_c(iter, map) \ + for (iter = atf_map_begin_c(map); \ + !atf_equal_map_citer_map_citer((iter), atf_map_end_c(map)); \ + iter = atf_map_citer_next(iter)) + +#endif /* ATF_C_MAP_H */ diff --git a/external/bsd/atf/dist/atf-c/detail/map_test.c b/external/bsd/atf/dist/atf-c/detail/map_test.c new file mode 100644 index 000000000..644ab6926 --- /dev/null +++ b/external/bsd/atf/dist/atf-c/detail/map_test.c @@ -0,0 +1,425 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include + +#include "atf-c/utils.h" + +#include "map.h" +#include "test_helpers.h" + +/* --------------------------------------------------------------------- + * Tests for the "atf_map" type. + * --------------------------------------------------------------------- */ + +/* + * Constructors and destructors. + */ + +ATF_TC(map_init); +ATF_TC_HEAD(map_init, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks the atf_map_init function"); +} +ATF_TC_BODY(map_init, tc) +{ + atf_map_t map; + + RE(atf_map_init(&map)); + ATF_REQUIRE_EQ(atf_map_size(&map), 0); + atf_map_fini(&map); +} + +ATF_TC_WITHOUT_HEAD(map_init_charpp_null); +ATF_TC_BODY(map_init_charpp_null, tc) +{ + atf_map_t map; + + RE(atf_map_init_charpp(&map, NULL)); + ATF_REQUIRE_EQ(atf_map_size(&map), 0); + atf_map_fini(&map); +} + +ATF_TC_WITHOUT_HEAD(map_init_charpp_empty); +ATF_TC_BODY(map_init_charpp_empty, tc) +{ + const char *const array[] = { NULL }; + atf_map_t map; + + RE(atf_map_init_charpp(&map, array)); + ATF_REQUIRE_EQ(atf_map_size(&map), 0); + atf_map_fini(&map); +} + +ATF_TC_WITHOUT_HEAD(map_init_charpp_some); +ATF_TC_BODY(map_init_charpp_some, tc) +{ + const char *const array[] = { "K1", "V1", "K2", "V2", NULL }; + atf_map_t map; + atf_map_citer_t iter; + + RE(atf_map_init_charpp(&map, array)); + ATF_REQUIRE_EQ(atf_map_size(&map), 2); + + iter = atf_map_find_c(&map, "K1"); + ATF_REQUIRE(!atf_equal_map_citer_map_citer(iter, atf_map_end_c(&map))); + ATF_REQUIRE(strcmp(atf_map_citer_key(iter), "K1") == 0); + ATF_REQUIRE(strcmp(atf_map_citer_data(iter), "V1") == 0); + + iter = atf_map_find_c(&map, "K2"); + ATF_REQUIRE(!atf_equal_map_citer_map_citer(iter, atf_map_end_c(&map))); + ATF_REQUIRE(strcmp(atf_map_citer_key(iter), "K2") == 0); + ATF_REQUIRE(strcmp(atf_map_citer_data(iter), "V2") == 0); + + atf_map_fini(&map); +} + +ATF_TC_WITHOUT_HEAD(map_init_charpp_short); +ATF_TC_BODY(map_init_charpp_short, tc) +{ + const char *const array[] = { "K1", "V1", "K2", NULL }; + atf_map_t map; + + atf_error_t err = atf_map_init_charpp(&map, array); + ATF_REQUIRE(atf_is_error(err)); + ATF_REQUIRE(atf_error_is(err, "libc")); +} + +/* + * Getters. + */ + +ATF_TC(find); +ATF_TC_HEAD(find, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks the atf_map_find function"); +} +ATF_TC_BODY(find, tc) +{ + atf_map_t map; + char val1[] = "V1"; + char val2[] = "V2"; + atf_map_iter_t iter; + + RE(atf_map_init(&map)); + RE(atf_map_insert(&map, "K1", val1, false)); + RE(atf_map_insert(&map, "K2", val2, false)); + + iter = atf_map_find(&map, "K0"); + ATF_REQUIRE(atf_equal_map_iter_map_iter(iter, atf_map_end(&map))); + + iter = atf_map_find(&map, "K1"); + ATF_REQUIRE(!atf_equal_map_iter_map_iter(iter, atf_map_end(&map))); + ATF_REQUIRE(strcmp(atf_map_iter_key(iter), "K1") == 0); + ATF_REQUIRE(strcmp(atf_map_iter_data(iter), "V1") == 0); + strcpy(atf_map_iter_data(iter), "Z1"); + + iter = atf_map_find(&map, "K1"); + ATF_REQUIRE(!atf_equal_map_iter_map_iter(iter, atf_map_end(&map))); + ATF_REQUIRE(strcmp(atf_map_iter_key(iter), "K1") == 0); + ATF_REQUIRE(strcmp(atf_map_iter_data(iter), "Z1") == 0); + + iter = atf_map_find(&map, "K2"); + ATF_REQUIRE(!atf_equal_map_iter_map_iter(iter, atf_map_end(&map))); + ATF_REQUIRE(strcmp(atf_map_iter_key(iter), "K2") == 0); + ATF_REQUIRE(strcmp(atf_map_iter_data(iter), "V2") == 0); + + atf_map_fini(&map); +} + +ATF_TC(find_c); +ATF_TC_HEAD(find_c, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks the atf_map_find_c function"); +} +ATF_TC_BODY(find_c, tc) +{ + atf_map_t map; + char val1[] = "V1"; + char val2[] = "V2"; + atf_map_citer_t iter; + + RE(atf_map_init(&map)); + RE(atf_map_insert(&map, "K1", val1, false)); + RE(atf_map_insert(&map, "K2", val2, false)); + + iter = atf_map_find_c(&map, "K0"); + ATF_REQUIRE(atf_equal_map_citer_map_citer(iter, atf_map_end_c(&map))); + + iter = atf_map_find_c(&map, "K1"); + ATF_REQUIRE(!atf_equal_map_citer_map_citer(iter, atf_map_end_c(&map))); + ATF_REQUIRE(strcmp(atf_map_citer_key(iter), "K1") == 0); + ATF_REQUIRE(strcmp(atf_map_citer_data(iter), "V1") == 0); + + iter = atf_map_find_c(&map, "K2"); + ATF_REQUIRE(!atf_equal_map_citer_map_citer(iter, atf_map_end_c(&map))); + ATF_REQUIRE(strcmp(atf_map_citer_key(iter), "K2") == 0); + ATF_REQUIRE(strcmp(atf_map_citer_data(iter), "V2") == 0); + + atf_map_fini(&map); +} + +ATF_TC_WITHOUT_HEAD(to_charpp_empty); +ATF_TC_BODY(to_charpp_empty, tc) +{ + atf_map_t map; + char **array; + + RE(atf_map_init(&map)); + ATF_REQUIRE((array = atf_map_to_charpp(&map)) != NULL); + atf_map_fini(&map); + + ATF_CHECK_EQ(NULL, array[0]); + atf_utils_free_charpp(array); +} + +ATF_TC_WITHOUT_HEAD(to_charpp_some); +ATF_TC_BODY(to_charpp_some, tc) +{ + atf_map_t map; + char **array; + + char s1[] = "one"; + char s2[] = "two"; + char s3[] = "three"; + + RE(atf_map_init(&map)); + RE(atf_map_insert(&map, "K1", s1, false)); + RE(atf_map_insert(&map, "K2", s2, false)); + RE(atf_map_insert(&map, "K3", s3, false)); + ATF_REQUIRE((array = atf_map_to_charpp(&map)) != NULL); + atf_map_fini(&map); + + ATF_CHECK_STREQ("K1", array[0]); + ATF_CHECK_STREQ("one", array[1]); + ATF_CHECK_STREQ("K2", array[2]); + ATF_CHECK_STREQ("two", array[3]); + ATF_CHECK_STREQ("K3", array[4]); + ATF_CHECK_STREQ("three", array[5]); + ATF_CHECK_EQ(NULL, array[6]); + atf_utils_free_charpp(array); +} + +/* + * Modifiers. + */ + +ATF_TC(map_insert); +ATF_TC_HEAD(map_insert, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks the atf_map_insert function"); +} +ATF_TC_BODY(map_insert, tc) +{ + atf_map_t map; + char buf[] = "1st test string"; + char buf2[] = "2nd test string"; + const char *ptr; + atf_map_citer_t iter; + + RE(atf_map_init(&map)); + + printf("Inserting some values\n"); + ATF_REQUIRE_EQ(atf_map_size(&map), 0); + RE(atf_map_insert(&map, "K1", buf, false)); + ATF_REQUIRE_EQ(atf_map_size(&map), 1); + RE(atf_map_insert(&map, "K2", buf, false)); + ATF_REQUIRE_EQ(atf_map_size(&map), 2); + RE(atf_map_insert(&map, "K3", buf, false)); + ATF_REQUIRE_EQ(atf_map_size(&map), 3); + + printf("Replacing a value\n"); + iter = atf_map_find_c(&map, "K3"); + ATF_REQUIRE(!atf_equal_map_citer_map_citer(iter, atf_map_end_c(&map))); + ptr = atf_map_citer_data(iter); + ATF_REQUIRE_EQ(ptr, buf); + RE(atf_map_insert(&map, "K3", buf2, false)); + ATF_REQUIRE_EQ(atf_map_size(&map), 3); + iter = atf_map_find_c(&map, "K3"); + ATF_REQUIRE(!atf_equal_map_citer_map_citer(iter, atf_map_end_c(&map))); + ptr = atf_map_citer_data(iter); + ATF_REQUIRE_EQ(ptr, buf2); + + atf_map_fini(&map); +} + +/* + * Macros. + */ + +ATF_TC(map_for_each); +ATF_TC_HEAD(map_for_each, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks the atf_map_for_each macro"); +} +ATF_TC_BODY(map_for_each, tc) +{ + atf_map_t map; + atf_map_iter_t iter; + size_t count, i, size; + char keys[10][5]; + int nums[10]; + + printf("Iterating over empty map\n"); + RE(atf_map_init(&map)); + count = 0; + atf_map_for_each(iter, &map) { + count++; + printf("Item count is now %zd\n", count); + } + ATF_REQUIRE_EQ(count, 0); + atf_map_fini(&map); + + for (size = 0; size <= 10; size++) { + printf("Iterating over map of %zd elements\n", size); + RE(atf_map_init(&map)); + for (i = 0; i < size; i++) { + nums[i] = i + 1; + snprintf(keys[i], sizeof(keys[i]), "%d", nums[i]); + RE(atf_map_insert(&map, keys[i], &nums[i], false)); + } + count = 0; + atf_map_for_each(iter, &map) { + printf("Retrieved item: %d\n", *(int *)atf_map_iter_data(iter)); + count++; + } + ATF_REQUIRE_EQ(count, size); + atf_map_fini(&map); + } +} + +ATF_TC(map_for_each_c); +ATF_TC_HEAD(map_for_each_c, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks the atf_map_for_each_c macro"); +} +ATF_TC_BODY(map_for_each_c, tc) +{ + atf_map_t map; + atf_map_citer_t iter; + size_t count, i, size; + char keys[10][5]; + int nums[10]; + + printf("Iterating over empty map\n"); + RE(atf_map_init(&map)); + count = 0; + atf_map_for_each_c(iter, &map) { + count++; + printf("Item count is now %zd\n", count); + } + ATF_REQUIRE_EQ(count, 0); + atf_map_fini(&map); + + for (size = 0; size <= 10; size++) { + printf("Iterating over map of %zd elements\n", size); + RE(atf_map_init(&map)); + for (i = 0; i < size; i++) { + nums[i] = i + 1; + snprintf(keys[i], sizeof(keys[i]), "%d", nums[i]); + RE(atf_map_insert(&map, keys[i], &nums[i], false)); + } + count = 0; + atf_map_for_each_c(iter, &map) { + printf("Retrieved item: %d\n", + *(const int *)atf_map_citer_data(iter)); + count++; + } + ATF_REQUIRE_EQ(count, size); + atf_map_fini(&map); + } +} + +/* + * Other. + */ + +ATF_TC(stable_keys); +ATF_TC_HEAD(stable_keys, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks that the keys do not change " + "even if their original values do"); +} +ATF_TC_BODY(stable_keys, tc) +{ + atf_map_t map; + atf_map_citer_t iter; + char key[] = "K1"; + + RE(atf_map_init(&map)); + + RE(atf_map_insert(&map, key, strdup("test-value"), true)); + iter = atf_map_find_c(&map, "K1"); + ATF_REQUIRE(!atf_equal_map_citer_map_citer(iter, atf_map_end_c(&map))); + iter = atf_map_find_c(&map, "K2"); + ATF_REQUIRE(atf_equal_map_citer_map_citer(iter, atf_map_end_c(&map))); + + strcpy(key, "K2"); + iter = atf_map_find_c(&map, "K1"); + ATF_REQUIRE(!atf_equal_map_citer_map_citer(iter, atf_map_end_c(&map))); + iter = atf_map_find_c(&map, "K2"); + ATF_REQUIRE(atf_equal_map_citer_map_citer(iter, atf_map_end_c(&map))); + + atf_map_fini(&map); +} + +/* --------------------------------------------------------------------- + * Main. + * --------------------------------------------------------------------- */ + +ATF_TP_ADD_TCS(tp) +{ + /* Constructors and destructors. */ + ATF_TP_ADD_TC(tp, map_init); + ATF_TP_ADD_TC(tp, map_init_charpp_null); + ATF_TP_ADD_TC(tp, map_init_charpp_empty); + ATF_TP_ADD_TC(tp, map_init_charpp_some); + ATF_TP_ADD_TC(tp, map_init_charpp_short); + + /* Getters. */ + ATF_TP_ADD_TC(tp, find); + ATF_TP_ADD_TC(tp, find_c); + ATF_TP_ADD_TC(tp, to_charpp_empty); + ATF_TP_ADD_TC(tp, to_charpp_some); + + /* Modifiers. */ + ATF_TP_ADD_TC(tp, map_insert); + + /* Macros. */ + ATF_TP_ADD_TC(tp, map_for_each); + ATF_TP_ADD_TC(tp, map_for_each_c); + + /* Other. */ + ATF_TP_ADD_TC(tp, stable_keys); + + return atf_no_error(); +} diff --git a/external/bsd/atf/dist/atf-c/detail/process.c b/external/bsd/atf/dist/atf-c/detail/process.c new file mode 100644 index 000000000..bc36b570e --- /dev/null +++ b/external/bsd/atf/dist/atf-c/detail/process.c @@ -0,0 +1,674 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2007 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "atf-c/defs.h" +#include "atf-c/error.h" + +#include "process.h" +#include "sanity.h" + +/* This prototype is not in the header file because this is a private + * function; however, we need to access it during testing. */ +atf_error_t atf_process_status_init(atf_process_status_t *, int); + +/* --------------------------------------------------------------------- + * The "stream_prepare" auxiliary type. + * --------------------------------------------------------------------- */ + +struct stream_prepare { + const atf_process_stream_t *m_sb; + + bool m_pipefds_ok; + int m_pipefds[2]; +}; +typedef struct stream_prepare stream_prepare_t; + +static +atf_error_t +stream_prepare_init(stream_prepare_t *sp, const atf_process_stream_t *sb) +{ + atf_error_t err; + + const int type = atf_process_stream_type(sb); + + sp->m_sb = sb; + sp->m_pipefds_ok = false; + + if (type == atf_process_stream_type_capture) { + if (pipe(sp->m_pipefds) == -1) + err = atf_libc_error(errno, "Failed to create pipe"); + else { + err = atf_no_error(); + sp->m_pipefds_ok = true; + } + } else + err = atf_no_error(); + + return err; +} + +static +void +stream_prepare_fini(stream_prepare_t *sp) +{ + if (sp->m_pipefds_ok) { + close(sp->m_pipefds[0]); + close(sp->m_pipefds[1]); + } +} + +/* --------------------------------------------------------------------- + * The "atf_process_stream" type. + * --------------------------------------------------------------------- */ + +const int atf_process_stream_type_capture = 1; +const int atf_process_stream_type_connect = 2; +const int atf_process_stream_type_inherit = 3; +const int atf_process_stream_type_redirect_fd = 4; +const int atf_process_stream_type_redirect_path = 5; + +static +bool +stream_is_valid(const atf_process_stream_t *sb) +{ + return (sb->m_type == atf_process_stream_type_capture) || + (sb->m_type == atf_process_stream_type_connect) || + (sb->m_type == atf_process_stream_type_inherit) || + (sb->m_type == atf_process_stream_type_redirect_fd) || + (sb->m_type == atf_process_stream_type_redirect_path); +} + +atf_error_t +atf_process_stream_init_capture(atf_process_stream_t *sb) +{ + sb->m_type = atf_process_stream_type_capture; + + POST(stream_is_valid(sb)); + return atf_no_error(); +} + +atf_error_t +atf_process_stream_init_connect(atf_process_stream_t *sb, + const int src_fd, const int tgt_fd) +{ + PRE(src_fd >= 0); + PRE(tgt_fd >= 0); + PRE(src_fd != tgt_fd); + + sb->m_type = atf_process_stream_type_connect; + sb->m_src_fd = src_fd; + sb->m_tgt_fd = tgt_fd; + + POST(stream_is_valid(sb)); + return atf_no_error(); +} + +atf_error_t +atf_process_stream_init_inherit(atf_process_stream_t *sb) +{ + sb->m_type = atf_process_stream_type_inherit; + + POST(stream_is_valid(sb)); + return atf_no_error(); +} + +atf_error_t +atf_process_stream_init_redirect_fd(atf_process_stream_t *sb, + const int fd) +{ + sb->m_type = atf_process_stream_type_redirect_fd; + sb->m_fd = fd; + + POST(stream_is_valid(sb)); + return atf_no_error(); +} + +atf_error_t +atf_process_stream_init_redirect_path(atf_process_stream_t *sb, + const atf_fs_path_t *path) +{ + sb->m_type = atf_process_stream_type_redirect_path; + sb->m_path = path; + + POST(stream_is_valid(sb)); + return atf_no_error(); +} + +void +atf_process_stream_fini(atf_process_stream_t *sb) +{ + PRE(stream_is_valid(sb)); +} + +int +atf_process_stream_type(const atf_process_stream_t *sb) +{ + PRE(stream_is_valid(sb)); + + return sb->m_type; +} + +/* --------------------------------------------------------------------- + * The "atf_process_status" type. + * --------------------------------------------------------------------- */ + +atf_error_t +atf_process_status_init(atf_process_status_t *s, int status) +{ + s->m_status = status; + + return atf_no_error(); +} + +void +atf_process_status_fini(atf_process_status_t *s ATF_DEFS_ATTRIBUTE_UNUSED) +{ +} + +bool +atf_process_status_exited(const atf_process_status_t *s) +{ + int mutable_status = s->m_status; + return WIFEXITED(mutable_status); +} + +int +atf_process_status_exitstatus(const atf_process_status_t *s) +{ + PRE(atf_process_status_exited(s)); + int mutable_status = s->m_status; + return WEXITSTATUS(mutable_status); +} + +bool +atf_process_status_signaled(const atf_process_status_t *s) +{ + int mutable_status = s->m_status; + return WIFSIGNALED(mutable_status); +} + +int +atf_process_status_termsig(const atf_process_status_t *s) +{ + PRE(atf_process_status_signaled(s)); + int mutable_status = s->m_status; + return WTERMSIG(mutable_status); +} + +bool +atf_process_status_coredump(const atf_process_status_t *s) +{ + PRE(atf_process_status_signaled(s)); +#if defined(WCOREDUMP) + int mutable_status = s->m_status; + return WCOREDUMP(mutable_status); +#else + return false; +#endif +} + +/* --------------------------------------------------------------------- + * The "atf_process_child" type. + * --------------------------------------------------------------------- */ + +static +atf_error_t +atf_process_child_init(atf_process_child_t *c) +{ + c->m_pid = 0; + c->m_stdout = -1; + c->m_stderr = -1; + + return atf_no_error(); +} + +static +void +atf_process_child_fini(atf_process_child_t *c) +{ + if (c->m_stdout != -1) + close(c->m_stdout); + if (c->m_stderr != -1) + close(c->m_stderr); +} + +atf_error_t +atf_process_child_wait(atf_process_child_t *c, atf_process_status_t *s) +{ + atf_error_t err; + int status; + + if (waitpid(c->m_pid, &status, 0) == -1) + err = atf_libc_error(errno, "Failed waiting for process %d", + c->m_pid); + else { + atf_process_child_fini(c); + err = atf_process_status_init(s, status); + } + + return err; +} + +pid_t +atf_process_child_pid(const atf_process_child_t *c) +{ + return c->m_pid; +} + +int +atf_process_child_stdout(atf_process_child_t *c) +{ + PRE(c->m_stdout != -1); + return c->m_stdout; +} + +int +atf_process_child_stderr(atf_process_child_t *c) +{ + PRE(c->m_stderr != -1); + return c->m_stderr; +} + +/* --------------------------------------------------------------------- + * Free functions. + * --------------------------------------------------------------------- */ + +static +atf_error_t +safe_dup(const int oldfd, const int newfd) +{ + atf_error_t err; + + if (oldfd != newfd) { + if (dup2(oldfd, newfd) == -1) { + err = atf_libc_error(errno, "Could not allocate file descriptor"); + } else { + close(oldfd); + err = atf_no_error(); + } + } else + err = atf_no_error(); + + return err; +} + +static +atf_error_t +child_connect(const stream_prepare_t *sp, int procfd) +{ + atf_error_t err; + const int type = atf_process_stream_type(sp->m_sb); + + if (type == atf_process_stream_type_capture) { + close(sp->m_pipefds[0]); + err = safe_dup(sp->m_pipefds[1], procfd); + } else if (type == atf_process_stream_type_connect) { + if (dup2(sp->m_sb->m_tgt_fd, sp->m_sb->m_src_fd) == -1) + err = atf_libc_error(errno, "Cannot connect descriptor %d to %d", + sp->m_sb->m_tgt_fd, sp->m_sb->m_src_fd); + else + err = atf_no_error(); + } else if (type == atf_process_stream_type_inherit) { + err = atf_no_error(); + } else if (type == atf_process_stream_type_redirect_fd) { + err = safe_dup(sp->m_sb->m_fd, procfd); + } else if (type == atf_process_stream_type_redirect_path) { + int aux = open(atf_fs_path_cstring(sp->m_sb->m_path), + O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (aux == -1) + err = atf_libc_error(errno, "Could not create %s", + atf_fs_path_cstring(sp->m_sb->m_path)); + else { + err = safe_dup(aux, procfd); + if (atf_is_error(err)) + close(aux); + } + } else { + UNREACHABLE; + err = atf_no_error(); + } + + return err; +} + +static +void +parent_connect(const stream_prepare_t *sp, int *fd) +{ + const int type = atf_process_stream_type(sp->m_sb); + + if (type == atf_process_stream_type_capture) { + close(sp->m_pipefds[1]); + *fd = sp->m_pipefds[0]; + } else if (type == atf_process_stream_type_connect) { + /* Do nothing. */ + } else if (type == atf_process_stream_type_inherit) { + /* Do nothing. */ + } else if (type == atf_process_stream_type_redirect_fd) { + /* Do nothing. */ + } else if (type == atf_process_stream_type_redirect_path) { + /* Do nothing. */ + } else { + UNREACHABLE; + } +} + +static +atf_error_t +do_parent(atf_process_child_t *c, + const pid_t pid, + const stream_prepare_t *outsp, + const stream_prepare_t *errsp) +{ + atf_error_t err; + + err = atf_process_child_init(c); + if (atf_is_error(err)) + goto out; + + c->m_pid = pid; + + parent_connect(outsp, &c->m_stdout); + parent_connect(errsp, &c->m_stderr); + +out: + return err; +} + +static +void +do_child(void (*)(void *), + void *, + const stream_prepare_t *, + const stream_prepare_t *) ATF_DEFS_ATTRIBUTE_NORETURN; + +static +void +do_child(void (*start)(void *), + void *v, + const stream_prepare_t *outsp, + const stream_prepare_t *errsp) +{ + atf_error_t err; + + err = child_connect(outsp, STDOUT_FILENO); + if (atf_is_error(err)) + goto out; + + err = child_connect(errsp, STDERR_FILENO); + if (atf_is_error(err)) + goto out; + + start(v); + UNREACHABLE; + +out: + if (atf_is_error(err)) { + char buf[1024]; + + atf_error_format(err, buf, sizeof(buf)); + fprintf(stderr, "Unhandled error: %s\n", buf); + atf_error_free(err); + + exit(EXIT_FAILURE); + } else + exit(EXIT_SUCCESS); +} + +static +atf_error_t +fork_with_streams(atf_process_child_t *c, + void (*start)(void *), + const atf_process_stream_t *outsb, + const atf_process_stream_t *errsb, + void *v) +{ + atf_error_t err; + stream_prepare_t outsp; + stream_prepare_t errsp; + pid_t pid; + + err = stream_prepare_init(&outsp, outsb); + if (atf_is_error(err)) + goto out; + + err = stream_prepare_init(&errsp, errsb); + if (atf_is_error(err)) + goto err_outpipe; + + pid = fork(); + if (pid == -1) { + err = atf_libc_error(errno, "Failed to fork"); + goto err_errpipe; + } + + if (pid == 0) { + do_child(start, v, &outsp, &errsp); + UNREACHABLE; + abort(); + err = atf_no_error(); + } else { + err = do_parent(c, pid, &outsp, &errsp); + if (atf_is_error(err)) + goto err_errpipe; + } + + goto out; + +err_errpipe: + stream_prepare_fini(&errsp); +err_outpipe: + stream_prepare_fini(&outsp); + +out: + return err; +} + +static +atf_error_t +init_stream_w_default(const atf_process_stream_t *usersb, + atf_process_stream_t *inheritsb, + const atf_process_stream_t **realsb) +{ + atf_error_t err; + + if (usersb == NULL) { + err = atf_process_stream_init_inherit(inheritsb); + if (!atf_is_error(err)) + *realsb = inheritsb; + } else { + err = atf_no_error(); + *realsb = usersb; + } + + return err; +} + +atf_error_t +atf_process_fork(atf_process_child_t *c, + void (*start)(void *), + const atf_process_stream_t *outsb, + const atf_process_stream_t *errsb, + void *v) +{ + atf_error_t err; + atf_process_stream_t inherit_outsb, inherit_errsb; + const atf_process_stream_t *real_outsb, *real_errsb; + + real_outsb = NULL; /* Shut up GCC warning. */ + err = init_stream_w_default(outsb, &inherit_outsb, &real_outsb); + if (atf_is_error(err)) + goto out; + + real_errsb = NULL; /* Shut up GCC warning. */ + err = init_stream_w_default(errsb, &inherit_errsb, &real_errsb); + if (atf_is_error(err)) + goto out_out; + + err = fork_with_streams(c, start, real_outsb, real_errsb, v); + + if (errsb == NULL) + atf_process_stream_fini(&inherit_errsb); +out_out: + if (outsb == NULL) + atf_process_stream_fini(&inherit_outsb); +out: + return err; +} + +static +int +const_execvp(const char *file, const char *const *argv) +{ +#define UNCONST(a) ((void *)(unsigned long)(const void *)(a)) + return execvp(file, UNCONST(argv)); +#undef UNCONST +} + +static +atf_error_t +list_to_array(const atf_list_t *l, const char ***ap) +{ + atf_error_t err; + const char **a; + + a = (const char **)malloc((atf_list_size(l) + 1) * sizeof(const char *)); + if (a == NULL) + err = atf_no_memory_error(); + else { + const char **aiter; + atf_list_citer_t liter; + + aiter = a; + atf_list_for_each_c(liter, l) { + *aiter = (const char *)atf_list_citer_data(liter); + aiter++; + } + *aiter = NULL; + + err = atf_no_error(); + *ap = a; + } + + return err; +} + +struct exec_args { + const atf_fs_path_t *m_prog; + const char *const *m_argv; + void (*m_prehook)(void); +}; + +static +void +do_exec(void *v) +{ + struct exec_args *ea = v; + + if (ea->m_prehook != NULL) + ea->m_prehook(); + + const int ret = const_execvp(atf_fs_path_cstring(ea->m_prog), ea->m_argv); + const int errnocopy = errno; + INV(ret == -1); + fprintf(stderr, "exec(%s) failed: %s\n", + atf_fs_path_cstring(ea->m_prog), strerror(errnocopy)); + exit(EXIT_FAILURE); +} + +atf_error_t +atf_process_exec_array(atf_process_status_t *s, + const atf_fs_path_t *prog, + const char *const *argv, + const atf_process_stream_t *outsb, + const atf_process_stream_t *errsb, + void (*prehook)(void)) +{ + atf_error_t err; + atf_process_child_t c; + struct exec_args ea = { prog, argv, prehook }; + + PRE(outsb == NULL || + atf_process_stream_type(outsb) != atf_process_stream_type_capture); + PRE(errsb == NULL || + atf_process_stream_type(errsb) != atf_process_stream_type_capture); + + err = atf_process_fork(&c, do_exec, outsb, errsb, &ea); + if (atf_is_error(err)) + goto out; + +again: + err = atf_process_child_wait(&c, s); + if (atf_is_error(err)) { + INV(atf_error_is(err, "libc") && atf_libc_error_code(err) == EINTR); + atf_error_free(err); + goto again; + } + +out: + return err; +} + +atf_error_t +atf_process_exec_list(atf_process_status_t *s, + const atf_fs_path_t *prog, + const atf_list_t *argv, + const atf_process_stream_t *outsb, + const atf_process_stream_t *errsb, + void (*prehook)(void)) +{ + atf_error_t err; + const char **argv2; + + PRE(outsb == NULL || + atf_process_stream_type(outsb) != atf_process_stream_type_capture); + PRE(errsb == NULL || + atf_process_stream_type(errsb) != atf_process_stream_type_capture); + + argv2 = NULL; /* Silence GCC warning. */ + err = list_to_array(argv, &argv2); + if (atf_is_error(err)) + goto out; + + err = atf_process_exec_array(s, prog, argv2, outsb, errsb, prehook); + + free(argv2); +out: + return err; +} diff --git a/external/bsd/atf/dist/atf-c/detail/process.h b/external/bsd/atf/dist/atf-c/detail/process.h new file mode 100644 index 000000000..b4aad3d93 --- /dev/null +++ b/external/bsd/atf/dist/atf-c/detail/process.h @@ -0,0 +1,136 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if !defined(ATF_C_PROCESS_H) +#define ATF_C_PROCESS_H + +#include + +#include + +#include + +#include "fs.h" +#include "list.h" + +/* --------------------------------------------------------------------- + * The "atf_process_stream" type. + * --------------------------------------------------------------------- */ + +struct atf_process_stream { + int m_type; + + /* Valid if m_type == connect. */ + int m_src_fd; + int m_tgt_fd; + + /* Valid if m_type == redirect_fd. */ + int m_fd; + + /* Valid if m_type == redirect_path. */ + const atf_fs_path_t *m_path; +}; +typedef struct atf_process_stream atf_process_stream_t; + +extern const int atf_process_stream_type_capture; +extern const int atf_process_stream_type_connect; +extern const int atf_process_stream_type_inherit; +extern const int atf_process_stream_type_redirect_fd; +extern const int atf_process_stream_type_redirect_path; + +atf_error_t atf_process_stream_init_capture(atf_process_stream_t *); +atf_error_t atf_process_stream_init_connect(atf_process_stream_t *, + const int, const int); +atf_error_t atf_process_stream_init_inherit(atf_process_stream_t *); +atf_error_t atf_process_stream_init_redirect_fd(atf_process_stream_t *, + const int fd); +atf_error_t atf_process_stream_init_redirect_path(atf_process_stream_t *, + const atf_fs_path_t *); +void atf_process_stream_fini(atf_process_stream_t *); + +int atf_process_stream_type(const atf_process_stream_t *); + +/* --------------------------------------------------------------------- + * The "atf_process_status" type. + * --------------------------------------------------------------------- */ + +struct atf_process_status { + int m_status; +}; +typedef struct atf_process_status atf_process_status_t; + +void atf_process_status_fini(atf_process_status_t *); + +bool atf_process_status_exited(const atf_process_status_t *); +int atf_process_status_exitstatus(const atf_process_status_t *); +bool atf_process_status_signaled(const atf_process_status_t *); +int atf_process_status_termsig(const atf_process_status_t *); +bool atf_process_status_coredump(const atf_process_status_t *); + +/* --------------------------------------------------------------------- + * The "atf_process_child" type. + * --------------------------------------------------------------------- */ + +struct atf_process_child { + pid_t m_pid; + + int m_stdout; + int m_stderr; +}; +typedef struct atf_process_child atf_process_child_t; + +atf_error_t atf_process_child_wait(atf_process_child_t *, + atf_process_status_t *); +pid_t atf_process_child_pid(const atf_process_child_t *); +int atf_process_child_stdout(atf_process_child_t *); +int atf_process_child_stderr(atf_process_child_t *); + +/* --------------------------------------------------------------------- + * Free functions. + * --------------------------------------------------------------------- */ + +atf_error_t atf_process_fork(atf_process_child_t *, + void (*)(void *), + const atf_process_stream_t *, + const atf_process_stream_t *, + void *); +atf_error_t atf_process_exec_array(atf_process_status_t *, + const atf_fs_path_t *, + const char *const *, + const atf_process_stream_t *, + const atf_process_stream_t *, + void (*)(void)); +atf_error_t atf_process_exec_list(atf_process_status_t *, + const atf_fs_path_t *, + const atf_list_t *, + const atf_process_stream_t *, + const atf_process_stream_t *, + void (*)(void)); + +#endif /* !defined(ATF_C_PROCESS_H) */ diff --git a/external/bsd/atf/dist/atf-c/detail/process_helpers.c b/external/bsd/atf/dist/atf-c/detail/process_helpers.c new file mode 100644 index 000000000..61f1b67c9 --- /dev/null +++ b/external/bsd/atf/dist/atf-c/detail/process_helpers.c @@ -0,0 +1,117 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include /* NO_CHECK_STYLE */ +#include +#include +#include +#include +#include + +static +int +h_echo(const char *msg) +{ + printf("%s\n", msg); + return EXIT_SUCCESS; +} + +static +int +h_exit_failure(void) +{ + return EXIT_FAILURE; +} + +static +int +h_exit_signal(void) +{ + kill(getpid(), SIGKILL); + assert(0); /* NO_CHECK_STYLE */ + return EXIT_FAILURE; +} + +static +int +h_exit_success(void) +{ + return EXIT_SUCCESS; +} + +static +int +h_stdout_stderr(const char *id) +{ + fprintf(stdout, "Line 1 to stdout for %s\n", id); + fprintf(stdout, "Line 2 to stdout for %s\n", id); + fprintf(stderr, "Line 1 to stderr for %s\n", id); + fprintf(stderr, "Line 2 to stderr for %s\n", id); + + return EXIT_SUCCESS; +} + +static +void +check_args(const int argc, const char *const argv[], const int required) +{ + if (argc < required) { + fprintf(stderr, "Usage: %s helper-name [args]\n", argv[0]); + exit(EXIT_FAILURE); + } +} + +int +main(int argc, const char *const argv[]) +{ + int exitcode; + + check_args(argc, argv, 2); + + if (strcmp(argv[1], "echo") == 0) { + check_args(argc, argv, 3); + exitcode = h_echo(argv[2]); + } else if (strcmp(argv[1], "exit-failure") == 0) + exitcode = h_exit_failure(); + else if (strcmp(argv[1], "exit-signal") == 0) + exitcode = h_exit_signal(); + else if (strcmp(argv[1], "exit-success") == 0) + exitcode = h_exit_success(); + else if (strcmp(argv[1], "stdout-stderr") == 0) { + check_args(argc, argv, 3); + exitcode = h_stdout_stderr(argv[2]); + } else { + fprintf(stderr, "%s: Unknown helper %s\n", argv[0], argv[1]); + exitcode = EXIT_FAILURE; + } + + return exitcode; +} diff --git a/external/bsd/atf/dist/atf-c/detail/process_test.c b/external/bsd/atf/dist/atf-c/detail/process_test.c new file mode 100644 index 000000000..dcd51a7cc --- /dev/null +++ b/external/bsd/atf/dist/atf-c/detail/process_test.c @@ -0,0 +1,1165 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "atf-c/defs.h" + +#include "process.h" +#include "sanity.h" +#include "test_helpers.h" + +atf_error_t atf_process_status_init(atf_process_status_t *, int); + +/* --------------------------------------------------------------------- + * Auxiliary functions for testing of 'atf_process_fork'. + * --------------------------------------------------------------------- */ + +/* + * Testing of atf_process_fork is quite messy. We want to be able to test + * all the possible combinations of stdout and stderr behavior to ensure + * that the streams are manipulated correctly. + * + * To do this, the do_fork function is a wrapper for atf_process_fork that + * issues stream-specific hooks before fork, while the child is running and + * after the child terminates. We then provide test cases that just call + * do_fork with different hooks. + * + * The hooks are described by base_stream, and we then have one *_stream + * type for ever possible stream behavior. + */ + +enum out_type { stdout_type, stderr_type }; + +struct base_stream { + void (*init)(void *); + void (*process)(void *, atf_process_child_t *); + void (*fini)(void *); + + /* m_sb is initialized by subclasses that need it, but all consumers + * must use m_sb_ptr, which may or may not point to m_sb. This allows + * us to test the interface with a NULL value, which triggers a + * default behavior. */ + atf_process_stream_t m_sb; + atf_process_stream_t *m_sb_ptr; + enum out_type m_type; +}; +#define BASE_STREAM(ihook, phook, fhook, type) \ + { .init = ihook, \ + .process = phook, \ + .fini = fhook, \ + .m_type = type } + +static +void +check_file(const enum out_type type) +{ + switch (type) { + case stdout_type: + ATF_CHECK(atf_utils_grep_file("stdout: msg", "stdout")); + ATF_CHECK(!atf_utils_grep_file("stderr: msg", "stdout")); + break; + case stderr_type: + ATF_CHECK(atf_utils_grep_file("stderr: msg", "stderr")); + ATF_CHECK(!atf_utils_grep_file("stdout: msg", "stderr")); + break; + default: + UNREACHABLE; + } +} + +struct capture_stream { + struct base_stream m_base; + + char *m_msg; +}; +#define CAPTURE_STREAM(type) \ + { .m_base = BASE_STREAM(capture_stream_init, \ + capture_stream_process, \ + capture_stream_fini, \ + type) } + +static +void +capture_stream_init(void *v) +{ + struct capture_stream *s = v; + + s->m_base.m_sb_ptr = &s->m_base.m_sb; + RE(atf_process_stream_init_capture(&s->m_base.m_sb)); + s->m_msg = NULL; +} + +static +void +capture_stream_process(void *v, atf_process_child_t *c) +{ + struct capture_stream *s = v; + + switch (s->m_base.m_type) { + case stdout_type: + s->m_msg = atf_utils_readline(atf_process_child_stdout(c)); + break; + case stderr_type: + s->m_msg = atf_utils_readline(atf_process_child_stderr(c)); + break; + default: + UNREACHABLE; + } +} + +static +void +capture_stream_fini(void *v) +{ + struct capture_stream *s = v; + + switch (s->m_base.m_type) { + case stdout_type: + ATF_CHECK(atf_utils_grep_string("stdout: msg", s->m_msg)); + ATF_CHECK(!atf_utils_grep_string("stderr: msg", s->m_msg)); + break; + case stderr_type: + ATF_CHECK(!atf_utils_grep_string("stdout: msg", s->m_msg)); + ATF_CHECK(atf_utils_grep_string("stderr: msg", s->m_msg)); + break; + default: + UNREACHABLE; + } + + free(s->m_msg); + atf_process_stream_fini(&s->m_base.m_sb); +} + +struct connect_stream { + struct base_stream m_base; + + int m_fd; +}; +#define CONNECT_STREAM(type) \ + { .m_base = BASE_STREAM(connect_stream_init, \ + NULL, \ + connect_stream_fini, \ + type) } + +static +void +connect_stream_init(void *v) +{ + struct connect_stream *s = v; + int src_fd; + + switch (s->m_base.m_type) { + case stdout_type: + src_fd = STDOUT_FILENO; + s->m_fd = open("stdout", O_WRONLY | O_CREAT | O_TRUNC, 0644); + break; + case stderr_type: + src_fd = STDERR_FILENO; + s->m_fd = open("stderr", O_WRONLY | O_CREAT | O_TRUNC, 0644); + break; + default: + UNREACHABLE; + src_fd = -1; + } + ATF_REQUIRE(s->m_fd != -1); + + s->m_base.m_sb_ptr = &s->m_base.m_sb; + RE(atf_process_stream_init_connect(&s->m_base.m_sb, src_fd, s->m_fd)); +} + +static +void +connect_stream_fini(void *v) +{ + struct connect_stream *s = v; + + ATF_REQUIRE(close(s->m_fd) != -1); + + atf_process_stream_fini(&s->m_base.m_sb); + + check_file(s->m_base.m_type); +} + +struct inherit_stream { + struct base_stream m_base; + int m_fd; + + int m_old_fd; +}; +#define INHERIT_STREAM(type) \ + { .m_base = BASE_STREAM(inherit_stream_init, \ + NULL, \ + inherit_stream_fini, \ + type) } + +static +void +inherit_stream_init(void *v) +{ + struct inherit_stream *s = v; + const char *name; + + s->m_base.m_sb_ptr = &s->m_base.m_sb; + RE(atf_process_stream_init_inherit(&s->m_base.m_sb)); + + switch (s->m_base.m_type) { + case stdout_type: + s->m_fd = STDOUT_FILENO; + name = "stdout"; + break; + case stderr_type: + s->m_fd = STDERR_FILENO; + name = "stderr"; + break; + default: + UNREACHABLE; + name = NULL; + } + + s->m_old_fd = dup(s->m_fd); + ATF_REQUIRE(s->m_old_fd != -1); + ATF_REQUIRE(close(s->m_fd) != -1); + ATF_REQUIRE_EQ(open(name, O_WRONLY | O_CREAT | O_TRUNC, 0644), + s->m_fd); +} + +static +void +inherit_stream_fini(void *v) +{ + struct inherit_stream *s = v; + + ATF_REQUIRE(dup2(s->m_old_fd, s->m_fd) != -1); + ATF_REQUIRE(close(s->m_old_fd) != -1); + + atf_process_stream_fini(&s->m_base.m_sb); + + check_file(s->m_base.m_type); +} + +#define default_stream inherit_stream +#define DEFAULT_STREAM(type) \ + { .m_base = BASE_STREAM(default_stream_init, \ + NULL, \ + default_stream_fini, \ + type) } + +static +void +default_stream_init(void *v) +{ + struct inherit_stream *s = v; + + inherit_stream_init(v); + s->m_base.m_sb_ptr = NULL; +} + +static +void +default_stream_fini(void *v) +{ + inherit_stream_fini(v); +} + +struct redirect_fd_stream { + struct base_stream m_base; + + int m_fd; +}; +#define REDIRECT_FD_STREAM(type) \ + { .m_base = BASE_STREAM(redirect_fd_stream_init, \ + NULL, \ + redirect_fd_stream_fini, \ + type) } + +static +void +redirect_fd_stream_init(void *v) +{ + struct redirect_fd_stream *s = v; + + switch (s->m_base.m_type) { + case stdout_type: + s->m_fd = open("stdout", O_WRONLY | O_CREAT | O_TRUNC, 0644); + break; + case stderr_type: + s->m_fd = open("stderr", O_WRONLY | O_CREAT | O_TRUNC, 0644); + break; + default: + UNREACHABLE; + } + ATF_REQUIRE(s->m_fd != -1); + + s->m_base.m_sb_ptr = &s->m_base.m_sb; + RE(atf_process_stream_init_redirect_fd(&s->m_base.m_sb, s->m_fd)); +} + +static +void +redirect_fd_stream_fini(void *v) +{ + struct redirect_fd_stream *s = v; + + ATF_REQUIRE(close(s->m_fd) != -1); + + atf_process_stream_fini(&s->m_base.m_sb); + + check_file(s->m_base.m_type); +} + +struct redirect_path_stream { + struct base_stream m_base; + + atf_fs_path_t m_path; +}; +#define REDIRECT_PATH_STREAM(type) \ + { .m_base = BASE_STREAM(redirect_path_stream_init, \ + NULL, \ + redirect_path_stream_fini, \ + type) } + +static +void +redirect_path_stream_init(void *v) +{ + struct redirect_path_stream *s = v; + + switch (s->m_base.m_type) { + case stdout_type: + RE(atf_fs_path_init_fmt(&s->m_path, "stdout")); + break; + case stderr_type: + RE(atf_fs_path_init_fmt(&s->m_path, "stderr")); + break; + default: + UNREACHABLE; + } + + s->m_base.m_sb_ptr = &s->m_base.m_sb; + RE(atf_process_stream_init_redirect_path(&s->m_base.m_sb, &s->m_path)); +} + +static +void +redirect_path_stream_fini(void *v) +{ + struct redirect_path_stream *s = v; + + atf_process_stream_fini(&s->m_base.m_sb); + + atf_fs_path_fini(&s->m_path); + + check_file(s->m_base.m_type); +} + +static void child_print(void *) ATF_DEFS_ATTRIBUTE_NORETURN; + +struct child_print_data { + const char *m_msg; +}; + +static +void +child_print(void *v) +{ + struct child_print_data *cpd = v; + + fprintf(stdout, "stdout: %s\n", cpd->m_msg); + fprintf(stderr, "stderr: %s\n", cpd->m_msg); + + exit(EXIT_SUCCESS); +} + +static +void +do_fork(const struct base_stream *outfs, void *out, + const struct base_stream *errfs, void *err) +{ + atf_process_child_t child; + atf_process_status_t status; + struct child_print_data cpd = { "msg" }; + + outfs->init(out); + errfs->init(err); + + RE(atf_process_fork(&child, child_print, outfs->m_sb_ptr, + errfs->m_sb_ptr, &cpd)); + if (outfs->process != NULL) + outfs->process(out, &child); + if (errfs->process != NULL) + errfs->process(err, &child); + RE(atf_process_child_wait(&child, &status)); + + outfs->fini(out); + errfs->fini(err); + + atf_process_status_fini(&status); +} + +/* --------------------------------------------------------------------- + * Test cases for the "stream" type. + * --------------------------------------------------------------------- */ + +ATF_TC(stream_init_capture); +ATF_TC_HEAD(stream_init_capture, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the " + "atf_process_stream_init_capture function"); +} +ATF_TC_BODY(stream_init_capture, tc) +{ + atf_process_stream_t sb; + + RE(atf_process_stream_init_capture(&sb)); + + ATF_CHECK_EQ(atf_process_stream_type(&sb), + atf_process_stream_type_capture); + + atf_process_stream_fini(&sb); +} + +ATF_TC(stream_init_connect); +ATF_TC_HEAD(stream_init_connect, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the " + "atf_process_stream_init_connect function"); +} +ATF_TC_BODY(stream_init_connect, tc) +{ + atf_process_stream_t sb; + + RE(atf_process_stream_init_connect(&sb, 1, 2)); + + ATF_CHECK_EQ(atf_process_stream_type(&sb), + atf_process_stream_type_connect); + + atf_process_stream_fini(&sb); +} + +ATF_TC(stream_init_inherit); +ATF_TC_HEAD(stream_init_inherit, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the " + "atf_process_stream_init_inherit function"); +} +ATF_TC_BODY(stream_init_inherit, tc) +{ + atf_process_stream_t sb; + + RE(atf_process_stream_init_inherit(&sb)); + + ATF_CHECK_EQ(atf_process_stream_type(&sb), + atf_process_stream_type_inherit); + + atf_process_stream_fini(&sb); +} + +ATF_TC(stream_init_redirect_fd); +ATF_TC_HEAD(stream_init_redirect_fd, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the " + "atf_process_stream_init_redirect_fd function"); +} +ATF_TC_BODY(stream_init_redirect_fd, tc) +{ + atf_process_stream_t sb; + + RE(atf_process_stream_init_redirect_fd(&sb, 1)); + + ATF_CHECK_EQ(atf_process_stream_type(&sb), + atf_process_stream_type_redirect_fd); + + atf_process_stream_fini(&sb); +} + +ATF_TC(stream_init_redirect_path); +ATF_TC_HEAD(stream_init_redirect_path, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the " + "atf_process_stream_init_redirect_path function"); +} +ATF_TC_BODY(stream_init_redirect_path, tc) +{ + atf_process_stream_t sb; + atf_fs_path_t path; + + RE(atf_fs_path_init_fmt(&path, "foo")); + RE(atf_process_stream_init_redirect_path(&sb, &path)); + + ATF_CHECK_EQ(atf_process_stream_type(&sb), + atf_process_stream_type_redirect_path); + + atf_process_stream_fini(&sb); + atf_fs_path_fini(&path); +} + +/* --------------------------------------------------------------------- + * Test cases for the "status" type. + * --------------------------------------------------------------------- */ + +static void child_exit_success(void) ATF_DEFS_ATTRIBUTE_NORETURN; +static void child_exit_failure(void) ATF_DEFS_ATTRIBUTE_NORETURN; +static void child_sigkill(void) ATF_DEFS_ATTRIBUTE_NORETURN; +static void child_sigquit(void) ATF_DEFS_ATTRIBUTE_NORETURN; +static void child_sigterm(void) ATF_DEFS_ATTRIBUTE_NORETURN; + +void +child_exit_success(void) +{ + exit(EXIT_SUCCESS); +} + +void +child_exit_failure(void) +{ + exit(EXIT_FAILURE); +} + +void +child_sigkill(void) +{ + kill(getpid(), SIGKILL); + abort(); +} + +void +child_sigquit(void) +{ + kill(getpid(), SIGQUIT); + abort(); +} + +void +child_sigterm(void) +{ + kill(getpid(), SIGTERM); + abort(); +} + +static +int +fork_and_wait_child(void (*child_func)(void)) +{ + pid_t pid; + int status; + + pid = fork(); + ATF_REQUIRE(pid != -1); + if (pid == 0) { + status = 0; /* Silence compiler warnings */ + child_func(); + UNREACHABLE; + } else { + ATF_REQUIRE(waitpid(pid, &status, 0) != 0); + } + + return status; +} + +ATF_TC(status_exited); +ATF_TC_HEAD(status_exited, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the status type for processes " + "that exit cleanly"); +} +ATF_TC_BODY(status_exited, tc) +{ + { + const int rawstatus = fork_and_wait_child(child_exit_success); + atf_process_status_t s; + RE(atf_process_status_init(&s, rawstatus)); + ATF_CHECK(atf_process_status_exited(&s)); + ATF_CHECK_EQ(atf_process_status_exitstatus(&s), EXIT_SUCCESS); + ATF_CHECK(!atf_process_status_signaled(&s)); + atf_process_status_fini(&s); + } + + { + const int rawstatus = fork_and_wait_child(child_exit_failure); + atf_process_status_t s; + RE(atf_process_status_init(&s, rawstatus)); + ATF_CHECK(atf_process_status_exited(&s)); + ATF_CHECK_EQ(atf_process_status_exitstatus(&s), EXIT_FAILURE); + ATF_CHECK(!atf_process_status_signaled(&s)); + atf_process_status_fini(&s); + } +} + +ATF_TC(status_signaled); +ATF_TC_HEAD(status_signaled, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the status type for processes " + "that end due to a signal"); +} +ATF_TC_BODY(status_signaled, tc) +{ + { + const int rawstatus = fork_and_wait_child(child_sigkill); + atf_process_status_t s; + RE(atf_process_status_init(&s, rawstatus)); + ATF_CHECK(!atf_process_status_exited(&s)); + ATF_CHECK(atf_process_status_signaled(&s)); + ATF_CHECK_EQ(atf_process_status_termsig(&s), SIGKILL); + ATF_CHECK(!atf_process_status_coredump(&s)); + atf_process_status_fini(&s); + } + + { + const int rawstatus = fork_and_wait_child(child_sigterm); + atf_process_status_t s; + RE(atf_process_status_init(&s, rawstatus)); + ATF_CHECK(!atf_process_status_exited(&s)); + ATF_CHECK(atf_process_status_signaled(&s)); + ATF_CHECK_EQ(atf_process_status_termsig(&s), SIGTERM); + ATF_CHECK(!atf_process_status_coredump(&s)); + atf_process_status_fini(&s); + } +} + +ATF_TC(status_coredump); +ATF_TC_HEAD(status_coredump, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the status type for processes " + "that crash"); +} +ATF_TC_BODY(status_coredump, tc) +{ +#if !defined(__minix) + struct rlimit rl; + rl.rlim_cur = RLIM_INFINITY; + rl.rlim_max = RLIM_INFINITY; + if (setrlimit(RLIMIT_CORE, &rl) == -1) + atf_tc_skip("Cannot unlimit the core file size; check limits " + "manually"); +#endif + + const int rawstatus = fork_and_wait_child(child_sigquit); + atf_process_status_t s; + RE(atf_process_status_init(&s, rawstatus)); + ATF_CHECK(!atf_process_status_exited(&s)); + ATF_CHECK(atf_process_status_signaled(&s)); + ATF_CHECK_EQ(atf_process_status_termsig(&s), SIGQUIT); + ATF_CHECK(atf_process_status_coredump(&s)); + atf_process_status_fini(&s); +} + +/* --------------------------------------------------------------------- + * Test cases for the "child" type. + * --------------------------------------------------------------------- */ + +static void child_report_pid(void *) ATF_DEFS_ATTRIBUTE_NORETURN; + +static +void +child_report_pid(void *v ATF_DEFS_ATTRIBUTE_UNUSED) +{ + const pid_t pid = getpid(); + if (write(STDOUT_FILENO, &pid, sizeof(pid)) != sizeof(pid)) + abort(); + fprintf(stderr, "Reporting %d to parent\n", (int)getpid()); + exit(EXIT_SUCCESS); +} + +ATF_TC(child_pid); +ATF_TC_HEAD(child_pid, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the correctness of the pid " + "stored in the child type"); +} +ATF_TC_BODY(child_pid, tc) +{ + atf_process_stream_t outsb, errsb; + atf_process_child_t child; + atf_process_status_t status; + pid_t pid; + + RE(atf_process_stream_init_capture(&outsb)); + RE(atf_process_stream_init_inherit(&errsb)); + + RE(atf_process_fork(&child, child_report_pid, &outsb, &errsb, NULL)); + ATF_CHECK_EQ(read(atf_process_child_stdout(&child), &pid, sizeof(pid)), + sizeof(pid)); + printf("Expected PID: %d\n", (int)atf_process_child_pid(&child)); + printf("Actual PID: %d\n", (int)pid); + ATF_CHECK_EQ(atf_process_child_pid(&child), pid); + + RE(atf_process_child_wait(&child, &status)); + atf_process_status_fini(&status); + + atf_process_stream_fini(&outsb); + atf_process_stream_fini(&errsb); +} + +static +void +child_loop(void *v ATF_DEFS_ATTRIBUTE_UNUSED) +{ + for (;;) + sleep(1); +} + +static +void +nop_signal(int sig ATF_DEFS_ATTRIBUTE_UNUSED) +{ +} + +static +void +child_spawn_loop_and_wait_eintr(void *v ATF_DEFS_ATTRIBUTE_UNUSED) +{ + atf_process_child_t child; + atf_process_status_t status; + struct sigaction sighup, old_sighup; + +#define RE_ABORT(expr) \ + do { \ + atf_error_t _aux_err = expr; \ + if (atf_is_error(_aux_err)) { \ + atf_error_free(_aux_err); \ + abort(); \ + } \ + } while (0) + + { + atf_process_stream_t outsb, errsb; + + RE_ABORT(atf_process_stream_init_capture(&outsb)); + RE_ABORT(atf_process_stream_init_inherit(&errsb)); + RE_ABORT(atf_process_fork(&child, child_loop, &outsb, &errsb, NULL)); + atf_process_stream_fini(&outsb); + atf_process_stream_fini(&errsb); + } + + sighup.sa_handler = nop_signal; + sigemptyset(&sighup.sa_mask); + sighup.sa_flags = 0; + if (sigaction(SIGHUP, &sighup, &old_sighup) == -1) + abort(); + + printf("waiting\n"); + fflush(stdout); + + fprintf(stderr, "Child entering wait(2)\n"); + atf_error_t err = atf_process_child_wait(&child, &status); + fprintf(stderr, "Child's wait(2) terminated\n"); + if (!atf_is_error(err)) { + fprintf(stderr, "wait completed successfully (not interrupted)\n"); + abort(); + } + if (!atf_error_is(err, "libc")) { + fprintf(stderr, "wait did not raise libc_error\n"); + abort(); + } + if (atf_libc_error_code(err) != EINTR) { + fprintf(stderr, "libc_error is not EINTR\n"); + abort(); + } + atf_error_free(err); + + sigaction(SIGHUP, &old_sighup, NULL); + + fprintf(stderr, "Child is killing subchild\n"); + kill(atf_process_child_pid(&child), SIGTERM); + + RE_ABORT(atf_process_child_wait(&child, &status)); + atf_process_status_fini(&status); + +#undef RE_ABORT + + exit(EXIT_SUCCESS); +} + +ATF_TC(child_wait_eintr); +ATF_TC_HEAD(child_wait_eintr, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the interruption of the wait " + "method by an external signal, and the return of " + "an EINTR error"); + atf_tc_set_md_var(tc, "timeout", "30"); +} +ATF_TC_BODY(child_wait_eintr, tc) +{ + atf_process_child_t child; + atf_process_status_t status; + + { + atf_process_stream_t outsb, errsb; + + RE(atf_process_stream_init_capture(&outsb)); + RE(atf_process_stream_init_inherit(&errsb)); + RE(atf_process_fork(&child, child_spawn_loop_and_wait_eintr, + &outsb, &errsb, NULL)); + atf_process_stream_fini(&outsb); + atf_process_stream_fini(&errsb); + } + + { + /* Wait until the child process performs the wait call. This is + * racy, because the message we get from it is sent *before* + * doing the real system call... but I can't figure any other way + * to do this. */ + char buf[16]; + printf("Waiting for child to issue wait(2)\n"); + ATF_REQUIRE(read(atf_process_child_stdout(&child), buf, + sizeof(buf)) > 0); + sleep(1); + } + + printf("Interrupting child's wait(2) call\n"); + kill(atf_process_child_pid(&child), SIGHUP); + + printf("Waiting for child's completion\n"); + RE(atf_process_child_wait(&child, &status)); + ATF_REQUIRE(atf_process_status_exited(&status)); + ATF_REQUIRE_EQ(atf_process_status_exitstatus(&status), EXIT_SUCCESS); + atf_process_status_fini(&status); +} + +/* --------------------------------------------------------------------- + * Tests cases for the free functions. + * --------------------------------------------------------------------- */ + +static +void +do_exec(const atf_tc_t *tc, const char *helper_name, atf_process_status_t *s, + void (*prehook)(void)) +{ + atf_fs_path_t process_helpers; + const char *argv[3]; + + get_process_helpers_path(tc, true, &process_helpers); + + argv[0] = atf_fs_path_cstring(&process_helpers); + argv[1] = helper_name; + argv[2] = NULL; + printf("Executing %s %s\n", argv[0], argv[1]); + + RE(atf_process_exec_array(s, &process_helpers, argv, NULL, NULL, prehook)); + atf_fs_path_fini(&process_helpers); +} + +static +void +check_line(int fd, const char *exp) +{ + char *line = atf_utils_readline(fd); + ATF_CHECK(line != NULL); + ATF_CHECK_STREQ_MSG(exp, line, "read: '%s', expected: '%s'", line, exp); + free(line); +} + +ATF_TC(exec_failure); +ATF_TC_HEAD(exec_failure, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests execing a command"); +} +ATF_TC_BODY(exec_failure, tc) +{ + atf_process_status_t status; + + do_exec(tc, "exit-failure", &status, NULL); + ATF_CHECK(atf_process_status_exited(&status)); + ATF_CHECK_EQ(atf_process_status_exitstatus(&status), EXIT_FAILURE); + atf_process_status_fini(&status); +} + +ATF_TC(exec_list); +ATF_TC_HEAD(exec_list, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests execing a command"); +} +ATF_TC_BODY(exec_list, tc) +{ + atf_fs_path_t process_helpers; + atf_list_t argv; + atf_process_status_t status; + + RE(atf_list_init(&argv)); + + get_process_helpers_path(tc, true, &process_helpers); + atf_list_append(&argv, strdup(atf_fs_path_cstring(&process_helpers)), true); + atf_list_append(&argv, strdup("echo"), true); + atf_list_append(&argv, strdup("test-message"), true); + { + atf_fs_path_t outpath; + atf_process_stream_t outsb; + + RE(atf_fs_path_init_fmt(&outpath, "stdout")); + RE(atf_process_stream_init_redirect_path(&outsb, &outpath)); + RE(atf_process_exec_list(&status, &process_helpers, &argv, &outsb, + NULL, NULL)); + atf_process_stream_fini(&outsb); + atf_fs_path_fini(&outpath); + } + atf_list_fini(&argv); + + ATF_CHECK(atf_process_status_exited(&status)); + ATF_CHECK_EQ(atf_process_status_exitstatus(&status), EXIT_SUCCESS); + + { + int fd = open("stdout", O_RDONLY); + ATF_CHECK(fd != -1); + check_line(fd, "test-message"); + close(fd); + } + + atf_process_status_fini(&status); + atf_fs_path_fini(&process_helpers); +} + +static void +exit_early(void) +{ + exit(80); +} + +ATF_TC(exec_prehook); +ATF_TC_HEAD(exec_prehook, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests execing a command with a prehook"); +} +ATF_TC_BODY(exec_prehook, tc) +{ + atf_process_status_t status; + + do_exec(tc, "exit-success", &status, exit_early); + ATF_CHECK(atf_process_status_exited(&status)); + ATF_CHECK_EQ(atf_process_status_exitstatus(&status), 80); + atf_process_status_fini(&status); +} + +ATF_TC(exec_success); +ATF_TC_HEAD(exec_success, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests execing a command"); +} +ATF_TC_BODY(exec_success, tc) +{ + atf_process_status_t status; + + do_exec(tc, "exit-success", &status, NULL); + ATF_CHECK(atf_process_status_exited(&status)); + ATF_CHECK_EQ(atf_process_status_exitstatus(&status), EXIT_SUCCESS); + atf_process_status_fini(&status); +} + +static const int exit_v_null = 1; +static const int exit_v_notnull = 2; + +static +void +child_cookie(void *v) +{ + if (v == NULL) + exit(exit_v_null); + else + exit(exit_v_notnull); + + UNREACHABLE; +} + +ATF_TC(fork_cookie); +ATF_TC_HEAD(fork_cookie, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests forking a child, with " + "a null and non-null data cookie"); +} +ATF_TC_BODY(fork_cookie, tc) +{ + atf_process_stream_t outsb, errsb; + + RE(atf_process_stream_init_inherit(&outsb)); + RE(atf_process_stream_init_inherit(&errsb)); + + { + atf_process_child_t child; + atf_process_status_t status; + + RE(atf_process_fork(&child, child_cookie, &outsb, &errsb, NULL)); + RE(atf_process_child_wait(&child, &status)); + + ATF_CHECK(atf_process_status_exited(&status)); + ATF_CHECK_EQ(atf_process_status_exitstatus(&status), exit_v_null); + + atf_process_status_fini(&status); + } + + { + atf_process_child_t child; + atf_process_status_t status; + int dummy_int; + + RE(atf_process_fork(&child, child_cookie, &outsb, &errsb, &dummy_int)); + RE(atf_process_child_wait(&child, &status)); + + ATF_CHECK(atf_process_status_exited(&status)); + ATF_CHECK_EQ(atf_process_status_exitstatus(&status), exit_v_notnull); + + atf_process_status_fini(&status); + } + + atf_process_stream_fini(&errsb); + atf_process_stream_fini(&outsb); +} + +#define TC_FORK_STREAMS(outlc, outuc, errlc, erruc) \ + ATF_TC(fork_out_ ## outlc ## _err_ ## errlc); \ + ATF_TC_HEAD(fork_out_ ## outlc ## _err_ ## errlc, tc) \ + { \ + atf_tc_set_md_var(tc, "descr", "Tests forking a child, with " \ + "stdout " #outlc " and stderr " #errlc); \ + } \ + ATF_TC_BODY(fork_out_ ## outlc ## _err_ ## errlc, tc) \ + { \ + struct outlc ## _stream out = outuc ## _STREAM(stdout_type); \ + struct errlc ## _stream err = erruc ## _STREAM(stderr_type); \ + do_fork(&out.m_base, &out, &err.m_base, &err); \ + } + +TC_FORK_STREAMS(capture, CAPTURE, capture, CAPTURE); +TC_FORK_STREAMS(capture, CAPTURE, connect, CONNECT); +TC_FORK_STREAMS(capture, CAPTURE, default, DEFAULT); +TC_FORK_STREAMS(capture, CAPTURE, inherit, INHERIT); +TC_FORK_STREAMS(capture, CAPTURE, redirect_fd, REDIRECT_FD); +TC_FORK_STREAMS(capture, CAPTURE, redirect_path, REDIRECT_PATH); +TC_FORK_STREAMS(connect, CONNECT, capture, CAPTURE); +TC_FORK_STREAMS(connect, CONNECT, connect, CONNECT); +TC_FORK_STREAMS(connect, CONNECT, default, DEFAULT); +TC_FORK_STREAMS(connect, CONNECT, inherit, INHERIT); +TC_FORK_STREAMS(connect, CONNECT, redirect_fd, REDIRECT_FD); +TC_FORK_STREAMS(connect, CONNECT, redirect_path, REDIRECT_PATH); +TC_FORK_STREAMS(default, DEFAULT, capture, CAPTURE); +TC_FORK_STREAMS(default, DEFAULT, connect, CONNECT); +TC_FORK_STREAMS(default, DEFAULT, default, DEFAULT); +TC_FORK_STREAMS(default, DEFAULT, inherit, INHERIT); +TC_FORK_STREAMS(default, DEFAULT, redirect_fd, REDIRECT_FD); +TC_FORK_STREAMS(default, DEFAULT, redirect_path, REDIRECT_PATH); +TC_FORK_STREAMS(inherit, INHERIT, capture, CAPTURE); +TC_FORK_STREAMS(inherit, INHERIT, connect, CONNECT); +TC_FORK_STREAMS(inherit, INHERIT, default, DEFAULT); +TC_FORK_STREAMS(inherit, INHERIT, inherit, INHERIT); +TC_FORK_STREAMS(inherit, INHERIT, redirect_fd, REDIRECT_FD); +TC_FORK_STREAMS(inherit, INHERIT, redirect_path, REDIRECT_PATH); +TC_FORK_STREAMS(redirect_fd, REDIRECT_FD, capture, CAPTURE); +TC_FORK_STREAMS(redirect_fd, REDIRECT_FD, connect, CONNECT); +TC_FORK_STREAMS(redirect_fd, REDIRECT_FD, default, DEFAULT); +TC_FORK_STREAMS(redirect_fd, REDIRECT_FD, inherit, INHERIT); +TC_FORK_STREAMS(redirect_fd, REDIRECT_FD, redirect_fd, REDIRECT_FD); +TC_FORK_STREAMS(redirect_fd, REDIRECT_FD, redirect_path, REDIRECT_PATH); +TC_FORK_STREAMS(redirect_path, REDIRECT_PATH, capture, CAPTURE); +TC_FORK_STREAMS(redirect_path, REDIRECT_PATH, connect, CONNECT); +TC_FORK_STREAMS(redirect_path, REDIRECT_PATH, default, DEFAULT); +TC_FORK_STREAMS(redirect_path, REDIRECT_PATH, inherit, INHERIT); +TC_FORK_STREAMS(redirect_path, REDIRECT_PATH, redirect_fd, REDIRECT_FD); +TC_FORK_STREAMS(redirect_path, REDIRECT_PATH, redirect_path, REDIRECT_PATH); + +#undef TC_FORK_STREAMS + +/* --------------------------------------------------------------------- + * Main. + * --------------------------------------------------------------------- */ + +ATF_TP_ADD_TCS(tp) +{ + /* Add the tests for the "stream" type. */ + ATF_TP_ADD_TC(tp, stream_init_capture); + ATF_TP_ADD_TC(tp, stream_init_connect); + ATF_TP_ADD_TC(tp, stream_init_inherit); + ATF_TP_ADD_TC(tp, stream_init_redirect_fd); + ATF_TP_ADD_TC(tp, stream_init_redirect_path); + + /* Add the tests for the "status" type. */ + ATF_TP_ADD_TC(tp, status_exited); + ATF_TP_ADD_TC(tp, status_signaled); + ATF_TP_ADD_TC(tp, status_coredump); + + /* Add the tests for the "child" type. */ + ATF_TP_ADD_TC(tp, child_pid); + ATF_TP_ADD_TC(tp, child_wait_eintr); + + /* Add the tests for the free functions. */ + ATF_TP_ADD_TC(tp, exec_failure); + ATF_TP_ADD_TC(tp, exec_list); + ATF_TP_ADD_TC(tp, exec_prehook); + ATF_TP_ADD_TC(tp, exec_success); + ATF_TP_ADD_TC(tp, fork_cookie); + ATF_TP_ADD_TC(tp, fork_out_capture_err_capture); + ATF_TP_ADD_TC(tp, fork_out_capture_err_connect); + ATF_TP_ADD_TC(tp, fork_out_capture_err_default); + ATF_TP_ADD_TC(tp, fork_out_capture_err_inherit); + ATF_TP_ADD_TC(tp, fork_out_capture_err_redirect_fd); + ATF_TP_ADD_TC(tp, fork_out_capture_err_redirect_path); + ATF_TP_ADD_TC(tp, fork_out_connect_err_capture); + ATF_TP_ADD_TC(tp, fork_out_connect_err_connect); + ATF_TP_ADD_TC(tp, fork_out_connect_err_default); + ATF_TP_ADD_TC(tp, fork_out_connect_err_inherit); + ATF_TP_ADD_TC(tp, fork_out_connect_err_redirect_fd); + ATF_TP_ADD_TC(tp, fork_out_connect_err_redirect_path); + ATF_TP_ADD_TC(tp, fork_out_default_err_capture); + ATF_TP_ADD_TC(tp, fork_out_default_err_connect); + ATF_TP_ADD_TC(tp, fork_out_default_err_default); + ATF_TP_ADD_TC(tp, fork_out_default_err_inherit); + ATF_TP_ADD_TC(tp, fork_out_default_err_redirect_fd); + ATF_TP_ADD_TC(tp, fork_out_default_err_redirect_path); + ATF_TP_ADD_TC(tp, fork_out_inherit_err_capture); + ATF_TP_ADD_TC(tp, fork_out_inherit_err_connect); + ATF_TP_ADD_TC(tp, fork_out_inherit_err_default); + ATF_TP_ADD_TC(tp, fork_out_inherit_err_inherit); + ATF_TP_ADD_TC(tp, fork_out_inherit_err_redirect_fd); + ATF_TP_ADD_TC(tp, fork_out_inherit_err_redirect_path); + ATF_TP_ADD_TC(tp, fork_out_redirect_fd_err_capture); + ATF_TP_ADD_TC(tp, fork_out_redirect_fd_err_connect); + ATF_TP_ADD_TC(tp, fork_out_redirect_fd_err_default); + ATF_TP_ADD_TC(tp, fork_out_redirect_fd_err_inherit); + ATF_TP_ADD_TC(tp, fork_out_redirect_fd_err_redirect_fd); + ATF_TP_ADD_TC(tp, fork_out_redirect_fd_err_redirect_path); + ATF_TP_ADD_TC(tp, fork_out_redirect_path_err_capture); + ATF_TP_ADD_TC(tp, fork_out_redirect_path_err_connect); + ATF_TP_ADD_TC(tp, fork_out_redirect_path_err_default); + ATF_TP_ADD_TC(tp, fork_out_redirect_path_err_inherit); + ATF_TP_ADD_TC(tp, fork_out_redirect_path_err_redirect_fd); + ATF_TP_ADD_TC(tp, fork_out_redirect_path_err_redirect_path); + + return atf_no_error(); +} diff --git a/external/bsd/atf/dist/atf-c/detail/sanity.c b/external/bsd/atf/dist/atf-c/detail/sanity.c new file mode 100644 index 000000000..d8a8905f2 --- /dev/null +++ b/external/bsd/atf/dist/atf-c/detail/sanity.c @@ -0,0 +1,78 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if defined(HAVE_CONFIG_H) +#include "bconfig.h" +#endif + +#include +#include +#include +#include + +#include "sanity.h" + +static +void +fail(const char *fmt, ...) +{ + va_list ap; + char buf[4096]; + + va_start(ap, fmt); + vsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); + warnx("%s", buf); + warnx("%s", ""); + warnx("This is probably a bug in this application or one of the " + "libraries it uses. If you believe this problem is caused " + "by, or is related to " PACKAGE_STRING ", please report it " + "to " PACKAGE_BUGREPORT " and provide as many detatils as " + "possible describing how you got to this condition."); + + abort(); +} + +void +atf_sanity_inv(const char *file, int line, const char *cond) +{ + fail("Invariant check failed at %s:%d: %s", file, line, cond); +} + +void +atf_sanity_pre(const char *file, int line, const char *cond) +{ + fail("Precondition check failed at %s:%d: %s", file, line, cond); +} + +void +atf_sanity_post(const char *file, int line, const char *cond) +{ + fail("Postcondition check failed at %s:%d: %s", file, line, cond); +} diff --git a/external/bsd/atf/dist/atf-c/detail/sanity.h b/external/bsd/atf/dist/atf-c/detail/sanity.h new file mode 100644 index 000000000..0b4f3e475 --- /dev/null +++ b/external/bsd/atf/dist/atf-c/detail/sanity.h @@ -0,0 +1,73 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if !defined(ATF_C_SANITY_H) +#define ATF_C_SANITY_H + +void atf_sanity_inv(const char *, int, const char *); +void atf_sanity_pre(const char *, int, const char *); +void atf_sanity_post(const char *, int, const char *); + +#if !defined(NDEBUG) + +#define INV(x) \ + do { \ + if (!(x)) \ + atf_sanity_inv(__FILE__, __LINE__, #x); \ + } while (0) +#define PRE(x) \ + do { \ + if (!(x)) \ + atf_sanity_pre(__FILE__, __LINE__, #x); \ + } while (0) +#define POST(x) \ + do { \ + if (!(x)) \ + atf_sanity_post(__FILE__, __LINE__, #x); \ + } while (0) + +#else /* defined(NDEBUG) */ + +#define INV(x) \ + do { \ + } while (0) + +#define PRE(x) \ + do { \ + } while (0) + +#define POST(x) \ + do { \ + } while (0) + +#endif /* !defined(NDEBUG) */ + +#define UNREACHABLE INV(0) + +#endif /* ATF_C_SANITY_H */ diff --git a/external/bsd/atf/dist/atf-c/detail/sanity_test.c b/external/bsd/atf/dist/atf-c/detail/sanity_test.c new file mode 100644 index 000000000..7c8285b51 --- /dev/null +++ b/external/bsd/atf/dist/atf-c/detail/sanity_test.c @@ -0,0 +1,233 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if defined(HAVE_CONFIG_H) +#include "bconfig.h" +#endif + +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include "dynstr.h" +#include "process.h" +#include "sanity.h" +#include "test_helpers.h" + +/* --------------------------------------------------------------------- + * Auxiliary functions. + * --------------------------------------------------------------------- */ + +enum type { inv, pre, post, unreachable }; + +struct test_data { + enum type m_type; + bool m_cond; +}; + +static void do_test_child(void *) ATF_DEFS_ATTRIBUTE_NORETURN; + +static +void +do_test_child(void *v) +{ + struct test_data *td = v; + + switch (td->m_type) { + case inv: + INV(td->m_cond); + break; + + case pre: + PRE(td->m_cond); + break; + + case post: + POST(td->m_cond); + break; + + case unreachable: + if (!td->m_cond) + UNREACHABLE; + break; + } + + exit(EXIT_SUCCESS); +} + +static +void +do_test(enum type t, bool cond) +{ + atf_process_child_t child; + atf_process_status_t status; + int nlines; + char *lines[3]; + + { + atf_process_stream_t outsb, errsb; + struct test_data td = { t, cond }; + + RE(atf_process_stream_init_inherit(&outsb)); + RE(atf_process_stream_init_capture(&errsb)); + RE(atf_process_fork(&child, do_test_child, &outsb, &errsb, &td)); + atf_process_stream_fini(&errsb); + atf_process_stream_fini(&outsb); + } + + nlines = 0; + while (nlines < 3 && (lines[nlines] = + atf_utils_readline(atf_process_child_stderr(&child))) != NULL) + nlines++; + ATF_REQUIRE(nlines == 0 || nlines == 3); + + RE(atf_process_child_wait(&child, &status)); + if (!cond) { + ATF_REQUIRE(atf_process_status_signaled(&status)); + ATF_REQUIRE(atf_process_status_termsig(&status) == SIGABRT); + } else { + ATF_REQUIRE(atf_process_status_exited(&status)); + ATF_REQUIRE(atf_process_status_exitstatus(&status) == EXIT_SUCCESS); + } + atf_process_status_fini(&status); + + if (!cond) { + switch (t) { + case inv: + ATF_REQUIRE(atf_utils_grep_string("Invariant", lines[0])); + break; + + case pre: + ATF_REQUIRE(atf_utils_grep_string("Precondition", lines[0])); + break; + + case post: + ATF_REQUIRE(atf_utils_grep_string("Postcondition", lines[0])); + break; + + case unreachable: + ATF_REQUIRE(atf_utils_grep_string("Invariant", lines[0])); + break; + } + + ATF_REQUIRE(atf_utils_grep_string(__FILE__, lines[0])); + ATF_REQUIRE(atf_utils_grep_string(PACKAGE_BUGREPORT, lines[2])); + } + + while (nlines > 0) { + nlines--; + free(lines[nlines]); + } +} + +static +void +require_ndebug(void) +{ +#if defined(NDEBUG) + atf_tc_skip("Sanity checks not available; code built with -DNDEBUG"); +#endif +} + +/* --------------------------------------------------------------------- + * Test cases for the free functions. + * --------------------------------------------------------------------- */ + +ATF_TC(inv); +ATF_TC_HEAD(inv, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the INV macro"); +} +ATF_TC_BODY(inv, tc) +{ + require_ndebug(); + + do_test(inv, false); + do_test(inv, true); +} + +ATF_TC(pre); +ATF_TC_HEAD(pre, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the PRE macro"); +} +ATF_TC_BODY(pre, tc) +{ + require_ndebug(); + + do_test(pre, false); + do_test(pre, true); +} + +ATF_TC(post); +ATF_TC_HEAD(post, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the POST macro"); +} +ATF_TC_BODY(post, tc) +{ + require_ndebug(); + + do_test(post, false); + do_test(post, true); +} + +ATF_TC(unreachable); +ATF_TC_HEAD(unreachable, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the UNREACHABLE macro"); +} +ATF_TC_BODY(unreachable, tc) +{ + require_ndebug(); + + do_test(unreachable, false); + do_test(unreachable, true); +} + +/* --------------------------------------------------------------------- + * Main. + * --------------------------------------------------------------------- */ + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, inv); + ATF_TP_ADD_TC(tp, pre); + ATF_TP_ADD_TC(tp, post); + ATF_TP_ADD_TC(tp, unreachable); + + return atf_no_error(); +} diff --git a/external/bsd/atf/dist/atf-c/detail/test_helpers.c b/external/bsd/atf/dist/atf-c/detail/test_helpers.c new file mode 100644 index 000000000..aa64c12de --- /dev/null +++ b/external/bsd/atf/dist/atf-c/detail/test_helpers.c @@ -0,0 +1,151 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include + +#include "atf-c/build.h" +#include "atf-c/check.h" +#include "atf-c/config.h" +#include "atf-c/error.h" +#include "atf-c/macros.h" + +#include "dynstr.h" +#include "fs.h" +#include "process.h" +#include "test_helpers.h" + +static +void +build_check_c_o_aux(const char *path, const char *failmsg, + const bool expect_pass) +{ + bool success; + atf_dynstr_t iflag; + const char *optargs[4]; + + RE(atf_dynstr_init_fmt(&iflag, "-I%s", atf_config_get("atf_includedir"))); + + optargs[0] = atf_dynstr_cstring(&iflag); + optargs[1] = "-Wall"; + optargs[2] = "-Werror"; + optargs[3] = NULL; + + RE(atf_check_build_c_o(path, "test.o", optargs, &success)); + + atf_dynstr_fini(&iflag); + + if ((expect_pass && !success) || (!expect_pass && success)) + atf_tc_fail("%s", failmsg); +} + +void +build_check_c_o(const atf_tc_t *tc, const char *sfile, const char *failmsg, + const bool expect_pass) +{ + atf_fs_path_t path; + + RE(atf_fs_path_init_fmt(&path, "%s/%s", + atf_tc_get_config_var(tc, "srcdir"), sfile)); + build_check_c_o_aux(atf_fs_path_cstring(&path), failmsg, expect_pass); + atf_fs_path_fini(&path); +} + +void +header_check(const char *hdrname) +{ + FILE *srcfile; + char failmsg[128]; + + srcfile = fopen("test.c", "w"); + ATF_REQUIRE(srcfile != NULL); + fprintf(srcfile, "#include <%s>\n", hdrname); + fclose(srcfile); + + snprintf(failmsg, sizeof(failmsg), + "Header check failed; %s is not self-contained", hdrname); + + build_check_c_o_aux("test.c", failmsg, true); +} + +void +get_process_helpers_path(const atf_tc_t *tc, const bool is_detail, + atf_fs_path_t *path) +{ + RE(atf_fs_path_init_fmt(path, "%s/%sprocess_helpers", + atf_tc_get_config_var(tc, "srcdir"), + is_detail ? "" : "detail/")); +} + +struct run_h_tc_data { + atf_tc_t *m_tc; + const char *m_resname; +}; + +static +void +run_h_tc_child(void *v) +{ + struct run_h_tc_data *data = (struct run_h_tc_data *)v; + + RE(atf_tc_run(data->m_tc, data->m_resname)); +} + +/* TODO: Investigate if it's worth to add this functionality as part of + * the public API. I.e. a function to easily run a test case body in a + * subprocess. */ +void +run_h_tc(atf_tc_t *tc, const char *outname, const char *errname, + const char *resname) +{ + atf_fs_path_t outpath, errpath; + atf_process_stream_t outb, errb; + atf_process_child_t child; + atf_process_status_t status; + + RE(atf_fs_path_init_fmt(&outpath, outname)); + RE(atf_fs_path_init_fmt(&errpath, errname)); + + struct run_h_tc_data data = { tc, resname }; + + RE(atf_process_stream_init_redirect_path(&outb, &outpath)); + RE(atf_process_stream_init_redirect_path(&errb, &errpath)); + RE(atf_process_fork(&child, run_h_tc_child, &outb, &errb, &data)); + atf_process_stream_fini(&errb); + atf_process_stream_fini(&outb); + + RE(atf_process_child_wait(&child, &status)); + ATF_CHECK(atf_process_status_exited(&status)); + atf_process_status_fini(&status); + + atf_fs_path_fini(&errpath); + atf_fs_path_fini(&outpath); +} diff --git a/external/bsd/atf/dist/atf-c/detail/test_helpers.h b/external/bsd/atf/dist/atf-c/detail/test_helpers.h new file mode 100644 index 000000000..5df034fb4 --- /dev/null +++ b/external/bsd/atf/dist/atf-c/detail/test_helpers.h @@ -0,0 +1,85 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if defined(TESTS_ATF_ATF_C_TEST_HELPERS_H) +# error "Cannot include test_helpers.h more than once." +#else +# define TESTS_ATF_ATF_C_TEST_HELPERS_H +#endif + +#include + +#include "atf-c/error_fwd.h" + +struct atf_dynstr; +struct atf_fs_path; + +#define CE(stm) ATF_CHECK(!atf_is_error(stm)) +#define RE(stm) ATF_REQUIRE(!atf_is_error(stm)) + +#define HEADER_TC(name, hdrname) \ + ATF_TC(name); \ + ATF_TC_HEAD(name, tc) \ + { \ + atf_tc_set_md_var(tc, "descr", "Tests that the " hdrname " file can " \ + "be included on its own, without any prerequisites"); \ + } \ + ATF_TC_BODY(name, tc) \ + { \ + header_check(hdrname); \ + } + +#define BUILD_TC(name, sfile, descr, failmsg) \ + ATF_TC(name); \ + ATF_TC_HEAD(name, tc) \ + { \ + atf_tc_set_md_var(tc, "descr", descr); \ + } \ + ATF_TC_BODY(name, tc) \ + { \ + build_check_c_o(tc, sfile, failmsg, true); \ + } + +#define BUILD_TC_FAIL(name, sfile, descr, failmsg) \ + ATF_TC(name); \ + ATF_TC_HEAD(name, tc) \ + { \ + atf_tc_set_md_var(tc, "descr", descr); \ + } \ + ATF_TC_BODY(name, tc) \ + { \ + build_check_c_o(tc, sfile, failmsg, false); \ + } + +void build_check_c_o(const atf_tc_t *, const char *, const char *, const bool); +void header_check(const char *); +void get_process_helpers_path(const atf_tc_t *, const bool, + struct atf_fs_path *); +bool read_line(int, struct atf_dynstr *); +void run_h_tc(atf_tc_t *, const char *, const char *, const char *); diff --git a/external/bsd/atf/dist/atf-c/detail/text.c b/external/bsd/atf/dist/atf-c/detail/text.c new file mode 100644 index 000000000..d91e8d1dc --- /dev/null +++ b/external/bsd/atf/dist/atf-c/detail/text.c @@ -0,0 +1,184 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include + +#include "atf-c/error.h" + +#include "dynstr.h" +#include "sanity.h" +#include "text.h" + +atf_error_t +atf_text_for_each_word(const char *instr, const char *sep, + atf_error_t (*func)(const char *, void *), + void *data) +{ + atf_error_t err; + char *str, *str2, *last; + + str = strdup(instr); + if (str == NULL) { + err = atf_no_memory_error(); + goto out; + } + + err = atf_no_error(); + str2 = strtok_r(str, sep, &last); + while (str2 != NULL && !atf_is_error(err)) { + err = func(str2, data); + str2 = strtok_r(NULL, sep, &last); + } + + free(str); +out: + return err; +} + +atf_error_t +atf_text_format(char **dest, const char *fmt, ...) +{ + atf_error_t err; + va_list ap; + + va_start(ap, fmt); + err = atf_text_format_ap(dest, fmt, ap); + va_end(ap); + + return err; +} + +atf_error_t +atf_text_format_ap(char **dest, const char *fmt, va_list ap) +{ + atf_error_t err; + atf_dynstr_t tmp; + va_list ap2; + + va_copy(ap2, ap); + err = atf_dynstr_init_ap(&tmp, fmt, ap2); + va_end(ap2); + if (!atf_is_error(err)) + *dest = atf_dynstr_fini_disown(&tmp); + + return err; +} + +atf_error_t +atf_text_split(const char *str, const char *delim, atf_list_t *words) +{ + atf_error_t err; + const char *end; + const char *iter; + + err = atf_list_init(words); + if (atf_is_error(err)) + goto err; + + end = str + strlen(str); + INV(*end == '\0'); + iter = str; + while (iter < end) { + const char *ptr; + + INV(iter != NULL); + ptr = strstr(iter, delim); + if (ptr == NULL) + ptr = end; + + INV(ptr >= iter); + if (ptr > iter) { + atf_dynstr_t word; + + err = atf_dynstr_init_raw(&word, iter, ptr - iter); + if (atf_is_error(err)) + goto err_list; + + err = atf_list_append(words, atf_dynstr_fini_disown(&word), true); + if (atf_is_error(err)) + goto err_list; + } + + iter = ptr + strlen(delim); + } + + INV(!atf_is_error(err)); + return err; + +err_list: + atf_list_fini(words); +err: + return err; +} + +atf_error_t +atf_text_to_bool(const char *str, bool *b) +{ + atf_error_t err; + + if (strcasecmp(str, "yes") == 0 || + strcasecmp(str, "true") == 0) { + *b = true; + err = atf_no_error(); + } else if (strcasecmp(str, "no") == 0 || + strcasecmp(str, "false") == 0) { + *b = false; + err = atf_no_error(); + } else { + /* XXX Not really a libc error. */ + err = atf_libc_error(EINVAL, "Cannot convert string '%s' " + "to boolean", str); + } + + return err; +} + +atf_error_t +atf_text_to_long(const char *str, long *l) +{ + atf_error_t err; + char *endptr; + long tmp; + + errno = 0; + tmp = strtol(str, &endptr, 10); + if (str[0] == '\0' || *endptr != '\0') + err = atf_libc_error(EINVAL, "'%s' is not a number", str); + else if (errno == ERANGE || (tmp == LONG_MAX || tmp == LONG_MIN)) + err = atf_libc_error(ERANGE, "'%s' is out of range", str); + else { + *l = tmp; + err = atf_no_error(); + } + + return err; +} diff --git a/external/bsd/atf/dist/atf-c/detail/text.h b/external/bsd/atf/dist/atf-c/detail/text.h new file mode 100644 index 000000000..8f8ddf4cc --- /dev/null +++ b/external/bsd/atf/dist/atf-c/detail/text.h @@ -0,0 +1,49 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if !defined(ATF_C_TEXT_H) +#define ATF_C_TEXT_H + +#include +#include + +#include + +#include "list.h" + +atf_error_t atf_text_for_each_word(const char *, const char *, + atf_error_t (*)(const char *, void *), + void *); +atf_error_t atf_text_format(char **, const char *, ...); +atf_error_t atf_text_format_ap(char **, const char *, va_list); +atf_error_t atf_text_split(const char *, const char *, atf_list_t *); +atf_error_t atf_text_to_bool(const char *, bool *); +atf_error_t atf_text_to_long(const char *, long *); + +#endif /* ATF_C_TEXT_H */ diff --git a/external/bsd/atf/dist/atf-c/detail/text_test.c b/external/bsd/atf/dist/atf-c/detail/text_test.c new file mode 100644 index 000000000..7bdf9c831 --- /dev/null +++ b/external/bsd/atf/dist/atf-c/detail/text_test.c @@ -0,0 +1,424 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +#include + +#include "sanity.h" +#include "test_helpers.h" +#include "text.h" + +/* --------------------------------------------------------------------- + * Auxiliary functions. + * --------------------------------------------------------------------- */ + +#define REQUIRE_ERROR(exp) \ + do { \ + atf_error_t err = exp; \ + ATF_REQUIRE(atf_is_error(err)); \ + atf_error_free(err); \ + } while (0) + +static +size_t +array_size(const char *words[]) +{ + size_t count; + const char **word; + + count = 0; + for (word = words; *word != NULL; word++) + count++; + + return count; +} + +static +void +check_split(const char *str, const char *delim, const char *words[]) +{ + atf_list_t list; + const char **word; + size_t i; + + printf("Splitting '%s' with delimiter '%s'\n", str, delim); + CE(atf_text_split(str, delim, &list)); + + printf("Expecting %zd words\n", array_size(words)); + ATF_CHECK_EQ(atf_list_size(&list), array_size(words)); + + for (word = words, i = 0; *word != NULL; word++, i++) { + printf("Word at position %zd should be '%s'\n", i, words[i]); + ATF_CHECK_STREQ((const char *)atf_list_index_c(&list, i), words[i]); + } + + atf_list_fini(&list); +} + +static +atf_error_t +word_acum(const char *word, void *data) +{ + char *acum = data; + + strcat(acum, word); + + return atf_no_error(); +} + +static +atf_error_t +word_count(const char *word ATF_DEFS_ATTRIBUTE_UNUSED, void *data) +{ + size_t *counter = data; + + (*counter)++; + + return atf_no_error(); +} + +struct fail_at { + int failpos; + int curpos; +}; + +static +atf_error_t +word_fail_at(const char *word ATF_DEFS_ATTRIBUTE_UNUSED, void *data) +{ + struct fail_at *fa = data; + atf_error_t err; + + if (fa->failpos == fa->curpos) + err = atf_no_memory_error(); /* Just a random error. */ + else { + fa->curpos++; + err = atf_no_error(); + } + + return err; +} + +/* --------------------------------------------------------------------- + * Test cases for the free functions. + * --------------------------------------------------------------------- */ + +ATF_TC(for_each_word); +ATF_TC_HEAD(for_each_word, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks the atf_text_for_each_word" + "function"); +} +ATF_TC_BODY(for_each_word, tc) +{ + size_t cnt; + char acum[1024]; + + cnt = 0; + strcpy(acum, ""); + RE(atf_text_for_each_word("1 2 3", " ", word_count, &cnt)); + RE(atf_text_for_each_word("1 2 3", " ", word_acum, acum)); + ATF_REQUIRE(cnt == 3); + ATF_REQUIRE(strcmp(acum, "123") == 0); + + cnt = 0; + strcpy(acum, ""); + RE(atf_text_for_each_word("1 2 3", ".", word_count, &cnt)); + RE(atf_text_for_each_word("1 2 3", ".", word_acum, acum)); + ATF_REQUIRE(cnt == 1); + ATF_REQUIRE(strcmp(acum, "1 2 3") == 0); + + cnt = 0; + strcpy(acum, ""); + RE(atf_text_for_each_word("1 2 3 4 5", " ", word_count, &cnt)); + RE(atf_text_for_each_word("1 2 3 4 5", " ", word_acum, acum)); + ATF_REQUIRE(cnt == 5); + ATF_REQUIRE(strcmp(acum, "12345") == 0); + + cnt = 0; + strcpy(acum, ""); + RE(atf_text_for_each_word("1 2.3.4 5", " .", word_count, &cnt)); + RE(atf_text_for_each_word("1 2.3.4 5", " .", word_acum, acum)); + ATF_REQUIRE(cnt == 5); + ATF_REQUIRE(strcmp(acum, "12345") == 0); + + { + struct fail_at fa; + fa.failpos = 3; + fa.curpos = 0; + atf_error_t err = atf_text_for_each_word("a b c d e", " ", + word_fail_at, &fa); + ATF_REQUIRE(atf_is_error(err)); + ATF_REQUIRE(atf_error_is(err, "no_memory")); + ATF_REQUIRE(fa.curpos == 3); + atf_error_free(err); + } +} + +ATF_TC(format); +ATF_TC_HEAD(format, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks the construction of free-form " + "strings using a variable parameters list"); +} +ATF_TC_BODY(format, tc) +{ + char *str; + atf_error_t err; + + err = atf_text_format(&str, "%s %s %d", "Test", "string", 1); + ATF_REQUIRE(!atf_is_error(err)); + ATF_REQUIRE(strcmp(str, "Test string 1") == 0); + free(str); +} + +static +void +format_ap(char **dest, const char *fmt, ...) +{ + va_list ap; + atf_error_t err; + + va_start(ap, fmt); + err = atf_text_format_ap(dest, fmt, ap); + va_end(ap); + + ATF_REQUIRE(!atf_is_error(err)); +} + +ATF_TC(format_ap); +ATF_TC_HEAD(format_ap, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks the construction of free-form " + "strings using a va_list argument"); +} +ATF_TC_BODY(format_ap, tc) +{ + char *str; + + format_ap(&str, "%s %s %d", "Test", "string", 1); + ATF_REQUIRE(strcmp(str, "Test string 1") == 0); + free(str); +} + +ATF_TC(split); +ATF_TC_HEAD(split, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks the split function"); +} +ATF_TC_BODY(split, tc) +{ + { + const char *words[] = { NULL }; + check_split("", " ", words); + } + + { + const char *words[] = { NULL }; + check_split(" ", " ", words); + } + + { + const char *words[] = { NULL }; + check_split(" ", " ", words); + } + + { + const char *words[] = { "a", "b", NULL }; + check_split("a b", " ", words); + } + + { + const char *words[] = { "a", "b", "c", "d", NULL }; + check_split("a b c d", " ", words); + } + + { + const char *words[] = { "foo", "bar", NULL }; + check_split("foo bar", " ", words); + } + + { + const char *words[] = { "foo", "bar", "baz", "foobar", NULL }; + check_split("foo bar baz foobar", " ", words); + } + + { + const char *words[] = { "foo", "bar", NULL }; + check_split(" foo bar", " ", words); + } + + { + const char *words[] = { "foo", "bar", NULL }; + check_split("foo bar", " ", words); + } + + { + const char *words[] = { "foo", "bar", NULL }; + check_split("foo bar ", " ", words); + } + + { + const char *words[] = { "foo", "bar", NULL }; + check_split(" foo bar ", " ", words); + } +} + +ATF_TC(split_delims); +ATF_TC_HEAD(split_delims, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks the split function using " + "different delimiters"); +} +ATF_TC_BODY(split_delims, tc) +{ + + { + const char *words[] = { NULL }; + check_split("", "/", words); + } + + { + const char *words[] = { " ", NULL }; + check_split(" ", "/", words); + } + + { + const char *words[] = { " ", NULL }; + check_split(" ", "/", words); + } + + { + const char *words[] = { "a", "b", NULL }; + check_split("a/b", "/", words); + } + + { + const char *words[] = { "a", "bcd", "ef", NULL }; + check_split("aLONGDELIMbcdLONGDELIMef", "LONGDELIM", words); + } +} + +ATF_TC(to_bool); +ATF_TC_HEAD(to_bool, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks the atf_text_to_bool function"); +} +ATF_TC_BODY(to_bool, tc) +{ + bool b; + + RE(atf_text_to_bool("true", &b)); ATF_REQUIRE(b); + RE(atf_text_to_bool("TRUE", &b)); ATF_REQUIRE(b); + RE(atf_text_to_bool("yes", &b)); ATF_REQUIRE(b); + RE(atf_text_to_bool("YES", &b)); ATF_REQUIRE(b); + + RE(atf_text_to_bool("false", &b)); ATF_REQUIRE(!b); + RE(atf_text_to_bool("FALSE", &b)); ATF_REQUIRE(!b); + RE(atf_text_to_bool("no", &b)); ATF_REQUIRE(!b); + RE(atf_text_to_bool("NO", &b)); ATF_REQUIRE(!b); + + b = false; + REQUIRE_ERROR(atf_text_to_bool("", &b)); + ATF_REQUIRE(!b); + b = true; + REQUIRE_ERROR(atf_text_to_bool("", &b)); + ATF_REQUIRE(b); + + b = false; + REQUIRE_ERROR(atf_text_to_bool("tru", &b)); + ATF_REQUIRE(!b); + b = true; + REQUIRE_ERROR(atf_text_to_bool("tru", &b)); + ATF_REQUIRE(b); + + b = false; + REQUIRE_ERROR(atf_text_to_bool("true2", &b)); + ATF_REQUIRE(!b); + b = true; + REQUIRE_ERROR(atf_text_to_bool("true2", &b)); + ATF_REQUIRE(b); + + b = false; + REQUIRE_ERROR(atf_text_to_bool("fals", &b)); + ATF_REQUIRE(!b); + b = true; + REQUIRE_ERROR(atf_text_to_bool("fals", &b)); + ATF_REQUIRE(b); + + b = false; + REQUIRE_ERROR(atf_text_to_bool("false2", &b)); + ATF_REQUIRE(!b); + b = true; + REQUIRE_ERROR(atf_text_to_bool("false2", &b)); + ATF_REQUIRE(b); +} + +ATF_TC(to_long); +ATF_TC_HEAD(to_long, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks the atf_text_to_long function"); +} +ATF_TC_BODY(to_long, tc) +{ + long l; + + RE(atf_text_to_long("0", &l)); ATF_REQUIRE_EQ(l, 0); + RE(atf_text_to_long("-5", &l)); ATF_REQUIRE_EQ(l, -5); + RE(atf_text_to_long("5", &l)); ATF_REQUIRE_EQ(l, 5); + RE(atf_text_to_long("123456789", &l)); ATF_REQUIRE_EQ(l, 123456789); + + l = 1212; + REQUIRE_ERROR(atf_text_to_long("", &l)); + ATF_REQUIRE_EQ(l, 1212); + REQUIRE_ERROR(atf_text_to_long("foo", &l)); + ATF_REQUIRE_EQ(l, 1212); + REQUIRE_ERROR(atf_text_to_long("1234x", &l)); + ATF_REQUIRE_EQ(l, 1212); +} + +/* --------------------------------------------------------------------- + * Main. + * --------------------------------------------------------------------- */ + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, for_each_word); + ATF_TP_ADD_TC(tp, format); + ATF_TP_ADD_TC(tp, format_ap); + ATF_TP_ADD_TC(tp, split); + ATF_TP_ADD_TC(tp, split_delims); + ATF_TP_ADD_TC(tp, to_bool); + ATF_TP_ADD_TC(tp, to_long); + + return atf_no_error(); +} diff --git a/external/bsd/atf/dist/atf-c/detail/tp_main.c b/external/bsd/atf/dist/atf-c/detail/tp_main.c new file mode 100644 index 000000000..a62ae0ad6 --- /dev/null +++ b/external/bsd/atf/dist/atf-c/detail/tp_main.c @@ -0,0 +1,617 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if defined(HAVE_CONFIG_H) +#include "bconfig.h" +#endif + +#include +#include +#include +#include +#include +#include + +#include "atf-c/error.h" +#include "atf-c/tc.h" +#include "atf-c/tp.h" +#include "atf-c/utils.h" + +#include "dynstr.h" +#include "env.h" +#include "fs.h" +#include "map.h" +#include "sanity.h" + +#if defined(HAVE_GNU_GETOPT) +# define GETOPT_POSIX "+" +#else +# define GETOPT_POSIX "" +#endif + +static const char *progname = NULL; + +/* This prototype is provided by macros.h during instantiation of the test + * program, so it can be kept private. Don't know if that's the best idea + * though. */ +int atf_tp_main(int, char **, atf_error_t (*)(atf_tp_t *)); + +enum tc_part { + BODY, + CLEANUP, +}; + +/* --------------------------------------------------------------------- + * The "usage" and "user" error types. + * --------------------------------------------------------------------- */ + +#define FREE_FORM_ERROR(name) \ + struct name ## _error_data { \ + char m_what[2048]; \ + }; \ + \ + static \ + void \ + name ## _format(const atf_error_t err, char *buf, size_t buflen) \ + { \ + const struct name ## _error_data *data; \ + \ + PRE(atf_error_is(err, #name)); \ + \ + data = atf_error_data(err); \ + snprintf(buf, buflen, "%s", data->m_what); \ + } \ + \ + static \ + atf_error_t \ + name ## _error(const char *fmt, ...) \ + { \ + atf_error_t err; \ + struct name ## _error_data data; \ + va_list ap; \ + \ + va_start(ap, fmt); \ + vsnprintf(data.m_what, sizeof(data.m_what), fmt, ap); \ + va_end(ap); \ + \ + err = atf_error_new(#name, &data, sizeof(data), name ## _format); \ + \ + return err; \ + } + +FREE_FORM_ERROR(usage); +FREE_FORM_ERROR(user); + +/* --------------------------------------------------------------------- + * Printing functions. + * --------------------------------------------------------------------- */ + +static +void +print_error(const atf_error_t err) +{ + char buf[4096]; + + PRE(atf_is_error(err)); + + atf_error_format(err, buf, sizeof(buf)); + fprintf(stderr, "%s: ERROR: %s\n", progname, buf); + + if (atf_error_is(err, "usage")) + fprintf(stderr, "%s: See atf-test-program(1) for usage details.\n", + progname); +} + +static +void +print_warning(const char *message) +{ + fprintf(stderr, "%s: WARNING: %s\n", progname, message); +} + +/* --------------------------------------------------------------------- + * Options handling. + * --------------------------------------------------------------------- */ + +struct params { + bool m_do_list; + atf_fs_path_t m_srcdir; + char *m_tcname; + enum tc_part m_tcpart; + atf_fs_path_t m_resfile; + atf_map_t m_config; +}; + +static +atf_error_t +argv0_to_dir(const char *argv0, atf_fs_path_t *dir) +{ + atf_error_t err; + atf_fs_path_t temp; + + err = atf_fs_path_init_fmt(&temp, "%s", argv0); + if (atf_is_error(err)) + goto out; + + err = atf_fs_path_branch_path(&temp, dir); + + atf_fs_path_fini(&temp); +out: + return err; +} + +static +atf_error_t +params_init(struct params *p, const char *argv0) +{ + atf_error_t err; + + p->m_do_list = false; + p->m_tcname = NULL; + p->m_tcpart = BODY; + + err = argv0_to_dir(argv0, &p->m_srcdir); + if (atf_is_error(err)) + return err; + + err = atf_fs_path_init_fmt(&p->m_resfile, "/dev/stdout"); + if (atf_is_error(err)) { + atf_fs_path_fini(&p->m_srcdir); + return err; + } + + err = atf_map_init(&p->m_config); + if (atf_is_error(err)) { + atf_fs_path_fini(&p->m_resfile); + atf_fs_path_fini(&p->m_srcdir); + return err; + } + + return err; +} + +static +void +params_fini(struct params *p) +{ + atf_map_fini(&p->m_config); + atf_fs_path_fini(&p->m_resfile); + atf_fs_path_fini(&p->m_srcdir); + if (p->m_tcname != NULL) + free(p->m_tcname); +} + +static +atf_error_t +parse_vflag(char *arg, atf_map_t *config) +{ + atf_error_t err; + char *split; + + split = strchr(arg, '='); + if (split == NULL) { + err = usage_error("-v requires an argument of the form var=value"); + goto out; + } + + *split = '\0'; + split++; + + err = atf_map_insert(config, arg, split, false); + +out: + return err; +} + +static +atf_error_t +replace_path_param(atf_fs_path_t *param, const char *value) +{ + atf_error_t err; + atf_fs_path_t temp; + + err = atf_fs_path_init_fmt(&temp, "%s", value); + if (!atf_is_error(err)) { + atf_fs_path_fini(param); + *param = temp; + } + + return err; +} + +/* --------------------------------------------------------------------- + * Test case listing. + * --------------------------------------------------------------------- */ + +static +void +list_tcs(const atf_tp_t *tp) +{ + const atf_tc_t *const *tcs; + const atf_tc_t *const *tcsptr; + + printf("Content-Type: application/X-atf-tp; version=\"1\"\n\n"); + + tcs = atf_tp_get_tcs(tp); + INV(tcs != NULL); /* Should be checked. */ + for (tcsptr = tcs; *tcsptr != NULL; tcsptr++) { + const atf_tc_t *tc = *tcsptr; + char **vars = atf_tc_get_md_vars(tc); + char **ptr; + + INV(vars != NULL); /* Should be checked. */ + + if (tcsptr != tcs) /* Not first. */ + printf("\n"); + + for (ptr = vars; *ptr != NULL; ptr += 2) { + if (strcmp(*ptr, "ident") == 0) { + printf("ident: %s\n", *(ptr + 1)); + break; + } + } + + for (ptr = vars; *ptr != NULL; ptr += 2) { + if (strcmp(*ptr, "ident") != 0) { + printf("%s: %s\n", *ptr, *(ptr + 1)); + } + } + + atf_utils_free_charpp(vars); + } +} + +/* --------------------------------------------------------------------- + * Main. + * --------------------------------------------------------------------- */ + +static +atf_error_t +handle_tcarg(const char *tcarg, char **tcname, enum tc_part *tcpart) +{ + atf_error_t err; + + err = atf_no_error(); + + *tcname = strdup(tcarg); + if (*tcname == NULL) { + err = atf_no_memory_error(); + goto out; + } + + char *delim = strchr(*tcname, ':'); + if (delim != NULL) { + *delim = '\0'; + + delim++; + if (strcmp(delim, "body") == 0) { + *tcpart = BODY; + } else if (strcmp(delim, "cleanup") == 0) { + *tcpart = CLEANUP; + } else { + err = usage_error("Invalid test case part `%s'", delim); + goto out; + } + } + +out: + return err; +} + +static +atf_error_t +process_params(int argc, char **argv, struct params *p) +{ + atf_error_t err; + int ch; + int old_opterr; + + err = params_init(p, argv[0]); + if (atf_is_error(err)) + goto out; + + old_opterr = opterr; + opterr = 0; + while (!atf_is_error(err) && + (ch = getopt(argc, argv, GETOPT_POSIX ":lr:s:v:")) != -1) { + switch (ch) { + case 'l': + p->m_do_list = true; + break; + + case 'r': + err = replace_path_param(&p->m_resfile, optarg); + break; + + case 's': + err = replace_path_param(&p->m_srcdir, optarg); + break; + + case 'v': + err = parse_vflag(optarg, &p->m_config); + break; + + case ':': + err = usage_error("Option -%c requires an argument.", optopt); + break; + + case '?': + default: + err = usage_error("Unknown option -%c.", optopt); + } + } + argc -= optind; + argv += optind; + + /* Clear getopt state just in case the test wants to use it. */ + opterr = old_opterr; + optind = 1; +#if defined(HAVE_OPTRESET) + optreset = 1; +#endif + + if (!atf_is_error(err)) { + if (p->m_do_list) { + if (argc > 0) + err = usage_error("Cannot provide test case names with -l"); + } else { + if (argc == 0) + err = usage_error("Must provide a test case name"); + else if (argc == 1) + err = handle_tcarg(argv[0], &p->m_tcname, &p->m_tcpart); + else if (argc > 1) { + err = usage_error("Cannot provide more than one test case " + "name"); + } + } + } + + if (atf_is_error(err)) + params_fini(p); + +out: + return err; +} + +static +atf_error_t +srcdir_strip_libtool(atf_fs_path_t *srcdir) +{ + atf_error_t err; + atf_fs_path_t parent; + + err = atf_fs_path_branch_path(srcdir, &parent); + if (atf_is_error(err)) + goto out; + + atf_fs_path_fini(srcdir); + *srcdir = parent; + + INV(!atf_is_error(err)); +out: + return err; +} + +static +atf_error_t +handle_srcdir(struct params *p) +{ + atf_error_t err; + atf_dynstr_t leafname; + atf_fs_path_t exe, srcdir; + bool b; + + err = atf_fs_path_copy(&srcdir, &p->m_srcdir); + if (atf_is_error(err)) + goto out; + + if (!atf_fs_path_is_absolute(&srcdir)) { + atf_fs_path_t srcdirabs; + + err = atf_fs_path_to_absolute(&srcdir, &srcdirabs); + if (atf_is_error(err)) + goto out_srcdir; + + atf_fs_path_fini(&srcdir); + srcdir = srcdirabs; + } + + err = atf_fs_path_leaf_name(&srcdir, &leafname); + if (atf_is_error(err)) + goto out_srcdir; + else { + const bool libs = atf_equal_dynstr_cstring(&leafname, ".libs"); + atf_dynstr_fini(&leafname); + + if (libs) { + err = srcdir_strip_libtool(&srcdir); + if (atf_is_error(err)) + goto out; + } + } + + err = atf_fs_path_copy(&exe, &srcdir); + if (atf_is_error(err)) + goto out_srcdir; + + err = atf_fs_path_append_fmt(&exe, "%s", progname); + if (atf_is_error(err)) + goto out_exe; + + err = atf_fs_exists(&exe, &b); + if (!atf_is_error(err)) { + if (b) { + err = atf_map_insert(&p->m_config, "srcdir", + strdup(atf_fs_path_cstring(&srcdir)), true); + } else { + err = user_error("Cannot find the test program in the source " + "directory `%s'", atf_fs_path_cstring(&srcdir)); + } + } + +out_exe: + atf_fs_path_fini(&exe); +out_srcdir: + atf_fs_path_fini(&srcdir); +out: + return err; +} + +static +atf_error_t +run_tc(const atf_tp_t *tp, struct params *p, int *exitcode) +{ + atf_error_t err; + + err = atf_no_error(); + + if (!atf_tp_has_tc(tp, p->m_tcname)) { + err = usage_error("Unknown test case `%s'", p->m_tcname); + goto out; + } + + if (!atf_env_has("__RUNNING_INSIDE_ATF_RUN") || strcmp(atf_env_get( + "__RUNNING_INSIDE_ATF_RUN"), "internal-yes-value") != 0) + { + print_warning("Running test cases without atf-run(1) is unsupported"); + print_warning("No isolation nor timeout control is being applied; you " + "may get unexpected failures; see atf-test-case(4)"); + } + + switch (p->m_tcpart) { + case BODY: + err = atf_tp_run(tp, p->m_tcname, atf_fs_path_cstring(&p->m_resfile)); + if (atf_is_error(err)) { + /* TODO: Handle error */ + *exitcode = EXIT_FAILURE; + atf_error_free(err); + } else { + *exitcode = EXIT_SUCCESS; + } + + break; + + case CLEANUP: + err = atf_tp_cleanup(tp, p->m_tcname); + if (atf_is_error(err)) { + /* TODO: Handle error */ + *exitcode = EXIT_FAILURE; + atf_error_free(err); + } else { + *exitcode = EXIT_SUCCESS; + } + + break; + + default: + UNREACHABLE; + } + + INV(!atf_is_error(err)); +out: + return err; +} + +static +atf_error_t +controlled_main(int argc, char **argv, + atf_error_t (*add_tcs_hook)(atf_tp_t *), + int *exitcode) +{ + atf_error_t err; + struct params p; + atf_tp_t tp; + char **raw_config; + + err = process_params(argc, argv, &p); + if (atf_is_error(err)) + goto out; + + err = handle_srcdir(&p); + if (atf_is_error(err)) + goto out_p; + + raw_config = atf_map_to_charpp(&p.m_config); + if (raw_config == NULL) { + err = atf_no_memory_error(); + goto out_p; + } + err = atf_tp_init(&tp, (const char* const*)raw_config); + atf_utils_free_charpp(raw_config); + if (atf_is_error(err)) + goto out_p; + + err = add_tcs_hook(&tp); + if (atf_is_error(err)) + goto out_tp; + + if (p.m_do_list) { + list_tcs(&tp); + INV(!atf_is_error(err)); + *exitcode = EXIT_SUCCESS; + } else { + err = run_tc(&tp, &p, exitcode); + } + +out_tp: + atf_tp_fini(&tp); +out_p: + params_fini(&p); +out: + return err; +} + +int +atf_tp_main(int argc, char **argv, atf_error_t (*add_tcs_hook)(atf_tp_t *)) +{ + atf_error_t err; + int exitcode; + + progname = strrchr(argv[0], '/'); + if (progname == NULL) + progname = argv[0]; + else + progname++; + + /* Libtool workaround: if running from within the source tree (binaries + * that are not installed yet), skip the "lt-" prefix added to files in + * the ".libs" directory to show the real (not temporary) name. */ + if (strncmp(progname, "lt-", 3) == 0) + progname += 3; + + exitcode = EXIT_FAILURE; /* Silence GCC warning. */ + err = controlled_main(argc, argv, add_tcs_hook, &exitcode); + if (atf_is_error(err)) { + print_error(err); + atf_error_free(err); + exitcode = EXIT_FAILURE; + } + + return exitcode; +} diff --git a/external/bsd/atf/dist/atf-c/detail/user.c b/external/bsd/atf/dist/atf-c/detail/user.c new file mode 100644 index 000000000..5a89bf42b --- /dev/null +++ b/external/bsd/atf/dist/atf-c/detail/user.c @@ -0,0 +1,78 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2007 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include + +#include "sanity.h" +#include "user.h" + +/* --------------------------------------------------------------------- + * Free functions. + * --------------------------------------------------------------------- */ + +uid_t +atf_user_euid(void) +{ + return geteuid(); +} + +bool +atf_user_is_member_of_group(gid_t gid) +{ + static gid_t groups[NGROUPS_MAX]; + static int ngroups = -1; + bool found; + int i; + + if (ngroups == -1) { + ngroups = getgroups(NGROUPS_MAX, groups); + INV(ngroups >= 0); + } + + found = false; + for (i = 0; !found && i < ngroups; i++) + if (groups[i] == gid) + found = true; + return found; +} + +bool +atf_user_is_root(void) +{ + return geteuid() == 0; +} + +bool +atf_user_is_unprivileged(void) +{ + return geteuid() != 0; +} diff --git a/external/bsd/atf/dist/atf-c/detail/user.h b/external/bsd/atf/dist/atf-c/detail/user.h new file mode 100644 index 000000000..d682bcfb4 --- /dev/null +++ b/external/bsd/atf/dist/atf-c/detail/user.h @@ -0,0 +1,49 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2007 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if !defined(ATF_C_USER_H) +#define ATF_C_USER_H + +#include + +#include + +/* TODO: Would be nice to have an atf_user_t type and transform all of + * the functions below to methods. */ + +/* --------------------------------------------------------------------- + * Free functions. + * --------------------------------------------------------------------- */ + +uid_t atf_user_euid(void); +bool atf_user_is_member_of_group(gid_t); +bool atf_user_is_root(void); +bool atf_user_is_unprivileged(void); + +#endif /* !defined(ATF_C_USER_H) */ diff --git a/external/bsd/atf/dist/atf-c/detail/user_test.c b/external/bsd/atf/dist/atf-c/detail/user_test.c new file mode 100644 index 000000000..0bf37e7e3 --- /dev/null +++ b/external/bsd/atf/dist/atf-c/detail/user_test.c @@ -0,0 +1,149 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2007 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include +#include +#include + +#include + +#include "test_helpers.h" +#include "user.h" + +/* --------------------------------------------------------------------- + * Test cases for the free functions. + * --------------------------------------------------------------------- */ + +ATF_TC(euid); +ATF_TC_HEAD(euid, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the atf_user_euid function"); +} +ATF_TC_BODY(euid, tc) +{ + ATF_REQUIRE_EQ(atf_user_euid(), geteuid()); +} + +ATF_TC(is_member_of_group); +ATF_TC_HEAD(is_member_of_group, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the atf_user_is_member_of_group " + "function"); +} +ATF_TC_BODY(is_member_of_group, tc) +{ + gid_t gids[NGROUPS_MAX]; + gid_t g, maxgid; + int ngids; + const gid_t maxgid_limit = 1 << 16; + + { + int i; + + ngids = getgroups(NGROUPS_MAX, gids); + if (ngids == -1) + atf_tc_fail("Call to getgroups failed"); + maxgid = 0; + for (i = 0; i < ngids; i++) { + printf("User group %d is %u\n", i, gids[i]); + if (maxgid < gids[i]) + maxgid = gids[i]; + } + printf("User belongs to %d groups\n", ngids); + printf("Last GID is %u\n", maxgid); + } + + if (maxgid > maxgid_limit) { + printf("Test truncated from %u groups to %u to keep the run time " + "reasonable enough\n", maxgid, maxgid_limit); + maxgid = maxgid_limit; + } + + for (g = 0; g < maxgid; g++) { + bool found = false; + int i; + + for (i = 0; !found && i < ngids; i++) { + if (gids[i] == g) + found = true; + } + + if (found) { + printf("Checking if user belongs to group %d\n", g); + ATF_REQUIRE(atf_user_is_member_of_group(g)); + } else { + printf("Checking if user does not belong to group %d\n", g); + ATF_REQUIRE(!atf_user_is_member_of_group(g)); + } + } +} + +ATF_TC(is_root); +ATF_TC_HEAD(is_root, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the atf_user_is_root function"); +} +ATF_TC_BODY(is_root, tc) +{ + if (geteuid() == 0) + ATF_REQUIRE(atf_user_is_root()); + else + ATF_REQUIRE(!atf_user_is_root()); +} + +ATF_TC(is_unprivileged); +ATF_TC_HEAD(is_unprivileged, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the atf_user_is_unprivileged " + "function"); +} +ATF_TC_BODY(is_unprivileged, tc) +{ + if (geteuid() != 0) + ATF_REQUIRE(atf_user_is_unprivileged()); + else + ATF_REQUIRE(!atf_user_is_unprivileged()); +} + +/* --------------------------------------------------------------------- + * Main. + * --------------------------------------------------------------------- */ + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, euid); + ATF_TP_ADD_TC(tp, is_member_of_group); + ATF_TP_ADD_TC(tp, is_root); + ATF_TP_ADD_TC(tp, is_unprivileged); + + return atf_no_error(); +} diff --git a/external/bsd/atf/dist/atf-c/error.c b/external/bsd/atf/dist/atf-c/error.c new file mode 100644 index 000000000..aeb55a8ba --- /dev/null +++ b/external/bsd/atf/dist/atf-c/error.c @@ -0,0 +1,267 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include + +#include "atf-c/error.h" + +#include "detail/sanity.h" + +/* Theoretically, there can only be a single error intance at any given + * point in time, because errors are raised at one point and must be + * handled immediately. If another error has to be raised during the + * handling process, something else has to be done with the previous + * error. + * + * This is per-thread information and will break threaded tests, but we + * currently do not have any threading support; therefore, this is fine. */ +static bool error_on_flight = false; + +/* --------------------------------------------------------------------- + * Auxiliary functions. + * --------------------------------------------------------------------- */ + +static +void +error_format(const atf_error_t err, char *buf, size_t buflen) +{ + PRE(err != NULL); + snprintf(buf, buflen, "Error '%s'", err->m_type); +} + +static +bool +error_init(atf_error_t err, const char *type, void *data, size_t datalen, + void (*format)(const atf_error_t, char *, size_t)) +{ + bool ok; + + PRE(data != NULL || datalen == 0); + PRE(datalen != 0 || data == NULL); + + err->m_free = false; + err->m_type = type; + err->m_format = (format == NULL) ? error_format : format; + + ok = true; + if (data == NULL) { + err->m_data = NULL; + } else { + err->m_data = malloc(datalen); + if (err->m_data == NULL) { + ok = false; + } else + memcpy(err->m_data, data, datalen); + } + + return ok; +} + +/* --------------------------------------------------------------------- + * The "atf_error" type. + * --------------------------------------------------------------------- */ + +atf_error_t +atf_error_new(const char *type, void *data, size_t datalen, + void (*format)(const atf_error_t, char *, size_t)) +{ + atf_error_t err; + + PRE(!error_on_flight); + PRE(data != NULL || datalen == 0); + PRE(datalen != 0 || data == NULL); + + err = malloc(sizeof(*err)); + if (err == NULL) + err = atf_no_memory_error(); + else { + if (!error_init(err, type, data, datalen, format)) { + free(err); + err = atf_no_memory_error(); + } else { + err->m_free = true; + error_on_flight = true; + } + } + + INV(err != NULL); + POST(error_on_flight); + return err; +} + +void +atf_error_free(atf_error_t err) +{ + bool freeit; + + PRE(error_on_flight); + PRE(err != NULL); + + freeit = err->m_free; + + if (err->m_data != NULL) + free(err->m_data); + + if (freeit) + free(err); + + error_on_flight = false; +} + +atf_error_t +atf_no_error(void) +{ + return NULL; +} + +bool +atf_is_error(const atf_error_t err) +{ + return err != NULL; +} + +bool +atf_error_is(const atf_error_t err, const char *type) +{ + PRE(err != NULL); + + return strcmp(err->m_type, type) == 0; +} + +const void * +atf_error_data(const atf_error_t err) +{ + PRE(err != NULL); + + return err->m_data; +} + +void +atf_error_format(const atf_error_t err, char *buf, size_t buflen) +{ + PRE(err != NULL); + err->m_format(err, buf, buflen); +} + +/* --------------------------------------------------------------------- + * Common error types. + * --------------------------------------------------------------------- */ + +/* + * The "libc" error. + */ + +struct atf_libc_error_data { + int m_errno; + char m_what[4096]; +}; +typedef struct atf_libc_error_data atf_libc_error_data_t; + +static +void +libc_format(const atf_error_t err, char *buf, size_t buflen) +{ + const atf_libc_error_data_t *data; + + PRE(atf_error_is(err, "libc")); + + data = atf_error_data(err); + snprintf(buf, buflen, "%s: %s", data->m_what, strerror(data->m_errno)); +} + +atf_error_t +atf_libc_error(int syserrno, const char *fmt, ...) +{ + atf_error_t err; + atf_libc_error_data_t data; + va_list ap; + + data.m_errno = syserrno; + va_start(ap, fmt); + vsnprintf(data.m_what, sizeof(data.m_what), fmt, ap); + va_end(ap); + + err = atf_error_new("libc", &data, sizeof(data), libc_format); + + return err; +} + +int +atf_libc_error_code(const atf_error_t err) +{ + const struct atf_libc_error_data *data; + + PRE(atf_error_is(err, "libc")); + + data = atf_error_data(err); + + return data->m_errno; +} + +const char * +atf_libc_error_msg(const atf_error_t err) +{ + const struct atf_libc_error_data *data; + + PRE(atf_error_is(err, "libc")); + + data = atf_error_data(err); + + return data->m_what; +} + +/* + * The "no_memory" error. + */ + +static struct atf_error no_memory_error; + +static +void +no_memory_format(const atf_error_t err, char *buf, size_t buflen) +{ + PRE(atf_error_is(err, "no_memory")); + + snprintf(buf, buflen, "Not enough memory"); +} + +atf_error_t +atf_no_memory_error(void) +{ + PRE(!error_on_flight); + + error_init(&no_memory_error, "no_memory", NULL, 0, + no_memory_format); + + error_on_flight = true; + return &no_memory_error; +} diff --git a/external/bsd/atf/dist/atf-c/error.h b/external/bsd/atf/dist/atf-c/error.h new file mode 100644 index 000000000..a8502801b --- /dev/null +++ b/external/bsd/atf/dist/atf-c/error.h @@ -0,0 +1,71 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if !defined(ATF_C_ERROR_H) +#define ATF_C_ERROR_H + +#include +#include + +#include + +/* --------------------------------------------------------------------- + * The "atf_error" type. + * --------------------------------------------------------------------- */ + +struct atf_error { + bool m_free; + const char *m_type; + void *m_data; + + void (*m_format)(struct atf_error *, char *, size_t); +}; + +atf_error_t atf_error_new(const char *, void *, size_t, + void (*)(const atf_error_t, char *, size_t)); +void atf_error_free(atf_error_t); + +atf_error_t atf_no_error(void); +bool atf_is_error(const atf_error_t); + +bool atf_error_is(const atf_error_t, const char *); +const void *atf_error_data(const atf_error_t); +void atf_error_format(const atf_error_t, char *, size_t); + +/* --------------------------------------------------------------------- + * Common error types. + * --------------------------------------------------------------------- */ + +atf_error_t atf_libc_error(int, const char *, ...); +int atf_libc_error_code(const atf_error_t); +const char *atf_libc_error_msg(const atf_error_t); + +atf_error_t atf_no_memory_error(void); + +#endif /* ATF_C_ERROR_H */ diff --git a/external/bsd/atf/dist/atf-c/error_fwd.h b/external/bsd/atf/dist/atf-c/error_fwd.h new file mode 100644 index 000000000..69d7e7dad --- /dev/null +++ b/external/bsd/atf/dist/atf-c/error_fwd.h @@ -0,0 +1,40 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if !defined(ATF_C_ERROR_FWD_H) +#define ATF_C_ERROR_FWD_H + +/* --------------------------------------------------------------------- + * The "atf_error" type. + * --------------------------------------------------------------------- */ + +struct atf_error; +typedef struct atf_error *atf_error_t; + +#endif /* ATF_C_ERROR_FWD_H */ diff --git a/external/bsd/atf/dist/atf-c/error_test.c b/external/bsd/atf/dist/atf-c/error_test.c new file mode 100644 index 000000000..2c2a30789 --- /dev/null +++ b/external/bsd/atf/dist/atf-c/error_test.c @@ -0,0 +1,313 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include + +#include + +#include "atf-c/defs.h" +#include "atf-c/error.h" + +#include "detail/test_helpers.h" + +/* --------------------------------------------------------------------- + * Auxiliary functions. + * --------------------------------------------------------------------- */ + +static +void +test_format(const atf_error_t err ATF_DEFS_ATTRIBUTE_UNUSED, + char *buf, size_t buflen) +{ + snprintf(buf, buflen, "Test formatting function"); +} + +/* --------------------------------------------------------------------- + * Tests for the "atf_error" type. + * --------------------------------------------------------------------- */ + +ATF_TC(error_new); +ATF_TC_HEAD(error_new, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks the construction of an error " + "object"); +} +ATF_TC_BODY(error_new, tc) +{ + atf_error_t err; + int data; + + err = atf_error_new("test_error", NULL, 0, NULL); + ATF_REQUIRE(atf_error_is(err, "test_error")); + ATF_REQUIRE(!atf_error_is(err, "unknown_error")); + ATF_REQUIRE(atf_error_data(err) == NULL); + atf_error_free(err); + + data = 5; + err = atf_error_new("test_data_error", &data, sizeof(data), NULL); + ATF_REQUIRE(atf_error_is(err, "test_data_error")); + ATF_REQUIRE(!atf_error_is(err, "unknown_error")); + ATF_REQUIRE(atf_error_data(err) != NULL); + ATF_REQUIRE_EQ(*((const int *)atf_error_data(err)), 5); + atf_error_free(err); +} + +ATF_TC(error_new_wo_memory); +ATF_TC_HEAD(error_new_wo_memory, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks that an unavailable memory error " + "raised when constructing an error object " + "is properly converted to the no_memory " + "static error type"); +} +ATF_TC_BODY(error_new_wo_memory, tc) +{ + atf_error_t err; + void *invalid; + + invalid = (void *)1; + + err = atf_error_new("test_error", invalid, SIZE_MAX, NULL); + ATF_REQUIRE(atf_error_is(err, "no_memory")); + ATF_REQUIRE(atf_error_data(err) == NULL); + atf_error_free(err); +} + +ATF_TC(no_error); +ATF_TC_HEAD(no_error, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks that constructing a non-error " + "object works"); +} +ATF_TC_BODY(no_error, tc) +{ + atf_error_t err; + + err = atf_no_error(); + ATF_REQUIRE(!atf_is_error(err)); +} + +ATF_TC(is_error); +ATF_TC_HEAD(is_error, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks the is_error method to determine " + "if an error object holds success or an error"); +} +ATF_TC_BODY(is_error, tc) +{ + atf_error_t err; + + err = atf_no_error(); + ATF_REQUIRE(!atf_is_error(err)); + + err = atf_error_new("test_error", NULL, 0, NULL); + ATF_REQUIRE(atf_is_error(err)); + atf_error_free(err); +} + +ATF_TC(format); +ATF_TC_HEAD(format, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks the default formatting function " + "and the ability to change it"); +} +ATF_TC_BODY(format, tc) +{ + atf_error_t err; + char buf[1024]; + + printf("Testing default formatting function\n"); + err = atf_error_new("test_error", NULL, 0, NULL); + atf_error_format(err, buf, sizeof(buf)); + printf("Error string is: %s\n", buf); + ATF_REQUIRE(strcmp(buf, "Error 'test_error'") == 0); + atf_error_free(err); + + printf("Testing custom formatting function\n"); + err = atf_error_new("test_error", NULL, 0, test_format); + atf_error_format(err, buf, sizeof(buf)); + printf("Error string is: %s\n", buf); + ATF_REQUIRE(strcmp(buf, "Test formatting function") == 0); + atf_error_free(err); +} + +/* --------------------------------------------------------------------- + * Tests for the "libc" error. + * --------------------------------------------------------------------- */ + +ATF_TC(libc_new); +ATF_TC_HEAD(libc_new, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks the construction of libc errors"); +} +ATF_TC_BODY(libc_new, tc) +{ + atf_error_t err; + + err = atf_libc_error(ENOMEM, "Test message 1"); + ATF_REQUIRE(atf_error_is(err, "libc")); + ATF_REQUIRE_EQ(atf_libc_error_code(err), ENOMEM); + ATF_REQUIRE(strcmp(atf_libc_error_msg(err), "Test message 1") == 0); + atf_error_free(err); + + err = atf_libc_error(EPERM, "%s message %d", "Test", 2); + ATF_REQUIRE(atf_error_is(err, "libc")); + ATF_REQUIRE_EQ(atf_libc_error_code(err), EPERM); + ATF_REQUIRE(strcmp(atf_libc_error_msg(err), "Test message 2") == 0); + atf_error_free(err); +} + +ATF_TC(libc_format); +ATF_TC_HEAD(libc_format, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks the formatting of libc errors"); +} +ATF_TC_BODY(libc_format, tc) +{ + atf_error_t err; + char buf[1024]; + + err = atf_libc_error(ENOMEM, "Test message 1"); + atf_error_format(err, buf, sizeof(buf)); + ATF_REQUIRE(strstr(buf, strerror(ENOMEM)) != NULL); + ATF_REQUIRE(strstr(buf, "Test message 1") != NULL); + atf_error_free(err); + + err = atf_libc_error(EPERM, "Test message 2"); + atf_error_format(err, buf, sizeof(buf)); + ATF_REQUIRE(strstr(buf, strerror(EPERM)) != NULL); + ATF_REQUIRE(strstr(buf, "Test message 2") != NULL); + atf_error_free(err); + + err = atf_libc_error(EPERM, "%s message %d", "Test", 3); + atf_error_format(err, buf, sizeof(buf)); + ATF_REQUIRE(strstr(buf, strerror(EPERM)) != NULL); + ATF_REQUIRE(strstr(buf, "Test message 3") != NULL); + atf_error_free(err); +} + +/* --------------------------------------------------------------------- + * Tests for the "no_memory" error. + * --------------------------------------------------------------------- */ + +ATF_TC(no_memory_new); +ATF_TC_HEAD(no_memory_new, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks the construction of no_memory " + "errors"); +} +ATF_TC_BODY(no_memory_new, tc) +{ + atf_error_t err; + + err = atf_no_memory_error(); + ATF_REQUIRE(atf_error_is(err, "no_memory")); + ATF_REQUIRE(atf_error_data(err) == NULL); + atf_error_free(err); +} + +ATF_TC(no_memory_format); +ATF_TC_HEAD(no_memory_format, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks the formatting of no_memory " + "errors"); +} +ATF_TC_BODY(no_memory_format, tc) +{ + atf_error_t err; + char buf[1024]; + + err = atf_no_memory_error(); + atf_error_format(err, buf, sizeof(buf)); + ATF_REQUIRE(strcmp(buf, "Not enough memory") == 0); + atf_error_free(err); +} + +ATF_TC(no_memory_twice); +ATF_TC_HEAD(no_memory_twice, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks the construction of no_memory " + "errors multiple times, as this error is initialized " + "statically"); +} +ATF_TC_BODY(no_memory_twice, tc) +{ + { + atf_error_t err = atf_no_memory_error(); + ATF_REQUIRE(atf_error_is(err, "no_memory")); + ATF_REQUIRE(atf_error_data(err) == NULL); + atf_error_free(err); + } + + { + atf_error_t err = atf_no_memory_error(); + ATF_REQUIRE(atf_error_is(err, "no_memory")); + ATF_REQUIRE(atf_error_data(err) == NULL); + atf_error_free(err); + } +} + +/* --------------------------------------------------------------------- + * Tests cases for the header file. + * --------------------------------------------------------------------- */ + +HEADER_TC(include, "atf-c/error.h"); +HEADER_TC(include_fwd, "atf-c/error_fwd.h"); + +/* --------------------------------------------------------------------- + * Main. + * --------------------------------------------------------------------- */ + +ATF_TP_ADD_TCS(tp) +{ + /* Add the tests for the "atf_error" type. */ + ATF_TP_ADD_TC(tp, error_new); + ATF_TP_ADD_TC(tp, error_new_wo_memory); + ATF_TP_ADD_TC(tp, no_error); + ATF_TP_ADD_TC(tp, is_error); + ATF_TP_ADD_TC(tp, format); + + /* Add the tests for the "libc" error. */ + ATF_TP_ADD_TC(tp, libc_new); + ATF_TP_ADD_TC(tp, libc_format); + + /* Add the tests for the "no_memory" error. */ + ATF_TP_ADD_TC(tp, no_memory_new); + ATF_TP_ADD_TC(tp, no_memory_format); + ATF_TP_ADD_TC(tp, no_memory_twice); + + /* Add the test cases for the header file. */ + ATF_TP_ADD_TC(tp, include); + ATF_TP_ADD_TC(tp, include_fwd); + + return atf_no_error(); +} diff --git a/external/bsd/atf/dist/atf-c/h_build.h b/external/bsd/atf/dist/atf-c/h_build.h new file mode 100644 index 000000000..9454fdfde --- /dev/null +++ b/external/bsd/atf/dist/atf-c/h_build.h @@ -0,0 +1,414 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2009 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if defined(TESTS_ATF_ATF_C_H_BUILD_H) +# error "Cannot include h_build.h more than once." +#else +# define TESTS_ATF_ATF_C_H_BUILD_H +#endif + +/* --------------------------------------------------------------------- + * Test case data. + * --------------------------------------------------------------------- */ + +static struct c_o_test { + const char *msg; + const char *cc; + const char *cflags; + const char *cppflags; + const char *sfile; + const char *ofile; + bool hasoptargs; + const char *const optargs[16]; + const char *const expargv[16]; +} c_o_tests[] = { + { + "No flags", + "cc", + "", + "", + "test.c", + "test.o", + false, + { + NULL + }, + { + "cc", "-o", "test.o", "-c", "test.c", NULL + }, + }, + + { + "Multi-word program name", + "cc -foo", + "", + "", + "test.c", + "test.o", + false, + { + NULL + }, + { + "cc", "-foo", "-o", "test.o", "-c", "test.c", NULL + }, + }, + + { + "Some cflags", + "cc", + "-f1 -f2 -f3 -f4-f5", + "", + "test.c", + "test.o", + false, + { + NULL + }, + { + "cc", "-f1", "-f2", "-f3", "-f4-f5", "-o", "test.o", + "-c", "test.c", NULL + }, + }, + + { + "Some cppflags", + "cc", + "", + "-f1 -f2 -f3 -f4-f5", + "test.c", + "test.o", + false, + { + NULL + }, + { + "cc", "-f1", "-f2", "-f3", "-f4-f5", "-o", "test.o", + "-c", "test.c", NULL + }, + }, + + { + "Some cflags and cppflags", + "cc", + "-f2", + "-f1", + "test.c", + "test.o", + false, + { + NULL + }, + { + "cc", "-f1", "-f2", "-o", "test.o", "-c", "test.c", NULL + }, + }, + + { + "Some optional arguments", + "cc", + "", + "", + "test.c", + "test.o", + true, + { + "-o1", "-o2", NULL + }, + { + "cc", "-o1", "-o2", "-o", "test.o", "-c", "test.c", NULL + }, + }, + + { + "Some cflags, cppflags and optional arguments", + "cc", + "-f2", + "-f1", + "test.c", + "test.o", + true, + { + "-o1", "-o2", NULL + }, + { + "cc", "-f1", "-f2", "-o1", "-o2", "-o", "test.o", + "-c", "test.c", NULL + }, + }, + + { + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + false, + { NULL }, + { NULL }, + }, +}; + +static struct cpp_test { + const char *msg; + const char *cpp; + const char *cppflags; + const char *sfile; + const char *ofile; + bool hasoptargs; + const char *const optargs[16]; + const char *const expargv[16]; +} cpp_tests[] = { + { + "No flags", + "cpp", + "", + "test.c", + "test.out", + false, + { + NULL + }, + { + "cpp", "-o", "test.out", "test.c", NULL + }, + }, + + { + "Multi-word program name", + "cpp -foo", + "", + "test.c", + "test.out", + false, + { + NULL + }, + { + "cpp", "-foo", "-o", "test.out", "test.c", NULL + }, + }, + + { + "Some cppflags", + "cpp", + "-f1 -f2 -f3 -f4-f5", + "test.c", + "test.out", + false, + { + NULL + }, + { + "cpp", "-f1", "-f2", "-f3", "-f4-f5", "-o", "test.out", + "test.c", NULL + }, + }, + + { + "Some optional arguments", + "cpp", + "", + "test.c", + "test.out", + true, + { + "-o1", "-o2", NULL + }, + { + "cpp", "-o1", "-o2", "-o", "test.out", "test.c", NULL + }, + }, + + { + "Some cppflags and optional arguments", + "cpp", + "-f1", + "test.c", + "test.out", + true, + { + "-o1", "-o2", NULL + }, + { + "cpp", "-f1", "-o1", "-o2", "-o", "test.out", "test.c", NULL + }, + }, + + { + NULL, + NULL, + NULL, + NULL, + NULL, + false, + { NULL }, + { NULL }, + }, +}; + +static struct cxx_o_test { + const char *msg; + const char *cxx; + const char *cxxflags; + const char *cppflags; + const char *sfile; + const char *ofile; + bool hasoptargs; + const char *const optargs[16]; + const char *const expargv[16]; +} cxx_o_tests[] = { + { + "No flags", + "c++", + "", + "", + "test.c", + "test.o", + false, + { + NULL + }, + { + "c++", "-o", "test.o", "-c", "test.c", NULL + }, + }, + + { + "Multi-word program name", + "c++ -foo", + "", + "", + "test.c", + "test.o", + false, + { + NULL + }, + { + "c++", "-foo", "-o", "test.o", "-c", "test.c", NULL + }, + }, + + { + "Some cxxflags", + "c++", + "-f1 -f2 -f3 -f4-f5", + "", + "test.c", + "test.o", + false, + { + NULL + }, + { + "c++", "-f1", "-f2", "-f3", "-f4-f5", "-o", "test.o", + "-c", "test.c", NULL + }, + }, + + { + "Some cppflags", + "c++", + "", + "-f1 -f2 -f3 -f4-f5", + "test.c", + "test.o", + false, + { + NULL + }, + { + "c++", "-f1", "-f2", "-f3", "-f4-f5", "-o", "test.o", + "-c", "test.c", NULL + }, + }, + + { + "Some cxxflags and cppflags", + "c++", + "-f2", + "-f1", + "test.c", + "test.o", + false, + { + NULL + }, + { + "c++", "-f1", "-f2", "-o", "test.o", "-c", "test.c", NULL + }, + }, + + { + "Some optional arguments", + "c++", + "", + "", + "test.c", + "test.o", + true, + { + "-o1", "-o2", NULL + }, + { + "c++", "-o1", "-o2", "-o", "test.o", "-c", "test.c", NULL + }, + }, + + { + "Some cxxflags, cppflags and optional arguments", + "c++", + "-f2", + "-f1", + "test.c", + "test.o", + true, + { + "-o1", "-o2", NULL + }, + { + "c++", "-f1", "-f2", "-o1", "-o2", "-o", "test.o", + "-c", "test.c", NULL + }, + }, + + { + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + false, + { NULL }, + { NULL }, + }, +}; diff --git a/external/bsd/atf/dist/atf-c/macros.h b/external/bsd/atf/dist/atf-c/macros.h new file mode 100644 index 000000000..7c33ccbc1 --- /dev/null +++ b/external/bsd/atf/dist/atf-c/macros.h @@ -0,0 +1,208 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if !defined(ATF_C_MACROS_H) +#define ATF_C_MACROS_H + +#include + +#include +#include +#include +#include +#include + +#define ATF_TC_NAME(tc) \ + (atfu_ ## tc ## _tc) + +#define ATF_TC_PACK_NAME(tc) \ + (atfu_ ## tc ## _tc_pack) + +#define ATF_TC_WITHOUT_HEAD(tc) \ + static void atfu_ ## tc ## _body(const atf_tc_t *); \ + static atf_tc_t atfu_ ## tc ## _tc; \ + static atf_tc_pack_t atfu_ ## tc ## _tc_pack = { \ + .m_ident = #tc, \ + .m_head = NULL, \ + .m_body = atfu_ ## tc ## _body, \ + .m_cleanup = NULL, \ + } + +#define ATF_TC(tc) \ + static void atfu_ ## tc ## _head(atf_tc_t *); \ + static void atfu_ ## tc ## _body(const atf_tc_t *); \ + static atf_tc_t atfu_ ## tc ## _tc; \ + static atf_tc_pack_t atfu_ ## tc ## _tc_pack = { \ + .m_ident = #tc, \ + .m_head = atfu_ ## tc ## _head, \ + .m_body = atfu_ ## tc ## _body, \ + .m_cleanup = NULL, \ + } + +#define ATF_TC_WITH_CLEANUP(tc) \ + static void atfu_ ## tc ## _head(atf_tc_t *); \ + static void atfu_ ## tc ## _body(const atf_tc_t *); \ + static void atfu_ ## tc ## _cleanup(const atf_tc_t *); \ + static atf_tc_t atfu_ ## tc ## _tc; \ + static atf_tc_pack_t atfu_ ## tc ## _tc_pack = { \ + .m_ident = #tc, \ + .m_head = atfu_ ## tc ## _head, \ + .m_body = atfu_ ## tc ## _body, \ + .m_cleanup = atfu_ ## tc ## _cleanup, \ + } + +#define ATF_TC_HEAD(tc, tcptr) \ + static \ + void \ + atfu_ ## tc ## _head(atf_tc_t *tcptr ATF_DEFS_ATTRIBUTE_UNUSED) + +#define ATF_TC_HEAD_NAME(tc) \ + (atfu_ ## tc ## _head) + +#define ATF_TC_BODY(tc, tcptr) \ + static \ + void \ + atfu_ ## tc ## _body(const atf_tc_t *tcptr ATF_DEFS_ATTRIBUTE_UNUSED) + +#define ATF_TC_BODY_NAME(tc) \ + (atfu_ ## tc ## _body) + +#define ATF_TC_CLEANUP(tc, tcptr) \ + static \ + void \ + atfu_ ## tc ## _cleanup(const atf_tc_t *tcptr ATF_DEFS_ATTRIBUTE_UNUSED) + +#define ATF_TC_CLEANUP_NAME(tc) \ + (atfu_ ## tc ## _cleanup) + +#define ATF_TP_ADD_TCS(tps) \ + static atf_error_t atfu_tp_add_tcs(atf_tp_t *); \ + int atf_tp_main(int, char **, atf_error_t (*)(atf_tp_t *)); \ + \ + int \ + main(int argc, char **argv) \ + { \ + return atf_tp_main(argc, argv, atfu_tp_add_tcs); \ + } \ + static \ + atf_error_t \ + atfu_tp_add_tcs(atf_tp_t *tps) + +#define ATF_TP_ADD_TC(tp, tc) \ + do { \ + atf_error_t atfu_err; \ + char **atfu_config = atf_tp_get_config(tp); \ + if (atfu_config == NULL) \ + return atf_no_memory_error(); \ + atfu_err = atf_tc_init_pack(&atfu_ ## tc ## _tc, \ + &atfu_ ## tc ## _tc_pack, \ + (const char *const *)atfu_config); \ + atf_utils_free_charpp(atfu_config); \ + if (atf_is_error(atfu_err)) \ + return atfu_err; \ + atfu_err = atf_tp_add_tc(tp, &atfu_ ## tc ## _tc); \ + if (atf_is_error(atfu_err)) \ + return atfu_err; \ + } while (0) + +#define ATF_REQUIRE_MSG(x, fmt, ...) \ + do { \ + if (!(x)) \ + atf_tc_fail_requirement(__FILE__, __LINE__, fmt, ##__VA_ARGS__); \ + } while(0) + +#define ATF_CHECK_MSG(x, fmt, ...) \ + do { \ + if (!(x)) \ + atf_tc_fail_check(__FILE__, __LINE__, fmt, ##__VA_ARGS__); \ + } while(0) + +#define ATF_REQUIRE(x) \ + do { \ + if (!(x)) \ + atf_tc_fail_requirement(__FILE__, __LINE__, "%s", #x " not met"); \ + } while(0) + +#define ATF_CHECK(x) \ + do { \ + if (!(x)) \ + atf_tc_fail_check(__FILE__, __LINE__, "%s", #x " not met"); \ + } while(0) + +#define ATF_REQUIRE_EQ(x, y) \ + ATF_REQUIRE_MSG((x) == (y), "%s != %s", #x, #y) + +#define ATF_CHECK_EQ(x, y) \ + ATF_CHECK_MSG((x) == (y), "%s != %s", #x, #y) + +#define ATF_REQUIRE_EQ_MSG(x, y, fmt, ...) \ + ATF_REQUIRE_MSG((x) == (y), "%s != %s: " fmt, #x, #y, ##__VA_ARGS__) + +#define ATF_CHECK_EQ_MSG(x, y, fmt, ...) \ + ATF_CHECK_MSG((x) == (y), "%s != %s: " fmt, #x, #y, ##__VA_ARGS__) + +#define ATF_REQUIRE_STREQ(x, y) \ + ATF_REQUIRE_MSG(strcmp(x, y) == 0, "%s != %s (%s != %s)", #x, #y, x, y) + +#define ATF_CHECK_STREQ(x, y) \ + ATF_CHECK_MSG(strcmp(x, y) == 0, "%s != %s (%s != %s)", #x, #y, x, y) + +#define ATF_REQUIRE_STREQ_MSG(x, y, fmt, ...) \ + ATF_REQUIRE_MSG(strcmp(x, y) == 0, "%s != %s (%s != %s): " fmt, \ + #x, #y, x, y, ##__VA_ARGS__) + +#define ATF_CHECK_STREQ_MSG(x, y, fmt, ...) \ + ATF_CHECK_MSG(strcmp(x, y) == 0, "%s != %s (%s != %s): " fmt, \ + #x, #y, x, y, ##__VA_ARGS__) + +#define ATF_REQUIRE_MATCH(regexp, string) \ + ATF_REQUIRE_MSG(atf_utils_grep_string("%s", string, regexp), \ + "'%s' not matched in '%s'", regexp, string); + +#define ATF_CHECK_MATCH(regexp, string) \ + ATF_CHECK_MSG(atf_utils_grep_string("%s", string, regexp), \ + "'%s' not matched in '%s'", regexp, string); + +#define ATF_REQUIRE_MATCH_MSG(regexp, string, fmt, ...) \ + ATF_REQUIRE_MSG(atf_utils_grep_string("%s", string, regexp), \ + "'%s' not matched in '%s': " fmt, regexp, string, \ + ##__VA_ARGS__); + +#define ATF_CHECK_MATCH_MSG(regexp, string, fmt, ...) \ + ATF_CHECK_MSG(atf_utils_grep_string("%s", string, regexp), \ + "'%s' not matched in '%s': " fmt, regexp, string, \ + ##__VA_ARGS__); + +#define ATF_CHECK_ERRNO(exp_errno, bool_expr) \ + atf_tc_check_errno(__FILE__, __LINE__, exp_errno, #bool_expr, bool_expr) + +#define ATF_REQUIRE_ERRNO(exp_errno, bool_expr) \ + atf_tc_require_errno(__FILE__, __LINE__, exp_errno, #bool_expr, bool_expr) + +#endif /* !defined(ATF_C_MACROS_H) */ diff --git a/external/bsd/atf/dist/atf-c/macros_h_test.c b/external/bsd/atf/dist/atf-c/macros_h_test.c new file mode 100644 index 000000000..3dae471e4 --- /dev/null +++ b/external/bsd/atf/dist/atf-c/macros_h_test.c @@ -0,0 +1,103 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +void atf_require_inside_if(void); +void atf_require_equal_inside_if(void); +void atf_check_errno_semicolons(void); +void atf_require_errno_semicolons(void); + +void +atf_require_inside_if(void) +{ + /* Make sure that ATF_REQUIRE can be used inside an if statement that + * does not have braces. Earlier versions of it generated an error + * if there was an else clause because they confused the compiler + * by defining an unprotected nested if. */ + if (true) + ATF_REQUIRE(true); + else + ATF_REQUIRE(true); +} + +void +atf_require_equal_inside_if(void) +{ + /* Make sure that ATF_REQUIRE_EQUAL can be used inside an if statement + * that does not have braces. Earlier versions of it generated an + * error if there was an else clause because they confused the + * compiler by defining an unprotected nested if. */ + if (true) + ATF_REQUIRE_EQ(true, true); + else + ATF_REQUIRE_EQ(true, true); +} + +void +atf_check_errno_semicolons(void) +{ + /* Check that ATF_CHECK_ERRNO does not contain a semicolon that would + * cause an empty-statement that confuses some compilers. */ + ATF_CHECK_ERRNO(1, 1 == 1); + ATF_CHECK_ERRNO(2, 2 == 2); +} + +void +atf_require_errno_semicolons(void) +{ + /* Check that ATF_REQUIRE_ERRNO does not contain a semicolon that would + * cause an empty-statement that confuses some compilers. */ + ATF_REQUIRE_ERRNO(1, 1 == 1); + ATF_REQUIRE_ERRNO(2, 2 == 2); +} + +/* Test case names should not be expanded during instatiation so that they + * can have the exact same name as macros. */ +#define TEST_MACRO_1 invalid + name +#define TEST_MACRO_2 invalid + name +#define TEST_MACRO_3 invalid + name +ATF_TC(TEST_MACRO_1); +ATF_TC_HEAD(TEST_MACRO_1, tc) { if (tc != NULL) {} } +ATF_TC_BODY(TEST_MACRO_1, tc) { if (tc != NULL) {} } +atf_tc_t *test_name_1 = &ATF_TC_NAME(TEST_MACRO_1); +void (*head_1)(atf_tc_t *) = ATF_TC_HEAD_NAME(TEST_MACRO_1); +void (*body_1)(const atf_tc_t *) = ATF_TC_BODY_NAME(TEST_MACRO_1); +ATF_TC_WITH_CLEANUP(TEST_MACRO_2); +ATF_TC_HEAD(TEST_MACRO_2, tc) { if (tc != NULL) {} } +ATF_TC_BODY(TEST_MACRO_2, tc) { if (tc != NULL) {} } +ATF_TC_CLEANUP(TEST_MACRO_2, tc) { if (tc != NULL) {} } +atf_tc_t *test_name_2 = &ATF_TC_NAME(TEST_MACRO_2); +void (*head_2)(atf_tc_t *) = ATF_TC_HEAD_NAME(TEST_MACRO_2); +void (*body_2)(const atf_tc_t *) = ATF_TC_BODY_NAME(TEST_MACRO_2); +void (*cleanup_2)(const atf_tc_t *) = ATF_TC_CLEANUP_NAME(TEST_MACRO_2); +ATF_TC_WITHOUT_HEAD(TEST_MACRO_3); +ATF_TC_BODY(TEST_MACRO_3, tc) { if (tc != NULL) {} } +atf_tc_t *test_name_3 = &ATF_TC_NAME(TEST_MACRO_3); +void (*body_3)(const atf_tc_t *) = ATF_TC_BODY_NAME(TEST_MACRO_3); diff --git a/external/bsd/atf/dist/atf-c/macros_test.c b/external/bsd/atf/dist/atf-c/macros_test.c new file mode 100644 index 000000000..f077a273d --- /dev/null +++ b/external/bsd/atf/dist/atf-c/macros_test.c @@ -0,0 +1,878 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "detail/fs.h" +#include "detail/process.h" +#include "detail/test_helpers.h" +#include "detail/text.h" + +/* --------------------------------------------------------------------- + * Auxiliary functions. + * --------------------------------------------------------------------- */ + +static +void +create_ctl_file(const char *name) +{ + atf_fs_path_t p; + + RE(atf_fs_path_init_fmt(&p, "%s", name)); + ATF_REQUIRE(open(atf_fs_path_cstring(&p), + O_CREAT | O_WRONLY | O_TRUNC, 0644) != -1); + atf_fs_path_fini(&p); +} + +static +bool +exists(const char *p) +{ + bool b; + atf_fs_path_t pp; + + RE(atf_fs_path_init_fmt(&pp, "%s", p)); + RE(atf_fs_exists(&pp, &b)); + atf_fs_path_fini(&pp); + + return b; +} + +static +void +init_and_run_h_tc(const char *name, void (*head)(atf_tc_t *), + void (*body)(const atf_tc_t *)) +{ + atf_tc_t tc; + const char *const config[] = { NULL }; + + RE(atf_tc_init(&tc, name, head, body, NULL, config)); + run_h_tc(&tc, "output", "error", "result"); + atf_tc_fini(&tc); +} + +/* --------------------------------------------------------------------- + * Helper test cases. + * --------------------------------------------------------------------- */ + +#define H_DEF(id, macro) \ + ATF_TC_HEAD(h_ ## id, tc) \ + { \ + atf_tc_set_md_var(tc, "descr", "Helper test case"); \ + } \ + ATF_TC_BODY(h_ ## id, tc) \ + { \ + create_ctl_file("before"); \ + macro; \ + create_ctl_file("after"); \ + } + +#define H_CHECK_HEAD_NAME(id) ATF_TC_HEAD_NAME(h_check_ ## id) +#define H_CHECK_BODY_NAME(id) ATF_TC_BODY_NAME(h_check_ ## id) +#define H_CHECK(id, condition) \ + H_DEF(check_ ## id, ATF_CHECK(condition)) + +#define H_CHECK_MSG_HEAD_NAME(id) ATF_TC_HEAD_NAME(h_check_msg_ ## id) +#define H_CHECK_MSG_BODY_NAME(id) ATF_TC_BODY_NAME(h_check_msg_ ## id) +#define H_CHECK_MSG(id, condition, msg) \ + H_DEF(check_msg_ ## id, ATF_CHECK_MSG(condition, msg)) + +#define H_CHECK_EQ_HEAD_NAME(id) ATF_TC_HEAD_NAME(h_check_eq_ ## id) +#define H_CHECK_EQ_BODY_NAME(id) ATF_TC_BODY_NAME(h_check_eq_ ## id) +#define H_CHECK_EQ(id, v1, v2) \ + H_DEF(check_eq_ ## id, ATF_CHECK_EQ(v1, v2)) + +#define H_CHECK_STREQ_HEAD_NAME(id) ATF_TC_HEAD_NAME(h_check_streq_ ## id) +#define H_CHECK_STREQ_BODY_NAME(id) ATF_TC_BODY_NAME(h_check_streq_ ## id) +#define H_CHECK_STREQ(id, v1, v2) \ + H_DEF(check_streq_ ## id, ATF_CHECK_STREQ(v1, v2)) + +#define H_CHECK_MATCH_HEAD_NAME(id) ATF_TC_HEAD_NAME(h_check_match_ ## id) +#define H_CHECK_MATCH_BODY_NAME(id) ATF_TC_BODY_NAME(h_check_match_ ## id) +#define H_CHECK_MATCH(id, v1, v2) \ + H_DEF(check_match_ ## id, ATF_CHECK_MATCH(v1, v2)) + +#define H_CHECK_EQ_MSG_HEAD_NAME(id) \ + ATF_TC_HEAD_NAME(h_check_eq_msg_ ## id) +#define H_CHECK_EQ_MSG_BODY_NAME(id) \ + ATF_TC_BODY_NAME(h_check_eq_msg_ ## id) +#define H_CHECK_EQ_MSG(id, v1, v2, msg) \ + H_DEF(check_eq_msg_ ## id, ATF_CHECK_EQ_MSG(v1, v2, msg)) + +#define H_CHECK_STREQ_MSG_HEAD_NAME(id) \ + ATF_TC_HEAD_NAME(h_check_streq_msg_ ## id) +#define H_CHECK_STREQ_MSG_BODY_NAME(id) \ + ATF_TC_BODY_NAME(h_check_streq_msg_ ## id) +#define H_CHECK_STREQ_MSG(id, v1, v2, msg) \ + H_DEF(check_streq_msg_ ## id, ATF_CHECK_STREQ_MSG(v1, v2, msg)) + +#define H_CHECK_MATCH_MSG_HEAD_NAME(id) \ + ATF_TC_HEAD_NAME(h_check_match_msg_ ## id) +#define H_CHECK_MATCH_MSG_BODY_NAME(id) \ + ATF_TC_BODY_NAME(h_check_match_msg_ ## id) +#define H_CHECK_MATCH_MSG(id, v1, v2, msg) \ + H_DEF(check_match_msg_ ## id, ATF_CHECK_MATCH_MSG(v1, v2, msg)) + +#define H_CHECK_ERRNO_HEAD_NAME(id) ATF_TC_HEAD_NAME(h_check_errno_ ## id) +#define H_CHECK_ERRNO_BODY_NAME(id) ATF_TC_BODY_NAME(h_check_errno_ ## id) +#define H_CHECK_ERRNO(id, exp_errno, bool_expr) \ + H_DEF(check_errno_ ## id, ATF_CHECK_ERRNO(exp_errno, bool_expr)) + +#define H_REQUIRE_HEAD_NAME(id) ATF_TC_HEAD_NAME(h_require_ ## id) +#define H_REQUIRE_BODY_NAME(id) ATF_TC_BODY_NAME(h_require_ ## id) +#define H_REQUIRE(id, condition) \ + H_DEF(require_ ## id, ATF_REQUIRE(condition)) + +#define H_REQUIRE_MSG_HEAD_NAME(id) ATF_TC_HEAD_NAME(h_require_msg_ ## id) +#define H_REQUIRE_MSG_BODY_NAME(id) ATF_TC_BODY_NAME(h_require_msg_ ## id) +#define H_REQUIRE_MSG(id, condition, msg) \ + H_DEF(require_msg_ ## id, ATF_REQUIRE_MSG(condition, msg)) + +#define H_REQUIRE_EQ_HEAD_NAME(id) ATF_TC_HEAD_NAME(h_require_eq_ ## id) +#define H_REQUIRE_EQ_BODY_NAME(id) ATF_TC_BODY_NAME(h_require_eq_ ## id) +#define H_REQUIRE_EQ(id, v1, v2) \ + H_DEF(require_eq_ ## id, ATF_REQUIRE_EQ(v1, v2)) + +#define H_REQUIRE_STREQ_HEAD_NAME(id) ATF_TC_HEAD_NAME(h_require_streq_ ## id) +#define H_REQUIRE_STREQ_BODY_NAME(id) ATF_TC_BODY_NAME(h_require_streq_ ## id) +#define H_REQUIRE_STREQ(id, v1, v2) \ + H_DEF(require_streq_ ## id, ATF_REQUIRE_STREQ(v1, v2)) + +#define H_REQUIRE_MATCH_HEAD_NAME(id) ATF_TC_HEAD_NAME(h_require_match_ ## id) +#define H_REQUIRE_MATCH_BODY_NAME(id) ATF_TC_BODY_NAME(h_require_match_ ## id) +#define H_REQUIRE_MATCH(id, v1, v2) \ + H_DEF(require_match_ ## id, ATF_REQUIRE_MATCH(v1, v2)) + +#define H_REQUIRE_EQ_MSG_HEAD_NAME(id) \ + ATF_TC_HEAD_NAME(h_require_eq_msg_ ## id) +#define H_REQUIRE_EQ_MSG_BODY_NAME(id) \ + ATF_TC_BODY_NAME(h_require_eq_msg_ ## id) +#define H_REQUIRE_EQ_MSG(id, v1, v2, msg) \ + H_DEF(require_eq_msg_ ## id, ATF_REQUIRE_EQ_MSG(v1, v2, msg)) + +#define H_REQUIRE_STREQ_MSG_HEAD_NAME(id) \ + ATF_TC_HEAD_NAME(h_require_streq_msg_ ## id) +#define H_REQUIRE_STREQ_MSG_BODY_NAME(id) \ + ATF_TC_BODY_NAME(h_require_streq_msg_ ## id) +#define H_REQUIRE_STREQ_MSG(id, v1, v2, msg) \ + H_DEF(require_streq_msg_ ## id, ATF_REQUIRE_STREQ_MSG(v1, v2, msg)) + +#define H_REQUIRE_MATCH_MSG_HEAD_NAME(id) \ + ATF_TC_HEAD_NAME(h_require_match_msg_ ## id) +#define H_REQUIRE_MATCH_MSG_BODY_NAME(id) \ + ATF_TC_BODY_NAME(h_require_match_msg_ ## id) +#define H_REQUIRE_MATCH_MSG(id, v1, v2, msg) \ + H_DEF(require_match_msg_ ## id, ATF_REQUIRE_MATCH_MSG(v1, v2, msg)) + +#define H_REQUIRE_ERRNO_HEAD_NAME(id) ATF_TC_HEAD_NAME(h_require_errno_ ## id) +#define H_REQUIRE_ERRNO_BODY_NAME(id) ATF_TC_BODY_NAME(h_require_errno_ ## id) +#define H_REQUIRE_ERRNO(id, exp_errno, bool_expr) \ + H_DEF(require_errno_ ## id, ATF_REQUIRE_ERRNO(exp_errno, bool_expr)) + +/* --------------------------------------------------------------------- + * Test cases for the ATF_{CHECK,REQUIRE}_ERRNO macros. + * --------------------------------------------------------------------- */ + +static int +errno_fail_stub(const int raised_errno) +{ + errno = raised_errno; + return -1; +} + +static int +errno_ok_stub(void) +{ + return 0; +} + +H_CHECK_ERRNO(no_error, -1, errno_ok_stub() == -1); +H_CHECK_ERRNO(errno_ok, 2, errno_fail_stub(2) == -1); +H_CHECK_ERRNO(errno_fail, 3, errno_fail_stub(4) == -1); + +H_REQUIRE_ERRNO(no_error, -1, errno_ok_stub() == -1); +H_REQUIRE_ERRNO(errno_ok, 2, errno_fail_stub(2) == -1); +H_REQUIRE_ERRNO(errno_fail, 3, errno_fail_stub(4) == -1); + +ATF_TC(check_errno); +ATF_TC_HEAD(check_errno, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the ATF_CHECK_ERRNO macro"); +} +ATF_TC_BODY(check_errno, tc) +{ + struct test { + void (*head)(atf_tc_t *); + void (*body)(const atf_tc_t *); + bool ok; + const char *exp_regex; + } *t, tests[] = { + { H_CHECK_ERRNO_HEAD_NAME(no_error), + H_CHECK_ERRNO_BODY_NAME(no_error), + false, "Expected true value in errno_ok_stub\\(\\) == -1" }, + { H_CHECK_ERRNO_HEAD_NAME(errno_ok), + H_CHECK_ERRNO_BODY_NAME(errno_ok), + true, NULL }, + { H_CHECK_ERRNO_HEAD_NAME(errno_fail), + H_CHECK_ERRNO_BODY_NAME(errno_fail), + false, "Expected errno 3, got 4, in errno_fail_stub\\(4\\) == -1" }, + { NULL, NULL, false, NULL } + }; + + for (t = &tests[0]; t->head != NULL; t++) { + init_and_run_h_tc("h_check_errno", t->head, t->body); + + ATF_REQUIRE(exists("before")); + ATF_REQUIRE(exists("after")); + + if (t->ok) { + ATF_REQUIRE(atf_utils_grep_file("^passed", "result")); + } else { + ATF_REQUIRE(atf_utils_grep_file("^failed", "result")); + ATF_REQUIRE(atf_utils_grep_file( + "macros_test.c:[0-9]+: %s$", "error", t->exp_regex)); + } + + ATF_REQUIRE(unlink("before") != -1); + ATF_REQUIRE(unlink("after") != -1); + } +} + +ATF_TC(require_errno); +ATF_TC_HEAD(require_errno, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the ATF_REQUIRE_ERRNO macro"); +} +ATF_TC_BODY(require_errno, tc) +{ + struct test { + void (*head)(atf_tc_t *); + void (*body)(const atf_tc_t *); + bool ok; + const char *exp_regex; + } *t, tests[] = { + { H_REQUIRE_ERRNO_HEAD_NAME(no_error), + H_REQUIRE_ERRNO_BODY_NAME(no_error), + false, "Expected true value in errno_ok_stub\\(\\) == -1" }, + { H_REQUIRE_ERRNO_HEAD_NAME(errno_ok), + H_REQUIRE_ERRNO_BODY_NAME(errno_ok), + true, NULL }, + { H_REQUIRE_ERRNO_HEAD_NAME(errno_fail), + H_REQUIRE_ERRNO_BODY_NAME(errno_fail), + false, "Expected errno 3, got 4, in errno_fail_stub\\(4\\) == -1" }, + { NULL, NULL, false, NULL } + }; + + for (t = &tests[0]; t->head != NULL; t++) { + init_and_run_h_tc("h_require_errno", t->head, t->body); + + ATF_REQUIRE(exists("before")); + if (t->ok) { + ATF_REQUIRE(atf_utils_grep_file("^passed", "result")); + ATF_REQUIRE(exists("after")); + } else { + ATF_REQUIRE(atf_utils_grep_file( + "^failed: .*macros_test.c:[0-9]+: %s$", "result", + t->exp_regex)); + ATF_REQUIRE(!exists("after")); + } + + ATF_REQUIRE(unlink("before") != -1); + if (t->ok) + ATF_REQUIRE(unlink("after") != -1); + } +} + +/* --------------------------------------------------------------------- + * Test cases for the ATF_CHECK and ATF_CHECK_MSG macros. + * --------------------------------------------------------------------- */ + +H_CHECK(0, 0); +H_CHECK(1, 1); +H_CHECK_MSG(0, 0, "expected a false value"); +H_CHECK_MSG(1, 1, "expected a true value"); + +ATF_TC(check); +ATF_TC_HEAD(check, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the ATF_CHECK and " + "ATF_CHECK_MSG macros"); +} +ATF_TC_BODY(check, tc) +{ + struct test { + void (*head)(atf_tc_t *); + void (*body)(const atf_tc_t *); + bool value; + const char *msg; + bool ok; + } *t, tests[] = { + { H_CHECK_HEAD_NAME(0), H_CHECK_BODY_NAME(0), 0, + "0 not met", false }, + { H_CHECK_HEAD_NAME(1), H_CHECK_BODY_NAME(1), 1, + "1 not met", true }, + { H_CHECK_MSG_HEAD_NAME(0), H_CHECK_MSG_BODY_NAME(0), 0, + "expected a false value", false }, + { H_CHECK_MSG_HEAD_NAME(1), H_CHECK_MSG_BODY_NAME(1), 1, + "expected a true value", true }, + { NULL, NULL, false, NULL, false } + }; + + for (t = &tests[0]; t->head != NULL; t++) { + printf("Checking with a %d value\n", t->value); + + init_and_run_h_tc("h_check", t->head, t->body); + + ATF_REQUIRE(exists("before")); + ATF_REQUIRE(exists("after")); + + if (t->ok) { + ATF_REQUIRE(atf_utils_grep_file("^passed", "result")); + } else { + ATF_REQUIRE(atf_utils_grep_file("^failed", "result")); + ATF_REQUIRE(atf_utils_grep_file("Check failed: .*" + "macros_test.c:[0-9]+: %s$", "error", t->msg)); + } + + ATF_REQUIRE(unlink("before") != -1); + ATF_REQUIRE(unlink("after") != -1); + } +} + +/* --------------------------------------------------------------------- + * Test cases for the ATF_CHECK_*EQ_ macros. + * --------------------------------------------------------------------- */ + +struct check_eq_test { + void (*head)(atf_tc_t *); + void (*body)(const atf_tc_t *); + const char *v1; + const char *v2; + const char *msg; + bool ok; +}; + +static +void +do_check_eq_tests(const struct check_eq_test *tests) +{ + const struct check_eq_test *t; + + for (t = &tests[0]; t->head != NULL; t++) { + printf("Checking with %s, %s and expecting %s\n", t->v1, t->v2, + t->ok ? "true" : "false"); + + init_and_run_h_tc("h_check", t->head, t->body); + + ATF_CHECK(exists("before")); + ATF_CHECK(exists("after")); + + if (t->ok) { + ATF_REQUIRE(atf_utils_grep_file("^passed", "result")); + } else { + ATF_REQUIRE(atf_utils_grep_file("^failed", "result")); + ATF_CHECK(atf_utils_grep_file("Check failed: .*" + "macros_test.c:[0-9]+: %s$", "error", t->msg)); + } + + ATF_CHECK(unlink("before") != -1); + ATF_CHECK(unlink("after") != -1); + } +} + +H_CHECK_EQ(1_1, 1, 1); +H_CHECK_EQ(1_2, 1, 2); +H_CHECK_EQ(2_1, 2, 1); +H_CHECK_EQ(2_2, 2, 2); +H_CHECK_EQ_MSG(1_1, 1, 1, "1 does not match 1"); +H_CHECK_EQ_MSG(1_2, 1, 2, "1 does not match 2"); +H_CHECK_EQ_MSG(2_1, 2, 1, "2 does not match 1"); +H_CHECK_EQ_MSG(2_2, 2, 2, "2 does not match 2"); + +ATF_TC(check_eq); +ATF_TC_HEAD(check_eq, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the ATF_CHECK_EQ and " + "ATF_CHECK_EQ_MSG macros"); +} +ATF_TC_BODY(check_eq, tc) +{ + struct check_eq_test tests[] = { + { H_CHECK_EQ_HEAD_NAME(1_1), H_CHECK_EQ_BODY_NAME(1_1), + "1", "1", "1 != 1", true }, + { H_CHECK_EQ_HEAD_NAME(1_2), H_CHECK_EQ_BODY_NAME(1_2), + "1", "2", "1 != 2", false }, + { H_CHECK_EQ_HEAD_NAME(2_1), H_CHECK_EQ_BODY_NAME(2_1), + "2", "1", "2 != 1", false }, + { H_CHECK_EQ_HEAD_NAME(2_2), H_CHECK_EQ_BODY_NAME(2_2), + "2", "2", "2 != 2", true }, + { H_CHECK_EQ_MSG_HEAD_NAME(1_1), H_CHECK_EQ_MSG_BODY_NAME(1_1), + "1", "1", "1 != 1: 1 does not match 1", true }, + { H_CHECK_EQ_MSG_HEAD_NAME(1_2), H_CHECK_EQ_MSG_BODY_NAME(1_2), + "1", "2", "1 != 2: 1 does not match 2", false }, + { H_CHECK_EQ_MSG_HEAD_NAME(2_1), H_CHECK_EQ_MSG_BODY_NAME(2_1), + "2", "1", "2 != 1: 2 does not match 1", false }, + { H_CHECK_EQ_MSG_HEAD_NAME(2_2), H_CHECK_EQ_MSG_BODY_NAME(2_2), + "2", "2", "2 != 2: 2 does not match 2", true }, + { NULL, NULL, 0, 0, "", false } + }; + do_check_eq_tests(tests); +} + +H_CHECK_STREQ(1_1, "1", "1"); +H_CHECK_STREQ(1_2, "1", "2"); +H_CHECK_STREQ(2_1, "2", "1"); +H_CHECK_STREQ(2_2, "2", "2"); +H_CHECK_STREQ_MSG(1_1, "1", "1", "1 does not match 1"); +H_CHECK_STREQ_MSG(1_2, "1", "2", "1 does not match 2"); +H_CHECK_STREQ_MSG(2_1, "2", "1", "2 does not match 1"); +H_CHECK_STREQ_MSG(2_2, "2", "2", "2 does not match 2"); +#define CHECK_STREQ_VAR1 "5" +#define CHECK_STREQ_VAR2 "9" +const char *check_streq_var1 = CHECK_STREQ_VAR1; +const char *check_streq_var2 = CHECK_STREQ_VAR2; +H_CHECK_STREQ(vars, check_streq_var1, check_streq_var2); + +ATF_TC(check_streq); +ATF_TC_HEAD(check_streq, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the ATF_CHECK_STREQ and " + "ATF_CHECK_STREQ_MSG macros"); +} +ATF_TC_BODY(check_streq, tc) +{ + struct check_eq_test tests[] = { + { H_CHECK_STREQ_HEAD_NAME(1_1), H_CHECK_STREQ_BODY_NAME(1_1), + "1", "1", "\"1\" != \"1\" \\(1 != 1\\)", true }, + { H_CHECK_STREQ_HEAD_NAME(1_2), H_CHECK_STREQ_BODY_NAME(1_2), + "1", "2", "\"1\" != \"2\" \\(1 != 2\\)", false }, + { H_CHECK_STREQ_HEAD_NAME(2_1), H_CHECK_STREQ_BODY_NAME(2_1), + "2", "1", "\"2\" != \"1\" \\(2 != 1\\)", false }, + { H_CHECK_STREQ_HEAD_NAME(2_2), H_CHECK_STREQ_BODY_NAME(2_2), + "2", "2", "\"2\" != \"2\" \\(2 != 2\\)", true }, + { H_CHECK_STREQ_MSG_HEAD_NAME(1_1), + H_CHECK_STREQ_MSG_BODY_NAME(1_1), + "1", "1", "\"1\" != \"1\" \\(1 != 1\\): 1 does not match 1", true }, + { H_CHECK_STREQ_MSG_HEAD_NAME(1_2), + H_CHECK_STREQ_MSG_BODY_NAME(1_2), + "1", "2", "\"1\" != \"2\" \\(1 != 2\\): 1 does not match 2", false }, + { H_CHECK_STREQ_MSG_HEAD_NAME(2_1), + H_CHECK_STREQ_MSG_BODY_NAME(2_1), + "2", "1", "\"2\" != \"1\" \\(2 != 1\\): 2 does not match 1", false }, + { H_CHECK_STREQ_MSG_HEAD_NAME(2_2), + H_CHECK_STREQ_MSG_BODY_NAME(2_2), + "2", "2", "\"2\" != \"2\" \\(2 != 2\\): 2 does not match 2", true }, + { H_CHECK_STREQ_HEAD_NAME(vars), H_CHECK_STREQ_BODY_NAME(vars), + check_streq_var1, check_streq_var2, + "check_streq_var1 != check_streq_var2 \\(" + CHECK_STREQ_VAR1 " != " CHECK_STREQ_VAR2 "\\)", false }, + { NULL, NULL, 0, 0, "", false } + }; + do_check_eq_tests(tests); +} + +/* --------------------------------------------------------------------- + * Test cases for the ATF_CHECK_MATCH and ATF_CHECK_MATCH_MSG macros. + * --------------------------------------------------------------------- */ + +H_CHECK_MATCH(yes, "hello [a-z]+", "abc hello world"); +H_CHECK_MATCH(no, "hello [a-z]+", "abc hello WORLD"); +H_CHECK_MATCH_MSG(yes, "hello [a-z]+", "abc hello world", "lowercase"); +H_CHECK_MATCH_MSG(no, "hello [a-z]+", "abc hello WORLD", "uppercase"); + +ATF_TC(check_match); +ATF_TC_HEAD(check_match, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the ATF_CHECK_MATCH and " + "ATF_CHECK_MATCH_MSG macros"); +} +ATF_TC_BODY(check_match, tc) +{ + struct check_eq_test tests[] = { + { H_CHECK_MATCH_HEAD_NAME(yes), H_CHECK_MATCH_BODY_NAME(yes), + "hello [a-z]+", "abc hello world", "", true }, + { H_CHECK_MATCH_HEAD_NAME(no), H_CHECK_MATCH_BODY_NAME(no), + "hello [a-z]+", "abc hello WORLD", + "'hello \\[a-z\\]\\+' not matched in 'abc hello WORLD'", false }, + { H_CHECK_MATCH_MSG_HEAD_NAME(yes), H_CHECK_MATCH_MSG_BODY_NAME(yes), + "hello [a-z]+", "abc hello world", "", true }, + { H_CHECK_MATCH_MSG_HEAD_NAME(no), H_CHECK_MATCH_MSG_BODY_NAME(no), + "hello [a-z]+", "abc hello WORLD", + "'hello \\[a-z\\]\\+' not matched in 'abc hello WORLD': uppercase", + false }, + { NULL, NULL, 0, 0, "", false } + }; + do_check_eq_tests(tests); +} + +/* --------------------------------------------------------------------- + * Test cases for the ATF_REQUIRE and ATF_REQUIRE_MSG macros. + * --------------------------------------------------------------------- */ + +H_REQUIRE(0, 0); +H_REQUIRE(1, 1); +H_REQUIRE_MSG(0, 0, "expected a false value"); +H_REQUIRE_MSG(1, 1, "expected a true value"); + +ATF_TC(require); +ATF_TC_HEAD(require, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the ATF_REQUIRE and " + "ATF_REQUIRE_MSG macros"); +} +ATF_TC_BODY(require, tc) +{ + struct test { + void (*head)(atf_tc_t *); + void (*body)(const atf_tc_t *); + bool value; + const char *msg; + bool ok; + } *t, tests[] = { + { H_REQUIRE_HEAD_NAME(0), H_REQUIRE_BODY_NAME(0), 0, + "0 not met", false }, + { H_REQUIRE_HEAD_NAME(1), H_REQUIRE_BODY_NAME(1), 1, + "1 not met", true }, + { H_REQUIRE_MSG_HEAD_NAME(0), H_REQUIRE_MSG_BODY_NAME(0), 0, + "expected a false value", false }, + { H_REQUIRE_MSG_HEAD_NAME(1), H_REQUIRE_MSG_BODY_NAME(1), 1, + "expected a true value", true }, + { NULL, NULL, false, NULL, false } + }; + + for (t = &tests[0]; t->head != NULL; t++) { + printf("Checking with a %d value\n", t->value); + + init_and_run_h_tc("h_require", t->head, t->body); + + ATF_REQUIRE(exists("before")); + if (t->ok) { + ATF_REQUIRE(atf_utils_grep_file("^passed", "result")); + ATF_REQUIRE(exists("after")); + } else { + ATF_REQUIRE(atf_utils_grep_file( + "^failed: .*macros_test.c:[0-9]+: %s$", "result", t->msg)); + ATF_REQUIRE(!exists("after")); + } + + ATF_REQUIRE(unlink("before") != -1); + if (t->ok) + ATF_REQUIRE(unlink("after") != -1); + } +} + +/* --------------------------------------------------------------------- + * Test cases for the ATF_REQUIRE_*EQ_ macros. + * --------------------------------------------------------------------- */ + +struct require_eq_test { + void (*head)(atf_tc_t *); + void (*body)(const atf_tc_t *); + const char *v1; + const char *v2; + const char *msg; + bool ok; +}; + +static +void +do_require_eq_tests(const struct require_eq_test *tests) +{ + const struct require_eq_test *t; + + for (t = &tests[0]; t->head != NULL; t++) { + printf("Checking with %s, %s and expecting %s\n", t->v1, t->v2, + t->ok ? "true" : "false"); + + init_and_run_h_tc("h_require", t->head, t->body); + + ATF_REQUIRE(exists("before")); + if (t->ok) { + ATF_REQUIRE(atf_utils_grep_file("^passed", "result")); + ATF_REQUIRE(exists("after")); + } else { + ATF_REQUIRE(atf_utils_grep_file("^failed: .*macros_test.c" + ":[0-9]+: %s$", "result", t->msg)); + ATF_REQUIRE(!exists("after")); + } + + ATF_REQUIRE(unlink("before") != -1); + if (t->ok) + ATF_REQUIRE(unlink("after") != -1); + } +} + +H_REQUIRE_EQ(1_1, 1, 1); +H_REQUIRE_EQ(1_2, 1, 2); +H_REQUIRE_EQ(2_1, 2, 1); +H_REQUIRE_EQ(2_2, 2, 2); +H_REQUIRE_EQ_MSG(1_1, 1, 1, "1 does not match 1"); +H_REQUIRE_EQ_MSG(1_2, 1, 2, "1 does not match 2"); +H_REQUIRE_EQ_MSG(2_1, 2, 1, "2 does not match 1"); +H_REQUIRE_EQ_MSG(2_2, 2, 2, "2 does not match 2"); + +ATF_TC(require_eq); +ATF_TC_HEAD(require_eq, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the ATF_REQUIRE_EQ and " + "ATF_REQUIRE_EQ_MSG macros"); +} +ATF_TC_BODY(require_eq, tc) +{ + struct require_eq_test tests[] = { + { H_REQUIRE_EQ_HEAD_NAME(1_1), H_REQUIRE_EQ_BODY_NAME(1_1), + "1", "1", "1 != 1", true }, + { H_REQUIRE_EQ_HEAD_NAME(1_2), H_REQUIRE_EQ_BODY_NAME(1_2), + "1", "2", "1 != 2", false }, + { H_REQUIRE_EQ_HEAD_NAME(2_1), H_REQUIRE_EQ_BODY_NAME(2_1), + "2", "1", "2 != 1", false }, + { H_REQUIRE_EQ_HEAD_NAME(2_2), H_REQUIRE_EQ_BODY_NAME(2_2), + "2", "2", "2 != 2", true }, + { H_REQUIRE_EQ_MSG_HEAD_NAME(1_1), H_REQUIRE_EQ_MSG_BODY_NAME(1_1), + "1", "1", "1 != 1: 1 does not match 1", true }, + { H_REQUIRE_EQ_MSG_HEAD_NAME(1_2), H_REQUIRE_EQ_MSG_BODY_NAME(1_2), + "1", "2", "1 != 2: 1 does not match 2", false }, + { H_REQUIRE_EQ_MSG_HEAD_NAME(2_1), H_REQUIRE_EQ_MSG_BODY_NAME(2_1), + "2", "1", "2 != 1: 2 does not match 1", false }, + { H_REQUIRE_EQ_MSG_HEAD_NAME(2_2), H_REQUIRE_EQ_MSG_BODY_NAME(2_2), + "2", "2", "2 != 2: 2 does not match 2", true }, + { NULL, NULL, 0, 0, "", false } + }; + do_require_eq_tests(tests); +} + +H_REQUIRE_STREQ(1_1, "1", "1"); +H_REQUIRE_STREQ(1_2, "1", "2"); +H_REQUIRE_STREQ(2_1, "2", "1"); +H_REQUIRE_STREQ(2_2, "2", "2"); +H_REQUIRE_STREQ_MSG(1_1, "1", "1", "1 does not match 1"); +H_REQUIRE_STREQ_MSG(1_2, "1", "2", "1 does not match 2"); +H_REQUIRE_STREQ_MSG(2_1, "2", "1", "2 does not match 1"); +H_REQUIRE_STREQ_MSG(2_2, "2", "2", "2 does not match 2"); +#define REQUIRE_STREQ_VAR1 "5" +#define REQUIRE_STREQ_VAR2 "9" +const char *require_streq_var1 = REQUIRE_STREQ_VAR1; +const char *require_streq_var2 = REQUIRE_STREQ_VAR2; +H_REQUIRE_STREQ(vars, require_streq_var1, require_streq_var2); + +ATF_TC(require_streq); +ATF_TC_HEAD(require_streq, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the ATF_REQUIRE_STREQ and " + "ATF_REQUIRE_STREQ_MSG macros"); +} +ATF_TC_BODY(require_streq, tc) +{ + struct require_eq_test tests[] = { + { H_REQUIRE_STREQ_HEAD_NAME(1_1), H_REQUIRE_STREQ_BODY_NAME(1_1), + "1", "1", "\"1\" != \"1\" \\(1 != 1\\)", true }, + { H_REQUIRE_STREQ_HEAD_NAME(1_2), H_REQUIRE_STREQ_BODY_NAME(1_2), + "1", "2", "\"1\" != \"2\" \\(1 != 2\\)", false }, + { H_REQUIRE_STREQ_HEAD_NAME(2_1), H_REQUIRE_STREQ_BODY_NAME(2_1), + "2", "1", "\"2\" != \"1\" \\(2 != 1\\)", false }, + { H_REQUIRE_STREQ_HEAD_NAME(2_2), H_REQUIRE_STREQ_BODY_NAME(2_2), + "2", "2", "\"2\" != \"2\" \\(2 != 2\\)", true }, + { H_REQUIRE_STREQ_MSG_HEAD_NAME(1_1), + H_REQUIRE_STREQ_MSG_BODY_NAME(1_1), + "1", "1", "\"1\" != \"1\" \\(1 != 1\\): 1 does not match 1", true }, + { H_REQUIRE_STREQ_MSG_HEAD_NAME(1_2), + H_REQUIRE_STREQ_MSG_BODY_NAME(1_2), + "1", "2", "\"1\" != \"2\" \\(1 != 2\\): 1 does not match 2", false }, + { H_REQUIRE_STREQ_MSG_HEAD_NAME(2_1), + H_REQUIRE_STREQ_MSG_BODY_NAME(2_1), + "2", "1", "\"2\" != \"1\" \\(2 != 1\\): 2 does not match 1", false }, + { H_REQUIRE_STREQ_MSG_HEAD_NAME(2_2), + H_REQUIRE_STREQ_MSG_BODY_NAME(2_2), + "2", "2", "\"2\" != \"2\" \\(2 != 2\\): 2 does not match 2", true }, + { H_REQUIRE_STREQ_HEAD_NAME(vars), H_REQUIRE_STREQ_BODY_NAME(vars), + require_streq_var1, require_streq_var2, + "require_streq_var1 != require_streq_var2 \\(" + REQUIRE_STREQ_VAR1 " != " REQUIRE_STREQ_VAR2 "\\)", false }, + { NULL, NULL, 0, 0, "", false } + }; + do_require_eq_tests(tests); +} + +/* --------------------------------------------------------------------- + * Test cases for the ATF_REQUIRE_MATCH and ATF_REQUIRE_MATCH_MSG macros. + * --------------------------------------------------------------------- */ + +H_REQUIRE_MATCH(yes, "hello [a-z]+", "abc hello world"); +H_REQUIRE_MATCH(no, "hello [a-z]+", "abc hello WORLD"); +H_REQUIRE_MATCH_MSG(yes, "hello [a-z]+", "abc hello world", "lowercase"); +H_REQUIRE_MATCH_MSG(no, "hello [a-z]+", "abc hello WORLD", "uppercase"); + +ATF_TC(require_match); +ATF_TC_HEAD(require_match, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the ATF_REQUIRE_MATCH and " + "ATF_REQUIRE_MATCH_MSG macros"); +} +ATF_TC_BODY(require_match, tc) +{ + struct require_eq_test tests[] = { + { H_REQUIRE_MATCH_HEAD_NAME(yes), H_REQUIRE_MATCH_BODY_NAME(yes), + "hello [a-z]+", "abc hello world", "", true }, + { H_REQUIRE_MATCH_HEAD_NAME(no), H_REQUIRE_MATCH_BODY_NAME(no), + "hello [a-z]+", "abc hello WORLD", + "'hello \\[a-z\\]\\+' not matched in 'abc hello WORLD'", false }, + { H_REQUIRE_MATCH_MSG_HEAD_NAME(yes), + H_REQUIRE_MATCH_MSG_BODY_NAME(yes), + "hello [a-z]+", "abc hello world", "", true }, + { H_REQUIRE_MATCH_MSG_HEAD_NAME(no), H_REQUIRE_MATCH_MSG_BODY_NAME(no), + "hello [a-z]+", "abc hello WORLD", + "'hello \\[a-z\\]\\+' not matched in 'abc hello WORLD': uppercase", + false }, + { NULL, NULL, 0, 0, "", false } + }; + do_require_eq_tests(tests); +} + +/* --------------------------------------------------------------------- + * Miscellaneous test cases covering several macros. + * --------------------------------------------------------------------- */ + +static +bool +aux_bool(const char *fmt ATF_DEFS_ATTRIBUTE_UNUSED) +{ + return false; +} + +static +const char * +aux_str(const char *fmt ATF_DEFS_ATTRIBUTE_UNUSED) +{ + return "foo"; +} + +H_CHECK(msg, aux_bool("%d")); +H_REQUIRE(msg, aux_bool("%d")); +H_CHECK_STREQ(msg, aux_str("%d"), ""); +H_REQUIRE_STREQ(msg, aux_str("%d"), ""); + +ATF_TC(msg_embedded_fmt); +ATF_TC_HEAD(msg_embedded_fmt, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests that format strings passed " + "as part of the automatically-generated messages " + "do not get expanded"); +} +ATF_TC_BODY(msg_embedded_fmt, tc) +{ + struct test { + void (*head)(atf_tc_t *); + void (*body)(const atf_tc_t *); + bool fatal; + const char *msg; + } *t, tests[] = { + { H_CHECK_HEAD_NAME(msg), H_CHECK_BODY_NAME(msg), false, + "aux_bool\\(\"%d\"\\) not met" }, + { H_REQUIRE_HEAD_NAME(msg), H_REQUIRE_BODY_NAME(msg), true, + "aux_bool\\(\"%d\"\\) not met" }, + { H_CHECK_STREQ_HEAD_NAME(msg), H_CHECK_STREQ_BODY_NAME(msg), false, + "aux_str\\(\"%d\"\\) != \"\" \\(foo != \\)" }, + { H_REQUIRE_STREQ_HEAD_NAME(msg), H_REQUIRE_STREQ_BODY_NAME(msg), true, + "aux_str\\(\"%d\"\\) != \"\" \\(foo != \\)" }, + { NULL, NULL, false, NULL } + }; + + for (t = &tests[0]; t->head != NULL; t++) { + printf("Checking with an expected '%s' message\n", t->msg); + + init_and_run_h_tc("h_check", t->head, t->body); + + if (t->fatal) { + bool matched = + atf_utils_grep_file( + "^failed: .*macros_test.c:[0-9]+: %s$", "result", t->msg); + ATF_CHECK_MSG(matched, "couldn't find error string in result"); + } else { + bool matched = atf_utils_grep_file("Check failed: .*" + "macros_test.c:[0-9]+: %s$", "error", t->msg); + ATF_CHECK_MSG(matched, "couldn't find error string in output"); + } + } +} + +/* --------------------------------------------------------------------- + * Tests cases for the header file. + * --------------------------------------------------------------------- */ + +HEADER_TC(include, "atf-c/macros.h"); +BUILD_TC(use, "macros_h_test.c", + "Tests that the macros provided by the atf-c/macros.h file " + "do not cause syntax errors when used", + "Build of macros_h_test.c failed; some macros in atf-c/macros.h " + "are broken"); +BUILD_TC_FAIL(detect_unused_tests, "unused_test.c", + "Tests that defining an unused test case raises a warning (and thus " + "an error)", + "Build of unused_test.c passed; unused test cases are not properly " + "detected"); + +/* --------------------------------------------------------------------- + * Main. + * --------------------------------------------------------------------- */ + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, check); + ATF_TP_ADD_TC(tp, check_eq); + ATF_TP_ADD_TC(tp, check_streq); + ATF_TP_ADD_TC(tp, check_errno); + ATF_TP_ADD_TC(tp, check_match); + + ATF_TP_ADD_TC(tp, require); + ATF_TP_ADD_TC(tp, require_eq); + ATF_TP_ADD_TC(tp, require_streq); + ATF_TP_ADD_TC(tp, require_errno); + ATF_TP_ADD_TC(tp, require_match); + + ATF_TP_ADD_TC(tp, msg_embedded_fmt); + + /* Add the test cases for the header file. */ + ATF_TP_ADD_TC(tp, include); + ATF_TP_ADD_TC(tp, use); + ATF_TP_ADD_TC(tp, detect_unused_tests); + + return atf_no_error(); +} diff --git a/external/bsd/atf/dist/atf-c/pkg_config_test.sh b/external/bsd/atf/dist/atf-c/pkg_config_test.sh new file mode 100644 index 000000000..efeae8323 --- /dev/null +++ b/external/bsd/atf/dist/atf-c/pkg_config_test.sh @@ -0,0 +1,149 @@ +# +# Automated Testing Framework (atf) +# +# Copyright (c) 2008 The NetBSD Foundation, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +# CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# The following tests assume that the atf-c.pc file is installed in a +# directory that is known by pkg-config. Otherwise they will fail, +# and you will be required to adjust PKG_CONFIG_PATH accordingly. +# +# It would be possible to bypass this requirement by setting the path +# explicitly during the tests, but then this would not do a real check +# to ensure that the installation is working. + +require_pc() +{ + pkg-config ${1} || atf_fail "pkg-config could not locate ${1}.pc;" \ + "maybe need to set PKG_CONFIG_PATH?" +} + +check_version() +{ + atf_check -s eq:0 -o save:stdout -e empty -x \ + "atf-version | head -n 1 | cut -d ' ' -f 4" + ver1=$(cat stdout) + echo "Version reported by atf-version: ${ver1}" + + atf_check -s eq:0 -o save:stdout -e empty pkg-config --modversion "${1}" + ver2=$(cat stdout) + echo "Version reported by pkg-config: ${ver2}" + + atf_check_equal ${ver1} ${ver2} +} + +atf_test_case version +version_head() +{ + atf_set "descr" "Checks that the version in atf-c is correct" + atf_set "require.progs" "atf-version pkg-config" +} +version_body() +{ + require_pc "atf-c" + + check_version "atf-c" +} + +atf_test_case build +build_head() +{ + atf_set "descr" "Checks that a test program can be built against" \ + "the C library based on the pkg-config information" + atf_set "require.progs" "pkg-config" +} +build_body() +{ + require_pc "atf-c" + + atf_check -s eq:0 -o save:stdout -e empty pkg-config --variable=cc atf-c + cc=$(cat stdout) + echo "Compiler is: ${cxx}" + atf_require_prog ${cxx} + + cat >tp.c < + +#include + +ATF_TC(tc); +ATF_TC_HEAD(tc, tc) { + atf_tc_set_md_var(tc, "descr", "A test case"); +} +ATF_TC_BODY(tc, tc) { + printf("Running\n"); +} + +ATF_TP_ADD_TCS(tp) { + ATF_TP_ADD_TC(tp, tc); + + return atf_no_error(); +} +EOF + + atf_check -s eq:0 -o save:stdout -e empty pkg-config --cflags atf-c + cflags=$(cat stdout) + echo "CFLAGS are: ${cflags}" + + atf_check -s eq:0 -o save:stdout -e empty \ + pkg-config --libs-only-L --libs-only-other atf-c + ldflags=$(cat stdout) + atf_check -s eq:0 -o save:stdout -e empty pkg-config --libs-only-l atf-c + libs=$(cat stdout) + echo "LDFLAGS are: ${ldflags}" + echo "LIBS are: ${libs}" + + atf_check -s eq:0 -o empty -e empty ${cc} ${cflags} -o tp.o -c tp.c + atf_check -s eq:0 -o empty -e empty ${cc} ${ldflags} -o tp tp.o ${libs} + + libpath= + for f in ${ldflags}; do + case ${f} in + -L*) + dir=$(echo ${f} | sed -e 's,^-L,,') + if [ -z "${libpath}" ]; then + libpath="${dir}" + else + libpath="${libpath}:${dir}" + fi + ;; + *) + ;; + esac + done + + atf_check -s eq:0 -o empty -e empty test -x tp + atf_check -s eq:0 -o match:'Running' -e empty -x \ + "LD_LIBRARY_PATH=${libpath} ./tp tc" +} + +atf_init_test_cases() +{ + atf_add_test_case version + atf_add_test_case build +} + +# vim: syntax=sh:expandtab:shiftwidth=4:softtabstop=4 diff --git a/external/bsd/atf/dist/atf-c/tc.c b/external/bsd/atf/dist/atf-c/tc.c new file mode 100644 index 000000000..cbdd00c4e --- /dev/null +++ b/external/bsd/atf/dist/atf-c/tc.c @@ -0,0 +1,1221 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "atf-c/defs.h" +#include "atf-c/error.h" +#include "atf-c/tc.h" + +#include "detail/env.h" +#include "detail/fs.h" +#include "detail/map.h" +#include "detail/sanity.h" +#include "detail/text.h" + +/* --------------------------------------------------------------------- + * Auxiliary functions. + * --------------------------------------------------------------------- */ + +enum expect_type { + EXPECT_PASS, + EXPECT_FAIL, + EXPECT_EXIT, + EXPECT_SIGNAL, + EXPECT_DEATH, + EXPECT_TIMEOUT, +}; + +struct context { + const atf_tc_t *tc; + const char *resfile; + size_t fail_count; + + enum expect_type expect; + atf_dynstr_t expect_reason; + size_t expect_previous_fail_count; + size_t expect_fail_count; + int expect_exitcode; + int expect_signo; +}; + +static void context_init(struct context *, const atf_tc_t *, const char *); +static void check_fatal_error(atf_error_t); +static void report_fatal_error(const char *, ...) + ATF_DEFS_ATTRIBUTE_NORETURN; +static atf_error_t write_resfile(const int, const char *, const int, + const atf_dynstr_t *); +static void create_resfile(const char *, const char *, const int, + atf_dynstr_t *); +static void error_in_expect(struct context *, const char *, ...) + ATF_DEFS_ATTRIBUTE_NORETURN; +static void validate_expect(struct context *); +static void expected_failure(struct context *, atf_dynstr_t *) + ATF_DEFS_ATTRIBUTE_NORETURN; +static void fail_requirement(struct context *, atf_dynstr_t *) + ATF_DEFS_ATTRIBUTE_NORETURN; +static void fail_check(struct context *, atf_dynstr_t *); +static void pass(struct context *) + ATF_DEFS_ATTRIBUTE_NORETURN; +static void skip(struct context *, atf_dynstr_t *) + ATF_DEFS_ATTRIBUTE_NORETURN; +static void format_reason_ap(atf_dynstr_t *, const char *, const size_t, + const char *, va_list); +static void format_reason_fmt(atf_dynstr_t *, const char *, const size_t, + const char *, ...); +static void errno_test(struct context *, const char *, const size_t, + const int, const char *, const bool, + void (*)(struct context *, atf_dynstr_t *)); +static atf_error_t check_prog_in_dir(const char *, void *); +static atf_error_t check_prog(struct context *, const char *); + +static void +context_init(struct context *ctx, const atf_tc_t *tc, const char *resfile) +{ + ctx->tc = tc; + ctx->resfile = resfile; + ctx->fail_count = 0; + ctx->expect = EXPECT_PASS; + check_fatal_error(atf_dynstr_init(&ctx->expect_reason)); + ctx->expect_previous_fail_count = 0; + ctx->expect_fail_count = 0; + ctx->expect_exitcode = 0; + ctx->expect_signo = 0; +} + +static void +check_fatal_error(atf_error_t err) +{ + if (atf_is_error(err)) { + char buf[1024]; + atf_error_format(err, buf, sizeof(buf)); + fprintf(stderr, "FATAL ERROR: %s\n", buf); + atf_error_free(err); + abort(); + } +} + +static void +report_fatal_error(const char *msg, ...) +{ + va_list ap; + fprintf(stderr, "FATAL ERROR: "); + + va_start(ap, msg); + vfprintf(stderr, msg, ap); + va_end(ap); + + fprintf(stderr, "\n"); + abort(); +} + +/** Writes to a results file. + * + * The results file is supposed to be already open. + * + * This function returns an error code instead of exiting in case of error + * because the caller needs to clean up the reason object before terminating. + */ +static atf_error_t +write_resfile(const int fd, const char *result, const int arg, + const atf_dynstr_t *reason) +{ + static char NL[] = "\n", CS[] = ": "; + char buf[64]; + const char *r; + struct iovec iov[5]; + ssize_t ret; + int count = 0; + + INV(arg == -1 || reason != NULL); + +#define UNCONST(a) ((void *)(unsigned long)(const void *)(a)) + iov[count].iov_base = UNCONST(result); + iov[count++].iov_len = strlen(result); + + if (reason != NULL) { + if (arg != -1) { + iov[count].iov_base = buf; + iov[count++].iov_len = snprintf(buf, sizeof(buf), "(%d)", arg); + } + + iov[count].iov_base = CS; + iov[count++].iov_len = sizeof(CS) - 1; + + r = atf_dynstr_cstring(reason); + iov[count].iov_base = UNCONST(r); + iov[count++].iov_len = strlen(r); + } +#undef UNCONST + + iov[count].iov_base = NL; + iov[count++].iov_len = sizeof(NL) - 1; + + while ((ret = writev(fd, iov, count)) == -1 && errno == EINTR) + continue; /* Retry. */ + if (ret != -1) + return atf_no_error(); + + return atf_libc_error( + errno, "Failed to write results file; result %s, reason %s", result, + reason == NULL ? "null" : atf_dynstr_cstring(reason)); +} + +/** Creates a results file. + * + * The input reason is released in all cases. + * + * An error in this function is considered to be fatal, hence why it does + * not return any error code. + */ +static void +create_resfile(const char *resfile, const char *result, const int arg, + atf_dynstr_t *reason) +{ + atf_error_t err; + + if (strcmp("/dev/stdout", resfile) == 0) { + err = write_resfile(STDOUT_FILENO, result, arg, reason); + } else if (strcmp("/dev/stderr", resfile) == 0) { + err = write_resfile(STDERR_FILENO, result, arg, reason); + } else { + const int fd = open(resfile, O_WRONLY | O_CREAT | O_TRUNC, + S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + if (fd == -1) { + err = atf_libc_error(errno, "Cannot create results file '%s'", + resfile); + } else { + err = write_resfile(fd, result, arg, reason); + close(fd); + } + } + + if (reason != NULL) + atf_dynstr_fini(reason); + + check_fatal_error(err); +} + +/** Fails a test case if validate_expect fails. */ +static void +error_in_expect(struct context *ctx, const char *fmt, ...) +{ + atf_dynstr_t reason; + va_list ap; + + va_start(ap, fmt); + format_reason_ap(&reason, NULL, 0, fmt, ap); + va_end(ap); + + ctx->expect = EXPECT_PASS; /* Ensure fail_requirement really fails. */ + fail_requirement(ctx, &reason); +} + +/** Ensures that the "expect" state is correct. + * + * Call this function before modifying the current value of expect. + */ +static void +validate_expect(struct context *ctx) +{ + if (ctx->expect == EXPECT_DEATH) { + error_in_expect(ctx, "Test case was expected to terminate abruptly " + "but it continued execution"); + } else if (ctx->expect == EXPECT_EXIT) { + error_in_expect(ctx, "Test case was expected to exit cleanly but it " + "continued execution"); + } else if (ctx->expect == EXPECT_FAIL) { + if (ctx->expect_fail_count == ctx->expect_previous_fail_count) + error_in_expect(ctx, "Test case was expecting a failure but none " + "were raised"); + else + INV(ctx->expect_fail_count > ctx->expect_previous_fail_count); + } else if (ctx->expect == EXPECT_PASS) { + /* Nothing to validate. */ + } else if (ctx->expect == EXPECT_SIGNAL) { + error_in_expect(ctx, "Test case was expected to receive a termination " + "signal but it continued execution"); + } else if (ctx->expect == EXPECT_TIMEOUT) { + error_in_expect(ctx, "Test case was expected to hang but it continued " + "execution"); + } else + UNREACHABLE; +} + +static void +expected_failure(struct context *ctx, atf_dynstr_t *reason) +{ + check_fatal_error(atf_dynstr_prepend_fmt(reason, "%s: ", + atf_dynstr_cstring(&ctx->expect_reason))); + create_resfile(ctx->resfile, "expected_failure", -1, reason); + exit(EXIT_SUCCESS); +} + +static void +fail_requirement(struct context *ctx, atf_dynstr_t *reason) +{ + if (ctx->expect == EXPECT_FAIL) { + expected_failure(ctx, reason); + } else if (ctx->expect == EXPECT_PASS) { + create_resfile(ctx->resfile, "failed", -1, reason); + exit(EXIT_FAILURE); + } else { + error_in_expect(ctx, "Test case raised a failure but was not " + "expecting one; reason was %s", atf_dynstr_cstring(reason)); + } + UNREACHABLE; +} + +static void +fail_check(struct context *ctx, atf_dynstr_t *reason) +{ + if (ctx->expect == EXPECT_FAIL) { + fprintf(stderr, "*** Expected check failure: %s: %s\n", + atf_dynstr_cstring(&ctx->expect_reason), + atf_dynstr_cstring(reason)); + ctx->expect_fail_count++; + } else if (ctx->expect == EXPECT_PASS) { + fprintf(stderr, "*** Check failed: %s\n", atf_dynstr_cstring(reason)); + ctx->fail_count++; + } else { + error_in_expect(ctx, "Test case raised a failure but was not " + "expecting one; reason was %s", atf_dynstr_cstring(reason)); + } + + atf_dynstr_fini(reason); +} + +static void +pass(struct context *ctx) +{ + if (ctx->expect == EXPECT_FAIL) { + error_in_expect(ctx, "Test case was expecting a failure but got " + "a pass instead"); + } else if (ctx->expect == EXPECT_PASS) { + create_resfile(ctx->resfile, "passed", -1, NULL); + exit(EXIT_SUCCESS); + } else { + error_in_expect(ctx, "Test case asked to explicitly pass but was " + "not expecting such condition"); + } + UNREACHABLE; +} + +static void +skip(struct context *ctx, atf_dynstr_t *reason) +{ + if (ctx->expect == EXPECT_PASS) { + create_resfile(ctx->resfile, "skipped", -1, reason); + exit(EXIT_SUCCESS); + } else { + error_in_expect(ctx, "Can only skip a test case when running in " + "expect pass mode"); + } + UNREACHABLE; +} + +/** Formats a failure/skip reason message. + * + * The formatted reason is stored in out_reason. out_reason is initialized + * in this function and is supposed to be released by the caller. In general, + * the reason will eventually be fed to create_resfile, which will release + * it. + * + * Errors in this function are fatal. Rationale being: reasons are used to + * create results files; if we can't format the reason correctly, the result + * of the test program will be bogus. So it's better to just exit with a + * fatal error. + */ +static void +format_reason_ap(atf_dynstr_t *out_reason, + const char *source_file, const size_t source_line, + const char *reason, va_list ap) +{ + atf_error_t err; + + if (source_file != NULL) { + err = atf_dynstr_init_fmt(out_reason, "%s:%zd: ", source_file, + source_line); + } else { + PRE(source_line == 0); + err = atf_dynstr_init(out_reason); + } + + if (!atf_is_error(err)) { + va_list ap2; + va_copy(ap2, ap); + err = atf_dynstr_append_ap(out_reason, reason, ap2); + va_end(ap2); + } + + check_fatal_error(err); +} + +static void +format_reason_fmt(atf_dynstr_t *out_reason, + const char *source_file, const size_t source_line, + const char *reason, ...) +{ + va_list ap; + + va_start(ap, reason); + format_reason_ap(out_reason, source_file, source_line, reason, ap); + va_end(ap); +} + +static void +errno_test(struct context *ctx, const char *file, const size_t line, + const int exp_errno, const char *expr_str, + const bool expr_result, + void (*fail_func)(struct context *, atf_dynstr_t *)) +{ + const int actual_errno = errno; + + if (expr_result) { + if (exp_errno != actual_errno) { + atf_dynstr_t reason; + + format_reason_fmt(&reason, file, line, "Expected errno %d, got %d, " + "in %s", exp_errno, actual_errno, expr_str); + fail_func(ctx, &reason); + } + } else { + atf_dynstr_t reason; + + format_reason_fmt(&reason, file, line, "Expected true value in %s", + expr_str); + fail_func(ctx, &reason); + } +} + +struct prog_found_pair { + const char *prog; + bool found; +}; + +static atf_error_t +check_prog_in_dir(const char *dir, void *data) +{ + struct prog_found_pair *pf = data; + atf_error_t err; + + if (pf->found) + err = atf_no_error(); + else { + atf_fs_path_t p; + + err = atf_fs_path_init_fmt(&p, "%s/%s", dir, pf->prog); + if (atf_is_error(err)) + goto out_p; + + err = atf_fs_eaccess(&p, atf_fs_access_x); + if (!atf_is_error(err)) + pf->found = true; + else { + atf_error_free(err); + INV(!pf->found); + err = atf_no_error(); + } + +out_p: + atf_fs_path_fini(&p); + } + + return err; +} + +static atf_error_t +check_prog(struct context *ctx, const char *prog) +{ + atf_error_t err; + atf_fs_path_t p; + + err = atf_fs_path_init_fmt(&p, "%s", prog); + if (atf_is_error(err)) + goto out; + + if (atf_fs_path_is_absolute(&p)) { + err = atf_fs_eaccess(&p, atf_fs_access_x); + if (atf_is_error(err)) { + atf_dynstr_t reason; + + atf_error_free(err); + atf_fs_path_fini(&p); + format_reason_fmt(&reason, NULL, 0, "The required program %s could " + "not be found", prog); + skip(ctx, &reason); + } + } else { + const char *path = atf_env_get("PATH"); + struct prog_found_pair pf; + atf_fs_path_t bp; + + err = atf_fs_path_branch_path(&p, &bp); + if (atf_is_error(err)) + goto out_p; + + if (strcmp(atf_fs_path_cstring(&bp), ".") != 0) { + atf_fs_path_fini(&bp); + atf_fs_path_fini(&p); + + report_fatal_error("Relative paths are not allowed when searching " + "for a program (%s)", prog); + UNREACHABLE; + } + + pf.prog = prog; + pf.found = false; + err = atf_text_for_each_word(path, ":", check_prog_in_dir, &pf); + if (atf_is_error(err)) + goto out_bp; + + if (!pf.found) { + atf_dynstr_t reason; + + atf_fs_path_fini(&bp); + atf_fs_path_fini(&p); + format_reason_fmt(&reason, NULL, 0, "The required program %s could " + "not be found in the PATH", prog); + fail_requirement(ctx, &reason); + } + +out_bp: + atf_fs_path_fini(&bp); + } + +out_p: + atf_fs_path_fini(&p); +out: + return err; +} + +/* --------------------------------------------------------------------- + * The "atf_tc" type. + * --------------------------------------------------------------------- */ + +struct atf_tc_impl { + const char *m_ident; + + atf_map_t m_vars; + atf_map_t m_config; + + atf_tc_head_t m_head; + atf_tc_body_t m_body; + atf_tc_cleanup_t m_cleanup; +}; + +/* + * Constructors/destructors. + */ + +atf_error_t +atf_tc_init(atf_tc_t *tc, const char *ident, atf_tc_head_t head, + atf_tc_body_t body, atf_tc_cleanup_t cleanup, + const char *const *config) +{ + atf_error_t err; + + tc->pimpl = malloc(sizeof(struct atf_tc_impl)); + if (tc->pimpl == NULL) { + err = atf_no_memory_error(); + goto err; + } + + tc->pimpl->m_ident = ident; + tc->pimpl->m_head = head; + tc->pimpl->m_body = body; + tc->pimpl->m_cleanup = cleanup; + + err = atf_map_init_charpp(&tc->pimpl->m_config, config); + if (atf_is_error(err)) + goto err; + + err = atf_map_init(&tc->pimpl->m_vars); + if (atf_is_error(err)) + goto err_vars; + + err = atf_tc_set_md_var(tc, "ident", ident); + if (atf_is_error(err)) + goto err_map; + + if (cleanup != NULL) { + err = atf_tc_set_md_var(tc, "has.cleanup", "true"); + if (atf_is_error(err)) + goto err_map; + } + + /* XXX Should the head be able to return error codes? */ + if (tc->pimpl->m_head != NULL) + tc->pimpl->m_head(tc); + + if (strcmp(atf_tc_get_md_var(tc, "ident"), ident) != 0) { + report_fatal_error("Test case head modified the read-only 'ident' " + "property"); + UNREACHABLE; + } + + INV(!atf_is_error(err)); + return err; + +err_map: + atf_map_fini(&tc->pimpl->m_vars); +err_vars: + atf_map_fini(&tc->pimpl->m_config); +err: + return err; +} + +atf_error_t +atf_tc_init_pack(atf_tc_t *tc, const atf_tc_pack_t *pack, + const char *const *config) +{ + return atf_tc_init(tc, pack->m_ident, pack->m_head, pack->m_body, + pack->m_cleanup, config); +} + +void +atf_tc_fini(atf_tc_t *tc) +{ + atf_map_fini(&tc->pimpl->m_vars); + free(tc->pimpl); +} + +/* + * Getters. + */ + +const char * +atf_tc_get_ident(const atf_tc_t *tc) +{ + return tc->pimpl->m_ident; +} + +const char * +atf_tc_get_config_var(const atf_tc_t *tc, const char *name) +{ + const char *val; + atf_map_citer_t iter; + + PRE(atf_tc_has_config_var(tc, name)); + iter = atf_map_find_c(&tc->pimpl->m_config, name); + val = atf_map_citer_data(iter); + INV(val != NULL); + + return val; +} + +const char * +atf_tc_get_config_var_wd(const atf_tc_t *tc, const char *name, + const char *defval) +{ + const char *val; + + if (!atf_tc_has_config_var(tc, name)) + val = defval; + else + val = atf_tc_get_config_var(tc, name); + + return val; +} + +bool +atf_tc_get_config_var_as_bool(const atf_tc_t *tc, const char *name) +{ + bool val; + const char *strval; + atf_error_t err; + + strval = atf_tc_get_config_var(tc, name); + err = atf_text_to_bool(strval, &val); + if (atf_is_error(err)) { + atf_error_free(err); + atf_tc_fail("Configuration variable %s does not have a valid " + "boolean value; found %s", name, strval); + } + + return val; +} + +bool +atf_tc_get_config_var_as_bool_wd(const atf_tc_t *tc, const char *name, + const bool defval) +{ + bool val; + + if (!atf_tc_has_config_var(tc, name)) + val = defval; + else + val = atf_tc_get_config_var_as_bool(tc, name); + + return val; +} + +long +atf_tc_get_config_var_as_long(const atf_tc_t *tc, const char *name) +{ + long val; + const char *strval; + atf_error_t err; + + strval = atf_tc_get_config_var(tc, name); + err = atf_text_to_long(strval, &val); + if (atf_is_error(err)) { + atf_error_free(err); + atf_tc_fail("Configuration variable %s does not have a valid " + "long value; found %s", name, strval); + } + + return val; +} + +long +atf_tc_get_config_var_as_long_wd(const atf_tc_t *tc, const char *name, + const long defval) +{ + long val; + + if (!atf_tc_has_config_var(tc, name)) + val = defval; + else + val = atf_tc_get_config_var_as_long(tc, name); + + return val; +} + +const char * +atf_tc_get_md_var(const atf_tc_t *tc, const char *name) +{ + const char *val; + atf_map_citer_t iter; + + PRE(atf_tc_has_md_var(tc, name)); + iter = atf_map_find_c(&tc->pimpl->m_vars, name); + val = atf_map_citer_data(iter); + INV(val != NULL); + + return val; +} + +char ** +atf_tc_get_md_vars(const atf_tc_t *tc) +{ + return atf_map_to_charpp(&tc->pimpl->m_vars); +} + +bool +atf_tc_has_config_var(const atf_tc_t *tc, const char *name) +{ + atf_map_citer_t end, iter; + + iter = atf_map_find_c(&tc->pimpl->m_config, name); + end = atf_map_end_c(&tc->pimpl->m_config); + return !atf_equal_map_citer_map_citer(iter, end); +} + +bool +atf_tc_has_md_var(const atf_tc_t *tc, const char *name) +{ + atf_map_citer_t end, iter; + + iter = atf_map_find_c(&tc->pimpl->m_vars, name); + end = atf_map_end_c(&tc->pimpl->m_vars); + return !atf_equal_map_citer_map_citer(iter, end); +} + +/* + * Modifiers. + */ + +atf_error_t +atf_tc_set_md_var(atf_tc_t *tc, const char *name, const char *fmt, ...) +{ + atf_error_t err; + char *value; + va_list ap; + + va_start(ap, fmt); + err = atf_text_format_ap(&value, fmt, ap); + va_end(ap); + + if (!atf_is_error(err)) + err = atf_map_insert(&tc->pimpl->m_vars, name, value, true); + else + free(value); + + return err; +} + +/* --------------------------------------------------------------------- + * Free functions, as they should be publicly but they can't. + * --------------------------------------------------------------------- */ + +static void _atf_tc_fail(struct context *, const char *, va_list) + ATF_DEFS_ATTRIBUTE_NORETURN; +static void _atf_tc_fail_nonfatal(struct context *, const char *, va_list); +static void _atf_tc_fail_check(struct context *, const char *, const size_t, + const char *, va_list); +static void _atf_tc_fail_requirement(struct context *, const char *, + const size_t, const char *, va_list) ATF_DEFS_ATTRIBUTE_NORETURN; +static void _atf_tc_pass(struct context *) ATF_DEFS_ATTRIBUTE_NORETURN; +static void _atf_tc_require_prog(struct context *, const char *); +static void _atf_tc_skip(struct context *, const char *, va_list) + ATF_DEFS_ATTRIBUTE_NORETURN; +static void _atf_tc_check_errno(struct context *, const char *, const size_t, + const int, const char *, const bool); +static void _atf_tc_require_errno(struct context *, const char *, const size_t, + const int, const char *, const bool); +static void _atf_tc_expect_pass(struct context *); +static void _atf_tc_expect_fail(struct context *, const char *, va_list); +static void _atf_tc_expect_exit(struct context *, const int, const char *, + va_list); +static void _atf_tc_expect_signal(struct context *, const int, const char *, + va_list); +static void _atf_tc_expect_death(struct context *, const char *, + va_list); + +static void +_atf_tc_fail(struct context *ctx, const char *fmt, va_list ap) +{ + va_list ap2; + atf_dynstr_t reason; + + va_copy(ap2, ap); + format_reason_ap(&reason, NULL, 0, fmt, ap2); + va_end(ap2); + + fail_requirement(ctx, &reason); + UNREACHABLE; +} + +static void +_atf_tc_fail_nonfatal(struct context *ctx, const char *fmt, va_list ap) +{ + va_list ap2; + atf_dynstr_t reason; + + va_copy(ap2, ap); + format_reason_ap(&reason, NULL, 0, fmt, ap2); + va_end(ap2); + + fail_check(ctx, &reason); +} + +static void +_atf_tc_fail_check(struct context *ctx, const char *file, const size_t line, + const char *fmt, va_list ap) +{ + va_list ap2; + atf_dynstr_t reason; + + va_copy(ap2, ap); + format_reason_ap(&reason, file, line, fmt, ap2); + va_end(ap2); + + fail_check(ctx, &reason); +} + +static void +_atf_tc_fail_requirement(struct context *ctx, const char *file, + const size_t line, const char *fmt, va_list ap) +{ + va_list ap2; + atf_dynstr_t reason; + + va_copy(ap2, ap); + format_reason_ap(&reason, file, line, fmt, ap2); + va_end(ap2); + + fail_requirement(ctx, &reason); + UNREACHABLE; +} + +static void +_atf_tc_pass(struct context *ctx) +{ + pass(ctx); + UNREACHABLE; +} + +static void +_atf_tc_require_prog(struct context *ctx, const char *prog) +{ + check_fatal_error(check_prog(ctx, prog)); +} + +static void +_atf_tc_skip(struct context *ctx, const char *fmt, va_list ap) +{ + atf_dynstr_t reason; + va_list ap2; + + va_copy(ap2, ap); + format_reason_ap(&reason, NULL, 0, fmt, ap2); + va_end(ap2); + + skip(ctx, &reason); +} + +static void +_atf_tc_check_errno(struct context *ctx, const char *file, const size_t line, + const int exp_errno, const char *expr_str, + const bool expr_result) +{ + errno_test(ctx, file, line, exp_errno, expr_str, expr_result, fail_check); +} + +static void +_atf_tc_require_errno(struct context *ctx, const char *file, const size_t line, + const int exp_errno, const char *expr_str, + const bool expr_result) +{ + errno_test(ctx, file, line, exp_errno, expr_str, expr_result, + fail_requirement); +} + +static void +_atf_tc_expect_pass(struct context *ctx) +{ + validate_expect(ctx); + + ctx->expect = EXPECT_PASS; +} + +static void +_atf_tc_expect_fail(struct context *ctx, const char *reason, va_list ap) +{ + va_list ap2; + + validate_expect(ctx); + + ctx->expect = EXPECT_FAIL; + atf_dynstr_fini(&ctx->expect_reason); + va_copy(ap2, ap); + check_fatal_error(atf_dynstr_init_ap(&ctx->expect_reason, reason, ap2)); + va_end(ap2); + ctx->expect_previous_fail_count = ctx->expect_fail_count; +} + +static void +_atf_tc_expect_exit(struct context *ctx, const int exitcode, const char *reason, + va_list ap) +{ + va_list ap2; + atf_dynstr_t formatted; + + validate_expect(ctx); + + ctx->expect = EXPECT_EXIT; + va_copy(ap2, ap); + check_fatal_error(atf_dynstr_init_ap(&formatted, reason, ap2)); + va_end(ap2); + + create_resfile(ctx->resfile, "expected_exit", exitcode, &formatted); +} + +static void +_atf_tc_expect_signal(struct context *ctx, const int signo, const char *reason, + va_list ap) +{ + va_list ap2; + atf_dynstr_t formatted; + + validate_expect(ctx); + + ctx->expect = EXPECT_SIGNAL; + va_copy(ap2, ap); + check_fatal_error(atf_dynstr_init_ap(&formatted, reason, ap2)); + va_end(ap2); + + create_resfile(ctx->resfile, "expected_signal", signo, &formatted); +} + +static void +_atf_tc_expect_death(struct context *ctx, const char *reason, va_list ap) +{ + va_list ap2; + atf_dynstr_t formatted; + + validate_expect(ctx); + + ctx->expect = EXPECT_DEATH; + va_copy(ap2, ap); + check_fatal_error(atf_dynstr_init_ap(&formatted, reason, ap2)); + va_end(ap2); + + create_resfile(ctx->resfile, "expected_death", -1, &formatted); +} + +static void +_atf_tc_expect_timeout(struct context *ctx, const char *reason, va_list ap) +{ + va_list ap2; + atf_dynstr_t formatted; + + validate_expect(ctx); + + ctx->expect = EXPECT_TIMEOUT; + va_copy(ap2, ap); + check_fatal_error(atf_dynstr_init_ap(&formatted, reason, ap2)); + va_end(ap2); + + create_resfile(ctx->resfile, "expected_timeout", -1, &formatted); +} + +/* --------------------------------------------------------------------- + * Free functions. + * --------------------------------------------------------------------- */ + +static struct context Current; + +atf_error_t +atf_tc_run(const atf_tc_t *tc, const char *resfile) +{ + context_init(&Current, tc, resfile); + + tc->pimpl->m_body(tc); + + validate_expect(&Current); + + if (Current.fail_count > 0) { + atf_dynstr_t reason; + + format_reason_fmt(&reason, NULL, 0, "%d checks failed; see output for " + "more details", Current.fail_count); + fail_requirement(&Current, &reason); + } else if (Current.expect_fail_count > 0) { + atf_dynstr_t reason; + + format_reason_fmt(&reason, NULL, 0, "%d checks failed as expected; " + "see output for more details", Current.expect_fail_count); + expected_failure(&Current, &reason); + } else { + pass(&Current); + } + UNREACHABLE; + return atf_no_error(); +} + +atf_error_t +atf_tc_cleanup(const atf_tc_t *tc) +{ + if (tc->pimpl->m_cleanup != NULL) + tc->pimpl->m_cleanup(tc); + return atf_no_error(); /* XXX */ +} + +/* --------------------------------------------------------------------- + * Free functions that depend on Current. + * --------------------------------------------------------------------- */ + +/* + * All the functions below provide delegates to other internal functions + * (prefixed by _) that take the current test case as an argument to + * prevent them from accessing global state. This is to keep the side- + * effects of the internal functions clearer and easier to understand. + * + * The public API should never have hid the fact that it needs access to + * the current test case (other than maybe in the macros), but changing it + * is hard. TODO: Revisit in the future. + */ + +void +atf_tc_fail(const char *fmt, ...) +{ + va_list ap; + + PRE(Current.tc != NULL); + + va_start(ap, fmt); + _atf_tc_fail(&Current, fmt, ap); + va_end(ap); +} + +void +atf_tc_fail_nonfatal(const char *fmt, ...) +{ + va_list ap; + + PRE(Current.tc != NULL); + + va_start(ap, fmt); + _atf_tc_fail_nonfatal(&Current, fmt, ap); + va_end(ap); +} + +void +atf_tc_fail_check(const char *file, const size_t line, const char *fmt, ...) +{ + va_list ap; + + PRE(Current.tc != NULL); + + va_start(ap, fmt); + _atf_tc_fail_check(&Current, file, line, fmt, ap); + va_end(ap); +} + +void +atf_tc_fail_requirement(const char *file, const size_t line, + const char *fmt, ...) +{ + va_list ap; + + PRE(Current.tc != NULL); + + va_start(ap, fmt); + _atf_tc_fail_requirement(&Current, file, line, fmt, ap); + va_end(ap); +} + +void +atf_tc_pass(void) +{ + PRE(Current.tc != NULL); + + _atf_tc_pass(&Current); +} + +void +atf_tc_require_prog(const char *prog) +{ + PRE(Current.tc != NULL); + + _atf_tc_require_prog(&Current, prog); +} + +void +atf_tc_skip(const char *fmt, ...) +{ + va_list ap; + + PRE(Current.tc != NULL); + + va_start(ap, fmt); + _atf_tc_skip(&Current, fmt, ap); + va_end(ap); +} + +void +atf_tc_check_errno(const char *file, const size_t line, const int exp_errno, + const char *expr_str, const bool expr_result) +{ + PRE(Current.tc != NULL); + + _atf_tc_check_errno(&Current, file, line, exp_errno, expr_str, + expr_result); +} + +void +atf_tc_require_errno(const char *file, const size_t line, const int exp_errno, + const char *expr_str, const bool expr_result) +{ + PRE(Current.tc != NULL); + + _atf_tc_require_errno(&Current, file, line, exp_errno, expr_str, + expr_result); +} + +void +atf_tc_expect_pass(void) +{ + PRE(Current.tc != NULL); + + _atf_tc_expect_pass(&Current); +} + +void +atf_tc_expect_fail(const char *reason, ...) +{ + va_list ap; + + PRE(Current.tc != NULL); + + va_start(ap, reason); + _atf_tc_expect_fail(&Current, reason, ap); + va_end(ap); +} + +void +atf_tc_expect_exit(const int exitcode, const char *reason, ...) +{ + va_list ap; + + PRE(Current.tc != NULL); + + va_start(ap, reason); + _atf_tc_expect_exit(&Current, exitcode, reason, ap); + va_end(ap); +} + +void +atf_tc_expect_signal(const int signo, const char *reason, ...) +{ + va_list ap; + + PRE(Current.tc != NULL); + + va_start(ap, reason); + _atf_tc_expect_signal(&Current, signo, reason, ap); + va_end(ap); +} + +void +atf_tc_expect_death(const char *reason, ...) +{ + va_list ap; + + PRE(Current.tc != NULL); + + va_start(ap, reason); + _atf_tc_expect_death(&Current, reason, ap); + va_end(ap); +} + +void +atf_tc_expect_timeout(const char *reason, ...) +{ + va_list ap; + + PRE(Current.tc != NULL); + + va_start(ap, reason); + _atf_tc_expect_timeout(&Current, reason, ap); + va_end(ap); +} diff --git a/external/bsd/atf/dist/atf-c/tc.h b/external/bsd/atf/dist/atf-c/tc.h new file mode 100644 index 000000000..3f24186b0 --- /dev/null +++ b/external/bsd/atf/dist/atf-c/tc.h @@ -0,0 +1,140 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if !defined(ATF_C_TC_H) +#define ATF_C_TC_H + +#include +#include + +#include +#include + +struct atf_tc; + +typedef void (*atf_tc_head_t)(struct atf_tc *); +typedef void (*atf_tc_body_t)(const struct atf_tc *); +typedef void (*atf_tc_cleanup_t)(const struct atf_tc *); + +/* --------------------------------------------------------------------- + * The "atf_tc_pack" type. + * --------------------------------------------------------------------- */ + +/* For static initialization only. */ +struct atf_tc_pack { + const char *m_ident; + + const char *const *m_config; + + atf_tc_head_t m_head; + atf_tc_body_t m_body; + atf_tc_cleanup_t m_cleanup; +}; +typedef const struct atf_tc_pack atf_tc_pack_t; + +/* --------------------------------------------------------------------- + * The "atf_tc" type. + * --------------------------------------------------------------------- */ + +struct atf_tc_impl; +struct atf_tc { + struct atf_tc_impl *pimpl; +}; +typedef struct atf_tc atf_tc_t; + +/* Constructors/destructors. */ +atf_error_t atf_tc_init(atf_tc_t *, const char *, atf_tc_head_t, + atf_tc_body_t, atf_tc_cleanup_t, + const char *const *); +atf_error_t atf_tc_init_pack(atf_tc_t *, atf_tc_pack_t *, + const char *const *); +void atf_tc_fini(atf_tc_t *); + +/* Getters. */ +const char *atf_tc_get_ident(const atf_tc_t *); +const char *atf_tc_get_config_var(const atf_tc_t *, const char *); +const char *atf_tc_get_config_var_wd(const atf_tc_t *, const char *, + const char *); +bool atf_tc_get_config_var_as_bool(const atf_tc_t *, const char *); +bool atf_tc_get_config_var_as_bool_wd(const atf_tc_t *, const char *, + const bool); +long atf_tc_get_config_var_as_long(const atf_tc_t *, const char *); +long atf_tc_get_config_var_as_long_wd(const atf_tc_t *, const char *, + const long); +const char *atf_tc_get_md_var(const atf_tc_t *, const char *); +char **atf_tc_get_md_vars(const atf_tc_t *); +bool atf_tc_has_config_var(const atf_tc_t *, const char *); +bool atf_tc_has_md_var(const atf_tc_t *, const char *); + +/* Modifiers. */ +atf_error_t atf_tc_set_md_var(atf_tc_t *, const char *, const char *, ...); + +/* --------------------------------------------------------------------- + * Free functions. + * --------------------------------------------------------------------- */ + +atf_error_t atf_tc_run(const atf_tc_t *, const char *); +atf_error_t atf_tc_cleanup(const atf_tc_t *); + +/* To be run from test case bodies only. */ +void atf_tc_fail(const char *, ...) + ATF_DEFS_ATTRIBUTE_FORMAT_PRINTF(1, 2) + ATF_DEFS_ATTRIBUTE_NORETURN; +void atf_tc_fail_nonfatal(const char *, ...) + ATF_DEFS_ATTRIBUTE_FORMAT_PRINTF(1, 2); +void atf_tc_pass(void) + ATF_DEFS_ATTRIBUTE_NORETURN; +void atf_tc_require_prog(const char *); +void atf_tc_skip(const char *, ...) + ATF_DEFS_ATTRIBUTE_FORMAT_PRINTF(1, 2) + ATF_DEFS_ATTRIBUTE_NORETURN; +void atf_tc_expect_pass(void); +void atf_tc_expect_fail(const char *, ...) + ATF_DEFS_ATTRIBUTE_FORMAT_PRINTF(1, 2); +void atf_tc_expect_exit(const int, const char *, ...) + ATF_DEFS_ATTRIBUTE_FORMAT_PRINTF(2, 3); +void atf_tc_expect_signal(const int, const char *, ...) + ATF_DEFS_ATTRIBUTE_FORMAT_PRINTF(2, 3); +void atf_tc_expect_death(const char *, ...) + ATF_DEFS_ATTRIBUTE_FORMAT_PRINTF(1, 2); +void atf_tc_expect_timeout(const char *, ...) + ATF_DEFS_ATTRIBUTE_FORMAT_PRINTF(1, 2); + +/* To be run from test case bodies only; internal to macros.h. */ +void atf_tc_fail_check(const char *, const size_t, const char *, ...) + ATF_DEFS_ATTRIBUTE_FORMAT_PRINTF(3, 4); +void atf_tc_fail_requirement(const char *, const size_t, const char *, ...) + ATF_DEFS_ATTRIBUTE_FORMAT_PRINTF(3, 4) + ATF_DEFS_ATTRIBUTE_NORETURN; +void atf_tc_check_errno(const char *, const size_t, const int, + const char *, const bool); +void atf_tc_require_errno(const char *, const size_t, const int, + const char *, const bool); + +#endif /* ATF_C_TC_H */ diff --git a/external/bsd/atf/dist/atf-c/tc_test.c b/external/bsd/atf/dist/atf-c/tc_test.c new file mode 100644 index 000000000..4aaf9a54c --- /dev/null +++ b/external/bsd/atf/dist/atf-c/tc_test.c @@ -0,0 +1,194 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include + +#include "detail/test_helpers.h" + +/* --------------------------------------------------------------------- + * Auxiliary test cases. + * --------------------------------------------------------------------- */ + +ATF_TC_HEAD(empty, tc) +{ + if (tc != NULL) {} +} +ATF_TC_BODY(empty, tc) +{ +} + +ATF_TC_HEAD(test_var, tc) +{ + atf_tc_set_md_var(tc, "test-var", "Test text"); +} + +/* --------------------------------------------------------------------- + * Test cases for the "atf_tc_t" type. + * --------------------------------------------------------------------- */ + +ATF_TC(init); +ATF_TC_HEAD(init, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the atf_tc_init function"); +} +ATF_TC_BODY(init, tcin) +{ + atf_tc_t tc; + + RE(atf_tc_init(&tc, "test1", ATF_TC_HEAD_NAME(empty), + ATF_TC_BODY_NAME(empty), NULL, NULL)); + ATF_REQUIRE(strcmp(atf_tc_get_ident(&tc), "test1") == 0); + ATF_REQUIRE(!atf_tc_has_md_var(&tc, "test-var")); + atf_tc_fini(&tc); + + RE(atf_tc_init(&tc, "test2", ATF_TC_HEAD_NAME(test_var), + ATF_TC_BODY_NAME(empty), NULL, NULL)); + ATF_REQUIRE(strcmp(atf_tc_get_ident(&tc), "test2") == 0); + ATF_REQUIRE(atf_tc_has_md_var(&tc, "test-var")); + atf_tc_fini(&tc); +} + +ATF_TC(init_pack); +ATF_TC_HEAD(init_pack, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the atf_tc_init_pack function"); +} +ATF_TC_BODY(init_pack, tcin) +{ + atf_tc_t tc; + atf_tc_pack_t tcp1 = { + .m_ident = "test1", + .m_head = ATF_TC_HEAD_NAME(empty), + .m_body = ATF_TC_BODY_NAME(empty), + .m_cleanup = NULL, + }; + atf_tc_pack_t tcp2 = { + .m_ident = "test2", + .m_head = ATF_TC_HEAD_NAME(test_var), + .m_body = ATF_TC_BODY_NAME(empty), + .m_cleanup = NULL, + }; + + RE(atf_tc_init_pack(&tc, &tcp1, NULL)); + ATF_REQUIRE(strcmp(atf_tc_get_ident(&tc), "test1") == 0); + ATF_REQUIRE(!atf_tc_has_md_var(&tc, "test-var")); + atf_tc_fini(&tc); + + RE(atf_tc_init_pack(&tc, &tcp2, NULL)); + ATF_REQUIRE(strcmp(atf_tc_get_ident(&tc), "test2") == 0); + ATF_REQUIRE(atf_tc_has_md_var(&tc, "test-var")); + atf_tc_fini(&tc); +} + +ATF_TC(vars); +ATF_TC_HEAD(vars, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the atf_tc_get_md_var, " + "atf_tc_has_md_var and atf_tc_set_md_var functions"); +} +ATF_TC_BODY(vars, tcin) +{ + atf_tc_t tc; + + RE(atf_tc_init(&tc, "test1", ATF_TC_HEAD_NAME(empty), + ATF_TC_BODY_NAME(empty), NULL, NULL)); + ATF_REQUIRE(!atf_tc_has_md_var(&tc, "test-var")); + RE(atf_tc_set_md_var(&tc, "test-var", "Test value")); + ATF_REQUIRE(atf_tc_has_md_var(&tc, "test-var")); + ATF_REQUIRE(strcmp(atf_tc_get_md_var(&tc, "test-var"), "Test value") == 0); + atf_tc_fini(&tc); +} + +ATF_TC(config); +ATF_TC_HEAD(config, tc) +{ + atf_tc_set_md_var(tc, "descr", "Tests the atf_tc_get_config_var, " + "atf_tc_get_config_var_wd and atf_tc_has_config_var " + "functions"); +} +ATF_TC_BODY(config, tcin) +{ + atf_tc_t tc; + const char *const config[] = { "test-var", "test-value", NULL }; + + RE(atf_tc_init(&tc, "test1", ATF_TC_HEAD_NAME(empty), + ATF_TC_BODY_NAME(empty), NULL, NULL)); + ATF_REQUIRE(!atf_tc_has_config_var(&tc, "test-var")); + ATF_REQUIRE(!atf_tc_has_md_var(&tc, "test-var")); + atf_tc_fini(&tc); + + RE(atf_tc_init(&tc, "test1", ATF_TC_HEAD_NAME(empty), + ATF_TC_BODY_NAME(empty), NULL, config)); + ATF_REQUIRE(atf_tc_has_config_var(&tc, "test-var")); + ATF_REQUIRE(strcmp(atf_tc_get_config_var(&tc, "test-var"), + "test-value") == 0); + ATF_REQUIRE(!atf_tc_has_md_var(&tc, "test-var")); + ATF_REQUIRE(!atf_tc_has_config_var(&tc, "test-var2")); + ATF_REQUIRE(strcmp(atf_tc_get_config_var_wd(&tc, "test-var2", "def-value"), + "def-value") == 0); + atf_tc_fini(&tc); +} + +/* --------------------------------------------------------------------- + * Test cases for the free functions. + * --------------------------------------------------------------------- */ + +/* TODO: Add test cases for atf_tc_run. This is going to be very tough, + * but good tests here could allow us to avoid much of the indirect + * testing done later on. */ + +/* --------------------------------------------------------------------- + * Tests cases for the header file. + * --------------------------------------------------------------------- */ + +HEADER_TC(include, "atf-c/tc.h"); + +/* --------------------------------------------------------------------- + * Main. + * --------------------------------------------------------------------- */ + +ATF_TP_ADD_TCS(tp) +{ + /* Add the test cases for the "atf_tcr_t" type. */ + ATF_TP_ADD_TC(tp, init); + ATF_TP_ADD_TC(tp, init_pack); + ATF_TP_ADD_TC(tp, vars); + ATF_TP_ADD_TC(tp, config); + + /* Add the test cases for the free functions. */ + /* TODO */ + + /* Add the test cases for the header file. */ + ATF_TP_ADD_TC(tp, include); + + return atf_no_error(); +} diff --git a/external/bsd/atf/dist/atf-c/tp.c b/external/bsd/atf/dist/atf-c/tp.c new file mode 100644 index 000000000..7833498ac --- /dev/null +++ b/external/bsd/atf/dist/atf-c/tp.c @@ -0,0 +1,217 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include + +#include "atf-c/error.h" +#include "atf-c/tc.h" +#include "atf-c/tp.h" + +#include "detail/fs.h" +#include "detail/map.h" +#include "detail/sanity.h" + +struct atf_tp_impl { + atf_list_t m_tcs; + atf_map_t m_config; +}; + +/* --------------------------------------------------------------------- + * Auxiliary functions. + * --------------------------------------------------------------------- */ + +static +const atf_tc_t * +find_tc(const atf_tp_t *tp, const char *ident) +{ + const atf_tc_t *tc; + atf_list_citer_t iter; + + tc = NULL; + atf_list_for_each_c(iter, &tp->pimpl->m_tcs) { + const atf_tc_t *tc2; + tc2 = atf_list_citer_data(iter); + if (strcmp(atf_tc_get_ident(tc2), ident) == 0) { + tc = tc2; + break; + } + } + return tc; +} + +/* --------------------------------------------------------------------- + * The "atf_tp" type. + * --------------------------------------------------------------------- */ + +/* + * Constructors/destructors. + */ + +atf_error_t +atf_tp_init(atf_tp_t *tp, const char *const *config) +{ + atf_error_t err; + + PRE(config != NULL); + + tp->pimpl = malloc(sizeof(struct atf_tp_impl)); + if (tp->pimpl == NULL) + return atf_no_memory_error(); + + err = atf_list_init(&tp->pimpl->m_tcs); + if (atf_is_error(err)) + goto out; + + err = atf_map_init_charpp(&tp->pimpl->m_config, config); + if (atf_is_error(err)) { + atf_list_fini(&tp->pimpl->m_tcs); + goto out; + } + + INV(!atf_is_error(err)); +out: + return err; +} + +void +atf_tp_fini(atf_tp_t *tp) +{ + atf_list_iter_t iter; + + atf_map_fini(&tp->pimpl->m_config); + + atf_list_for_each(iter, &tp->pimpl->m_tcs) { + atf_tc_t *tc = atf_list_iter_data(iter); + atf_tc_fini(tc); + } + atf_list_fini(&tp->pimpl->m_tcs); + + free(tp->pimpl); +} + +/* + * Getters. + */ + +char ** +atf_tp_get_config(const atf_tp_t *tp) +{ + return atf_map_to_charpp(&tp->pimpl->m_config); +} + +bool +atf_tp_has_tc(const atf_tp_t *tp, const char *id) +{ + const atf_tc_t *tc = find_tc(tp, id); + return tc != NULL; +} + +const atf_tc_t * +atf_tp_get_tc(const atf_tp_t *tp, const char *id) +{ + const atf_tc_t *tc = find_tc(tp, id); + PRE(tc != NULL); + return tc; +} + +const atf_tc_t *const * +atf_tp_get_tcs(const atf_tp_t *tp) +{ + const atf_tc_t **array; + atf_list_citer_t iter; + size_t i; + + array = malloc(sizeof(atf_tc_t *) * + (atf_list_size(&tp->pimpl->m_tcs) + 1)); + if (array == NULL) + goto out; + + i = 0; + atf_list_for_each_c(iter, &tp->pimpl->m_tcs) { + array[i] = atf_list_citer_data(iter); + if (array[i] == NULL) { + free(array); + array = NULL; + goto out; + } + + i++; + } + array[i] = NULL; + +out: + return array; +} + +/* + * Modifiers. + */ + +atf_error_t +atf_tp_add_tc(atf_tp_t *tp, atf_tc_t *tc) +{ + atf_error_t err; + + PRE(find_tc(tp, atf_tc_get_ident(tc)) == NULL); + + err = atf_list_append(&tp->pimpl->m_tcs, tc, false); + + POST(find_tc(tp, atf_tc_get_ident(tc)) != NULL); + + return err; +} + +/* --------------------------------------------------------------------- + * Free functions. + * --------------------------------------------------------------------- */ + +atf_error_t +atf_tp_run(const atf_tp_t *tp, const char *tcname, const char *resfile) +{ + const atf_tc_t *tc; + + tc = find_tc(tp, tcname); + PRE(tc != NULL); + + return atf_tc_run(tc, resfile); +} + +atf_error_t +atf_tp_cleanup(const atf_tp_t *tp, const char *tcname) +{ + const atf_tc_t *tc; + + tc = find_tc(tp, tcname); + PRE(tc != NULL); + + return atf_tc_cleanup(tc); +} diff --git a/external/bsd/atf/dist/atf-c/tp.h b/external/bsd/atf/dist/atf-c/tp.h new file mode 100644 index 000000000..e4f9ba46e --- /dev/null +++ b/external/bsd/atf/dist/atf-c/tp.h @@ -0,0 +1,69 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if !defined(ATF_C_TP_H) +#define ATF_C_TP_H + +#include + +#include + +struct atf_tc; + +/* --------------------------------------------------------------------- + * The "atf_tp" type. + * --------------------------------------------------------------------- */ + +struct atf_tp_impl; +struct atf_tp { + struct atf_tp_impl *pimpl; +}; +typedef struct atf_tp atf_tp_t; + +/* Constructors/destructors. */ +atf_error_t atf_tp_init(atf_tp_t *, const char *const *); +void atf_tp_fini(atf_tp_t *); + +/* Getters. */ +char **atf_tp_get_config(const atf_tp_t *); +bool atf_tp_has_tc(const atf_tp_t *, const char *); +const struct atf_tc *atf_tp_get_tc(const atf_tp_t *, const char *); +const struct atf_tc *const *atf_tp_get_tcs(const atf_tp_t *); + +/* Modifiers. */ +atf_error_t atf_tp_add_tc(atf_tp_t *, struct atf_tc *); + +/* --------------------------------------------------------------------- + * Free functions. + * --------------------------------------------------------------------- */ + +atf_error_t atf_tp_run(const atf_tp_t *, const char *, const char *); +atf_error_t atf_tp_cleanup(const atf_tp_t *, const char *); + +#endif /* ATF_C_TP_H */ diff --git a/external/bsd/atf/dist/atf-c/tp_test.c b/external/bsd/atf/dist/atf-c/tp_test.c new file mode 100644 index 000000000..5da18b20b --- /dev/null +++ b/external/bsd/atf/dist/atf-c/tp_test.c @@ -0,0 +1,101 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2010 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include + +#include "detail/test_helpers.h" + +ATF_TC(getopt); +ATF_TC_HEAD(getopt, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks if getopt(3) global state is " + "reset by the test program driver so that test cases can use " + "getopt(3) again"); +} +ATF_TC_BODY(getopt, tc) +{ + /* Provide an option that is unknown to the test program driver and + * one that is, together with an argument that would be swallowed by + * the test program option if it were recognized. */ + int argc = 4; + char arg1[] = "progname"; + char arg2[] = "-Z"; + char arg3[] = "-s"; + char arg4[] = "foo"; + char *const argv[] = { arg1, arg2, arg3, arg4, NULL }; + + int ch; + bool zflag; + + /* Given that this obviously is a test program, and that we used the + * same driver to start, we can test getopt(3) right here without doing + * any fancy stuff. */ + zflag = false; + while ((ch = getopt(argc, argv, ":Z")) != -1) { + switch (ch) { + case 'Z': + zflag = true; + break; + + case '?': + default: + if (optopt != 's') + atf_tc_fail("Unexpected unknown option -%c found", optopt); + } + } + + ATF_REQUIRE(zflag); + ATF_REQUIRE_EQ_MSG(1, argc - optind, "Invalid number of arguments left " + "after the call to getopt(3)"); + ATF_CHECK_STREQ_MSG("foo", argv[optind], "The non-option argument is " + "invalid"); +} + +/* --------------------------------------------------------------------- + * Tests cases for the header file. + * --------------------------------------------------------------------- */ + +HEADER_TC(include, "atf-c/tp.h"); + +/* --------------------------------------------------------------------- + * Main. + * --------------------------------------------------------------------- */ + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, getopt); + + /* Add the test cases for the header file. */ + ATF_TP_ADD_TC(tp, include); + + return atf_no_error(); +} diff --git a/external/bsd/atf/dist/atf-c/unused_test.c b/external/bsd/atf/dist/atf-c/unused_test.c new file mode 100644 index 000000000..e8de6823a --- /dev/null +++ b/external/bsd/atf/dist/atf-c/unused_test.c @@ -0,0 +1,56 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2012 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +ATF_TC(this_is_used); +ATF_TC_HEAD(this_is_used, tc) +{ + atf_tc_set_md_var(tc, "descr", "A test case that is not referenced"); +} +ATF_TC_BODY(this_is_used, tc) +{ +} + +ATF_TC(this_is_unused); +ATF_TC_HEAD(this_is_unused, tc) +{ + atf_tc_set_md_var(tc, "descr", "A test case that is referenced"); +} +ATF_TC_BODY(this_is_unused, tc) +{ +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, this_is_used); + /* ATF_TP_ADD_TC(tp, this_is_unused); */ + + return atf_no_error(); +} diff --git a/external/bsd/atf/dist/atf-c/utils.c b/external/bsd/atf/dist/atf-c/utils.c new file mode 100644 index 000000000..4409f7a4f --- /dev/null +++ b/external/bsd/atf/dist/atf-c/utils.c @@ -0,0 +1,415 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2010 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "atf-c/utils.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "detail/dynstr.h" + +/** Searches for a regexp in a string. + * + * \param regex The regexp to look for. + * \param str The string in which to look for the expression. + * + * \return True if there is a match; false otherwise. */ +static +bool +grep_string(const char *regex, const char *str) +{ + int res; + regex_t preg; + + printf("Looking for '%s' in '%s'\n", regex, str); + ATF_REQUIRE(regcomp(&preg, regex, REG_EXTENDED) == 0); + + res = regexec(&preg, str, 0, NULL, 0); + ATF_REQUIRE(res == 0 || res == REG_NOMATCH); + + regfree(&preg); + + return res == 0; +} + +/** Prints the contents of a file to stdout. + * + * \param name The name of the file to be printed. + * \param prefix An string to be prepended to every line of the printed + * file. */ +void +atf_utils_cat_file(const char *name, const char *prefix) +{ + const int fd = open(name, O_RDONLY); + ATF_REQUIRE_MSG(fd != -1, "Cannot open %s", name); + + char buffer[1024]; + ssize_t count; + bool continued = false; + while ((count = read(fd, buffer, sizeof(buffer) - 1)) > 0) { + buffer[count] = '\0'; + + if (!continued) + printf("%s", prefix); + + char *iter = buffer; + char *end; + while ((end = strchr(iter, '\n')) != NULL) { + *end = '\0'; + printf("%s\n", iter); + + iter = end + 1; + if (iter != buffer + count) + printf("%s", prefix); + else + continued = false; + } + if (iter < buffer + count) { + printf("%s", iter); + continued = true; + } + } + ATF_REQUIRE(count == 0); +} + +/** Compares a file against the given golden contents. + * + * \param name Name of the file to be compared. + * \param contents Expected contents of the file. + * + * \return True if the file matches the contents; false otherwise. */ +bool +atf_utils_compare_file(const char *name, const char *contents) +{ + const int fd = open(name, O_RDONLY); + ATF_REQUIRE_MSG(fd != -1, "Cannot open %s", name); + + const char *pos = contents; + ssize_t remaining = strlen(contents); + + char buffer[1024]; + ssize_t count; + while ((count = read(fd, buffer, sizeof(buffer))) > 0 && + count <= remaining) { + if (memcmp(pos, buffer, count) != 0) { + close(fd); + return false; + } + remaining -= count; + pos += count; + } + close(fd); + return count == 0 && remaining == 0; +} + +/** Copies a file. + * + * \param source Path to the source file. + * \param destination Path to the destination file. */ +void +atf_utils_copy_file(const char *source, const char *destination) +{ + const int input = open(source, O_RDONLY); + ATF_REQUIRE_MSG(input != -1, "Failed to open source file during " + "copy (%s)", source); + + const int output = open(destination, O_WRONLY | O_CREAT | O_TRUNC, 0777); + ATF_REQUIRE_MSG(output != -1, "Failed to open destination file during " + "copy (%s)", destination); + + char buffer[1024]; + ssize_t length; + while ((length = read(input, buffer, sizeof(buffer))) > 0) + ATF_REQUIRE_MSG(write(output, buffer, length) == length, + "Failed to write to %s during copy", destination); + ATF_REQUIRE_MSG(length != -1, "Failed to read from %s during copy", source); + + struct stat sb; + ATF_REQUIRE_MSG(fstat(input, &sb) != -1, + "Failed to stat source file %s during copy", source); + ATF_REQUIRE_MSG(fchmod(output, sb.st_mode) != -1, + "Failed to chmod destination file %s during copy", + destination); + + close(output); + close(input); +} + +/** Creates a file. + * + * \param name Name of the file to create. + * \param contents Text to write into the created file. + * \param ... Positional parameters to the contents. */ +void +atf_utils_create_file(const char *name, const char *contents, ...) +{ + va_list ap; + atf_dynstr_t formatted; + atf_error_t error; + + va_start(ap, contents); + error = atf_dynstr_init_ap(&formatted, contents, ap); + va_end(ap); + ATF_REQUIRE(!atf_is_error(error)); + + const int fd = open(name, O_WRONLY | O_CREAT | O_TRUNC, 0644); + ATF_REQUIRE_MSG(fd != -1, "Cannot create file %s", name); + ATF_REQUIRE(write(fd, atf_dynstr_cstring(&formatted), + atf_dynstr_length(&formatted)) != -1); + close(fd); + + atf_dynstr_fini(&formatted); +} + +/** Checks if a file exists. + * + * \param path Location of the file to check for. + * + * \return True if the file exists, false otherwise. */ +bool +atf_utils_file_exists(const char *path) +{ + const int ret = access(path, F_OK); + if (ret == -1) { + if (errno != ENOENT) + atf_tc_fail("Failed to check the existence of %s: %s", path, + strerror(errno)); + else + return false; + } else + return true; +} + +/** Spawns a subprocess and redirects its output to files. + * + * Use the atf_utils_wait() function to wait for the completion of the spawned + * subprocess and validate its exit conditions. + * + * \return 0 in the new child; the PID of the new child in the parent. Does + * not return in error conditions. */ +pid_t +atf_utils_fork(void) +{ + const pid_t pid = fork(); + if (pid == -1) + atf_tc_fail("fork failed"); + + if (pid == 0) { + atf_utils_redirect(STDOUT_FILENO, "atf_utils_fork_out.txt"); + atf_utils_redirect(STDERR_FILENO, "atf_utils_fork_err.txt"); + } + return pid; +} + +/** Frees an dynamically-allocated "argv" array. + * + * \param argv A dynamically-allocated array of dynamically-allocated + * strings. */ +void +atf_utils_free_charpp(char **argv) +{ + char **ptr; + + for (ptr = argv; *ptr != NULL; ptr++) + free(*ptr); + + free(argv); +} + +/** Searches for a regexp in a file. + * + * \param regex The regexp to look for. + * \param file The file in which to look for the expression. + * \param ... Positional parameters to the regex. + * + * \return True if there is a match; false otherwise. */ +bool +atf_utils_grep_file(const char *regex, const char *file, ...) +{ + int fd; + va_list ap; + atf_dynstr_t formatted; + atf_error_t error; + + va_start(ap, file); + error = atf_dynstr_init_ap(&formatted, regex, ap); + va_end(ap); + ATF_REQUIRE(!atf_is_error(error)); + + ATF_REQUIRE((fd = open(file, O_RDONLY)) != -1); + bool found = false; + char *line = NULL; + while (!found && (line = atf_utils_readline(fd)) != NULL) { + found = grep_string(atf_dynstr_cstring(&formatted), line); + free(line); + } + close(fd); + + atf_dynstr_fini(&formatted); + + return found; +} + +/** Searches for a regexp in a string. + * + * \param regex The regexp to look for. + * \param str The string in which to look for the expression. + * \param ... Positional parameters to the regex. + * + * \return True if there is a match; false otherwise. */ +bool +atf_utils_grep_string(const char *regex, const char *str, ...) +{ + bool res; + va_list ap; + atf_dynstr_t formatted; + atf_error_t error; + + va_start(ap, str); + error = atf_dynstr_init_ap(&formatted, regex, ap); + va_end(ap); + ATF_REQUIRE(!atf_is_error(error)); + + res = grep_string(atf_dynstr_cstring(&formatted), str); + + atf_dynstr_fini(&formatted); + + return res; +} + +/** Reads a line of arbitrary length. + * + * \param fd The descriptor from which to read the line. + * + * \return A pointer to the read line, which must be released with free(), or + * NULL if there was nothing to read from the file. */ +char * +atf_utils_readline(const int fd) +{ + char ch; + ssize_t cnt; + atf_dynstr_t temp; + atf_error_t error; + + error = atf_dynstr_init(&temp); + ATF_REQUIRE(!atf_is_error(error)); + + while ((cnt = read(fd, &ch, sizeof(ch))) == sizeof(ch) && + ch != '\n') { + error = atf_dynstr_append_fmt(&temp, "%c", ch); + ATF_REQUIRE(!atf_is_error(error)); + } + ATF_REQUIRE(cnt != -1); + + if (cnt == 0 && atf_dynstr_length(&temp) == 0) { + atf_dynstr_fini(&temp); + return NULL; + } else + return atf_dynstr_fini_disown(&temp); +} + +/** Redirects a file descriptor to a file. + * + * \param target_fd The file descriptor to be replaced. + * \param name The name of the file to direct the descriptor to. + * + * \pre Should only be called from the process spawned by fork_for_testing + * because this exits uncontrolledly. + * \post Terminates execution if the redirection fails. */ +void +atf_utils_redirect(const int target_fd, const char *name) +{ + if (target_fd == STDOUT_FILENO) + fflush(stdout); + else if (target_fd == STDERR_FILENO) + fflush(stderr); + + const int new_fd = open(name, O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (new_fd == -1) + err(EXIT_FAILURE, "Cannot create %s", name); + if (new_fd != target_fd) { + if (dup2(new_fd, target_fd) == -1) + err(EXIT_FAILURE, "Cannot redirect to fd %d", target_fd); + } + close(new_fd); +} + +/** Waits for a subprocess and validates its exit condition. + * + * \param pid The process to be waited for. Must have been started by + * testutils_fork(). + * \param exitstatus Expected exit status. + * \param expout Expected contents of stdout. + * \param experr Expected contents of stderr. */ +void +atf_utils_wait(const pid_t pid, const int exitstatus, const char *expout, + const char *experr) +{ + int status; + ATF_REQUIRE(waitpid(pid, &status, 0) != -1); + + atf_utils_cat_file("atf_utils_fork_out.txt", "subprocess stdout: "); + atf_utils_cat_file("atf_utils_fork_err.txt", "subprocess stderr: "); + + ATF_REQUIRE(WIFEXITED(status)); + ATF_REQUIRE_EQ(exitstatus, WEXITSTATUS(status)); + + const char *save_prefix = "save:"; + const size_t save_prefix_length = strlen(save_prefix); + + if (strlen(expout) > save_prefix_length && + strncmp(expout, save_prefix, save_prefix_length) == 0) { + atf_utils_copy_file("atf_utils_fork_out.txt", + expout + save_prefix_length); + } else { + ATF_REQUIRE(atf_utils_compare_file("atf_utils_fork_out.txt", expout)); + } + + if (strlen(experr) > save_prefix_length && + strncmp(experr, save_prefix, save_prefix_length) == 0) { + atf_utils_copy_file("atf_utils_fork_err.txt", + experr + save_prefix_length); + } else { + ATF_REQUIRE(atf_utils_compare_file("atf_utils_fork_err.txt", experr)); + } + + ATF_REQUIRE(unlink("atf_utils_fork_out.txt") != -1); + ATF_REQUIRE(unlink("atf_utils_fork_err.txt") != -1); +} diff --git a/external/bsd/atf/dist/atf-c/utils.h b/external/bsd/atf/dist/atf-c/utils.h new file mode 100644 index 000000000..666804d3a --- /dev/null +++ b/external/bsd/atf/dist/atf-c/utils.h @@ -0,0 +1,54 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2010 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if !defined(ATF_C_UTILS_H) +#define ATF_C_UTILS_H + +#include +#include + +#include + +void atf_utils_cat_file(const char *, const char *); +bool atf_utils_compare_file(const char *, const char *); +void atf_utils_copy_file(const char *, const char *); +void atf_utils_create_file(const char *, const char *, ...) + ATF_DEFS_ATTRIBUTE_FORMAT_PRINTF(2, 3); +bool atf_utils_file_exists(const char *); +pid_t atf_utils_fork(void); +void atf_utils_free_charpp(char **); +bool atf_utils_grep_file(const char *, const char *, ...) + ATF_DEFS_ATTRIBUTE_FORMAT_PRINTF(1, 3); +bool atf_utils_grep_string(const char *, const char *, ...) + ATF_DEFS_ATTRIBUTE_FORMAT_PRINTF(1, 3); +char *atf_utils_readline(int); +void atf_utils_redirect(const int, const char *); +void atf_utils_wait(const pid_t, const int, const char *, const char *); + +#endif /* ATF_C_UTILS_H */ diff --git a/external/bsd/atf/dist/atf-c/utils_test.c b/external/bsd/atf/dist/atf-c/utils_test.c new file mode 100644 index 000000000..57d6af8d2 --- /dev/null +++ b/external/bsd/atf/dist/atf-c/utils_test.c @@ -0,0 +1,538 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2010 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include "atf-c/utils.h" + +#include "detail/test_helpers.h" + +/** Reads the contents of a file into a buffer. + * + * Up to buflen-1 characters are read into buffer. If this function returns, + * the contents read into the buffer are guaranteed to be nul-terminated. + * Note, however, that if the file contains any nul characters itself, + * comparing it "as a string" will not work. + * + * \param path The file to be read, which must exist. + * \param buffer Buffer into which to store the file contents. + * \param buflen Size of the target buffer. + * + * \return The count of bytes read. */ +static ssize_t +read_file(const char *path, void *const buffer, const size_t buflen) +{ + const int fd = open(path, O_RDONLY); + ATF_REQUIRE_MSG(fd != -1, "Cannot open %s", path); + const ssize_t length = read(fd, buffer, buflen - 1); + close(fd); + ATF_REQUIRE(length != -1); + ((char *)buffer)[length] = '\0'; + return length; +} + +ATF_TC_WITHOUT_HEAD(cat_file__empty); +ATF_TC_BODY(cat_file__empty, tc) +{ + atf_utils_create_file("file.txt", "%s", ""); + atf_utils_redirect(STDOUT_FILENO, "captured.txt"); + atf_utils_cat_file("file.txt", "PREFIX"); + fflush(stdout); + close(STDOUT_FILENO); + + char buffer[1024]; + read_file("captured.txt", buffer, sizeof(buffer)); + ATF_REQUIRE_STREQ("", buffer); +} + +ATF_TC_WITHOUT_HEAD(cat_file__one_line); +ATF_TC_BODY(cat_file__one_line, tc) +{ + atf_utils_create_file("file.txt", "This is a single line\n"); + atf_utils_redirect(STDOUT_FILENO, "captured.txt"); + atf_utils_cat_file("file.txt", "PREFIX"); + fflush(stdout); + close(STDOUT_FILENO); + + char buffer[1024]; + read_file("captured.txt", buffer, sizeof(buffer)); + ATF_REQUIRE_STREQ("PREFIXThis is a single line\n", buffer); +} + +ATF_TC_WITHOUT_HEAD(cat_file__several_lines); +ATF_TC_BODY(cat_file__several_lines, tc) +{ + atf_utils_create_file("file.txt", "First\nSecond line\nAnd third\n"); + atf_utils_redirect(STDOUT_FILENO, "captured.txt"); + atf_utils_cat_file("file.txt", ">"); + fflush(stdout); + close(STDOUT_FILENO); + + char buffer[1024]; + read_file("captured.txt", buffer, sizeof(buffer)); + ATF_REQUIRE_STREQ(">First\n>Second line\n>And third\n", buffer); +} + +ATF_TC_WITHOUT_HEAD(cat_file__no_newline_eof); +ATF_TC_BODY(cat_file__no_newline_eof, tc) +{ + atf_utils_create_file("file.txt", "Foo\n bar baz"); + atf_utils_redirect(STDOUT_FILENO, "captured.txt"); + atf_utils_cat_file("file.txt", "PREFIX"); + fflush(stdout); + close(STDOUT_FILENO); + + char buffer[1024]; + read_file("captured.txt", buffer, sizeof(buffer)); + ATF_REQUIRE_STREQ("PREFIXFoo\nPREFIX bar baz", buffer); +} + +ATF_TC_WITHOUT_HEAD(compare_file__empty__match); +ATF_TC_BODY(compare_file__empty__match, tc) +{ + atf_utils_create_file("test.txt", "%s", ""); + ATF_REQUIRE(atf_utils_compare_file("test.txt", "")); +} + +ATF_TC_WITHOUT_HEAD(compare_file__empty__not_match); +ATF_TC_BODY(compare_file__empty__not_match, tc) +{ + atf_utils_create_file("test.txt", "%s", ""); + ATF_REQUIRE(!atf_utils_compare_file("test.txt", "\n")); + ATF_REQUIRE(!atf_utils_compare_file("test.txt", "foo")); + ATF_REQUIRE(!atf_utils_compare_file("test.txt", " ")); +} + +ATF_TC_WITHOUT_HEAD(compare_file__short__match); +ATF_TC_BODY(compare_file__short__match, tc) +{ + atf_utils_create_file("test.txt", "this is a short file"); + ATF_REQUIRE(atf_utils_compare_file("test.txt", "this is a short file")); +} + +ATF_TC_WITHOUT_HEAD(compare_file__short__not_match); +ATF_TC_BODY(compare_file__short__not_match, tc) +{ + atf_utils_create_file("test.txt", "this is a short file"); + ATF_REQUIRE(!atf_utils_compare_file("test.txt", "")); + ATF_REQUIRE(!atf_utils_compare_file("test.txt", "\n")); + ATF_REQUIRE(!atf_utils_compare_file("test.txt", "this is a Short file")); + ATF_REQUIRE(!atf_utils_compare_file("test.txt", "this is a short fil")); + ATF_REQUIRE(!atf_utils_compare_file("test.txt", "this is a short file ")); +} + +ATF_TC_WITHOUT_HEAD(compare_file__long__match); +ATF_TC_BODY(compare_file__long__match, tc) +{ + char long_contents[3456]; + size_t i = 0; + for (; i < sizeof(long_contents) - 1; i++) + long_contents[i] = '0' + (i % 10); + long_contents[i] = '\0'; + atf_utils_create_file("test.txt", "%s", long_contents); + + ATF_REQUIRE(atf_utils_compare_file("test.txt", long_contents)); +} + +ATF_TC_WITHOUT_HEAD(compare_file__long__not_match); +ATF_TC_BODY(compare_file__long__not_match, tc) +{ + char long_contents[3456]; + size_t i = 0; + for (; i < sizeof(long_contents) - 1; i++) + long_contents[i] = '0' + (i % 10); + long_contents[i] = '\0'; + atf_utils_create_file("test.txt", "%s", long_contents); + + ATF_REQUIRE(!atf_utils_compare_file("test.txt", "")); + ATF_REQUIRE(!atf_utils_compare_file("test.txt", "\n")); + ATF_REQUIRE(!atf_utils_compare_file("test.txt", "0123456789")); + long_contents[i - 1] = 'Z'; + ATF_REQUIRE(!atf_utils_compare_file("test.txt", long_contents)); +} + +ATF_TC_WITHOUT_HEAD(copy_file__empty); +ATF_TC_BODY(copy_file__empty, tc) +{ + atf_utils_create_file("src.txt", "%s", ""); + ATF_REQUIRE(chmod("src.txt", 0520) != -1); + + atf_utils_copy_file("src.txt", "dest.txt"); + ATF_REQUIRE(atf_utils_compare_file("dest.txt", "")); + struct stat sb; + ATF_REQUIRE(stat("dest.txt", &sb) != -1); + ATF_REQUIRE_EQ(0520, sb.st_mode & 0xfff); +} + +ATF_TC_WITHOUT_HEAD(copy_file__some_contents); +ATF_TC_BODY(copy_file__some_contents, tc) +{ + atf_utils_create_file("src.txt", "This is a\ntest file\n"); + atf_utils_copy_file("src.txt", "dest.txt"); + ATF_REQUIRE(atf_utils_compare_file("dest.txt", "This is a\ntest file\n")); +} + +ATF_TC_WITHOUT_HEAD(create_file); +ATF_TC_BODY(create_file, tc) +{ + atf_utils_create_file("test.txt", "This is a test with %d", 12345); + + char buffer[128]; + read_file("test.txt", buffer, sizeof(buffer)); + ATF_REQUIRE_STREQ("This is a test with 12345", buffer); +} + +ATF_TC_WITHOUT_HEAD(file_exists); +ATF_TC_BODY(file_exists, tc) +{ + atf_utils_create_file("test.txt", "foo"); + + ATF_REQUIRE( atf_utils_file_exists("test.txt")); + ATF_REQUIRE( atf_utils_file_exists("./test.txt")); + ATF_REQUIRE(!atf_utils_file_exists("./test.tx")); + ATF_REQUIRE(!atf_utils_file_exists("test.txt2")); +} + +ATF_TC_WITHOUT_HEAD(fork); +ATF_TC_BODY(fork, tc) +{ + fprintf(stdout, "Should not get into child\n"); + fprintf(stderr, "Should not get into child\n"); + pid_t pid = atf_utils_fork(); + if (pid == 0) { + fprintf(stdout, "Child stdout\n"); + fprintf(stderr, "Child stderr\n"); + exit(EXIT_SUCCESS); + } + + int status; + ATF_REQUIRE(waitpid(pid, &status, 0) != -1); + ATF_REQUIRE(WIFEXITED(status)); + ATF_REQUIRE_EQ(EXIT_SUCCESS, WEXITSTATUS(status)); + + char buffer[1024]; + read_file("atf_utils_fork_out.txt", buffer, sizeof(buffer)); + ATF_REQUIRE_STREQ("Child stdout\n", buffer); + read_file("atf_utils_fork_err.txt", buffer, sizeof(buffer)); + ATF_REQUIRE_STREQ("Child stderr\n", buffer); +} + +ATF_TC_WITHOUT_HEAD(free_charpp__empty); +ATF_TC_BODY(free_charpp__empty, tc) +{ + char **array = malloc(sizeof(char *) * 1); + array[0] = NULL; + + atf_utils_free_charpp(array); +} + +ATF_TC_WITHOUT_HEAD(free_charpp__some); +ATF_TC_BODY(free_charpp__some, tc) +{ + char **array = malloc(sizeof(char *) * 4); + array[0] = strdup("first"); + array[1] = strdup("second"); + array[2] = strdup("third"); + array[3] = NULL; + + atf_utils_free_charpp(array); +} + +ATF_TC_WITHOUT_HEAD(grep_file); +ATF_TC_BODY(grep_file, tc) +{ + atf_utils_create_file("test.txt", "line1\nthe second line\naaaabbbb\n"); + + ATF_CHECK(atf_utils_grep_file("line1", "test.txt")); + ATF_CHECK(atf_utils_grep_file("line%d", "test.txt", 1)); + ATF_CHECK(atf_utils_grep_file("second line", "test.txt")); + ATF_CHECK(atf_utils_grep_file("aa.*bb", "test.txt")); + ATF_CHECK(!atf_utils_grep_file("foo", "test.txt")); + ATF_CHECK(!atf_utils_grep_file("bar", "test.txt")); + ATF_CHECK(!atf_utils_grep_file("aaaaa", "test.txt")); +} + +ATF_TC_WITHOUT_HEAD(grep_string); +ATF_TC_BODY(grep_string, tc) +{ + const char *str = "a string - aaaabbbb"; + ATF_CHECK(atf_utils_grep_string("a string", str)); + ATF_CHECK(atf_utils_grep_string("^a string", str)); + ATF_CHECK(atf_utils_grep_string("aaaabbbb$", str)); + ATF_CHECK(atf_utils_grep_string("a%s*bb", str, "a.")); + ATF_CHECK(!atf_utils_grep_string("foo", str)); + ATF_CHECK(!atf_utils_grep_string("bar", str)); + ATF_CHECK(!atf_utils_grep_string("aaaaa", str)); +} + +ATF_TC_WITHOUT_HEAD(readline__none); +ATF_TC_BODY(readline__none, tc) +{ + atf_utils_create_file("empty.txt", "%s", ""); + + const int fd = open("empty.txt", O_RDONLY); + ATF_REQUIRE(fd != -1); + ATF_REQUIRE(atf_utils_readline(fd) == NULL); + close(fd); +} + +ATF_TC_WITHOUT_HEAD(readline__some); +ATF_TC_BODY(readline__some, tc) +{ + const char *l1 = "First line with % formatting % characters %"; + const char *l2 = "Second line; much longer than the first one"; + const char *l3 = "Last line, without terminator"; + + atf_utils_create_file("test.txt", "%s\n%s\n%s", l1, l2, l3); + + const int fd = open("test.txt", O_RDONLY); + ATF_REQUIRE(fd != -1); + + char *line; + + line = atf_utils_readline(fd); + ATF_REQUIRE_STREQ(l1, line); + free(line); + + line = atf_utils_readline(fd); + ATF_REQUIRE_STREQ(l2, line); + free(line); + + line = atf_utils_readline(fd); + ATF_REQUIRE_STREQ(l3, line); + free(line); + + close(fd); +} + +ATF_TC_WITHOUT_HEAD(redirect__stdout); +ATF_TC_BODY(redirect__stdout, tc) +{ + printf("Buffer this"); + atf_utils_redirect(STDOUT_FILENO, "captured.txt"); + printf("The printed message"); + fflush(stdout); + + char buffer[1024]; + read_file("captured.txt", buffer, sizeof(buffer)); + ATF_REQUIRE_STREQ("The printed message", buffer); +} + +ATF_TC_WITHOUT_HEAD(redirect__stderr); +ATF_TC_BODY(redirect__stderr, tc) +{ + fprintf(stderr, "Buffer this"); + atf_utils_redirect(STDERR_FILENO, "captured.txt"); + fprintf(stderr, "The printed message"); + fflush(stderr); + + char buffer[1024]; + read_file("captured.txt", buffer, sizeof(buffer)); + ATF_REQUIRE_STREQ("The printed message", buffer); +} + +ATF_TC_WITHOUT_HEAD(redirect__other); +ATF_TC_BODY(redirect__other, tc) +{ + const char *message = "Foo bar\nbaz\n"; + atf_utils_redirect(15, "captured.txt"); + ATF_REQUIRE(write(15, message, strlen(message)) != -1); + close(15); + + char buffer[1024]; + read_file("captured.txt", buffer, sizeof(buffer)); + ATF_REQUIRE_STREQ(message, buffer); +} + +static void +fork_and_wait(const int exitstatus, const char* expout, const char* experr) +{ + const pid_t pid = atf_utils_fork(); + if (pid == 0) { + fprintf(stdout, "Some output\n"); + fprintf(stderr, "Some error\n"); + exit(123); + } + atf_utils_wait(pid, exitstatus, expout, experr); + exit(EXIT_SUCCESS); +} + +ATF_TC_WITHOUT_HEAD(wait__ok); +ATF_TC_BODY(wait__ok, tc) +{ + const pid_t control = fork(); + ATF_REQUIRE(control != -1); + if (control == 0) + fork_and_wait(123, "Some output\n", "Some error\n"); + else { + int status; + ATF_REQUIRE(waitpid(control, &status, 0) != -1); + ATF_REQUIRE(WIFEXITED(status)); + ATF_REQUIRE_EQ(EXIT_SUCCESS, WEXITSTATUS(status)); + } +} + +ATF_TC_WITHOUT_HEAD(wait__invalid_exitstatus); +ATF_TC_BODY(wait__invalid_exitstatus, tc) +{ + const pid_t control = fork(); + ATF_REQUIRE(control != -1); + if (control == 0) + fork_and_wait(120, "Some output\n", "Some error\n"); + else { + int status; + ATF_REQUIRE(waitpid(control, &status, 0) != -1); + ATF_REQUIRE(WIFEXITED(status)); + ATF_REQUIRE_EQ(EXIT_FAILURE, WEXITSTATUS(status)); + } +} + +ATF_TC_WITHOUT_HEAD(wait__invalid_stdout); +ATF_TC_BODY(wait__invalid_stdout, tc) +{ + const pid_t control = fork(); + ATF_REQUIRE(control != -1); + if (control == 0) + fork_and_wait(123, "Some output foo\n", "Some error\n"); + else { + int status; + ATF_REQUIRE(waitpid(control, &status, 0) != -1); + ATF_REQUIRE(WIFEXITED(status)); + ATF_REQUIRE_EQ(EXIT_FAILURE, WEXITSTATUS(status)); + } +} + +ATF_TC_WITHOUT_HEAD(wait__invalid_stderr); +ATF_TC_BODY(wait__invalid_stderr, tc) +{ + const pid_t control = fork(); + ATF_REQUIRE(control != -1); + if (control == 0) + fork_and_wait(123, "Some output\n", "Some error foo\n"); + else { + int status; + ATF_REQUIRE(waitpid(control, &status, 0) != -1); + ATF_REQUIRE(WIFEXITED(status)); + ATF_REQUIRE_EQ(EXIT_FAILURE, WEXITSTATUS(status)); + } +} + +ATF_TC_WITHOUT_HEAD(wait__save_stdout); +ATF_TC_BODY(wait__save_stdout, tc) +{ + const pid_t control = fork(); + ATF_REQUIRE(control != -1); + if (control == 0) + fork_and_wait(123, "save:my-output.txt", "Some error\n"); + else { + int status; + ATF_REQUIRE(waitpid(control, &status, 0) != -1); + ATF_REQUIRE(WIFEXITED(status)); + ATF_REQUIRE_EQ(EXIT_SUCCESS, WEXITSTATUS(status)); + + ATF_REQUIRE(atf_utils_compare_file("my-output.txt", "Some output\n")); + } +} + +ATF_TC_WITHOUT_HEAD(wait__save_stderr); +ATF_TC_BODY(wait__save_stderr, tc) +{ + const pid_t control = fork(); + ATF_REQUIRE(control != -1); + if (control == 0) + fork_and_wait(123, "Some output\n", "save:my-output.txt"); + else { + int status; + ATF_REQUIRE(waitpid(control, &status, 0) != -1); + ATF_REQUIRE(WIFEXITED(status)); + ATF_REQUIRE_EQ(EXIT_SUCCESS, WEXITSTATUS(status)); + + ATF_REQUIRE(atf_utils_compare_file("my-output.txt", "Some error\n")); + } +} + +HEADER_TC(include, "atf-c/utils.h"); + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, cat_file__empty); + ATF_TP_ADD_TC(tp, cat_file__one_line); + ATF_TP_ADD_TC(tp, cat_file__several_lines); + ATF_TP_ADD_TC(tp, cat_file__no_newline_eof); + + ATF_TP_ADD_TC(tp, compare_file__empty__match); + ATF_TP_ADD_TC(tp, compare_file__empty__not_match); + ATF_TP_ADD_TC(tp, compare_file__short__match); + ATF_TP_ADD_TC(tp, compare_file__short__not_match); + ATF_TP_ADD_TC(tp, compare_file__long__match); + ATF_TP_ADD_TC(tp, compare_file__long__not_match); + + ATF_TP_ADD_TC(tp, copy_file__empty); + ATF_TP_ADD_TC(tp, copy_file__some_contents); + + ATF_TP_ADD_TC(tp, create_file); + + ATF_TP_ADD_TC(tp, file_exists); + + ATF_TP_ADD_TC(tp, fork); + + ATF_TP_ADD_TC(tp, free_charpp__empty); + ATF_TP_ADD_TC(tp, free_charpp__some); + + ATF_TP_ADD_TC(tp, grep_file); + ATF_TP_ADD_TC(tp, grep_string); + + ATF_TP_ADD_TC(tp, readline__none); + ATF_TP_ADD_TC(tp, readline__some); + + ATF_TP_ADD_TC(tp, redirect__stdout); + ATF_TP_ADD_TC(tp, redirect__stderr); + ATF_TP_ADD_TC(tp, redirect__other); + + ATF_TP_ADD_TC(tp, wait__ok); + ATF_TP_ADD_TC(tp, wait__save_stdout); + ATF_TP_ADD_TC(tp, wait__save_stderr); + ATF_TP_ADD_TC(tp, wait__invalid_exitstatus); + ATF_TP_ADD_TC(tp, wait__invalid_stdout); + ATF_TP_ADD_TC(tp, wait__invalid_stderr); + + ATF_TP_ADD_TC(tp, include); + + return atf_no_error(); +} diff --git a/external/bsd/atf/dist/atf-config/Atffile b/external/bsd/atf/dist/atf-config/Atffile new file mode 100644 index 000000000..146211e00 --- /dev/null +++ b/external/bsd/atf/dist/atf-config/Atffile @@ -0,0 +1,5 @@ +Content-Type: application/X-atf-atffile; version="1" + +prop: test-suite = atf + +tp-glob: *_test diff --git a/external/bsd/atf/dist/atf-config/Kyuafile b/external/bsd/atf/dist/atf-config/Kyuafile new file mode 100644 index 000000000..8ba4da828 --- /dev/null +++ b/external/bsd/atf/dist/atf-config/Kyuafile @@ -0,0 +1,5 @@ +syntax("kyuafile", 1) + +test_suite("atf") + +atf_test_program{name="integration_test"} diff --git a/external/bsd/atf/dist/atf-config/atf-config.1 b/external/bsd/atf/dist/atf-config/atf-config.1 new file mode 100644 index 000000000..deae6f640 --- /dev/null +++ b/external/bsd/atf/dist/atf-config/atf-config.1 @@ -0,0 +1,184 @@ +.\" +.\" Automated Testing Framework (atf) +.\" +.\" Copyright (c) 2007 The NetBSD Foundation, Inc. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +.\" CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +.\" IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +.\" GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +.\" IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.Dd March 14, 2009 +.Dt ATF-CONFIG 1 +.Os +.Sh NAME +.Nm atf-config +.Nd queries static configuration information of ATF +.Sh SYNOPSIS +.Nm +.Op Fl t +.Op Ar var1 Op Ar .. varN +.Nm +.Fl h +.Sh DESCRIPTION +.Nm +is a utility that queries static configuration information of ATF. +Static configuration refers to all those values for settings that +were built into the ATF binaries at build time. +.Pp +In the first synopsis form, +.Nm +will print variable-value pairs for all built-in static variables if +no variable names are provided as arguments. +If any is provided, it will only print the variable-value pairs for +those variables. +The output of the utility does not use the +.Sq = +symbol to separate the variable name from its corresponding value in +an attempt to avoid sourcing the output in shell scripts or Makefiles. +If you need to do that, the +.Fl t +flag allows you to query the value of individual variables without any +surrounding text. +.Pp +In the second synopsis form, +.Nm +will print information about all supported options and their purpose. +.Pp +The following options are available: +.Bl -tag -width flag +.It Fl h +Shows a short summary of all available options and their purpose. +.It Fl t +Changes the output of the utility to show the variable values, one +per line, without the variable names. +.El +.Ss Static configuration variables +The following list describes all the variables that are part of ATF's +static configuration: +.Bl -tag -width atfXbuildXcppflagsXX +.It Va atf_arch +The architecture name detected by ATF. +This is derived from +.Va atf_machine +because it is a subset of it. +Given that this name might be misdetected, it is provided to the user +as a configuration variable so that he can fix its value temporarily +until a real fix is incorporated into mainstream sources. +.It Va atf_build_cc +The C compiler used by the ATF checks that provide build-time tests. +.It Va atf_build_cflags +The C compiler flags used by the ATF checks that provide build-time tests. +.It Va atf_build_cpp +The C/C++ preprocessor used by the ATF checks that provide build-time tests. +.It Va atf_build_cppflags +The C/C++ preprocessor flags used by the ATF checks that provide build-time +tests. +.It Va atf_build_cxx +The C++ compiler used by the ATF checks that provide build-time tests. +.It Va atf_build_cxxflags +The C++ compiler flags used by the ATF checks that provide build-time tests. +.It Va atf_confdir +The path to the directory that contains the system-wide configuration +files for ATF. +.It Va atf_includedir +The path to the directory that contains the ATF header files. +.It Va atf_libdir +The path to the directory that contains the ATF libraries. +.It Va atf_libexecdir +The path to the directory that contains the auxiliary utilities of ATF, +used internally by the public tools. +.It Va atf_machine +The machine type name detected by ATF. +This should not be tunable but is provided for symmetry with +.Va atf_arch . +.It Va atf_pkgdatadir +The path to the directory that contains the files that form the ATF's +shell-scripting library. +.It Va atf_shell +The path to the shell interpreter that will be used by ATF. +.It Va atf_workdir +The path to the temporary directory that the utilities and the test +programs will use to store temporary files in. +.El +.Sh ENVIRONMENT +Every variable that is part of the static configuration can be +overridden at run-time by defining an environment variable. +This environment variable has the exact same name as the one shown by +.Nm +except that the name is all composed of uppercase letters. +.Pp +In general, empty values in the environment will be ignored unless +otherwise noted below. +.Pp +The recognized environment variables are: +.Bl -tag -width ATFXBUILDXCPPFLAGSXX +.It Ev ATF_ARCH +Overrides the built-in value of +.Va atf_arch . +.It Ev ATF_BUILD_CC +Overrides the built-in value of +.Va atf_build_cc . +.It Ev ATF_BUILD_CFLAGS +Overrides the built-in value of +.Va atf_build_cflags . +Empty values are allowed. +.It Ev ATF_BUILD_CPP +Overrides the built-in value of +.Va atf_build_cpp . +.It Ev ATF_BUILD_CPPFLAGS +Overrides the built-in value of +.Va atf_build_cppflags . +Empty values are allowed. +.It Ev ATF_BUILD_CXX +Overrides the built-in value of +.Va atf_build_cxx . +.It Ev ATF_BUILD_CXXFLAGS +Overrides the built-in value of +.Va atf_build_cxxflags . +Empty values are allowed. +.It Ev ATF_CONFDIR +Overrides the built-in value of +.Va atf_confdir . +.It Ev ATF_INCLUDEDIR +Overrides the built-in value of +.Va atf_includedir . +.It Ev ATF_LIBDIR +Overrides the built-in value of +.Va atf_libdir . +.It Ev ATF_LIBEXECDIR +Overrides the built-in value of +.Va atf_libexecdir . +.It Ev ATF_MACHINE +Overrides the built-in value of +.Va atf_machine . +.It Ev ATF_PKGDATADIR +Overrides the built-in value of +.Va atf_pkgdatadir . +.It Ev ATF_SHELL +Overrides the built-in value of +.Va atf_shell . +.It Ev ATF_WORKDIR +Overrides the built-in value of +.Va atf_workdir . +.El +.Sh SEE ALSO +.Xr atf 7 diff --git a/external/bsd/atf/dist/atf-config/atf-config.cpp b/external/bsd/atf/dist/atf-config/atf-config.cpp new file mode 100644 index 000000000..e5fdca195 --- /dev/null +++ b/external/bsd/atf/dist/atf-config/atf-config.cpp @@ -0,0 +1,145 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#include +#include +#include +#include + +extern "C" { +#include "atf-c/defs.h" +} + +#include "atf-c++/config.hpp" + +#include "atf-c++/detail/application.hpp" +#include "atf-c++/detail/sanity.hpp" + +class atf_config : public atf::application::app { + static const char* m_description; + + bool m_tflag; + + void process_option(int, const char*); + std::string specific_args(void) const; + options_set specific_options(void) const; + + std::string format_var(const std::string&, const std::string&); + +public: + atf_config(void); + + int main(void); +}; + +const char* atf_config::m_description = + "atf-config is a tool that queries the value of several " + "installation-specific configuration values of the atf. " + "It can be used by external tools to discover where specific " + "internal atf files are installed."; + +atf_config::atf_config(void) : + app(m_description, "atf-config(1)", "atf(7)"), + m_tflag(false) +{ +} + +void +atf_config::process_option(int ch, const char* arg ATF_DEFS_ATTRIBUTE_UNUSED) +{ + switch (ch) { + case 't': + m_tflag = true; + break; + + default: + UNREACHABLE; + } +} + +std::string +atf_config::specific_args(void) + const +{ + return "[var1 [.. varN]]"; +} + +atf_config::options_set +atf_config::specific_options(void) + const +{ + using atf::application::option; + options_set opts; + opts.insert(option('t', "", "Terse output: show values only")); + return opts; +} + +std::string +atf_config::format_var(const std::string& name, const std::string& val) +{ + std::string str; + + if (m_tflag) + str = val; + else + str = name + " : " + val; + + return str; +} + +int +atf_config::main(void) +{ + if (m_argc < 1) { + std::map< std::string, std::string > cv = atf::config::get_all(); + + for (std::map< std::string, std::string >::const_iterator iter = + cv.begin(); iter != cv.end(); iter++) + std::cout << format_var((*iter).first, (*iter).second) << "\n"; + } else { + for (int i = 0; i < m_argc; i++) { + if (!atf::config::has(m_argv[i])) + throw std::runtime_error(std::string("Unknown variable `") + + m_argv[i] + "'"); + } + + for (int i = 0; i < m_argc; i++) { + std::cout << format_var(m_argv[i], atf::config::get(m_argv[i])) + << "\n"; + } + } + + return EXIT_SUCCESS; +} + +int +main(int argc, char* const* argv) +{ + return atf_config().run(argc, argv); +} diff --git a/external/bsd/atf/dist/atf-config/integration_test.sh b/external/bsd/atf/dist/atf-config/integration_test.sh new file mode 100644 index 000000000..5d6505a41 --- /dev/null +++ b/external/bsd/atf/dist/atf-config/integration_test.sh @@ -0,0 +1,180 @@ +# +# Automated Testing Framework (atf) +# +# Copyright (c) 2007 The NetBSD Foundation, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +# CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +all_vars="atf_arch \ + atf_build_cc \ + atf_build_cflags \ + atf_build_cpp \ + atf_build_cppflags \ + atf_build_cxx \ + atf_build_cxxflags \ + atf_confdir \ + atf_includedir \ + atf_libdir \ + atf_libexecdir \ + atf_machine \ + atf_pkgdatadir \ + atf_shell \ + atf_workdir" +all_vars_no=15 + +atf_test_case list_all +list_all_head() +{ + atf_set "descr" "Tests that at atf-config prints all expected" \ + "variables, and not more" +} +list_all_body() +{ + atf_check -s eq:0 -o save:stdout -e empty atf-config + atf_check -s eq:0 -o empty -e empty \ + test "$(wc -l stdout | awk '{ print $1 }')" = "${all_vars_no}" + for v in ${all_vars}; do + atf_check -s eq:0 -o ignore -e empty grep "${v}" stdout + done +} + +atf_test_case query_one +query_one_head() +{ + atf_set "descr" "Tests that querying a single variable works" +} +query_one_body() +{ + for v in ${all_vars}; do + atf_check -s eq:0 -o save:stdout -o match:"${v}" -e empty \ + atf-config "${v}" + atf_check -s eq:0 -o empty -e empty \ + test "$(wc -l stdout | awk '{ print $1 }')" = 1 + done +} + +atf_test_case query_one_terse +query_one_terse_head() +{ + atf_set "descr" "Tests that querying a single variable in terse mode" \ + "works" +} +query_one_terse_body() +{ + for v in ${all_vars}; do + atf_check -s eq:0 -o save:stdout -o match:"${v}" -e empty \ + atf-config "${v}" + atf_check -s eq:0 -o empty -e empty \ + test "$(wc -l stdout | awk '{ print $1 }')" = 1 + atf_check -s eq:0 -o save:stdout -e empty cut -d ' ' -f 3- stdout + atf_check -s eq:0 -o empty -e empty mv stdout expout + atf_check -s eq:0 -o file:expout -e empty atf-config -t "${v}" + done +} + +atf_test_case query_multiple +query_multiple_head() +{ + atf_set "descr" "Tests that querying multiple variables works" +} +query_multiple_body() +{ + atf_check -s eq:0 -o save:stdout -o match:'atf_libexecdir' \ + -o match:'atf_shell' -e empty atf-config atf_libexecdir atf_shell + atf_check -s eq:0 -o empty -e empty \ + test "$(wc -l stdout | awk '{ print $1 }')" = 2 +} + +atf_test_case query_unknown +query_unknown_head() +{ + atf_set "descr" "Tests that querying an unknown variable delivers" \ + "the correct error" +} +query_unknown_body() +{ + atf_check -s eq:1 -o empty -e match:'Unknown variable.*non_existent' \ + atf-config non_existent +} + +atf_test_case query_mixture +query_mixture_head() +{ + atf_set "descr" "Tests that querying a known and an unknown variable" \ + "delivers the correct error" +} +query_mixture_body() +{ + for v in ${all_vars}; do + atf_check -s eq:1 -o empty -e match:'Unknown variable.*non_existent' \ + atf-config "${v}" non_existent + atf_check -s eq:1 -o empty -e match:'Unknown variable.*non_existent' \ + atf-config non_existent "${v}" + done +} + +atf_test_case override_env +override_env_head() +{ + atf_set "descr" "Tests that build-time variables can be overriden" \ + "through their corresponding environment variables" +} +override_env_body() +{ + for v in ${all_vars}; do + V=$(echo ${v} | tr '[a-z]' '[A-Z]') + atf_check -s eq:0 -o save:stdout -e empty -x "${V}=testval atf-config" + atf_check -s eq:0 -o empty -e empty mv stdout all + + atf_check -s eq:0 -o save:stdout -e empty grep "^${v} : " all + atf_check -s eq:0 -o empty -e empty mv stdout affected + atf_check -s eq:0 -o save:stdout -e empty grep -v "^${v} : " all + atf_check -s eq:0 -o empty -e empty mv stdout unaffected + + atf_check -s eq:0 -o empty -e empty \ + test "$(wc -l affected | awk '{ print $1 }')" = 1 + atf_check -s eq:0 -o empty -e empty \ + test "$(wc -l unaffected | awk '{ print $1 }')" = \ + "$((${all_vars_no} -1))" + + atf_check -s eq:0 -o ignore -e empty grep "^${v} : testval$" affected + atf_check -s eq:1 -o empty -e empty grep ' : testval$' unaffected + done +} + +atf_init_test_cases() +{ + atf_add_test_case list_all + + atf_add_test_case query_one + atf_add_test_case query_one_terse + atf_add_test_case query_multiple + atf_add_test_case query_unknown + atf_add_test_case query_mixture + + atf_add_test_case override_env +} + +# vim: syntax=sh:expandtab:shiftwidth=4:softtabstop=4 diff --git a/external/bsd/atf/dist/atf-report/Atffile b/external/bsd/atf/dist/atf-report/Atffile new file mode 100644 index 000000000..146211e00 --- /dev/null +++ b/external/bsd/atf/dist/atf-report/Atffile @@ -0,0 +1,5 @@ +Content-Type: application/X-atf-atffile; version="1" + +prop: test-suite = atf + +tp-glob: *_test diff --git a/external/bsd/atf/dist/atf-report/Kyuafile b/external/bsd/atf/dist/atf-report/Kyuafile new file mode 100644 index 000000000..d69e3fa54 --- /dev/null +++ b/external/bsd/atf/dist/atf-report/Kyuafile @@ -0,0 +1,6 @@ +syntax("kyuafile", 1) + +test_suite("atf") + +atf_test_program{name="integration_test"} +atf_test_program{name="reader_test"} diff --git a/external/bsd/atf/dist/atf-report/atf-report.1 b/external/bsd/atf/dist/atf-report/atf-report.1 new file mode 100644 index 000000000..df03af0e0 --- /dev/null +++ b/external/bsd/atf/dist/atf-report/atf-report.1 @@ -0,0 +1,168 @@ +.\" +.\" Automated Testing Framework (atf) +.\" +.\" Copyright (c) 2007 The NetBSD Foundation, Inc. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +.\" CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +.\" IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +.\" GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +.\" IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.Dd December 16, 2011 +.Dt ATF-REPORT 1 +.Os +.Sh NAME +.Nm atf-report +.Nd transforms the output of atf-run to different formats +.Sh SYNOPSIS +.Nm +.Op Fl o Ar fmt1:path1 Op .. Fl o Ar fmtN:pathN +.Nm +.Fl h +.Sh DESCRIPTION +.Nm +reads the output of +.Nm atf-run +and transforms it to different formats. +Some of these are user-friendly and others are machine-parseable, which +opens a wide range of possibilities to analyze the results of a test +suite's execution. +See +.Sx Output formats +below for more details on which these formats are. +.Pp +In the first synopsis form, +.Nm +reads the output of +.Nm atf-run +through its standard input and, if no +.Fl o +options are given, prints a user-friendly report on its standard +output using the +.Sq ticker +format. +If +.Fl o +options are provided (more than one are allowed), they specify the complete +list of reports to generate. +They are all generated simultaneously, and for obvious reasons, two reports +cannot be written to the same file. +Note that the default output is suppressed when +.Fl o +is provided. +.Pp +In the second synopsis form, +.Nm +will print information about all supported options and their purpose. +.Pp +The following options are available: +.Bl -tag -width XoXfmtXpathXX +.It Fl h +Shows a short summary of all available options and their purpose. +.It Fl o Ar fmt:path +Adds a new output format. +.Ar fmt +is one of the formats described later on in +.Sx Output formats . +.Ar path +specifies where the report will be written to. +Depending on the chosen format, this may refer to a single file or to +a directory. +For those formats that write to a single file, specifying a +.Sq - +as the path will redirect the report to the standard output. +.El +.Ss Output formats +The following output formats are allowed: +.Bl -tag -width tickerXX +.It csv +A machine-parseable Comma-Separated Values (CSV) file. +This file contains the results for all test cases and test programs. +Test cases are logged using the following syntax: +.Bd -literal -offset indent +tc, duration, test-program, test-case, result[, reason] +.Ed +.Pp +The +.Sq result +field for test cases is always one of +.Sq passed , +.Sq skipped +or +.Sq failed . +The last two are always followed by a reason. +.Pp +Test programs are logged with the following syntax: +.Bd -literal -offset indent +tp, duration, test-program, result[, reason] +.Ed +.Pp +In this case, the +.Sq result +can be one of: +.Sq passed , +which denotes test programs that ran without any failure; +.Sq failed , +which refers to test programs in which one or more test cases failed; +or +.Sq bogus , +which mentions those test programs that failed to execute by some reason. +The reason field is only available in the last case. +.Pp +The time required to execute each test case and test program is +also provided. +You should not rely on the order of the entries in the resulting output. +.It ticker +A user-friendly report that shows the progress of the test suite's +execution as it operates. +This type of report should always be redirected to a virtual terminal, +not a file, as it may use control sequences that will make the output +unreadable in regular files. +.It xml +A report contained in a single XML file. +Ideal for later processing with +.Xr xsltproc 1 +to generate nice HTML reports. +.El +.Sh EXAMPLES +The most simple way of running a test suite is to pipe the output of +.Nm atf-run +through +.Nm +without any additional flags. +This will use the default output format, which is suitable to most users: +.Bd -literal -offset indent +atf-run | atf-report +.Ed +.Pp +In some situations, it may be interesting to get a machine-parseable file +aside from the standard report. +This can be done as follows: +.Bd -literal -offset indent +atf-run | atf-report -o csv:testsuite.csv -o ticker:- +.Ed +.Pp +Or if the standard report is not desired, thus achieving completely silent +operation: +atf-run | atf-report -o csv:testsuite.csv +.Sh SEE ALSO +.Xr atf-run 1 , +.Xr atf 7 diff --git a/external/bsd/atf/dist/atf-report/atf-report.cpp b/external/bsd/atf/dist/atf-report/atf-report.cpp new file mode 100644 index 000000000..359b58b23 --- /dev/null +++ b/external/bsd/atf/dist/atf-report/atf-report.cpp @@ -0,0 +1,713 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +extern "C" { +#include +} + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "atf-c/defs.h" + +#include "atf-c++/detail/application.hpp" +#include "atf-c++/detail/fs.hpp" +#include "atf-c++/detail/sanity.hpp" +#include "atf-c++/detail/text.hpp" +#include "atf-c++/detail/ui.hpp" + +#include "reader.hpp" + +typedef std::auto_ptr< std::ostream > ostream_ptr; + +static ostream_ptr +open_outfile(const atf::fs::path& path) +{ + ostream_ptr osp; + if (path.str() == "-") + osp = ostream_ptr(new std::ofstream("/dev/stdout")); + else + osp = ostream_ptr(new std::ofstream(path.c_str())); + if (!(*osp)) + throw std::runtime_error("Could not create file " + path.str()); + return osp; +} + +static std::string +format_tv(struct timeval* tv) +{ + std::ostringstream output; + output << static_cast< long >(tv->tv_sec) << '.' + << std::setfill('0') << std::setw(6) + << static_cast< long >(tv->tv_usec); + return output.str(); +} + +// ------------------------------------------------------------------------ +// The "writer" interface. +// ------------------------------------------------------------------------ + +//! +//! \brief A base class that defines an output format. +//! +//! The writer base class defines a generic interface to output formats. +//! This is meant to be subclassed, and each subclass can redefine any +//! method to format the information as it wishes. +//! +//! This class is not tied to a output stream nor a file because, depending +//! on the output format, we will want to write to a single file or to +//! multiple ones. +//! +class writer { +public: + writer(void) {} + virtual ~writer(void) {} + + virtual void write_info(const std::string&, const std::string&) {} + virtual void write_ntps(size_t) {} + virtual void write_tp_start(const std::string&, size_t) {} + virtual void write_tp_end(struct timeval*, const std::string&) {} + virtual void write_tc_start(const std::string&) {} + virtual void write_tc_stdout_line(const std::string&) {} + virtual void write_tc_stderr_line(const std::string&) {} + virtual void write_tc_end(const std::string&, struct timeval*, + const std::string&) {} + virtual void write_eof(void) {} +}; + +// ------------------------------------------------------------------------ +// The "csv_writer" class. +// ------------------------------------------------------------------------ + +//! +//! \brief A very simple plain-text output format. +//! +//! The csv_writer class implements a very simple plain-text output +//! format that summarizes the results of each executed test case. The +//! results are meant to be easily parseable by third-party tools, hence +//! they are formatted as a CSV file. +//! +class csv_writer : public writer { + ostream_ptr m_os; + bool m_failed; + + std::string m_tpname; + std::string m_tcname; + +public: + csv_writer(const atf::fs::path& p) : + m_os(open_outfile(p)) + { + } + + virtual + void + write_tp_start(const std::string& name, + size_t ntcs ATF_DEFS_ATTRIBUTE_UNUSED) + { + m_tpname = name; + m_failed = false; + } + + virtual + void + write_tp_end(struct timeval* tv, const std::string& reason) + { + const std::string timestamp = format_tv(tv); + + if (!reason.empty()) + (*m_os) << "tp, " << timestamp << ", " << m_tpname << ", bogus, " + << reason << "\n"; + else if (m_failed) + (*m_os) << "tp, " << timestamp << ", "<< m_tpname << ", failed\n"; + else + (*m_os) << "tp, " << timestamp << ", "<< m_tpname << ", passed\n"; + } + + virtual + void + write_tc_start(const std::string& name) + { + m_tcname = name; + } + + virtual + void + write_tc_end(const std::string& state, struct timeval* tv, + const std::string& reason) + { + std::string str = m_tpname + ", " + m_tcname + ", " + state; + if (!reason.empty()) + str += ", " + reason; + (*m_os) << "tc, " << format_tv(tv) << ", " << str << "\n"; + + if (state == "failed") + m_failed = true; + } +}; + +// ------------------------------------------------------------------------ +// The "ticker_writer" class. +// ------------------------------------------------------------------------ + +//! +//! \brief A console-friendly output format. +//! +//! The ticker_writer class implements a formatter that is user-friendly +//! in the sense that it shows the execution of test cases in an easy to +//! read format. It is not meant to be parseable and its format can +//! freely change across releases. +//! +class ticker_writer : public writer { + ostream_ptr m_os; + + size_t m_curtp, m_ntps; + size_t m_tcs_passed, m_tcs_failed, m_tcs_skipped, m_tcs_expected_failures; + std::string m_tcname, m_tpname; + std::vector< std::string > m_failed_tcs; + std::map< std::string, std::string > m_expected_failures_tcs; + std::vector< std::string > m_failed_tps; + + void + write_info(const std::string& what, const std::string& val) + { + if (what == "tests.root") { + (*m_os) << "Tests root: " << val << "\n\n"; + } + } + + void + write_ntps(size_t ntps) + { + m_curtp = 1; + m_tcs_passed = 0; + m_tcs_failed = 0; + m_tcs_skipped = 0; + m_tcs_expected_failures = 0; + m_ntps = ntps; + } + + void + write_tp_start(const std::string& tp, size_t ntcs) + { + using atf::text::to_string; + using atf::ui::format_text; + + m_tpname = tp; + + (*m_os) << format_text(tp + " (" + to_string(m_curtp) + + "/" + to_string(m_ntps) + "): " + + to_string(ntcs) + " test cases") + << "\n"; + (*m_os).flush(); + } + + void + write_tp_end(struct timeval* tv, const std::string& reason) + { + using atf::ui::format_text_with_tag; + + m_curtp++; + + if (!reason.empty()) { + (*m_os) << format_text_with_tag("BOGUS TEST PROGRAM: Cannot " + "trust its results because " + "of `" + reason + "'", + m_tpname + ": ", false) + << "\n"; + m_failed_tps.push_back(m_tpname); + } + (*m_os) << "[" << format_tv(tv) << "s]\n\n"; + (*m_os).flush(); + + m_tpname.clear(); + } + + void + write_tc_start(const std::string& tcname) + { + m_tcname = tcname; + + (*m_os) << " " + tcname + ": "; + (*m_os).flush(); + } + + void + write_tc_end(const std::string& state, struct timeval* tv, + const std::string& reason) + { + std::string str; + + (*m_os) << "[" << format_tv(tv) << "s] "; + + if (state == "expected_death" || state == "expected_exit" || + state == "expected_failure" || state == "expected_signal" || + state == "expected_timeout") { + str = "Expected failure: " + reason; + m_tcs_expected_failures++; + m_expected_failures_tcs[m_tpname + ":" + m_tcname] = reason; + } else if (state == "failed") { + str = "Failed: " + reason; + m_tcs_failed++; + m_failed_tcs.push_back(m_tpname + ":" + m_tcname); + } else if (state == "passed") { + str = "Passed."; + m_tcs_passed++; + } else if (state == "skipped") { + str = "Skipped: " + reason; + m_tcs_skipped++; + } else + UNREACHABLE; + + // XXX Wrap text. format_text_with_tag does not currently allow + // to specify the current column, which is needed because we have + // already printed the tc's name. + (*m_os) << str << '\n'; + + m_tcname = ""; + } + + static void + write_expected_failures(const std::map< std::string, std::string >& xfails, + std::ostream& os) + { + using atf::ui::format_text; + using atf::ui::format_text_with_tag; + + os << format_text("Test cases for known bugs:") << "\n"; + + for (std::map< std::string, std::string >::const_iterator iter = + xfails.begin(); iter != xfails.end(); iter++) { + const std::string& name = (*iter).first; + const std::string& reason = (*iter).second; + + os << format_text_with_tag(reason, " " + name + ": ", false) + << "\n"; + } + } + + void + write_eof(void) + { + using atf::text::join; + using atf::text::to_string; + using atf::ui::format_text; + using atf::ui::format_text_with_tag; + + if (!m_failed_tps.empty()) { + (*m_os) << format_text("Failed (bogus) test programs:") + << "\n"; + (*m_os) << format_text_with_tag(join(m_failed_tps, ", "), + " ", false) << "\n\n"; + } + + if (!m_expected_failures_tcs.empty()) { + write_expected_failures(m_expected_failures_tcs, *m_os); + (*m_os) << "\n"; + } + + if (!m_failed_tcs.empty()) { + (*m_os) << format_text("Failed test cases:") << "\n"; + (*m_os) << format_text_with_tag(join(m_failed_tcs, ", "), + " ", false) << "\n\n"; + } + + (*m_os) << format_text("Summary for " + to_string(m_ntps) + + " test programs:") << "\n"; + (*m_os) << format_text_with_tag(to_string(m_tcs_passed) + + " passed test cases.", + " ", false) << "\n"; + (*m_os) << format_text_with_tag(to_string(m_tcs_failed) + + " failed test cases.", + " ", false) << "\n"; + (*m_os) << format_text_with_tag(to_string(m_tcs_expected_failures) + + " expected failed test cases.", + " ", false) << "\n"; + (*m_os) << format_text_with_tag(to_string(m_tcs_skipped) + + " skipped test cases.", + " ", false) << "\n"; + } + +public: + ticker_writer(const atf::fs::path& p) : + m_os(open_outfile(p)) + { + } +}; + +// ------------------------------------------------------------------------ +// The "xml" class. +// ------------------------------------------------------------------------ + +//! +//! \brief A single-file XML output format. +//! +//! The xml_writer class implements a formatter that prints the results +//! of test cases in an XML format easily parseable later on by other +//! utilities. +//! +class xml_writer : public writer { + ostream_ptr m_os; + + std::string m_tcname, m_tpname; + + static + std::string + attrval(const std::string& str) + { + return str; + } + + static + std::string + elemval(const std::string& str) + { + std::ostringstream buf; + for (std::string::const_iterator iter = str.begin(); + iter != str.end(); iter++) { + const int character = static_cast< unsigned char >(*iter); + if (character == '&') { + buf << "&"; + } else if (character == '<') { + buf << "<"; + } else if (character == '>') { + buf << ">"; + } else if (std::isalnum(character) || std::ispunct(character) || + std::isspace(character)) { + buf << static_cast< char >(character); + } else { + buf << "&#" << character << ";"; + } + } + return buf.str(); + } + + void + write_info(const std::string& what, const std::string& val) + { + (*m_os) << "" << val << "\n"; + } + + void + write_tp_start(const std::string& tp, + size_t ntcs ATF_DEFS_ATTRIBUTE_UNUSED) + { + (*m_os) << "\n"; + } + + void + write_tp_end(struct timeval* tv, const std::string& reason) + { + if (!reason.empty()) + (*m_os) << "" << elemval(reason) << "\n"; + (*m_os) << "" << format_tv(tv) << ""; + (*m_os) << "\n"; + } + + void + write_tc_start(const std::string& tcname) + { + (*m_os) << "\n"; + } + + void + write_tc_stdout_line(const std::string& line) + { + (*m_os) << "" << elemval(line) << "\n"; + } + + void + write_tc_stderr_line(const std::string& line) + { + (*m_os) << "" << elemval(line) << "\n"; + } + + void + write_tc_end(const std::string& state, struct timeval* tv, + const std::string& reason) + { + std::string str; + + if (state == "expected_death" || state == "expected_exit" || + state == "expected_failure" || state == "expected_signal" || + state == "expected_timeout") { + (*m_os) << "<" << state << ">" << elemval(reason) + << "\n"; + } else if (state == "passed") { + (*m_os) << "\n"; + } else if (state == "failed") { + (*m_os) << "" << elemval(reason) << "\n"; + } else if (state == "skipped") { + (*m_os) << "" << elemval(reason) << "\n"; + } else + UNREACHABLE; + (*m_os) << "" << format_tv(tv) << ""; + (*m_os) << "\n"; + } + + void + write_eof(void) + { + (*m_os) << "\n"; + } + +public: + xml_writer(const atf::fs::path& p) : + m_os(open_outfile(p)) + { + (*m_os) << "\n" + << "\n\n" + "\n"; + } +}; + +// ------------------------------------------------------------------------ +// The "converter" class. +// ------------------------------------------------------------------------ + +//! +//! \brief A reader that redirects events to multiple writers. +//! +//! The converter class implements an atf_tps_reader that, for each event +//! raised by the parser, redirects it to multiple writers so that they +//! can reformat it according to their output rules. +//! +class converter : public atf::atf_report::atf_tps_reader { + typedef std::vector< writer* > outs_vector; + outs_vector m_outs; + + void + got_info(const std::string& what, const std::string& val) + { + for (outs_vector::iterator iter = m_outs.begin(); + iter != m_outs.end(); iter++) + (*iter)->write_info(what, val); + } + + void + got_ntps(size_t ntps) + { + for (outs_vector::iterator iter = m_outs.begin(); + iter != m_outs.end(); iter++) + (*iter)->write_ntps(ntps); + } + + void + got_tp_start(const std::string& tp, size_t ntcs) + { + for (outs_vector::iterator iter = m_outs.begin(); + iter != m_outs.end(); iter++) + (*iter)->write_tp_start(tp, ntcs); + } + + void + got_tp_end(struct timeval* tv, const std::string& reason) + { + for (outs_vector::iterator iter = m_outs.begin(); + iter != m_outs.end(); iter++) + (*iter)->write_tp_end(tv, reason); + } + + void + got_tc_start(const std::string& tcname) + { + for (outs_vector::iterator iter = m_outs.begin(); + iter != m_outs.end(); iter++) + (*iter)->write_tc_start(tcname); + } + + void + got_tc_stdout_line(const std::string& line) + { + for (outs_vector::iterator iter = m_outs.begin(); + iter != m_outs.end(); iter++) + (*iter)->write_tc_stdout_line(line); + } + + void + got_tc_stderr_line(const std::string& line) + { + for (outs_vector::iterator iter = m_outs.begin(); + iter != m_outs.end(); iter++) + (*iter)->write_tc_stderr_line(line); + } + + void + got_tc_end(const std::string& state, struct timeval* tv, + const std::string& reason) + { + for (outs_vector::iterator iter = m_outs.begin(); + iter != m_outs.end(); iter++) + (*iter)->write_tc_end(state, tv, reason); + } + + void + got_eof(void) + { + for (outs_vector::iterator iter = m_outs.begin(); + iter != m_outs.end(); iter++) + (*iter)->write_eof(); + } + +public: + converter(std::istream& is) : + atf::atf_report::atf_tps_reader(is) + { + } + + ~converter(void) + { + for (outs_vector::iterator iter = m_outs.begin(); + iter != m_outs.end(); iter++) + delete *iter; + } + + void + add_output(const std::string& fmt, const atf::fs::path& p) + { + if (fmt == "csv") { + m_outs.push_back(new csv_writer(p)); + } else if (fmt == "ticker") { + m_outs.push_back(new ticker_writer(p)); + } else if (fmt == "xml") { + m_outs.push_back(new xml_writer(p)); + } else + throw std::runtime_error("Unknown format `" + fmt + "'"); + } +}; + +// ------------------------------------------------------------------------ +// The "atf_report" class. +// ------------------------------------------------------------------------ + +class atf_report : public atf::application::app { + static const char* m_description; + + typedef std::pair< std::string, atf::fs::path > fmt_path_pair; + std::vector< fmt_path_pair > m_oflags; + + void process_option(int, const char*); + options_set specific_options(void) const; + +public: + atf_report(void); + + int main(void); +}; + +const char* atf_report::m_description = + "atf-report is a tool that parses the output of atf-run and " + "generates user-friendly reports in multiple different formats."; + +atf_report::atf_report(void) : + app(m_description, "atf-report(1)", "atf(7)") +{ +} + +void +atf_report::process_option(int ch, const char* arg) +{ + switch (ch) { + case 'o': + { + std::string str(arg); + std::string::size_type pos = str.find(':'); + if (pos == std::string::npos) + throw std::runtime_error("Syntax error in -o option"); + else { + std::string fmt = str.substr(0, pos); + atf::fs::path path = atf::fs::path(str.substr(pos + 1)); + m_oflags.push_back(fmt_path_pair(fmt, path)); + } + } + break; + + default: + UNREACHABLE; + } +} + +atf_report::options_set +atf_report::specific_options(void) + const +{ + using atf::application::option; + options_set opts; + opts.insert(option('o', "fmt:path", "Adds a new output file; multiple " + "ones can be specified, and a - " + "path means stdout")); + return opts; +} + +int +atf_report::main(void) +{ + if (m_argc > 0) + throw std::runtime_error("No arguments allowed"); + + if (m_oflags.empty()) + m_oflags.push_back(fmt_path_pair("ticker", atf::fs::path("-"))); + + // Look for path duplicates. + std::set< atf::fs::path > paths; + for (std::vector< fmt_path_pair >::const_iterator iter = m_oflags.begin(); + iter != m_oflags.end(); iter++) { + atf::fs::path p = (*iter).second; + if (p == atf::fs::path("/dev/stdout")) + p = atf::fs::path("-"); + if (paths.find(p) != paths.end()) + throw std::runtime_error("The file `" + p.str() + "' was " + "specified more than once"); + paths.insert((*iter).second); + } + + // Generate the output files. + converter cnv(std::cin); + for (std::vector< fmt_path_pair >::const_iterator iter = m_oflags.begin(); + iter != m_oflags.end(); iter++) + cnv.add_output((*iter).first, (*iter).second); + cnv.read(); + + return EXIT_SUCCESS; +} + +int +main(int argc, char* const* argv) +{ + return atf_report().run(argc, argv); +} diff --git a/external/bsd/atf/dist/atf-report/fail_helper.cpp b/external/bsd/atf/dist/atf-report/fail_helper.cpp new file mode 100644 index 000000000..1009f0e47 --- /dev/null +++ b/external/bsd/atf/dist/atf-report/fail_helper.cpp @@ -0,0 +1,45 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#include "atf-c++/macros.hpp" + +ATF_TEST_CASE(main); +ATF_TEST_CASE_HEAD(main) +{ + set_md_var("descr", "Helper test case that always fails"); +} +ATF_TEST_CASE_BODY(main) +{ + fail("This always fails"); +} + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, main); +} diff --git a/external/bsd/atf/dist/atf-report/integration_test.sh b/external/bsd/atf/dist/atf-report/integration_test.sh new file mode 100644 index 000000000..b19346a86 --- /dev/null +++ b/external/bsd/atf/dist/atf-report/integration_test.sh @@ -0,0 +1,448 @@ +# +# Automated Testing Framework (atf) +# +# Copyright (c) 2007 The NetBSD Foundation, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +# CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +create_helpers() +{ + mkdir dir1 + cp $(atf_get_srcdir)/pass_helper dir1/tp1 + cp $(atf_get_srcdir)/fail_helper dir1/tp2 + cp $(atf_get_srcdir)/pass_helper tp3 + cp $(atf_get_srcdir)/fail_helper tp4 + + cat >tp5 <Atffile <dir1/Atffile <etc/atf-run.hooks <tps.out 2>/dev/null + rm -rf etc +} + +atf_test_case default +default_head() +{ + atf_set "descr" "Checks that the default output uses the ticker" \ + "format" +} +default_body() +{ + create_helpers + run_helpers + + # Check that the default output uses the ticker format. + atf_check -s eq:0 -o match:'test cases' -o match:'Failed test cases' \ + -o match:'Summary for' -e empty -x 'atf-report Atffile <expout <expout <expout <>'; expected \`:' +EOF +# NO_CHECK_STYLE_END + + atf_check -s eq:0 -o file:expout -e empty -x \ + "atf-report -o csv:- expout <>'; expected \`:'' +[#.#s] + +Failed (bogus) test programs: + tp5 + +Failed test cases: + dir1/tp2:main, tp4:main + +Summary for 5 test programs: + 2 passed test cases. + 2 failed test cases. + 0 expected failed test cases. + 0 skipped test cases. +EOF + + atf_check -s eq:0 -o file:expout -e empty -x \ + "atf-report -o ticker:- expout < + + + +A value + + + +#.# +#.# + + +This always fails +#.# +#.# + + + +#.# +#.# + + +This always fails +#.# +#.# + +Invalid format for test case list: 1: Unexpected token \`<<NEWLINE>>'; expected \`:' +#.# +Another value + +EOF +# NO_CHECK_STYLE_END + + atf_check -s eq:0 -o file:expout -e empty -x \ + "atf-report -o xml:- < tps.out | sed -E -e 's/>[0-9]+.[0-9]{6}#.#Atffile <expout < + + + +A value + + +--- a 2007-11-04 14:00:41.000000000 +0100 ++++ b 2007-11-04 14:00:48.000000000 +0100 +@@ -1,7 +1,7 @@ + This test is meant to simulate a diff. + Blank space at beginning of context lines must be preserved. + +-First original line. +-Second original line. ++First modified line. ++Second modified line. + + EOF + +#.# +#.# +Another value + +EOF +# NO_CHECK_STYLE_END + + run_helpers + atf_check -s eq:0 -o file:expout -e empty -x \ + "atf-report -o xml:- [0-9]+.[0-9]{6}#.#experr < + +#include "atf-c++/macros.hpp" + +// ------------------------------------------------------------------------ +// Helper tests for "t_integration". +// ------------------------------------------------------------------------ + +ATF_TEST_CASE(diff); +ATF_TEST_CASE_HEAD(diff) +{ + set_md_var("descr", "Helper test case for the t_integration program"); +} +ATF_TEST_CASE_BODY(diff) +{ + std::cout << "--- a 2007-11-04 14:00:41.000000000 +0100\n"; + std::cout << "+++ b 2007-11-04 14:00:48.000000000 +0100\n"; + std::cout << "@@ -1,7 +1,7 @@\n"; + std::cout << " This test is meant to simulate a diff.\n"; + std::cout << " Blank space at beginning of context lines must be " + "preserved.\n"; + std::cout << " \n"; + std::cout << "-First original line.\n"; + std::cout << "-Second original line.\n"; + std::cout << "+First modified line.\n"; + std::cout << "+Second modified line.\n"; + std::cout << " \n"; + std::cout << " EOF\n"; +} + +// ------------------------------------------------------------------------ +// Main. +// ------------------------------------------------------------------------ + +ATF_INIT_TEST_CASES(tcs) +{ + // Add helper tests for t_integration. + ATF_ADD_TEST_CASE(tcs, diff); +} diff --git a/external/bsd/atf/dist/atf-report/pass_helper.cpp b/external/bsd/atf/dist/atf-report/pass_helper.cpp new file mode 100644 index 000000000..b752b131b --- /dev/null +++ b/external/bsd/atf/dist/atf-report/pass_helper.cpp @@ -0,0 +1,44 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#include "atf-c++/macros.hpp" + +ATF_TEST_CASE(main); +ATF_TEST_CASE_HEAD(main) +{ + set_md_var("descr", "Helper test case that always passes"); +} +ATF_TEST_CASE_BODY(main) +{ +} + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, main); +} diff --git a/external/bsd/atf/dist/atf-report/reader.cpp b/external/bsd/atf/dist/atf-report/reader.cpp new file mode 100644 index 000000000..8f5fde791 --- /dev/null +++ b/external/bsd/atf/dist/atf-report/reader.cpp @@ -0,0 +1,440 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +extern "C" { +#include +} + +#include +#include +#include + +#include "atf-c/defs.h" + +#include "atf-c++/detail/parser.hpp" +#include "atf-c++/detail/sanity.hpp" +#include "atf-c++/detail/text.hpp" + +#include "reader.hpp" + +namespace impl = atf::atf_report; +#define IMPL_NAME "atf::atf_report" + +// ------------------------------------------------------------------------ +// Auxiliary functions. +// ------------------------------------------------------------------------ + +template< typename Type > +Type +string_to_int(const std::string& str) +{ + std::istringstream ss(str); + Type s; + ss >> s; + + return s; +} + +// ------------------------------------------------------------------------ +// The "atf_tps" auxiliary parser. +// ------------------------------------------------------------------------ + +namespace atf_tps { + +static const atf::parser::token_type eof_type = 0; +static const atf::parser::token_type nl_type = 1; +static const atf::parser::token_type text_type = 2; +static const atf::parser::token_type colon_type = 3; +static const atf::parser::token_type comma_type = 4; +static const atf::parser::token_type tps_count_type = 5; +static const atf::parser::token_type tp_start_type = 6; +static const atf::parser::token_type tp_end_type = 7; +static const atf::parser::token_type tc_start_type = 8; +static const atf::parser::token_type tc_so_type = 9; +static const atf::parser::token_type tc_se_type = 10; +static const atf::parser::token_type tc_end_type = 11; +static const atf::parser::token_type passed_type = 12; +static const atf::parser::token_type failed_type = 13; +static const atf::parser::token_type skipped_type = 14; +static const atf::parser::token_type info_type = 16; +static const atf::parser::token_type expected_death_type = 17; +static const atf::parser::token_type expected_exit_type = 18; +static const atf::parser::token_type expected_failure_type = 19; +static const atf::parser::token_type expected_signal_type = 20; +static const atf::parser::token_type expected_timeout_type = 21; + +class tokenizer : public atf::parser::tokenizer< std::istream > { +public: + tokenizer(std::istream& is, size_t curline) : + atf::parser::tokenizer< std::istream > + (is, true, eof_type, nl_type, text_type, curline) + { + add_delim(':', colon_type); + add_delim(',', comma_type); + add_keyword("tps-count", tps_count_type); + add_keyword("tp-start", tp_start_type); + add_keyword("tp-end", tp_end_type); + add_keyword("tc-start", tc_start_type); + add_keyword("tc-so", tc_so_type); + add_keyword("tc-se", tc_se_type); + add_keyword("tc-end", tc_end_type); + add_keyword("passed", passed_type); + add_keyword("failed", failed_type); + add_keyword("skipped", skipped_type); + add_keyword("info", info_type); + add_keyword("expected_death", expected_death_type); + add_keyword("expected_exit", expected_exit_type); + add_keyword("expected_failure", expected_failure_type); + add_keyword("expected_signal", expected_signal_type); + add_keyword("expected_timeout", expected_timeout_type); + } +}; + +} // namespace atf_tps + +struct timeval +read_timeval(atf::parser::parser< atf_tps::tokenizer >& parser) +{ + using namespace atf_tps; + + atf::parser::token t = parser.expect(text_type, "timestamp"); + const std::string::size_type divider = t.text().find('.'); + if (divider == std::string::npos || divider == 0 || + divider == t.text().length() - 1) + throw atf::parser::parse_error(t.lineno(), + "Malformed timestamp value " + t.text()); + + struct timeval tv; + tv.tv_sec = string_to_int< long >(t.text().substr(0, divider)); + tv.tv_usec = string_to_int< long >(t.text().substr(divider + 1)); + return tv; +} + +// ------------------------------------------------------------------------ +// The "atf_tps_reader" class. +// ------------------------------------------------------------------------ + +impl::atf_tps_reader::atf_tps_reader(std::istream& is) : + m_is(is) +{ +} + +impl::atf_tps_reader::~atf_tps_reader(void) +{ +} + +void +impl::atf_tps_reader::got_info( + const std::string& what ATF_DEFS_ATTRIBUTE_UNUSED, + const std::string& val ATF_DEFS_ATTRIBUTE_UNUSED) +{ +} + +void +impl::atf_tps_reader::got_ntps(size_t ntps ATF_DEFS_ATTRIBUTE_UNUSED) +{ +} + +void +impl::atf_tps_reader::got_tp_start( + const std::string& tp ATF_DEFS_ATTRIBUTE_UNUSED, + size_t ntcs ATF_DEFS_ATTRIBUTE_UNUSED) +{ +} + +void +impl::atf_tps_reader::got_tp_end( + struct timeval* tv ATF_DEFS_ATTRIBUTE_UNUSED, + const std::string& reason ATF_DEFS_ATTRIBUTE_UNUSED) +{ +} + +void +impl::atf_tps_reader::got_tc_start( + const std::string& tcname ATF_DEFS_ATTRIBUTE_UNUSED) +{ +} + +void +impl::atf_tps_reader::got_tc_stdout_line( + const std::string& line ATF_DEFS_ATTRIBUTE_UNUSED) +{ +} + +void +impl::atf_tps_reader::got_tc_stderr_line( + const std::string& line ATF_DEFS_ATTRIBUTE_UNUSED) +{ +} + +void +impl::atf_tps_reader::got_tc_end( + const std::string& state ATF_DEFS_ATTRIBUTE_UNUSED, + struct timeval* tv ATF_DEFS_ATTRIBUTE_UNUSED, + const std::string& reason ATF_DEFS_ATTRIBUTE_UNUSED) +{ +} + +void +impl::atf_tps_reader::got_eof(void) +{ +} + +void +impl::atf_tps_reader::read_info(void* pptr) +{ + using atf::parser::parse_error; + using namespace atf_tps; + + atf::parser::parser< tokenizer >& p = + *reinterpret_cast< atf::parser::parser< tokenizer >* > + (pptr); + + (void)p.expect(colon_type, "`:'"); + + atf::parser::token t = p.expect(text_type, "info property name"); + (void)p.expect(comma_type, "`,'"); + got_info(t.text(), atf::text::trim(p.rest_of_line())); + + (void)p.expect(nl_type, "new line"); +} + +void +impl::atf_tps_reader::read_tp(void* pptr) +{ + using atf::parser::parse_error; + using namespace atf_tps; + + atf::parser::parser< tokenizer >& p = + *reinterpret_cast< atf::parser::parser< tokenizer >* > + (pptr); + + atf::parser::token t = p.expect(tp_start_type, + "start of test program"); + + t = p.expect(colon_type, "`:'"); + + struct timeval s1 = read_timeval(p); + + t = p.expect(comma_type, "`,'"); + + t = p.expect(text_type, "test program name"); + std::string tpname = t.text(); + + t = p.expect(comma_type, "`,'"); + + t = p.expect(text_type, "number of test programs"); + size_t ntcs = string_to_int< std::size_t >(t.text()); + + t = p.expect(nl_type, "new line"); + + ATF_PARSER_CALLBACK(p, got_tp_start(tpname, ntcs)); + + size_t i = 0; + while (p.good() && i < ntcs) { + try { + read_tc(&p); + i++; + } catch (const parse_error& pe) { + p.add_error(pe); + p.reset(nl_type); + } + } + t = p.expect(tp_end_type, "end of test program"); + + t = p.expect(colon_type, "`:'"); + + struct timeval s2 = read_timeval(p); + + struct timeval s3; + timersub(&s2, &s1, &s3); + + t = p.expect(comma_type, "`,'"); + + t = p.expect(text_type, "test program name"); + if (t.text() != tpname) + throw parse_error(t.lineno(), "Test program name used in " + "terminator does not match " + "opening"); + + t = p.expect(nl_type, comma_type, + "new line or comma_type"); + std::string reason; + if (t.type() == comma_type) { + reason = text::trim(p.rest_of_line()); + if (reason.empty()) + throw parse_error(t.lineno(), + "Empty reason for failed test program"); + t = p.next(); + } + + ATF_PARSER_CALLBACK(p, got_tp_end(&s3, reason)); +} + +void +impl::atf_tps_reader::read_tc(void* pptr) +{ + using atf::parser::parse_error; + using namespace atf_tps; + + atf::parser::parser< tokenizer >& p = + *reinterpret_cast< atf::parser::parser< tokenizer >* > + (pptr); + + atf::parser::token t = p.expect(tc_start_type, "start of test case"); + + t = p.expect(colon_type, "`:'"); + + struct timeval s1 = read_timeval(p); + + t = p.expect(comma_type, "`,'"); + + t = p.expect(text_type, "test case name"); + std::string tcname = t.text(); + + ATF_PARSER_CALLBACK(p, got_tc_start(tcname)); + + t = p.expect(nl_type, "new line"); + + t = p.expect(tc_end_type, tc_so_type, tc_se_type, + "end of test case or test case's stdout/stderr line"); + while (t.type() != tc_end_type && + (t.type() == tc_so_type || t.type() == tc_se_type)) { + atf::parser::token t2 = t; + + t = p.expect(colon_type, "`:'"); + + std::string line = p.rest_of_line(); + + if (t2.type() == tc_so_type) { + ATF_PARSER_CALLBACK(p, got_tc_stdout_line(line)); + } else { + INV(t2.type() == tc_se_type); + ATF_PARSER_CALLBACK(p, got_tc_stderr_line(line)); + } + + t = p.expect(nl_type, "new line"); + + t = p.expect(tc_end_type, tc_so_type, tc_se_type, + "end of test case or test case's stdout/stderr line"); + } + + t = p.expect(colon_type, "`:'"); + + struct timeval s2 = read_timeval(p); + + struct timeval s3; + timersub(&s2, &s1, &s3); + + t = p.expect(comma_type, "`,'"); + + t = p.expect(text_type, "test case name"); + if (t.text() != tcname) + throw parse_error(t.lineno(), + "Test case name used in terminator does not " + "match opening"); + + t = p.expect(comma_type, "`,'"); + + t = p.expect(expected_death_type, expected_exit_type, expected_failure_type, + expected_signal_type, expected_timeout_type, passed_type, failed_type, + skipped_type, "expected_{death,exit,failure,signal,timeout}, failed, " + "passed or skipped"); + if (t.type() == passed_type) { + ATF_PARSER_CALLBACK(p, got_tc_end("passed", &s3, "")); + } else { + std::string state; + if (t.type() == expected_death_type) state = "expected_death"; + else if (t.type() == expected_exit_type) state = "expected_exit"; + else if (t.type() == expected_failure_type) state = "expected_failure"; + else if (t.type() == expected_signal_type) state = "expected_signal"; + else if (t.type() == expected_timeout_type) state = "expected_timeout"; + else if (t.type() == failed_type) state = "failed"; + else if (t.type() == skipped_type) state = "skipped"; + else UNREACHABLE; + + t = p.expect(comma_type, "`,'"); + std::string reason = text::trim(p.rest_of_line()); + if (reason.empty()) + throw parse_error(t.lineno(), "Empty reason for " + state + + " test case result"); + ATF_PARSER_CALLBACK(p, got_tc_end(state, &s3, reason)); + } + + t = p.expect(nl_type, "new line"); +} + +void +impl::atf_tps_reader::read(void) +{ + using atf::parser::parse_error; + using namespace atf_tps; + + std::pair< size_t, atf::parser::headers_map > hml = + atf::parser::read_headers(m_is, 1); + atf::parser::validate_content_type(hml.second, "application/X-atf-tps", 3); + + tokenizer tkz(m_is, hml.first); + atf::parser::parser< tokenizer > p(tkz); + + try { + atf::parser::token t; + + while ((t = p.expect(tps_count_type, info_type, "tps-count or info " + "field")).type() == info_type) + read_info(&p); + + t = p.expect(colon_type, "`:'"); + + t = p.expect(text_type, "number of test programs"); + size_t ntps = string_to_int< std::size_t >(t.text()); + ATF_PARSER_CALLBACK(p, got_ntps(ntps)); + + t = p.expect(nl_type, "new line"); + + size_t i = 0; + while (p.good() && i < ntps) { + try { + read_tp(&p); + i++; + } catch (const parse_error& pe) { + p.add_error(pe); + p.reset(nl_type); + } + } + + while ((t = p.expect(eof_type, info_type, "end of stream or info " + "field")).type() == info_type) + read_info(&p); + ATF_PARSER_CALLBACK(p, got_eof()); + } catch (const parse_error& pe) { + p.add_error(pe); + p.reset(nl_type); + } +} diff --git a/external/bsd/atf/dist/atf-report/reader.hpp b/external/bsd/atf/dist/atf-report/reader.hpp new file mode 100644 index 000000000..2ef038a0d --- /dev/null +++ b/external/bsd/atf/dist/atf-report/reader.hpp @@ -0,0 +1,91 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#if !defined(_ATF_REPORT_FORMATS_HPP_) +#define _ATF_REPORT_FORMATS_HPP_ + +extern "C" { +#include +} + +#include +#include + +#include + +namespace atf { +namespace atf_report { + +struct test_case_result { + enum state_enum { + PASSED, + FAILED, + SKIPPED, + }; + const state_enum state; + const std::string& reason; + + test_case_result(const state_enum p_state, const std::string& p_reason) : + state(p_state), + reason(p_reason) + { + } +}; + +class atf_tps_reader { + std::istream& m_is; + + void read_info(void*); + void read_tp(void*); + void read_tc(void*); + +protected: + virtual void got_info(const std::string&, const std::string&); + virtual void got_ntps(size_t); + virtual void got_tp_start(const std::string&, size_t); + virtual void got_tp_end(struct timeval*, const std::string&); + + virtual void got_tc_start(const std::string&); + virtual void got_tc_stdout_line(const std::string&); + virtual void got_tc_stderr_line(const std::string&); + virtual void got_tc_end(const std::string&, struct timeval*, + const std::string&); + virtual void got_eof(void); + +public: + atf_tps_reader(std::istream&); + virtual ~atf_tps_reader(void); + + void read(void); +}; + +} // namespace atf_report +} // namespace atf + +#endif // !defined(_ATF_REPORT_FORMATS_HPP_) diff --git a/external/bsd/atf/dist/atf-report/reader_test.cpp b/external/bsd/atf/dist/atf-report/reader_test.cpp new file mode 100644 index 000000000..59e4059ef --- /dev/null +++ b/external/bsd/atf/dist/atf-report/reader_test.cpp @@ -0,0 +1,989 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2010 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#include +#include +#include +#include +#include + +#include "atf-c++/macros.hpp" + +#include "atf-c++/detail/parser.hpp" +#include "atf-c++/detail/sanity.hpp" +#include "atf-c++/detail/test_helpers.hpp" +#include "atf-c++/detail/text.hpp" + +#include "reader.hpp" + +namespace impl = atf::atf_report; + +class tps_reader : protected impl::atf_tps_reader { + void + got_info(const std::string& what, const std::string& val) + { + m_calls.push_back("got_info(" + what + ", " + val + ")"); + } + + void + got_ntps(size_t ntps) + { + m_calls.push_back("got_ntps(" + atf::text::to_string(ntps) + ")"); + } + + void + got_tp_start(const std::string& tpname, size_t ntcs) + { + m_calls.push_back("got_tp_start(" + tpname + ", " + + atf::text::to_string(ntcs) + ")"); + } + + void + got_tp_end(struct timeval* tv ATF_DEFS_ATTRIBUTE_UNUSED, + const std::string& reason) + { + m_calls.push_back("got_tp_end(" + reason + ")"); + } + + void + got_tc_start(const std::string& tcname) + { + m_calls.push_back("got_tc_start(" + tcname + ")"); + } + + void + got_tc_end(const std::string& state, + struct timeval* tv ATF_DEFS_ATTRIBUTE_UNUSED, + const std::string& reason) + { + const std::string r = state + (reason.empty() ? "" : ", " + reason); + m_calls.push_back("got_tc_end(" + r + ")"); + } + + void + got_tc_stdout_line(const std::string& line) + { + m_calls.push_back("got_tc_stdout_line(" + line + ")"); + } + + void + got_tc_stderr_line(const std::string& line) + { + m_calls.push_back("got_tc_stderr_line(" + line + ")"); + } + + void + got_eof(void) + { + m_calls.push_back("got_eof()"); + } + +public: + tps_reader(std::istream& is) : + impl::atf_tps_reader(is) + { + } + + void + read(void) + { + atf_tps_reader::read(); + } + + std::vector< std::string > m_calls; +}; + +ATF_TEST_CASE_WITHOUT_HEAD(tps_1); +ATF_TEST_CASE_BODY(tps_1) +{ + const char* input = + "Content-Type: application/X-atf-tps; version=\"3\"\n" + "\n" + "tps-count: 0\n" + ; + + const char* exp_calls[] = { + "got_ntps(0)", + "got_eof()", + NULL + }; + + const char* exp_errors[] = { + NULL + }; + + do_parser_test< tps_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(tps_2); +ATF_TEST_CASE_BODY(tps_2) +{ + const char* input = + "Content-Type: application/X-atf-tps; version=\"3\"\n" + "\n" + "tps-count: 2\n" + "tp-start: 123.456, first-prog, 0\n" + "tp-end: 123.567, first-prog\n" + "tp-start: 123.678, second-prog, 0\n" + "tp-end: 123.789, second-prog, This program failed\n" + ; + + const char* exp_calls[] = { + "got_ntps(2)", + "got_tp_start(first-prog, 0)", + "got_tp_end()", + "got_tp_start(second-prog, 0)", + "got_tp_end(This program failed)", + "got_eof()", + NULL + }; + + const char* exp_errors[] = { + NULL + }; + + do_parser_test< tps_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(tps_3); +ATF_TEST_CASE_BODY(tps_3) +{ + const char* input = + "Content-Type: application/X-atf-tps; version=\"3\"\n" + "\n" + "tps-count: 2\n" + "tp-start: 123.123, first-prog, 3\n" + "tc-start: 123.234, first-test\n" + "tc-end: 123.345, first-test, passed\n" + "tc-start: 123.456, second-test\n" + "tc-end: 123.567, second-test, skipped, Testing skipped reason\n" + "tc-start: 123.678, third.test\n" + "tc-end: 123.789, third.test, failed, Testing failed reason\n" + "tp-end: 123.890, first-prog\n" + "tp-start: 124.901, second-prog, 3\n" + "tc-start: 124.1012, first-test\n" + "tc-so:first stdout line for 1st test\n" + "tc-se:first stderr line for 1st test\n" + "tc-so:second stdout line for 1st test\n" + "tc-se:second stderr line for 1st test\n" + "tc-end: 124.1123, first-test, passed\n" + "tc-start: 124.1234, second-test\n" + "tc-so:first stdout line for 2nd test\n" + "tc-se:first stderr line for 2nd test\n" + "tc-so:second stdout line for 2nd test\n" + "tc-se:second stderr line for 2nd test\n" + "tc-end: 124.1345, second-test, skipped, Testing skipped reason\n" + "tc-start: 124.1456, third.test\n" + "tc-so:first stdout line for 3rd test\n" + "tc-se:first stderr line for 3rd test\n" + "tc-so:second stdout line for 3rd test\n" + "tc-se:second stderr line for 3rd test\n" + "tc-end: 124.1567, third.test, failed, Testing failed reason\n" + "tp-end: 124.1678, second-prog, This program failed\n" + ; + + const char* exp_calls[] = { + "got_ntps(2)", + "got_tp_start(first-prog, 3)", + "got_tc_start(first-test)", + "got_tc_end(passed)", + "got_tc_start(second-test)", + "got_tc_end(skipped, Testing skipped reason)", + "got_tc_start(third.test)", + "got_tc_end(failed, Testing failed reason)", + "got_tp_end()", + "got_tp_start(second-prog, 3)", + "got_tc_start(first-test)", + "got_tc_stdout_line(first stdout line for 1st test)", + "got_tc_stderr_line(first stderr line for 1st test)", + "got_tc_stdout_line(second stdout line for 1st test)", + "got_tc_stderr_line(second stderr line for 1st test)", + "got_tc_end(passed)", + "got_tc_start(second-test)", + "got_tc_stdout_line(first stdout line for 2nd test)", + "got_tc_stderr_line(first stderr line for 2nd test)", + "got_tc_stdout_line(second stdout line for 2nd test)", + "got_tc_stderr_line(second stderr line for 2nd test)", + "got_tc_end(skipped, Testing skipped reason)", + "got_tc_start(third.test)", + "got_tc_stdout_line(first stdout line for 3rd test)", + "got_tc_stderr_line(first stderr line for 3rd test)", + "got_tc_stdout_line(second stdout line for 3rd test)", + "got_tc_stderr_line(second stderr line for 3rd test)", + "got_tc_end(failed, Testing failed reason)", + "got_tp_end(This program failed)", + "got_eof()", + NULL + }; + + const char* exp_errors[] = { + NULL + }; + + do_parser_test< tps_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(tps_4); +ATF_TEST_CASE_BODY(tps_4) +{ + const char* input = + "Content-Type: application/X-atf-tps; version=\"3\"\n" + "\n" + "info: a, foo\n" + "info: b, bar\n" + "info: c, baz\n" + "tps-count: 2\n" + "tp-start: 234.1, first-prog, 3\n" + "tc-start: 234.12, first-test\n" + "tc-end: 234.23, first-test, passed\n" + "tc-start: 234.34, second-test\n" + "tc-end: 234.45, second-test, skipped, Testing skipped reason\n" + "tc-start: 234.56, third-test\n" + "tc-end: 234.67, third-test, failed, Testing failed reason\n" + "tp-end: 234.78, first-prog\n" + "tp-start: 234.89, second-prog, 3\n" + "tc-start: 234.90, first-test\n" + "tc-so:first stdout line for 1st test\n" + "tc-se:first stderr line for 1st test\n" + "tc-so:second stdout line for 1st test\n" + "tc-se:second stderr line for 1st test\n" + "tc-end: 234.101, first-test, passed\n" + "tc-start: 234.112, second-test\n" + "tc-so:first stdout line for 2nd test\n" + "tc-se:first stderr line for 2nd test\n" + "tc-so:second stdout line for 2nd test\n" + "tc-se:second stderr line for 2nd test\n" + "tc-end: 234.123, second-test, skipped, Testing skipped reason\n" + "tc-start: 234.134, third-test\n" + "tc-so:first stdout line for 3rd test\n" + "tc-se:first stderr line for 3rd test\n" + "tc-so:second stdout line for 3rd test\n" + "tc-se:second stderr line for 3rd test\n" + "tc-end: 234.145, third-test, failed, Testing failed reason\n" + "tp-end: 234.156, second-prog, This program failed\n" + "info: d, foo\n" + "info: e, bar\n" + "info: f, baz\n" + ; + + const char* exp_calls[] = { + "got_info(a, foo)", + "got_info(b, bar)", + "got_info(c, baz)", + "got_ntps(2)", + "got_tp_start(first-prog, 3)", + "got_tc_start(first-test)", + "got_tc_end(passed)", + "got_tc_start(second-test)", + "got_tc_end(skipped, Testing skipped reason)", + "got_tc_start(third-test)", + "got_tc_end(failed, Testing failed reason)", + "got_tp_end()", + "got_tp_start(second-prog, 3)", + "got_tc_start(first-test)", + "got_tc_stdout_line(first stdout line for 1st test)", + "got_tc_stderr_line(first stderr line for 1st test)", + "got_tc_stdout_line(second stdout line for 1st test)", + "got_tc_stderr_line(second stderr line for 1st test)", + "got_tc_end(passed)", + "got_tc_start(second-test)", + "got_tc_stdout_line(first stdout line for 2nd test)", + "got_tc_stderr_line(first stderr line for 2nd test)", + "got_tc_stdout_line(second stdout line for 2nd test)", + "got_tc_stderr_line(second stderr line for 2nd test)", + "got_tc_end(skipped, Testing skipped reason)", + "got_tc_start(third-test)", + "got_tc_stdout_line(first stdout line for 3rd test)", + "got_tc_stderr_line(first stderr line for 3rd test)", + "got_tc_stdout_line(second stdout line for 3rd test)", + "got_tc_stderr_line(second stderr line for 3rd test)", + "got_tc_end(failed, Testing failed reason)", + "got_tp_end(This program failed)", + "got_info(d, foo)", + "got_info(e, bar)", + "got_info(f, baz)", + "got_eof()", + NULL + }; + + const char* exp_errors[] = { + NULL + }; + + do_parser_test< tps_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(tps_5); +ATF_TEST_CASE_BODY(tps_5) +{ + const char* input = + "Content-Type: application/X-atf-tps; version=\"3\"\n" + "\n" + "tps-count: 1\n" + "tp-start: 345.123, the-prog, 1\n" + "tc-start: 345.134, the-test\n" + "tc-so:--- a 2007-11-04 14:00:41.000000000 +0100\n" + "tc-so:+++ b 2007-11-04 14:00:48.000000000 +0100\n" + "tc-so:@@ -1,7 +1,7 @@\n" + "tc-so: This test is meant to simulate a diff.\n" + "tc-so: Blank space at beginning of context lines must be preserved.\n" + "tc-so: \n" + "tc-so:-First original line.\n" + "tc-so:-Second original line.\n" + "tc-so:+First modified line.\n" + "tc-so:+Second modified line.\n" + "tc-so: \n" + "tc-so: EOF\n" + "tc-end: 345.145, the-test, passed\n" + "tp-end: 345.156, the-prog\n" + ; + + // NO_CHECK_STYLE_BEGIN + const char* exp_calls[] = { + "got_ntps(1)", + "got_tp_start(the-prog, 1)", + "got_tc_start(the-test)", + "got_tc_stdout_line(--- a 2007-11-04 14:00:41.000000000 +0100)", + "got_tc_stdout_line(+++ b 2007-11-04 14:00:48.000000000 +0100)", + "got_tc_stdout_line(@@ -1,7 +1,7 @@)", + "got_tc_stdout_line( This test is meant to simulate a diff.)", + "got_tc_stdout_line( Blank space at beginning of context lines must be preserved.)", + "got_tc_stdout_line( )", + "got_tc_stdout_line(-First original line.)", + "got_tc_stdout_line(-Second original line.)", + "got_tc_stdout_line(+First modified line.)", + "got_tc_stdout_line(+Second modified line.)", + "got_tc_stdout_line( )", + "got_tc_stdout_line( EOF)", + "got_tc_end(passed)", + "got_tp_end()", + "got_eof()", + NULL + }; + // NO_CHECK_STYLE_END + + const char* exp_errors[] = { + NULL + }; + + do_parser_test< tps_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(tps_6); +ATF_TEST_CASE_BODY(tps_6) +{ + const char* input = + "Content-Type: application/X-atf-tps; version=\"3\"\n" + "\n" + "tps-count: 1\n" + "tp-start: 321.1, the-prog, 8\n" + "tc-start: 321.12, one\n" + "tc-end: 321.23, one, expected_death, The reason\n" + "tc-start: 321.34, two\n" + "tc-end: 321.45, two, expected_exit, This would be an exit\n" + "tc-start: 321.56, three\n" + "tc-end: 321.67, three, expected_failure, And this a failure\n" + "tc-start: 321.78, four\n" + "tc-end: 321.89, four, expected_signal, And this a signal\n" + "tc-start: 321.90, five\n" + "tc-end: 321.101, five, failed, Another reason\n" + "tc-start: 321.112, six\n" + "tc-end: 321.123, six, passed\n" + "tc-start: 321.134, seven\n" + "tc-end: 321.145, seven, skipped, Skipping it\n" + "tc-start: 321.156, eight\n" + "tc-end: 321.167, eight, expected_timeout, Some hang reason\n" + "tp-end: 321.178, the-prog\n" + ; + + // NO_CHECK_STYLE_BEGIN + const char* exp_calls[] = { + "got_ntps(1)", + "got_tp_start(the-prog, 8)", + "got_tc_start(one)", + "got_tc_end(expected_death, The reason)", + "got_tc_start(two)", + "got_tc_end(expected_exit, This would be an exit)", + "got_tc_start(three)", + "got_tc_end(expected_failure, And this a failure)", + "got_tc_start(four)", + "got_tc_end(expected_signal, And this a signal)", + "got_tc_start(five)", + "got_tc_end(failed, Another reason)", + "got_tc_start(six)", + "got_tc_end(passed)", + "got_tc_start(seven)", + "got_tc_end(skipped, Skipping it)", + "got_tc_start(eight)", + "got_tc_end(expected_timeout, Some hang reason)", + "got_tp_end()", + "got_eof()", + NULL + }; + // NO_CHECK_STYLE_END + + const char* exp_errors[] = { + NULL + }; + + do_parser_test< tps_reader >(input, exp_calls, exp_errors); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(tps_50); +ATF_TEST_CASE_BODY(tps_50) +{ + const char* input = + "Content-Type: application/X-atf-tps; version=\"3\"\n" + "\n" + "foo\n" + ; + + const char* exp_calls[] = { + NULL + }; + + const char* exp_errors[] = { + "3: Unexpected token `foo'; expected tps-count or info field", + NULL + }; + + do_parser_test< tps_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(tps_51); +ATF_TEST_CASE_BODY(tps_51) +{ + const char* input = + "Content-Type: application/X-atf-tps; version=\"3\"\n" + "\n" + "tps-count\n" + ; + + const char* exp_calls[] = { + NULL + }; + + const char* exp_errors[] = { + "3: Unexpected token `<>'; expected `:'", + NULL + }; + + do_parser_test< tps_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(tps_52); +ATF_TEST_CASE_BODY(tps_52) +{ + const char* input = + "Content-Type: application/X-atf-tps; version=\"3\"\n" + "\n" + "tps-count:\n" + ; + + const char* exp_calls[] = { + NULL + }; + + const char* exp_errors[] = { + "3: Unexpected token `<>'; expected number of test programs", + NULL + }; + + do_parser_test< tps_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(tps_53); +ATF_TEST_CASE_BODY(tps_53) +{ + const char* input = + "Content-Type: application/X-atf-tps; version=\"3\"\n" + "\n" + "tps-count: 1\n" + "foo\n" + ; + + const char* exp_calls[] = { + "got_ntps(1)", + NULL + }; + + const char* exp_errors[] = { + "4: Unexpected token `foo'; expected start of test program", + NULL + }; + + do_parser_test< tps_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(tps_54); +ATF_TEST_CASE_BODY(tps_54) +{ + const char* input = + "Content-Type: application/X-atf-tps; version=\"3\"\n" + "\n" + "tps-count: 1\n" + "foo\n" + "tp-start\n" + "tp-start:\n" + "tp-start: 123\n" + "tp-start: 123.\n" + "tp-start: 123.456\n" + "tp-start: 123.456,\n" + "tp-start: 123.456, foo\n" + "tp-start: 123.456, foo,\n" + "tp-start: 123.456, foo, 0\n" + "bar\n" + "tp-start: 456.789, foo, 0\n" + "tp-end\n" + "tp-start: 777.777, foo, 0\n" + "tp-end:\n" + "tp-start: 777.777, foo, 0\n" + "tp-end: 777\n" + "tp-start: 777.777, foo, 0\n" + "tp-end: 777.\n" + "tp-start: 777.777, foo, 0\n" + "tp-end: 777.888\n" + "tp-start: 777.777, foo, 0\n" + "tp-end: 777.888, \n" + "tp-start: 777.777, foo, 0\n" + "tp-end: 777.888, bar\n" + "tp-start: 777.777, foo, 0\n" + "tp-end: 777.888, foo,\n" + ; + + const char* exp_calls[] = { + "got_ntps(1)", + NULL + }; + + const char* exp_errors[] = { + "4: Unexpected token `foo'; expected start of test program", + "5: Unexpected token `<>'; expected `:'", + "6: Unexpected token `<>'; expected timestamp", + "7: Malformed timestamp value 123", + "8: Malformed timestamp value 123.", + "9: Unexpected token `<>'; expected `,'", + "10: Unexpected token `<>'; expected test program name", + "11: Unexpected token `<>'; expected `,'", + "12: Unexpected token `<>'; expected number of test programs", + "14: Unexpected token `bar'; expected end of test program", + "16: Unexpected token `<>'; expected `:'", + "18: Unexpected token `<>'; expected timestamp", + "20: Malformed timestamp value 777", + "22: Malformed timestamp value 777.", + "24: Unexpected token `<>'; expected `,'", + + "26: Unexpected token `<>'; expected test program name", + "28: Test program name used in terminator does not match opening", + "30: Empty reason for failed test program", + NULL + }; + + do_parser_test< tps_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(tps_55); +ATF_TEST_CASE_BODY(tps_55) +{ + const char* input = + "Content-Type: application/X-atf-tps; version=\"3\"\n" + "\n" + "tps-count: 1\n" + "tp-start: 100.200, foo, 1\n" + "foo\n" + "tc-start\n" + "tc-start:\n" + "tc-start: 111\n" + "tc-start: 111.\n" + "tc-start: 111.222\n" + "tc-start: 111.222,\n" + "tc-start: 111.222, foo\n" + "bar\n" + "tc-start: 111.333, foo\n" + "tc-end\n" + "tc-start: 111.444, foo\n" + "tc-end:\n" + "tc-start: 111.444, foo\n" + "tc-end: 111\n" + "tc-start: 111.444, foo\n" + "tc-end: 111.\n" + "tc-start: 111.444, foo\n" + "tc-end: 111.555\n" + "tc-start: 111.444, foo\n" + "tc-end: 111.555, \n" + "tc-start: 111.444, foo\n" + "tc-end: 111.555, bar\n" + "tc-start: 111.444, foo\n" + "tc-end: 111.555, foo\n" + "tc-start: 111.444, foo\n" + "tc-end: 111.555, foo,\n" + "tp-end: 111.666, foo\n" + ; + + const char* exp_calls[] = { + "got_ntps(1)", + "got_tp_start(foo, 1)", + NULL + }; + + // NO_CHECK_STYLE_BEGIN + const char* exp_errors[] = { + "5: Unexpected token `foo'; expected start of test case", + "6: Unexpected token `<>'; expected `:'", + "7: Unexpected token `<>'; expected timestamp", + "8: Malformed timestamp value 111", + "9: Malformed timestamp value 111.", + "10: Unexpected token `<>'; expected `,'", + "11: Unexpected token `<>'; expected test case name", + "13: Unexpected token `bar'; expected end of test case or test case's stdout/stderr line", + "15: Unexpected token `<>'; expected `:'", + "17: Unexpected token `<>'; expected timestamp", + "19: Malformed timestamp value 111", + "21: Malformed timestamp value 111.", + "23: Unexpected token `<>'; expected `,'", + "25: Unexpected token `<>'; expected test case name", + "27: Test case name used in terminator does not match opening", + "29: Unexpected token `<>'; expected `,'", + "31: Unexpected token `<>'; expected expected_{death,exit,failure,signal,timeout}, failed, passed or skipped", + "32: Unexpected token `tp-end'; expected start of test case", + NULL + }; + // NO_CHECK_STYLE_END + + do_parser_test< tps_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(tps_56); +ATF_TEST_CASE_BODY(tps_56) +{ + const char* input = + "Content-Type: application/X-atf-tps; version=\"3\"\n" + "\n" + "tps-count: 1\n" + "tp-start: 111.222, foo, 1\n" + "tc-start: 111.333, foo\n" + "tc-end: 111.444, foo, passe\n" + "tc-start: 111.333, foo\n" + "tc-end: 111.444, foo, passed,\n" + "tc-start: 111.555, bar\n" + "tc-end: 111.666, bar, failed\n" + "tc-start: 111.555, bar\n" + "tc-end: 111.666, bar, failed,\n" + "tc-start: 111.555, baz\n" + "tc-end: 111.666, baz, skipped\n" + "tc-start: 111.555, baz\n" + "tc-end: 111.666, baz, skipped,\n" + "tp-end: 111.777, foo\n" + ; + + const char* exp_calls[] = { + "got_ntps(1)", + "got_tp_start(foo, 1)", + "got_tc_start(foo)", + NULL + }; + + // NO_CHECK_STYLE_BEGIN + const char* exp_errors[] = { + "6: Unexpected token `passe'; expected expected_{death,exit,failure,signal,timeout}, failed, passed or skipped", + "8: Unexpected token `,'; expected new line", + "10: Unexpected token `<>'; expected `,'", + "12: Empty reason for failed test case result", + "14: Unexpected token `<>'; expected `,'", + "16: Empty reason for skipped test case result", + "17: Unexpected token `tp-end'; expected start of test case", + NULL + }; + // NO_CHECK_STYLE_END + + do_parser_test< tps_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(tps_57); +ATF_TEST_CASE_BODY(tps_57) +{ + const char* input = + "Content-Type: application/X-atf-tps; version=\"3\"\n" + "\n" + "tps-count: 2\n" + "tp-start: 111.222, foo, 0\n" + "tp-end: 111.333, foo\n" + ; + + const char* exp_calls[] = { + "got_ntps(2)", + "got_tp_start(foo, 0)", + "got_tp_end()", + NULL + }; + + const char* exp_errors[] = { + "6: Unexpected token `<>'; expected start of test program", + NULL + }; + + do_parser_test< tps_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(tps_58); +ATF_TEST_CASE_BODY(tps_58) +{ + const char* input = + "Content-Type: application/X-atf-tps; version=\"3\"\n" + "\n" + "tps-count: 1\n" + "tp-start: 111.222, foo, 0\n" + "tp-end: 111.333, foo\n" + "tp-start: 111.444, bar, 0\n" + "tp-end: 111.555, bar\n" + ; + + const char* exp_calls[] = { + "got_ntps(1)", + "got_tp_start(foo, 0)", + "got_tp_end()", + NULL + }; + + const char* exp_errors[] = { + "6: Unexpected token `tp-start'; expected end of stream or info field", + NULL + }; + + do_parser_test< tps_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(tps_59); +ATF_TEST_CASE_BODY(tps_59) +{ + const char* input = + "Content-Type: application/X-atf-tps; version=\"3\"\n" + "\n" + "info\n" + ; + + const char* exp_calls[] = { + NULL + }; + + const char* exp_errors[] = { + "3: Unexpected token `<>'; expected `:'", + NULL + }; + + do_parser_test< tps_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(tps_60); +ATF_TEST_CASE_BODY(tps_60) +{ + const char* input = + "Content-Type: application/X-atf-tps; version=\"3\"\n" + "\n" + "info:\n" + ; + + const char* exp_calls[] = { + NULL + }; + + const char* exp_errors[] = { + "3: Unexpected token `<>'; expected info property name", + NULL + }; + + do_parser_test< tps_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(tps_61); +ATF_TEST_CASE_BODY(tps_61) +{ + const char* input = + "Content-Type: application/X-atf-tps; version=\"3\"\n" + "\n" + "info: a\n" + ; + + const char* exp_calls[] = { + NULL + }; + + const char* exp_errors[] = { + "3: Unexpected token `<>'; expected `,'", + NULL + }; + + do_parser_test< tps_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(tps_62); +ATF_TEST_CASE_BODY(tps_62) +{ + const char* input = + "Content-Type: application/X-atf-tps; version=\"3\"\n" + "\n" + "info: a,\n" + ; + + const char* exp_calls[] = { + "got_info(a, )", + NULL + }; + + const char* exp_errors[] = { + "4: Unexpected token `<>'; expected tps-count or info field", + NULL + }; + + do_parser_test< tps_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(tps_63); +ATF_TEST_CASE_BODY(tps_63) +{ + const char* input = + "Content-Type: application/X-atf-tps; version=\"3\"\n" + "\n" + "info: a, b\n" + ; + + const char* exp_calls[] = { + "got_info(a, b)", + NULL + }; + + const char* exp_errors[] = { + "4: Unexpected token `<>'; expected tps-count or info field", + NULL + }; + + do_parser_test< tps_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(tps_64); +ATF_TEST_CASE_BODY(tps_64) +{ + const char* input = + "Content-Type: application/X-atf-tps; version=\"3\"\n" + "\n" + "info: a, b\n" + "info: a.b.c.def, g\n" + "tps-count\n" + ; + + const char* exp_calls[] = { + "got_info(a, b)", + "got_info(a.b.c.def, g)", + NULL + }; + + const char* exp_errors[] = { + "5: Unexpected token `<>'; expected `:'", + NULL + }; + + do_parser_test< tps_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(tps_65); +ATF_TEST_CASE_BODY(tps_65) +{ + const char* input = + "Content-Type: application/X-atf-tps; version=\"3\"\n" + "\n" + "info: a, b\n" + "tps-count:\n" + ; + + const char* exp_calls[] = { + "got_info(a, b)", + NULL + }; + + const char* exp_errors[] = { + "4: Unexpected token `<>'; expected number of test programs", + NULL + }; + + do_parser_test< tps_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(tps_66); +ATF_TEST_CASE_BODY(tps_66) +{ + const char* input = + "Content-Type: application/X-atf-tps; version=\"3\"\n" + "\n" + "info: a, b\n" + "tps-count: 0\n" + "info\n" + ; + + const char* exp_calls[] = { + "got_info(a, b)", + "got_ntps(0)", + NULL + }; + + const char* exp_errors[] = { + "5: Unexpected token `<>'; expected `:'", + NULL + }; + + do_parser_test< tps_reader >(input, exp_calls, exp_errors); +} + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, tps_1); + ATF_ADD_TEST_CASE(tcs, tps_2); + ATF_ADD_TEST_CASE(tcs, tps_3); + ATF_ADD_TEST_CASE(tcs, tps_4); + ATF_ADD_TEST_CASE(tcs, tps_5); + ATF_ADD_TEST_CASE(tcs, tps_6); + ATF_ADD_TEST_CASE(tcs, tps_50); + ATF_ADD_TEST_CASE(tcs, tps_51); + ATF_ADD_TEST_CASE(tcs, tps_52); + ATF_ADD_TEST_CASE(tcs, tps_53); + ATF_ADD_TEST_CASE(tcs, tps_54); + ATF_ADD_TEST_CASE(tcs, tps_55); + ATF_ADD_TEST_CASE(tcs, tps_56); + ATF_ADD_TEST_CASE(tcs, tps_57); + ATF_ADD_TEST_CASE(tcs, tps_58); + ATF_ADD_TEST_CASE(tcs, tps_59); + ATF_ADD_TEST_CASE(tcs, tps_60); + ATF_ADD_TEST_CASE(tcs, tps_61); + ATF_ADD_TEST_CASE(tcs, tps_62); + ATF_ADD_TEST_CASE(tcs, tps_63); + ATF_ADD_TEST_CASE(tcs, tps_64); + ATF_ADD_TEST_CASE(tcs, tps_65); + ATF_ADD_TEST_CASE(tcs, tps_66); +} + diff --git a/external/bsd/atf/dist/atf-report/tests-results.css b/external/bsd/atf/dist/atf-report/tests-results.css new file mode 100644 index 000000000..24fc12cbf --- /dev/null +++ b/external/bsd/atf/dist/atf-report/tests-results.css @@ -0,0 +1,199 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2007 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +body { + margin: 0 0 0 0; +} + +.nobr { + white-space: nowrap; +} + +h1 { + background: black; + color: white; + font-family: Arial; + font-size: 24pt; + padding: 5pt; +} + +h2 { + background: #eeeeee; + font-family: Arial; + font-size: 16pt; + margin-left: 10pt; + margin-right: 10pt; + padding: 3pt; +} + +h3 { + font-family: Arial; + font-size: 12pt; + margin-left: 20pt; + margin-right: 20pt; + padding: 3pt; +} + +p.details { + margin-left: 20pt; + margin-right: 20pt; +} + +p.term { + margin-left: 40pt; + margin-right: 40pt; +} + +pre.so { + margin-left: 40pt; + margin-right: 40pt; +} + +pre.se { + margin-left: 40pt; + margin-right: 40pt; +} + +table.summary { + border-collapse: collapse; + border-color: black; + border-style: solid; + border-width: 1pt; + margin-left: auto; + margin-right: auto; +} + +table.summary th { + background: #aaaadd; + border-style: solid; + border-width: 1pt; + padding: 3pt 6pt 3pt 6pt; +} + +table.summary td { + border-style: solid; + border-width: 1pt; + padding: 3pt 6pt 3pt 6pt; +} + +table.summary td.numeric p { + text-align: right; +} + +table.summary td.numeric-error p { + text-align: right; + color: red; +} + +table.summary td.numeric-warning p { + text-align: right; + color: #aaaa00; +} + +table.summary tr.group { + background: #dddddd; +} + +table.summary tr.entry td p { + margin-left: 10pt; +} + +table.tcs-summary { + border-collapse: collapse; + border-color: black; + border-style: solid; + border-width: 1pt; + margin-left: auto; + margin-right: auto; + width: 80%; +} + +table.tcs-summary td { + border-style: solid; + border-width: 1pt; + padding: 3pt 6pt 3pt 6pt; +} + +table.tcs-summary th { + background: #aaaadd; + border-style: solid; + border-width: 1pt; + padding: 3pt 6pt 3pt 6pt; +} + +table.tcs-summary td.numeric { + width: 1pt; +} + +table.tcs-summary td.numeric p { + text-align: right; +} + +table.tcs-summary td.tp-numeric { + background: #dddddd; + width: 1pt; +} + +table.tcs-summary td.tp-numeric p { + text-align: right; +} + +table.tcs-summary td.tp-id { + background: #dddddd; + font-weight: bold; + width: 1pt; +} + +table.tcs-summary td.tc-id p { + margin-left: 10pt; +} + +table.tcs-summary td.tcr-passed { + background: #aaffaa; + width: 1pt; +} + +table.tcs-summary td.tcr-failed { + background: #ffaaaa; + width: 1pt; +} + +table.tcs-summary td.tcr-skipped { + background: #ffffaa; + width: 1pt; +} + +table.tcs-summary td.tcr-xfail { + background: #ffaaff; + width: 1pt; +} + +table.tcs-summary td.tcr-reason { + width: 100%; +} diff --git a/external/bsd/atf/dist/atf-report/tests-results.dtd b/external/bsd/atf/dist/atf-report/tests-results.dtd new file mode 100644 index 000000000..c16f7edfb --- /dev/null +++ b/external/bsd/atf/dist/atf-report/tests-results.dtd @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/external/bsd/atf/dist/atf-report/tests-results.xsl b/external/bsd/atf/dist/atf-report/tests-results.xsl new file mode 100644 index 000000000..91b77c543 --- /dev/null +++ b/external/bsd/atf/dist/atf-report/tests-results.xsl @@ -0,0 +1,564 @@ + +]> + + + + + + + tests-results.css + ATF Tests Results + + + + + + + + + + + + + + + + + + + + + + <xsl:value-of select="$global.title" /> + + + +

+ + + + + + + + + + + + + + + + + + + + +
+ + +

Execution summary

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Item

Value

ATF

Version

Timings

Start time of tests

End time of tests

System information

Host name

Operating system

Operating system release

Operating system version

Platform

Tests results

Root

Test programs

Bogus test + programs

+

+

Bogus test programs

+

+

Test cases

Passed test cases

Failed test + cases

+

+

Failed test cases

+

+

Expected + failures

+

+

Expected failures

+

+

Skipped test + cases

+

+

Skipped test cases

+

+

See more execution + details

+
+ + + +

Execution details

+ +

Environment variables

+ +
    + + + +
+
+ + +
  • +

    +
  • +
    + + +

    Test cases summary

    + + + + + + + + + + all + +

    Test case

    Result

    Reason

    Duration

    +
    + + +
    +

    Expected failures summary

    + + + + + + + + + + xfail + +

    Test case

    Result

    Reason

    Duration

    + + + +
    +

    Failed test cases summary

    + + + + + + + + + + failed + +

    Test case

    Result

    Reason

    Duration

    + + + +
    +

    Bogus test programs summary

    + + + + + + + bogus + +
    Test program
    + + + +
    +

    Skipped test cases summary

    + + + + + + + + + + skipped + +

    Test case

    Result

    Reason

    Duration

    + + + + + + + + yes + yes + yes + yes + yes + yes + yes + yes + yes + yes + no + + + + + + +

    + + +

    s

    + + + + + + + +
    +
    + + + + + + + + + yes + yes + yes + yes + yes + yes + yes + yes + yes + no + + + + + + + + +

    + + +

    +
    + + + + +

    s

    + + + + + + +

    Passed

    +

    N/A

    +
    + + +

    Expected death

    +

    +
    + + +

    Expected exit

    +

    +
    + + +

    Expected failure

    +

    +
    + + +

    Expected timeout

    +

    +
    + + +

    Expected signal

    +

    +
    + + +

    Failed

    +

    +
    + + +

    Skipped

    +

    +
    + + + + + + +

    FAILED:

    +
    + + +

    XFAIL:

    +
    + + +

    SKIPPED:

    +
    + + + + + +

    Test case: + / +

    + + +

    Duration: +

    +
    + +

    Termination reason

    + + + +

    Standard output stream

    +
    +
    + + +

    Standard error stream

    +
    +
    +
    + + + seconds + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/external/bsd/atf/dist/atf-run/Atffile b/external/bsd/atf/dist/atf-run/Atffile new file mode 100644 index 000000000..146211e00 --- /dev/null +++ b/external/bsd/atf/dist/atf-run/Atffile @@ -0,0 +1,5 @@ +Content-Type: application/X-atf-atffile; version="1" + +prop: test-suite = atf + +tp-glob: *_test diff --git a/external/bsd/atf/dist/atf-run/Kyuafile b/external/bsd/atf/dist/atf-run/Kyuafile new file mode 100644 index 000000000..305d699e1 --- /dev/null +++ b/external/bsd/atf/dist/atf-run/Kyuafile @@ -0,0 +1,13 @@ +syntax("kyuafile", 1) + +test_suite("atf") + +atf_test_program{name="atffile_test"} +atf_test_program{name="config_test"} +atf_test_program{name="fs_test"} +atf_test_program{name="integration_test"} +atf_test_program{name="io_test"} +atf_test_program{name="requirements_test"} +atf_test_program{name="signals_test"} +atf_test_program{name="test_program_test"} +atf_test_program{name="user_test"} diff --git a/external/bsd/atf/dist/atf-run/atf-run.1 b/external/bsd/atf/dist/atf-run/atf-run.1 new file mode 100644 index 000000000..d593f4794 --- /dev/null +++ b/external/bsd/atf/dist/atf-run/atf-run.1 @@ -0,0 +1,202 @@ +.\" +.\" Automated Testing Framework (atf) +.\" +.\" Copyright (c) 2007 The NetBSD Foundation, Inc. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +.\" CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +.\" IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +.\" GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +.\" IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.Dd November 1, 2010 +.Dt ATF-RUN 1 +.Os +.Sh NAME +.Nm atf-run +.Nd executes a collection of test programs +.Sh SYNOPSIS +.Nm +.Op Fl v Ar var1=value1 Op .. Fl v Ar varN=valueN +.Op Ar test_program1 Op Ar .. test_programN +.Nm +.Fl h +.Sh DESCRIPTION +.Nm +executes a collection of test programs or, in other words, a complete +test suite. +The results of each test program are collected by the tool, and are then +multiplexed into a single machine-parseable report; see +.Xr atf-formats 5 +for more details. +This report can later be transformed into many different and saner formats +using the +.Nm atf-report +tool. +.Pp +The list of test programs to execute is read from an +.Pa Atffile +present in the current directory. +This file describes the test suite stored in the directory it lives in, +which aside from the list of test programs also includes meta-data and +configuration variables. +.Pp +.Nm +is also in charge of reading the configuration files that tune the behavior +of each test program and passing down the necessary variables to them. +More details on how this is done are given in the +.Sx Configuration +section. +.Pp +In the first synopsis form, +.Nm +parses the +.Pa Atffile +in the current directory and runs all the test programs specified in it. +If any test program names are given as part of the command line, those are +the ones executed instead of the complete list. +.Pp +In the second synopsis form, +.Nm +will print information about all supported options and their purpose. +.Pp +The following options are available: +.Bl -tag -width XvXvarXvalueXX +.It Fl h +Shows a short summary of all available options and their purpose. +.It Fl v Ar var=value +Sets the configuration variable +.Ar var +to the given value +.Ar value . +.El +.Ss Configuration +.Nm +reads configuration data from multiple places. +After all of these places have been analyzed, a list of variable-value +pairs are passed to the test programs to be run. +.Pp +The following locations are scanned for configuration data, in order. +Items down the list override values defined above them: +.Bl -enum +.It +Configuration variables defined in the +.Pa Atffile . +.It +Configuration variables defined in the system-wide configuration file +shared among all test suites. +This lives in +.Pa ${ATF_CONFDIR}/common.conf . +.It +Configuration variables defined in the system-wide test-suite-specific +configuration file. +This lives in +.Pa ${ATF_CONFDIR}/.conf . +.It +Configuration variables defined in the user-specific configuration file +shared among all test suites. +This lives in +.Pa ${HOME}/.atf/common.conf . +.It +Configuration variables defined in the user-specific test-suite-specific +configuration file. +This lives in +.Pa ${HOME}/.atf/.conf . +.It +Configuration variables provided as part of the command line through the +.Fl v +option. +.El +.Pp +The value of +.Va ATF_CONFDIR +in the above list determined as detailed in +.Xr atf-config 1 . +.Pp +The following configuration variables are globally recognized: +.Bl -tag -width XunprivilegedXuserXX +.It Va unprivileged-user +The name of the system user that atf-run will drop root privileges into +for test cases defining +.Sq require.user=unprivileged . +Note that this is +.Em not provided for security purposes ; +this feature is only for the convenience of the user. +.El +.Ss Hooks +.Nm Ns 's +internal behavior can be customized by the system administrator and the +user by means of hooks. +These hooks are written in the shell script language for simplicity and +are stored in the following files, which are read in the order provided +below: +.Bl -enum +.It +${ATF_CONFDIR}/atf-run.hooks +.It +${HOME}/.atf/atf-run.hooks +.El +.Pp +The following hooks are supported: +.Bl -tag -width infoXstartXhookXX +.It info_start_hook +Called before +.Nm +executes any test program. +The purpose of this hook is to write additional +.Sq info +stanzas to the top of the output report; these are defined by the +.Sq application/X-atf-tps format +described in +.Xr atf-formats 5 . +Always use the +.Sq atf_tps_writer_info +function to print these. +.Pp +This takes no parameters. +.It info_end_hook +Similar to +.Sq info_start_hook +but executed after all test programs have been run so that additional +.Sq info +stanzas can be added to the bottom of the output report. +.Pp +This takes no parameters. +.El +.Pp +All hooks are accompanied by a function named +.Sq default_ +that can be executed by them to invoke the default behavior built into +.Nm . +For example, in order to extend the default +.Sq info_start_hook +hook, we could write the following function: +.Bd -literal -offset indent +info_start_hook() +{ + default_info_start_hook "${@}" + + atf_tps_writer_info "uptime" "$(uptime)" +} +.Ed +.Sh SEE ALSO +.Xr atf-report 1 , +.Xr atf-test-program 1 , +.Xr atf 7 diff --git a/external/bsd/atf/dist/atf-run/atf-run.cpp b/external/bsd/atf/dist/atf-run/atf-run.cpp new file mode 100644 index 000000000..e28e8fdf0 --- /dev/null +++ b/external/bsd/atf/dist/atf-run/atf-run.cpp @@ -0,0 +1,563 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#if defined(HAVE_CONFIG_H) +#include "bconfig.h" +#endif + +extern "C" { +#include +#include +#include +#include +#include +} + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "atf-c++/detail/application.hpp" +#include "atf-c++/config.hpp" +#include "atf-c++/tests.hpp" + +#include "atf-c++/detail/env.hpp" +#include "atf-c++/detail/exceptions.hpp" +#include "atf-c++/detail/fs.hpp" +#include "atf-c++/detail/parser.hpp" +#include "atf-c++/detail/process.hpp" +#include "atf-c++/detail/sanity.hpp" +#include "atf-c++/detail/text.hpp" + +#include "atffile.hpp" +#include "config.hpp" +#include "fs.hpp" +#include "requirements.hpp" +#include "test-program.hpp" + +namespace impl = atf::atf_run; + +#if defined(MAXCOMLEN) +static const std::string::size_type max_core_name_length = MAXCOMLEN; +#else +static const std::string::size_type max_core_name_length = std::string::npos; +#endif + +class atf_run : public atf::application::app { + static const char* m_description; + + atf::tests::vars_map m_cmdline_vars; + + static atf::tests::vars_map::value_type parse_var(const std::string&); + + void process_option(int, const char*); + std::string specific_args(void) const; + options_set specific_options(void) const; + + void parse_vflag(const std::string&); + + std::vector< std::string > conf_args(void) const; + + size_t count_tps(std::vector< std::string >) const; + + int run_test(const atf::fs::path&, impl::atf_tps_writer&, + const atf::tests::vars_map&); + int run_test_directory(const atf::fs::path&, impl::atf_tps_writer&); + int run_test_program(const atf::fs::path&, impl::atf_tps_writer&, + const atf::tests::vars_map&); + + impl::test_case_result get_test_case_result(const std::string&, + const atf::process::status&, const atf::fs::path&) const; + +public: + atf_run(void); + + int main(void); +}; + +static void +sanitize_gdb_env(void) +{ + try { + atf::env::unset("TERM"); + } catch (...) { + // Just swallow exceptions here; they cannot propagate into C, which + // is where this function is called from, and even if these exceptions + // appear they are benign. + } +} + +static void +dump_stacktrace(const atf::fs::path& tp, const atf::process::status& s, + const atf::fs::path& workdir, impl::atf_tps_writer& w) +{ + PRE(s.signaled() && s.coredump()); + + w.stderr_tc("Test program crashed; attempting to get stack trace"); + + const atf::fs::path corename = workdir / + (tp.leaf_name().substr(0, max_core_name_length) + ".core"); + if (!atf::fs::exists(corename)) { + w.stderr_tc("Expected file " + corename.str() + " not found"); + return; + } + + const atf::fs::path gdb(GDB); + const atf::fs::path gdbout = workdir / "gdb.out"; + const atf::process::argv_array args(gdb.leaf_name().c_str(), "-batch", + "-q", "-ex", "bt", tp.c_str(), + corename.c_str(), NULL); + atf::process::status status = atf::process::exec( + gdb, args, + atf::process::stream_redirect_path(gdbout), + atf::process::stream_redirect_path(atf::fs::path("/dev/null")), + sanitize_gdb_env); + if (!status.exited() || status.exitstatus() != EXIT_SUCCESS) { + w.stderr_tc("Execution of " GDB " failed"); + return; + } + + std::ifstream input(gdbout.c_str()); + if (input) { + std::string line; + while (std::getline(input, line).good()) + w.stderr_tc(line); + input.close(); + } + + w.stderr_tc("Stack trace complete"); +} + +const char* atf_run::m_description = + "atf-run is a tool that runs tests programs and collects their " + "results."; + +atf_run::atf_run(void) : + app(m_description, "atf-run(1)", "atf(7)") +{ +} + +void +atf_run::process_option(int ch, const char* arg) +{ + switch (ch) { + case 'v': + parse_vflag(arg); + break; + + default: + UNREACHABLE; + } +} + +std::string +atf_run::specific_args(void) + const +{ + return "[test-program1 .. test-programN]"; +} + +atf_run::options_set +atf_run::specific_options(void) + const +{ + using atf::application::option; + options_set opts; + opts.insert(option('v', "var=value", "Sets the configuration variable " + "`var' to `value'; overrides " + "values in configuration files")); + return opts; +} + +void +atf_run::parse_vflag(const std::string& str) +{ + if (str.empty()) + throw std::runtime_error("-v requires a non-empty argument"); + + std::vector< std::string > ws = atf::text::split(str, "="); + if (ws.size() == 1 && str[str.length() - 1] == '=') { + m_cmdline_vars[ws[0]] = ""; + } else { + if (ws.size() != 2) + throw std::runtime_error("-v requires an argument of the form " + "var=value"); + + m_cmdline_vars[ws[0]] = ws[1]; + } +} + +int +atf_run::run_test(const atf::fs::path& tp, + impl::atf_tps_writer& w, + const atf::tests::vars_map& config) +{ + atf::fs::file_info fi(tp); + + int errcode; + if (fi.get_type() == atf::fs::file_info::dir_type) + errcode = run_test_directory(tp, w); + else { + const atf::tests::vars_map effective_config = + impl::merge_configs(config, m_cmdline_vars); + + errcode = run_test_program(tp, w, effective_config); + } + return errcode; +} + +int +atf_run::run_test_directory(const atf::fs::path& tp, + impl::atf_tps_writer& w) +{ + impl::atffile af = impl::read_atffile(tp / "Atffile"); + + atf::tests::vars_map test_suite_vars; + { + atf::tests::vars_map::const_iterator iter = + af.props().find("test-suite"); + INV(iter != af.props().end()); + test_suite_vars = impl::read_config_files((*iter).second); + } + + bool ok = true; + for (std::vector< std::string >::const_iterator iter = af.tps().begin(); + iter != af.tps().end(); iter++) { + const bool result = run_test(tp / *iter, w, + impl::merge_configs(af.conf(), test_suite_vars)); + ok &= (result == EXIT_SUCCESS); + } + + return ok ? EXIT_SUCCESS : EXIT_FAILURE; +} + +impl::test_case_result +atf_run::get_test_case_result(const std::string& broken_reason, + const atf::process::status& s, + const atf::fs::path& resfile) + const +{ + using atf::text::to_string; + using impl::read_test_case_result; + using impl::test_case_result; + + if (!broken_reason.empty()) { + test_case_result tcr; + + try { + tcr = read_test_case_result(resfile); + + if (tcr.state() == "expected_timeout") { + return tcr; + } else { + return test_case_result("failed", -1, broken_reason); + } + } catch (const std::runtime_error&) { + return test_case_result("failed", -1, broken_reason); + } + } + + if (s.exited()) { + test_case_result tcr; + + try { + tcr = read_test_case_result(resfile); + } catch (const std::runtime_error& e) { + return test_case_result("failed", -1, "Test case exited " + "normally but failed to create the results file: " + + std::string(e.what())); + } + + if (tcr.state() == "expected_death") { + return tcr; + } else if (tcr.state() == "expected_exit") { + if (tcr.value() == -1 || s.exitstatus() == tcr.value()) + return tcr; + else + return test_case_result("failed", -1, "Test case was " + "expected to exit with a " + to_string(tcr.value()) + + " error code but returned " + to_string(s.exitstatus())); + } else if (tcr.state() == "expected_failure") { + if (s.exitstatus() == EXIT_SUCCESS) + return tcr; + else + return test_case_result("failed", -1, "Test case returned an " + "error in expected_failure mode but it should not have"); + } else if (tcr.state() == "expected_signal") { + return test_case_result("failed", -1, "Test case exited cleanly " + "but was expected to receive a signal"); + } else if (tcr.state() == "failed") { + if (s.exitstatus() == EXIT_SUCCESS) + return test_case_result("failed", -1, "Test case " + "exited successfully but reported failure"); + else + return tcr; + } else if (tcr.state() == "passed") { + if (s.exitstatus() == EXIT_SUCCESS) + return tcr; + else + return test_case_result("failed", -1, "Test case exited as " + "passed but reported an error"); + } else if (tcr.state() == "skipped") { + if (s.exitstatus() == EXIT_SUCCESS) + return tcr; + else + return test_case_result("failed", -1, "Test case exited as " + "skipped but reported an error"); + } + } else if (s.signaled()) { + test_case_result tcr; + + try { + tcr = read_test_case_result(resfile); + } catch (const std::runtime_error&) { + return test_case_result("failed", -1, "Test program received " + "signal " + atf::text::to_string(s.termsig()) + + (s.coredump() ? " (core dumped)" : "")); + } + + if (tcr.state() == "expected_death") { + return tcr; + } else if (tcr.state() == "expected_signal") { + if (tcr.value() == -1 || s.termsig() == tcr.value()) + return tcr; + else + return test_case_result("failed", -1, "Test case was " + "expected to exit due to a " + to_string(tcr.value()) + + " signal but got " + to_string(s.termsig())); + } else { + return test_case_result("failed", -1, "Test program received " + "signal " + atf::text::to_string(s.termsig()) + + (s.coredump() ? " (core dumped)" : "") + " and created a " + "bogus results file"); + } + } + UNREACHABLE; + return test_case_result(); +} + +int +atf_run::run_test_program(const atf::fs::path& tp, + impl::atf_tps_writer& w, + const atf::tests::vars_map& config) +{ + int errcode = EXIT_SUCCESS; + + impl::metadata md; + try { + md = impl::get_metadata(tp, config); + } catch (const atf::parser::format_error& e) { + w.start_tp(tp.str(), 0); + w.end_tp("Invalid format for test case list: " + std::string(e.what())); + return EXIT_FAILURE; + } catch (const atf::parser::parse_errors& e) { + const std::string reason = atf::text::join(e, "; "); + w.start_tp(tp.str(), 0); + w.end_tp("Invalid format for test case list: " + reason); + return EXIT_FAILURE; + } + + impl::temp_dir resdir(atf::fs::path(atf::config::get("atf_workdir")) / + "atf-run.XXXXXX"); + + w.start_tp(tp.str(), md.test_cases.size()); + if (md.test_cases.empty()) { + w.end_tp("Bogus test program: reported 0 test cases"); + errcode = EXIT_FAILURE; + } else { + for (std::map< std::string, atf::tests::vars_map >::const_iterator iter + = md.test_cases.begin(); iter != md.test_cases.end(); iter++) { + const std::string& tcname = (*iter).first; + const atf::tests::vars_map& tcmd = (*iter).second; + + w.start_tc(tcname); + + try { + const std::string& reqfail = impl::check_requirements( + tcmd, config); + if (!reqfail.empty()) { + w.end_tc("skipped", reqfail); + continue; + } + } catch (const std::runtime_error& e) { + w.end_tc("failed", e.what()); + errcode = EXIT_FAILURE; + continue; + } + + const std::pair< int, int > user = impl::get_required_user( + tcmd, config); + + atf::fs::path resfile = resdir.get_path() / "tcr"; + INV(!atf::fs::exists(resfile)); + try { + const bool has_cleanup = atf::text::to_bool( + (*tcmd.find("has.cleanup")).second); + + impl::temp_dir workdir(atf::fs::path(atf::config::get( + "atf_workdir")) / "atf-run.XXXXXX"); + if (user.first != -1 && user.second != -1) { + if (::chown(workdir.get_path().c_str(), user.first, + user.second) == -1) { + throw atf::system_error("chown(" + + workdir.get_path().str() + ")", "chown(2) failed", + errno); + } + resfile = workdir.get_path() / "tcr"; + } + + std::pair< std::string, const atf::process::status > s = + impl::run_test_case(tp, tcname, "body", tcmd, config, + resfile, workdir.get_path(), w); + if (s.second.signaled() && s.second.coredump()) + dump_stacktrace(tp, s.second, workdir.get_path(), w); + if (has_cleanup) + (void)impl::run_test_case(tp, tcname, "cleanup", tcmd, + config, resfile, workdir.get_path(), w); + + // TODO: Force deletion of workdir. + + impl::test_case_result tcr = get_test_case_result(s.first, + s.second, resfile); + + w.end_tc(tcr.state(), tcr.reason()); + if (tcr.state() == "failed") + errcode = EXIT_FAILURE; + } catch (...) { + if (atf::fs::exists(resfile)) + atf::fs::remove(resfile); + throw; + } + if (atf::fs::exists(resfile)) + atf::fs::remove(resfile); + + } + w.end_tp(""); + } + + return errcode; +} + +size_t +atf_run::count_tps(std::vector< std::string > tps) + const +{ + size_t ntps = 0; + + for (std::vector< std::string >::const_iterator iter = tps.begin(); + iter != tps.end(); iter++) { + atf::fs::path tp(*iter); + atf::fs::file_info fi(tp); + + if (fi.get_type() == atf::fs::file_info::dir_type) { + impl::atffile af = impl::read_atffile(tp / "Atffile"); + std::vector< std::string > aux = af.tps(); + for (std::vector< std::string >::iterator i2 = aux.begin(); + i2 != aux.end(); i2++) + *i2 = (tp / *i2).str(); + ntps += count_tps(aux); + } else + ntps++; + } + + return ntps; +} + +static +void +call_hook(const std::string& tool, const std::string& hook) +{ + const atf::fs::path sh(atf::config::get("atf_shell")); + const atf::fs::path hooks = + atf::fs::path(atf::config::get("atf_pkgdatadir")) / (tool + ".hooks"); + + const atf::process::status s = + atf::process::exec(sh, + atf::process::argv_array(sh.c_str(), hooks.c_str(), + hook.c_str(), NULL), + atf::process::stream_inherit(), + atf::process::stream_inherit()); + + + if (!s.exited() || s.exitstatus() != EXIT_SUCCESS) + throw std::runtime_error("Failed to run the '" + hook + "' hook " + "for '" + tool + "'"); +} + +int +atf_run::main(void) +{ + impl::atffile af = impl::read_atffile(atf::fs::path("Atffile")); + + std::vector< std::string > tps; + tps = af.tps(); + if (m_argc >= 1) { + // TODO: Ensure that the given test names are listed in the + // Atffile. Take into account that the file can be using globs. + tps.clear(); + for (int i = 0; i < m_argc; i++) + tps.push_back(m_argv[i]); + } + + // Read configuration data for this test suite. + atf::tests::vars_map test_suite_vars; + { + atf::tests::vars_map::const_iterator iter = + af.props().find("test-suite"); + INV(iter != af.props().end()); + test_suite_vars = impl::read_config_files((*iter).second); + } + + impl::atf_tps_writer w(std::cout); + call_hook("atf-run", "info_start_hook"); + w.ntps(count_tps(tps)); + + bool ok = true; + for (std::vector< std::string >::const_iterator iter = tps.begin(); + iter != tps.end(); iter++) { + const bool result = run_test(atf::fs::path(*iter), w, + impl::merge_configs(af.conf(), test_suite_vars)); + ok &= (result == EXIT_SUCCESS); + } + + call_hook("atf-run", "info_end_hook"); + + return ok ? EXIT_SUCCESS : EXIT_FAILURE; +} + +int +main(int argc, char* const* argv) +{ + return atf_run().run(argc, argv); +} diff --git a/external/bsd/atf/dist/atf-run/atffile.cpp b/external/bsd/atf/dist/atf-run/atffile.cpp new file mode 100644 index 000000000..22ece645d --- /dev/null +++ b/external/bsd/atf/dist/atf-run/atffile.cpp @@ -0,0 +1,343 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#include + +#include "atf-c/defs.h" + +#include "atf-c++/detail/exceptions.hpp" +#include "atf-c++/detail/expand.hpp" +#include "atf-c++/detail/parser.hpp" +#include "atf-c++/detail/sanity.hpp" + +#include "atffile.hpp" + +namespace impl = atf::atf_run; +namespace detail = atf::atf_run::detail; + +// ------------------------------------------------------------------------ +// The "atf_atffile" auxiliary parser. +// ------------------------------------------------------------------------ + +namespace atf_atffile { + +static const atf::parser::token_type eof_type = 0; +static const atf::parser::token_type nl_type = 1; +static const atf::parser::token_type text_type = 2; +static const atf::parser::token_type colon_type = 3; +static const atf::parser::token_type conf_type = 4; +static const atf::parser::token_type dblquote_type = 5; +static const atf::parser::token_type equal_type = 6; +static const atf::parser::token_type hash_type = 7; +static const atf::parser::token_type prop_type = 8; +static const atf::parser::token_type tp_type = 9; +static const atf::parser::token_type tp_glob_type = 10; + +class tokenizer : public atf::parser::tokenizer< std::istream > { +public: + tokenizer(std::istream& is, size_t curline) : + atf::parser::tokenizer< std::istream > + (is, true, eof_type, nl_type, text_type, curline) + { + add_delim(':', colon_type); + add_delim('=', equal_type); + add_delim('#', hash_type); + add_quote('"', dblquote_type); + add_keyword("conf", conf_type); + add_keyword("prop", prop_type); + add_keyword("tp", tp_type); + add_keyword("tp-glob", tp_glob_type); + } +}; + +} // namespace atf_atffile + +// ------------------------------------------------------------------------ +// The "atf_atffile_reader" class. +// ------------------------------------------------------------------------ + +detail::atf_atffile_reader::atf_atffile_reader(std::istream& is) : + m_is(is) +{ +} + +detail::atf_atffile_reader::~atf_atffile_reader(void) +{ +} + +void +detail::atf_atffile_reader::got_conf( + const std::string& name ATF_DEFS_ATTRIBUTE_UNUSED, + const std::string& val ATF_DEFS_ATTRIBUTE_UNUSED) +{ +} + +void +detail::atf_atffile_reader::got_prop( + const std::string& name ATF_DEFS_ATTRIBUTE_UNUSED, + const std::string& val ATF_DEFS_ATTRIBUTE_UNUSED) +{ +} + +void +detail::atf_atffile_reader::got_tp( + const std::string& name ATF_DEFS_ATTRIBUTE_UNUSED, + bool isglob ATF_DEFS_ATTRIBUTE_UNUSED) +{ +} + +void +detail::atf_atffile_reader::got_eof(void) +{ +} + +void +detail::atf_atffile_reader::read(void) +{ + using atf::parser::parse_error; + using namespace atf_atffile; + + std::pair< size_t, atf::parser::headers_map > hml = + atf::parser::read_headers(m_is, 1); + atf::parser::validate_content_type(hml.second, + "application/X-atf-atffile", 1); + + tokenizer tkz(m_is, hml.first); + atf::parser::parser< tokenizer > p(tkz); + + for (;;) { + try { + atf::parser::token t = + p.expect(conf_type, hash_type, prop_type, tp_type, + tp_glob_type, nl_type, eof_type, + "conf, #, prop, tp, tp-glob, a new line or eof"); + if (t.type() == eof_type) + break; + + if (t.type() == conf_type) { + t = p.expect(colon_type, "`:'"); + + t = p.expect(text_type, "variable name"); + std::string var = t.text(); + + t = p.expect(equal_type, "equal sign"); + + t = p.expect(text_type, "word or quoted string"); + ATF_PARSER_CALLBACK(p, got_conf(var, t.text())); + } else if (t.type() == hash_type) { + (void)p.rest_of_line(); + } else if (t.type() == prop_type) { + t = p.expect(colon_type, "`:'"); + + t = p.expect(text_type, "property name"); + std::string name = t.text(); + + t = p.expect(equal_type, "equale sign"); + + t = p.expect(text_type, "word or quoted string"); + ATF_PARSER_CALLBACK(p, got_prop(name, t.text())); + } else if (t.type() == tp_type) { + t = p.expect(colon_type, "`:'"); + + t = p.expect(text_type, "word or quoted string"); + ATF_PARSER_CALLBACK(p, got_tp(t.text(), false)); + } else if (t.type() == tp_glob_type) { + t = p.expect(colon_type, "`:'"); + + t = p.expect(text_type, "word or quoted string"); + ATF_PARSER_CALLBACK(p, got_tp(t.text(), true)); + } else if (t.type() == nl_type) { + continue; + } else + UNREACHABLE; + + t = p.expect(nl_type, hash_type, eof_type, + "new line or comment"); + if (t.type() == hash_type) { + (void)p.rest_of_line(); + t = p.next(); + } else if (t.type() == eof_type) + break; + } catch (const parse_error& pe) { + p.add_error(pe); + p.reset(nl_type); + } + } + + ATF_PARSER_CALLBACK(p, got_eof()); +} + +// ------------------------------------------------------------------------ +// The "reader" helper class. +// ------------------------------------------------------------------------ + +class reader : public detail::atf_atffile_reader { + const atf::fs::directory& m_dir; + atf::tests::vars_map m_conf, m_props; + std::vector< std::string > m_tps; + + void + got_tp(const std::string& name, bool isglob) + { + if (isglob) { + std::vector< std::string > ms = + atf::expand::expand_glob(name, m_dir.names()); + // Cannot use m_tps.insert(iterator, begin, end) here because it + // does not work under Solaris. + for (std::vector< std::string >::const_iterator iter = ms.begin(); + iter != ms.end(); iter++) + m_tps.push_back(*iter); + } else { + if (m_dir.find(name) == m_dir.end()) + throw atf::not_found_error< atf::fs::path > + ("Cannot locate the " + name + " file", + atf::fs::path(name)); + m_tps.push_back(name); + } + } + + void + got_prop(const std::string& name, const std::string& val) + { + m_props[name] = val; + } + + void + got_conf(const std::string& var, const std::string& val) + { + m_conf[var] = val; + } + +public: + reader(std::istream& is, const atf::fs::directory& dir) : + detail::atf_atffile_reader(is), + m_dir(dir) + { + } + + const atf::tests::vars_map& + conf(void) + const + { + return m_conf; + } + + const atf::tests::vars_map& + props(void) + const + { + return m_props; + } + + const std::vector< std::string >& + tps(void) + const + { + return m_tps; + } +}; + +// ------------------------------------------------------------------------ +// The "atffile" class. +// ------------------------------------------------------------------------ + +impl::atffile::atffile(const atf::tests::vars_map& config_vars, + const std::vector< std::string >& test_program_names, + const atf::tests::vars_map& properties) : + m_conf(config_vars), + m_tps(test_program_names), + m_props(properties) +{ + PRE(properties.find("test-suite") != properties.end()); +} + +const std::vector< std::string >& +impl::atffile::tps(void) + const +{ + return m_tps; +} + +const atf::tests::vars_map& +impl::atffile::conf(void) + const +{ + return m_conf; +} + +const atf::tests::vars_map& +impl::atffile::props(void) + const +{ + return m_props; +} + +// ------------------------------------------------------------------------ +// Free functions. +// ------------------------------------------------------------------------ + +// XXX Glob expansion and file existance checks certainly do not belong in +// a *parser*. This needs to be taken out... +impl::atffile +impl::read_atffile(const atf::fs::path& filename) +{ + // Scan the directory where the atffile lives in to gather a list of + // all possible test programs in it. + fs::directory dir(filename.branch_path()); + dir.erase(filename.leaf_name()); + fs::directory::iterator iter = dir.begin(); + while (iter != dir.end()) { + const std::string& name = (*iter).first; + const fs::file_info& fi = (*iter).second; + + // Discard hidden files and non-executable ones so that they are + // not candidates for glob matching. + if (name[0] == '.' || (!fi.is_owner_executable() && + !fi.is_group_executable())) + dir.erase(iter++); + else + iter++; + } + + // Parse the atffile. + std::ifstream is(filename.c_str()); + if (!is) + throw atf::not_found_error< fs::path > + ("Cannot open Atffile", filename); + reader r(is, dir); + r.read(); + is.close(); + + // Sanity checks. + if (r.props().find("test-suite") == r.props().end()) + throw atf::not_found_error< std::string > + ("Undefined property `test-suite'", "test-suite"); + + return atffile(r.conf(), r.tps(), r.props()); +} diff --git a/external/bsd/atf/dist/atf-run/atffile.hpp b/external/bsd/atf/dist/atf-run/atffile.hpp new file mode 100644 index 000000000..8c915c24c --- /dev/null +++ b/external/bsd/atf/dist/atf-run/atffile.hpp @@ -0,0 +1,95 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#if !defined(_ATF_RUN_ATFFILE_HPP_) +#define _ATF_RUN_ATFFILE_HPP_ + +#include +#include + +#include "atf-c++/tests.hpp" + +#include "atf-c++/detail/fs.hpp" + +namespace atf { +namespace atf_run { + +// ------------------------------------------------------------------------ +// The "atf_atffile_reader" class. +// ------------------------------------------------------------------------ + +namespace detail { + +class atf_atffile_reader { + std::istream& m_is; + +protected: + virtual void got_conf(const std::string&, const std::string &); + virtual void got_prop(const std::string&, const std::string &); + virtual void got_tp(const std::string&, bool); + virtual void got_eof(void); + +public: + atf_atffile_reader(std::istream&); + virtual ~atf_atffile_reader(void); + + void read(void); +}; + +} // namespace detail + +// ------------------------------------------------------------------------ +// The "atffile" class. +// ------------------------------------------------------------------------ + +class atffile { + atf::tests::vars_map m_conf; + std::vector< std::string > m_tps; + atf::tests::vars_map m_props; + +public: + atffile(const atf::tests::vars_map&, + const std::vector< std::string >&, + const atf::tests::vars_map&); + + const atf::tests::vars_map& conf(void) const; + const std::vector< std::string >& tps(void) const; + const atf::tests::vars_map& props(void) const; +}; + +// ------------------------------------------------------------------------ +// Free functions. +// ------------------------------------------------------------------------ + +atffile read_atffile(const fs::path&); + +} // namespace atf_run +} // namespace atf + +#endif // !defined(_ATF_RUN_ATFFILE_HPP_) diff --git a/external/bsd/atf/dist/atf-run/atffile_test.cpp b/external/bsd/atf/dist/atf-run/atffile_test.cpp new file mode 100644 index 000000000..e5781a337 --- /dev/null +++ b/external/bsd/atf/dist/atf-run/atffile_test.cpp @@ -0,0 +1,636 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2009 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +extern "C" { +#include +#include +} + +#include +#include +#include + +#include "atf-c++/macros.hpp" + +#include "atf-c++/detail/exceptions.hpp" +#include "atf-c++/detail/test_helpers.hpp" + +#include "atffile.hpp" + +namespace detail = atf::atf_run::detail; + +// ------------------------------------------------------------------------ +// Auxiliary functions. +// ------------------------------------------------------------------------ + +namespace { + +static +std::auto_ptr< std::ofstream > +new_atffile(void) +{ + std::auto_ptr< std::ofstream > os(new std::ofstream("Atffile")); + ATF_REQUIRE(*os); + + (*os) << "Content-Type: application/X-atf-atffile; version=\"1\"\n\n"; + return os; +} + +static +void +touch_exec(const char* name) +{ + std::ofstream os(name); + ATF_REQUIRE(os); + os.close(); + ATF_REQUIRE(::chmod(name, S_IRWXU) != -1); +} + +static inline +bool +is_in(const std::string& value, const std::vector< std::string >& v) +{ + return std::find(v.begin(), v.end(), value) != v.end(); +} + +} // anonymous namespace + +// ------------------------------------------------------------------------ +// Tests cases for the "atffile" parser. +// ------------------------------------------------------------------------ + +class atffile_reader : protected detail::atf_atffile_reader { + void + got_conf(const std::string& name, const std::string& val) + { + m_calls.push_back("got_conf(" + name + ", " + val + ")"); + } + + void + got_prop(const std::string& name, const std::string& val) + { + m_calls.push_back("got_prop(" + name + ", " + val + ")"); + } + + void + got_tp(const std::string& name, bool isglob) + { + m_calls.push_back("got_tp(" + name + ", " + (isglob ? "true" : "false") + + ")"); + } + + void + got_eof(void) + { + m_calls.push_back("got_eof()"); + } + +public: + atffile_reader(std::istream& is) : + detail::atf_atffile_reader(is) + { + } + + void + read(void) + { + atf_atffile_reader::read(); + } + + std::vector< std::string > m_calls; +}; + +ATF_TEST_CASE_WITHOUT_HEAD(atffile_1); +ATF_TEST_CASE_BODY(atffile_1) +{ + const char* input = + "Content-Type: application/X-atf-atffile; version=\"1\"\n" + "\n" + ; + + const char* exp_calls[] = { + "got_eof()", + NULL + }; + + const char* exp_errors[] = { + NULL + }; + + do_parser_test< atffile_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(atffile_2); +ATF_TEST_CASE_BODY(atffile_2) +{ + const char* input = + "Content-Type: application/X-atf-atffile; version=\"1\"\n" + "\n" + "# This is a comment on a line of its own.\n" + "# And this is another one.\n" + "\n" + " # Another after some whitespace.\n" + "\n" + "# The last one after an empty line.\n" + ; + + const char* exp_calls[] = { + "got_eof()", + NULL + }; + + const char* exp_errors[] = { + NULL + }; + + do_parser_test< atffile_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(atffile_3); +ATF_TEST_CASE_BODY(atffile_3) +{ + const char* input = + "Content-Type: application/X-atf-atffile; version=\"1\"\n" + "\n" + "conf: var1=value1\n" + "conf: var2 = value2\n" + "conf: var3 = value3\n" + "conf: var4 = value4\n" + "\n" + "conf:var5=value5\n" + " conf:var6=value6\n" + "\n" + "conf: var7 = \"This is a long value.\"\n" + "conf: var8 = \"Single-word\"\n" + "conf: var9 = \" Single-word \"\n" + "conf: var10 = Single-word\n" + ; + + const char* exp_calls[] = { + "got_conf(var1, value1)", + "got_conf(var2, value2)", + "got_conf(var3, value3)", + "got_conf(var4, value4)", + "got_conf(var5, value5)", + "got_conf(var6, value6)", + "got_conf(var7, This is a long value.)", + "got_conf(var8, Single-word)", + "got_conf(var9, Single-word )", + "got_conf(var10, Single-word)", + "got_eof()", + NULL + }; + + const char* exp_errors[] = { + NULL + }; + + do_parser_test< atffile_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(atffile_4); +ATF_TEST_CASE_BODY(atffile_4) +{ + const char* input = + "Content-Type: application/X-atf-atffile; version=\"1\"\n" + "\n" + "prop: var1=value1\n" + "prop: var2 = value2\n" + "prop: var3 = value3\n" + "prop: var4 = value4\n" + "\n" + "prop:var5=value5\n" + " prop:var6=value6\n" + "\n" + "prop: var7 = \"This is a long value.\"\n" + "prop: var8 = \"Single-word\"\n" + "prop: var9 = \" Single-word \"\n" + "prop: var10 = Single-word\n" + ; + + const char* exp_calls[] = { + "got_prop(var1, value1)", + "got_prop(var2, value2)", + "got_prop(var3, value3)", + "got_prop(var4, value4)", + "got_prop(var5, value5)", + "got_prop(var6, value6)", + "got_prop(var7, This is a long value.)", + "got_prop(var8, Single-word)", + "got_prop(var9, Single-word )", + "got_prop(var10, Single-word)", + "got_eof()", + NULL + }; + + const char* exp_errors[] = { + NULL + }; + + do_parser_test< atffile_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(atffile_5); +ATF_TEST_CASE_BODY(atffile_5) +{ + const char* input = + "Content-Type: application/X-atf-atffile; version=\"1\"\n" + "\n" + "tp:foo\n" + "tp: foo\n" + "tp: foo\n" + "tp: foo\n" + "tp: foo\n" + "tp: \"name with spaces\"\n" + "tp: \"single-word\"\n" + "tp: single-word\n" + "\n" + "tp-glob:foo*?bar\n" + "tp-glob: foo*?bar\n" + "tp-glob: foo*?bar\n" + "tp-glob: foo*?bar\n" + "tp-glob: foo*?bar\n" + "tp-glob: \"glob * with ? spaces\"\n" + "tp-glob: \"single-*-word\"\n" + "tp-glob: single-*-word\n" + ; + + const char* exp_calls[] = { + "got_tp(foo, false)", + "got_tp(foo, false)", + "got_tp(foo, false)", + "got_tp(foo, false)", + "got_tp(foo, false)", + "got_tp(name with spaces, false)", + "got_tp(single-word, false)", + "got_tp(single-word, false)", + "got_tp(foo*?bar, true)", + "got_tp(foo*?bar, true)", + "got_tp(foo*?bar, true)", + "got_tp(foo*?bar, true)", + "got_tp(foo*?bar, true)", + "got_tp(glob * with ? spaces, true)", + "got_tp(single-*-word, true)", + "got_tp(single-*-word, true)", + "got_eof()", + NULL + }; + + const char* exp_errors[] = { + NULL + }; + + do_parser_test< atffile_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(atffile_6); +ATF_TEST_CASE_BODY(atffile_6) +{ + const char* input = + "Content-Type: application/X-atf-atffile; version=\"1\"\n" + "\n" + "prop: foo = bar # A comment.\n" + "conf: foo = bar # A comment.\n" + "tp: foo # A comment.\n" + "tp-glob: foo # A comment.\n" + ; + + const char* exp_calls[] = { + "got_prop(foo, bar)", + "got_conf(foo, bar)", + "got_tp(foo, false)", + "got_tp(foo, true)", + "got_eof()", + NULL + }; + + const char* exp_errors[] = { + NULL + }; + + do_parser_test< atffile_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(atffile_50); +ATF_TEST_CASE_BODY(atffile_50) +{ + const char* input = + "Content-Type: application/X-atf-atffile; version=\"1\"\n" + "\n" + "foo\n" + ; + + const char* exp_calls[] = { + NULL + }; + + // NO_CHECK_STYLE_BEGIN + const char* exp_errors[] = { + "3: Unexpected token `foo'; expected conf, #, prop, tp, tp-glob, a new line or eof", + NULL + }; + // NO_CHECK_STYLE_END + + do_parser_test< atffile_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(atffile_51); +ATF_TEST_CASE_BODY(atffile_51) +{ + const char* input = + "Content-Type: application/X-atf-atffile; version=\"1\"\n" + "\n" + "foo bar\n" + "baz\n" + ; + + const char* exp_calls[] = { + NULL + }; + + // NO_CHECK_STYLE_BEGIN + const char* exp_errors[] = { + "3: Unexpected token `foo'; expected conf, #, prop, tp, tp-glob, a new line or eof", + "4: Unexpected token `baz'; expected conf, #, prop, tp, tp-glob, a new line or eof", + NULL + }; + // NO_CHECK_STYLE_END + + do_parser_test< atffile_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(atffile_52); +ATF_TEST_CASE_BODY(atffile_52) +{ + const char* input = + "Content-Type: application/X-atf-atffile; version=\"1\"\n" + "\n" + "conf\n" + "conf:\n" + "conf: foo =\n" + "conf: bar = # A comment.\n" + "\n" + "prop\n" + "prop:\n" + "prop: foo =\n" + "prop: bar = # A comment.\n" + "\n" + "tp\n" + "tp:\n" + "tp: # A comment.\n" + "\n" + "tp-glob\n" + "tp-glob:\n" + "tp-glob: # A comment.\n" + ; + + const char* exp_calls[] = { + NULL + }; + + const char* exp_errors[] = { + "3: Unexpected token `<>'; expected `:'", + "4: Unexpected token `<>'; expected variable name", + "5: Unexpected token `<>'; expected word or quoted string", + "6: Unexpected token `#'; expected word or quoted string", + "8: Unexpected token `<>'; expected `:'", + "9: Unexpected token `<>'; expected property name", + "10: Unexpected token `<>'; expected word or quoted string", + "11: Unexpected token `#'; expected word or quoted string", + "13: Unexpected token `<>'; expected `:'", + "14: Unexpected token `<>'; expected word or quoted string", + "15: Unexpected token `#'; expected word or quoted string", + "17: Unexpected token `<>'; expected `:'", + "18: Unexpected token `<>'; expected word or quoted string", + "19: Unexpected token `#'; expected word or quoted string", + NULL + }; + + do_parser_test< atffile_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(atffile_53); +ATF_TEST_CASE_BODY(atffile_53) +{ + const char* input = + "Content-Type: application/X-atf-atffile; version=\"1\"\n" + "\n" + "prop: foo = \"Correct value\" # With comment.\n" + "\n" + "prop: bar = # A comment.\n" + "\n" + "prop: baz = \"Last variable\"\n" + "\n" + "# End of file.\n" + ; + + const char* exp_calls[] = { + "got_prop(foo, Correct value)", + NULL + }; + + const char* exp_errors[] = { + "5: Unexpected token `#'; expected word or quoted string", + NULL + }; + + do_parser_test< atffile_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(atffile_54); +ATF_TEST_CASE_BODY(atffile_54) +{ + const char* input = + "Content-Type: application/X-atf-atffile; version=\"1\"\n" + "\n" + "prop: foo = \"\n" + "prop: bar = \"text\n" + "prop: baz = \"te\\\"xt\n" + "prop: last = \"\\\"\n" + ; + + const char* exp_calls[] = { + NULL + }; + + const char* exp_errors[] = { + "3: Missing double quotes before end of line", + "4: Missing double quotes before end of line", + "5: Missing double quotes before end of line", + "6: Missing double quotes before end of line", + NULL + }; + + do_parser_test< atffile_reader >(input, exp_calls, exp_errors); +} + +// ------------------------------------------------------------------------ +// Tests cases for the "atffile" class. +// ------------------------------------------------------------------------ + +ATF_TEST_CASE(atffile_getters); +ATF_TEST_CASE_HEAD(atffile_getters) {} +ATF_TEST_CASE_BODY(atffile_getters) { + atf::tests::vars_map config_vars; + config_vars["config-var-1"] = "value 1"; + + std::vector< std::string > test_program_names; + test_program_names.push_back("test-program-1"); + + atf::tests::vars_map properties; + properties["test-suite"] = "a test name"; + + const atf::atf_run::atffile atffile(config_vars, test_program_names, + properties); + ATF_REQUIRE(config_vars == atffile.conf()); + ATF_REQUIRE(test_program_names == atffile.tps()); + ATF_REQUIRE(properties == atffile.props()); +} + +// ------------------------------------------------------------------------ +// Tests cases for the free functions. +// ------------------------------------------------------------------------ + +ATF_TEST_CASE_WITHOUT_HEAD(read_ok_simple); +ATF_TEST_CASE_BODY(read_ok_simple) { + std::auto_ptr< std::ofstream > os = new_atffile(); + (*os) << "prop: test-suite = foo\n"; + (*os) << "tp: tp-1\n"; + (*os) << "conf: var1 = value1\n"; + (*os) << "tp: tp-2\n"; + (*os) << "tp: tp-3\n"; + (*os) << "prop: prop1 = propvalue1\n"; + (*os) << "conf: var2 = value2\n"; + (*os).close(); + + touch_exec("tp-1"); + touch_exec("tp-2"); + touch_exec("tp-3"); + + const atf::atf_run::atffile atffile = atf::atf_run::read_atffile( + atf::fs::path("Atffile")); + ATF_REQUIRE_EQ(2, atffile.conf().size()); + ATF_REQUIRE_EQ("value1", atffile.conf().find("var1")->second); + ATF_REQUIRE_EQ("value2", atffile.conf().find("var2")->second); + ATF_REQUIRE_EQ(3, atffile.tps().size()); + ATF_REQUIRE(is_in("tp-1", atffile.tps())); + ATF_REQUIRE(is_in("tp-2", atffile.tps())); + ATF_REQUIRE(is_in("tp-3", atffile.tps())); + ATF_REQUIRE_EQ(2, atffile.props().size()); + ATF_REQUIRE_EQ("foo", atffile.props().find("test-suite")->second); + ATF_REQUIRE_EQ("propvalue1", atffile.props().find("prop1")->second); +} + +ATF_TEST_CASE_WITHOUT_HEAD(read_ok_some_globs); +ATF_TEST_CASE_BODY(read_ok_some_globs) { + std::auto_ptr< std::ofstream > os = new_atffile(); + (*os) << "prop: test-suite = foo\n"; + (*os) << "tp: foo\n"; + (*os) << "tp-glob: *K*\n"; + (*os) << "tp: bar\n"; + (*os) << "tp-glob: t_*\n"; + (*os).close(); + + touch_exec("foo"); + touch_exec("bar"); + touch_exec("aK"); + touch_exec("KKKKK"); + touch_exec("t_hello"); + touch_exec("zzzt_hello"); + + const atf::atf_run::atffile atffile = atf::atf_run::read_atffile( + atf::fs::path("Atffile")); + ATF_REQUIRE_EQ(5, atffile.tps().size()); + ATF_REQUIRE(is_in("foo", atffile.tps())); + ATF_REQUIRE(is_in("bar", atffile.tps())); + ATF_REQUIRE(is_in("aK", atffile.tps())); + ATF_REQUIRE(is_in("KKKKK", atffile.tps())); + ATF_REQUIRE(is_in("t_hello", atffile.tps())); +} + +ATF_TEST_CASE_WITHOUT_HEAD(read_missing_test_suite); +ATF_TEST_CASE_BODY(read_missing_test_suite) { + std::auto_ptr< std::ofstream > os = new_atffile(); + (*os).close(); + + try { + (void)atf::atf_run::read_atffile(atf::fs::path("Atffile")); + ATF_FAIL("Missing property 'test-suite' did not raise an error"); + } catch (const atf::not_found_error< std::string >& e) { + ATF_REQUIRE_EQ("test-suite", e.get_value()); + } +} + +ATF_TEST_CASE_WITHOUT_HEAD(read_missing_test_program); +ATF_TEST_CASE_BODY(read_missing_test_program) { + std::auto_ptr< std::ofstream > os = new_atffile(); + (*os) << "tp: foo\n"; + (*os) << "tp: bar\n"; + (*os) << "tp: baz\n"; + (*os).close(); + + touch_exec("foo"); + touch_exec("baz"); + + try { + (void)atf::atf_run::read_atffile(atf::fs::path("Atffile")); + ATF_FAIL("Missing file 'bar' did not raise an error"); + } catch (const atf::not_found_error< atf::fs::path >& e) { + ATF_REQUIRE_EQ("bar", e.get_value().str()); + } +} + +// ------------------------------------------------------------------------ +// Main. +// ------------------------------------------------------------------------ + +ATF_INIT_TEST_CASES(tcs) +{ + // Add the test cases for the parser class. + ATF_ADD_TEST_CASE(tcs, atffile_1); + ATF_ADD_TEST_CASE(tcs, atffile_2); + ATF_ADD_TEST_CASE(tcs, atffile_3); + ATF_ADD_TEST_CASE(tcs, atffile_4); + ATF_ADD_TEST_CASE(tcs, atffile_5); + ATF_ADD_TEST_CASE(tcs, atffile_6); + ATF_ADD_TEST_CASE(tcs, atffile_50); + ATF_ADD_TEST_CASE(tcs, atffile_51); + ATF_ADD_TEST_CASE(tcs, atffile_52); + ATF_ADD_TEST_CASE(tcs, atffile_53); + ATF_ADD_TEST_CASE(tcs, atffile_54); + + // Add the test cases for the atffile class. + ATF_ADD_TEST_CASE(tcs, atffile_getters); + + // Add the test cases for the free functions. + ATF_ADD_TEST_CASE(tcs, read_ok_simple); + ATF_ADD_TEST_CASE(tcs, read_ok_some_globs); + ATF_ADD_TEST_CASE(tcs, read_missing_test_suite); + ATF_ADD_TEST_CASE(tcs, read_missing_test_program); +} diff --git a/external/bsd/atf/dist/atf-run/bad_metadata_helper.c b/external/bsd/atf/dist/atf-run/bad_metadata_helper.c new file mode 100644 index 000000000..0f7fcb926 --- /dev/null +++ b/external/bsd/atf/dist/atf-run/bad_metadata_helper.c @@ -0,0 +1,38 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2010 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +int +main(void) +{ + printf("incorrectly formatted metadata\n"); + return EXIT_SUCCESS; +} diff --git a/external/bsd/atf/dist/atf-run/config.cpp b/external/bsd/atf/dist/atf-run/config.cpp new file mode 100644 index 000000000..0ea240fe2 --- /dev/null +++ b/external/bsd/atf/dist/atf-run/config.cpp @@ -0,0 +1,224 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#include +#include + +#include "atf-c/defs.h" + +#include "atf-c++/config.hpp" + +#include "atf-c++/detail/env.hpp" +#include "atf-c++/detail/fs.hpp" +#include "atf-c++/detail/sanity.hpp" +#include "atf-c++/detail/parser.hpp" + +#include "config.hpp" + +namespace impl = atf::atf_run; +namespace detail = atf::atf_run::detail; + +namespace { + +namespace atf_config { + +static const atf::parser::token_type eof_type = 0; +static const atf::parser::token_type nl_type = 1; +static const atf::parser::token_type text_type = 2; +static const atf::parser::token_type dblquote_type = 3; +static const atf::parser::token_type equal_type = 4; +static const atf::parser::token_type hash_type = 5; + +class tokenizer : public atf::parser::tokenizer< std::istream > { +public: + tokenizer(std::istream& is, size_t curline) : + atf::parser::tokenizer< std::istream > + (is, true, eof_type, nl_type, text_type, curline) + { + add_delim('=', equal_type); + add_delim('#', hash_type); + add_quote('"', dblquote_type); + } +}; + +} // namespace atf_config + +class config_reader : public detail::atf_config_reader { + atf::tests::vars_map m_vars; + + void + got_var(const std::string& var, const std::string& name) + { + m_vars[var] = name; + } + +public: + config_reader(std::istream& is) : + atf_config_reader(is) + { + } + + const atf::tests::vars_map& + get_vars(void) + const + { + return m_vars; + } +}; + +template< class K, class V > +static +void +merge_maps(std::map< K, V >& dest, const std::map< K, V >& src) +{ + for (typename std::map< K, V >::const_iterator iter = src.begin(); + iter != src.end(); iter++) + dest[(*iter).first] = (*iter).second; +} + +static +void +merge_config_file(const atf::fs::path& config_path, + atf::tests::vars_map& config) +{ + std::ifstream is(config_path.c_str()); + if (is) { + config_reader reader(is); + reader.read(); + merge_maps(config, reader.get_vars()); + } +} + +static +std::vector< atf::fs::path > +get_config_dirs(void) +{ + std::vector< atf::fs::path > dirs; + dirs.push_back(atf::fs::path(atf::config::get("atf_confdir"))); + if (atf::env::has("HOME")) + dirs.push_back(atf::fs::path(atf::env::get("HOME")) / ".atf"); + return dirs; +} + +} // anonymous namespace + +detail::atf_config_reader::atf_config_reader(std::istream& is) : + m_is(is) +{ +} + +detail::atf_config_reader::~atf_config_reader(void) +{ +} + +void +detail::atf_config_reader::got_var( + const std::string& var ATF_DEFS_ATTRIBUTE_UNUSED, + const std::string& val ATF_DEFS_ATTRIBUTE_UNUSED) +{ +} + +void +detail::atf_config_reader::got_eof(void) +{ +} + +void +detail::atf_config_reader::read(void) +{ + using atf::parser::parse_error; + using namespace atf_config; + + std::pair< size_t, atf::parser::headers_map > hml = + atf::parser::read_headers(m_is, 1); + atf::parser::validate_content_type(hml.second, + "application/X-atf-config", 1); + + tokenizer tkz(m_is, hml.first); + atf::parser::parser< tokenizer > p(tkz); + + for (;;) { + try { + atf::parser::token t = p.expect(eof_type, hash_type, text_type, + nl_type, + "eof, #, new line or text"); + if (t.type() == eof_type) + break; + + if (t.type() == hash_type) { + (void)p.rest_of_line(); + t = p.expect(nl_type, "new line"); + } else if (t.type() == text_type) { + std::string name = t.text(); + + t = p.expect(equal_type, "equal sign"); + + t = p.expect(text_type, "word or quoted string"); + ATF_PARSER_CALLBACK(p, got_var(name, t.text())); + + t = p.expect(nl_type, hash_type, "new line or comment"); + if (t.type() == hash_type) { + (void)p.rest_of_line(); + t = p.expect(nl_type, "new line"); + } + } else if (t.type() == nl_type) { + } else + UNREACHABLE; + } catch (const parse_error& pe) { + p.add_error(pe); + p.reset(nl_type); + } + } + + ATF_PARSER_CALLBACK(p, got_eof()); +} + +atf::tests::vars_map +impl::merge_configs(const atf::tests::vars_map& lower, + const atf::tests::vars_map& upper) +{ + atf::tests::vars_map merged = lower; + merge_maps(merged, upper); + return merged; +} + +atf::tests::vars_map +impl::read_config_files(const std::string& test_suite_name) +{ + atf::tests::vars_map config; + + const std::vector< atf::fs::path > dirs = get_config_dirs(); + for (std::vector< atf::fs::path >::const_iterator iter = dirs.begin(); + iter != dirs.end(); iter++) { + merge_config_file((*iter) / "common.conf", config); + merge_config_file((*iter) / (test_suite_name + ".conf"), config); + } + + return config; +} diff --git a/external/bsd/atf/dist/atf-run/config.hpp b/external/bsd/atf/dist/atf-run/config.hpp new file mode 100644 index 000000000..2cefec9a5 --- /dev/null +++ b/external/bsd/atf/dist/atf-run/config.hpp @@ -0,0 +1,61 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2010 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#include +#include + +#include "atf-c++/tests.hpp" + +namespace atf { +namespace atf_run { + +namespace detail { + +class atf_config_reader { + std::istream& m_is; + +protected: + virtual void got_var(const std::string&, const std::string &); + virtual void got_eof(void); + +public: + atf_config_reader(std::istream&); + virtual ~atf_config_reader(void); + + void read(void); +}; + +} // namespace detail + +atf::tests::vars_map merge_configs(const atf::tests::vars_map&, + const atf::tests::vars_map&); +atf::tests::vars_map read_config_files(const std::string&); + +} // namespace atf_run +} // namespace atf diff --git a/external/bsd/atf/dist/atf-run/config_test.cpp b/external/bsd/atf/dist/atf-run/config_test.cpp new file mode 100644 index 000000000..5b103a78a --- /dev/null +++ b/external/bsd/atf/dist/atf-run/config_test.cpp @@ -0,0 +1,391 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2010 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#include "atf-c++/detail/env.hpp" +#include "atf-c++/detail/test_helpers.hpp" +#include "atf-c++/config.hpp" +#include "atf-c++/macros.hpp" + +#include "config.hpp" + +namespace impl = atf::atf_run; +namespace detail = atf::atf_run::detail; + +using atf::tests::vars_map; + +namespace atf { +namespace config { + +void __reinit(void); + +} // namespace config +} // namespace atf + +// ------------------------------------------------------------------------- +// Tests for the "config" parser. +// ------------------------------------------------------------------------- + +class config_reader : protected detail::atf_config_reader { + void + got_var(const std::string& name, const std::string& val) + { + m_calls.push_back("got_var(" + name + ", " + val + ")"); + } + + void + got_eof(void) + { + m_calls.push_back("got_eof()"); + } + +public: + config_reader(std::istream& is) : + detail::atf_config_reader(is) + { + } + + void + read(void) + { + atf_config_reader::read(); + } + + std::vector< std::string > m_calls; +}; + +ATF_TEST_CASE_WITHOUT_HEAD(config_1); +ATF_TEST_CASE_BODY(config_1) +{ + const char* input = + "Content-Type: application/X-atf-config; version=\"1\"\n" + "\n" + ; + + const char* exp_calls[] = { + "got_eof()", + NULL + }; + + const char* exp_errors[] = { + NULL + }; + + do_parser_test< config_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(config_2); +ATF_TEST_CASE_BODY(config_2) +{ + const char* input = + "Content-Type: application/X-atf-config; version=\"1\"\n" + "\n" + "# This is a comment on a line of its own.\n" + "# And this is another one.\n" + "\n" + " # Another after some whitespace.\n" + "\n" + "# The last one after an empty line.\n" + ; + + const char* exp_calls[] = { + "got_eof()", + NULL + }; + + const char* exp_errors[] = { + NULL + }; + + do_parser_test< config_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(config_3); +ATF_TEST_CASE_BODY(config_3) +{ + const char* input = + "Content-Type: application/X-atf-config; version=\"1\"\n" + "\n" + "var1=value1\n" + "var2 = value2\n" + "var3 = value3\n" + "var4 = value4\n" + "\n" + "var5=value5\n" + " var6=value6\n" + "\n" + "var7 = \"This is a long value.\"\n" + "var8 = \"Single-word\"\n" + "var9 = \" Single-word \"\n" + "var10 = Single-word\n" + ; + + const char* exp_calls[] = { + "got_var(var1, value1)", + "got_var(var2, value2)", + "got_var(var3, value3)", + "got_var(var4, value4)", + "got_var(var5, value5)", + "got_var(var6, value6)", + "got_var(var7, This is a long value.)", + "got_var(var8, Single-word)", + "got_var(var9, Single-word )", + "got_var(var10, Single-word)", + "got_eof()", + NULL + }; + + const char* exp_errors[] = { + NULL + }; + + do_parser_test< config_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(config_4); +ATF_TEST_CASE_BODY(config_4) +{ + const char* input = + "Content-Type: application/X-atf-config; version=\"1\"\n" + "\n" + "foo = bar # A comment.\n" + ; + + const char* exp_calls[] = { + "got_var(foo, bar)", + "got_eof()", + NULL + }; + + const char* exp_errors[] = { + NULL + }; + + do_parser_test< config_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(config_50); +ATF_TEST_CASE_BODY(config_50) +{ + const char* input = + "Content-Type: application/X-atf-config; version=\"1\"\n" + "\n" + "foo\n" + ; + + const char* exp_calls[] = { + NULL + }; + + const char* exp_errors[] = { + "3: Unexpected token `<>'; expected equal sign", + NULL + }; + + do_parser_test< config_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(config_51); +ATF_TEST_CASE_BODY(config_51) +{ + const char* input = + "Content-Type: application/X-atf-config; version=\"1\"\n" + "\n" + "foo bar\n" + "baz\n" + ; + + const char* exp_calls[] = { + NULL + }; + + const char* exp_errors[] = { + "3: Unexpected token `bar'; expected equal sign", + "4: Unexpected token `<>'; expected equal sign", + NULL + }; + + do_parser_test< config_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(config_52); +ATF_TEST_CASE_BODY(config_52) +{ + const char* input = + "Content-Type: application/X-atf-config; version=\"1\"\n" + "\n" + "foo =\n" + "bar = # A comment.\n" + ; + + const char* exp_calls[] = { + NULL + }; + + const char* exp_errors[] = { + "3: Unexpected token `<>'; expected word or quoted string", + "4: Unexpected token `#'; expected word or quoted string", + NULL + }; + + do_parser_test< config_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(config_53); +ATF_TEST_CASE_BODY(config_53) +{ + const char* input = + "Content-Type: application/X-atf-config; version=\"1\"\n" + "\n" + "foo = \"Correct value\" # With comment.\n" + "\n" + "bar = # A comment.\n" + "\n" + "baz = \"Last variable\"\n" + "\n" + "# End of file.\n" + ; + + const char* exp_calls[] = { + "got_var(foo, Correct value)", + NULL + }; + + const char* exp_errors[] = { + "5: Unexpected token `#'; expected word or quoted string", + NULL + }; + + do_parser_test< config_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(config_54); +ATF_TEST_CASE_BODY(config_54) +{ + const char* input = + "Content-Type: application/X-atf-config; version=\"1\"\n" + "\n" + "foo = \"\n" + "bar = \"text\n" + "baz = \"te\\\"xt\n" + "last = \"\\\"\n" + ; + + const char* exp_calls[] = { + NULL + }; + + const char* exp_errors[] = { + "3: Missing double quotes before end of line", + "4: Missing double quotes before end of line", + "5: Missing double quotes before end of line", + "6: Missing double quotes before end of line", + NULL + }; + + do_parser_test< config_reader >(input, exp_calls, exp_errors); +} + +// ------------------------------------------------------------------------- +// Tests for the free functions. +// ------------------------------------------------------------------------- + +ATF_TEST_CASE(merge_configs_both_empty); +ATF_TEST_CASE_HEAD(merge_configs_both_empty) {} +ATF_TEST_CASE_BODY(merge_configs_both_empty) { + vars_map lower, upper; + + ATF_REQUIRE(impl::merge_configs(lower, upper).empty()); +} + +ATF_TEST_CASE(merge_configs_lower_empty); +ATF_TEST_CASE_HEAD(merge_configs_lower_empty) {} +ATF_TEST_CASE_BODY(merge_configs_lower_empty) { + vars_map lower, upper; + upper["var"] = "value"; + + vars_map merged = impl::merge_configs(lower, upper); + ATF_REQUIRE_EQ("value", merged["var"]); +} + +ATF_TEST_CASE(merge_configs_upper_empty); +ATF_TEST_CASE_HEAD(merge_configs_upper_empty) {} +ATF_TEST_CASE_BODY(merge_configs_upper_empty) { + vars_map lower, upper; + lower["var"] = "value"; + + vars_map merged = impl::merge_configs(lower, upper); + ATF_REQUIRE_EQ("value", merged["var"]); +} + +ATF_TEST_CASE(merge_configs_mixed); +ATF_TEST_CASE_HEAD(merge_configs_mixed) {} +ATF_TEST_CASE_BODY(merge_configs_mixed) { + vars_map lower, upper; + lower["var1"] = "value1"; + lower["var2"] = "value2-l"; + upper["var2"] = "value2-u"; + upper["var3"] = "value3"; + + vars_map merged = impl::merge_configs(lower, upper); + ATF_REQUIRE_EQ("value1", merged["var1"]); + ATF_REQUIRE_EQ("value2-u", merged["var2"]); + ATF_REQUIRE_EQ("value3", merged["var3"]); +} + +ATF_TEST_CASE(read_config_files_none); +ATF_TEST_CASE_HEAD(read_config_files_none) {} +ATF_TEST_CASE_BODY(read_config_files_none) { + atf::env::set("ATF_CONFDIR", "."); + atf::config::__reinit(); + ATF_REQUIRE(vars_map() == impl::read_config_files("test-suite")); +} + +// ------------------------------------------------------------------------- +// Main. +// ------------------------------------------------------------------------- + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, config_1); + ATF_ADD_TEST_CASE(tcs, config_2); + ATF_ADD_TEST_CASE(tcs, config_3); + ATF_ADD_TEST_CASE(tcs, config_4); + ATF_ADD_TEST_CASE(tcs, config_50); + ATF_ADD_TEST_CASE(tcs, config_51); + ATF_ADD_TEST_CASE(tcs, config_52); + ATF_ADD_TEST_CASE(tcs, config_53); + ATF_ADD_TEST_CASE(tcs, config_54); + + ATF_ADD_TEST_CASE(tcs, merge_configs_both_empty); + ATF_ADD_TEST_CASE(tcs, merge_configs_lower_empty); + ATF_ADD_TEST_CASE(tcs, merge_configs_upper_empty); + ATF_ADD_TEST_CASE(tcs, merge_configs_mixed); + + ATF_ADD_TEST_CASE(tcs, read_config_files_none); +} diff --git a/external/bsd/atf/dist/atf-run/expect_helpers.c b/external/bsd/atf/dist/atf-run/expect_helpers.c new file mode 100644 index 000000000..b38ccf574 --- /dev/null +++ b/external/bsd/atf/dist/atf-run/expect_helpers.c @@ -0,0 +1,193 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2010 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +#include + +ATF_TC_WITHOUT_HEAD(pass_and_pass); +ATF_TC_BODY(pass_and_pass, tc) +{ + atf_tc_expect_pass(); +} + +ATF_TC_WITHOUT_HEAD(pass_but_fail_requirement); +ATF_TC_BODY(pass_but_fail_requirement, tc) +{ + atf_tc_expect_pass(); + atf_tc_fail("Some reason"); +} + +ATF_TC_WITHOUT_HEAD(pass_but_fail_check); +ATF_TC_BODY(pass_but_fail_check, tc) +{ + atf_tc_expect_pass(); + atf_tc_fail_nonfatal("Some reason"); +} + +ATF_TC_WITHOUT_HEAD(fail_and_fail_requirement); +ATF_TC_BODY(fail_and_fail_requirement, tc) +{ + atf_tc_expect_fail("Fail %s", "reason"); + atf_tc_fail("The failure"); + atf_tc_expect_pass(); +} + +ATF_TC_WITHOUT_HEAD(fail_and_fail_check); +ATF_TC_BODY(fail_and_fail_check, tc) +{ + atf_tc_expect_fail("Fail first"); + atf_tc_fail_nonfatal("abc"); + atf_tc_expect_pass(); + + atf_tc_expect_fail("And fail again"); + atf_tc_fail_nonfatal("def"); + atf_tc_expect_pass(); +} + +ATF_TC_WITHOUT_HEAD(fail_but_pass); +ATF_TC_BODY(fail_but_pass, tc) +{ + atf_tc_expect_fail("Fail first"); + atf_tc_fail_nonfatal("abc"); + atf_tc_expect_pass(); + + atf_tc_expect_fail("Will not fail"); + atf_tc_expect_pass(); + + atf_tc_expect_fail("And fail again"); + atf_tc_fail_nonfatal("def"); + atf_tc_expect_pass(); +} + +ATF_TC_WITHOUT_HEAD(exit_any_and_exit); +ATF_TC_BODY(exit_any_and_exit, tc) +{ + atf_tc_expect_exit(-1, "Call will exit"); + exit(EXIT_SUCCESS); +} + +ATF_TC_WITHOUT_HEAD(exit_code_and_exit); +ATF_TC_BODY(exit_code_and_exit, tc) +{ + atf_tc_expect_exit(123, "Call will exit"); + exit(123); +} + +ATF_TC_WITHOUT_HEAD(exit_but_pass); +ATF_TC_BODY(exit_but_pass, tc) +{ + atf_tc_expect_exit(-1, "Call won't exit"); +} + +ATF_TC_WITHOUT_HEAD(signal_any_and_signal); +ATF_TC_BODY(signal_any_and_signal, tc) +{ + atf_tc_expect_signal(-1, "Call will signal"); + kill(getpid(), SIGKILL); +} + +ATF_TC_WITHOUT_HEAD(signal_no_and_signal); +ATF_TC_BODY(signal_no_and_signal, tc) +{ + atf_tc_expect_signal(SIGHUP, "Call will signal"); + kill(getpid(), SIGHUP); +} + +ATF_TC_WITHOUT_HEAD(signal_but_pass); +ATF_TC_BODY(signal_but_pass, tc) +{ + atf_tc_expect_signal(-1, "Call won't signal"); +} + +ATF_TC_WITHOUT_HEAD(death_and_exit); +ATF_TC_BODY(death_and_exit, tc) +{ + atf_tc_expect_death("Exit case"); + exit(123); +} + +ATF_TC_WITHOUT_HEAD(death_and_signal); +ATF_TC_BODY(death_and_signal, tc) +{ + atf_tc_expect_death("Signal case"); + kill(getpid(), SIGKILL); +} + +ATF_TC_WITHOUT_HEAD(death_but_pass); +ATF_TC_BODY(death_but_pass, tc) +{ + atf_tc_expect_death("Call won't die"); +} + +ATF_TC(timeout_and_hang); +ATF_TC_HEAD(timeout_and_hang, tc) +{ + atf_tc_set_md_var(tc, "timeout", "1"); +} +ATF_TC_BODY(timeout_and_hang, tc) +{ + atf_tc_expect_timeout("Will overrun"); + sleep(5); +} + +ATF_TC(timeout_but_pass); +ATF_TC_HEAD(timeout_but_pass, tc) +{ + atf_tc_set_md_var(tc, "timeout", "1"); +} +ATF_TC_BODY(timeout_but_pass, tc) +{ + atf_tc_expect_timeout("Will just exit"); +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, pass_and_pass); + ATF_TP_ADD_TC(tp, pass_but_fail_requirement); + ATF_TP_ADD_TC(tp, pass_but_fail_check); + ATF_TP_ADD_TC(tp, fail_and_fail_requirement); + ATF_TP_ADD_TC(tp, fail_and_fail_check); + ATF_TP_ADD_TC(tp, fail_but_pass); + ATF_TP_ADD_TC(tp, exit_any_and_exit); + ATF_TP_ADD_TC(tp, exit_code_and_exit); + ATF_TP_ADD_TC(tp, exit_but_pass); + ATF_TP_ADD_TC(tp, signal_any_and_signal); + ATF_TP_ADD_TC(tp, signal_no_and_signal); + ATF_TP_ADD_TC(tp, signal_but_pass); + ATF_TP_ADD_TC(tp, death_and_exit); + ATF_TP_ADD_TC(tp, death_and_signal); + ATF_TP_ADD_TC(tp, death_but_pass); + ATF_TP_ADD_TC(tp, timeout_and_hang); + ATF_TP_ADD_TC(tp, timeout_but_pass); + + return atf_no_error(); +} diff --git a/external/bsd/atf/dist/atf-run/fs.cpp b/external/bsd/atf/dist/atf-run/fs.cpp new file mode 100644 index 000000000..e84a90da7 --- /dev/null +++ b/external/bsd/atf/dist/atf-run/fs.cpp @@ -0,0 +1,265 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#if defined(HAVE_CONFIG_H) +#include "bconfig.h" +#endif + +extern "C" { +#include +#include +#include +#include + +#include +} + +#include +#include +#include + +#include "atf-c++/detail/auto_array.hpp" +#include "atf-c++/detail/process.hpp" +#include "atf-c++/detail/sanity.hpp" + +#include "fs.hpp" +#include "user.hpp" + +namespace impl = atf::atf_run; +#define IMPL_NAME "atf::atf_run" + +// ------------------------------------------------------------------------ +// Auxiliary functions. +// ------------------------------------------------------------------------ + +static void cleanup_aux(const atf::fs::path&, dev_t, bool); +static void cleanup_aux_dir(const atf::fs::path&, const atf::fs::file_info&, + bool); +static void do_unmount(const atf::fs::path&); + +// The cleanup routines below are tricky: they are executed immediately after +// a test case's death, and after we have forcibly killed any stale processes. +// However, even if the processes are dead, this does not mean that the file +// system we are scanning is stable. In particular, if the test case has +// mounted file systems through fuse/puffs, the fact that the processes died +// does not mean that the file system is truly unmounted. +// +// The code below attempts to cope with this by catching errors and either +// ignoring them or retrying the actions on the same file/directory a few times +// before giving up. +static const int max_retries = 5; +static const int retry_delay_in_seconds = 1; + +// The erase parameter in this routine is to control nested mount points. +// We want to descend into a mount point to unmount anything that is +// mounted under it, but we do not want to delete any files while doing +// this traversal. In other words, we erase files until we cross the +// first mount point, and after that point we only scan and unmount. +static +void +cleanup_aux(const atf::fs::path& p, dev_t parent_device, bool erase) +{ + try { + atf::fs::file_info fi(p); + + if (fi.get_type() == atf::fs::file_info::dir_type) + cleanup_aux_dir(p, fi, fi.get_device() == parent_device); + + if (fi.get_device() != parent_device) + do_unmount(p); + + if (erase) { + if (fi.get_type() == atf::fs::file_info::dir_type) + atf::fs::rmdir(p); + else + atf::fs::remove(p); + } + } catch (const atf::system_error& e) { + if (e.code() != ENOENT && e.code() != ENOTDIR) + throw e; + } +} + +static +void +cleanup_aux_dir(const atf::fs::path& p, const atf::fs::file_info& fi, + bool erase) +{ + if (erase && ((fi.get_mode() & S_IRWXU) != S_IRWXU)) { + int retries = max_retries; +retry_chmod: + if (chmod(p.c_str(), fi.get_mode() | S_IRWXU) == -1) { + if (retries > 0) { + retries--; + ::sleep(retry_delay_in_seconds); + goto retry_chmod; + } else { + throw atf::system_error(IMPL_NAME "::cleanup(" + + p.str() + ")", "chmod(2) failed", + errno); + } + } + } + + std::set< std::string > subdirs; + { + bool ok = false; + int retries = max_retries; + while (!ok) { + INV(retries > 0); + try { + const atf::fs::directory d(p); + subdirs = d.names(); + ok = true; + } catch (const atf::system_error& e) { + retries--; + if (retries == 0) + throw e; + ::sleep(retry_delay_in_seconds); + } + } + INV(ok); + } + + for (std::set< std::string >::const_iterator iter = subdirs.begin(); + iter != subdirs.end(); iter++) { + const std::string& name = *iter; + if (name != "." && name != "..") + cleanup_aux(p / name, fi.get_device(), erase); + } +} + +static +void +do_unmount(const atf::fs::path& in_path) +{ + // At least, FreeBSD's unmount(2) requires the path to be absolute. + // Let's make it absolute in all cases just to be safe that this does + // not affect other systems. + const atf::fs::path& abs_path = in_path.is_absolute() ? + in_path : in_path.to_absolute(); + +#if defined(HAVE_UNMOUNT) + int retries = max_retries; +retry_unmount: + if (unmount(abs_path.c_str(), 0) == -1) { + if (errno == EBUSY && retries > 0) { + retries--; + ::sleep(retry_delay_in_seconds); + goto retry_unmount; + } else { + throw atf::system_error(IMPL_NAME "::cleanup(" + in_path.str() + + ")", "unmount(2) failed", errno); + } + } +#else + // We could use umount(2) instead if it was available... but + // trying to do so under, e.g. Linux, is a nightmare because we + // also have to update /etc/mtab to match what we did. It is + // satf::fser to just leave the system-specific umount(8) tool deal + // with it, at least for now. + + const atf::fs::path prog("umount"); + atf::process::argv_array argv("umount", abs_path.c_str(), NULL); + + atf::process::status s = atf::process::exec(prog, argv, + atf::process::stream_inherit(), atf::process::stream_inherit()); + if (!s.exited() || s.exitstatus() != EXIT_SUCCESS) + throw std::runtime_error("Call to unmount failed"); +#endif +} + +// ------------------------------------------------------------------------ +// The "temp_dir" class. +// ------------------------------------------------------------------------ + +impl::temp_dir::temp_dir(const atf::fs::path& p) +{ + atf::auto_array< char > buf(new char[p.str().length() + 1]); + std::strcpy(buf.get(), p.c_str()); + if (::mkdtemp(buf.get()) == NULL) + throw system_error(IMPL_NAME "::temp_dir::temp_dir(" + + p.str() + ")", "mkdtemp(3) failed", + errno); + + m_path.reset(new atf::fs::path(buf.get())); +} + +impl::temp_dir::~temp_dir(void) +{ + cleanup(*m_path); +} + +const atf::fs::path& +impl::temp_dir::get_path(void) + const +{ + return *m_path; +} + +// ------------------------------------------------------------------------ +// Free functions. +// ------------------------------------------------------------------------ + +atf::fs::path +impl::change_directory(const atf::fs::path& dir) +{ + atf::fs::path olddir = get_current_dir(); + + if (olddir != dir) { + if (::chdir(dir.c_str()) == -1) + throw system_error(IMPL_NAME "::chdir(" + dir.str() + ")", + "chdir(2) failed", errno); + } + + return olddir; +} + +void +impl::cleanup(const atf::fs::path& p) +{ + atf::fs::file_info fi(p); + cleanup_aux(p, fi.get_device(), true); +} + +atf::fs::path +impl::get_current_dir(void) +{ + std::auto_ptr< char > cwd; +#if defined(HAVE_GETCWD_DYN) + cwd.reset(getcwd(NULL, 0)); +#else + cwd.reset(getcwd(NULL, MAXPATHLEN)); +#endif + if (cwd.get() == NULL) + throw atf::system_error(IMPL_NAME "::get_current_dir()", + "getcwd() failed", errno); + + return atf::fs::path(cwd.get()); +} diff --git a/external/bsd/atf/dist/atf-run/fs.hpp b/external/bsd/atf/dist/atf-run/fs.hpp new file mode 100644 index 000000000..37382684b --- /dev/null +++ b/external/bsd/atf/dist/atf-run/fs.hpp @@ -0,0 +1,57 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#if !defined(_ATF_RUN_FS_HPP_) +#define _ATF_RUN_FS_HPP_ + +#include + +#include "atf-c++/detail/fs.hpp" + +namespace atf { +namespace atf_run { + +class temp_dir { + std::auto_ptr< atf::fs::path > m_path; + +public: + temp_dir(const atf::fs::path&); + ~temp_dir(void); + + const atf::fs::path& get_path(void) const; +}; + +atf::fs::path change_directory(const atf::fs::path&); +void cleanup(const atf::fs::path&); +atf::fs::path get_current_dir(void); + +} // namespace atf_run +} // namespace atf + +#endif // !defined(_ATF_RUN_FS_HPP_) diff --git a/external/bsd/atf/dist/atf-run/fs_test.cpp b/external/bsd/atf/dist/atf-run/fs_test.cpp new file mode 100644 index 000000000..f03045eb6 --- /dev/null +++ b/external/bsd/atf/dist/atf-run/fs_test.cpp @@ -0,0 +1,260 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +extern "C" { +#include +#include +} + +#include +#include + +#include "atf-c++/macros.hpp" + +#include "atf-c++/detail/exceptions.hpp" +#include "atf-c++/detail/fs.hpp" + +#include "fs.hpp" +#include "user.hpp" + +// ------------------------------------------------------------------------ +// Auxiliary functions. +// ------------------------------------------------------------------------ + +static +void +create_file(const char *name) +{ + std::ofstream os(name); + os.close(); +} + +// ------------------------------------------------------------------------ +// Test cases for the "temp_dir" class. +// ------------------------------------------------------------------------ + +ATF_TEST_CASE(temp_dir_raii); +ATF_TEST_CASE_HEAD(temp_dir_raii) +{ + set_md_var("descr", "Tests the RAII behavior of the temp_dir class"); +} +ATF_TEST_CASE_BODY(temp_dir_raii) +{ + using atf::atf_run::temp_dir; + + atf::fs::path t1("non-existent"); + atf::fs::path t2("non-existent"); + + { + atf::fs::path tmpl("testdir.XXXXXX"); + temp_dir td1(tmpl); + temp_dir td2(tmpl); + t1 = td1.get_path(); + t2 = td2.get_path(); + ATF_REQUIRE(t1.str().find("XXXXXX") == std::string::npos); + ATF_REQUIRE(t2.str().find("XXXXXX") == std::string::npos); + ATF_REQUIRE(t1 != t2); + ATF_REQUIRE(!atf::fs::exists(tmpl)); + ATF_REQUIRE( atf::fs::exists(t1)); + ATF_REQUIRE( atf::fs::exists(t2)); + + atf::fs::file_info fi1(t1); + ATF_REQUIRE( fi1.is_owner_readable()); + ATF_REQUIRE( fi1.is_owner_writable()); + ATF_REQUIRE( fi1.is_owner_executable()); + ATF_REQUIRE(!fi1.is_group_readable()); + ATF_REQUIRE(!fi1.is_group_writable()); + ATF_REQUIRE(!fi1.is_group_executable()); + ATF_REQUIRE(!fi1.is_other_readable()); + ATF_REQUIRE(!fi1.is_other_writable()); + ATF_REQUIRE(!fi1.is_other_executable()); + + atf::fs::file_info fi2(t2); + ATF_REQUIRE( fi2.is_owner_readable()); + ATF_REQUIRE( fi2.is_owner_writable()); + ATF_REQUIRE( fi2.is_owner_executable()); + ATF_REQUIRE(!fi2.is_group_readable()); + ATF_REQUIRE(!fi2.is_group_writable()); + ATF_REQUIRE(!fi2.is_group_executable()); + ATF_REQUIRE(!fi2.is_other_readable()); + ATF_REQUIRE(!fi2.is_other_writable()); + ATF_REQUIRE(!fi2.is_other_executable()); + } + + ATF_REQUIRE(t1.str() != "non-existent"); + ATF_REQUIRE(!atf::fs::exists(t1)); + ATF_REQUIRE(t2.str() != "non-existent"); + ATF_REQUIRE(!atf::fs::exists(t2)); +} + + +// ------------------------------------------------------------------------ +// Test cases for the free functions. +// ------------------------------------------------------------------------ + +ATF_TEST_CASE(cleanup); +ATF_TEST_CASE_HEAD(cleanup) +{ + set_md_var("descr", "Tests the cleanup function"); +} +ATF_TEST_CASE_BODY(cleanup) +{ + using atf::atf_run::cleanup; + + ::mkdir("root", 0755); + ::mkdir("root/dir", 0755); + ::mkdir("root/dir/1", 0100); + ::mkdir("root/dir/2", 0644); + create_file("root/reg"); + + atf::fs::path p("root"); + ATF_REQUIRE(atf::fs::exists(p)); + ATF_REQUIRE(atf::fs::exists(p / "dir")); + ATF_REQUIRE(atf::fs::exists(p / "dir/1")); + ATF_REQUIRE(atf::fs::exists(p / "dir/2")); + ATF_REQUIRE(atf::fs::exists(p / "reg")); + cleanup(p); + ATF_REQUIRE(!atf::fs::exists(p)); +} + +ATF_TEST_CASE(cleanup_eacces_on_root); +ATF_TEST_CASE_HEAD(cleanup_eacces_on_root) +{ + set_md_var("descr", "Tests the cleanup function"); +} +ATF_TEST_CASE_BODY(cleanup_eacces_on_root) +{ + using atf::atf_run::cleanup; + + ::mkdir("aux", 0755); + ::mkdir("aux/root", 0755); + ATF_REQUIRE(::chmod("aux", 0555) != -1); + + try { + cleanup(atf::fs::path("aux/root")); + ATF_REQUIRE(atf::atf_run::is_root()); + } catch (const atf::system_error& e) { + ATF_REQUIRE(!atf::atf_run::is_root()); + ATF_REQUIRE_EQ(EACCES, e.code()); + } +} + +ATF_TEST_CASE(cleanup_eacces_on_subdir); +ATF_TEST_CASE_HEAD(cleanup_eacces_on_subdir) +{ + set_md_var("descr", "Tests the cleanup function"); +} +ATF_TEST_CASE_BODY(cleanup_eacces_on_subdir) +{ + using atf::atf_run::cleanup; + + ::mkdir("root", 0755); + ::mkdir("root/1", 0755); + ::mkdir("root/1/2", 0755); + ::mkdir("root/1/2/3", 0755); + ATF_REQUIRE(::chmod("root/1/2", 0555) != -1); + ATF_REQUIRE(::chmod("root/1", 0555) != -1); + + const atf::fs::path p("root"); + cleanup(p); + ATF_REQUIRE(!atf::fs::exists(p)); +} + +ATF_TEST_CASE(change_directory); +ATF_TEST_CASE_HEAD(change_directory) +{ + set_md_var("descr", "Tests the change_directory function"); +} +ATF_TEST_CASE_BODY(change_directory) +{ + using atf::atf_run::change_directory; + using atf::atf_run::get_current_dir; + + ::mkdir("files", 0755); + ::mkdir("files/dir", 0755); + create_file("files/reg"); + + const atf::fs::path old = get_current_dir(); + + ATF_REQUIRE_THROW(atf::system_error, + change_directory(atf::fs::path("files/reg"))); + ATF_REQUIRE(get_current_dir() == old); + + atf::fs::path old2 = change_directory(atf::fs::path("files")); + ATF_REQUIRE(old2 == old); + atf::fs::path old3 = change_directory(atf::fs::path("dir")); + ATF_REQUIRE(old3 == old2 / "files"); + atf::fs::path old4 = change_directory(atf::fs::path("../..")); + ATF_REQUIRE(old4 == old3 / "dir"); + ATF_REQUIRE(get_current_dir() == old); +} + +ATF_TEST_CASE(get_current_dir); +ATF_TEST_CASE_HEAD(get_current_dir) +{ + set_md_var("descr", "Tests the get_current_dir function"); +} +ATF_TEST_CASE_BODY(get_current_dir) +{ + using atf::atf_run::change_directory; + using atf::atf_run::get_current_dir; + + ::mkdir("files", 0755); + ::mkdir("files/dir", 0755); + create_file("files/reg"); + + atf::fs::path curdir = get_current_dir(); + change_directory(atf::fs::path(".")); + ATF_REQUIRE(get_current_dir() == curdir); + change_directory(atf::fs::path("files")); + ATF_REQUIRE(get_current_dir() == curdir / "files"); + change_directory(atf::fs::path("dir")); + ATF_REQUIRE(get_current_dir() == curdir / "files/dir"); + change_directory(atf::fs::path("..")); + ATF_REQUIRE(get_current_dir() == curdir / "files"); + change_directory(atf::fs::path("..")); + ATF_REQUIRE(get_current_dir() == curdir); +} + +// ------------------------------------------------------------------------ +// Main. +// ------------------------------------------------------------------------ + +ATF_INIT_TEST_CASES(tcs) +{ + // Add the tests for the "temp_dir" class. + ATF_ADD_TEST_CASE(tcs, temp_dir_raii); + + // Add the tests for the free functions. + ATF_ADD_TEST_CASE(tcs, cleanup); + ATF_ADD_TEST_CASE(tcs, cleanup_eacces_on_root); + ATF_ADD_TEST_CASE(tcs, cleanup_eacces_on_subdir); + ATF_ADD_TEST_CASE(tcs, change_directory); + ATF_ADD_TEST_CASE(tcs, get_current_dir); +} diff --git a/external/bsd/atf/dist/atf-run/integration_test.sh b/external/bsd/atf/dist/atf-run/integration_test.sh new file mode 100644 index 000000000..afd013efb --- /dev/null +++ b/external/bsd/atf/dist/atf-run/integration_test.sh @@ -0,0 +1,1134 @@ +# +# Automated Testing Framework (atf) +# +# Copyright (c) 2007 The NetBSD Foundation, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +# CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +create_atffile() +{ + ATF_CONFDIR="$(pwd)"; export ATF_CONFDIR + + cat >Atffile <>Atffile + done +} + +create_helper() +{ + cp $(atf_get_srcdir)/misc_helpers helper + create_atffile helper + TESTCASE=${1}; export TESTCASE +} + +create_helper_stdin() +{ + # TODO: This really, really, really must use real test programs. + cat >${1} <>${1} + [ ${cnt} -lt ${2} ] && echo "echo" >>${1} + cnt=$((${cnt} + 1)) + done +cat >>${1} <>${1} +} + +create_mount_helper() +{ + cat >${1} <>${1} + cat >>${1} <etc/common.conf <.conf." + cat >etc/atf.conf <.atf/common.conf <.conf." + cat >.atf/atf.conf <etc/common.conf <>Atffile + atf_check -s eq:0 -o match:'testvar: a value' -e ignore -x \ + "ATF_CONFDIR=$(pwd)/etc atf-run helper" + + echo "Checking that defining 'testvar' trough the configuration" \ + "file overrides the one in the Atffile." + mkdir etc + cat >etc/common.conf <> Atffile + atf_check -s eq:1 -o ignore -e ignore -x "ATF_CONFDIR=$(pwd)/etc atf-run" + + echo "Checking that defining 'testvar' in the correct Atffile works." + echo 'conf: testvar = "a value"' >>dir/Atffile + atf_check -s eq:0 -o match:'testvar: a value' -e ignore -x \ + "ATF_CONFDIR=$(pwd)/etc atf-run" +} + +atf_test_case fds +fds_head() +{ + atf_set "descr" "Tests that all streams are properly captured" +} +fds_body() +{ + create_helper fds + + atf_check -s eq:0 \ + -o match:'^tc-so:msg1 to stdout$' \ + -o match:'^tc-so:msg2 to stdout$' \ + -o match:'^tc-se:msg1 to stderr$' \ + -o match:'^tc-se:msg2 to stderr$' \ + -e empty atf-run +} + +atf_test_case mux_streams +mux_streams_head() +{ + atf_set "descr" "Tests for a race condition in stream multiplexing" +} +mux_streams_body() +{ + create_helper mux_streams + + for i in 1 2 3 4 5; do + echo "Attempt ${i}" + atf_check -s eq:0 -o match:'stdout 9999' -o match:'stderr 9999' atf-run + done +} + +atf_test_case expect +expect_head() +{ + atf_set "descr" "Tests the processing of test case results and the" \ + "expect features" +} +expect_body() +{ + ln -s "$(atf_get_srcdir)/expect_helpers" . + create_atffile expect_helpers + + atf_check -s eq:1 \ + -o match:'death_and_exit, expected_death' \ + -o match:'death_and_signal, expected_death' \ + -o match:'death_but_pass, failed' \ + -o match:'exit_any_and_exit, expected_exit' \ + -o match:'exit_but_pass, failed' \ + -o match:'exit_code_and_exit, expected_exit' \ + -o match:'fail_and_fail_check, expected_failure' \ + -o match:'fail_and_fail_requirement, expected_failure' \ + -o match:'fail_but_pass, failed' \ + -o match:'pass_and_pass, passed' \ + -o match:'pass_but_fail_check, failed' \ + -o match:'pass_but_fail_requirement, failed' \ + -o match:'signal_any_and_signal, expected_signal' \ + -o match:'signal_but_pass, failed' \ + -o match:'signal_no_and_signal, expected_signal' \ + -o match:'timeout_and_hang, expected_timeout' \ + -o match:'timeout_but_pass, failed' \ + -e empty atf-run +} + +atf_test_case missing_results +missing_results_head() +{ + atf_set "descr" "Ensures that atf-run correctly handles test cases that " \ + "do not create the results file" +} +missing_results_body() +{ + create_helper_stdin helper 1 <\${resfile} +echo 'line 2' >>\${resfile} +exit 0 +EOF + chmod +x helper + + create_atffile helper + + re='^tc-end: [0-9][0-9]*\.[0-9]*, tc1,' + atf_check -s eq:1 -o match:"${re} .*line 1.*line 2" -e empty atf-run +} + +atf_test_case broken_tp_list +broken_tp_list_head() +{ + atf_set "descr" "Ensures that atf-run reports test programs that" \ + "provide a bogus test case list" +} +broken_tp_list_body() +{ + cat >helper <\${resfile} +exit 0 +EOF + chmod +x helper + + create_atffile helper + + re='^tc-end: [0-9][0-9]*\.[0-9]*, tc1,' + atf_check -s eq:1 \ + -o match:"${re} .*exited successfully.*reported failure" \ + -e empty atf-run +} + +atf_test_case signaled +signaled_head() +{ + atf_set "descr" "Ensures that atf-run reports test program's crashes" \ + "correctly regardless of their actual results" +} +signaled_body() +{ + create_helper_stdin helper 2 <\${resfile} +case \${testcase} in + tc1) ;; + tc2) echo "Killing myself!" ; kill -9 \$\$ ;; +esac +EOF + chmod +x helper + + create_atffile helper + + re='^tc-end: [0-9][0-9]*\.[0-9]*, tc2,' + atf_check -s eq:1 -o match:"${re} .*received signal 9" \ + -e empty atf-run +} + +atf_test_case hooks +hooks_head() +{ + atf_set "descr" "Checks that the default hooks work and that they" \ + "can be overriden by the user" +} +hooks_body() +{ + cp $(atf_get_srcdir)/pass_helper helper + create_atffile helper + + mkdir atf + mkdir .atf + + echo "Checking default hooks" + atf_check -s eq:0 -o match:'^info: time.start, ' \ + -o match:'^info: time.end, ' -e empty -x \ + "ATF_CONFDIR=$(pwd)/atf atf-run" + + echo "Checking the system-wide info_start hook" + cat >atf/atf-run.hooks <.atf/atf-run.hooks <atf/atf-run.hooks <.atf/atf-run.hooks <\${ROOT} +mkdir foo +mkdir foo/bar +mkdir foo/bar/mnt +do_mount foo/bar/mnt +mkdir foo/baz +do_mount foo/baz +mkdir foo/baz/foo +mkdir foo/baz/foo/bar +do_mount foo/baz/foo/bar +EOF + create_atffile helper + chmod +x helper + + platform=$(uname) + case ${platform} in + Linux|FreeBSD|NetBSD|SunOS) + ;; + *) + # XXX Possibly specify in meta-data too. + atf_skip "Test unimplemented in this platform (${platform})" + ;; + esac + + atf_check -s eq:0 -o match:"main, passed" -e ignore atf-run helper + mount | grep $(cat root) && atf_fail "Some file systems remain mounted" + atf_check -s eq:1 -o empty -e empty test -d $(cat root)/foo +} + +atf_test_case cleanup_symlink +cleanup_symlink_head() +{ + atf_set "descr" "Tests that the removal algorithm does not follow" \ + "symlinks, which may live in another device and thus" \ + "be treated as mount points" + atf_set "require.user" "root" +} +cleanup_symlink_body() +{ + ROOT="$(pwd)/root"; export ROOT + + create_mount_helper helper <\${ROOT} +atf_check -s eq:0 -o empty -e empty mkdir foo +atf_check -s eq:0 -o empty -e empty mkdir foo/bar +do_mount foo/bar +atf_check -s eq:0 -o empty -e empty touch a +atf_check -s eq:0 -o empty -e empty ln -s "\$(pwd)/a" foo/bar +EOF + create_atffile helper + chmod +x helper + + platform=$(uname) + case ${platform} in + Linux|FreeBSD|NetBSD|SunOS) + ;; + *) + # XXX Possibly specify in meta-data too. + atf_skip "Test unimplemented in this platform (${platform})" + ;; + esac + + atf_check -s eq:0 -o match:"main, passed" -e ignore atf-run helper + mount | grep $(cat root) && atf_fail "Some file systems remain mounted" + atf_check -s eq:1 -o empty -e empty test -d $(cat root)/foo +} + +atf_test_case require_arch +require_arch_head() +{ + atf_set "descr" "Tests that atf-run validates the require.arch property" +} +require_arch_body() +{ + create_helper require_arch + create_atffile helper + + echo "Checking for the real architecture" + arch=$(atf-config -t atf_arch) + atf_check -s eq:0 -o match:"${TESTCASE}, passed" -e ignore atf-run \ + -v arch="${arch}" helper + atf_check -s eq:0 -o match:"${TESTCASE}, passed" -e ignore atf-run \ + -v arch="foo ${arch}" helper + atf_check -s eq:0 -o match:"${TESTCASE}, passed" -e ignore atf-run \ + -v arch="${arch} foo" helper + + echo "Checking for a fictitious architecture" + arch=fictitious + export ATF_ARCH=fictitious + atf_check -s eq:0 -o match:"${TESTCASE}, passed" -e ignore atf-run \ + -v arch="${arch}" helper + atf_check -s eq:0 -o match:"${TESTCASE}, passed" -e ignore atf-run \ + -v arch="foo ${arch}" helper + atf_check -s eq:0 -o match:"${TESTCASE}, passed" -e ignore atf-run \ + -v arch="${arch} foo" helper + + echo "Triggering some failures" + atf_check -s eq:0 -o match:"${TESTCASE}, skipped, .*foo.*architecture" \ + -e ignore atf-run -v arch="foo" helper + atf_check -s eq:0 \ + -o match:"${TESTCASE}, skipped, .*foo bar.*architectures" -e ignore \ + atf-run -v arch="foo bar" helper + atf_check -s eq:0 \ + -o match:"${TESTCASE}, skipped, .*fictitiousxxx.*architecture" \ + -e ignore atf-run -v arch="${arch}xxx" helper +} + +atf_test_case require_config +require_config_head() +{ + atf_set "descr" "Tests that atf-run validates the require.config property" +} +require_config_body() +{ + create_helper require_config + create_atffile helper + + atf_check -s eq:0 -o match:"${TESTCASE}, skipped, .*var1.*not defined" \ + -e ignore atf-run helper + atf_check -s eq:0 -o match:"${TESTCASE}, skipped, .*var2.*not defined" \ + -e ignore atf-run -v var1=foo helper + atf_check -s eq:0 -o match:"${TESTCASE}, passed" -e ignore atf-run \ + -v var1=a -v var2=' ' helper +} + +atf_test_case require_files +require_files_head() +{ + atf_set "descr" "Tests that atf-run validates the require.files property" +} +require_files_body() +{ + create_helper require_files + create_atffile helper + + touch i-exist + + echo "Checking absolute paths" + atf_check -s eq:0 -o match:"${TESTCASE}, passed" -e ignore atf-run \ + -v files='/bin/cp' helper + atf_check -s eq:0 -o match:"${TESTCASE}, passed" -e ignore atf-run \ + -v files="$(pwd)/i-exist" helper + atf_check -s eq:0 \ + -o match:"${TESTCASE}, skipped, .*/dont-exist" \ + -e ignore atf-run -v files="$(pwd)/i-exist $(pwd)/dont-exist" helper + + echo "Checking that relative paths are not allowed" + atf_check -s eq:1 \ + -o match:"${TESTCASE}, failed, Relative paths.*not allowed.*hello" \ + -e ignore atf-run -v files='hello' helper + atf_check -s eq:1 \ + -o match:"${TESTCASE}, failed, Relative paths.*not allowed.*a/b" \ + -e ignore atf-run -v files='a/b' helper +} + +atf_test_case require_machine +require_machine_head() +{ + atf_set "descr" "Tests that atf-run validates the require.machine property" +} +require_machine_body() +{ + create_helper require_machine + create_atffile helper + + echo "Checking for the real machine type" + machine=$(atf-config -t atf_machine) + atf_check -s eq:0 -o match:"${TESTCASE}, passed" -e ignore atf-run \ + -v machine="${machine}" helper + atf_check -s eq:0 -o match:"${TESTCASE}, passed" -e ignore atf-run \ + -v machine="foo ${machine}" helper + atf_check -s eq:0 -o match:"${TESTCASE}, passed" -e ignore atf-run \ + -v machine="${machine} foo" helper + + echo "Checking for a fictitious machine type" + machine=fictitious + export ATF_MACHINE=fictitious + atf_check -s eq:0 -o match:"${TESTCASE}, passed" -e ignore atf-run \ + -v machine="${machine}" helper + atf_check -s eq:0 -o match:"${TESTCASE}, passed" -e ignore atf-run \ + -v machine="foo ${machine}" helper + atf_check -s eq:0 -o match:"${TESTCASE}, passed" -e ignore atf-run \ + -v machine="${machine} foo" helper + + echo "Triggering some failures" + atf_check -s eq:0 -o match:"${TESTCASE}, skipped, .*foo.*machine type" \ + -e ignore atf-run -v machine="foo" helper + atf_check -s eq:0 \ + -o match:"${TESTCASE}, skipped, .*foo bar.*machine types" -e ignore \ + atf-run -v machine="foo bar" helper + atf_check -s eq:0 \ + -o match:"${TESTCASE}, skipped, .*fictitiousxxx.*machine type" \ + -e ignore atf-run -v machine="${machine}xxx" helper +} + +atf_test_case require_progs +require_progs_head() +{ + atf_set "descr" "Tests that atf-run validates the require.progs property" +} +require_progs_body() +{ + create_helper require_progs + create_atffile helper + + echo "Checking absolute paths" + atf_check -s eq:0 -o match:"${TESTCASE}, passed" -e ignore atf-run \ + -v progs='/bin/cp' helper + atf_check -s eq:0 \ + -o match:"${TESTCASE}, skipped, .*/bin/__non-existent__.*PATH" \ + -e ignore atf-run -v progs='/bin/__non-existent__' helper + + echo "Checking that relative paths are not allowed" + atf_check -s eq:1 \ + -o match:"${TESTCASE}, failed, Relative paths.*not allowed.*bin/cp" \ + -e ignore atf-run -v progs='bin/cp' helper + + echo "Check plain file names, searching them in the PATH." + atf_check -s eq:0 -o match:"${TESTCASE}, passed" -e ignore atf-run \ + -v progs='cp' helper + atf_check -s eq:0 \ + -o match:"${TESTCASE}, skipped, .*__non-existent__.*PATH" -e ignore \ + atf-run -v progs='__non-existent__' helper +} + +atf_test_case require_user_root +require_user_root_head() +{ + atf_set "descr" "Tests that atf-run validates the require.user property" \ + "when it is set to 'root'" +} +require_user_root_body() +{ + create_helper require_user + create_atffile helper + + if [ $(id -u) -eq 0 ]; then + exp=passed + else + exp=skipped + fi + atf_check -s eq:0 -o match:"${TESTCASE}, ${exp}" -e ignore atf-run \ + -v user=root helper +} + +atf_test_case require_user_unprivileged +require_user_unprivileged_head() +{ + atf_set "descr" "Tests that atf-run validates the require.user property" \ + "when it is set to 'root'" +} +require_user_unprivileged_body() +{ + create_helper require_user + create_atffile helper + + if [ $(id -u) -eq 0 ]; then + exp=skipped + else + exp=passed + fi + atf_check -s eq:0 -o match:"${TESTCASE}, ${exp}" -e ignore atf-run \ + -v user=unprivileged helper +} + +atf_test_case require_user_bad +require_user_bad_head() +{ + atf_set "descr" "Tests that atf-run validates the require.user property" \ + "when it is set to 'root'" +} +require_user_bad_body() +{ + create_helper require_user + create_atffile helper + + atf_check -s eq:1 -o match:"${TESTCASE}, failed, Invalid value.*foobar" \ + -e ignore atf-run -v user=foobar helper +} + +atf_test_case timeout +timeout_head() +{ + atf_set "descr" "Tests that atf-run kills a test case that times out" +} +timeout_body() +{ + create_helper timeout + create_atffile helper + + atf_check -s eq:1 \ + -o match:"${TESTCASE}, failed, .*timed out after 1 second" -e ignore \ + atf-run -v statedir=$(pwd) helper + if [ -f finished ]; then + atf_fail "Test case was not killed after time out" + fi +} + +atf_test_case timeout_forkexit +timeout_forkexit_head() +{ + atf_set "descr" "Tests that atf-run deals gracefully with a test program" \ + "that forks, exits, but the child process hangs" +} +timeout_forkexit_body() +{ + create_helper timeout_forkexit + create_atffile helper + + atf_check -s eq:0 -o match:"${TESTCASE}, passed" -e ignore atf-run \ + -v statedir=$(pwd) helper + test -f parent-finished || atf_fail "Parent did not exit as expected" + test -f child-finished && atf_fail "Subprocess exited but it should have" \ + "been forcibly terminated" || true +} + +atf_test_case ignore_deprecated_use_fs +ignore_deprecated_use_fs_head() +{ + atf_set "descr" "Tests that atf-run ignores the deprecated use.fs property" +} +ignore_deprecated_use_fs_body() +{ + create_helper use_fs + create_atffile helper + + atf_check -s eq:0 -o ignore -e ignore atf-run helper +} + +atf_init_test_cases() +{ + atf_add_test_case no_warnings + atf_add_test_case config + atf_add_test_case vflag + atf_add_test_case atffile + atf_add_test_case atffile_recursive + atf_add_test_case expect + atf_add_test_case fds + atf_add_test_case mux_streams + atf_add_test_case missing_results + atf_add_test_case broken_results + atf_add_test_case broken_tp_list + atf_add_test_case zero_tcs + atf_add_test_case exit_codes + atf_add_test_case signaled + atf_add_test_case hooks + atf_add_test_case isolation_env + atf_add_test_case isolation_home + atf_add_test_case isolation_stdin + atf_add_test_case isolation_umask + atf_add_test_case cleanup_pass + atf_add_test_case cleanup_fail + atf_add_test_case cleanup_skip + atf_add_test_case cleanup_curdir + atf_add_test_case cleanup_signal + atf_add_test_case cleanup_mount + atf_add_test_case cleanup_symlink + atf_add_test_case require_arch + atf_add_test_case require_config + atf_add_test_case require_files + atf_add_test_case require_machine + atf_add_test_case require_progs + atf_add_test_case require_user_root + atf_add_test_case require_user_unprivileged + atf_add_test_case require_user_bad + atf_add_test_case timeout + atf_add_test_case timeout_forkexit + atf_add_test_case ignore_deprecated_use_fs +} + +# vim: syntax=sh:expandtab:shiftwidth=4:softtabstop=4 diff --git a/external/bsd/atf/dist/atf-run/io.cpp b/external/bsd/atf/dist/atf-run/io.cpp new file mode 100644 index 000000000..c99ee34ef --- /dev/null +++ b/external/bsd/atf/dist/atf-run/io.cpp @@ -0,0 +1,361 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +extern "C" { +#include +#include +#include +#include +} + +#include +#include + +extern "C" { +#include "../atf-c/error.h" +} + +#include "../atf-c++/detail/auto_array.hpp" +#include "../atf-c++/detail/exceptions.hpp" +#include "../atf-c++/detail/sanity.hpp" + +#include "io.hpp" + +namespace impl = atf::atf_run; +#define IMPL_NAME "atf::atf_run" + +// ------------------------------------------------------------------------ +// The "file_handle" class. +// ------------------------------------------------------------------------ + +impl::file_handle::file_handle(void) : + m_handle(invalid_value()) +{ +} + +impl::file_handle::file_handle(handle_type h) : + m_handle(h) +{ + PRE(m_handle != invalid_value()); +} + +impl::file_handle::file_handle(const file_handle& fh) : + m_handle(fh.m_handle) +{ + fh.m_handle = invalid_value(); +} + +impl::file_handle::~file_handle(void) +{ + if (is_valid()) + close(); +} + +impl::file_handle& +impl::file_handle::operator=(const file_handle& fh) +{ + m_handle = fh.m_handle; + fh.m_handle = invalid_value(); + + return *this; +} + +bool +impl::file_handle::is_valid(void) + const +{ + return m_handle != invalid_value(); +} + +void +impl::file_handle::close(void) +{ + PRE(is_valid()); + + ::close(m_handle); + + m_handle = invalid_value(); +} + +impl::file_handle::handle_type +impl::file_handle::disown(void) +{ + PRE(is_valid()); + + handle_type h = m_handle; + m_handle = invalid_value(); + return h; +} + +impl::file_handle::handle_type +impl::file_handle::get(void) + const +{ + PRE(is_valid()); + + return m_handle; +} + +void +impl::file_handle::posix_remap(handle_type h) +{ + PRE(is_valid()); + + if (m_handle == h) + return; + + if (::dup2(m_handle, h) == -1) + throw system_error(IMPL_NAME "::file_handle::posix_remap", + "dup2(2) failed", errno); + + if (::close(m_handle) == -1) { + ::close(h); + throw system_error(IMPL_NAME "::file_handle::posix_remap", + "close(2) failed", errno); + } + + m_handle = h; +} + +impl::file_handle::handle_type +impl::file_handle::invalid_value(void) +{ + return -1; +} + +// ------------------------------------------------------------------------ +// The "systembuf" class. +// ------------------------------------------------------------------------ + +impl::systembuf::systembuf(handle_type h, std::size_t bufsize) : + m_handle(h), + m_bufsize(bufsize), + m_read_buf(NULL), + m_write_buf(NULL) +{ + PRE(m_handle >= 0); + PRE(m_bufsize > 0); + + try { + m_read_buf = new char[bufsize]; + m_write_buf = new char[bufsize]; + } catch (...) { + if (m_read_buf != NULL) + delete [] m_read_buf; + if (m_write_buf != NULL) + delete [] m_write_buf; + throw; + } + + setp(m_write_buf, m_write_buf + m_bufsize); +} + +impl::systembuf::~systembuf(void) +{ + delete [] m_read_buf; + delete [] m_write_buf; +} + +impl::systembuf::int_type +impl::systembuf::underflow(void) +{ + PRE(gptr() >= egptr()); + + bool ok; + ssize_t cnt = ::read(m_handle, m_read_buf, m_bufsize); + ok = (cnt != -1 && cnt != 0); + + if (!ok) + return traits_type::eof(); + else { + setg(m_read_buf, m_read_buf, m_read_buf + cnt); + return traits_type::to_int_type(*gptr()); + } +} + +impl::systembuf::int_type +impl::systembuf::overflow(int c) +{ + PRE(pptr() >= epptr()); + if (sync() == -1) + return traits_type::eof(); + if (!traits_type::eq_int_type(c, traits_type::eof())) { + traits_type::assign(*pptr(), c); + pbump(1); + } + return traits_type::not_eof(c); +} + +int +impl::systembuf::sync(void) +{ + ssize_t cnt = pptr() - pbase(); + + bool ok; + ok = ::write(m_handle, pbase(), cnt) == cnt; + + if (ok) + pbump(-cnt); + return ok ? 0 : -1; +} + +// ------------------------------------------------------------------------ +// The "pistream" class. +// ------------------------------------------------------------------------ + +impl::pistream::pistream(const int fd) : + std::istream(NULL), + m_systembuf(fd) +{ + rdbuf(&m_systembuf); +} + +// ------------------------------------------------------------------------ +// The "muxer" class. +// ------------------------------------------------------------------------ + +static int +safe_poll(struct pollfd fds[], nfds_t nfds, int timeout) +{ + int ret = ::poll(fds, nfds, timeout); + if (ret == -1) { + if (errno == EINTR) + ret = 0; + else + throw atf::system_error(IMPL_NAME "::safe_poll", "poll(2) failed", + errno); + } + INV(ret >= 0); + return ret; +} + +static size_t +safe_read(const int fd, void* buffer, const size_t nbytes, + const bool report_errors) +{ + int ret; + while ((ret = ::read(fd, buffer, nbytes)) == -1 && errno == EINTR) {} + if (ret == -1) { + INV(errno != EINTR); + + if (report_errors) + throw atf::system_error(IMPL_NAME "::safe_read", "read(2) failed", + errno); + else + ret = 0; + } + INV(ret >= 0); + return static_cast< size_t >(ret); +} + +impl::muxer::muxer(const int* fds, const size_t nfds, const size_t bufsize) : + m_fds(fds), + m_nfds(nfds), + m_bufsize(bufsize), + m_buffers(new std::string[nfds]) +{ +} + +impl::muxer::~muxer(void) +{ +} + +size_t +impl::muxer::read_one(const size_t index, const int fd, std::string& accum, + const bool report_errors) +{ + atf::auto_array< char > buffer(new char[m_bufsize]); + const size_t nbytes = safe_read(fd, buffer.get(), m_bufsize - 1, + report_errors); + INV(nbytes < m_bufsize); + buffer[nbytes] = '\0'; + + std::string line(accum); + + size_t line_start = 0; + for (size_t i = 0; i < nbytes; i++) { + if (buffer[i] == '\n') { + line_callback(index, line); + line.clear(); + accum.clear(); + line_start = i + 1; + } else if (buffer[i] == '\r') { + // Do nothing. + } else { + line.append(1, buffer[i]); + } + } + accum.append(&buffer[line_start]); + + return nbytes; +} + +void +impl::muxer::mux(volatile const bool& terminate) +{ + atf::auto_array< struct pollfd > poll_fds(new struct pollfd[m_nfds]); + for (size_t i = 0; i < m_nfds; i++) { + poll_fds[i].fd = m_fds[i]; + poll_fds[i].events = POLLIN; + } + + size_t nactive = m_nfds; + while (nactive > 0 && !terminate) { + int ret; + while (!terminate && (ret = safe_poll(poll_fds.get(), 2, 250)) == 0) {} + + for (size_t i = 0; !terminate && i < m_nfds; i++) { + if (poll_fds[i].events == 0) + continue; + + if (poll_fds[i].revents & POLLHUP) { + // Any data still available at this point will be processed by + // a call to the flush method. + poll_fds[i].events = 0; + + INV(nactive >= 1); + nactive--; + } else if (poll_fds[i].revents & (POLLIN | POLLRDNORM | POLLRDBAND | + POLLPRI)) { + (void)read_one(i, poll_fds[i].fd, m_buffers[i], true); + } + } + } +} + +void +impl::muxer::flush(void) +{ + for (size_t i = 0; i < m_nfds; i++) { + while (read_one(i, m_fds[i], m_buffers[i], false) > 0) {} + + if (!m_buffers[i].empty()) + line_callback(i, m_buffers[i]); + } +} diff --git a/external/bsd/atf/dist/atf-run/io.hpp b/external/bsd/atf/dist/atf-run/io.hpp new file mode 100644 index 000000000..b8ff59a80 --- /dev/null +++ b/external/bsd/atf/dist/atf-run/io.hpp @@ -0,0 +1,426 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#if !defined(_ATF_RUN_IO_HPP_) +#define _ATF_RUN_IO_HPP_ + +#include +#include +#include + +#include "fs.hpp" + +#include "../atf-c++/detail/auto_array.hpp" +#include "../atf-c++/noncopyable.hpp" + +namespace atf { +namespace atf_run { + +// ------------------------------------------------------------------------ +// The "file_handle" class. +// ------------------------------------------------------------------------ + +//! +//! \brief Simple RAII model for system file handles. +//! +//! The \a file_handle class is a simple RAII model for native system file +//! handles. This class wraps one of such handles grabbing its ownership, +//! and automaticaly closes it upon destruction. It is basically used +//! inside the library to avoid leaking open file handles, shall an +//! unexpected execution trace occur. +//! +//! A \a file_handle object can be copied but doing so invalidates the +//! source object. There can only be a single valid \a file_handle object +//! for a given system file handle. This is similar to std::auto_ptr\<\>'s +//! semantics. +//! +//! This class also provides some convenience methods to issue special file +//! operations under their respective platforms. +//! +class file_handle +{ +public: + //! + //! \brief Opaque name for the native handle type. + //! + //! Each operating system identifies file handles using a specific type. + //! The \a handle_type type is used to transparently refer to file + //! handles regarless of the operating system in which this class is + //! used. + //! + //! If this class is used in a POSIX system, \a NativeSystemHandle is + //! an integer type while it is a \a HANDLE in a Win32 system. + //! + typedef int handle_type; + + //! + //! \brief Constructs an invalid file handle. + //! + //! This constructor creates a new \a file_handle object that represents + //! an invalid file handle. An invalid file handle can be copied but + //! cannot be manipulated in any way (except checking for its validity). + //! + //! \see is_valid() + //! + file_handle(void); + + //! + //! \brief Constructs a new file handle from a native file handle. + //! + //! This constructor creates a new \a file_handle object that takes + //! ownership of the given \a h native file handle. The user must not + //! close \a h on his own during the lifetime of the new object. + //! Ownership can be reclaimed using disown(). + //! + //! \pre The native file handle must be valid; a close operation must + //! succeed on it. + //! + //! \see disown() + //! + file_handle(handle_type h); + + //! + //! \brief Copy constructor; invalidates the source handle. + //! + //! This copy constructor creates a new file handle from a given one. + //! Ownership of the native file handle is transferred to the new + //! object, effectively invalidating the source file handle. This + //! avoids having two live \a file_handle objects referring to the + //! same native file handle. The source file handle need not be + //! valid in the name of simplicity. + //! + //! \post The source file handle is invalid. + //! \post The new file handle owns the source's native file handle. + //! + file_handle(const file_handle& fh); + + //! + //! \brief Releases resources if the handle is valid. + //! + //! If the file handle is valid, the destructor closes it. + //! + //! \see is_valid() + //! + ~file_handle(void); + + //! + //! \brief Assignment operator; invalidates the source handle. + //! + //! This assignment operator transfers ownership of the RHS file + //! handle to the LHS one, effectively invalidating the source file + //! handle. This avoids having two live \a file_handle objects + //! referring to the same native file handle. The source file + //! handle need not be valid in the name of simplicity. + //! + //! \post The RHS file handle is invalid. + //! \post The LHS file handle owns RHS' native file handle. + //! \return A reference to the LHS file handle. + //! + file_handle& operator=(const file_handle& fh); + + //! + //! \brief Checks whether the file handle is valid or not. + //! + //! Returns a boolean indicating whether the file handle is valid or + //! not. If the file handle is invalid, no other applications can be + //! executed other than the destructor. + //! + //! \return True if the file handle is valid; false otherwise. + //! + bool is_valid(void) const; + + //! + //! \brief Closes the file handle. + //! + //! Explicitly closes the file handle, which must be valid. Upon + //! exit, the handle is not valid any more. + //! + //! \pre The file handle is valid. + //! \post The file handle is invalid. + //! \post The native file handle is closed. + //! + void close(void); + + //! + //! \brief Reclaims ownership of the native file handle. + //! + //! Explicitly reclaims ownership of the native file handle contained + //! in the \a file_handle object, returning the native file handle. + //! The caller is responsible of closing it later on. + //! + //! \pre The file handle is valid. + //! \post The file handle is invalid. + //! \return The native file handle. + //! + handle_type disown(void); + + //! + //! \brief Gets the native file handle. + //! + //! Returns the native file handle for the \a file_handle object. + //! The caller can issue any operation on it except closing it. + //! If closing is required, disown() shall be used. + //! + //! \pre The file handle is valid. + //! \return The native file handle. + //! + handle_type get(void) const; + + //! + //! \brief Changes the native file handle to the given one. + //! + //! Given a new native file handle \a h, this operation assigns this + //! handle to the current object, closing its old native file handle. + //! In other words, it first calls dup2() to remap the old handle to + //! the new one and then closes the old handle. + //! + //! If \a h matches the current value of the handle, this is a no-op. + //! This is done for simplicity, to avoid the caller having to check + //! this condition on its own. + //! + //! If \a h is open, it is automatically closed by dup2(). + //! + //! This operation is only available in POSIX systems. + //! + //! \pre The file handle is valid. + //! \pre The native file handle \a h is valid; i.e., it must be + //! closeable. + //! \post The file handle's native file handle is \a h. + //! \throw system_error If the internal remapping operation fails. + //! + void posix_remap(handle_type h); + +private: + //! + //! \brief Internal handle value. + //! + //! This variable holds the native handle value for the file handle + //! hold by this object. It is interesting to note that this needs + //! to be mutable because the copy constructor and the assignment + //! operator invalidate the source object. + //! + mutable handle_type m_handle; + + //! + //! \brief Constant function representing an invalid handle value. + //! + //! Returns the platform-specific handle value that represents an + //! invalid handle. This is a constant function rather than a regular + //! constant because, in the latter case, we cannot define it under + //! Win32 due to the value being of a complex type. + //! + static handle_type invalid_value(void); +}; + +// ------------------------------------------------------------------------ +// The "systembuf" class. +// ------------------------------------------------------------------------ + +//! +//! \brief std::streambuf implementation for system file handles. +//! +//! systembuf provides a std::streambuf implementation for system file +//! handles. Contrarywise to file_handle, this class does \b not take +//! ownership of the native file handle; this should be taken care of +//! somewhere else. +//! +//! This class follows the expected semantics of a std::streambuf object. +//! However, it is not copyable to avoid introducing inconsistences with +//! the on-disk file and the in-memory buffers. +//! +class systembuf : public std::streambuf, atf::noncopyable +{ +public: + typedef int handle_type; + + //! + //! \brief Constructs a new systembuf for the given file handle. + //! + //! This constructor creates a new systembuf object that reads or + //! writes data from/to the \a h native file handle. This handle + //! is \b not owned by the created systembuf object; the code + //! should take care of it externally. + //! + //! This class buffers input and output; the buffer size may be + //! tuned through the \a bufsize parameter, which defaults to 8192 + //! bytes. + //! + //! \see pistream. + //! + explicit systembuf(handle_type h, std::size_t bufsize = 8192); + ~systembuf(void); + +private: + //! + //! \brief Native file handle used by the systembuf object. + //! + handle_type m_handle; + + //! + //! \brief Internal buffer size used during read and write operations. + //! + std::size_t m_bufsize; + + //! + //! \brief Internal buffer used during read operations. + //! + char* m_read_buf; + + //! + //! \brief Internal buffer used during write operations. + //! + char* m_write_buf; + +protected: + //! + //! \brief Reads new data from the native file handle. + //! + //! This operation is called by input methods when there are no more + //! data in the input buffer. The function fills the buffer with new + //! data, if available. + //! + //! \pre All input positions are exhausted (gptr() >= egptr()). + //! \post The input buffer has new data, if available. + //! \returns traits_type::eof() if a read error occurrs or there are + //! no more data to be read. Otherwise returns + //! traits_type::to_int_type(*gptr()). + //! + virtual int_type underflow(void); + + //! + //! \brief Makes room in the write buffer for additional data. + //! + //! This operation is called by output methods when there is no more + //! space in the output buffer to hold a new element. The function + //! first flushes the buffer's contents to disk and then clears it to + //! leave room for more characters. The given \a c character is + //! stored at the beginning of the new space. + //! + //! \pre All output positions are exhausted (pptr() >= epptr()). + //! \post The output buffer has more space if no errors occurred + //! during the write to disk. + //! \post *(pptr() - 1) is \a c. + //! \returns traits_type::eof() if a write error occurrs. Otherwise + //! returns traits_type::not_eof(c). + //! + virtual int_type overflow(int c); + + //! + //! \brief Flushes the output buffer to disk. + //! + //! Synchronizes the systembuf buffers with the contents of the file + //! associated to this object through the native file handle. The + //! output buffer is flushed to disk and cleared to leave new room + //! for more data. + //! + //! \returns 0 on success, -1 if an error occurred. + //! + virtual int sync(void); +}; + +// ------------------------------------------------------------------------ +// The "pistream" class. +// ------------------------------------------------------------------------ + +//! +//! \brief Child process' output stream. +//! +//! The pistream class represents an output communication channel with the +//! child process. The child process writes data to this stream and the +//! parent process can read it through the pistream object. In other +//! words, from the child's point of view, the communication channel is an +//! output one, but from the parent's point of view it is an input one; +//! hence the confusing pistream name. +//! +//! pistream objects cannot be copied because they own the file handle +//! they use to communicate with the child and because they buffer data +//! that flows through the communication channel. +//! +//! A pistream object behaves as a std::istream stream in all senses. +//! The class is only provided because it must provide a method to let +//! the caller explicitly close the communication channel. +//! +//! \remark Blocking remarks: Functions that read data from this +//! stream can block if the associated file handle blocks during the read. +//! As this class is used to communicate with child processes through +//! anonymous pipes, the most typical blocking condition happens when the +//! child has no more data to send to the pipe's system buffer. When +//! this happens, the buffer eventually empties and the system blocks +//! until the writer generates some data. +//! +class pistream : public std::istream, noncopyable +{ + //! + //! \brief The systembuf object used to manage this stream's data. + //! + systembuf m_systembuf; + +public: + //! + //! \brief Creates a new process' output stream. + //! + //! Given a file handle, this constructor creates a new pistream + //! object that owns the given file handle \a fh. Ownership of + //! \a fh is transferred to the created pistream object. + //! + //! \pre \a fh is valid. + //! \post \a fh is invalid. + //! \post The new pistream object owns \a fh. + //! + explicit pistream(const int); +}; + +// ------------------------------------------------------------------------ +// The "muxer" class. +// ------------------------------------------------------------------------ + +class muxer : noncopyable { + const int* m_fds; + const size_t m_nfds; + + const size_t m_bufsize; + atf::auto_array< std::string > m_buffers; + +protected: + virtual void line_callback(const size_t, const std::string&) = 0; + + size_t read_one(const size_t, const int, std::string&, const bool); + +public: + muxer(const int*, const size_t, const size_t bufsize = 1024); + virtual ~muxer(void); + + void mux(volatile const bool&); + void flush(void); +}; + +} // namespace atf_run +} // namespace atf + +#endif // !defined(_ATF_RUN_IO_HPP_) diff --git a/external/bsd/atf/dist/atf-run/io_test.cpp b/external/bsd/atf/dist/atf-run/io_test.cpp new file mode 100644 index 000000000..03fc97e82 --- /dev/null +++ b/external/bsd/atf/dist/atf-run/io_test.cpp @@ -0,0 +1,471 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +extern "C" { +#include +#include + +#include +#include +} + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../atf-c++/detail/sanity.hpp" +#include "../atf-c++/macros.hpp" + +#include "io.hpp" +#include "signals.hpp" + +// ------------------------------------------------------------------------ +// Auxiliary functions. +// ------------------------------------------------------------------------ + +static +void +systembuf_check_data(std::istream& is, std::size_t length) +{ + char ch = 'A', chr; + std::size_t cnt = 0; + while (is >> chr) { + ATF_REQUIRE_EQ(ch, chr); + if (ch == 'Z') + ch = 'A'; + else + ch++; + cnt++; + } + ATF_REQUIRE_EQ(cnt, length); +} + +static +void +systembuf_write_data(std::ostream& os, std::size_t length) +{ + char ch = 'A'; + for (std::size_t i = 0; i < length; i++) { + os << ch; + if (ch == 'Z') + ch = 'A'; + else + ch++; + } + os.flush(); +} + +static +void +systembuf_test_read(std::size_t length, std::size_t bufsize) +{ + using atf::atf_run::systembuf; + + std::ofstream f("test_read.txt"); + systembuf_write_data(f, length); + f.close(); + + int fd = ::open("test_read.txt", O_RDONLY); + ATF_REQUIRE(fd != -1); + systembuf sb(fd, bufsize); + std::istream is(&sb); + systembuf_check_data(is, length); + ::close(fd); + ::unlink("test_read.txt"); +} + +static +void +systembuf_test_write(std::size_t length, std::size_t bufsize) +{ + using atf::atf_run::systembuf; + + int fd = ::open("test_write.txt", O_WRONLY | O_CREAT | O_TRUNC, + S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + ATF_REQUIRE(fd != -1); + systembuf sb(fd, bufsize); + std::ostream os(&sb); + systembuf_write_data(os, length); + ::close(fd); + + std::ifstream is("test_write.txt"); + systembuf_check_data(is, length); + is.close(); + ::unlink("test_write.txt"); +} + +// ------------------------------------------------------------------------ +// Test cases for the "file_handle" class. +// ------------------------------------------------------------------------ + +ATF_TEST_CASE(file_handle_ctor); +ATF_TEST_CASE_HEAD(file_handle_ctor) +{ + set_md_var("descr", "Tests file_handle's constructors"); +} +ATF_TEST_CASE_BODY(file_handle_ctor) +{ + using atf::atf_run::file_handle; + + file_handle fh1; + ATF_REQUIRE(!fh1.is_valid()); + + file_handle fh2(STDOUT_FILENO); + ATF_REQUIRE(fh2.is_valid()); + fh2.disown(); +} + +ATF_TEST_CASE(file_handle_copy); +ATF_TEST_CASE_HEAD(file_handle_copy) +{ + set_md_var("descr", "Tests file_handle's copy constructor"); +} +ATF_TEST_CASE_BODY(file_handle_copy) +{ + using atf::atf_run::file_handle; + + file_handle fh1; + file_handle fh2(STDOUT_FILENO); + + file_handle fh3(fh2); + ATF_REQUIRE(!fh2.is_valid()); + ATF_REQUIRE(fh3.is_valid()); + + fh1 = fh3; + ATF_REQUIRE(!fh3.is_valid()); + ATF_REQUIRE(fh1.is_valid()); + + fh1.disown(); +} + +ATF_TEST_CASE(file_handle_get); +ATF_TEST_CASE_HEAD(file_handle_get) +{ + set_md_var("descr", "Tests the file_handle::get method"); +} +ATF_TEST_CASE_BODY(file_handle_get) +{ + using atf::atf_run::file_handle; + + file_handle fh1(STDOUT_FILENO); + ATF_REQUIRE_EQ(fh1.get(), STDOUT_FILENO); +} + +ATF_TEST_CASE(file_handle_posix_remap); +ATF_TEST_CASE_HEAD(file_handle_posix_remap) +{ + set_md_var("descr", "Tests the file_handle::posix_remap method"); +} +ATF_TEST_CASE_BODY(file_handle_posix_remap) +{ + using atf::atf_run::file_handle; + + int pfd[2]; + + ATF_REQUIRE(::pipe(pfd) != -1); + file_handle rend(pfd[0]); + file_handle wend(pfd[1]); + + ATF_REQUIRE(rend.get() != 10); + ATF_REQUIRE(wend.get() != 10); + wend.posix_remap(10); + ATF_REQUIRE_EQ(wend.get(), 10); + ATF_REQUIRE(::write(wend.get(), "test-posix-remap", 16) != -1); + { + char buf[17]; + ATF_REQUIRE_EQ(::read(rend.get(), buf, sizeof(buf)), 16); + buf[16] = '\0'; + ATF_REQUIRE(std::strcmp(buf, "test-posix-remap") == 0); + } + + // Redo previous to ensure that remapping over the same descriptor + // has no side-effects. + ATF_REQUIRE_EQ(wend.get(), 10); + wend.posix_remap(10); + ATF_REQUIRE_EQ(wend.get(), 10); + ATF_REQUIRE(::write(wend.get(), "test-posix-remap", 16) != -1); + { + char buf[17]; + ATF_REQUIRE_EQ(::read(rend.get(), buf, sizeof(buf)), 16); + buf[16] = '\0'; + ATF_REQUIRE(std::strcmp(buf, "test-posix-remap") == 0); + } +} + +// ------------------------------------------------------------------------ +// Test cases for the "systembuf" class. +// ------------------------------------------------------------------------ + +ATF_TEST_CASE(systembuf_short_read); +ATF_TEST_CASE_HEAD(systembuf_short_read) +{ + set_md_var("descr", "Tests that a short read (one that fits in the " + "internal buffer) works when using systembuf"); +} +ATF_TEST_CASE_BODY(systembuf_short_read) +{ + systembuf_test_read(64, 1024); +} + +ATF_TEST_CASE(systembuf_long_read); +ATF_TEST_CASE_HEAD(systembuf_long_read) +{ + set_md_var("descr", "Tests that a long read (one that does not fit in " + "the internal buffer) works when using systembuf"); +} +ATF_TEST_CASE_BODY(systembuf_long_read) +{ + systembuf_test_read(64 * 1024, 1024); +} + +ATF_TEST_CASE(systembuf_short_write); +ATF_TEST_CASE_HEAD(systembuf_short_write) +{ + set_md_var("descr", "Tests that a short write (one that fits in the " + "internal buffer) works when using systembuf"); +} +ATF_TEST_CASE_BODY(systembuf_short_write) +{ + systembuf_test_write(64, 1024); +} + +ATF_TEST_CASE(systembuf_long_write); +ATF_TEST_CASE_HEAD(systembuf_long_write) +{ + set_md_var("descr", "Tests that a long write (one that does not fit " + "in the internal buffer) works when using systembuf"); +} +ATF_TEST_CASE_BODY(systembuf_long_write) +{ + systembuf_test_write(64 * 1024, 1024); +} + +// ------------------------------------------------------------------------ +// Test cases for the "pistream" class. +// ------------------------------------------------------------------------ + +ATF_TEST_CASE(pistream); +ATF_TEST_CASE_HEAD(pistream) +{ + set_md_var("descr", "Tests the pistream class"); +} +ATF_TEST_CASE_BODY(pistream) +{ + using atf::atf_run::file_handle; + using atf::atf_run::pistream; + using atf::atf_run::systembuf; + + int fds[2]; + ATF_REQUIRE(::pipe(fds) != -1); + + pistream rend(fds[0]); + + systembuf wbuf(fds[1]); + std::ostream wend(&wbuf); + + // XXX This assumes that the pipe's buffer is big enough to accept + // the data written without blocking! + wend << "1Test 1message\n"; + wend.flush(); + std::string tmp; + rend >> tmp; + ATF_REQUIRE_EQ(tmp, "1Test"); + rend >> tmp; + ATF_REQUIRE_EQ(tmp, "1message"); +} + +// ------------------------------------------------------------------------ +// Tests for the "muxer" class. +// ------------------------------------------------------------------------ + +namespace { + +static void +check_stream(std::ostream& os) +{ + // If we receive a signal while writing to the stream, the bad bit gets set. + // Things seem to behave fine afterwards if we clear such error condition. + // However, I'm not sure if it's safe to query errno at this point. + ATF_REQUIRE(os.good() || (os.bad() && errno == EINTR)); + os.clear(); +} + +class mock_muxer : public atf::atf_run::muxer { + void line_callback(const size_t index, const std::string& line) + { + // The following should be enabled but causes the output to be so big + // that it is annoying. Reenable at some point if we make atf store + // the output of the test cases in some other way (e.g. only if a test + // failes), because this message is the only help in seeing how the + // test fails. + //std::cout << "line_callback(" << index << ", " << line << ")\n"; + check_stream(std::cout); + switch (index) { + case 0: lines0.push_back(line); break; + case 1: lines1.push_back(line); break; + default: ATF_REQUIRE(false); + } + } + +public: + mock_muxer(const int* fds, const size_t nfds, const size_t bufsize) : + muxer(fds, nfds, bufsize) {} + + std::vector< std::string > lines0; + std::vector< std::string > lines1; +}; + +static bool child_finished = false; +static void sigchld_handler(int signo) +{ + INV(signo == SIGCHLD); + child_finished = true; +} + +static void +child_printer(const int pipeout[2], const int pipeerr[2], + const size_t iterations) +{ + ::close(pipeout[0]); + ::close(pipeerr[0]); + ATF_REQUIRE(::dup2(pipeout[1], STDOUT_FILENO) != -1); + ATF_REQUIRE(::dup2(pipeerr[1], STDERR_FILENO) != -1); + ::close(pipeout[1]); + ::close(pipeerr[1]); + + for (size_t i = 0; i < iterations; i++) { + std::cout << "stdout " << i << "\n"; + std::cerr << "stderr " << i << "\n"; + } + + std::cout << "stdout eof\n"; + std::cerr << "stderr eof\n"; + std::exit(EXIT_SUCCESS); +} + +static void +muxer_test(const size_t bufsize, const size_t iterations) +{ + int pipeout[2], pipeerr[2]; + ATF_REQUIRE(pipe(pipeout) != -1); + ATF_REQUIRE(pipe(pipeerr) != -1); + + atf::atf_run::signal_programmer sigchld(SIGCHLD, sigchld_handler); + + std::cout.flush(); + std::cerr.flush(); + + pid_t pid = ::fork(); + ATF_REQUIRE(pid != -1); + if (pid == 0) { + sigchld.unprogram(); + child_printer(pipeout, pipeerr, iterations); + UNREACHABLE; + } + ::close(pipeout[1]); + ::close(pipeerr[1]); + + int fds[2] = {pipeout[0], pipeerr[0]}; + mock_muxer mux(fds, 2, bufsize); + + mux.mux(child_finished); + check_stream(std::cout); + std::cout << "mux done\n"; + + mux.flush(); + std::cout << "flush done\n"; + check_stream(std::cout); + + sigchld.unprogram(); + int status; + ATF_REQUIRE(::waitpid(pid, &status, 0) != -1); + ATF_REQUIRE(WIFEXITED(status)); + ATF_REQUIRE(WEXITSTATUS(status) == EXIT_SUCCESS); + + ATF_REQUIRE(std::cout.good()); + ATF_REQUIRE(std::cerr.good()); + for (size_t i = 0; i < iterations; i++) { + std::ostringstream exp0, exp1; + exp0 << "stdout " << i; + exp1 << "stderr " << i; + + ATF_REQUIRE(mux.lines0.size() > i); + ATF_REQUIRE_EQ(exp0.str(), mux.lines0[i]); + ATF_REQUIRE(mux.lines1.size() > i); + ATF_REQUIRE_EQ(exp1.str(), mux.lines1[i]); + } + ATF_REQUIRE_EQ("stdout eof", mux.lines0[iterations]); + ATF_REQUIRE_EQ("stderr eof", mux.lines1[iterations]); + std::cout << "all done\n"; +} + +} // anonymous namespace + +ATF_TEST_CASE_WITHOUT_HEAD(muxer_small_buffer); +ATF_TEST_CASE_BODY(muxer_small_buffer) +{ + muxer_test(4, 20000); +} + +ATF_TEST_CASE_WITHOUT_HEAD(muxer_large_buffer); +ATF_TEST_CASE_BODY(muxer_large_buffer) +{ + muxer_test(1024, 50000); +} + +// ------------------------------------------------------------------------ +// Main. +// ------------------------------------------------------------------------ + +ATF_INIT_TEST_CASES(tcs) +{ + // Add the tests for the "file_handle" class. + ATF_ADD_TEST_CASE(tcs, file_handle_ctor); + ATF_ADD_TEST_CASE(tcs, file_handle_copy); + ATF_ADD_TEST_CASE(tcs, file_handle_get); + ATF_ADD_TEST_CASE(tcs, file_handle_posix_remap); + + // Add the tests for the "systembuf" class. + ATF_ADD_TEST_CASE(tcs, systembuf_short_read); + ATF_ADD_TEST_CASE(tcs, systembuf_long_read); + ATF_ADD_TEST_CASE(tcs, systembuf_short_write); + ATF_ADD_TEST_CASE(tcs, systembuf_long_write); + + // Add the tests for the "pistream" class. + ATF_ADD_TEST_CASE(tcs, pistream); + + // Add the tests for the "muxer" class. + ATF_ADD_TEST_CASE(tcs, muxer_small_buffer); + ATF_ADD_TEST_CASE(tcs, muxer_large_buffer); +} diff --git a/external/bsd/atf/dist/atf-run/misc_helpers.cpp b/external/bsd/atf/dist/atf-run/misc_helpers.cpp new file mode 100644 index 000000000..abc9a4a94 --- /dev/null +++ b/external/bsd/atf/dist/atf-run/misc_helpers.cpp @@ -0,0 +1,419 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +extern "C" { +#include + +#include +#include +} + +#include +#include +#include +#include +#include +#include + +#include "atf-c++/macros.hpp" + +#include "atf-c++/detail/env.hpp" +#include "atf-c++/detail/fs.hpp" +#include "atf-c++/detail/process.hpp" +#include "atf-c++/detail/sanity.hpp" + +// ------------------------------------------------------------------------ +// Auxiliary functions. +// ------------------------------------------------------------------------ + +static +void +touch(const std::string& path) +{ + std::ofstream os(path.c_str()); + if (!os) + ATF_FAIL("Could not create file " + path); + os.close(); +} + +// ------------------------------------------------------------------------ +// Helper tests for "t_integration". +// ------------------------------------------------------------------------ + +ATF_TEST_CASE(pass); +ATF_TEST_CASE_HEAD(pass) +{ + set_md_var("descr", "Helper test case for the t_integration test program"); +} +ATF_TEST_CASE_BODY(pass) +{ +} + +ATF_TEST_CASE(config); +ATF_TEST_CASE_HEAD(config) +{ + set_md_var("descr", "Helper test case for the t_integration test program"); +} +ATF_TEST_CASE_BODY(config) +{ + std::cout << "1st: " << get_config_var("1st") << "\n"; + std::cout << "2nd: " << get_config_var("2nd") << "\n"; + std::cout << "3rd: " << get_config_var("3rd") << "\n"; + std::cout << "4th: " << get_config_var("4th") << "\n"; +} + +ATF_TEST_CASE(fds); +ATF_TEST_CASE_HEAD(fds) +{ + set_md_var("descr", "Helper test case for the t_integration test program"); +} +ATF_TEST_CASE_BODY(fds) +{ + std::cout << "msg1 to stdout" << "\n"; + std::cout << "msg2 to stdout" << "\n"; + std::cerr << "msg1 to stderr" << "\n"; + std::cerr << "msg2 to stderr" << "\n"; +} + +ATF_TEST_CASE_WITHOUT_HEAD(mux_streams); +ATF_TEST_CASE_BODY(mux_streams) +{ + for (size_t i = 0; i < 10000; i++) { + switch (i % 5) { + case 0: + std::cout << "stdout " << i << "\n"; + break; + case 1: + std::cerr << "stderr " << i << "\n"; + break; + case 2: + std::cout << "stdout " << i << "\n"; + std::cerr << "stderr " << i << "\n"; + break; + case 3: + std::cout << "stdout " << i << "\n"; + std::cout << "stdout " << i << "\n"; + std::cerr << "stderr " << i << "\n"; + break; + case 4: + std::cout << "stdout " << i << "\n"; + std::cerr << "stderr " << i << "\n"; + std::cerr << "stderr " << i << "\n"; + break; + default: + UNREACHABLE; + } + } +} + +ATF_TEST_CASE(testvar); +ATF_TEST_CASE_HEAD(testvar) +{ + set_md_var("descr", "Helper test case for the t_integration test program"); +} +ATF_TEST_CASE_BODY(testvar) +{ + if (!has_config_var("testvar")) + fail("testvar variable not defined"); + std::cout << "testvar: " << get_config_var("testvar") << "\n"; +} + +ATF_TEST_CASE(env_list); +ATF_TEST_CASE_HEAD(env_list) +{ + set_md_var("descr", "Helper test case for the t_integration test program"); +} +ATF_TEST_CASE_BODY(env_list) +{ + const atf::process::status s = + atf::process::exec(atf::fs::path("env"), + atf::process::argv_array("env", NULL), + atf::process::stream_inherit(), + atf::process::stream_inherit()); + ATF_REQUIRE(s.exited()); + ATF_REQUIRE(s.exitstatus() == EXIT_SUCCESS); +} + +ATF_TEST_CASE(env_home); +ATF_TEST_CASE_HEAD(env_home) +{ + set_md_var("descr", "Helper test case for the t_integration test program"); +} +ATF_TEST_CASE_BODY(env_home) +{ + ATF_REQUIRE(atf::env::has("HOME")); + atf::fs::path p(atf::env::get("HOME")); + atf::fs::file_info fi1(p); + atf::fs::file_info fi2(atf::fs::path(".")); + ATF_REQUIRE_EQ(fi1.get_device(), fi2.get_device()); + ATF_REQUIRE_EQ(fi1.get_inode(), fi2.get_inode()); +} + +ATF_TEST_CASE(read_stdin); +ATF_TEST_CASE_HEAD(read_stdin) +{ + set_md_var("descr", "Helper test case for the t_integration test program"); +} +ATF_TEST_CASE_BODY(read_stdin) +{ + char buf[100]; + ssize_t len = ::read(STDIN_FILENO, buf, sizeof(buf) - 1); + ATF_REQUIRE(len != -1); + + buf[len + 1] = '\0'; + for (ssize_t i = 0; i < len; i++) { + if (buf[i] != '\0') { + fail("The stdin of the test case does not seem to be /dev/zero; " + "got '" + std::string(buf) + "'"); + } + } +} + +ATF_TEST_CASE(umask); +ATF_TEST_CASE_HEAD(umask) +{ + set_md_var("descr", "Helper test case for the t_integration test program"); +} +ATF_TEST_CASE_BODY(umask) +{ + mode_t m = ::umask(0); + std::cout << "umask: " << std::setw(4) << std::setfill('0') + << std::oct << m << "\n"; + (void)::umask(m); +} + +ATF_TEST_CASE_WITH_CLEANUP(cleanup_states); +ATF_TEST_CASE_HEAD(cleanup_states) +{ + set_md_var("descr", "Helper test case for the t_integration test program"); +} +ATF_TEST_CASE_BODY(cleanup_states) +{ + touch(get_config_var("statedir") + "/to-delete"); + touch(get_config_var("statedir") + "/to-stay"); + + if (get_config_var("state") == "fail") + ATF_FAIL("On purpose"); + else if (get_config_var("state") == "skip") + ATF_SKIP("On purpose"); +} +ATF_TEST_CASE_CLEANUP(cleanup_states) +{ + atf::fs::remove(atf::fs::path(get_config_var("statedir") + "/to-delete")); +} + +ATF_TEST_CASE_WITH_CLEANUP(cleanup_curdir); +ATF_TEST_CASE_HEAD(cleanup_curdir) +{ + set_md_var("descr", "Helper test case for the t_integration test program"); +} +ATF_TEST_CASE_BODY(cleanup_curdir) +{ + std::ofstream os("oldvalue"); + if (!os) + ATF_FAIL("Failed to create oldvalue file"); + os << 1234; + os.close(); +} +ATF_TEST_CASE_CLEANUP(cleanup_curdir) +{ + std::ifstream is("oldvalue"); + if (is) { + int i; + is >> i; + std::cout << "Old value: " << i << "\n"; + is.close(); + } +} + +ATF_TEST_CASE(require_arch); +ATF_TEST_CASE_HEAD(require_arch) +{ + set_md_var("descr", "Helper test case for the t_integration test program"); + set_md_var("require.arch", get_config_var("arch", "not-set")); +} +ATF_TEST_CASE_BODY(require_arch) +{ +} + +ATF_TEST_CASE(require_config); +ATF_TEST_CASE_HEAD(require_config) +{ + set_md_var("descr", "Helper test case for the t_integration test program"); + set_md_var("require.config", "var1 var2"); +} +ATF_TEST_CASE_BODY(require_config) +{ + std::cout << "var1: " << get_config_var("var1") << "\n"; + std::cout << "var2: " << get_config_var("var2") << "\n"; +} + +ATF_TEST_CASE(require_files); +ATF_TEST_CASE_HEAD(require_files) +{ + set_md_var("descr", "Helper test case for the t_integration test program"); + set_md_var("require.files", get_config_var("files", "not-set")); +} +ATF_TEST_CASE_BODY(require_files) +{ +} + +ATF_TEST_CASE(require_machine); +ATF_TEST_CASE_HEAD(require_machine) +{ + set_md_var("descr", "Helper test case for the t_integration test program"); + set_md_var("require.machine", get_config_var("machine", "not-set")); +} +ATF_TEST_CASE_BODY(require_machine) +{ +} + +ATF_TEST_CASE(require_progs); +ATF_TEST_CASE_HEAD(require_progs) +{ + set_md_var("descr", "Helper test case for the t_integration test program"); + set_md_var("require.progs", get_config_var("progs", "not-set")); +} +ATF_TEST_CASE_BODY(require_progs) +{ +} + +ATF_TEST_CASE(require_user); +ATF_TEST_CASE_HEAD(require_user) +{ + set_md_var("descr", "Helper test case for the t_integration test program"); + set_md_var("require.user", get_config_var("user", "not-set")); +} +ATF_TEST_CASE_BODY(require_user) +{ +} + +ATF_TEST_CASE(timeout); +ATF_TEST_CASE_HEAD(timeout) +{ + set_md_var("descr", "Helper test case for the t_integration test program"); + set_md_var("timeout", "1"); +} +ATF_TEST_CASE_BODY(timeout) +{ + sleep(10); + touch(get_config_var("statedir") + "/finished"); +} + +ATF_TEST_CASE(timeout_forkexit); +ATF_TEST_CASE_HEAD(timeout_forkexit) +{ + set_md_var("descr", "Helper test case for the t_integration test program"); +} +ATF_TEST_CASE_BODY(timeout_forkexit) +{ + pid_t pid = fork(); + ATF_REQUIRE(pid != -1); + + if (pid == 0) { + sigset_t mask; + sigemptyset(&mask); + + std::cout << "Waiting in subprocess\n"; + std::cout.flush(); + ::sigsuspend(&mask); + + touch(get_config_var("statedir") + "/child-finished"); + std::cout << "Subprocess exiting\n"; + std::cout.flush(); + exit(EXIT_SUCCESS); + } else { + // Don't wait for the child process and let atf-run deal with it. + touch(get_config_var("statedir") + "/parent-finished"); + std::cout << "Parent process exiting\n"; + ATF_PASS(); + } +} + +ATF_TEST_CASE(use_fs); +ATF_TEST_CASE_HEAD(use_fs) +{ + set_md_var("descr", "Helper test case for the t_integration test program"); + set_md_var("use.fs", "this-is-deprecated"); +} +ATF_TEST_CASE_BODY(use_fs) +{ + touch("test-file"); +} + +// ------------------------------------------------------------------------ +// Main. +// ------------------------------------------------------------------------ + +ATF_INIT_TEST_CASES(tcs) +{ + std::string which = atf::env::get("TESTCASE"); + + // Add helper tests for t_integration. + if (which == "pass") + ATF_ADD_TEST_CASE(tcs, pass); + if (which == "config") + ATF_ADD_TEST_CASE(tcs, config); + if (which == "fds") + ATF_ADD_TEST_CASE(tcs, fds); + if (which == "mux_streams") + ATF_ADD_TEST_CASE(tcs, mux_streams); + if (which == "testvar") + ATF_ADD_TEST_CASE(tcs, testvar); + if (which == "env_list") + ATF_ADD_TEST_CASE(tcs, env_list); + if (which == "env_home") + ATF_ADD_TEST_CASE(tcs, env_home); + if (which == "read_stdin") + ATF_ADD_TEST_CASE(tcs, read_stdin); + if (which == "umask") + ATF_ADD_TEST_CASE(tcs, umask); + if (which == "cleanup_states") + ATF_ADD_TEST_CASE(tcs, cleanup_states); + if (which == "cleanup_curdir") + ATF_ADD_TEST_CASE(tcs, cleanup_curdir); + if (which == "require_arch") + ATF_ADD_TEST_CASE(tcs, require_arch); + if (which == "require_config") + ATF_ADD_TEST_CASE(tcs, require_config); + if (which == "require_files") + ATF_ADD_TEST_CASE(tcs, require_files); + if (which == "require_machine") + ATF_ADD_TEST_CASE(tcs, require_machine); + if (which == "require_progs") + ATF_ADD_TEST_CASE(tcs, require_progs); + if (which == "require_user") + ATF_ADD_TEST_CASE(tcs, require_user); + if (which == "timeout") + ATF_ADD_TEST_CASE(tcs, timeout); + if (which == "timeout_forkexit") + ATF_ADD_TEST_CASE(tcs, timeout_forkexit); + if (which == "use_fs") + ATF_ADD_TEST_CASE(tcs, use_fs); +} diff --git a/external/bsd/atf/dist/atf-run/pass_helper.cpp b/external/bsd/atf/dist/atf-run/pass_helper.cpp new file mode 100644 index 000000000..b752b131b --- /dev/null +++ b/external/bsd/atf/dist/atf-run/pass_helper.cpp @@ -0,0 +1,44 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#include "atf-c++/macros.hpp" + +ATF_TEST_CASE(main); +ATF_TEST_CASE_HEAD(main) +{ + set_md_var("descr", "Helper test case that always passes"); +} +ATF_TEST_CASE_BODY(main) +{ +} + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, main); +} diff --git a/external/bsd/atf/dist/atf-run/requirements.cpp b/external/bsd/atf/dist/atf-run/requirements.cpp new file mode 100644 index 000000000..75537d5ea --- /dev/null +++ b/external/bsd/atf/dist/atf-run/requirements.cpp @@ -0,0 +1,319 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +extern "C" { +#include +#include +} + +#include +#include +#include + +extern "C" { +#include "atf-c/defs.h" +} + +#include "atf-c++/config.hpp" + +#include "atf-c++/detail/fs.hpp" +#include "atf-c++/detail/env.hpp" +#include "atf-c++/detail/sanity.hpp" +#include "atf-c++/detail/text.hpp" + +#include "requirements.hpp" +#include "user.hpp" + +namespace impl = atf::atf_run; + +namespace { + +static +bool +has_program(const atf::fs::path& program) +{ + bool found = false; + + if (program.is_absolute()) { + found = atf::fs::is_executable(program); + } else { + if (program.str().find('/') != std::string::npos) + throw std::runtime_error("Relative paths are not allowed " + "when searching for a program (" + + program.str() + ")"); + + const std::vector< std::string > dirs = atf::text::split( + atf::env::get("PATH"), ":"); + for (std::vector< std::string >::const_iterator iter = dirs.begin(); + !found && iter != dirs.end(); iter++) { + const atf::fs::path& p = atf::fs::path(*iter) / program; + if (atf::fs::is_executable(p)) + found = true; + } + } + + return found; +} + +static +std::string +check_arch(const std::string& arches) +{ + const std::vector< std::string > v = atf::text::split(arches, " "); + + for (std::vector< std::string >::const_iterator iter = v.begin(); + iter != v.end(); iter++) { + if ((*iter) == atf::config::get("atf_arch")) + return ""; + } + + if (v.size() == 1) + return "Requires the '" + arches + "' architecture"; + else + return "Requires one of the '" + arches + "' architectures"; +} + +static +std::string +check_config(const std::string& variables, const atf::tests::vars_map& config) +{ + const std::vector< std::string > v = atf::text::split(variables, " "); + for (std::vector< std::string >::const_iterator iter = v.begin(); + iter != v.end(); iter++) { + if (config.find((*iter)) == config.end()) + return "Required configuration variable '" + (*iter) + "' not " + "defined"; + } + return ""; +} + +static +std::string +check_files(const std::string& progs) +{ + const std::vector< std::string > v = atf::text::split(progs, " "); + for (std::vector< std::string >::const_iterator iter = v.begin(); + iter != v.end(); iter++) { + const atf::fs::path file(*iter); + if (!file.is_absolute()) + throw std::runtime_error("Relative paths are not allowed when " + "checking for a required file (" + file.str() + ")"); + if (!atf::fs::exists(file)) + return "Required file '" + file.str() + "' not found"; + } + return ""; +} + +static +std::string +check_machine(const std::string& machines) +{ + const std::vector< std::string > v = atf::text::split(machines, " "); + + for (std::vector< std::string >::const_iterator iter = v.begin(); + iter != v.end(); iter++) { + if ((*iter) == atf::config::get("atf_machine")) + return ""; + } + + if (v.size() == 1) + return "Requires the '" + machines + "' machine type"; + else + return "Requires one of the '" + machines + "' machine types"; +} + +#if defined(__APPLE__) || defined(__NetBSD__) +static +std::string +check_memory_sysctl(const int64_t needed, const char* sysctl_variable) +{ + int64_t available; + std::size_t available_length = sizeof(available); + if (::sysctlbyname(sysctl_variable, &available, &available_length, + NULL, 0) == -1) { + const char* e = std::strerror(errno); + return "Failed to get sysctl(hw.usermem64) value: " + std::string(e); + } + + if (available < needed) { + return "Not enough memory; needed " + atf::text::to_string(needed) + + ", available " + atf::text::to_string(available); + } else + return ""; +} +# if defined(__APPLE__) +static +std::string +check_memory_darwin(const int64_t needed) +{ + return check_memory_sysctl(needed, "hw.usermem"); +} +# elif defined(__NetBSD__) +static +std::string +check_memory_netbsd(const int64_t needed) +{ + return check_memory_sysctl(needed, "hw.usermem64"); +} +# else +# error "Conditional error" +# endif +#else +static +std::string +check_memory_unknown(const int64_t needed ATF_DEFS_ATTRIBUTE_UNUSED) +{ + return ""; +} +#endif + +static +std::string +check_memory(const std::string& raw_memory) +{ + const int64_t needed = atf::text::to_bytes(raw_memory); + +#if defined(__APPLE__) + return check_memory_darwin(needed); +#elif defined(__NetBSD__) + return check_memory_netbsd(needed); +#else + return check_memory_unknown(needed); +#endif +} + +static +std::string +check_progs(const std::string& progs) +{ + const std::vector< std::string > v = atf::text::split(progs, " "); + for (std::vector< std::string >::const_iterator iter = v.begin(); + iter != v.end(); iter++) { + if (!has_program(atf::fs::path(*iter))) + return "Required program '" + (*iter) + "' not found in the PATH"; + } + return ""; +} + +static +std::string +check_user(const std::string& user, const atf::tests::vars_map& config) +{ + if (user == "root") { + if (!impl::is_root()) + return "Requires root privileges"; + else + return ""; + } else if (user == "unprivileged") { + if (impl::is_root()) { + const atf::tests::vars_map::const_iterator iter = config.find( + "unprivileged-user"); + if (iter == config.end()) + return "Requires an unprivileged user and the " + "'unprivileged-user' configuration variable is not set"; + else { + const std::string& unprivileged_user = (*iter).second; + try { + (void)impl::get_user_ids(unprivileged_user); + return ""; + } catch (const std::runtime_error& e) { + return "Failed to get information for user " + + unprivileged_user; + } + } + } else + return ""; + } else + throw std::runtime_error("Invalid value '" + user + "' for property " + "require.user"); +} + +} // anonymous namespace + +std::string +impl::check_requirements(const atf::tests::vars_map& metadata, + const atf::tests::vars_map& config) +{ + std::string failure_reason = ""; + + for (atf::tests::vars_map::const_iterator iter = metadata.begin(); + failure_reason.empty() && iter != metadata.end(); iter++) { + const std::string& name = (*iter).first; + const std::string& value = (*iter).second; + INV(!value.empty()); // Enforced by application/X-atf-tp parser. + + if (name == "require.arch") + failure_reason = check_arch(value); + else if (name == "require.config") + failure_reason = check_config(value, config); + else if (name == "require.files") + failure_reason = check_files(value); + else if (name == "require.machine") + failure_reason = check_machine(value); + else if (name == "require.memory") + failure_reason = check_memory(value); + else if (name == "require.progs") + failure_reason = check_progs(value); + else if (name == "require.user") + failure_reason = check_user(value, config); + else { + // Unknown require.* properties are forbidden by the + // application/X-atf-tp parser. + INV(failure_reason.find("require.") != 0); + } + } + + return failure_reason; +} + +std::pair< int, int > +impl::get_required_user(const atf::tests::vars_map& metadata, + const atf::tests::vars_map& config) +{ + const atf::tests::vars_map::const_iterator user = metadata.find( + "require.user"); + if (user == metadata.end()) + return std::make_pair(-1, -1); + + if ((*user).second == "unprivileged") { + if (impl::is_root()) { + const atf::tests::vars_map::const_iterator iter = config.find( + "unprivileged-user"); + try { + return impl::get_user_ids((*iter).second); + } catch (const std::exception& e) { + UNREACHABLE; // This has been validated by check_user. + throw e; + } + } else { + return std::make_pair(-1, -1); + } + } else + return std::make_pair(-1, -1); +} diff --git a/external/bsd/atf/dist/atf-run/requirements.hpp b/external/bsd/atf/dist/atf-run/requirements.hpp new file mode 100644 index 000000000..62c072d5f --- /dev/null +++ b/external/bsd/atf/dist/atf-run/requirements.hpp @@ -0,0 +1,44 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2010 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#include +#include + +#include "atf-c++/tests.hpp" + +namespace atf { +namespace atf_run { + +std::string check_requirements(const atf::tests::vars_map&, + const atf::tests::vars_map&); +std::pair< int, int > get_required_user(const atf::tests::vars_map&, + const atf::tests::vars_map&); + +} // namespace atf_run +} // namespace atf diff --git a/external/bsd/atf/dist/atf-run/requirements_test.cpp b/external/bsd/atf/dist/atf-run/requirements_test.cpp new file mode 100644 index 000000000..ef72b411d --- /dev/null +++ b/external/bsd/atf/dist/atf-run/requirements_test.cpp @@ -0,0 +1,398 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2010 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#include "atf-c++/config.hpp" +#include "atf-c++/detail/text.hpp" +#include "atf-c++/macros.hpp" + +#include "requirements.hpp" +#include "user.hpp" + +namespace impl = atf::atf_run; + +// ------------------------------------------------------------------------- +// Auxiliary functions. +// ------------------------------------------------------------------------- + +namespace { + +const atf::tests::vars_map no_config; + +void +do_check(const std::string& expected, const atf::tests::vars_map& metadata, + const atf::tests::vars_map& config = no_config) +{ + const std::string actual = impl::check_requirements(metadata, config); + if (!atf::text::match(actual, expected)) + ATF_FAIL("Requirements failure reason \"" + actual + "\" does not " + "match \"" + expected + "\""); +} + +} // anonymous namespace + +// ------------------------------------------------------------------------- +// Tests for the require.arch metadata property. +// ------------------------------------------------------------------------- + +ATF_TEST_CASE(require_arch_one_ok); +ATF_TEST_CASE_HEAD(require_arch_one_ok) {} +ATF_TEST_CASE_BODY(require_arch_one_ok) { + atf::tests::vars_map metadata; + metadata["require.arch"] = atf::config::get("atf_arch"); + do_check("", metadata); +} + +ATF_TEST_CASE(require_arch_one_fail); +ATF_TEST_CASE_HEAD(require_arch_one_fail) {} +ATF_TEST_CASE_BODY(require_arch_one_fail) { + atf::tests::vars_map metadata; + metadata["require.arch"] = "__fake_arch__"; + do_check("Requires the '__fake_arch__' architecture", metadata); +} + +ATF_TEST_CASE(require_arch_many_ok); +ATF_TEST_CASE_HEAD(require_arch_many_ok) {} +ATF_TEST_CASE_BODY(require_arch_many_ok) { + atf::tests::vars_map metadata; + metadata["require.arch"] = "__foo__ " + atf::config::get("atf_arch") + + " __bar__"; + do_check("", metadata); +} + +ATF_TEST_CASE(require_arch_many_fail); +ATF_TEST_CASE_HEAD(require_arch_many_fail) {} +ATF_TEST_CASE_BODY(require_arch_many_fail) { + atf::tests::vars_map metadata; + metadata["require.arch"] = "__foo__ __bar__ __baz__"; + do_check("Requires one of the '__foo__ __bar__ __baz__' architectures", + metadata); +} + +// ------------------------------------------------------------------------- +// Tests for the require.config metadata property. +// ------------------------------------------------------------------------- + +ATF_TEST_CASE(require_config_one_ok); +ATF_TEST_CASE_HEAD(require_config_one_ok) {} +ATF_TEST_CASE_BODY(require_config_one_ok) { + atf::tests::vars_map metadata, config; + metadata["require.config"] = "var1"; + config["var1"] = "some-value"; + do_check("", metadata, config); +} + +ATF_TEST_CASE(require_config_one_fail); +ATF_TEST_CASE_HEAD(require_config_one_fail) {} +ATF_TEST_CASE_BODY(require_config_one_fail) { + atf::tests::vars_map metadata, config; + metadata["require.config"] = "var1"; + do_check("Required configuration variable 'var1' not defined", metadata, + config); +} + +ATF_TEST_CASE(require_config_many_ok); +ATF_TEST_CASE_HEAD(require_config_many_ok) {} +ATF_TEST_CASE_BODY(require_config_many_ok) { + atf::tests::vars_map metadata, config; + metadata["require.config"] = "var1 var2 var3"; + config["var1"] = "first-value"; + config["var2"] = "second-value"; + config["var3"] = "third-value"; + do_check("", metadata, config); +} + +ATF_TEST_CASE(require_config_many_fail); +ATF_TEST_CASE_HEAD(require_config_many_fail) {} +ATF_TEST_CASE_BODY(require_config_many_fail) { + atf::tests::vars_map metadata, config; + metadata["require.config"] = "var1 var2 var3"; + config["var1"] = "first-value"; + config["var3"] = "third-value"; + do_check("Required configuration variable 'var2' not defined", metadata, + config); +} + +// ------------------------------------------------------------------------- +// Tests for the require.files metadata property. +// ------------------------------------------------------------------------- + +ATF_TEST_CASE_WITHOUT_HEAD(require_files_one_ok); +ATF_TEST_CASE_BODY(require_files_one_ok) { + atf::tests::vars_map metadata; + metadata["require.files"] = "/bin/ls"; + do_check("", metadata); +} + +ATF_TEST_CASE_WITHOUT_HEAD(require_files_one_missing); +ATF_TEST_CASE_BODY(require_files_one_missing) { + atf::tests::vars_map metadata; + metadata["require.files"] = "/non-existent/foo"; + do_check("Required file '/non-existent/foo' not found", metadata); +} + +ATF_TEST_CASE_WITHOUT_HEAD(require_files_one_fail); +ATF_TEST_CASE_BODY(require_files_one_fail) { + atf::tests::vars_map metadata; + metadata["require.files"] = "/bin/cp this-is-relative"; + ATF_REQUIRE_THROW_RE(std::runtime_error, "Relative.*(this-is-relative)", + impl::check_requirements(metadata, no_config)); +} + +ATF_TEST_CASE_WITHOUT_HEAD(require_files_many_ok); +ATF_TEST_CASE_BODY(require_files_many_ok) { + atf::tests::vars_map metadata; + metadata["require.files"] = "/bin/ls /bin/cp"; + do_check("", metadata); +} + +ATF_TEST_CASE_WITHOUT_HEAD(require_files_many_missing); +ATF_TEST_CASE_BODY(require_files_many_missing) { + atf::tests::vars_map metadata; + metadata["require.files"] = "/bin/ls /non-existent/bar /bin/cp"; + do_check("Required file '/non-existent/bar' not found", metadata); +} + +ATF_TEST_CASE_WITHOUT_HEAD(require_files_many_fail); +ATF_TEST_CASE_BODY(require_files_many_fail) { + atf::tests::vars_map metadata; + metadata["require.files"] = "/bin/cp also-relative"; + ATF_REQUIRE_THROW_RE(std::runtime_error, "Relative.*(also-relative)", + impl::check_requirements(metadata, no_config)); +} + +// ------------------------------------------------------------------------- +// Tests for the require.machine metadata property. +// ------------------------------------------------------------------------- + +ATF_TEST_CASE(require_machine_one_ok); +ATF_TEST_CASE_HEAD(require_machine_one_ok) {} +ATF_TEST_CASE_BODY(require_machine_one_ok) { + atf::tests::vars_map metadata; + metadata["require.machine"] = atf::config::get("atf_machine"); + do_check("", metadata); +} + +ATF_TEST_CASE(require_machine_one_fail); +ATF_TEST_CASE_HEAD(require_machine_one_fail) {} +ATF_TEST_CASE_BODY(require_machine_one_fail) { + atf::tests::vars_map metadata; + metadata["require.machine"] = "__fake_machine__"; + do_check("Requires the '__fake_machine__' machine type", metadata); +} + +ATF_TEST_CASE(require_machine_many_ok); +ATF_TEST_CASE_HEAD(require_machine_many_ok) {} +ATF_TEST_CASE_BODY(require_machine_many_ok) { + atf::tests::vars_map metadata; + metadata["require.machine"] = "__foo__ " + atf::config::get("atf_machine") + + " __bar__"; + do_check("", metadata); +} + +ATF_TEST_CASE(require_machine_many_fail); +ATF_TEST_CASE_HEAD(require_machine_many_fail) {} +ATF_TEST_CASE_BODY(require_machine_many_fail) { + atf::tests::vars_map metadata; + metadata["require.machine"] = "__foo__ __bar__ __baz__"; + do_check("Requires one of the '__foo__ __bar__ __baz__' machine types", + metadata); +} + +// ------------------------------------------------------------------------- +// Tests for the require.memory metadata property. +// ------------------------------------------------------------------------- + +ATF_TEST_CASE_WITHOUT_HEAD(require_memory_ok); +ATF_TEST_CASE_BODY(require_memory_ok) { + atf::tests::vars_map metadata; + metadata["require.memory"] = "1m"; + do_check("", metadata); +} + +ATF_TEST_CASE_WITHOUT_HEAD(require_memory_not_enough); +ATF_TEST_CASE_BODY(require_memory_not_enough) { + atf::tests::vars_map metadata; + metadata["require.memory"] = "128t"; +#if defined(__APPLE__) || defined(__NetBSD__) + do_check("Not enough memory; needed 140737488355328, available [0-9]*", + metadata); +#else + skip("Don't know how to check for the amount of physical memory"); +#endif +} + +ATF_TEST_CASE_WITHOUT_HEAD(require_memory_fail); +ATF_TEST_CASE_BODY(require_memory_fail) { + atf::tests::vars_map metadata; + metadata["require.memory"] = "foo"; + ATF_REQUIRE_THROW(std::runtime_error, + impl::check_requirements(metadata, no_config)); +} + +// ------------------------------------------------------------------------- +// Tests for the require.progs metadata property. +// ------------------------------------------------------------------------- + +ATF_TEST_CASE(require_progs_one_ok); +ATF_TEST_CASE_HEAD(require_progs_one_ok) {} +ATF_TEST_CASE_BODY(require_progs_one_ok) { + atf::tests::vars_map metadata; + metadata["require.progs"] = "cp"; + do_check("", metadata); +} + +ATF_TEST_CASE(require_progs_one_missing); +ATF_TEST_CASE_HEAD(require_progs_one_missing) {} +ATF_TEST_CASE_BODY(require_progs_one_missing) { + atf::tests::vars_map metadata; + metadata["require.progs"] = "cp __non-existent__"; + do_check("Required program '__non-existent__' not found in the PATH", + metadata); +} + +ATF_TEST_CASE(require_progs_one_fail); +ATF_TEST_CASE_HEAD(require_progs_one_fail) {} +ATF_TEST_CASE_BODY(require_progs_one_fail) { + atf::tests::vars_map metadata; + metadata["require.progs"] = "bin/cp"; + ATF_REQUIRE_THROW(std::runtime_error, + impl::check_requirements(metadata, no_config)); +} + +ATF_TEST_CASE(require_progs_many_ok); +ATF_TEST_CASE_HEAD(require_progs_many_ok) {} +ATF_TEST_CASE_BODY(require_progs_many_ok) { + atf::tests::vars_map metadata; + metadata["require.progs"] = "cp ls mv"; + do_check("", metadata); +} + +ATF_TEST_CASE(require_progs_many_missing); +ATF_TEST_CASE_HEAD(require_progs_many_missing) {} +ATF_TEST_CASE_BODY(require_progs_many_missing) { + atf::tests::vars_map metadata; + metadata["require.progs"] = "mv ls __foo__ cp"; + do_check("Required program '__foo__' not found in the PATH", metadata); +} + +ATF_TEST_CASE(require_progs_many_fail); +ATF_TEST_CASE_HEAD(require_progs_many_fail) {} +ATF_TEST_CASE_BODY(require_progs_many_fail) { + atf::tests::vars_map metadata; + metadata["require.progs"] = "ls cp ../bin/cp"; + ATF_REQUIRE_THROW(std::runtime_error, + impl::check_requirements(metadata, no_config)); +} + +// ------------------------------------------------------------------------- +// Tests for the require.user metadata property. +// ------------------------------------------------------------------------- + +ATF_TEST_CASE(require_user_root); +ATF_TEST_CASE_HEAD(require_user_root) {} +ATF_TEST_CASE_BODY(require_user_root) { + atf::tests::vars_map metadata; + metadata["require.user"] = "root"; + if (atf::atf_run::is_root()) + do_check("", metadata); + else + do_check("Requires root privileges", metadata); +} + +ATF_TEST_CASE(require_user_unprivileged); +ATF_TEST_CASE_HEAD(require_user_unprivileged) {} +ATF_TEST_CASE_BODY(require_user_unprivileged) { + atf::tests::vars_map metadata; + metadata["require.user"] = "unprivileged"; + if (atf::atf_run::is_root()) + do_check("Requires an unprivileged user and the 'unprivileged-user' " + "configuration variable is not set", metadata); + else + do_check("", metadata); +} + +ATF_TEST_CASE(require_user_fail); +ATF_TEST_CASE_HEAD(require_user_fail) {} +ATF_TEST_CASE_BODY(require_user_fail) { + atf::tests::vars_map metadata; + metadata["require.user"] = "nobody"; + ATF_REQUIRE_THROW(std::runtime_error, + impl::check_requirements(metadata, no_config)); +} + +// ------------------------------------------------------------------------- +// Main. +// ------------------------------------------------------------------------- + +ATF_INIT_TEST_CASES(tcs) +{ + // Add test cases for require.arch. + ATF_ADD_TEST_CASE(tcs, require_arch_one_ok); + ATF_ADD_TEST_CASE(tcs, require_arch_one_fail); + ATF_ADD_TEST_CASE(tcs, require_arch_many_ok); + ATF_ADD_TEST_CASE(tcs, require_arch_many_fail); + + // Add test cases for require.config. + ATF_ADD_TEST_CASE(tcs, require_config_one_ok); + ATF_ADD_TEST_CASE(tcs, require_config_one_fail); + ATF_ADD_TEST_CASE(tcs, require_config_many_ok); + ATF_ADD_TEST_CASE(tcs, require_config_many_fail); + + // Add test cases for require.files. + ATF_ADD_TEST_CASE(tcs, require_files_one_ok); + ATF_ADD_TEST_CASE(tcs, require_files_one_missing); + ATF_ADD_TEST_CASE(tcs, require_files_one_fail); + ATF_ADD_TEST_CASE(tcs, require_files_many_ok); + ATF_ADD_TEST_CASE(tcs, require_files_many_missing); + ATF_ADD_TEST_CASE(tcs, require_files_many_fail); + + // Add test cases for require.machine. + ATF_ADD_TEST_CASE(tcs, require_machine_one_ok); + ATF_ADD_TEST_CASE(tcs, require_machine_one_fail); + ATF_ADD_TEST_CASE(tcs, require_machine_many_ok); + ATF_ADD_TEST_CASE(tcs, require_machine_many_fail); + + // Add test cases for require.memory. + ATF_ADD_TEST_CASE(tcs, require_memory_ok); + ATF_ADD_TEST_CASE(tcs, require_memory_not_enough); + ATF_ADD_TEST_CASE(tcs, require_memory_fail); + + // Add test cases for require.progs. + ATF_ADD_TEST_CASE(tcs, require_progs_one_ok); + ATF_ADD_TEST_CASE(tcs, require_progs_one_missing); + ATF_ADD_TEST_CASE(tcs, require_progs_one_fail); + ATF_ADD_TEST_CASE(tcs, require_progs_many_ok); + ATF_ADD_TEST_CASE(tcs, require_progs_many_missing); + ATF_ADD_TEST_CASE(tcs, require_progs_many_fail); + + // Add test cases for require.user. + ATF_ADD_TEST_CASE(tcs, require_user_root); + ATF_ADD_TEST_CASE(tcs, require_user_unprivileged); + ATF_ADD_TEST_CASE(tcs, require_user_fail); +} diff --git a/external/bsd/atf/dist/atf-run/sample/atf-run.hooks b/external/bsd/atf/dist/atf-run/sample/atf-run.hooks new file mode 100644 index 000000000..86d187d3d --- /dev/null +++ b/external/bsd/atf/dist/atf-run/sample/atf-run.hooks @@ -0,0 +1,23 @@ +# +# Definition of custom hooks for atf-run. +# +# Uncomment any hooks that you want to override and add your own code +# to them. Some sample calls are included in them. Be very careful +# with what you print from here. +# +# See atf-run(1) for more details. +# + +#info_start_hook() +#{ +# default_info_start_hook "${@}" +# +# atf_tps_writer_info "extra.info" "An example" +#} + +#info_end_hook() +#{ +# default_info_end_hook "${@}" +# +# atf_tps_writer_info "extra.info" "An example" +#} diff --git a/external/bsd/atf/dist/atf-run/sample/common.conf b/external/bsd/atf/dist/atf-run/sample/common.conf new file mode 100644 index 000000000..464ee96d0 --- /dev/null +++ b/external/bsd/atf/dist/atf-run/sample/common.conf @@ -0,0 +1,11 @@ +Content-Type: application/X-atf-config; version="1" + +# +# Sample configuration file for properties affecting all test suites. +# + +# When running the test suite as root, some tests require to switch to +# an unprivileged user to perform extra checks. Set this variable to +# the user you want to use in those cases. If not set, those tests will +# be skipped. +#unprivileged-user = "_atf" diff --git a/external/bsd/atf/dist/atf-run/several_tcs_helper.c b/external/bsd/atf/dist/atf-run/several_tcs_helper.c new file mode 100644 index 000000000..d287c8193 --- /dev/null +++ b/external/bsd/atf/dist/atf-run/several_tcs_helper.c @@ -0,0 +1,67 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2010 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +ATF_TC(first); +ATF_TC_HEAD(first, tc) +{ + atf_tc_set_md_var(tc, "descr", "Description 1"); +} +ATF_TC_BODY(first, tc) +{ +} + +ATF_TC_WITH_CLEANUP(second); +ATF_TC_HEAD(second, tc) +{ + atf_tc_set_md_var(tc, "descr", "Description 2"); + atf_tc_set_md_var(tc, "timeout", "500"); + atf_tc_set_md_var(tc, "X-property", "Custom property"); +} +ATF_TC_BODY(second, tc) +{ +} +ATF_TC_CLEANUP(second, tc) +{ +} + +ATF_TC_WITHOUT_HEAD(third); +ATF_TC_BODY(third, tc) +{ +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, first); + ATF_TP_ADD_TC(tp, second); + ATF_TP_ADD_TC(tp, third); + + return atf_no_error(); +} diff --git a/external/bsd/atf/dist/atf-run/share/atf-run.hooks b/external/bsd/atf/dist/atf-run/share/atf-run.hooks new file mode 100644 index 000000000..c94f3bcfc --- /dev/null +++ b/external/bsd/atf/dist/atf-run/share/atf-run.hooks @@ -0,0 +1,94 @@ +# +# Automated Testing Framework (atf) +# +# Copyright (c) 2007 The NetBSD Foundation, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +# CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +atf_tps_writer_info() +{ + class=${1}; shift + echo "info: ${class}, $*" +} + +info_start_hook() +{ + default_info_start_hook "${@}" +} + +default_info_start_hook() +{ + atf_tps_writer_info "atf.version" $(atf-version | head -n 1) + + atf_tps_writer_info "tests.root" $(pwd) + + atf_tps_writer_info "time.start" $(date) + + atf_tps_writer_info "uname.sysname" $(uname -s) + atf_tps_writer_info "uname.nodename" $(uname -n) + atf_tps_writer_info "uname.release" $(uname -r) + atf_tps_writer_info "uname.version" $(uname -v) + atf_tps_writer_info "uname.machine" $(uname -m) + + # Add all the environment variables to the report. We have to be + # careful with those that span over multiple lines; otherwise their + # values could be printed as multiple different variables (one per + # line), which is incorrect. + oldifs="${IFS}" + IFS=' +' + set -- $(env) + val=${1}; shift + while [ ${#} -gt 0 ]; do + if echo "${1}" | grep '^[a-zA-Z0-0_][a-zA-Z0-9_]*=' >/dev/null; then + atf_tps_writer_info "env" "${val}" + val="${1}" + else + val="${val} ${1}" + fi + shift + done + atf_tps_writer_info "env" "${val}" + IFS="${oldifs}" +} + +info_end_hook() +{ + default_info_end_hook "${@}" +} + +default_info_end_hook() +{ + atf_tps_writer_info "time.end" $(date) +} + +sitehooks=$(atf-config -t atf_confdir)/atf-run.hooks +userhooks=${HOME}/.atf/atf-run.hooks +[ -f ${sitehooks} ] && . ${sitehooks} +[ -f ${userhooks} ] && . ${userhooks} + +eval ${1} + +# vim: syntax=sh:expandtab:shiftwidth=4:softtabstop=4 diff --git a/external/bsd/atf/dist/atf-run/signals.cpp b/external/bsd/atf/dist/atf-run/signals.cpp new file mode 100644 index 000000000..851c8f02c --- /dev/null +++ b/external/bsd/atf/dist/atf-run/signals.cpp @@ -0,0 +1,147 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#if defined(HAVE_CONFIG_H) +#include "bconfig.h" +#endif + +extern "C" { +#include +#include +} + +#include + +#include "atf-c++/detail/exceptions.hpp" +#include "atf-c++/detail/sanity.hpp" + +#include "signals.hpp" + +namespace impl = atf::atf_run; +#define IMPL_NAME "atf::atf_run" + +const int impl::last_signo = LAST_SIGNO; + +// ------------------------------------------------------------------------ +// The "signal_holder" class. +// ------------------------------------------------------------------------ + +namespace { + +static bool happened[LAST_SIGNO + 1]; + +static +void +holder_handler(const int signo) +{ + happened[signo] = true; +} + +} // anonymous namespace + +impl::signal_holder::signal_holder(const int signo) : + m_signo(signo), + m_sp(NULL) +{ + happened[signo] = false; + m_sp = new signal_programmer(m_signo, holder_handler); +} + +impl::signal_holder::~signal_holder(void) +{ + if (m_sp != NULL) + delete m_sp; + + if (happened[m_signo]) + ::kill(::getpid(), m_signo); +} + +void +impl::signal_holder::process(void) +{ + if (happened[m_signo]) { + delete m_sp; + m_sp = NULL; + happened[m_signo] = false; + ::kill(::getpid(), m_signo); + m_sp = new signal_programmer(m_signo, holder_handler); + } +} + +// ------------------------------------------------------------------------ +// The "signal_programmer" class. +// ------------------------------------------------------------------------ + +impl::signal_programmer::signal_programmer(const int signo, const handler h) : + m_signo(signo), + m_handler(h), + m_programmed(false) +{ + struct ::sigaction sa; + + sa.sa_handler = m_handler; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + + if (::sigaction(m_signo, &sa, &m_oldsa) == -1) + throw atf::system_error(IMPL_NAME, "Could not install handler for " + "signal", errno); + m_programmed = true; +} + +impl::signal_programmer::~signal_programmer(void) +{ + unprogram(); +} + +void +impl::signal_programmer::unprogram(void) +{ + if (m_programmed) { + if (::sigaction(m_signo, &m_oldsa, NULL) == -1) + UNREACHABLE; + m_programmed = false; + } +} + +// ------------------------------------------------------------------------ +// Free functions. +// ------------------------------------------------------------------------ + +void +impl::reset(const int signo) +{ + struct ::sigaction sa; + + sa.sa_handler = SIG_DFL; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + + (void)::sigaction(signo, &sa, NULL); +} diff --git a/external/bsd/atf/dist/atf-run/signals.hpp b/external/bsd/atf/dist/atf-run/signals.hpp new file mode 100644 index 000000000..8765ac9ec --- /dev/null +++ b/external/bsd/atf/dist/atf-run/signals.hpp @@ -0,0 +1,92 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#if !defined(_ATF_RUN_SIGNALS_HPP_) +#define _ATF_RUN_SIGNALS_HPP_ + +extern "C" { +#include +} + +namespace atf { +namespace atf_run { + +extern const int last_signo; +typedef void (*handler)(const int); + +class signal_programmer; + +// ------------------------------------------------------------------------ +// The "signal_holder" class. +// ------------------------------------------------------------------------ + +// +// A RAII model to hold a signal while the object is alive. +// +class signal_holder { + const int m_signo; + signal_programmer* m_sp; + +public: + signal_holder(const int); + ~signal_holder(void); + + void process(void); +}; + +// ------------------------------------------------------------------------ +// The "signal_programmer" class. +// ------------------------------------------------------------------------ + +// +// A RAII model to program a signal while the object is alive. +// +class signal_programmer { + const int m_signo; + const handler m_handler; + bool m_programmed; + struct sigaction m_oldsa; + +public: + signal_programmer(const int, const handler); + ~signal_programmer(void); + + void unprogram(void); +}; + +// ------------------------------------------------------------------------ +// Free functions. +// ------------------------------------------------------------------------ + +void reset(const int); + +} // namespace atf_run +} // namespace atf + +#endif // !defined(_ATF_RUN_SIGNALS_HPP_) diff --git a/external/bsd/atf/dist/atf-run/signals_test.cpp b/external/bsd/atf/dist/atf-run/signals_test.cpp new file mode 100644 index 000000000..358c8a8ab --- /dev/null +++ b/external/bsd/atf/dist/atf-run/signals_test.cpp @@ -0,0 +1,277 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2008 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +extern "C" { +#include +#include +#include +} + +#include +#include +#include + +#include "atf-c/defs.h" + +#include "atf-c++/macros.hpp" + +#include "atf-c++/detail/exceptions.hpp" +#include "atf-c++/detail/process.hpp" + +#include "signals.hpp" + +// ------------------------------------------------------------------------ +// Auxiliary functions. +// ------------------------------------------------------------------------ + +namespace sigusr1 { + static bool happened = false; + + static + void + handler(int signo ATF_DEFS_ATTRIBUTE_UNUSED) + { + happened = true; + } + + static + void + program(void) + { + struct sigaction sa; + sa.sa_handler = handler; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + if (::sigaction(SIGUSR1, &sa, NULL) == -1) + throw atf::system_error("sigusr1::program", + "sigaction(2) failed", errno); + } +} // namespace sigusr1 + +namespace sigusr1_2 { + static bool happened = false; + + static + void + handler(int signo ATF_DEFS_ATTRIBUTE_UNUSED) + { + happened = true; + } +} // namespace sigusr1_2 + +// ------------------------------------------------------------------------ +// Tests for the "signal_holder" class. +// ------------------------------------------------------------------------ + +ATF_TEST_CASE(signal_holder_preserve); +ATF_TEST_CASE_HEAD(signal_holder_preserve) +{ + set_md_var("descr", "Tests that signal_holder preserves the original " + "signal handler and restores it upon destruction"); +} +ATF_TEST_CASE_BODY(signal_holder_preserve) +{ + using atf::atf_run::signal_holder; + + sigusr1::program(); + + sigusr1::happened = false; + ::kill(::getpid(), SIGUSR1); + ATF_REQUIRE(sigusr1::happened); + + { + signal_holder hld(SIGUSR1); + ::kill(::getpid(), SIGUSR1); + } + + sigusr1::happened = false; + ::kill(::getpid(), SIGUSR1); + ATF_REQUIRE(sigusr1::happened); +} + +ATF_TEST_CASE(signal_holder_destructor); +ATF_TEST_CASE_HEAD(signal_holder_destructor) +{ + set_md_var("descr", "Tests that signal_holder processes a pending " + "signal upon destruction"); +} +ATF_TEST_CASE_BODY(signal_holder_destructor) +{ + using atf::atf_run::signal_holder; + + sigusr1::program(); + + sigusr1::happened = false; + ::kill(::getpid(), SIGUSR1); + ATF_REQUIRE(sigusr1::happened); + + { + signal_holder hld(SIGUSR1); + + sigusr1::happened = false; + ::kill(::getpid(), SIGUSR1); + ATF_REQUIRE(!sigusr1::happened); + } + ATF_REQUIRE(sigusr1::happened); +} + +ATF_TEST_CASE(signal_holder_process); +ATF_TEST_CASE_HEAD(signal_holder_process) +{ + set_md_var("descr", "Tests that signal_holder's process method works " + "to process a delayed signal explicitly"); +} +ATF_TEST_CASE_BODY(signal_holder_process) +{ + using atf::atf_run::signal_holder; + + sigusr1::program(); + + sigusr1::happened = false; + ::kill(::getpid(), SIGUSR1); + ATF_REQUIRE(sigusr1::happened); + + { + signal_holder hld(SIGUSR1); + + sigusr1::happened = false; + ::kill(::getpid(), SIGUSR1); + ATF_REQUIRE(!sigusr1::happened); + + hld.process(); + ATF_REQUIRE(sigusr1::happened); + + sigusr1::happened = false; + } + ATF_REQUIRE(!sigusr1::happened); +} + +// ------------------------------------------------------------------------ +// Tests for the "signal_programmer" class. +// ------------------------------------------------------------------------ + +ATF_TEST_CASE(signal_programmer_program); +ATF_TEST_CASE_HEAD(signal_programmer_program) +{ + set_md_var("descr", "Tests that signal_programmer correctly installs a " + "handler"); +} +ATF_TEST_CASE_BODY(signal_programmer_program) +{ + using atf::atf_run::signal_programmer; + + signal_programmer sp(SIGUSR1, sigusr1_2::handler); + + sigusr1_2::happened = false; + ::kill(::getpid(), SIGUSR1); + ATF_REQUIRE(sigusr1_2::happened); +} + +ATF_TEST_CASE(signal_programmer_preserve); +ATF_TEST_CASE_HEAD(signal_programmer_preserve) +{ + set_md_var("descr", "Tests that signal_programmer uninstalls the " + "handler during destruction"); +} +ATF_TEST_CASE_BODY(signal_programmer_preserve) +{ + using atf::atf_run::signal_programmer; + + sigusr1::program(); + sigusr1::happened = false; + + { + signal_programmer sp(SIGUSR1, sigusr1_2::handler); + + sigusr1_2::happened = false; + ::kill(::getpid(), SIGUSR1); + ATF_REQUIRE(sigusr1_2::happened); + } + + ATF_REQUIRE(!sigusr1::happened); + ::kill(::getpid(), SIGUSR1); + ATF_REQUIRE(sigusr1::happened); +} + +// ------------------------------------------------------------------------ +// Tests cases for the free functions. +// ------------------------------------------------------------------------ + +static +void +reset_child(void *v ATF_DEFS_ATTRIBUTE_UNUSED) +{ + sigusr1::program(); + + sigusr1::happened = false; + atf::atf_run::reset(SIGUSR1); + kill(::getpid(), SIGUSR1); + + if (sigusr1::happened) { + std::cerr << "Signal was not resetted correctly\n"; + std::abort(); + } else { + std::exit(EXIT_SUCCESS); + } +} + +ATF_TEST_CASE(reset); +ATF_TEST_CASE_HEAD(reset) +{ + set_md_var("descr", "Tests the reset function"); +} +ATF_TEST_CASE_BODY(reset) +{ + atf::process::child c = + atf::process::fork(reset_child, atf::process::stream_inherit(), + atf::process::stream_inherit(), NULL); + + const atf::process::status s = c.wait(); + ATF_REQUIRE(s.exited() || s.signaled()); + ATF_REQUIRE(!s.signaled() || s.termsig() == SIGUSR1); +} + +// ------------------------------------------------------------------------ +// Main. +// ------------------------------------------------------------------------ + +ATF_INIT_TEST_CASES(tcs) +{ + // Add the tests for the "signal_holder" class. + ATF_ADD_TEST_CASE(tcs, signal_holder_preserve); + ATF_ADD_TEST_CASE(tcs, signal_holder_destructor); + ATF_ADD_TEST_CASE(tcs, signal_holder_process); + + // Add the tests for the "signal_programmer" class. + ATF_ADD_TEST_CASE(tcs, signal_programmer_program); + ATF_ADD_TEST_CASE(tcs, signal_programmer_preserve); + + // Add the test cases for the free functions. + ATF_ADD_TEST_CASE(tcs, reset); +} diff --git a/external/bsd/atf/dist/atf-run/test-program.cpp b/external/bsd/atf/dist/atf-run/test-program.cpp new file mode 100644 index 000000000..1e52aa525 --- /dev/null +++ b/external/bsd/atf/dist/atf-run/test-program.cpp @@ -0,0 +1,792 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +extern "C" { +#include +#include +#include + +#include +#include +#include +} + +#include +#include +#include +#include +#include + +#include "atf-c/defs.h" + +#include "atf-c++/detail/env.hpp" +#include "atf-c++/detail/parser.hpp" +#include "atf-c++/detail/process.hpp" +#include "atf-c++/detail/sanity.hpp" +#include "atf-c++/detail/text.hpp" + +#include "config.hpp" +#include "fs.hpp" +#include "io.hpp" +#include "requirements.hpp" +#include "signals.hpp" +#include "test-program.hpp" +#include "timer.hpp" +#include "user.hpp" + +namespace impl = atf::atf_run; +namespace detail = atf::atf_run::detail; + +namespace { + +static void +check_stream(std::ostream& os) +{ + // If we receive a signal while writing to the stream, the bad bit gets set. + // Things seem to behave fine afterwards if we clear such error condition. + // However, I'm not sure if it's safe to query errno at this point. + if (os.bad()) { + if (errno == EINTR) + os.clear(); + else + throw std::runtime_error("Failed"); + } +} + +namespace atf_tp { + +static const atf::parser::token_type eof_type = 0; +static const atf::parser::token_type nl_type = 1; +static const atf::parser::token_type text_type = 2; +static const atf::parser::token_type colon_type = 3; +static const atf::parser::token_type dblquote_type = 4; + +class tokenizer : public atf::parser::tokenizer< std::istream > { +public: + tokenizer(std::istream& is, size_t curline) : + atf::parser::tokenizer< std::istream > + (is, true, eof_type, nl_type, text_type, curline) + { + add_delim(':', colon_type); + add_quote('"', dblquote_type); + } +}; + +} // namespace atf_tp + +class metadata_reader : public detail::atf_tp_reader { + impl::test_cases_map m_tcs; + + void got_tc(const std::string& ident, const atf::tests::vars_map& props) + { + if (m_tcs.find(ident) != m_tcs.end()) + throw(std::runtime_error("Duplicate test case " + ident + + " in test program")); + m_tcs[ident] = props; + + if (m_tcs[ident].find("has.cleanup") == m_tcs[ident].end()) + m_tcs[ident].insert(std::make_pair("has.cleanup", "false")); + + if (m_tcs[ident].find("timeout") == m_tcs[ident].end()) + m_tcs[ident].insert(std::make_pair("timeout", "300")); + } + +public: + metadata_reader(std::istream& is) : + detail::atf_tp_reader(is) + { + } + + const impl::test_cases_map& + get_tcs(void) + const + { + return m_tcs; + } +}; + +struct get_metadata_params { + const atf::fs::path& executable; + const atf::tests::vars_map& config; + + get_metadata_params(const atf::fs::path& p_executable, + const atf::tests::vars_map& p_config) : + executable(p_executable), + config(p_config) + { + } +}; + +struct test_case_params { + const atf::fs::path& executable; + const std::string& test_case_name; + const std::string& test_case_part; + const atf::tests::vars_map& metadata; + const atf::tests::vars_map& config; + const atf::fs::path& resfile; + const atf::fs::path& workdir; + + test_case_params(const atf::fs::path& p_executable, + const std::string& p_test_case_name, + const std::string& p_test_case_part, + const atf::tests::vars_map& p_metadata, + const atf::tests::vars_map& p_config, + const atf::fs::path& p_resfile, + const atf::fs::path& p_workdir) : + executable(p_executable), + test_case_name(p_test_case_name), + test_case_part(p_test_case_part), + metadata(p_metadata), + config(p_config), + resfile(p_resfile), + workdir(p_workdir) + { + } +}; + +static +std::string +generate_timestamp(void) +{ + struct timeval tv; + if (gettimeofday(&tv, NULL) == -1) + return "0.0"; + + char buf[32]; + const int len = snprintf(buf, sizeof(buf), "%ld.%ld", + static_cast< long >(tv.tv_sec), + static_cast< long >(tv.tv_usec)); + if (len >= static_cast< int >(sizeof(buf)) || len < 0) + return "0.0"; + else + return buf; +} + +static +void +append_to_vector(std::vector< std::string >& v1, + const std::vector< std::string >& v2) +{ + std::copy(v2.begin(), v2.end(), + std::back_insert_iterator< std::vector< std::string > >(v1)); +} + +static +char** +vector_to_argv(const std::vector< std::string >& v) +{ + char** argv = new char*[v.size() + 1]; + for (std::vector< std::string >::size_type i = 0; i < v.size(); i++) { + argv[i] = strdup(v[i].c_str()); + } + argv[v.size()] = NULL; + return argv; +} + +static +void +exec_or_exit(const atf::fs::path& executable, + const std::vector< std::string >& argv) +{ + // This leaks memory in case of a failure, but it is OK. Exiting will + // do the necessary cleanup. + char* const* native_argv = vector_to_argv(argv); + + ::execv(executable.c_str(), native_argv); + + const std::string message = "Failed to execute '" + executable.str() + + "': " + std::strerror(errno) + "\n"; + if (::write(STDERR_FILENO, message.c_str(), message.length()) == -1) + std::abort(); + std::exit(EXIT_FAILURE); +} + +static +std::vector< std::string > +config_to_args(const atf::tests::vars_map& config) +{ + std::vector< std::string > args; + + for (atf::tests::vars_map::const_iterator iter = config.begin(); + iter != config.end(); iter++) + args.push_back("-v" + (*iter).first + "=" + (*iter).second); + + return args; +} + +static +void +silence_stdin(void) +{ + ::close(STDIN_FILENO); + int fd = ::open("/dev/null", O_RDONLY); + if (fd == -1) + throw std::runtime_error("Could not open /dev/null"); + INV(fd == STDIN_FILENO); +} + +static +void +prepare_child(const atf::fs::path& workdir) +{ +#if !defined(__minix) + const int ret = ::setpgid(::getpid(), 0); + INV(ret != -1); +#endif /* defined(__minix) */ + + ::umask(S_IWGRP | S_IWOTH); + + for (int i = 1; i <= impl::last_signo; i++) + impl::reset(i); + + atf::env::set("HOME", workdir.str()); + atf::env::unset("LANG"); + atf::env::unset("LC_ALL"); + atf::env::unset("LC_COLLATE"); + atf::env::unset("LC_CTYPE"); + atf::env::unset("LC_MESSAGES"); + atf::env::unset("LC_MONETARY"); + atf::env::unset("LC_NUMERIC"); + atf::env::unset("LC_TIME"); + atf::env::set("TZ", "UTC"); + + atf::env::set("__RUNNING_INSIDE_ATF_RUN", "internal-yes-value"); + + impl::change_directory(workdir); + + silence_stdin(); +} + +static +void +get_metadata_child(void* raw_params) +{ + const get_metadata_params* params = + static_cast< const get_metadata_params* >(raw_params); + + std::vector< std::string > argv; + argv.push_back(params->executable.leaf_name()); + argv.push_back("-l"); + argv.push_back("-s" + params->executable.branch_path().str()); + append_to_vector(argv, config_to_args(params->config)); + + exec_or_exit(params->executable, argv); +} + +void +run_test_case_child(void* raw_params) +{ + const test_case_params* params = + static_cast< const test_case_params* >(raw_params); + + const std::pair< int, int > user = impl::get_required_user( + params->metadata, params->config); + if (user.first != -1 && user.second != -1) + impl::drop_privileges(user); + + // The input 'tp' parameter may be relative and become invalid once + // we change the current working directory. + const atf::fs::path absolute_executable = params->executable.to_absolute(); + + // Prepare the test program's arguments. We use dynamic memory and + // do not care to release it. We are going to die anyway very soon, + // either due to exec(2) or to exit(3). + std::vector< std::string > argv; + argv.push_back(absolute_executable.leaf_name()); + argv.push_back("-r" + params->resfile.str()); + argv.push_back("-s" + absolute_executable.branch_path().str()); + append_to_vector(argv, config_to_args(params->config)); + argv.push_back(params->test_case_name + ":" + params->test_case_part); + + prepare_child(params->workdir); + exec_or_exit(absolute_executable, argv); +} + +static void +tokenize_result(const std::string& line, std::string& out_state, + std::string& out_arg, std::string& out_reason) +{ + const std::string::size_type pos = line.find_first_of(":("); + if (pos == std::string::npos) { + out_state = line; + out_arg = ""; + out_reason = ""; + } else if (line[pos] == ':') { + out_state = line.substr(0, pos); + out_arg = ""; + out_reason = atf::text::trim(line.substr(pos + 1)); + } else if (line[pos] == '(') { + const std::string::size_type pos2 = line.find("):", pos); + if (pos2 == std::string::npos) + throw std::runtime_error("Invalid test case result '" + line + + "': unclosed optional argument"); + out_state = line.substr(0, pos); + out_arg = line.substr(pos + 1, pos2 - pos - 1); + out_reason = atf::text::trim(line.substr(pos2 + 2)); + } else + UNREACHABLE; +} + +static impl::test_case_result +handle_result(const std::string& state, const std::string& arg, + const std::string& reason) +{ + PRE(state == "passed"); + + if (!arg.empty() || !reason.empty()) + throw std::runtime_error("The test case result '" + state + "' cannot " + "be accompanied by a reason nor an expected value"); + + return impl::test_case_result(state, -1, reason); +} + +static impl::test_case_result +handle_result_with_reason(const std::string& state, const std::string& arg, + const std::string& reason) +{ + PRE(state == "expected_death" || state == "expected_failure" || + state == "expected_timeout" || state == "failed" || state == "skipped"); + + if (!arg.empty() || reason.empty()) + throw std::runtime_error("The test case result '" + state + "' must " + "be accompanied by a reason but not by an expected value"); + + return impl::test_case_result(state, -1, reason); +} + +static impl::test_case_result +handle_result_with_reason_and_arg(const std::string& state, + const std::string& arg, + const std::string& reason) +{ + PRE(state == "expected_exit" || state == "expected_signal"); + + if (reason.empty()) + throw std::runtime_error("The test case result '" + state + "' must " + "be accompanied by a reason"); + + int value; + if (arg.empty()) { + value = -1; + } else { + try { + value = atf::text::to_type< int >(arg); + } catch (const std::runtime_error&) { + throw std::runtime_error("The value '" + arg + "' passed to the '" + + state + "' state must be an integer"); + } + } + + return impl::test_case_result(state, value, reason); +} + +} // anonymous namespace + +detail::atf_tp_reader::atf_tp_reader(std::istream& is) : + m_is(is) +{ +} + +detail::atf_tp_reader::~atf_tp_reader(void) +{ +} + +void +detail::atf_tp_reader::got_tc( + const std::string& ident ATF_DEFS_ATTRIBUTE_UNUSED, + const std::map< std::string, std::string >& md ATF_DEFS_ATTRIBUTE_UNUSED) +{ +} + +void +detail::atf_tp_reader::got_eof(void) +{ +} + +void +detail::atf_tp_reader::validate_and_insert(const std::string& name, + const std::string& value, const size_t lineno, + std::map< std::string, std::string >& md) +{ + using atf::parser::parse_error; + + if (value.empty()) + throw parse_error(lineno, "The value for '" + name +"' cannot be " + "empty"); + + const std::string ident_regex = "^[_A-Za-z0-9]+$"; + const std::string integer_regex = "^[0-9]+$"; + + if (name == "descr") { + // Any non-empty value is valid. + } else if (name == "has.cleanup") { + try { + (void)atf::text::to_bool(value); + } catch (const std::runtime_error&) { + throw parse_error(lineno, "The has.cleanup property requires a" + " boolean value"); + } + } else if (name == "ident") { + if (!atf::text::match(value, ident_regex)) + throw parse_error(lineno, "The identifier must match " + + ident_regex + "; was '" + value + "'"); + } else if (name == "require.arch") { + } else if (name == "require.config") { + } else if (name == "require.files") { + } else if (name == "require.machine") { + } else if (name == "require.memory") { + try { + (void)atf::text::to_bytes(value); + } catch (const std::runtime_error&) { + throw parse_error(lineno, "The require.memory property requires an " + "integer value representing an amount of bytes"); + } + } else if (name == "require.progs") { + } else if (name == "require.user") { + } else if (name == "timeout") { + if (!atf::text::match(value, integer_regex)) + throw parse_error(lineno, "The timeout property requires an integer" + " value"); + } else if (name == "use.fs") { + // Deprecated; ignore it. + } else if (name.size() > 2 && name[0] == 'X' && name[1] == '-') { + // Any non-empty value is valid. + } else { + throw parse_error(lineno, "Unknown property '" + name + "'"); + } + + md.insert(std::make_pair(name, value)); +} + +void +detail::atf_tp_reader::read(void) +{ + using atf::parser::parse_error; + using namespace atf_tp; + + std::pair< size_t, atf::parser::headers_map > hml = + atf::parser::read_headers(m_is, 1); + atf::parser::validate_content_type(hml.second, + "application/X-atf-tp", 1); + + tokenizer tkz(m_is, hml.first); + atf::parser::parser< tokenizer > p(tkz); + + try { + atf::parser::token t = p.expect(text_type, "property name"); + if (t.text() != "ident") + throw parse_error(t.lineno(), "First property of a test case " + "must be 'ident'"); + + std::map< std::string, std::string > props; + do { + const std::string name = t.text(); + t = p.expect(colon_type, "`:'"); + const std::string value = atf::text::trim(p.rest_of_line()); + t = p.expect(nl_type, "new line"); + validate_and_insert(name, value, t.lineno(), props); + + t = p.expect(eof_type, nl_type, text_type, "property name, new " + "line or eof"); + if (t.type() == nl_type || t.type() == eof_type) { + const std::map< std::string, std::string >::const_iterator + iter = props.find("ident"); + if (iter == props.end()) + throw parse_error(t.lineno(), "Test case definition did " + "not define an 'ident' property"); + ATF_PARSER_CALLBACK(p, got_tc((*iter).second, props)); + props.clear(); + + if (t.type() == nl_type) { + t = p.expect(text_type, "property name"); + if (t.text() != "ident") + throw parse_error(t.lineno(), "First property of a " + "test case must be 'ident'"); + } + } + } while (t.type() != eof_type); + ATF_PARSER_CALLBACK(p, got_eof()); + } catch (const parse_error& pe) { + p.add_error(pe); + p.reset(nl_type); + } +} + +impl::test_case_result +detail::parse_test_case_result(const std::string& line) +{ + std::string state, arg, reason; + tokenize_result(line, state, arg, reason); + + if (state == "expected_death") + return handle_result_with_reason(state, arg, reason); + else if (state.compare(0, 13, "expected_exit") == 0) + return handle_result_with_reason_and_arg(state, arg, reason); + else if (state.compare(0, 16, "expected_failure") == 0) + return handle_result_with_reason(state, arg, reason); + else if (state.compare(0, 15, "expected_signal") == 0) + return handle_result_with_reason_and_arg(state, arg, reason); + else if (state.compare(0, 16, "expected_timeout") == 0) + return handle_result_with_reason(state, arg, reason); + else if (state == "failed") + return handle_result_with_reason(state, arg, reason); + else if (state == "passed") + return handle_result(state, arg, reason); + else if (state == "skipped") + return handle_result_with_reason(state, arg, reason); + else + throw std::runtime_error("Unknown test case result type in: " + line); +} + +impl::atf_tps_writer::atf_tps_writer(std::ostream& os) : + m_os(os) +{ + atf::parser::headers_map hm; + atf::parser::attrs_map ct_attrs; + ct_attrs["version"] = "3"; + hm["Content-Type"] = + atf::parser::header_entry("Content-Type", "application/X-atf-tps", + ct_attrs); + atf::parser::write_headers(hm, m_os); +} + +void +impl::atf_tps_writer::info(const std::string& what, const std::string& val) +{ + m_os << "info: " << what << ", " << val << "\n"; + m_os.flush(); +} + +void +impl::atf_tps_writer::ntps(size_t p_ntps) +{ + m_os << "tps-count: " << p_ntps << "\n"; + m_os.flush(); +} + +void +impl::atf_tps_writer::start_tp(const std::string& tp, size_t ntcs) +{ + m_tpname = tp; + m_os << "tp-start: " << generate_timestamp() << ", " << tp << ", " + << ntcs << "\n"; + m_os.flush(); +} + +void +impl::atf_tps_writer::end_tp(const std::string& reason) +{ + PRE(reason.find('\n') == std::string::npos); + if (reason.empty()) + m_os << "tp-end: " << generate_timestamp() << ", " << m_tpname << "\n"; + else + m_os << "tp-end: " << generate_timestamp() << ", " << m_tpname + << ", " << reason << "\n"; + m_os.flush(); +} + +void +impl::atf_tps_writer::start_tc(const std::string& tcname) +{ + m_tcname = tcname; + m_os << "tc-start: " << generate_timestamp() << ", " << tcname << "\n"; + m_os.flush(); +} + +void +impl::atf_tps_writer::stdout_tc(const std::string& line) +{ + m_os << "tc-so:" << line << "\n"; + check_stream(m_os); + m_os.flush(); + check_stream(m_os); +} + +void +impl::atf_tps_writer::stderr_tc(const std::string& line) +{ + m_os << "tc-se:" << line << "\n"; + check_stream(m_os); + m_os.flush(); + check_stream(m_os); +} + +void +impl::atf_tps_writer::end_tc(const std::string& state, + const std::string& reason) +{ + std::string str = ", " + m_tcname + ", " + state; + if (!reason.empty()) + str += ", " + reason; + m_os << "tc-end: " << generate_timestamp() << str << "\n"; + m_os.flush(); +} + +impl::metadata +impl::get_metadata(const atf::fs::path& executable, + const atf::tests::vars_map& config) +{ + get_metadata_params params(executable, config); + atf::process::child child = + atf::process::fork(get_metadata_child, + atf::process::stream_capture(), + atf::process::stream_inherit(), + static_cast< void * >(¶ms)); + + impl::pistream outin(child.stdout_fd()); + + metadata_reader parser(outin); + parser.read(); + + const atf::process::status status = child.wait(); + if (!status.exited() || status.exitstatus() != EXIT_SUCCESS) + throw atf::parser::format_error("Test program returned failure " + "exit status for test case list"); + + return metadata(parser.get_tcs()); +} + +impl::test_case_result +impl::read_test_case_result(const atf::fs::path& results_path) +{ + std::ifstream results_file(results_path.c_str()); + if (!results_file) + throw std::runtime_error("Failed to open " + results_path.str()); + + std::string line, extra_line; + std::getline(results_file, line); + if (!results_file.good()) + throw std::runtime_error("Results file is empty"); + + while (std::getline(results_file, extra_line).good()) + line += "<>" + extra_line; + + results_file.close(); + + return detail::parse_test_case_result(line); +} + +namespace { + +static volatile bool terminate_poll; + +static void +sigchld_handler(const int signo ATF_DEFS_ATTRIBUTE_UNUSED) +{ + terminate_poll = true; +} + +class child_muxer : public impl::muxer { + impl::atf_tps_writer& m_writer; + + void + line_callback(const size_t index, const std::string& line) + { + switch (index) { + case 0: m_writer.stdout_tc(line); break; + case 1: m_writer.stderr_tc(line); break; + default: UNREACHABLE; + } + } + +public: + child_muxer(const int* fds, const size_t nfds, + impl::atf_tps_writer& writer) : + muxer(fds, nfds), + m_writer(writer) + { + } +}; + +} // anonymous namespace + +std::pair< std::string, atf::process::status > +impl::run_test_case(const atf::fs::path& executable, + const std::string& test_case_name, + const std::string& test_case_part, + const atf::tests::vars_map& metadata, + const atf::tests::vars_map& config, + const atf::fs::path& resfile, + const atf::fs::path& workdir, + atf_tps_writer& writer) +{ + // TODO: Capture termination signals and deliver them to the subprocess + // instead. Or maybe do something else; think about it. + + test_case_params params(executable, test_case_name, test_case_part, + metadata, config, resfile, workdir); + atf::process::child child = + atf::process::fork(run_test_case_child, + atf::process::stream_capture(), + atf::process::stream_capture(), + static_cast< void * >(¶ms)); + + terminate_poll = false; + + const atf::tests::vars_map::const_iterator iter = metadata.find("timeout"); + INV(iter != metadata.end()); + const unsigned int timeout = + atf::text::to_type< unsigned int >((*iter).second); + const pid_t child_pid = child.pid(); + + // Get the input stream of stdout and stderr. + impl::file_handle outfh = child.stdout_fd(); + impl::file_handle errfh = child.stderr_fd(); + + bool timed_out = false; + + // Process the test case's output and multiplex it into our output + // stream as we read it. + int fds[2] = {outfh.get(), errfh.get()}; + child_muxer mux(fds, 2, writer); + try { + child_timer timeout_timer(timeout, child_pid, terminate_poll); + signal_programmer sigchld(SIGCHLD, sigchld_handler); + mux.mux(terminate_poll); + timed_out = timeout_timer.fired(); + } catch (...) { + UNREACHABLE; + } + + ::killpg(child_pid, SIGKILL); + mux.flush(); + atf::process::status status = child.wait(); + + std::string reason; + + if (timed_out) { + // Don't assume the child process has been signaled due to the timeout + // expiration as older versions did. The child process may have exited + // but we may have timed out due to a subchild process getting stuck. + reason = "Test case timed out after " + atf::text::to_string(timeout) + + " " + (timeout == 1 ? "second" : "seconds"); + } + + return std::make_pair(reason, status); +} diff --git a/external/bsd/atf/dist/atf-run/test-program.hpp b/external/bsd/atf/dist/atf-run/test-program.hpp new file mode 100644 index 000000000..daba3ce01 --- /dev/null +++ b/external/bsd/atf/dist/atf-run/test-program.hpp @@ -0,0 +1,150 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2010 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#include + +#include "atf-c++/tests.hpp" + +#include "atf-c++/detail/fs.hpp" +#include "atf-c++/detail/process.hpp" + +namespace atf { +namespace atf_run { + +struct test_case_result { + std::string m_state; + int m_value; + std::string m_reason; + +public: + test_case_result(void) : + m_state("UNINITIALIZED"), + m_value(-1), + m_reason("") + { + } + + test_case_result(const std::string& p_state, const int p_value, + const std::string& p_reason) : + m_state(p_state), + m_value(p_value), + m_reason(p_reason) + { + } + + const std::string& + state(void) const + { + return m_state; + } + + int + value(void) const + { + return m_value; + } + + const std::string& + reason(void) const + { + return m_reason; + } +}; + +namespace detail { + +class atf_tp_reader { + std::istream& m_is; + + void validate_and_insert(const std::string&, const std::string&, + const size_t, + std::map< std::string, std::string >&); + +protected: + virtual void got_tc(const std::string&, + const std::map< std::string, std::string >&); + virtual void got_eof(void); + +public: + atf_tp_reader(std::istream&); + virtual ~atf_tp_reader(void); + + void read(void); +}; + +test_case_result parse_test_case_result(const std::string&); + +} // namespace detail + +class atf_tps_writer { + std::ostream& m_os; + + std::string m_tpname, m_tcname; + +public: + atf_tps_writer(std::ostream&); + + void info(const std::string&, const std::string&); + void ntps(size_t); + + void start_tp(const std::string&, size_t); + void end_tp(const std::string&); + + void start_tc(const std::string&); + void stdout_tc(const std::string&); + void stderr_tc(const std::string&); + void end_tc(const std::string&, const std::string&); +}; + +typedef std::map< std::string, atf::tests::vars_map > test_cases_map; + +struct metadata { + test_cases_map test_cases; + + metadata(void) + { + } + + metadata(const test_cases_map& p_test_cases) : + test_cases(p_test_cases) + { + } +}; + +class atf_tps_writer; + +metadata get_metadata(const atf::fs::path&, const atf::tests::vars_map&); +test_case_result read_test_case_result(const atf::fs::path&); +std::pair< std::string, atf::process::status > run_test_case( + const atf::fs::path&, const std::string&, const std::string&, + const atf::tests::vars_map&, const atf::tests::vars_map&, + const atf::fs::path&, const atf::fs::path&, atf_tps_writer&); + +} // namespace atf_run +} // namespace atf diff --git a/external/bsd/atf/dist/atf-run/test_program_test.cpp b/external/bsd/atf/dist/atf-run/test_program_test.cpp new file mode 100644 index 000000000..444dc3e4d --- /dev/null +++ b/external/bsd/atf/dist/atf-run/test_program_test.cpp @@ -0,0 +1,1020 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2010 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#include +#include + +#include "atf-c++/macros.hpp" + +#include "atf-c++/detail/parser.hpp" +#include "atf-c++/detail/test_helpers.hpp" +#include "atf-c++/detail/text.hpp" + +#include "test-program.hpp" + +namespace impl = atf::atf_run; +namespace detail = atf::atf_run::detail; + +using atf::tests::vars_map; + +// ------------------------------------------------------------------------- +// Auxiliary functions. +// ------------------------------------------------------------------------- + +static +atf::fs::path +get_helper(const atf::tests::tc& tc, const char* name) +{ + return atf::fs::path(tc.get_config_var("srcdir")) / name; +} + +static +void +check_property(const vars_map& props, const char* name, const char* value) +{ + const vars_map::const_iterator iter = props.find(name); + ATF_REQUIRE(iter != props.end()); + ATF_REQUIRE_EQ(value, (*iter).second); +} + +static void +check_result(const char* exp_state, const int exp_value, const char* exp_reason, + const impl::test_case_result& tcr) +{ + ATF_REQUIRE_EQ(exp_state, tcr.state()); + ATF_REQUIRE_EQ(exp_value, tcr.value()); + ATF_REQUIRE_EQ(exp_reason, tcr.reason()); +} + +static +void +write_test_case_result(const char *results_path, const std::string& contents) +{ + std::ofstream results_file(results_path); + ATF_REQUIRE(results_file); + + results_file << contents; +} + +static +void +print_indented(const std::string& str) +{ + std::vector< std::string > ws = atf::text::split(str, "\n"); + for (std::vector< std::string >::const_iterator iter = ws.begin(); + iter != ws.end(); iter++) + std::cout << ">>" << *iter << "<<\n"; +} + +// XXX Should this string handling and verbosity level be part of the +// ATF_REQUIRE_EQ macro? It may be hard to predict sometimes that a +// string can have newlines in it, and so the error message generated +// at the moment will be bogus if there are some. +static +void +check_match(const atf::tests::tc& tc, const std::string& str, + const std::string& exp) +{ + if (!atf::text::match(str, exp)) { + std::cout << "String match check failed.\n" + << "Adding >> and << to delimit the string boundaries " + "below.\n"; + std::cout << "GOT:\n"; + print_indented(str); + std::cout << "EXPECTED:\n"; + print_indented(exp); + tc.fail("Constructed string differs from the expected one"); + } +} + +// ------------------------------------------------------------------------- +// Tests for the "tp" reader. +// ------------------------------------------------------------------------- + +class tp_reader : protected detail::atf_tp_reader { + void + got_tc(const std::string& ident, + const std::map< std::string, std::string >& md) + { + std::string call = "got_tc(" + ident + ", {"; + for (std::map< std::string, std::string >::const_iterator iter = + md.begin(); iter != md.end(); iter++) { + if (iter != md.begin()) + call += ", "; + call += (*iter).first + '=' + (*iter).second; + } + call += "})"; + m_calls.push_back(call); + } + + void + got_eof(void) + { + m_calls.push_back("got_eof()"); + } + +public: + tp_reader(std::istream& is) : + detail::atf_tp_reader(is) + { + } + + void + read(void) + { + atf_tp_reader::read(); + } + + std::vector< std::string > m_calls; +}; + +ATF_TEST_CASE_WITHOUT_HEAD(tp_1); +ATF_TEST_CASE_BODY(tp_1) +{ + const char* input = + "Content-Type: application/X-atf-tp; version=\"1\"\n" + "\n" + "ident: test_case_1\n" + "\n" + "ident: test_case_2\n" + "\n" + "ident: test_case_3\n" + ; + + const char* exp_calls[] = { + "got_tc(test_case_1, {ident=test_case_1})", + "got_tc(test_case_2, {ident=test_case_2})", + "got_tc(test_case_3, {ident=test_case_3})", + "got_eof()", + NULL + }; + + const char* exp_errors[] = { + NULL + }; + + do_parser_test< tp_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(tp_2); +ATF_TEST_CASE_BODY(tp_2) +{ + const char* input = + "Content-Type: application/X-atf-tp; version=\"1\"\n" + "\n" + "ident: test_case_1\n" + "descr: This is the description\n" + "timeout: 300\n" + "\n" + "ident: test_case_2\n" + "\n" + "ident: test_case_3\n" + "X-prop1: A custom property\n" + "descr: Third test case\n" + ; + + // NO_CHECK_STYLE_BEGIN + const char* exp_calls[] = { + "got_tc(test_case_1, {descr=This is the description, ident=test_case_1, timeout=300})", + "got_tc(test_case_2, {ident=test_case_2})", + "got_tc(test_case_3, {X-prop1=A custom property, descr=Third test case, ident=test_case_3})", + "got_eof()", + NULL + }; + // NO_CHECK_STYLE_END + + const char* exp_errors[] = { + NULL + }; + + do_parser_test< tp_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(tp_3); +ATF_TEST_CASE_BODY(tp_3) +{ + const char* input = + "Content-Type: application/X-atf-tp; version=\"1\"\n" + "\n" + "ident: single_test\n" + "descr: Some description\n" + "timeout: 300\n" + "require.arch: thearch\n" + "require.config: foo-bar\n" + "require.files: /a/1 /b/2\n" + "require.machine: themachine\n" + "require.progs: /bin/cp mv\n" + "require.user: root\n" + ; + + // NO_CHECK_STYLE_BEGIN + const char* exp_calls[] = { + "got_tc(single_test, {descr=Some description, ident=single_test, require.arch=thearch, require.config=foo-bar, require.files=/a/1 /b/2, require.machine=themachine, require.progs=/bin/cp mv, require.user=root, timeout=300})", + "got_eof()", + NULL + }; + // NO_CHECK_STYLE_END + + const char* exp_errors[] = { + NULL + }; + + do_parser_test< tp_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(tp_4); +ATF_TEST_CASE_BODY(tp_4) +{ + const char* input = + "Content-Type: application/X-atf-tp; version=\"1\"\n" + "\n" + "ident: single_test \n" + "descr: Some description \n" + ; + + const char* exp_calls[] = { + "got_tc(single_test, {descr=Some description, ident=single_test})", + "got_eof()", + NULL + }; + + const char* exp_errors[] = { + NULL + }; + + do_parser_test< tp_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(tp_50); +ATF_TEST_CASE_BODY(tp_50) +{ + const char* input = + "Content-Type: application/X-atf-tp; version=\"1\"\n" + "\n" + ; + + const char* exp_calls[] = { + NULL + }; + + const char* exp_errors[] = { + "3: Unexpected token `<>'; expected property name", + NULL + }; + + do_parser_test< tp_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(tp_51); +ATF_TEST_CASE_BODY(tp_51) +{ + const char* input = + "Content-Type: application/X-atf-tp; version=\"1\"\n" + "\n" + "\n" + "\n" + "\n" + ; + + const char* exp_calls[] = { + NULL + }; + + const char* exp_errors[] = { + "3: Unexpected token `<>'; expected property name", + NULL + }; + + do_parser_test< tp_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(tp_52); +ATF_TEST_CASE_BODY(tp_52) +{ + const char* input = + "Content-Type: application/X-atf-tp; version=\"1\"\n" + "\n" + "ident: test1\n" + "ident: test2\n" + ; + + const char* exp_calls[] = { + "got_tc(test1, {ident=test1})", + "got_eof()", + NULL + }; + + const char* exp_errors[] = { + NULL + }; + + do_parser_test< tp_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(tp_53); +ATF_TEST_CASE_BODY(tp_53) +{ + const char* input = + "Content-Type: application/X-atf-tp; version=\"1\"\n" + "\n" + "descr: Out of order\n" + "ident: test1\n" + ; + + const char* exp_calls[] = { + NULL + }; + + const char* exp_errors[] = { + "3: First property of a test case must be 'ident'", + NULL + }; + + do_parser_test< tp_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(tp_54); +ATF_TEST_CASE_BODY(tp_54) +{ + const char* input = + "Content-Type: application/X-atf-tp; version=\"1\"\n" + "\n" + "ident:\n" + ; + + const char* exp_calls[] = { + NULL + }; + + const char* exp_errors[] = { + "3: The value for 'ident' cannot be empty", + NULL + }; + + do_parser_test< tp_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(tp_55); +ATF_TEST_CASE_BODY(tp_55) +{ + const char* input = + "Content-Type: application/X-atf-tp; version=\"1\"\n" + "\n" + "ident: +*,\n" + ; + + const char* exp_calls[] = { + NULL + }; + + const char* exp_errors[] = { + "3: The identifier must match ^[_A-Za-z0-9]+$; was '+*,'", + NULL + }; + + do_parser_test< tp_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(tp_56); +ATF_TEST_CASE_BODY(tp_56) +{ + const char* input = + "Content-Type: application/X-atf-tp; version=\"1\"\n" + "\n" + "ident: test\n" + "timeout: hello\n" + ; + + const char* exp_calls[] = { + NULL + }; + + const char* exp_errors[] = { + "4: The timeout property requires an integer value", + NULL + }; + + do_parser_test< tp_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(tp_57); +ATF_TEST_CASE_BODY(tp_57) +{ + const char* input = + "Content-Type: application/X-atf-tp; version=\"1\"\n" + "\n" + "ident: test\n" + "unknown: property\n" + ; + + const char* exp_calls[] = { + NULL + }; + + const char* exp_errors[] = { + "4: Unknown property 'unknown'", + NULL + }; + + do_parser_test< tp_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(tp_58); +ATF_TEST_CASE_BODY(tp_58) +{ + const char* input = + "Content-Type: application/X-atf-tp; version=\"1\"\n" + "\n" + "ident: test\n" + "X-foo:\n" + ; + + const char* exp_calls[] = { + NULL + }; + + const char* exp_errors[] = { + "4: The value for 'X-foo' cannot be empty", + NULL + }; + + do_parser_test< tp_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(tp_59); +ATF_TEST_CASE_BODY(tp_59) +{ + const char* input = + "Content-Type: application/X-atf-tp; version=\"1\"\n" + "\n" + "\n" + "ident: test\n" + "timeout: 300\n" + ; + + const char* exp_calls[] = { + NULL + }; + + const char* exp_errors[] = { + "3: Unexpected token `<>'; expected property name", + NULL + }; + + do_parser_test< tp_reader >(input, exp_calls, exp_errors); +} + +ATF_TEST_CASE_WITHOUT_HEAD(tp_60); +ATF_TEST_CASE_BODY(tp_60) +{ + const char* input = + "Content-Type: application/X-atf-tp; version=\"1\"\n" + "\n" + "ident: test\n" + "require.memory: 12345D\n" + ; + + const char* exp_calls[] = { + NULL + }; + + const char* exp_errors[] = { + "4: The require.memory property requires an integer value representing" + " an amount of bytes", + NULL + }; + + do_parser_test< tp_reader >(input, exp_calls, exp_errors); +} + +// ------------------------------------------------------------------------- +// Tests for the "tps" writer. +// ------------------------------------------------------------------------- + +ATF_TEST_CASE(atf_tps_writer); +ATF_TEST_CASE_HEAD(atf_tps_writer) +{ + set_md_var("descr", "Verifies the application/X-atf-tps writer"); +} +ATF_TEST_CASE_BODY(atf_tps_writer) +{ + std::ostringstream expss; + std::ostringstream ss; + const char *ts_regex = "[0-9]+\\.[0-9]{1,6}, "; + +#define RESET \ + expss.str(""); \ + ss.str("") + +#define CHECK \ + check_match(*this, ss.str(), expss.str()) + + { + RESET; + + impl::atf_tps_writer w(ss); + expss << "Content-Type: application/X-atf-tps; version=\"3\"\n\n"; + CHECK; + } + + { + RESET; + + impl::atf_tps_writer w(ss); + expss << "Content-Type: application/X-atf-tps; version=\"3\"\n\n"; + CHECK; + + w.info("foo", "bar"); + expss << "info: foo, bar\n"; + CHECK; + + w.info("baz", "second info"); + expss << "info: baz, second info\n"; + CHECK; + } + + { + RESET; + + impl::atf_tps_writer w(ss); + expss << "Content-Type: application/X-atf-tps; version=\"3\"\n\n"; + CHECK; + + w.ntps(0); + expss << "tps-count: 0\n"; + CHECK; + } + + { + RESET; + + impl::atf_tps_writer w(ss); + expss << "Content-Type: application/X-atf-tps; version=\"3\"\n\n"; + CHECK; + + w.ntps(123); + expss << "tps-count: 123\n"; + CHECK; + } + + { + RESET; + + impl::atf_tps_writer w(ss); + expss << "Content-Type: application/X-atf-tps; version=\"3\"\n\n"; + CHECK; + + w.ntps(2); + expss << "tps-count: 2\n"; + CHECK; + + w.start_tp("foo", 0); + expss << "tp-start: " << ts_regex << "foo, 0\n"; + CHECK; + + w.end_tp(""); + expss << "tp-end: " << ts_regex << "foo\n"; + CHECK; + + w.start_tp("bar", 0); + expss << "tp-start: " << ts_regex << "bar, 0\n"; + CHECK; + + w.end_tp("failed program"); + expss << "tp-end: " << ts_regex << "bar, failed program\n"; + CHECK; + } + + { + RESET; + + impl::atf_tps_writer w(ss); + expss << "Content-Type: application/X-atf-tps; version=\"3\"\n\n"; + CHECK; + + w.ntps(1); + expss << "tps-count: 1\n"; + CHECK; + + w.start_tp("foo", 1); + expss << "tp-start: " << ts_regex << "foo, 1\n"; + CHECK; + + w.start_tc("brokentc"); + expss << "tc-start: " << ts_regex << "brokentc\n"; + CHECK; + + w.end_tp("aborted"); + expss << "tp-end: " << ts_regex << "foo, aborted\n"; + CHECK; + } + + { + RESET; + + impl::atf_tps_writer w(ss); + expss << "Content-Type: application/X-atf-tps; version=\"3\"\n\n"; + CHECK; + + w.ntps(1); + expss << "tps-count: 1\n"; + CHECK; + + w.start_tp("thetp", 3); + expss << "tp-start: " << ts_regex << "thetp, 3\n"; + CHECK; + + w.start_tc("passtc"); + expss << "tc-start: " << ts_regex << "passtc\n"; + CHECK; + + w.end_tc("passed", ""); + expss << "tc-end: " << ts_regex << "passtc, passed\n"; + CHECK; + + w.start_tc("failtc"); + expss << "tc-start: " << ts_regex << "failtc\n"; + CHECK; + + w.end_tc("failed", "The reason"); + expss << "tc-end: " << ts_regex << "failtc, failed, The reason\n"; + CHECK; + + w.start_tc("skiptc"); + expss << "tc-start: " << ts_regex << "skiptc\n"; + CHECK; + + w.end_tc("skipped", "The reason"); + expss << "tc-end: " << ts_regex << "skiptc, skipped, The reason\n"; + CHECK; + + w.end_tp(""); + expss << "tp-end: " << ts_regex << "thetp\n"; + CHECK; + } + + { + RESET; + + impl::atf_tps_writer w(ss); + expss << "Content-Type: application/X-atf-tps; version=\"3\"\n\n"; + CHECK; + + w.ntps(1); + expss << "tps-count: 1\n"; + CHECK; + + w.start_tp("thetp", 1); + expss << "tp-start: " << ts_regex << "thetp, 1\n"; + CHECK; + + w.start_tc("thetc"); + expss << "tc-start: " << ts_regex << "thetc\n"; + CHECK; + + w.stdout_tc("a line"); + expss << "tc-so:a line\n"; + CHECK; + + w.stdout_tc("another line"); + expss << "tc-so:another line\n"; + CHECK; + + w.stderr_tc("an error message"); + expss << "tc-se:an error message\n"; + CHECK; + + w.end_tc("passed", ""); + expss << "tc-end: " << ts_regex << "thetc, passed\n"; + CHECK; + + w.end_tp(""); + expss << "tp-end: " << ts_regex << "thetp\n"; + CHECK; + } + + { + RESET; + + impl::atf_tps_writer w(ss); + expss << "Content-Type: application/X-atf-tps; version=\"3\"\n\n"; + CHECK; + + w.ntps(1); + expss << "tps-count: 1\n"; + CHECK; + + w.start_tp("thetp", 0); + expss << "tp-start: " << ts_regex << "thetp, 0\n"; + CHECK; + + w.end_tp(""); + expss << "tp-end: " << ts_regex << "thetp\n"; + CHECK; + + w.info("foo", "bar"); + expss << "info: foo, bar\n"; + CHECK; + + w.info("baz", "second value"); + expss << "info: baz, second value\n"; + CHECK; + } + +#undef CHECK +#undef RESET +} + +// ------------------------------------------------------------------------- +// Tests for the free functions. +// ------------------------------------------------------------------------- + +ATF_TEST_CASE(get_metadata_bad); +ATF_TEST_CASE_HEAD(get_metadata_bad) {} +ATF_TEST_CASE_BODY(get_metadata_bad) { + const atf::fs::path executable = get_helper(*this, "bad_metadata_helper"); + ATF_REQUIRE_THROW(atf::parser::parse_errors, + impl::get_metadata(executable, vars_map())); +} + +ATF_TEST_CASE(get_metadata_zero_tcs); +ATF_TEST_CASE_HEAD(get_metadata_zero_tcs) {} +ATF_TEST_CASE_BODY(get_metadata_zero_tcs) { + const atf::fs::path executable = get_helper(*this, "zero_tcs_helper"); + ATF_REQUIRE_THROW(atf::parser::parse_errors, + impl::get_metadata(executable, vars_map())); +} + +ATF_TEST_CASE(get_metadata_several_tcs); +ATF_TEST_CASE_HEAD(get_metadata_several_tcs) {} +ATF_TEST_CASE_BODY(get_metadata_several_tcs) { + const atf::fs::path executable = get_helper(*this, "several_tcs_helper"); + const impl::metadata md = impl::get_metadata(executable, vars_map()); + ATF_REQUIRE_EQ(3, md.test_cases.size()); + + { + const impl::test_cases_map::const_iterator iter = + md.test_cases.find("first"); + ATF_REQUIRE(iter != md.test_cases.end()); + + ATF_REQUIRE_EQ(4, (*iter).second.size()); + check_property((*iter).second, "descr", "Description 1"); + check_property((*iter).second, "has.cleanup", "false"); + check_property((*iter).second, "ident", "first"); + check_property((*iter).second, "timeout", "300"); + } + + { + const impl::test_cases_map::const_iterator iter = + md.test_cases.find("second"); + ATF_REQUIRE(iter != md.test_cases.end()); + + ATF_REQUIRE_EQ(5, (*iter).second.size()); + check_property((*iter).second, "descr", "Description 2"); + check_property((*iter).second, "has.cleanup", "true"); + check_property((*iter).second, "ident", "second"); + check_property((*iter).second, "timeout", "500"); + check_property((*iter).second, "X-property", "Custom property"); + } + + { + const impl::test_cases_map::const_iterator iter = + md.test_cases.find("third"); + ATF_REQUIRE(iter != md.test_cases.end()); + + ATF_REQUIRE_EQ(3, (*iter).second.size()); + check_property((*iter).second, "has.cleanup", "false"); + check_property((*iter).second, "ident", "third"); + check_property((*iter).second, "timeout", "300"); + } +} + +ATF_TEST_CASE_WITHOUT_HEAD(parse_test_case_result_expected_death); +ATF_TEST_CASE_BODY(parse_test_case_result_expected_death) { + check_result("expected_death", -1, "foo bar", + detail::parse_test_case_result("expected_death: foo bar")); + + ATF_REQUIRE_THROW(std::runtime_error, + detail::parse_test_case_result("expected_death")); + ATF_REQUIRE_THROW(std::runtime_error, + detail::parse_test_case_result("expected_death(3): foo")); +} + +ATF_TEST_CASE_WITHOUT_HEAD(parse_test_case_result_expected_exit); +ATF_TEST_CASE_BODY(parse_test_case_result_expected_exit) { + check_result("expected_exit", -1, "foo bar", + detail::parse_test_case_result("expected_exit: foo bar")); + check_result("expected_exit", -1, "foo bar", + detail::parse_test_case_result("expected_exit(): foo bar")); + check_result("expected_exit", 5, "foo bar", + detail::parse_test_case_result("expected_exit(5): foo bar")); + + ATF_REQUIRE_THROW(std::runtime_error, + detail::parse_test_case_result("expected_exit")); + ATF_REQUIRE_THROW(std::runtime_error, + detail::parse_test_case_result("expected_exit(")); +} + +ATF_TEST_CASE_WITHOUT_HEAD(parse_test_case_result_expected_failure); +ATF_TEST_CASE_BODY(parse_test_case_result_expected_failure) { + check_result("expected_failure", -1, "foo bar", + detail::parse_test_case_result("expected_failure: foo bar")); + + ATF_REQUIRE_THROW(std::runtime_error, + detail::parse_test_case_result("expected_failure")); + ATF_REQUIRE_THROW(std::runtime_error, + detail::parse_test_case_result("expected_failure(3): foo")); +} + +ATF_TEST_CASE_WITHOUT_HEAD(parse_test_case_result_expected_signal); +ATF_TEST_CASE_BODY(parse_test_case_result_expected_signal) { + check_result("expected_signal", -1, "foo bar", + detail::parse_test_case_result("expected_signal: foo bar")); + check_result("expected_signal", -1, "foo bar", + detail::parse_test_case_result("expected_signal(): foo bar")); + check_result("expected_signal", 5, "foo bar", + detail::parse_test_case_result("expected_signal(5): foo bar")); + + ATF_REQUIRE_THROW(std::runtime_error, + detail::parse_test_case_result("expected_signal")); + ATF_REQUIRE_THROW(std::runtime_error, + detail::parse_test_case_result("expected_signal(")); +} + +ATF_TEST_CASE_WITHOUT_HEAD(parse_test_case_result_expected_timeout); +ATF_TEST_CASE_BODY(parse_test_case_result_expected_timeout) { + check_result("expected_timeout", -1, "foo bar", + detail::parse_test_case_result("expected_timeout: foo bar")); + + ATF_REQUIRE_THROW(std::runtime_error, + detail::parse_test_case_result("expected_timeout")); + ATF_REQUIRE_THROW(std::runtime_error, + detail::parse_test_case_result("expected_timeout(3): foo")); +} + +ATF_TEST_CASE_WITHOUT_HEAD(parse_test_case_result_failed); +ATF_TEST_CASE_BODY(parse_test_case_result_failed) { + check_result("failed", -1, "foo bar", + detail::parse_test_case_result("failed: foo bar")); + + ATF_REQUIRE_THROW(std::runtime_error, + detail::parse_test_case_result("failed")); + ATF_REQUIRE_THROW(std::runtime_error, + detail::parse_test_case_result("failed(3): foo")); +} + +ATF_TEST_CASE_WITHOUT_HEAD(parse_test_case_result_passed); +ATF_TEST_CASE_BODY(parse_test_case_result_passed) { + check_result("passed", -1, "", + detail::parse_test_case_result("passed")); + + ATF_REQUIRE_THROW(std::runtime_error, + detail::parse_test_case_result("passed: foo")); + ATF_REQUIRE_THROW(std::runtime_error, + detail::parse_test_case_result("passed(3): foo")); +} + +ATF_TEST_CASE_WITHOUT_HEAD(parse_test_case_result_skipped); +ATF_TEST_CASE_BODY(parse_test_case_result_skipped) { + check_result("skipped", -1, "foo bar", + detail::parse_test_case_result("skipped: foo bar")); + + ATF_REQUIRE_THROW(std::runtime_error, + detail::parse_test_case_result("skipped")); + ATF_REQUIRE_THROW(std::runtime_error, + detail::parse_test_case_result("skipped(3): foo")); +} + +ATF_TEST_CASE_WITHOUT_HEAD(parse_test_case_result_unknown); +ATF_TEST_CASE_BODY(parse_test_case_result_unknown) { + ATF_REQUIRE_THROW(std::runtime_error, + detail::parse_test_case_result("foo")); + ATF_REQUIRE_THROW(std::runtime_error, + detail::parse_test_case_result("bar: foo")); + ATF_REQUIRE_THROW(std::runtime_error, + detail::parse_test_case_result("baz: foo")); +} + +ATF_TEST_CASE_WITHOUT_HEAD(read_test_case_result_failed); +ATF_TEST_CASE_BODY(read_test_case_result_failed) { + write_test_case_result("resfile", "failed: foo bar\n"); + const impl::test_case_result tcr = impl::read_test_case_result( + atf::fs::path("resfile")); + ATF_REQUIRE_EQ("failed", tcr.state()); + ATF_REQUIRE_EQ("foo bar", tcr.reason()); +} + +ATF_TEST_CASE_WITHOUT_HEAD(read_test_case_result_skipped); +ATF_TEST_CASE_BODY(read_test_case_result_skipped) { + write_test_case_result("resfile", "skipped: baz bar\n"); + const impl::test_case_result tcr = impl::read_test_case_result( + atf::fs::path("resfile")); + ATF_REQUIRE_EQ("skipped", tcr.state()); + ATF_REQUIRE_EQ("baz bar", tcr.reason()); +} + + +ATF_TEST_CASE(read_test_case_result_no_file); +ATF_TEST_CASE_HEAD(read_test_case_result_no_file) {} +ATF_TEST_CASE_BODY(read_test_case_result_no_file) { + ATF_REQUIRE_THROW(std::runtime_error, + impl::read_test_case_result(atf::fs::path("resfile"))); +} + +ATF_TEST_CASE_WITHOUT_HEAD(read_test_case_result_empty_file); +ATF_TEST_CASE_BODY(read_test_case_result_empty_file) { + write_test_case_result("resfile", ""); + ATF_REQUIRE_THROW(std::runtime_error, + impl::read_test_case_result(atf::fs::path("resfile"))); +} + +ATF_TEST_CASE_WITHOUT_HEAD(read_test_case_result_invalid); +ATF_TEST_CASE_BODY(read_test_case_result_invalid) { + write_test_case_result("resfile", "passed: hello\n"); + ATF_REQUIRE_THROW(std::runtime_error, + impl::read_test_case_result(atf::fs::path("resfile"))); +} + +ATF_TEST_CASE_WITHOUT_HEAD(read_test_case_result_multiline); +ATF_TEST_CASE_BODY(read_test_case_result_multiline) { + write_test_case_result("resfile", "skipped: foo\nbar\n"); + const impl::test_case_result tcr = impl::read_test_case_result( + atf::fs::path("resfile")); + ATF_REQUIRE_EQ("skipped", tcr.state()); + ATF_REQUIRE_EQ("foo<>bar", tcr.reason()); +} + +// ------------------------------------------------------------------------- +// Main. +// ------------------------------------------------------------------------- + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, tp_1); + ATF_ADD_TEST_CASE(tcs, tp_2); + ATF_ADD_TEST_CASE(tcs, tp_3); + ATF_ADD_TEST_CASE(tcs, tp_4); + ATF_ADD_TEST_CASE(tcs, tp_50); + ATF_ADD_TEST_CASE(tcs, tp_51); + ATF_ADD_TEST_CASE(tcs, tp_52); + ATF_ADD_TEST_CASE(tcs, tp_53); + ATF_ADD_TEST_CASE(tcs, tp_54); + ATF_ADD_TEST_CASE(tcs, tp_55); + ATF_ADD_TEST_CASE(tcs, tp_56); + ATF_ADD_TEST_CASE(tcs, tp_57); + ATF_ADD_TEST_CASE(tcs, tp_58); + ATF_ADD_TEST_CASE(tcs, tp_59); + ATF_ADD_TEST_CASE(tcs, tp_60); + + ATF_ADD_TEST_CASE(tcs, atf_tps_writer); + + ATF_ADD_TEST_CASE(tcs, get_metadata_bad); + ATF_ADD_TEST_CASE(tcs, get_metadata_zero_tcs); + ATF_ADD_TEST_CASE(tcs, get_metadata_several_tcs); + + ATF_ADD_TEST_CASE(tcs, parse_test_case_result_expected_death); + ATF_ADD_TEST_CASE(tcs, parse_test_case_result_expected_exit); + ATF_ADD_TEST_CASE(tcs, parse_test_case_result_expected_failure); + ATF_ADD_TEST_CASE(tcs, parse_test_case_result_expected_signal); + ATF_ADD_TEST_CASE(tcs, parse_test_case_result_expected_timeout); + ATF_ADD_TEST_CASE(tcs, parse_test_case_result_failed); + ATF_ADD_TEST_CASE(tcs, parse_test_case_result_passed); + ATF_ADD_TEST_CASE(tcs, parse_test_case_result_skipped); + ATF_ADD_TEST_CASE(tcs, parse_test_case_result_unknown); + + ATF_ADD_TEST_CASE(tcs, read_test_case_result_failed); + ATF_ADD_TEST_CASE(tcs, read_test_case_result_skipped); + ATF_ADD_TEST_CASE(tcs, read_test_case_result_no_file); + ATF_ADD_TEST_CASE(tcs, read_test_case_result_empty_file); + ATF_ADD_TEST_CASE(tcs, read_test_case_result_multiline); + ATF_ADD_TEST_CASE(tcs, read_test_case_result_invalid); + + // TODO: Add tests for run_test_case once all the missing functionality + // is implemented. +} diff --git a/external/bsd/atf/dist/atf-run/timer.cpp b/external/bsd/atf/dist/atf-run/timer.cpp new file mode 100644 index 000000000..6ed70d97f --- /dev/null +++ b/external/bsd/atf/dist/atf-run/timer.cpp @@ -0,0 +1,215 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2010 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#if defined(HAVE_CONFIG_H) +# include +#endif + +extern "C" { +#include +} + +#include +#include +#include + +extern "C" { +#include "atf-c/defs.h" +} + +#include "atf-c++/detail/exceptions.hpp" +#include "atf-c++/detail/sanity.hpp" + +#include "signals.hpp" +#include "timer.hpp" + +namespace impl = atf::atf_run; +#define IMPL_NAME "atf::atf_run" + +#if !defined(HAVE_TIMER_T) +static impl::timer* compat_handle; +#endif + +// ------------------------------------------------------------------------ +// Auxiliary functions. +// ------------------------------------------------------------------------ + +#if defined(HAVE_TIMER_T) +static +void +handler(const int signo ATF_DEFS_ATTRIBUTE_UNUSED, siginfo_t* si, + void* uc ATF_DEFS_ATTRIBUTE_UNUSED) +{ + impl::timer* timer = static_cast< impl::timer* >(si->si_value.sival_ptr); + timer->set_fired(); + timer->timeout_callback(); +} +#else +static +void +handler(const int signo ATF_DEFS_ATTRIBUTE_UNUSED, + siginfo_t* si ATF_DEFS_ATTRIBUTE_UNUSED, + void* uc ATF_DEFS_ATTRIBUTE_UNUSED) +{ + compat_handle->set_fired(); + compat_handle->timeout_callback(); +} +#endif + +// ------------------------------------------------------------------------ +// The "timer" class. +// ------------------------------------------------------------------------ + +struct impl::timer::impl { +#if defined(HAVE_TIMER_T) + ::timer_t m_timer; + ::itimerspec m_old_it; +#else + ::itimerval m_old_it; +#endif + + struct ::sigaction m_old_sa; + volatile bool m_fired; + + impl(void) : m_fired(false) + { + } +}; + +impl::timer::timer(const unsigned int seconds) : + m_pimpl(new impl()) +{ + struct ::sigaction sa; + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_SIGINFO; + sa.sa_sigaction = ::handler; + if (::sigaction(SIGALRM, &sa, &m_pimpl->m_old_sa) == -1) + throw system_error(IMPL_NAME "::timer::timer", + "Failed to set signal handler", errno); + +#if defined(HAVE_TIMER_T) + struct ::sigevent se; + se.sigev_notify = SIGEV_SIGNAL; + se.sigev_signo = SIGALRM; + se.sigev_value.sival_ptr = static_cast< void* >(this); + se.sigev_notify_function = NULL; + se.sigev_notify_attributes = NULL; + if (::timer_create(CLOCK_MONOTONIC, &se, &m_pimpl->m_timer) == -1) { + ::sigaction(SIGALRM, &m_pimpl->m_old_sa, NULL); + throw system_error(IMPL_NAME "::timer::timer", + "Failed to create timer", errno); + } + + struct ::itimerspec it; + it.it_interval.tv_sec = 0; + it.it_interval.tv_nsec = 0; + it.it_value.tv_sec = seconds; + it.it_value.tv_nsec = 0; + if (::timer_settime(m_pimpl->m_timer, 0, &it, &m_pimpl->m_old_it) == -1) { + ::sigaction(SIGALRM, &m_pimpl->m_old_sa, NULL); + ::timer_delete(m_pimpl->m_timer); + throw system_error(IMPL_NAME "::timer::timer", + "Failed to program timer", errno); + } +#else + ::itimerval it; + it.it_interval.tv_sec = 0; + it.it_interval.tv_usec = 0; + it.it_value.tv_sec = seconds; + it.it_value.tv_usec = 0; + if (::setitimer(ITIMER_REAL, &it, &m_pimpl->m_old_it) == -1) { + ::sigaction(SIGALRM, &m_pimpl->m_old_sa, NULL); + throw system_error(IMPL_NAME "::timer::timer", + "Failed to program timer", errno); + } + INV(compat_handle == NULL); + compat_handle = this; +#endif +} + +impl::timer::~timer(void) +{ +#if defined(HAVE_TIMER_T) + { + const int ret = ::timer_delete(m_pimpl->m_timer); + INV(ret != -1); + } +#else + { + const int ret = ::setitimer(ITIMER_REAL, &m_pimpl->m_old_it, NULL); + INV(ret != -1); + } +#endif + const int ret = ::sigaction(SIGALRM, &m_pimpl->m_old_sa, NULL); + INV(ret != -1); + +#if !defined(HAVE_TIMER_T) + compat_handle = NULL; +#endif +} + +bool +impl::timer::fired(void) + const +{ + return m_pimpl->m_fired; +} + +void +impl::timer::set_fired(void) +{ + m_pimpl->m_fired = true; +} + +// ------------------------------------------------------------------------ +// The "child_timer" class. +// ------------------------------------------------------------------------ + +impl::child_timer::child_timer(const unsigned int seconds, const pid_t pid, + volatile bool& terminate) : + timer(seconds), + m_pid(pid), + m_terminate(terminate) +{ +} + +impl::child_timer::~child_timer(void) +{ +} + +void +impl::child_timer::timeout_callback(void) +{ + static const timespec ts = { 1, 0 }; + m_terminate = true; + ::kill(-m_pid, SIGTERM); + ::nanosleep(&ts, NULL); + if (::kill(-m_pid, 0) != -1) + ::kill(-m_pid, SIGKILL); +} diff --git a/external/bsd/atf/dist/atf-run/timer.hpp b/external/bsd/atf/dist/atf-run/timer.hpp new file mode 100644 index 000000000..8eb722840 --- /dev/null +++ b/external/bsd/atf/dist/atf-run/timer.hpp @@ -0,0 +1,81 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2010 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#if !defined(_ATF_RUN_ALARM_HPP_) +#define _ATF_RUN_ALARM_HPP_ + +extern "C" { +#include +} + +#include + +#include "atf-c++/noncopyable.hpp" + +namespace atf { +namespace atf_run { + +class signal_programmer; + +// ------------------------------------------------------------------------ +// The "timer" class. +// ------------------------------------------------------------------------ + +class timer : noncopyable { + struct impl; + std::auto_ptr< impl > m_pimpl; + +public: + timer(const unsigned int); + virtual ~timer(void); + + bool fired(void) const; + void set_fired(void); + virtual void timeout_callback(void) = 0; +}; + +// ------------------------------------------------------------------------ +// The "child_timer" class. +// ------------------------------------------------------------------------ + +class child_timer : public timer { + const pid_t m_pid; + volatile bool& m_terminate; + +public: + child_timer(const unsigned int, const pid_t, volatile bool&); + virtual ~child_timer(void); + + void timeout_callback(void); +}; + +} // namespace atf_run +} // namespace atf + +#endif // !defined(_ATF_RUN_ALARM_HPP_) diff --git a/external/bsd/atf/dist/atf-run/user.cpp b/external/bsd/atf/dist/atf-run/user.cpp new file mode 100644 index 000000000..37329f166 --- /dev/null +++ b/external/bsd/atf/dist/atf-run/user.cpp @@ -0,0 +1,89 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +extern "C" { +#include + +#include +#include + +#include "../atf-c/detail/user.h" +} + +#include +#include + +#include "../atf-c++/detail/sanity.hpp" + +#include "user.hpp" + +namespace impl = atf::atf_run; +#define IMPL_NAME "atf::atf_run" + +uid_t +impl::euid(void) +{ + return atf_user_euid(); +} + +void +impl::drop_privileges(const std::pair< int, int > ids) +{ + if (::setgid(ids.second) == -1) + throw std::runtime_error("Failed to drop group privileges"); + if (::setuid(ids.first) == -1) + throw std::runtime_error("Failed to drop user privileges"); +} + +std::pair< int, int > +impl::get_user_ids(const std::string& user) +{ + const struct passwd* pw = ::getpwnam(user.c_str()); + if (pw == NULL) + throw std::runtime_error("Failed to get information for user " + user); + return std::make_pair(pw->pw_uid, pw->pw_gid); +} + +bool +impl::is_member_of_group(gid_t gid) +{ + return atf_user_is_member_of_group(gid); +} + +bool +impl::is_root(void) +{ + return atf_user_is_root(); +} + +bool +impl::is_unprivileged(void) +{ + return atf_user_is_unprivileged(); +} diff --git a/external/bsd/atf/dist/atf-run/user.hpp b/external/bsd/atf/dist/atf-run/user.hpp new file mode 100644 index 000000000..11b3e5546 --- /dev/null +++ b/external/bsd/atf/dist/atf-run/user.hpp @@ -0,0 +1,52 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#if !defined(_ATF_RUN_USER_HPP_) +#define _ATF_RUN_USER_HPP_ + +extern "C" { +#include +} + +#include + +namespace atf { +namespace atf_run { + +uid_t euid(void); +void drop_privileges(const std::pair< int, int >); +std::pair< int, int > get_user_ids(const std::string&); +bool is_member_of_group(gid_t); +bool is_root(void); +bool is_unprivileged(void); + +} // namespace atf_run +} // namespace atf + +#endif // !defined(_ATF_RUN_USER_HPP_) diff --git a/external/bsd/atf/dist/atf-run/user_test.cpp b/external/bsd/atf/dist/atf-run/user_test.cpp new file mode 100644 index 000000000..7218ba655 --- /dev/null +++ b/external/bsd/atf/dist/atf-run/user_test.cpp @@ -0,0 +1,148 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +extern "C" { +#include +#include +#include +#include +} + +#include +#include + +#include "../atf-c++/macros.hpp" + +#include "user.hpp" + +// ------------------------------------------------------------------------ +// Test cases for the free functions. +// ------------------------------------------------------------------------ + +ATF_TEST_CASE(euid); +ATF_TEST_CASE_HEAD(euid) +{ + set_md_var("descr", "Tests the euid function"); +} +ATF_TEST_CASE_BODY(euid) +{ + using atf::atf_run::euid; + + ATF_REQUIRE_EQ(euid(), ::geteuid()); +} + +ATF_TEST_CASE(is_member_of_group); +ATF_TEST_CASE_HEAD(is_member_of_group) +{ + set_md_var("descr", "Tests the is_member_of_group function"); +} +ATF_TEST_CASE_BODY(is_member_of_group) +{ + using atf::atf_run::is_member_of_group; + + std::set< gid_t > groups; + gid_t maxgid = 0; + { + gid_t gids[NGROUPS_MAX]; + int ngids = ::getgroups(NGROUPS_MAX, gids); + if (ngids == -1) + ATF_FAIL("Call to ::getgroups failed"); + for (int i = 0; i < ngids; i++) { + groups.insert(gids[i]); + if (gids[i] > maxgid) + maxgid = gids[i]; + } + std::cout << "User belongs to " << ngids << " groups\n"; + std::cout << "Last GID is " << maxgid << "\n"; + } + + const gid_t maxgid_limit = 1 << 16; + if (maxgid > maxgid_limit) { + std::cout << "Test truncated from " << maxgid << " groups to " + << maxgid_limit << " to keep the run time reasonable " + "enough\n"; + maxgid = maxgid_limit; + } + + for (gid_t g = 0; g <= maxgid; g++) { + if (groups.find(g) == groups.end()) { + std::cout << "Checking if user does not belong to group " + << g << "\n"; + ATF_REQUIRE(!is_member_of_group(g)); + } else { + std::cout << "Checking if user belongs to group " << g << "\n"; + ATF_REQUIRE(is_member_of_group(g)); + } + } +} + +ATF_TEST_CASE(is_root); +ATF_TEST_CASE_HEAD(is_root) +{ + set_md_var("descr", "Tests the is_root function"); +} +ATF_TEST_CASE_BODY(is_root) +{ + using atf::atf_run::is_root; + + if (::geteuid() == 0) { + ATF_REQUIRE(is_root()); + } else { + ATF_REQUIRE(!is_root()); + } +} + +ATF_TEST_CASE(is_unprivileged); +ATF_TEST_CASE_HEAD(is_unprivileged) +{ + set_md_var("descr", "Tests the is_unprivileged function"); +} +ATF_TEST_CASE_BODY(is_unprivileged) +{ + using atf::atf_run::is_unprivileged; + + if (::geteuid() != 0) { + ATF_REQUIRE(is_unprivileged()); + } else { + ATF_REQUIRE(!is_unprivileged()); + } +} + +// ------------------------------------------------------------------------ +// Main. +// ------------------------------------------------------------------------ + +ATF_INIT_TEST_CASES(tcs) +{ + // Add the tests for the free functions. + ATF_ADD_TEST_CASE(tcs, euid); + ATF_ADD_TEST_CASE(tcs, is_member_of_group); + ATF_ADD_TEST_CASE(tcs, is_root); + ATF_ADD_TEST_CASE(tcs, is_unprivileged); +} diff --git a/external/bsd/atf/dist/atf-run/zero_tcs_helper.c b/external/bsd/atf/dist/atf-run/zero_tcs_helper.c new file mode 100644 index 000000000..d4068b17a --- /dev/null +++ b/external/bsd/atf/dist/atf-run/zero_tcs_helper.c @@ -0,0 +1,36 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2010 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +ATF_TP_ADD_TCS(tp) +{ + if (tp != NULL) {} /* Use tp. */ + return atf_no_error(); +} diff --git a/external/bsd/atf/dist/atf-sh/Atffile b/external/bsd/atf/dist/atf-sh/Atffile new file mode 100644 index 000000000..f1735c308 --- /dev/null +++ b/external/bsd/atf/dist/atf-sh/Atffile @@ -0,0 +1,11 @@ +Content-Type: application/X-atf-atffile; version="1" + +prop: test-suite = atf + +tp: tc_test +tp: tp_test +tp: normalize_test +tp: config_test +tp: atf-check_test +tp: atf_check_test +tp: integration_test diff --git a/external/bsd/atf/dist/atf-sh/Kyuafile b/external/bsd/atf/dist/atf-sh/Kyuafile new file mode 100644 index 000000000..01a9253e7 --- /dev/null +++ b/external/bsd/atf/dist/atf-sh/Kyuafile @@ -0,0 +1,11 @@ +syntax("kyuafile", 1) + +test_suite("atf") + +atf_test_program{name="tc_test"} +atf_test_program{name="tp_test"} +atf_test_program{name="normalize_test"} +atf_test_program{name="config_test"} +atf_test_program{name="atf-check_test"} +atf_test_program{name="atf_check_test"} +atf_test_program{name="integration_test"} diff --git a/external/bsd/atf/dist/atf-sh/atf-check.1 b/external/bsd/atf/dist/atf-sh/atf-check.1 new file mode 100644 index 000000000..06904bc3f --- /dev/null +++ b/external/bsd/atf/dist/atf-sh/atf-check.1 @@ -0,0 +1,151 @@ +.\" +.\" Automated Testing Framework (atf) +.\" +.\" Copyright (c) 2008 The NetBSD Foundation, Inc. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +.\" CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +.\" IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +.\" GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +.\" IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.Dd June 27, 2010 +.Dt ATF-CHECK 1 +.Os +.Sh NAME +.Nm atf-check +.Nd executes a command and analyzes its results +.Sh SYNOPSIS +.Nm +.Op Fl s Ar qual:value +.Op Fl o Ar action:arg ... +.Op Fl e Ar action:arg ... +.Op Fl x +.Ar command +.Nm +.Fl h +.Sh DESCRIPTION +.Nm +executes a given command and analyzes its results, including +exit code, stdout and stderr. +.Pp +In the first synopsis form, +.Nm +will execute the provided command and apply checks specified +by arguments. +By default it will act as if it was run with +.Fl s +.Ar exit:0 +.Fl o +.Ar empty +.Fl e +.Ar empty . +Multiple checks for the same output channel are allowed and, if specified, +their results will be combined as a logical and (meaning that the output must +match all the provided checks). +.Pp +In the second synopsis form, +.Nm +will print information about all supported options and their purpose. +.Pp +The following options are available: +.Bl -tag -width XqualXvalueXX +.It Fl h +Shows a short summary of all available options and their purpose. +.It Fl s Ar qual:value +Analyzes termination status. +Must be one of: +.Bl -tag -width signal: -compact +.It Ar exit: +checks that the program exited cleanly and that its exit status is equal to +.Va value . +The exit code can be omitted altogether, in which case any clean exit is +accepted. +.It Ar ignore +ignores the exit check. +.It Ar signal: +checks that the program exited due to a signal and that the signal that +terminated it is +.Va value . +The signal can be specified both as a number or as a name, or it can also +be omitted altogether, in which case any signal is accepted. +.El +.Pp +Most of these checkers can be prefixed by the +.Sq not- +string, which effectively reverses the check. +.It Fl o Ar action:arg +Analyzes standard output. +Must be one of: +.Bl -tag -width inline: -compact +.It Ar empty +checks that stdout is empty +.It Ar ignore +ignores stdout +.It Ar file: +compares stdout with given file +.It Ar inline: +compares stdout with inline value +.It Ar match: +looks for a regular expression in stdout +.It Ar save: +saves stdout to given file +.El +.Pp +Most of these checkers can be prefixed by the +.Sq not- +string, which effectively reverses the check. +.It Fl e Ar action:arg +Analyzes standard error (syntax identical to above) +.It Fl x +Executes +.Ar command +as a shell command line, executing it with the system shell defined by +.Va ATF_SHELL +in +.Xr atf-config 1 . +You should avoid using this flag if at all possible to prevent shell quoting +issues. +.El +.Sh EXIT STATUS +.Nm +exits 0 on success, and other (unspecified) value on failure. +.Sh EXAMPLES +.Bd -literal -offset indent +# Exit code 0, nothing on stdout/stderr +atf-check 'true' + +# Typical usage if failure is expected +atf-check -s not-exit:0 'false' + +# Checking stdout/stderr +echo foobar >expout +atf-check -o file:expout -e inline:"xx\etyy\en" \e + 'echo foobar ; printf "xx\etyy\en" >&2' + +# Checking for a crash +atf-check -s signal:sigsegv my_program + +# Combined checks +atf-check -o match:foo -o not-match:bar echo foo baz +.Ed +.Sh SEE ALSO +.Xr atf-config 1 , +.Xr atf 7 diff --git a/external/bsd/atf/dist/atf-sh/atf-check.cpp b/external/bsd/atf/dist/atf-sh/atf-check.cpp new file mode 100644 index 000000000..8fc1545c2 --- /dev/null +++ b/external/bsd/atf/dist/atf-sh/atf-check.cpp @@ -0,0 +1,835 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2008 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +extern "C" { +#include +#include + +#include +#include +#include +} + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "atf-c++/check.hpp" +#include "atf-c++/config.hpp" + +#include "atf-c++/detail/application.hpp" +#include "atf-c++/detail/auto_array.hpp" +#include "atf-c++/detail/exceptions.hpp" +#include "atf-c++/detail/fs.hpp" +#include "atf-c++/detail/process.hpp" +#include "atf-c++/detail/sanity.hpp" +#include "atf-c++/detail/text.hpp" + +// ------------------------------------------------------------------------ +// Auxiliary functions. +// ------------------------------------------------------------------------ + +namespace { + +enum status_check_t { + sc_exit, + sc_ignore, + sc_signal, +}; + +struct status_check { + status_check_t type; + bool negated; + int value; + + status_check(const status_check_t& p_type, const bool p_negated, + const int p_value) : + type(p_type), + negated(p_negated), + value(p_value) + { + } +}; + +enum output_check_t { + oc_ignore, + oc_inline, + oc_file, + oc_empty, + oc_match, + oc_save +}; + +struct output_check { + output_check_t type; + bool negated; + std::string value; + + output_check(const output_check_t& p_type, const bool p_negated, + const std::string& p_value) : + type(p_type), + negated(p_negated), + value(p_value) + { + } +}; + +class temp_file : public std::ostream { + std::auto_ptr< atf::fs::path > m_path; + int m_fd; + +public: + temp_file(const atf::fs::path& p) : + std::ostream(NULL), + m_fd(-1) + { + atf::auto_array< char > buf(new char[p.str().length() + 1]); + std::strcpy(buf.get(), p.c_str()); + + m_fd = ::mkstemp(buf.get()); + if (m_fd == -1) + throw atf::system_error("atf_check::temp_file::temp_file(" + + p.str() + ")", "mkstemp(3) failed", + errno); + + m_path.reset(new atf::fs::path(buf.get())); + } + + ~temp_file(void) + { + close(); + try { + remove(*m_path); + } catch (const atf::system_error&) { + // Ignore deletion errors. + } + } + + const atf::fs::path& + get_path(void) const + { + return *m_path; + } + + void + write(const std::string& text) + { + if (::write(m_fd, text.c_str(), text.size()) == -1) + throw atf::system_error("atf_check", "write(2) failed", errno); + } + + void + close(void) + { + if (m_fd != -1) { + flush(); + ::close(m_fd); + m_fd = -1; + } + } +}; + +} // anonymous namespace + +static int +parse_exit_code(const std::string& str) +{ + try { + const int value = atf::text::to_type< int >(str); + if (value < 0 || value > 255) + throw std::runtime_error("Unused reason"); + return value; + } catch (const std::runtime_error&) { + throw atf::application::usage_error("Invalid exit code for -s option; " + "must be an integer in range 0-255"); + } +} + +static struct name_number { + const char *name; + int signo; +} signal_names_to_numbers[] = { + { "hup", SIGHUP }, + { "int", SIGINT }, + { "quit", SIGQUIT }, + { "trap", SIGTRAP }, + { "abrt", SIGABRT }, + { "kill", SIGKILL }, + { "segv", SIGSEGV }, + { "pipe", SIGPIPE }, + { "alrm", SIGALRM }, + { "term", SIGTERM }, + { "usr1", SIGUSR1 }, + { "usr2", SIGUSR2 }, + { NULL, INT_MIN }, +}; + +static int +signal_name_to_number(const std::string& str) +{ + struct name_number* iter = signal_names_to_numbers; + int signo = INT_MIN; + while (signo == INT_MIN && iter->name != NULL) { + if (str == iter->name || str == std::string("sig") + iter->name) + signo = iter->signo; + else + iter++; + } + return signo; +} + +static int +parse_signal(const std::string& str) +{ + const int signo = signal_name_to_number(str); + if (signo == INT_MIN) { + try { + return atf::text::to_type< int >(str); + } catch (std::runtime_error) { + throw atf::application::usage_error("Invalid signal name or number " + "in -s option"); + } + } + INV(signo != INT_MIN); + return signo; +} + +static status_check +parse_status_check_arg(const std::string& arg) +{ + const std::string::size_type delimiter = arg.find(':'); + bool negated = (arg.compare(0, 4, "not-") == 0); + const std::string action_str = arg.substr(0, delimiter); + const std::string action = negated ? action_str.substr(4) : action_str; + const std::string value_str = ( + delimiter == std::string::npos ? "" : arg.substr(delimiter + 1)); + int value; + + status_check_t type; + if (action == "eq") { + // Deprecated; use exit instead. TODO: Remove after 0.10. + type = sc_exit; + if (negated) + throw atf::application::usage_error("Cannot negate eq checker"); + negated = false; + value = parse_exit_code(value_str); + } else if (action == "exit") { + type = sc_exit; + if (value_str.empty()) + value = INT_MIN; + else + value = parse_exit_code(value_str); + } else if (action == "ignore") { + if (negated) + throw atf::application::usage_error("Cannot negate ignore checker"); + type = sc_ignore; + value = INT_MIN; + } else if (action == "ne") { + // Deprecated; use not-exit instead. TODO: Remove after 0.10. + type = sc_exit; + if (negated) + throw atf::application::usage_error("Cannot negate ne checker"); + negated = true; + value = parse_exit_code(value_str); + } else if (action == "signal") { + type = sc_signal; + if (value_str.empty()) + value = INT_MIN; + else + value = parse_signal(value_str); + } else + throw atf::application::usage_error("Invalid status checker"); + + return status_check(type, negated, value); +} + +static +output_check +parse_output_check_arg(const std::string& arg) +{ + const std::string::size_type delimiter = arg.find(':'); + const bool negated = (arg.compare(0, 4, "not-") == 0); + const std::string action_str = arg.substr(0, delimiter); + const std::string action = negated ? action_str.substr(4) : action_str; + + output_check_t type; + if (action == "empty") + type = oc_empty; + else if (action == "file") + type = oc_file; + else if (action == "ignore") { + if (negated) + throw atf::application::usage_error("Cannot negate ignore checker"); + type = oc_ignore; + } else if (action == "inline") + type = oc_inline; + else if (action == "match") + type = oc_match; + else if (action == "save") { + if (negated) + throw atf::application::usage_error("Cannot negate save checker"); + type = oc_save; + } else + throw atf::application::usage_error("Invalid output checker"); + + return output_check(type, negated, arg.substr(delimiter + 1)); +} + +static +std::string +flatten_argv(char* const* argv) +{ + std::string cmdline; + + char* const* arg = &argv[0]; + while (*arg != NULL) { + if (arg != &argv[0]) + cmdline += ' '; + + cmdline += *arg; + + arg++; + } + + return cmdline; +} + +static +std::auto_ptr< atf::check::check_result > +execute(const char* const* argv) +{ + std::cout << "Executing command [ "; + for (int i = 0; argv[i] != NULL; ++i) + std::cout << argv[i] << " "; + std::cout << "]\n"; + + atf::process::argv_array argva(argv); + return atf::check::exec(argva); +} + +static +std::auto_ptr< atf::check::check_result > +execute_with_shell(char* const* argv) +{ + const std::string cmd = flatten_argv(argv); + + const char* sh_argv[4]; + sh_argv[0] = atf::config::get("atf_shell").c_str(); + sh_argv[1] = "-c"; + sh_argv[2] = cmd.c_str(); + sh_argv[3] = NULL; + return execute(sh_argv); +} + +static +void +cat_file(const atf::fs::path& path) +{ + std::ifstream stream(path.c_str()); + if (!stream) + throw std::runtime_error("Failed to open " + path.str()); + + stream >> std::noskipws; + std::istream_iterator< char > begin(stream), end; + std::ostream_iterator< char > out(std::cerr); + std::copy(begin, end, out); + + stream.close(); +} + +static +bool +grep_file(const atf::fs::path& path, const std::string& regexp) +{ + std::ifstream stream(path.c_str()); + if (!stream) + throw std::runtime_error("Failed to open " + path.str()); + + bool found = false; + + std::string line; + while (!found && !std::getline(stream, line).fail()) { + if (atf::text::match(line, regexp)) + found = true; + } + + stream.close(); + + return found; +} + +static +bool +file_empty(const atf::fs::path& p) +{ + atf::fs::file_info f(p); + + return (f.get_size() == 0); +} + +static bool +compare_files(const atf::fs::path& p1, const atf::fs::path& p2) +{ + bool equal = false; + + std::ifstream f1(p1.c_str()); + if (!f1) + throw std::runtime_error("Failed to open " + p1.str()); + + std::ifstream f2(p2.c_str()); + if (!f2) + throw std::runtime_error("Failed to open " + p1.str()); + + for (;;) { + char buf1[512], buf2[512]; + + f1.read(buf1, sizeof(buf1)); + if (f1.bad()) + throw std::runtime_error("Failed to read from " + p1.str()); + + f2.read(buf2, sizeof(buf2)); + if (f2.bad()) + throw std::runtime_error("Failed to read from " + p1.str()); + + if ((f1.gcount() == 0) && (f2.gcount() == 0)) { + equal = true; + break; + } + + if ((f1.gcount() != f2.gcount()) || + (std::memcmp(buf1, buf2, f1.gcount()) != 0)) { + break; + } + } + + return equal; +} + +static +void +print_diff(const atf::fs::path& p1, const atf::fs::path& p2) +{ + const atf::process::status s = + atf::process::exec(atf::fs::path("diff"), + atf::process::argv_array("diff", "-u", p1.c_str(), + p2.c_str(), NULL), + atf::process::stream_connect(STDOUT_FILENO, + STDERR_FILENO), + atf::process::stream_inherit()); + + if (!s.exited()) + std::cerr << "Failed to run diff(3)\n"; + + if (s.exitstatus() != 1) + std::cerr << "Error while running diff(3)\n"; +} + +static +std::string +decode(const std::string& s) +{ + size_t i; + std::string res; + + res.reserve(s.length()); + + i = 0; + while (i < s.length()) { + char c = s[i++]; + + if (c == '\\') { + switch (s[i++]) { + case 'a': c = '\a'; break; + case 'b': c = '\b'; break; + case 'c': break; + case 'e': c = 033; break; + case 'f': c = '\f'; break; + case 'n': c = '\n'; break; + case 'r': c = '\r'; break; + case 't': c = '\t'; break; + case 'v': c = '\v'; break; + case '\\': break; + case '0': + { + int count = 3; + c = 0; + while (--count >= 0 && (unsigned)(s[i] - '0') < 8) + c = (c << 3) + (s[i++] - '0'); + break; + } + default: + --i; + break; + } + } + + res.push_back(c); + } + + return res; +} + +static +bool +run_status_check(const status_check& sc, const atf::check::check_result& cr) +{ + bool result; + + if (sc.type == sc_exit) { + if (cr.exited() && sc.value != INT_MIN) { + const int status = cr.exitcode(); + + if (!sc.negated && sc.value != status) { + std::cerr << "Fail: incorrect exit status: " + << status << ", expected: " + << sc.value << "\n"; + result = false; + } else if (sc.negated && sc.value == status) { + std::cerr << "Fail: incorrect exit status: " + << status << ", expected: " + << "anything else\n"; + result = false; + } else + result = true; + } else if (cr.exited() && sc.value == INT_MIN) { + result = true; + } else { + std::cerr << "Fail: program did not exit cleanly\n"; + result = false; + } + } else if (sc.type == sc_ignore) { + result = true; + } else if (sc.type == sc_signal) { + if (cr.signaled() && sc.value != INT_MIN) { + const int status = cr.termsig(); + + if (!sc.negated && sc.value != status) { + std::cerr << "Fail: incorrect signal received: " + << status << ", expected: " << sc.value << "\n"; + result = false; + } else if (sc.negated && sc.value == status) { + std::cerr << "Fail: incorrect signal received: " + << status << ", expected: " + << "anything else\n"; + result = false; + } else + result = true; + } else if (cr.signaled() && sc.value == INT_MIN) { + result = true; + } else { + std::cerr << "Fail: program did not receive a signal\n"; + result = false; + } + } else { + UNREACHABLE; + result = false; + } + + if (result == false) { + std::cerr << "stdout:\n"; + cat_file(atf::fs::path(cr.stdout_path())); + std::cerr << "\n"; + + std::cerr << "stderr:\n"; + cat_file(atf::fs::path(cr.stderr_path())); + std::cerr << "\n"; + } + + return result; +} + +static +bool +run_status_checks(const std::vector< status_check >& checks, + const atf::check::check_result& result) +{ + bool ok = false; + + for (std::vector< status_check >::const_iterator iter = checks.begin(); + !ok && iter != checks.end(); iter++) { + ok |= run_status_check(*iter, result); + } + + return ok; +} + +static +bool +run_output_check(const output_check oc, const atf::fs::path& path, + const std::string& stdxxx) +{ + bool result; + + if (oc.type == oc_empty) { + const bool is_empty = file_empty(path); + if (!oc.negated && !is_empty) { + std::cerr << "Fail: " << stdxxx << " not empty\n"; + print_diff(atf::fs::path("/dev/null"), path); + result = false; + } else if (oc.negated && is_empty) { + std::cerr << "Fail: " << stdxxx << " is empty\n"; + result = false; + } else + result = true; + } else if (oc.type == oc_file) { + const bool equals = compare_files(path, atf::fs::path(oc.value)); + if (!oc.negated && !equals) { + std::cerr << "Fail: " << stdxxx << " does not match golden " + "output\n"; + print_diff(atf::fs::path(oc.value), path); + result = false; + } else if (oc.negated && equals) { + std::cerr << "Fail: " << stdxxx << " matches golden output\n"; + cat_file(atf::fs::path(oc.value)); + result = false; + } else + result = true; + } else if (oc.type == oc_ignore) { + result = true; + } else if (oc.type == oc_inline) { + atf::fs::path path2 = atf::fs::path(atf::config::get("atf_workdir")) + / "inline.XXXXXX"; + temp_file temp(path2); + temp.write(decode(oc.value)); + temp.close(); + + const bool equals = compare_files(path, temp.get_path()); + if (!oc.negated && !equals) { + std::cerr << "Fail: " << stdxxx << " does not match expected " + "value\n"; + print_diff(temp.get_path(), path); + result = false; + } else if (oc.negated && equals) { + std::cerr << "Fail: " << stdxxx << " matches expected value\n"; + cat_file(temp.get_path()); + result = false; + } else + result = true; + } else if (oc.type == oc_match) { + const bool matches = grep_file(path, oc.value); + if (!oc.negated && !matches) { + std::cerr << "Fail: regexp " + oc.value + " not in " << stdxxx + << "\n"; + cat_file(path); + result = false; + } else if (oc.negated && matches) { + std::cerr << "Fail: regexp " + oc.value + " is in " << stdxxx + << "\n"; + cat_file(path); + result = false; + } else + result = true; + } else if (oc.type == oc_save) { + INV(!oc.negated); + std::ifstream ifs(path.c_str(), std::fstream::binary); + ifs >> std::noskipws; + std::istream_iterator< char > begin(ifs), end; + + std::ofstream ofs(oc.value.c_str(), std::fstream::binary + | std::fstream::trunc); + std::ostream_iterator obegin(ofs); + + std::copy(begin, end, obegin); + result = true; + } else { + UNREACHABLE; + result = false; + } + + return result; +} + +static +bool +run_output_checks(const std::vector< output_check >& checks, + const atf::fs::path& path, const std::string& stdxxx) +{ + bool ok = true; + + for (std::vector< output_check >::const_iterator iter = checks.begin(); + iter != checks.end(); iter++) { + ok &= run_output_check(*iter, path, stdxxx); + } + + return ok; +} + +// ------------------------------------------------------------------------ +// The "atf_check" application. +// ------------------------------------------------------------------------ + +namespace { + +class atf_check : public atf::application::app { + bool m_xflag; + + std::vector< status_check > m_status_checks; + std::vector< output_check > m_stdout_checks; + std::vector< output_check > m_stderr_checks; + + static const char* m_description; + + bool run_output_checks(const atf::check::check_result&, + const std::string&) const; + + std::string specific_args(void) const; + options_set specific_options(void) const; + void process_option(int, const char*); + void process_option_s(const std::string&); + +public: + atf_check(void); + int main(void); +}; + +} // anonymous namespace + +const char* atf_check::m_description = + "atf-check executes given command and analyzes its results."; + +atf_check::atf_check(void) : + app(m_description, "atf-check(1)", "atf(7)"), + m_xflag(false) +{ +} + +bool +atf_check::run_output_checks(const atf::check::check_result& r, + const std::string& stdxxx) + const +{ + if (stdxxx == "stdout") { + return ::run_output_checks(m_stdout_checks, + atf::fs::path(r.stdout_path()), "stdout"); + } else if (stdxxx == "stderr") { + return ::run_output_checks(m_stderr_checks, + atf::fs::path(r.stderr_path()), "stderr"); + } else { + UNREACHABLE; + return false; + } +} + +std::string +atf_check::specific_args(void) + const +{ + return ""; +} + +atf_check::options_set +atf_check::specific_options(void) + const +{ + using atf::application::option; + options_set opts; + + opts.insert(option('s', "qual:value", "Handle status. Qualifier " + "must be one of: ignore exit: signal:")); + opts.insert(option('o', "action:arg", "Handle stdout. Action must be " + "one of: empty ignore file: inline: match:regexp " + "save:")); + opts.insert(option('e', "action:arg", "Handle stderr. Action must be " + "one of: empty ignore file: inline: match:regexp " + "save:")); + opts.insert(option('x', "", "Execute command as a shell command")); + + return opts; +} + +void +atf_check::process_option(int ch, const char* arg) +{ + switch (ch) { + case 's': + m_status_checks.push_back(parse_status_check_arg(arg)); + break; + + case 'o': + m_stdout_checks.push_back(parse_output_check_arg(arg)); + break; + + case 'e': + m_stderr_checks.push_back(parse_output_check_arg(arg)); + break; + + case 'x': + m_xflag = true; + break; + + default: + UNREACHABLE; + } +} + +int +atf_check::main(void) +{ + if (m_argc < 1) + throw atf::application::usage_error("No command specified"); + + int status = EXIT_FAILURE; + + std::auto_ptr< atf::check::check_result > r = + m_xflag ? execute_with_shell(m_argv) : execute(m_argv); + + if (m_status_checks.empty()) + m_status_checks.push_back(status_check(sc_exit, false, EXIT_SUCCESS)); + else if (m_status_checks.size() > 1) { + // TODO: Remove this restriction. + throw atf::application::usage_error("Cannot specify -s more than once"); + } + + if (m_stdout_checks.empty()) + m_stdout_checks.push_back(output_check(oc_empty, false, "")); + if (m_stderr_checks.empty()) + m_stderr_checks.push_back(output_check(oc_empty, false, "")); + + if ((run_status_checks(m_status_checks, *r) == false) || + (run_output_checks(*r, "stderr") == false) || + (run_output_checks(*r, "stdout") == false)) + status = EXIT_FAILURE; + else + status = EXIT_SUCCESS; + + return status; +} + +int +main(int argc, char* const* argv) +{ + return atf_check().run(argc, argv); +} diff --git a/external/bsd/atf/dist/atf-sh/atf-check_test.sh b/external/bsd/atf/dist/atf-sh/atf-check_test.sh new file mode 100644 index 000000000..7319a2b88 --- /dev/null +++ b/external/bsd/atf/dist/atf-sh/atf-check_test.sh @@ -0,0 +1,463 @@ +# +# Automated Testing Framework (atf) +# +# Copyright (c) 2008 The NetBSD Foundation, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +# CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# The Atf_Check and Atf-Shell variables are set by atf-sh. + +h_pass() +{ + cmd="$1"; shift + + echo "Running [atf-check $*] against [${cmd}]" + + cat >script.sh <tmp; then + cat tmp + atf_fail "atf-check failed" + fi +} + +h_fail() +{ + cmd="$1"; shift + + echo "Running [atf-check $*] against [${cmd}]" + + cat >script.sh <tmp; then + cat tmp + atf_fail "atf-check succeeded but should fail" + fi +} + +atf_test_case sflag_eq_ne +sflag_eq_ne_head() +{ + atf_set "descr" "Tests for the -s option using the 'eq' and 'ne' qualifiers" +} +sflag_eq_ne_body() +{ + h_pass "true" -s eq:0 + h_pass "false" -s ne:0 + h_pass "exit 255" -s eq:255 + h_pass "exit 0" -s ne:255 + + h_fail "exit 256" -s eq:256 + h_fail "exit -1" -s eq:-1 + h_fail "true" -s ne:256 + h_fail "true" -s ne:-1 +} + +atf_test_case sflag_exit +sflag_exit_head() +{ + atf_set "descr" "Tests for the -s option using the 'exit' qualifier" +} +sflag_exit_body() +{ + h_pass 'true' -s exit:0 + h_pass 'false' -s not-exit:0 + h_pass 'exit 255' -s exit:255 + h_pass 'exit 0' -s not-exit:255 + + h_fail 'exit 256' -s exit:256 + h_fail 'exit -1' -s exit:-1 + h_fail 'true' -s not-exit:256 + h_fail 'true' -s not-exit:-1 + + h_pass 'true' -s exit + h_pass 'false' -s exit + if ${Atf_Check} -s exit -x 'kill $$'; then + atf_fail "Signal detected as clean exit" + fi +} + +atf_test_case sflag_ignore +sflag_ignore_head() +{ + atf_set "descr" "Tests for the -s option using the 'ignore' qualifier" +} +sflag_ignore_body() +{ + h_pass 'true' -s ignore + h_pass 'false' -s ignore + if ${Atf_Check} -s ignored -x 'kill $$'; then + atf_fail "Signal not ignored" + fi +} + +atf_test_case sflag_signal +sflag_signal_head() +{ + atf_set "descr" "Tests for the -s option using the 'signal' qualifier" +} +sflag_signal_body() +{ + ${Atf_Check} -s signal:hup -x 'kill -1 $$' || atf_fail "Signal not detected" + ${Atf_Check} -s signal:sighup -x 'kill -1 $$' || atf_fail "Signal not" \ + "detected" + ${Atf_Check} -s signal:1 -x 'kill -1 $$' || atf_fail "Signal not detected" + ${Atf_Check} -s signal -x 'kill -1 $$' || atf_fail "Signal not detected" + + ${Atf_Check} -s not-signal:kill -x 'kill -9 $$' && \ + atf_fail "not-signal:kill matched kill -9" + ${Atf_Check} -s not-signal:kill -x 'kill -1 $$' || \ + atf_fail "not-signal:kill did not match kill -1" + + h_fail 'true' -s signal + h_fail 'false' -s signal +} + +atf_test_case xflag +xflag_head() +{ + atf_set "descr" "Tests for the -x option" +} +xflag_body() +{ + ${Atf_Check} -s ne:0 -o ignore -e ignore "echo foo 2>&1" || \ + atf_fail "Shell command succeeded without -x" + + ${Atf_Check} -e inline:"foo\n" -x "echo foo 1>&2" || \ + atf_fail "Cannot run command with -x" + + ${Atf_Check} -o inline:"foo\n" -x echo foo || \ + atf_fail "Using -x does not respect all provided arguments" +} + +atf_test_case oflag_empty +oflag_empty_head() +{ + atf_set "descr" "Tests for the -o option using the 'empty' argument" +} +oflag_empty_body() +{ + h_pass "true" -o empty + h_fail "echo foo" -o empty +} + +atf_test_case oflag_ignore +oflag_ignore_head() +{ + atf_set "descr" "Tests for the -o option using the 'ignore' argument" +} +oflag_ignore_body() +{ + h_pass "true" -o ignore + h_pass "echo foo" -o ignore +} + +atf_test_case oflag_file +oflag_file_head() +{ + atf_set "descr" "Tests for the -o option using the 'file:' argument" +} +oflag_file_body() +{ + touch empty + h_pass "true" -o file:empty + + echo foo >text + h_pass "echo foo" -o file:text + h_fail "echo bar" -o file:text + + dd if=/dev/urandom of=bin bs=1k count=10 + h_pass "cat bin" -o file:bin +} + +atf_test_case oflag_inline +oflag_inline_head() +{ + atf_set "descr" "Tests for the -o option using the 'inline:' argument" +} +oflag_inline_body() +{ + h_pass "true" -o inline: + h_pass "echo foo bar" -o inline:"foo bar\n" + h_pass "printf 'foo bar'" -o inline:"foo bar" + h_pass "printf '\t\n\t\n'" -o inline:"\t\n\t\n" + # XXX Ugly hack to workaround the lack of \e in FreeBSD. Also, \e doesn't + # seem to work as expected in Linux. Look for a nicer solution. + case $(uname) in + Darwin|FreeBSD|Linux) + h_pass "printf '\a\b\f\n\r\t\v'" -o inline:"\a\b\f\n\r\t\v" + ;; + *) + h_pass "printf '\a\b\e\f\n\r\t\v'" -o inline:"\a\b\e\f\n\r\t\v" + ;; + esac + h_pass "printf '\011\022\033\012'" -o inline:"\011\022\033\012" + + h_fail "echo foo bar" -o inline:"foo bar" + h_fail "echo -n foo bar" -o inline:"foo bar\n" +} + +atf_test_case oflag_match +oflag_match_head() +{ + atf_set "descr" "Tests for the -o option using the 'match:' argument" +} +oflag_match_body() +{ + h_pass "printf no-newline" -o "match:^no-newline" + h_pass "echo line1; echo foo bar" -o "match:^foo" + h_pass "echo foo bar" -o "match:o b" + h_fail "echo foo bar" -o "match:baz" + h_fail "echo foo bar" -o "match:^bar" +} + +atf_test_case oflag_save +oflag_save_head() +{ + atf_set "descr" "Tests for the -o option using the 'save:' argument" +} +oflag_save_body() +{ + h_pass "echo foo" -o save:out + echo foo >exp + cmp -s out exp || atf_fail "Saved output does not match expected results" +} + +atf_test_case oflag_multiple +oflag_multiple_head() +{ + atf_set "descr" "Tests for multiple occurrences of the -o option" +} +oflag_multiple_body() +{ + h_pass "echo foo bar" -o match:foo -o match:bar + h_pass "echo foo; echo bar" -o match:foo -o match:bar + h_fail "echo foo baz" -o match:bar -o match:foo + h_fail "echo foo; echo baz" -o match:bar -o match:foo +} + +atf_test_case oflag_negated +oflag_negated_head() +{ + atf_set "descr" "Tests for negated occurrences of the -o option" +} +oflag_negated_body() +{ + h_fail "echo foo" -o empty + h_pass "echo foo" -o not-empty + + h_pass "echo foo bar" -o match:foo + h_fail "echo foo bar" -o not-match:foo +} + +atf_test_case eflag_empty +eflag_empty_head() +{ + atf_set "descr" "Tests for the -e option using the 'empty' argument" +} +eflag_empty_body() +{ + h_pass "true 1>&2" -e empty + h_fail "echo foo 1>&2" -e empty +} + +atf_test_case eflag_ignore +eflag_ignore_head() +{ + atf_set "descr" "Tests for the -e option using the 'ignore' argument" +} +eflag_ignore_body() +{ + h_pass "true 1>&2" -e ignore + h_pass "echo foo 1>&2" -e ignore +} + +atf_test_case eflag_file +eflag_file_head() +{ + atf_set "descr" "Tests for the -e option using the 'file:' argument" +} +eflag_file_body() +{ + touch empty + h_pass "true 1>&2" -e file:empty + + echo foo >text + h_pass "echo foo 1>&2" -e file:text + h_fail "echo bar 1>&2" -e file:text + + dd if=/dev/urandom of=bin bs=1k count=10 + h_pass "cat bin 1>&2" -e file:bin +} + +atf_test_case eflag_inline +eflag_inline_head() +{ + atf_set "descr" "Tests for the -e option using the 'inline:' argument" +} +eflag_inline_body() +{ + h_pass "true 1>&2" -e inline: + h_pass "echo foo bar 1>&2" -e inline:"foo bar\n" + h_pass "printf 'foo bar' 1>&2" -e inline:"foo bar" + h_pass "printf '\t\n\t\n' 1>&2" -e inline:"\t\n\t\n" + # XXX Ugly hack to workaround the lack of \e in FreeBSD. Also, \e doesn't + # seem to work as expected in Linux. Look for a nicer solution. + case $(uname) in + Darwin|FreeBSD|Linux) + h_pass "printf '\a\b\f\n\r\t\v' 1>&2" -e inline:"\a\b\f\n\r\t\v" + ;; + *) + h_pass "printf '\a\b\e\f\n\r\t\v' 1>&2" -e inline:"\a\b\e\f\n\r\t\v" + ;; + esac + h_pass "printf '\011\022\033\012' 1>&2" -e inline:"\011\022\033\012" + + h_fail "echo foo bar 1>&2" -e inline:"foo bar" + h_fail "echo -n foo bar 1>&2" -e inline:"foo bar\n" +} + +atf_test_case eflag_save +eflag_save_head() +{ + atf_set "descr" "Tests for the -e option using the 'save:' argument" +} +eflag_save_body() +{ + h_pass "echo foo 1>&2" -e save:out + echo foo >exp + cmp -s out exp || atf_fail "Saved output does not match expected results" +} + +atf_test_case eflag_match +eflag_match_head() +{ + atf_set "descr" "Tests for the -e option using the 'match:' argument" +} +eflag_match_body() +{ + h_pass "printf no-newline 1>&2" -e "match:^no-newline" + h_pass "echo line1 1>&2; echo foo bar 1>&2" -e "match:^foo" + h_pass "echo foo bar 1>&2" -e "match:o b" + h_fail "echo foo bar 1>&2" -e "match:baz" + h_fail "echo foo bar 1>&2" -e "match:^bar" +} + +atf_test_case eflag_multiple +eflag_multiple_head() +{ + atf_set "descr" "Tests for multiple occurrences of the -e option" +} +eflag_multiple_body() +{ + h_pass "echo foo bar 1>&2" -e match:foo -e match:bar + h_pass "echo foo 1>&2; echo bar 1>&2" -e match:foo -e match:bar + h_fail "echo foo baz 1>&2" -e match:bar -e match:foo + h_fail "echo foo 1>&2; echo baz 1>&2" -e match:bar -e match:foo +} + +atf_test_case eflag_negated +eflag_negated_head() +{ + atf_set "descr" "Tests for negated occurrences of the -e option" +} +eflag_negated_body() +{ + h_fail "echo foo 1>&2" -e empty + h_pass "echo foo 1>&2" -e not-empty + + h_pass "echo foo bar 1>&2" -e match:foo + h_fail "echo foo bar 1>&2" -e not-match:foo +} + +atf_test_case stdin +stdin_head() +{ + atf_set "descr" "Tests that stdin is preserved" +} +stdin_body() +{ + echo "hello" | ${Atf_Check} -o match:"hello" cat || \ + atf_fail "atf-check does not seem to respect stdin" +} + +atf_test_case invalid_umask +invalid_umask_head() +{ + atf_set "descr" "Tests for a correct error condition if the umask is" \ + "too restrictive" +} +invalid_umask_body() +{ + umask 0222 + ${Atf_Check} false 2>stderr && \ + atf_fail "atf-check returned 0 but it should have failed" + cat stderr + grep 'temporary.*current umask.*0222' stderr >/dev/null || \ + atf_fail "atf-check did not report an error related to the" \ + "current umask" +} + +atf_init_test_cases() +{ + atf_add_test_case sflag_eq_ne + atf_add_test_case sflag_exit + atf_add_test_case sflag_ignore + atf_add_test_case sflag_signal + + atf_add_test_case xflag + + atf_add_test_case oflag_empty + atf_add_test_case oflag_ignore + atf_add_test_case oflag_file + atf_add_test_case oflag_inline + atf_add_test_case oflag_match + atf_add_test_case oflag_save + atf_add_test_case oflag_multiple + atf_add_test_case oflag_negated + + atf_add_test_case eflag_empty + atf_add_test_case eflag_ignore + atf_add_test_case eflag_file + atf_add_test_case eflag_inline + atf_add_test_case eflag_match + atf_add_test_case eflag_save + atf_add_test_case eflag_multiple + atf_add_test_case eflag_negated + + atf_add_test_case stdin + + atf_add_test_case invalid_umask +} + +# vim: syntax=sh:expandtab:shiftwidth=4:softtabstop=4 diff --git a/external/bsd/atf/dist/atf-sh/atf-sh-api.3 b/external/bsd/atf/dist/atf-sh/atf-sh-api.3 new file mode 100644 index 000000000..247b52c83 --- /dev/null +++ b/external/bsd/atf/dist/atf-sh/atf-sh-api.3 @@ -0,0 +1,340 @@ +.\" +.\" Automated Testing Framework (atf) +.\" +.\" Copyright (c) 2008 The NetBSD Foundation, Inc. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +.\" CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +.\" IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +.\" GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +.\" IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.Dd June 28, 2010 +.Dt ATF-SH-API 3 +.Os +.Sh NAME +.Nm atf_add_test_case , +.Nm atf_check , +.Nm atf_check_equal , +.Nm atf_config_get , +.Nm atf_config_has , +.Nm atf_expect_death , +.Nm atf_expect_exit , +.Nm atf_expect_fail , +.Nm atf_expect_pass , +.Nm atf_expect_signal , +.Nm atf_expect_timeout , +.Nm atf_fail , +.Nm atf_get , +.Nm atf_get_srcdir , +.Nm atf_pass , +.Nm atf_require_prog , +.Nm atf_set , +.Nm atf_skip , +.Nm atf_test_case +.Nd POSIX shell API to write ATF-based test programs +.Sh SYNOPSIS +.Fn atf_add_test_case "name" +.Fn atf_check "command" +.Fn atf_check_equal "expr1" "expr2" +.Fn atf_config_get "var_name" +.Fn atf_config_has "var_name" +.Fn atf_expect_death "reason" "..." +.Fn atf_expect_exit "exitcode" "reason" "..." +.Fn atf_expect_fail "reason" "..." +.Fn atf_expect_pass +.Fn atf_expect_signal "signo" "reason" "..." +.Fn atf_expect_timeout "reason" "..." +.Fn atf_fail "reason" +.Fn atf_get "var_name" +.Fn atf_get_srcdir +.Fn atf_pass +.Fn atf_require_prog "prog_name" +.Fn atf_set "var_name" "value" +.Fn atf_skip "reason" +.Fn atf_test_case "name" "cleanup" +.Sh DESCRIPTION +ATF +provides a simple but powerful interface to easily write test programs in +the POSIX shell language. +These are extremely helpful given that they are trivial to write due to the +language simplicity and the great deal of available external tools, so they +are often ideal to test other applications at the user level. +.Pp +Test programs written using this library must be run using the +.Xr atf-sh 1 +interpreter by putting the following on their very first line: +.Bd -literal -offset indent +#! /usr/bin/env atf-sh +.Ed +.Pp +Shell-based test programs always follow this template: +.Bd -literal -offset indent +atf_test_case tc1 +tc1_head() { + ... first test case's header ... +} +tc1_body() { + ... first test case's body ... +} + +atf_test_case tc2 cleanup +tc2_head() { + ... second test case's header ... +} +tc2_body() { + ... second test case's body ... +} +tc2_cleanup() { + ... second test case's cleanup ... +} + +.Ns ... additional test cases ... + +atf_init_test_cases() { + atf_add_test_case tc1 + atf_add_test_case tc2 + ... add additional test cases ... +} +.Ed +.Ss Definition of test cases +Test cases have an identifier and are composed of three different parts: +the header, the body and an optional cleanup routine, all of which are +described in +.Xr atf-test-case 4 . +To define test cases, one can use the +.Fn atf_test_case +function, which takes a first parameter specifiying the test case's +name and instructs the library to set things up to accept it as a valid +test case. +The second parameter is optional and, if provided, must be +.Sq cleanup ; +providing this parameter allows defining a cleanup routine for the test +case. +It is important to note that this function +.Em does not +set the test case up for execution when the program is run. +In order to do so, a later registration is needed through the +.Fn atf_add_test_case +function detailed in +.Sx Program initialization . +.Pp +Later on, one must define the three parts of the body by providing two +or three functions (remember that the cleanup routine is optional). +These functions are named after the test case's identifier, and are +.Fn _head , +.Fn _body +and +.Fn _cleanup. +None of these take parameters when executed. +.Ss Program initialization +The test program must define an +.Fn atf_init_test_cases +function, which is in charge of registering the test cases that will be +executed at run time by using the +.Fn atf_add_test_case +function, which takes the name of a test case as its single parameter. +This main function should not do anything else, except maybe sourcing +auxiliary source files that define extra variables and functions. +.Ss Configuration variables +The test case has read-only access to the current configuration variables +through the +.Fn atf_config_has +and +.Fn atf_config_get +methods. +The former takes a single parameter specifying a variable name and returns +a boolean indicating whether the variable is defined or not. +The latter can take one or two parameters. +If it takes only one, it specifies the variable from which to get the +value, and this variable must be defined. +If it takes two, the second one specifies a default value to be returned +if the variable is not available. +.Ss Access to the source directory +It is possible to get the path to the test case's source directory from +anywhere in the test program by using the +.Fn atf_get_srcdir +function. +It is interesting to note that this can be used inside +.Fn atf_init_test_cases +to silently include additional helper files from the source directory. +.Ss Requiring programs +Aside from the +.Va require.progs +meta-data variable available in the header only, one can also check for +additional programs in the test case's body by using the +.Fn atf_require_prog +function, which takes the base name or full path of a single binary. +Relative paths are forbidden. +If it is not found, the test case will be automatically skipped. +.Ss Test case finalization +The test case finalizes either when the body reaches its end, at which +point the test is assumed to have +.Em passed , +or at any explicit call to +.Fn atf_pass , +.Fn atf_fail +or +.Fn atf_skip . +These three functions terminate the execution of the test case immediately. +The cleanup routine will be processed afterwards in a completely automated +way, regardless of the test case's termination reason. +.Pp +.Fn atf_pass +does not take any parameters. +.Fn atf_fail +and +.Fn atf_skip +take a single string parameter that describes why the test case failed or +was skipped, respectively. +It is very important to provide a clear error message in both cases so that +the user can quickly know why the test did not pass. +.Ss Expectations +Everything explained in the previous section changes when the test case +expectations are redefined by the programmer. +.Pp +Each test case has an internal state called +.Sq expect +that describes what the test case expectations are at any point in time. +The value of this property can change during execution by any of: +.Bl -tag -width indent +.It Fn atf_expect_death "reason" "..." +Expects the test case to exit prematurely regardless of the nature of the +exit. +.It Fn atf_expect_exit "exitcode" "reason" "..." +Expects the test case to exit cleanly. +If +.Va exitcode +is not +.Sq -1 , +.Xr atf-run 1 +will validate that the exit code of the test case matches the one provided +in this call. +Otherwise, the exact value will be ignored. +.It Fn atf_expect_fail "reason" +Any failure raised in this mode is recorded, but such failures do not report +the test case as failed; instead, the test case finalizes cleanly and is +reported as +.Sq expected failure ; +this report includes the provided +.Fa reason +as part of it. +If no error is raised while running in this mode, then the test case is +reported as +.Sq failed . +.Pp +This mode is useful to reproduce actual known bugs in tests. +Whenever the developer fixes the bug later on, the test case will start +reporting a failure, signaling the developer that the test case must be +adjusted to the new conditions. +In this situation, it is useful, for example, to set +.Fa reason +as the bug number for tracking purposes. +.It Fn atf_expect_pass +This is the normal mode of execution. +In this mode, any failure is reported as such to the user and the test case +is marked as +.Sq failed . +.It Fn atf_expect_signal "signo" "reason" "..." +Expects the test case to terminate due to the reception of a signal. +If +.Va signo +is not +.Sq -1 , +.Xr atf-run 1 +will validate that the signal that terminated the test case matches the one +provided in this call. +Otherwise, the exact value will be ignored. +.It Fn atf_expect_timeout "reason" "..." +Expects the test case to execute for longer than its timeout. +.El +.Ss Helper functions for common checks +.Fn atf_check [options] command [args] +.Pp +This function wraps the execution of the +.Nm atf-check +tool and makes the test case fail if the tool reports failure. +You should always use this function instead of the tool in your scripts. +For more details on the parameters of this function, refer to +.Xr atf-check 1 . +.Pp +.Fn atf_check_equal expr1 expr2 +.Pp +This function takes two expressions, evaluates them and, if their +results differ, aborts the test case with an appropriate failure message. +.Sh EXAMPLES +The following shows a complete test program with a single test case that +validates the addition operator: +.Bd -literal -offset indent +atf_test_case addition +addition_head() { + atf_set "descr" "Sample tests for the addition operator" +} +addition_body() { + atf_check_equal $((0 + 0)) 0 + atf_check_equal $((0 + 1)) 1 + atf_check_equal $((1 + 0)) 0 + + atf_check_equal $((1 + 1)) 2 + + atf_check_equal $((100 + 200)) 300 +} + +atf_init_test_cases() { + atf_add_test_case addition +} +.Ed +.Pp +This other example shows how to include a file with extra helper functions +in the test program: +.Bd -literal -offset indent +.Ns ... definition of test cases ... + +atf_init_test_cases() { + . $(atf_get_srcdir)/helper_functions.sh + + atf_add_test_case foo1 + atf_add_test_case foo2 +} +.Ed +.Pp +This example demonstrates the use of the very useful +.Fn atf_check +function: +.Bd -literal -offset indent +# Check for silent output +atf_check 'true' 0 null null + +# Check for silent output and failure +atf_check 'false' 1 null null + +# Check for known stdout and silent stderr +echo foo >expout +atf_check 'echo foo' 0 expout null + +# Generate a file for later inspection +atf_check 'ls' 0 stdout null +grep foo ls || atf_fail "foo file not found in listing" +.Ed +.Sh SEE ALSO +.Xr atf-sh 1 , +.Xr atf-test-program 1 , +.Xr atf-test-case 4 , +.Xr atf 7 diff --git a/external/bsd/atf/dist/atf-sh/atf-sh.1 b/external/bsd/atf/dist/atf-sh/atf-sh.1 new file mode 100644 index 000000000..b194bf4a1 --- /dev/null +++ b/external/bsd/atf/dist/atf-sh/atf-sh.1 @@ -0,0 +1,77 @@ +.\" +.\" Automated Testing Framework (atf) +.\" +.\" Copyright (c) 2010 The NetBSD Foundation, Inc. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +.\" CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +.\" IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +.\" GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +.\" IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.Dd May 9, 2010 +.Dt ATF-SH 1 +.Os +.Sh NAME +.Nm atf-sh +.Nd interpreter for shell-based test programs +.Sh SYNOPSIS +.Nm +.Ar script +.Nm +.Fl h +.Sh DESCRIPTION +.Nm +is an interpreter that runs the test program given in +.Ar script +after loading the +.Xr atf-sh-api 3 +library. +.Pp +.Nm +is not a real interpreter though: it is just a wrapper around +the system-wide shell defined by the +.Sq atf_shell +configuration value in +.Xr atf-config 1 . +.Nm +executes the interpreter, loads the +.Xr atf-sh-api 3 +library and then runs the script. +.Pp +Scripts using +.Xr atf-sh-api 3 +should start with: +.Bd -literal -offset indent +#! /usr/bin/env atf-sh +.Ed +.Pp +The following options are available: +.Bl -tag -width XhXX +.It Fl h +Shows a short summary of all available options and their purpose. +For those formats that write to a single file, specifying a +.Sq - +as the path will redirect the report to the standard output. +.El +.Sh SEE ALSO +.Xr atf-config 1 , +.Xr atf-sh-api 3 , +.Xr atf 7 diff --git a/external/bsd/atf/dist/atf-sh/atf-sh.cpp b/external/bsd/atf/dist/atf-sh/atf-sh.cpp new file mode 100644 index 000000000..d7bc7fc82 --- /dev/null +++ b/external/bsd/atf/dist/atf-sh/atf-sh.cpp @@ -0,0 +1,156 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2010 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +extern "C" { +#include +} + +#include +#include +#include +#include + +#include "atf-c++/config.hpp" + +#include "atf-c++/detail/application.hpp" +#include "atf-c++/detail/fs.hpp" +#include "atf-c++/detail/sanity.hpp" + +// ------------------------------------------------------------------------ +// Auxiliary functions. +// ------------------------------------------------------------------------ + +namespace { + +static +std::string +fix_plain_name(const char *filename) +{ + const atf::fs::path filepath(filename); + if (filepath.branch_path().str() == ".") + return std::string("./") + filename; + else + return std::string(filename); +} + +static +std::string* +construct_script(const char* filename) +{ + const std::string libexecdir = atf::config::get("atf_libexecdir"); + const std::string pkgdatadir = atf::config::get("atf_pkgdatadir"); + const std::string shell = atf::config::get("atf_shell"); + + std::string* command = new std::string(); + command->reserve(512); + (*command) += ("Atf_Check='" + libexecdir + "/atf-check' ; " + + "Atf_Shell='" + shell + "' ; " + + ". " + pkgdatadir + "/libatf-sh.subr ; " + + ". " + fix_plain_name(filename) + " ; " + + "main \"${@}\""); + return command; +} + +static +const char** +construct_argv(const std::string& shell, const int interpreter_argc, + const char* const* interpreter_argv) +{ + PRE(interpreter_argc >= 1); + PRE(interpreter_argv[0] != NULL); + + const std::string* script = construct_script(interpreter_argv[0]); + + const int count = 4 + (interpreter_argc - 1) + 1; + const char** argv = new const char*[count]; + argv[0] = shell.c_str(); + argv[1] = "-c"; + argv[2] = script->c_str(); + argv[3] = interpreter_argv[0]; + + for (int i = 1; i < interpreter_argc; i++) + argv[4 + i - 1] = interpreter_argv[i]; + + argv[count - 1] = NULL; + + return argv; +} + +} // anonymous namespace + +// ------------------------------------------------------------------------ +// The "atf_sh" class. +// ------------------------------------------------------------------------ + +class atf_sh : public atf::application::app { + static const char* m_description; + +public: + atf_sh(void); + + int main(void); +}; + +const char* atf_sh::m_description = + "atf-sh is a shell interpreter that extends the functionality of the " + "system sh(1) with the atf-sh library."; + +atf_sh::atf_sh(void) : + app(m_description, "atf-sh(1)", "atf(7)") +{ +} + +int +atf_sh::main(void) +{ + if (m_argc < 1) + throw atf::application::usage_error("No test program provided"); + + const atf::fs::path script(m_argv[0]); + if (!atf::fs::exists(script)) + throw std::runtime_error("The test program '" + script.str() + "' " + "does not exist"); + + const std::string shell = atf::config::get("atf_shell"); + const char** argv = construct_argv(shell, m_argc, m_argv); + // Don't bother keeping track of the memory allocated by construct_argv: + // we are going to exec or die immediately. + + const int ret = execv(shell.c_str(), const_cast< char** >(argv)); + INV(ret == -1); + std::cerr << "Failed to execute " << shell << ": " << std::strerror(errno) + << "\n"; + return EXIT_FAILURE; +} + +int +main(int argc, char* const* argv) +{ + return atf_sh().run(argc, argv); +} diff --git a/external/bsd/atf/dist/atf-sh/atf-sh.pc.in b/external/bsd/atf/dist/atf-sh/atf-sh.pc.in new file mode 100644 index 000000000..930dc4c3d --- /dev/null +++ b/external/bsd/atf/dist/atf-sh/atf-sh.pc.in @@ -0,0 +1,8 @@ +# ATF pkg-config file + +exec_prefix=__EXEC_PREFIX__ +interpreter=${exec_prefix}/bin/atf-sh + +Name: atf-sh +Description: Automated Testing Framework (POSIX shell binding) +Version: __ATF_VERSION__ diff --git a/external/bsd/atf/dist/atf-sh/atf_check_test.sh b/external/bsd/atf/dist/atf-sh/atf_check_test.sh new file mode 100644 index 000000000..da13c92cd --- /dev/null +++ b/external/bsd/atf/dist/atf-sh/atf_check_test.sh @@ -0,0 +1,181 @@ +# +# Automated Testing Framework (atf) +# +# Copyright (c) 2007 The NetBSD Foundation, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +# CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# TODO: Bring in the checks in the bootstrap testsuite for atf_check. + +atf_test_case info_ok +info_ok_head() +{ + atf_set "descr" "Verifies that atf_check prints an informative" \ + "message even when the command is successful" +} +info_ok_body() +{ + h="$(atf_get_srcdir)/misc_helpers -s $(atf_get_srcdir)" + + atf_check -s eq:0 -o save:stdout -e save:stderr -x \ + "${h} atf_check_info_ok" + grep 'Executing command.*true' stdout >/dev/null || \ + atf_fail "atf_check does not print an informative message" + + atf_check -s eq:0 -o save:stdout -e save:stderr -x \ + "${h} atf_check_info_fail" + grep 'Executing command.*false' stdout >/dev/null || \ + atf_fail "atf_check does not print an informative message" +} + +atf_test_case expout_mismatch +expout_mismatch_head() +{ + atf_set "descr" "Verifies that atf_check prints a diff of the" \ + "stdout and the expected stdout if the two do not" \ + "match" +} +expout_mismatch_body() +{ + h="$(atf_get_srcdir)/misc_helpers -s $(atf_get_srcdir)" + + atf_check -s eq:1 -o save:stdout -e save:stderr -x \ + "${h} atf_check_expout_mismatch" + grep 'Executing command.*echo bar' stdout >/dev/null || \ + atf_fail "atf_check does not print an informative message" + grep 'stdout does not match golden output' stderr >/dev/null || \ + atf_fail "atf_check does not print the stdout header" + grep 'stderr' stderr >/dev/null && \ + atf_fail "atf_check prints the stderr header" + grep '^-foo' stderr >/dev/null || \ + atf_fail "atf_check does not print the stdout's diff" + grep '^+bar' stderr >/dev/null || \ + atf_fail "atf_check does not print the stdout's diff" +} + +atf_test_case experr_mismatch +experr_mismatch_head() +{ + atf_set "descr" "Verifies that atf_check prints a diff of the" \ + "stderr and the expected stderr if the two do not" \ + "match" +} +experr_mismatch_body() +{ + h="$(atf_get_srcdir)/misc_helpers -s $(atf_get_srcdir)" + + atf_check -s eq:1 -o save:stdout -e save:stderr -x \ + "${h} atf_check_experr_mismatch" + grep 'Executing command.*echo bar' stdout >/dev/null || \ + atf_fail "atf_check does not print an informative message" + grep 'stdout' stderr >/dev/null && \ + atf_fail "atf_check prints the stdout header" + grep 'stderr does not match golden output' stderr >/dev/null || \ + atf_fail "atf_check does not print the stderr header" + grep '^-foo' stderr >/dev/null || \ + atf_fail "atf_check does not print the stderr's diff" + grep '^+bar' stderr >/dev/null || \ + atf_fail "atf_check does not print the stderr's diff" +} + +atf_test_case null_stdout +null_stdout_head() +{ + atf_set "descr" "Verifies that atf_check prints a the stdout it got" \ + "when it was supposed to be null" +} +null_stdout_body() +{ + h="$(atf_get_srcdir)/misc_helpers -s $(atf_get_srcdir)" + + atf_check -s eq:1 -o save:stdout -e save:stderr -x \ + "${h} atf_check_null_stdout" + grep 'Executing command.*echo.*These.*contents' stdout >/dev/null || \ + atf_fail "atf_check does not print an informative message" + grep 'stdout not empty' stderr >/dev/null || \ + atf_fail "atf_check does not print the stdout header" + grep 'stderr' stderr >/dev/null && \ + atf_fail "atf_check prints the stderr header" + grep 'These are the contents' stderr >/dev/null || \ + atf_fail "atf_check does not print stdout's contents" +} + +atf_test_case null_stderr +null_stderr_head() +{ + atf_set "descr" "Verifies that atf_check prints a the stderr it got" \ + "when it was supposed to be null" +} +null_stderr_body() +{ + h="$(atf_get_srcdir)/misc_helpers -s $(atf_get_srcdir)" + + atf_check -s eq:1 -o save:stdout -e save:stderr -x \ + "${h} atf_check_null_stderr" + grep 'Executing command.*echo.*These.*contents' stdout >/dev/null || \ + atf_fail "atf_check does not print an informative message" + grep 'stdout' stderr >/dev/null && \ + atf_fail "atf_check prints the stdout header" + grep 'stderr not empty' stderr >/dev/null || \ + atf_fail "atf_check does not print the stderr header" + grep 'These are the contents' stderr >/dev/null || \ + atf_fail "atf_check does not print stderr's contents" +} + +atf_test_case equal +equal_head() +{ + atf_set "descr" "Verifies that atf_check_equal works" +} +equal_body() +{ + h="$(atf_get_srcdir)/misc_helpers -s $(atf_get_srcdir)" + + atf_check -s eq:0 -o ignore -e ignore -x "${h} atf_check_equal_ok" + + atf_check -s eq:1 -o ignore -e ignore -x \ + "${h} -r resfile atf_check_equal_fail" + atf_check -s eq:0 -o ignore -e empty grep '^failed: a != b (a != b)$' \ + resfile + + atf_check -s eq:0 -o ignore -e ignore -x "${h} atf_check_equal_eval_ok" + + atf_check -s eq:1 -o ignore -e ignore -x \ + "${h} -r resfile atf_check_equal_eval_fail" + atf_check -s eq:0 -o ignore -e empty \ + grep '^failed: \${x} != \${y} (a != b)$' resfile +} + +atf_init_test_cases() +{ + atf_add_test_case info_ok + atf_add_test_case expout_mismatch + atf_add_test_case experr_mismatch + atf_add_test_case null_stdout + atf_add_test_case null_stderr + atf_add_test_case equal +} + +# vim: syntax=sh:expandtab:shiftwidth=4:softtabstop=4 diff --git a/external/bsd/atf/dist/atf-sh/config_test.sh b/external/bsd/atf/dist/atf-sh/config_test.sh new file mode 100644 index 000000000..f7f57f019 --- /dev/null +++ b/external/bsd/atf/dist/atf-sh/config_test.sh @@ -0,0 +1,83 @@ +# +# Automated Testing Framework (atf) +# +# Copyright (c) 2007 The NetBSD Foundation, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +# CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +atf_test_case has +has_head() +{ + atf_set "descr" "Verifies that atf_config_has works" +} +has_body() +{ + h="$(atf_get_srcdir)/misc_helpers -s $(atf_get_srcdir)" + + atf_check -s eq:0 -o match:'foo not found' -e ignore -x \ + "TEST_VARIABLE=foo ${h} config_has" + + atf_check -s eq:0 -o match:'foo found' -e ignore -x \ + "TEST_VARIABLE=foo ${h} -v foo=bar config_has" + + echo "Checking for deprecated variables" + atf_check -s eq:0 -o match:'workdir not found' -e ignore -x \ + "TEST_VARIABLE=workdir ${h} config_has" +} + +atf_test_case get +get_head() +{ + atf_set "descr" "Verifies that atf_config_get works" +} +get_body() +{ + h="$(atf_get_srcdir)/misc_helpers -s $(atf_get_srcdir)" + + echo "Querying an undefined variable" + ( atf_config_get "undefined" ) >out 2>err && \ + atf_fail "Getting an undefined variable succeeded" + grep 'not find' err || \ + atf_fail "Getting an undefined variable did not report an error" + + echo "Querying an undefined variable using a default value" + v=$(atf_config_get "undefined" "the default value") + [ "${v}" = "the default value" ] || \ + atf_fail "Default value does not work" + + atf_check -s eq:0 -o match:'foo = bar' -e ignore -x \ + "TEST_VARIABLE=foo ${h} -v foo=bar config_get" + + atf_check -s eq:0 -o match:'foo = baz' -e ignore -x \ + "TEST_VARIABLE=foo ${h} -v foo=baz config_get" +} + +atf_init_test_cases() +{ + atf_add_test_case has + atf_add_test_case get +} + +# vim: syntax=sh:expandtab:shiftwidth=4:softtabstop=4 diff --git a/external/bsd/atf/dist/atf-sh/integration_test.sh b/external/bsd/atf/dist/atf-sh/integration_test.sh new file mode 100644 index 000000000..55bb2784e --- /dev/null +++ b/external/bsd/atf/dist/atf-sh/integration_test.sh @@ -0,0 +1,91 @@ +# +# Automated Testing Framework (atf) +# +# Copyright (c) 2010 The NetBSD Foundation, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +# CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +create_test_program() { + echo '#! /usr/bin/env atf-sh' >"${1}" + cat >>"${1}" + chmod +x "${1}" +} + +atf_test_case no_args +no_args_body() +{ + cat >experr <experr <>>\${0}<<<" + while test \${#} -gt 0; do + echo ">>>\${1}<<<" + shift + done + true +} +EOF + + cat >expout <>>./tp<<< +>>> a b <<< +>>>foo<<< +EOF + atf_check -s eq:0 -o file:expout -e empty ./tp ' a b ' foo + + cat >expout <>>tp<<< +>>> hello bye <<< +>>>foo bar<<< +EOF + atf_check -s eq:0 -o file:expout -e empty atf-sh tp ' hello bye ' 'foo bar' +} + +atf_init_test_cases() +{ + atf_add_test_case no_args + atf_add_test_case missing_script + atf_add_test_case arguments +} + +# vim: syntax=sh:expandtab:shiftwidth=4:softtabstop=4 diff --git a/external/bsd/atf/dist/atf-sh/libatf-sh.subr b/external/bsd/atf/dist/atf-sh/libatf-sh.subr new file mode 100644 index 000000000..8525b220c --- /dev/null +++ b/external/bsd/atf/dist/atf-sh/libatf-sh.subr @@ -0,0 +1,779 @@ +# +# Automated Testing Framework (atf) +# +# Copyright (c) 2007 The NetBSD Foundation, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +# CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +set -e + +# ------------------------------------------------------------------------ +# GLOBAL VARIABLES +# ------------------------------------------------------------------------ + +# Values for the expect property. +Expect=pass +Expect_Reason= + +# A boolean variable that indicates whether we are parsing a test case's +# head or not. +Parsing_Head=false + +# The program name. +Prog_Name=${0##*/} + +# The file to which the test case will print its result. +Results_File= + +# The test program's source directory: i.e. where its auxiliary data files +# and helper utilities can be found. Can be overriden through the '-s' flag. +Source_Dir="$(dirname ${0})" + +# Indicates the test case we are currently processing. +Test_Case= + +# List of meta-data variables for the current test case. +Test_Case_Vars= + +# The list of all test cases provided by the test program. +Test_Cases= + +# ------------------------------------------------------------------------ +# PUBLIC INTERFACE +# ------------------------------------------------------------------------ + +# +# atf_add_test_case tc-name +# +# Adds the given test case to the list of test cases that form the test +# program. The name provided here must be accompanied by two functions +# named after it: _head and _body, and optionally by +# a _cleanup function. +# +atf_add_test_case() +{ + Test_Cases="${Test_Cases} ${1}" +} + +# +# atf_check cmd expcode expout experr +# +# Executes atf-check with given arguments and automatically calls +# atf_fail in case of failure. +# +atf_check() +{ + ${Atf_Check} "${@}" || \ + atf_fail "atf-check failed; see the output of the test for details" +} + +# +# atf_check_equal expr1 expr2 +# +# Checks that expr1's value matches expr2's and, if not, raises an +# error. Ideally expr1 and expr2 should be provided quoted (not +# expanded) so that the error message is helpful; otherwise it will +# only show the values, not the expressions themselves. +# +atf_check_equal() +{ + eval _val1=\"${1}\" + eval _val2=\"${2}\" + test "${_val1}" = "${_val2}" || \ + atf_fail "${1} != ${2} (${_val1} != ${_val2})" +} + +# +# atf_config_get varname [defvalue] +# +# Prints the value of a configuration variable. If it is not +# defined, prints the given default value. +# +atf_config_get() +{ + _varname="__tc_config_var_$(_atf_normalize ${1})" + if [ ${#} -eq 1 ]; then + eval _value=\"\${${_varname}-__unset__}\" + [ "${_value}" = __unset__ ] && \ + _atf_error 1 "Could not find configuration variable \`${1}'" + echo ${_value} + elif [ ${#} -eq 2 ]; then + eval echo \${${_varname}-${2}} + else + _atf_error 1 "Incorrect number of parameters for atf_config_get" + fi +} + +# +# atf_config_has varname +# +# Returns a boolean indicating if the given configuration variable is +# defined or not. +# +atf_config_has() +{ + _varname="__tc_config_var_$(_atf_normalize ${1})" + eval _value=\"\${${_varname}-__unset__}\" + [ "${_value}" != __unset__ ] +} + +# +# atf_expect_death reason +# +# Sets the expectations to 'death'. +# +atf_expect_death() +{ + _atf_validate_expect + + Expect=death + _atf_create_resfile "expected_death: ${*}" +} + +# +# atf_expect_timeout reason +# +# Sets the expectations to 'timeout'. +# +atf_expect_timeout() +{ + _atf_validate_expect + + Expect=timeout + _atf_create_resfile "expected_timeout: ${*}" +} + +# +# atf_expect_exit exitcode reason +# +# Sets the expectations to 'exit'. +# +atf_expect_exit() +{ + _exitcode="${1}"; shift + + _atf_validate_expect + + Expect=exit + if [ "${_exitcode}" = "-1" ]; then + _atf_create_resfile "expected_exit: ${*}" + else + _atf_create_resfile "expected_exit(${_exitcode}): ${*}" + fi +} + +# +# atf_expect_fail reason +# +# Sets the expectations to 'fail'. +# +atf_expect_fail() +{ + _atf_validate_expect + + Expect=fail + Expect_Reason="${*}" +} + +# +# atf_expect_pass +# +# Sets the expectations to 'pass'. +# +atf_expect_pass() +{ + _atf_validate_expect + + Expect=pass + Expect_Reason= +} + +# +# atf_expect_signal signo reason +# +# Sets the expectations to 'signal'. +# +atf_expect_signal() +{ + _signo="${1}"; shift + + _atf_validate_expect + + Expect=signal + if [ "${_signo}" = "-1" ]; then + _atf_create_resfile "expected_signal: ${*}" + else + _atf_create_resfile "expected_signal(${_signo}): ${*}" + fi +} + +# +# atf_expected_failure msg1 [.. msgN] +# +# Makes the test case report an expected failure with the given error +# message. Multiple words can be provided, which are concatenated with +# a single blank space. +# +atf_expected_failure() +{ + _atf_create_resfile "expected_failure: ${Expect_Reason}: ${*}" + exit 0 +} + +# +# atf_fail msg1 [.. msgN] +# +# Makes the test case fail with the given error message. Multiple +# words can be provided, in which case they are joined by a single +# blank space. +# +atf_fail() +{ + case "${Expect}" in + fail) + atf_expected_failure "${@}" + ;; + pass) + _atf_create_resfile "failed: ${*}" + exit 1 + ;; + *) + _atf_error 128 "Unreachable" + ;; + esac +} + +# +# atf_get varname +# +# Prints the value of a test case-specific variable. Given that one +# should not get the value of non-existent variables, it is fine to +# always use this function as 'val=$(atf_get var)'. +# +atf_get() +{ + eval echo \${__tc_var_${Test_Case}_$(_atf_normalize ${1})} +} + +# +# atf_get_srcdir +# +# Prints the value of the test case's source directory. +# +atf_get_srcdir() +{ + echo ${Source_Dir} +} + +# +# atf_pass +# +# Makes the test case pass. Shouldn't be used in general, as a test +# case that does not explicitly fail is assumed to pass. +# +atf_pass() +{ + case "${Expect}" in + fail) + Expect=pass + atf_fail "Test case was expecting a failure but got a pass instead" + ;; + pass) + _atf_create_resfile passed + exit 0 + ;; + *) + _atf_error 128 "Unreachable" + ;; + esac +} + +# +# atf_require_prog prog +# +# Checks that the given program name (either provided as an absolute +# path or as a plain file name) can be found. If it is not available, +# automatically skips the test case with an appropriate message. +# +# Relative paths are not allowed because the test case cannot predict +# where it will be executed from. +# +atf_require_prog() +{ + _prog= + case ${1} in + /*) + _prog="${1}" + [ -x ${_prog} ] || \ + atf_skip "The required program ${1} could not be found" + ;; + */*) + atf_fail "atf_require_prog does not accept relative path names \`${1}'" + ;; + *) + _prog=$(_atf_find_in_path "${1}") + [ -n "${_prog}" ] || \ + atf_skip "The required program ${1} could not be found" \ + "in the PATH" + ;; + esac +} + +# +# atf_set varname val1 [.. valN] +# +# Sets the test case's variable 'varname' to the specified values +# which are concatenated using a single blank space. This function +# is supposed to be called form the test case's head only. +# +atf_set() +{ + ${Parsing_Head} || \ + _atf_error 128 "atf_set called from the test case's body" + + Test_Case_Vars="${Test_Case_Vars} ${1}" + _var=$(_atf_normalize ${1}); shift + eval __tc_var_${Test_Case}_${_var}=\"\${*}\" +} + +# +# atf_skip msg1 [.. msgN] +# +# Skips the test case because of the reason provided. Multiple words +# can be given, in which case they are joined by a single blank space. +# +atf_skip() +{ + _atf_create_resfile "skipped: ${*}" + exit 0 +} + +# +# atf_test_case tc-name cleanup +# +# Defines a new test case named tc-name. The name provided here must be +# accompanied by two functions named after it: _head and +# _body. If cleanup is set to 'cleanup', then this also expects +# a _cleanup function to be defined. +# +atf_test_case() +{ + eval "${1}_head() { :; }" + eval "${1}_body() { atf_fail 'Test case not implemented'; }" + if [ "${2}" = cleanup ]; then + eval __has_cleanup_${1}=true + eval "${1}_cleanup() { :; }" + else + eval "${1}_cleanup() { + _atf_error 1 'Test case ${1} declared without a cleanup routine'; }" + fi +} + +# ------------------------------------------------------------------------ +# PRIVATE INTERFACE +# ------------------------------------------------------------------------ + +# +# _atf_config_set varname val1 [.. valN] +# +# Sets the test case's private variable 'varname' to the specified +# values which are concatenated using a single blank space. +# +_atf_config_set() +{ + _var=$(_atf_normalize ${1}); shift + eval __tc_config_var_${_var}=\"\${*}\" + Config_Vars="${Config_Vars} __tc_config_var_${_var}" +} + +# +# _atf_config_set_str varname=val +# +# Sets the test case's private variable 'varname' to the specified +# value. The parameter is of the form 'varname=val'. +# +_atf_config_set_from_str() +{ + _oldifs=${IFS} + IFS='=' + set -- ${*} + _var=${1} + shift + _val="${@}" + IFS=${_oldifs} + _atf_config_set "${_var}" "${_val}" +} + +# +# _atf_create_resfile contents +# +# Creates the results file. +# +_atf_create_resfile() +{ + if [ -n "${Results_File}" ]; then + echo "${*}" >"${Results_File}" || \ + _atf_error 128 "Cannot create results file '${Results_File}'" + else + echo "${*}" + fi +} + +# +# _atf_error error_code [msg1 [.. msgN]] +# +# Prints the given error message (which can be composed of multiple +# arguments, in which case are joined by a single space) and exits +# with the specified error code. +# +# This must not be used by test programs themselves (hence making +# the function private) to indicate a test case's failure. They +# have to use the atf_fail function. +# +_atf_error() +{ + _error_code="${1}"; shift + + echo "${Prog_Name}: ERROR:" "$@" 1>&2 + exit ${_error_code} +} + +# +# _atf_warning msg1 [.. msgN] +# +# Prints the given warning message (which can be composed of multiple +# arguments, in which case are joined by a single space). +# +_atf_warning() +{ + echo "${Prog_Name}: WARNING:" "$@" 1>&2 +} + +# +# _atf_find_in_path program +# +# Looks for a program in the path and prints the full path to it or +# nothing if it could not be found. It also returns true in case of +# success. +# +_atf_find_in_path() +{ + _prog="${1}" + + _oldifs=${IFS} + IFS=: + for _dir in ${PATH} + do + if [ -x ${_dir}/${_prog} ]; then + IFS=${_oldifs} + echo ${_dir}/${_prog} + return 0 + fi + done + IFS=${_oldifs} + + return 1 +} + +# +# _atf_has_tc name +# +# Returns true if the given test case exists. +# +_atf_has_tc() +{ + for _tc in ${Test_Cases}; do + [ "${_tc}" != "${1}" ] || return 0 + done + return 1 +} + +# +# _atf_list_tcs +# +# Describes all test cases and prints the list to the standard output. +# +_atf_list_tcs() +{ + echo 'Content-Type: application/X-atf-tp; version="1"' + echo + + set -- ${Test_Cases} + while [ ${#} -gt 0 ]; do + _atf_parse_head ${1} + + echo "ident: $(atf_get ident)" + for _var in ${Test_Case_Vars}; do + [ "${_var}" != "ident" ] && echo "${_var}: $(atf_get ${_var})" + done + + [ ${#} -gt 1 ] && echo + shift + done +} + +# +# _atf_normalize str +# +# Normalizes a string so that it is a valid shell variable name. +# +_atf_normalize() +{ + echo ${1} | tr .- __ +} + +# +# _atf_parse_head tcname +# +# Evaluates a test case's head to gather its variables and prepares the +# test program to run it. +# +_atf_parse_head() +{ + Parsing_Head=true + + Test_Case="${1}" + Test_Case_Vars= + + if _atf_has_cleanup "${1}"; then + atf_set has.cleanup "true" + fi + + ${1}_head + atf_set ident "${1}" + + Parsing_Head=false +} + +# +# _atf_run_tc tc +# +# Runs the specified test case. Prints its exit status to the +# standard output and returns a boolean indicating if the test was +# successful or not. +# +_atf_run_tc() +{ + case ${1} in + *:*) + _tcname=${1%%:*} + _tcpart=${1#*:} + + if [ "${_tcpart}" != body -a "${_tcpart}" != cleanup ]; then + _atf_syntax_error "Unknown test case part \`${_tcpart}'" + fi + ;; + + *) + _tcname=${1} + _tcpart=body + ;; + esac + + _atf_has_tc "${_tcname}" || _atf_syntax_error "Unknown test case \`${1}'" + + if [ "${__RUNNING_INSIDE_ATF_RUN}" != "internal-yes-value" ]; then + _atf_warning "Running test cases without atf-run(1) is unsupported" + _atf_warning "No isolation nor timeout control is being applied;" \ + "you may get unexpected failures; see atf-test-case(4)" + fi + + _atf_parse_head ${_tcname} + + case ${_tcpart} in + body) + if ${_tcname}_body; then + _atf_validate_expect + _atf_create_resfile passed + else + Expect=pass + atf_fail "Test case body returned a non-ok exit code, but" \ + "this is not allowed" + fi + ;; + cleanup) + if _atf_has_cleanup "${_tcname}"; then + ${_tcname}_cleanup || _atf_error 128 "The test case cleanup" \ + "returned a non-ok exit code, but this is not allowed" + fi + ;; + *) + _atf_error 128 "Unknown test case part" + ;; + esac +} + +# +# _atf_syntax_error msg1 [.. msgN] +# +# Formats and prints a syntax error message and terminates the +# program prematurely. +# +_atf_syntax_error() +{ + echo "${Prog_Name}: ERROR: ${@}" 1>&2 + echo "${Prog_Name}: See atf-test-program(1) for usage details." 1>&2 + exit 1 +} + +# +# _atf_has_cleanup tc-name +# +# Returns a boolean indicating if the given test case has a cleanup +# routine or not. +# +_atf_has_cleanup() +{ + _found=true + eval "[ x\"\${__has_cleanup_${1}}\" = xtrue ] || _found=false" + [ "${_found}" = true ] +} + +# +# _atf_validate_expect +# +# Ensures that the current test case state is correct regarding the expect +# status. +# +_atf_validate_expect() +{ + case "${Expect}" in + death) + Expect=pass + atf_fail "Test case was expected to terminate abruptly but it" \ + "continued execution" + ;; + exit) + Expect=pass + atf_fail "Test case was expected to exit cleanly but it continued" \ + "execution" + ;; + fail) + Expect=pass + atf_fail "Test case was expecting a failure but none were raised" + ;; + pass) + ;; + signal) + Expect=pass + atf_fail "Test case was expected to receive a termination signal" \ + "but it continued execution" + ;; + timeout) + Expect=pass + atf_fail "Test case was expected to hang but it continued execution" + ;; + *) + _atf_error 128 "Unreachable" + ;; + esac +} + +# +# _atf_warning [msg1 [.. msgN]] +# +# Prints the given warning message (which can be composed of multiple +# arguments, in which case are joined by a single space). +# +# This must not be used by test programs themselves (hence making +# the function private). +# +_atf_warning() +{ + echo "${Prog_Name}: WARNING:" "$@" 1>&2 +} + +# +# main [options] test_case +# +# Test program's entry point. +# +main() +{ + # Process command-line options first. + _numargs=${#} + _lflag=false + while getopts :lr:s:v: arg; do + case ${arg} in + l) + _lflag=true + ;; + + r) + Results_File=${OPTARG} + ;; + + s) + Source_Dir=${OPTARG} + ;; + + v) + _atf_config_set_from_str "${OPTARG}" + ;; + + \?) + _atf_syntax_error "Unknown option -${OPTARG}." + # NOTREACHED + ;; + esac + done + shift `expr ${OPTIND} - 1` + + # First of all, make sure that the source directory is correct. It + # doesn't matter if the user did not change it, because the default + # value may not work. (TODO: It possibly should, even though it is + # not a big deal because atf-run deals with this.) + case ${Source_Dir} in + /*) + ;; + *) + Source_Dir=$(pwd)/${Source_Dir} + ;; + esac + [ -f ${Source_Dir}/${Prog_Name} ] || \ + _atf_error 1 "Cannot find the test program in the source" \ + "directory \`${Source_Dir}'" + + # Call the test program's hook to register all available test cases. + atf_init_test_cases + + # Run or list test cases. + if `${_lflag}`; then + if [ ${#} -gt 0 ]; then + _atf_syntax_error "Cannot provide test case names with -l" + fi + _atf_list_tcs + else + if [ ${#} -eq 0 ]; then + _atf_syntax_error "Must provide a test case name" + elif [ ${#} -gt 1 ]; then + _atf_syntax_error "Cannot provide more than one test case name" + else + _atf_run_tc "${1}" + fi + fi +} + +# vim: syntax=sh:expandtab:shiftwidth=4:softtabstop=4 diff --git a/external/bsd/atf/dist/atf-sh/misc_helpers.sh b/external/bsd/atf/dist/atf-sh/misc_helpers.sh new file mode 100644 index 000000000..8b72f0ae2 --- /dev/null +++ b/external/bsd/atf/dist/atf-sh/misc_helpers.sh @@ -0,0 +1,296 @@ +# +# Automated Testing Framework (atf) +# +# Copyright (c) 2007 The NetBSD Foundation, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +# CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# ------------------------------------------------------------------------- +# Helper tests for "t_atf_check". +# ------------------------------------------------------------------------- + +atf_test_case atf_check_info_ok +atf_check_info_ok_head() +{ + atf_set "descr" "Helper test case for the t_atf_check test program" +} +atf_check_info_ok_body() +{ + atf_check -s eq:0 -o empty -e empty true +} + +atf_test_case atf_check_info_fail +atf_check_info_fail_head() +{ + atf_set "descr" "Helper test case for the t_atf_check test program" +} +atf_check_info_fail_body() +{ + # In Solaris, /usr/bin/false returns 255 rather than 1. Use the + # built-in version for the check. + atf_check -s eq:1 -o empty -e empty sh -c "false" +} + +atf_test_case atf_check_expout_mismatch +atf_check_expout_mismatch_head() +{ + atf_set "descr" "Helper test case for the t_atf_check test program" +} +atf_check_expout_mismatch_body() +{ + cat >expout <experr <&2' +} + +atf_test_case atf_check_null_stdout +atf_check_null_stdout_head() +{ + atf_set "descr" "Helper test case for the t_atf_check test program" +} +atf_check_null_stdout_body() +{ + atf_check -s eq:0 -o empty -e empty echo "These are the contents" +} + +atf_test_case atf_check_null_stderr +atf_check_null_stderr_head() +{ + atf_set "descr" "Helper test case for the t_atf_check test program" +} +atf_check_null_stderr_body() +{ + atf_check -s eq:0 -o empty -e empty -x 'echo "These are the contents" 1>&2' +} + +atf_test_case atf_check_equal_ok +atf_check_equal_ok_head() +{ + atf_set "descr" "Helper test case for the t_atf_check test program" +} +atf_check_equal_ok_body() +{ + atf_check_equal a a +} + +atf_test_case atf_check_equal_fail +atf_check_equal_fail_head() +{ + atf_set "descr" "Helper test case for the t_atf_check test program" +} +atf_check_equal_fail_body() +{ + atf_check_equal a b +} + +atf_test_case atf_check_equal_eval_ok +atf_check_equal_eval_ok_head() +{ + atf_set "descr" "Helper test case for the t_atf_check test program" +} +atf_check_equal_eval_ok_body() +{ + x=a + y=a + atf_check_equal '${x}' '${y}' +} + +atf_test_case atf_check_equal_eval_fail +atf_check_equal_eval_fail_head() +{ + atf_set "descr" "Helper test case for the t_atf_check test program" +} +atf_check_equal_eval_fail_body() +{ + x=a + y=b + atf_check_equal '${x}' '${y}' +} + +# ------------------------------------------------------------------------- +# Helper tests for "t_config". +# ------------------------------------------------------------------------- + +atf_test_case config_get +config_get_head() +{ + atf_set "descr" "Helper test case for the t_config test program" +} +config_get_body() +{ + if atf_config_has ${TEST_VARIABLE}; then + echo "${TEST_VARIABLE} = $(atf_config_get ${TEST_VARIABLE})" + fi +} + +atf_test_case config_has +config_has_head() +{ + atf_set "descr" "Helper test case for the t_config test program" +} +config_has_body() +{ + if atf_config_has ${TEST_VARIABLE}; then + echo "${TEST_VARIABLE} found" + else + echo "${TEST_VARIABLE} not found" + fi +} + +# ------------------------------------------------------------------------- +# Helper tests for "t_normalize". +# ------------------------------------------------------------------------- + +atf_test_case normalize +normalize_head() +{ + atf_set "descr" "Helper test case for the t_normalize test program" + atf_set "a.b" "test value 1" + atf_set "c-d" "test value 2" +} +normalize_body() +{ + echo "a.b: $(atf_get a.b)" + echo "c-d: $(atf_get c-d)" +} + +# ------------------------------------------------------------------------- +# Helper tests for "t_tc". +# ------------------------------------------------------------------------- + +atf_test_case tc_pass_true +tc_pass_true_head() +{ + atf_set "descr" "Helper test case for the t_tc test program" +} +tc_pass_true_body() +{ + true +} + +atf_test_case tc_pass_false +tc_pass_false_head() +{ + atf_set "descr" "Helper test case for the t_tc test program" +} +tc_pass_false_body() +{ + false +} + +atf_test_case tc_pass_return_error +tc_pass_return_error_head() +{ + atf_set "descr" "Helper test case for the t_tc test program" +} +tc_pass_return_error_body() +{ + return 1 +} + +atf_test_case tc_fail +tc_fail_head() +{ + atf_set "descr" "Helper test case for the t_tc test program" +} +tc_fail_body() +{ + echo "An error" 1>&2 + exit 1 +} + +atf_test_case tc_missing_body +tc_missing_body_head() +{ + atf_set "descr" "Helper test case for the t_tc test program" +} + +# ------------------------------------------------------------------------- +# Helper tests for "t_tp". +# ------------------------------------------------------------------------- + +atf_test_case tp_srcdir +tp_srcdir_head() +{ + atf_set "descr" "Helper test case for the t_tp test program" +} +tp_srcdir_body() +{ + echo "Calling helper" + helper_subr || atf_fail "Could not call helper subroutine" +} + +# ------------------------------------------------------------------------- +# Main. +# ------------------------------------------------------------------------- + +atf_init_test_cases() +{ + # Add helper tests for t_atf_check. + atf_add_test_case atf_check_info_ok + atf_add_test_case atf_check_info_fail + atf_add_test_case atf_check_expout_mismatch + atf_add_test_case atf_check_experr_mismatch + atf_add_test_case atf_check_null_stdout + atf_add_test_case atf_check_null_stderr + atf_add_test_case atf_check_equal_ok + atf_add_test_case atf_check_equal_fail + atf_add_test_case atf_check_equal_eval_ok + atf_add_test_case atf_check_equal_eval_fail + + # Add helper tests for t_config. + atf_add_test_case config_get + atf_add_test_case config_has + + # Add helper tests for t_normalize. + atf_add_test_case normalize + + # Add helper tests for t_tc. + atf_add_test_case tc_pass_true + atf_add_test_case tc_pass_false + atf_add_test_case tc_pass_return_error + atf_add_test_case tc_fail + atf_add_test_case tc_missing_body + + # Add helper tests for t_tp. + [ -f $(atf_get_srcdir)/subrs ] && . $(atf_get_srcdir)/subrs + atf_add_test_case tp_srcdir +} + +# vim: syntax=sh:expandtab:shiftwidth=4:softtabstop=4 diff --git a/external/bsd/atf/dist/atf-sh/normalize_test.sh b/external/bsd/atf/dist/atf-sh/normalize_test.sh new file mode 100644 index 000000000..0f59da03b --- /dev/null +++ b/external/bsd/atf/dist/atf-sh/normalize_test.sh @@ -0,0 +1,48 @@ +# +# Automated Testing Framework (atf) +# +# Copyright (c) 2007 The NetBSD Foundation, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +# CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +atf_test_case main +main_head() +{ + atf_set "descr" "Verifies that variable names with symbols not" \ + "allowed as part of shell variable names work" +} +main_body() +{ + h="$(atf_get_srcdir)/misc_helpers -s $(atf_get_srcdir)" + atf_check -s eq:0 -o match:'a.b: test value 1' \ + -o match:'c-d: test value 2' -e ignore ${h} normalize +} + +atf_init_test_cases() +{ + atf_add_test_case main +} + +# vim: syntax=sh:expandtab:shiftwidth=4:softtabstop=4 diff --git a/external/bsd/atf/dist/atf-sh/tc_test.sh b/external/bsd/atf/dist/atf-sh/tc_test.sh new file mode 100644 index 000000000..5bece4200 --- /dev/null +++ b/external/bsd/atf/dist/atf-sh/tc_test.sh @@ -0,0 +1,64 @@ +# +# Automated Testing Framework (atf) +# +# Copyright (c) 2007 The NetBSD Foundation, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +# CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +atf_test_case default_status +default_status_head() +{ + atf_set "descr" "Verifies that test cases get the correct default" \ + "status if they did not provide any" +} +default_status_body() +{ + h="$(atf_get_srcdir)/misc_helpers -s $(atf_get_srcdir)" + atf_check -s eq:0 -o ignore -e ignore ${h} tc_pass_true + atf_check -s eq:1 -o ignore -e ignore ${h} tc_pass_false + atf_check -s eq:1 -o match:'failed:.*body.*non-ok exit code' -e ignore \ + ${h} tc_pass_return_error + atf_check -s eq:1 -o ignore -e match:'An error' ${h} tc_fail +} + +atf_test_case missing_body +missing_body_head() +{ + atf_set "descr" "Verifies that test cases without a body are reported" \ + "as failed" +} +missing_body_body() +{ + h="$(atf_get_srcdir)/misc_helpers -s $(atf_get_srcdir)" + atf_check -s eq:1 -o ignore -e ignore ${h} tc_missing_body +} + +atf_init_test_cases() +{ + atf_add_test_case default_status + atf_add_test_case missing_body +} + +# vim: syntax=sh:expandtab:shiftwidth=4:softtabstop=4 diff --git a/external/bsd/atf/dist/atf-sh/tp_test.sh b/external/bsd/atf/dist/atf-sh/tp_test.sh new file mode 100644 index 000000000..c159813d5 --- /dev/null +++ b/external/bsd/atf/dist/atf-sh/tp_test.sh @@ -0,0 +1,56 @@ +# +# Automated Testing Framework (atf) +# +# Copyright (c) 2007 The NetBSD Foundation, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +# CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +atf_test_case srcdir +srcdir_head() +{ + atf_set "descr" "Verifies that the source directory can be queried" \ + "from the initialization function" +} +srcdir_body() +{ + mkdir work + atf_check -s eq:0 -o empty -e empty cp "$(atf_get_srcdir)/misc_helpers" work + cat >work/subrs < +#include + +#include "atf-c++/detail/application.hpp" +#include "atf-c++/detail/ui.hpp" + +#include "revision.h" + +class atf_version : public atf::application::app { + static const char* m_description; + +public: + atf_version(void); + + int main(void); +}; + +const char* atf_version::m_description = + "atf-version is a tool that shows information about the currently " + "installed version of ATF."; + +atf_version::atf_version(void) : + app(m_description, "atf-version(1)", "atf(7)") +{ +} + +int +atf_version::main(void) +{ + using atf::ui::format_text; + using atf::ui::format_text_with_tag; + + std::cout << PACKAGE_STRING " (" PACKAGE_TARNAME "-" PACKAGE_VERSION + ")\n" PACKAGE_COPYRIGHT "\n\n"; + +#if defined(PACKAGE_REVISION_TYPE_DIST) + std::cout << format_text("Built from a distribution file; no revision " + "information available.") << "\n"; +#elif defined(PACKAGE_REVISION_TYPE_GIT) + std::cout << format_text_with_tag(PACKAGE_REVISION_BRANCH, "Branch: ", + false) << "\n"; + std::cout << format_text_with_tag(PACKAGE_REVISION_BASE +# if PACKAGE_REVISION_MODIFIED + " (locally modified)" +# endif + " " PACKAGE_REVISION_DATE, + "Base revision: ", false) << "\n"; +#else +# error "Unknown PACKAGE_REVISION_TYPE value" +#endif + + return EXIT_SUCCESS; +} + +int +main(int argc, char* const* argv) +{ + return atf_version().run(argc, argv); +} diff --git a/external/bsd/atf/dist/atf-version/generate-revision.sh b/external/bsd/atf/dist/atf-version/generate-revision.sh new file mode 100644 index 000000000..169be85f9 --- /dev/null +++ b/external/bsd/atf/dist/atf-version/generate-revision.sh @@ -0,0 +1,142 @@ +#! /bin/sh +# +# Automated Testing Framework (atf) +# +# Copyright (c) 2007 The NetBSD Foundation, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +# CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# +# Generates a header file with information about the revision used to +# build ATF. +# + +set -e + +Prog_Name=${0##*/} + +GIT= +ROOT= + +# +# err message +# +err() { + echo "${Prog_Name}: ${@}" 1>&2 + exit 1 +} + +# +# call_git args +# +call_git() { + ( cd "${ROOT}" && "${GIT}" "${@}" ) +} + +# +# generate_from_dist revfile version +# +generate_from_dist() { + revfile=${1}; shift + version=${1}; shift + + >${revfile} + + echo "#define PACKAGE_REVISION_TYPE_DIST" >>${revfile} +} + +# +# generate_from_git revfile +# +generate_from_git() { + revfile=${1} + + rev_base_id=$(call_git rev-parse HEAD) + rev_branch=$(call_git branch | grep '^\* ' | cut -d ' ' -f 2-) + rev_date=$(call_git log -1 | grep '^Date:' | sed -e 's,^Date:[ \t]*,,') + if [ -z "$(call_git status -s)" ]; then + rev_modified=false + else + rev_modified=true + fi + + >${revfile} + + echo "#define PACKAGE_REVISION_TYPE_GIT" >>${revfile} + + echo "#define PACKAGE_REVISION_BRANCH \"${rev_branch}\"" >>${revfile} + echo "#define PACKAGE_REVISION_BASE \"${rev_base_id}\"" >>${revfile} + + if [ ${rev_modified} = true ]; then + echo "#define PACKAGE_REVISION_MODIFIED 1" >>${revfile} + fi + + echo "#define PACKAGE_REVISION_DATE \"${rev_date}\"" >>${revfile} +} + +# +# main +# +# Entry point. +# +main() { + outfile= + version= + while getopts :g:r:o:v: arg; do + case ${arg} in + g) + GIT=${OPTARG} + ;; + o) + outfile=${OPTARG} + ;; + r) + ROOT=${OPTARG} + ;; + v) + version=${OPTARG} + ;; + *) + err "Unknown option ${arg}" + ;; + esac + done + [ -n "${ROOT}" ] || \ + err "Must specify the top-level source directory with -r" + [ -n "${outfile}" ] || \ + err "Must specify an output file with -o" + [ -n "${version}" ] || \ + err "Must specify a version number with -v" + + if [ -n "${GIT}" -a -d ${ROOT}/.git ]; then + generate_from_git ${outfile} + else + generate_from_dist ${outfile} ${version} + fi +} + +main "${@}" + +# vim: syntax=sh:expandtab:shiftwidth=4:softtabstop=4 diff --git a/external/bsd/atf/dist/doc/atf-formats.5 b/external/bsd/atf/dist/doc/atf-formats.5 new file mode 100644 index 000000000..bb919f483 --- /dev/null +++ b/external/bsd/atf/dist/doc/atf-formats.5 @@ -0,0 +1,231 @@ +.\" +.\" Automated Testing Framework (atf) +.\" +.\" Copyright (c) 2007 The NetBSD Foundation, Inc. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +.\" CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +.\" IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +.\" GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +.\" IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.Dd December 20, 2011 +.Dt ATF-FORMATS 5 +.Os +.Sh NAME +.Nm atf-formats +.Nd machine-parseable data formats used by ATF +.Sh DESCRIPTION +This manual page describes the multiple data formats used in ATF. +These formats affect configuration files, control files and any data that +is externalized or internalized by the tools. +.Pp +Data files are always organized as follows: +.Bd -literal -offset indent +Header1: Value1 \\ + ... | head +HeaderN: ValueN / + mandatory blank line +Free-form text contents \\ + ... | body + ... / +.Ed +.Pp +A file must always contain a +.Sq Content-Type +header and must always separate that header from the body with a blank +line, even if the body is empty. +.Pp +The +.Sq Content-Type +is always of the form: +.Bd -literal -offset indent +Content-Type: application/X-atf-; version="" +.Ed +.Pp +where +.Sq subtype +indicates the specific file format and +.Sq version +its format version. +This header must be the first one of the file. +.Pp +The main purpose of the +.Sq Content-Type +header, aside from determining the format used in the file, is to allow +future changes to a given format. +Whenever an incompatible change is made, the version is bumped by one. +By keeping the header in the first line, future versions may even remove +the need for such a header -- e.g. if some format was replaced by XML +files, which have their own mandatory header. +.Pp +The rest of this document details the different format types. +.Ss Format: application/X-atf-atffile, version: 1 +Atffiles are logically divided into three sections: +.Bl -bullet +.It +Test programs: the list of test programs that define the test suite +described by the Atffile. +.It +Meta-data properties: these define some constant values applicable to +all the test programs defined in the file. +In some sense they define the properties that describe the test suite. +.It +Configuration variables: defaults for configuration variables that +can be overridden through configuration files or the command line. +.El +.Pp +The grammar for Atffiles is the following: +.Bd -literal -offset indent +DATA ::= ( ( CONF | PROP | TP )? COMMENT? NEWLINE )* EOF +CONF ::= 'conf:' WORD EQUAL STRING +PROP ::= 'prop:' WORD EQUAL STRING +TP ::= TPFILE | TPGLOB +TPFILE ::= 'tp: ' STRING +TPGLOB ::= 'tp-glob: ' STRING +STRING ::= WORD | '"' WORD* '"' +.Ed +.Pp +The meaning of the constructions above is: +.Bl -tag -width TPGLOBXX +.It CONF +Definition of a configuration variable. +.It PROP +Definition of a meta-data property. +.It TPFILE +Addition of a test program into the test suite. +The string is taken literally as the program's name, and this program +must exist. +.It TPGLOB +Addition of multiple test programs into the test suite. +The string is taken as a glob pattern, which may have or not have any +matches in the current directory. +.El +.Pp +An example: +.Bd -literal -offset indent +prop: test-suite = utilities + +conf: unprivileged-user = nobody + +tp: t_cp +tp: t_mv +tp: t_df +tp-glob: t_dir_* +.Ed +.Ss Format: application/X-atf-config, version: 1 +Configuration files are very simple: they only contain a list of variable +name/variable value pairs. +Their grammar is: +.Bd -literal -offset indent +DATA ::= ( VAR? COMMENT? NEWLINE )* EOF +VAR ::= WORD EQUAL STRING +COMMENT ::= HASH WORD* +STRING ::= WORD | '"' WORD* '"' +.Ed +.Pp +An example: +.Bd -literal -offset indent +# This is the system-wide configuration file for ATF. +# The above and this line are comments placed on their own line. + +var1 = this is a variable value +var2 = this is another one # Optional comment at the end. +.Ed +.Ss Format: application/X-atf-tps, version: 3 +The +.Sq application/X-atf-tps +format multiplexes the standard output, standard error and results output +streams from multiple test programs into a single data file. +This format is used by +.Xr atf-run 1 +to report the execution of several test programs and is later parsed by +.Xr atf-report 1 +to inform the user of this process. +It has the following grammar: +.Bd -literal -offset indent +DATA ::= INFO* TPS-COUNT TP-STANZA* INFO* EOF +INFO ::= 'info' COLON STRING COMMA STRING NEWLINE +TPS-COUNT ::= 'tps-count' COLON POSITIVE-NUMBER NEWLINE +TP-STANZA ::= TP-START TC-STANZA* TC-END +TP-START ::= 'tp-start' COLON TIMESTAMP COMMA STRING COMMA + POSITIVE-NUMBER NEWLINE +TP-END ::= 'tc-end' COLON TIMESTAMP COMMA STRING (COMMA STRING)? +TC-STANZA ::= TC-START (TC-SO | TC-SE)* TC-END +TC-START ::= 'tc-start' COLON TIMESTAMP COMMA STRING NEWLINE +TC-SO ::= 'tc-so' COLON STRING NEWLINE +TC-SE ::= 'tc-se' COLON STRING NEWLINE +TC-END ::= 'tc-end' COLON TIMESTAMP COMMA STRING COMMA TCR NEWLINE +TCR ::= 'passed' | ('failed' | 'skipped') COMMA STRING +TIMESTAMP ::= [0-9]+.[0-9]+ +.Ed +.Pp +The meaning of the constructions above is: +.Bl -tag -width TPSXCOUNTXX +.It TPS-COUNT +Indicates the number of test programs that will be executed. +There will be this exact amount of +.Sq TP-STANZA +constructions following it. +.It TP-START +Indicates the beginning of a test program. +This includes the program's name and the amount of test cases that +will follow. +.It TP-END +Indicates the completion of a test program. +This is followed by the program's name and, if the program ended +prematurely, an error message indicating the reason of its failure. +A successful execution of a test program (regardless of the status of its +test cases) must not be accompanied by any reason. +.It TC-START +Indicates the beginning of a test case. +This is accompanied by the test case's name. +.It TC-SO +Contains a text line sent to the standard output stream during the +execution of the test case. +Leading and trailing space is preserved. +.It TC-SE +Contains a text line sent to the standard error stream during the +execution of the test case. +Leading and trailing space is preserved. +.It TC-END +Indicates the completion of a test case. +This is accompanied by the test case's name, its result and the reason +associated with this result (if applicable). +.El +.Pp +An example: +.Bd -literal -offset indent +tps-count: 2 +tp-start: calculator, 1324318951.838923, 2 +tc-start: add, 1324318951.839101 +tc-end: add, 1324318951.839500, passed +tc-start: subtract, 1324318951.840001 +tc-so: 3-2 expected to return 1 but got 0 +tc-end: subtract, 1324318952.000123, failed, Calculated an unexpected value +tp-end: calculator, 1324318952.002301 +tp-start: files, 1, 1324318952.502348 +tc-start: copy, 1324318952.508291 +tc-se: could not find the cp(1) utility +tc-end: copy, 1324318953.203145, skipped +tp-end: files, 1324318953.203800 +.Ed +.Sh SEE ALSO +.Xr atf 7 diff --git a/external/bsd/atf/dist/doc/atf-test-case.4 b/external/bsd/atf/dist/doc/atf-test-case.4 new file mode 100644 index 000000000..e1b2bf45c --- /dev/null +++ b/external/bsd/atf/dist/doc/atf-test-case.4 @@ -0,0 +1,319 @@ +.\" +.\" Automated Testing Framework (atf) +.\" +.\" Copyright (c) 2007 The NetBSD Foundation, Inc. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +.\" CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +.\" IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +.\" GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +.\" IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.Dd January 13, 2011 +.Dt ATF-TEST-CASE 4 +.Os +.Sh NAME +.Nm atf-test-case +.Nd generic description of test cases +.Sh DESCRIPTION +A +.Em test case +is a piece of code that stress-tests a specific feature of the software. +This feature is typically self-contained enough, either in the amount of +code that implements it or in the general idea that describes it, to +warrant its independent testing. +Given this, test cases are very fine-grained, but they attempt to group +similar smaller tests which are semantically related. +.Pp +A test case is defined by three components regardless of the language it is +implemented in: a header, a body and a cleanup routine. +The +.Em header +is, basically, a declarative piece of code that defines several +properties to describe what the test case does and how it behaves. +In other words: it defines the test case's +.Em meta-data , +further described in the +.Sx Meta-data +section. +The +.Em body +is the test case itself. +It executes all actions needed to reproduce the test, and checks for +failures. +This body is only executed if the abstract conditions specified by the +header are met. +The +.Em cleanup +routine is a piece of code always executed after the body, regardless of +the exit status of the test case. +It can be used to undo side-effects of the test case. +Note that almost all side-effects of a test case are automatically cleaned +up by the library; this is explained in more detail in the rest of this +document. +.Pp +It is extremely important to keep the separation between a test case's +header and body well-defined, because the header is +.Em always +parsed, whereas the body is only executed when the conditions defined in +the header are met and when the user specifies that test case. +.Pp +At last, test cases are always contained into test programs. +The test programs act as a front-end to them, providing a consistent +interface to the user and several APIs to ease their implementation. +.Ss Results +Upon termination, a test case reports a status and, optionally, a textual +reason describing why the test reported such status. +The caller must ensure that the test case really performed the task that its +status describes, as the test program may be bogus and therefore providing a +misleading result (e.g. providing a result that indicates success but the +error code of the program says otherwise). +.Pp +The possible exit status of a test case are one of the following: +.Bl -tag -width expectedXfailureXX +.It expected_death +The test case expects to terminate abruptly. +.It expected_exit +The test case expects to exit cleanly. +.It expected_failure +The test case expects to exit with a controller fatal/non-fatal failure. +If this happens, the test program exits with a success error code. +.It expected_signal +The test case expects to receive a signal that makes it terminate. +.It expected_timeout +The test case expects to execute for longer than its timeout. +.It passed +The test case was executed successfully. +The test program exits with a success error code. +.It skipped +The test case could not be executed because some preconditions were not +met. +This is not a failure because it can typically be resolved by adjusting +the system to meet the necessary conditions. +This is always accompanied by a +.Em reason , +a message describing why the test was skipped. +The test program exits with a success error code. +.It failed +An error appeared during the execution of the test case. +This is always accompanied by a +.Em reason , +a message describing why the test failed. +The test program exits with a failure error code. +.El +.Pp +The usefulness of the +.Sq expected_* +results comes when writing test cases that verify known failures caused, +in general, due to programming errors (aka bugs). +Whenever the faulty condition that the expectation is trying to convery is +fixed, then the test case will be reported as +.Sq failed +and the developer will have to adjust it to match its new condition. +.Pp +It is important to note that all +.Sq expected_* +results are only provided as a +.Em hint +to the caller; the caller must verify that the test case did actually terminate +as the expected condition says. +.Ss Input/output +Test cases are free to print whatever they want to their +.Xr stdout 4 +and +.Xr stderr 4 +file descriptors. +They are, in fact, encouraged to print status information as they execute +to keep the user informed of their actions. +This is specially important for long test cases. +.Pp +Test cases will log their results to an auxiliary file, which is then +collected by the test program they are contained in. +The developer need not care about this as long as he uses the correct +APIs to implement the test cases. +.Pp +The standard input of the test cases is unconditionally connected to +.Sq /dev/zero . +.Ss Meta-data +The following list describes all meta-data properties interpreted +internally by ATF. +You are free to define new properties in your test cases and use them as +you wish, but non-standard properties must be prefixed by +.Sq X- . +.Bl -tag -width requireXmachineXX +.It descr +Type: textual. +Required. +.Pp +A brief textual description of the test case's purpose. +Will be shown to the user in reports. +Also good for documentation purposes. +.It has.cleanup +Type: boolean. +Optional. +.Pp +If set to true, specifies that the test case has a cleanup routine that has +to be executed by +.Xr atf-run 1 +during the cleanup phase of the execution. +This property is automatically set by the framework when defining a test case +with a cleanup routine, so it should never be set by hand. +.It ident +Type: textual. +Required. +.Pp +The test case's identifier. +Must be unique inside the test program and should be short but descriptive. +.It require.arch +Type: textual. +Optional. +.Pp +A whitespace separated list of architectures that the test case can be run +under without causing errors due to an architecture mismatch. +.It require.config +Type: textual. +Optional. +.Pp +A whitespace separated list of configuration variables that must be defined +to execute the test case. +If any of the required variables is not defined, the test case is +.Em skipped . +.It require.files +Type: textual. +Optional. +.Pp +A whitespace separated list of files that must be present to execute the +test case. +The names of these files must be absolute paths. +If any of the required files is not found, the test case is +.Em skipped . +.It require.machine +Type: textual. +Optional. +.Pp +A whitespace separated list of machine types that the test case can be run +under without causing errors due to a machine type mismatch. +.It require.memory +Type: integer. +Optional. +Specifies the minimum amount of physical memory needed by the test. +The value can have a size suffix such as +.Sq K , +.Sq M , +.Sq G +or +.Sq T +to make the amount of bytes easier to type and read. +.It require.progs +Type: textual. +Optional. +.Pp +A whitespace separated list of programs that must be present to execute +the test case. +These can be given as plain names, in which case they are looked in the +user's +.Ev PATH , +or as absolute paths. +If any of the required programs is not found, the test case is +.Em skipped . +.It require.user +Type: textual. +Optional. +.Pp +The required privileges to execute the test case. +Can be one of +.Sq root +or +.Sq unprivileged . +.Pp +If the test case is running as a regular user and this property is +.Sq root , +the test case is +.Em skipped . +.Pp +If the test case is running as root and this property is +.Sq unprivileged , +.Xr atf-run 1 +will automatically drop the privileges if the +.Sq unprivileged-user +configuration property is set; otherwise the test case is +.Em skipped . +.It timeout +Type: integral. +Optional; defaults to +.Sq 300 . +.Pp +Specifies the maximum amount of time the test case can run. +This is particularly useful because some tests can stall either because they +are incorrectly coded or because they trigger an anomalous behavior of the +program. +It is not acceptable for these tests to stall the whole execution of the +test program. +.Pp +Can optionally be set to zero, in which case the test case has no run-time +limit. +This is discouraged. +.El +.Ss Environment +Every time a test case is executed, several environment variables are +cleared or reseted to sane values to ensure they do not make the test fail +due to unexpected conditions. +These variables are: +.Bl -tag -width LCXMESSAGESXX +.It Ev HOME +Set to the work directory's path. +.It Ev LANG +Undefined. +.It Ev LC_ALL +Undefined. +.It Ev LC_COLLATE +Undefined. +.It Ev LC_CTYPE +Undefined. +.It Ev LC_MESSAGES +Undefined. +.It Ev LC_MONETARY +Undefined. +.It Ev LC_NUMERIC +Undefined. +.It Ev LC_TIME +Undefined. +.It Ev TZ +Hardcoded to +.Sq UTC . +.El +.Ss Work directories +The test program always creates a temporary directory +and switches to it before running the test case's body. +This way the test case is free to modify its current directory as it +wishes, and the runtime engine will be able to clean it up later on in a +safe way, removing any traces of its execution from the system. +To do so, the runtime engine will perform a recursive removal of the work +directory without crossing mount points; if a mount point is found, the +file system will be unmounted (if possible). +.Ss File creation mode mask (umask) +Test cases are always executed with a file creation mode mask (umask) of +.Sq 0022 . +The test case's code is free to change this during execution. +.Sh SEE ALSO +.Xr atf-run 1 , +.Xr atf-test-program 1 , +.Xr atf-formats 5 , +.Xr atf 7 diff --git a/external/bsd/atf/dist/doc/atf-test-program.1 b/external/bsd/atf/dist/doc/atf-test-program.1 new file mode 100644 index 000000000..49ee12ddf --- /dev/null +++ b/external/bsd/atf/dist/doc/atf-test-program.1 @@ -0,0 +1,103 @@ +.\" +.\" Automated Testing Framework (atf) +.\" +.\" Copyright (c) 2007 The NetBSD Foundation, Inc. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +.\" CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +.\" IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +.\" GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +.\" IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.Dd February 6, 2011 +.Dt ATF-TEST-PROGRAM 1 +.Os +.Sh NAME +.Nm atf-test-program +.Nd common interface to ATF test programs +.Sh SYNOPSIS +.Nm +.Op Fl r Ar resfile +.Op Fl s Ar srcdir +.Op Fl v Ar var1=value1 Op .. Fl v Ar varN=valueN +.Ar test_case +.Nm +.Fl l +.Sh DESCRIPTION +Test programs written using the ATF libraries all share a common user +interface, which is what this manual page describes. +.Em NOTE: There is no binary known as +.Nm ; +.Em what is described in this manual page is the command-line interface +.Em exposed by the atf-c, atf-c++ and atf-sh bindings . +.Pp +In the first synopsis form, the test program will execute the provided +test case and print its results to the standard output, unless otherwise +stated by the +.Fl r +flag. +Optionally, the test case name can be suffixed by +.Sq :cleanup , +in which case the cleanup routine of the test case will be executed +instead of the test case body; see +.Xr atf-test-case 4 . +Note that the test case is +.Em executed without isolation , +so it can and probably will create and modify files in the current directory. +To execute test cases in a controller manner, refer to +.Xr atf-run 1 , +which is the preferred way to run test cases. +You should only execute test cases by hand for debugging purposes. +.Pp +In the second synopsis form, the test program will list all available +test cases alongside their meta-data properties in a format that is +machine parseable. +This list is processed by +.Xr atf-run 1 +to know how to execute the test cases of a given test program. +.Pp +The following options are available: +.Bl -tag -width XvXvarXvalueXX +.It Fl l +Lists available test cases alongside a brief description for each of them. +.It Fl r Ar resfile +Specifies the file that will receive the test case result. +If not specified, the test case prints its results to stdout. +If the result of a test case needs to be parsed by another program, you must +use this option to redirect the result to a file and then read the resulting +file from the other program. +Note: +.Em do not try to process the stdout of the test case +because your program may break in the future. +.It Fl s Ar srcdir +The path to the directory where the test program is located. +This is needed in all cases, except when the test program is being executed +from the current directory. +The test program will use this path to locate any helper data files or +utilities. +.It Fl v Ar var=value +Sets the configuration variable +.Ar var +to the value +.Ar value . +.El +.Sh SEE ALSO +.Xr atf-run 1 , +.Xr atf 7 diff --git a/external/bsd/atf/dist/doc/atf.7.in b/external/bsd/atf/dist/doc/atf.7.in new file mode 100644 index 000000000..5fcca44df --- /dev/null +++ b/external/bsd/atf/dist/doc/atf.7.in @@ -0,0 +1,192 @@ +.\" +.\" Automated Testing Framework (atf) +.\" +.\" Copyright (c) 2007 The NetBSD Foundation, Inc. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +.\" CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +.\" IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +.\" GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +.\" IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.Dd August 28, 2010 +.Dt ATF 7 +.Os +.Sh NAME +.Nm ATF +.Nd introduction to the Automated Testing Framework +.Sh DESCRIPTION +.Em IMPORTANT: If you are here because you want to know how to run the tests in +.Em Pa __TESTSDIR__ , +.Em you most likely want to read the +.Em Xr tests 7 +.Em manual page instead. +.Pp +The Automated Testing Framework +.Pf ( Nm ) +is a collection of libraries and utilities designed to ease unattended +application testing in the hands of developers and end users of a specific +piece of software. +.Pp +As regards developers, +.Nm +provides the necessary means to easily create +test suites composed of multiple test programs, which in turn are a +collection of test cases. +It also attempts to simplify the debugging of problems when these test +cases detect an error by providing as much information as possible +about the failure. +.Pp +As regards users, it simplifies the process of running the test suites and, +in special, encourages end users to run them often: they do not need to +have source trees around nor any other development tools installed to be +able to certify that a given piece of software works on their machine as +advertised. +.Pp +If your operating systems distributes +.Nm , +it is possible that it provides an introductory +.Xr tests 7 +manual page. +You are encouraged to read it now. +.Ss License +.Nm +is distributed under the terms of the TNF License, a 2-clause BSD license. +For more details please see: +.Bd -literal -offset indent +.Pa __DOCDIR__/COPYING +.Ed +.Ss Components +.Nm +is a highly modular piece of software. +It provides a couple of libraries to ease the implementation of test +programs: one for the C and C++ languages and another one for shell +scripts. +It also includes multiple small utilities that follow the principle of +doing a single thing but doing it right. +This section outlines which these components are. +.Pp +Public utilities: +.Bl -tag -width atfXtestXprogramXXXXX +.It Xr atf-check 1 +Executes a command and checks that its exit code, its standard output +and its standard error output match pre-specified expected values. +.It Xr atf-config 1 +Queries static configuration information. +.It Xr atf-report 1 +Converts the output of +.Nm atf-run +to user-friendly and/or machine-parseable reports. +.It Xr atf-run 1 +Automates the execution of a series of test programs and collects their +results in a unified report. +.It Xr atf-sh 1 +Shell interpreter for shell-based test programs. +.El +.Pp +Programming interfaces: +.Bl -tag -width atfXtestXprogramXXXXX +.It Xr atf-c-api 3 +C programming interface for test programs. +.It Xr atf-c++-api 3 +C++ programming interface for test programs. +.It Xr atf-sh-api 3 +POSIX shell programming interface for test programs. +.El +.Pp +Other: +.Bl -tag -width atfXtestXprogramXXXXX +.It Xr atf-formats 5 +Description of the machine-parseable data formats used by the tools. +.It Xr atf-test-case 4 +Generic description of test cases, independent of the language they are +implemented in. +.It Xr atf-test-program 1 +Common interface provided by the test programs written using the +.Nm +libraries. +.El +.Ss Recommended reading order +For end users wishing to run tests: +.Bl -enum -compact +.It +.Xr tests 7 +(only if provided by your operating system). +.It +.Xr atf-test-program 1 +.It +.Xr atf-run 1 +.It +.Xr atf-report 1 +.It +.Xr atf-config 1 +.El +.Pp +For developers wanting to write their own tests: +.Bl -enum -compact +.It +Everything recommended to users. +.It +.Xr atf-test-case 4 +.It +.Xr atf-c-api 3 +.It +.Xr atf-c++-api 3 +.It +.Xr atf-sh-api 3 +.It +.Xr atf-sh 1 +.It +.Xr atf-check 1 +.El +.Pp +For those interested in +.Nm +internals: +.Bl -enum -compact +.It +Everything recommended to users. +.It +Everything recommended to developers. +.It +.Xr atf-formats 5 +.El +.Sh SEE ALSO +.Xr tests 7 +.Sh HISTORY +.Nm +started as a Google Summer of Code 2007 project mentored by The NetBSD +Foundation. +Its original goal was to provide a testing framework for The NetBSD +Operating System, but it grew as an independent project because the +framework itself did not need to be tied to a specific operating system. +.Pp +For more details on this subject, please see: +.Bd -literal -offset indent +.Pa __DOCDIR__/NEWS +.Pa __DOCDIR__/ROADMAP +.Ed +.Sh AUTHORS +For more details on the people that made +.Nm +possible, please see: +.Bd -literal -offset indent +.Pa __DOCDIR__/AUTHORS +.Ed diff --git a/external/bsd/atf/dist/test-programs/Atffile b/external/bsd/atf/dist/test-programs/Atffile new file mode 100644 index 000000000..6a67a8ffb --- /dev/null +++ b/external/bsd/atf/dist/test-programs/Atffile @@ -0,0 +1,9 @@ +Content-Type: application/X-atf-atffile; version="1" + +prop: test-suite = atf + +tp: config_test +tp: expect_test +tp: meta_data_test +tp: srcdir_test +tp: result_test diff --git a/external/bsd/atf/dist/test-programs/Kyuafile b/external/bsd/atf/dist/test-programs/Kyuafile new file mode 100644 index 000000000..e5252829e --- /dev/null +++ b/external/bsd/atf/dist/test-programs/Kyuafile @@ -0,0 +1,9 @@ +syntax("kyuafile", 1) + +test_suite("atf") + +atf_test_program{name="config_test"} +atf_test_program{name="expect_test"} +atf_test_program{name="meta_data_test"} +atf_test_program{name="srcdir_test"} +atf_test_program{name="result_test"} diff --git a/external/bsd/atf/dist/test-programs/c_helpers.c b/external/bsd/atf/dist/test-programs/c_helpers.c new file mode 100644 index 000000000..ac9bcc336 --- /dev/null +++ b/external/bsd/atf/dist/test-programs/c_helpers.c @@ -0,0 +1,508 @@ +/* + * Automated Testing Framework (atf) + * + * Copyright (c) 2007 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "atf-c/error.h" + +#include "atf-c/detail/env.h" +#include "atf-c/detail/fs.h" +#include "atf-c/detail/test_helpers.h" +#include "atf-c/detail/text.h" + +/* --------------------------------------------------------------------- + * Auxiliary functions. + * --------------------------------------------------------------------- */ + +static +void +safe_remove(const char* path) +{ + if (unlink(path) == -1) + atf_tc_fail("unlink(2) of %s failed", path); +} + +static +void +touch(const char *path) +{ + int fd; + fd = open(path, O_WRONLY | O_TRUNC | O_CREAT, 0644); + if (fd == -1) + atf_tc_fail("Could not create file %s", path); + close(fd); +} + +/* --------------------------------------------------------------------- + * Helper tests for "t_cleanup". + * --------------------------------------------------------------------- */ + +ATF_TC_WITH_CLEANUP(cleanup_pass); +ATF_TC_HEAD(cleanup_pass, tc) +{ + atf_tc_set_md_var(tc, "descr", "Helper test case for the t_cleanup test " + "program"); +} +ATF_TC_BODY(cleanup_pass, tc) +{ + touch(atf_tc_get_config_var(tc, "tmpfile")); +} +ATF_TC_CLEANUP(cleanup_pass, tc) +{ + if (atf_tc_get_config_var_as_bool(tc, "cleanup")) + safe_remove(atf_tc_get_config_var(tc, "tmpfile")); +} + +ATF_TC_WITH_CLEANUP(cleanup_fail); +ATF_TC_HEAD(cleanup_fail, tc) +{ + atf_tc_set_md_var(tc, "descr", "Helper test case for the t_cleanup test " + "program"); +} +ATF_TC_BODY(cleanup_fail, tc) +{ + touch(atf_tc_get_config_var(tc, "tmpfile")); + atf_tc_fail("On purpose"); +} +ATF_TC_CLEANUP(cleanup_fail, tc) +{ + if (atf_tc_get_config_var_as_bool(tc, "cleanup")) + safe_remove(atf_tc_get_config_var(tc, "tmpfile")); +} + +ATF_TC_WITH_CLEANUP(cleanup_skip); +ATF_TC_HEAD(cleanup_skip, tc) +{ + atf_tc_set_md_var(tc, "descr", "Helper test case for the t_cleanup test " + "program"); +} +ATF_TC_BODY(cleanup_skip, tc) +{ + touch(atf_tc_get_config_var(tc, "tmpfile")); + atf_tc_skip("On purpose"); +} +ATF_TC_CLEANUP(cleanup_skip, tc) +{ + if (atf_tc_get_config_var_as_bool(tc, "cleanup")) + safe_remove(atf_tc_get_config_var(tc, "tmpfile")); +} + +ATF_TC_WITH_CLEANUP(cleanup_curdir); +ATF_TC_HEAD(cleanup_curdir, tc) +{ + atf_tc_set_md_var(tc, "descr", "Helper test case for the t_cleanup test " + "program"); +} +ATF_TC_BODY(cleanup_curdir, tc) +{ + FILE *f; + + f = fopen("oldvalue", "w"); + if (f == NULL) + atf_tc_fail("Failed to create oldvalue file"); + fprintf(f, "1234"); + fclose(f); +} +ATF_TC_CLEANUP(cleanup_curdir, tc) +{ + FILE *f; + + f = fopen("oldvalue", "r"); + if (f != NULL) { + int i; + if (fscanf(f, "%d", &i) != 1) + fprintf(stderr, "Failed to read old value\n"); + else + printf("Old value: %d", i); + fclose(f); + } +} + +ATF_TC_WITH_CLEANUP(cleanup_sigterm); +ATF_TC_HEAD(cleanup_sigterm, tc) +{ + atf_tc_set_md_var(tc, "descr", "Helper test case for the t_cleanup test " + "program"); +} +ATF_TC_BODY(cleanup_sigterm, tc) +{ + char *nofile; + + touch(atf_tc_get_config_var(tc, "tmpfile")); + kill(getpid(), SIGTERM); + + RE(atf_text_format(&nofile, "%s.no", + atf_tc_get_config_var(tc, "tmpfile"))); + touch(nofile); + free(nofile); +} +ATF_TC_CLEANUP(cleanup_sigterm, tc) +{ + safe_remove(atf_tc_get_config_var(tc, "tmpfile")); +} + +/* --------------------------------------------------------------------- + * Helper tests for "t_config". + * --------------------------------------------------------------------- */ + +ATF_TC(config_unset); +ATF_TC_HEAD(config_unset, tc) +{ + atf_tc_set_md_var(tc, "descr", "Helper test case for the t_config test " + "program"); +} +ATF_TC_BODY(config_unset, tc) +{ + ATF_REQUIRE(!atf_tc_has_config_var(tc, "test")); +} + +ATF_TC(config_empty); +ATF_TC_HEAD(config_empty, tc) +{ + atf_tc_set_md_var(tc, "descr", "Helper test case for the t_config test " + "program"); +} +ATF_TC_BODY(config_empty, tc) +{ + ATF_REQUIRE(atf_tc_has_config_var(tc, "test")); + ATF_REQUIRE(strlen(atf_tc_get_config_var(tc, "test")) == 0); +} + +ATF_TC(config_value); +ATF_TC_HEAD(config_value, tc) +{ + atf_tc_set_md_var(tc, "descr", "Helper test case for the t_config test " + "program"); +} +ATF_TC_BODY(config_value, tc) +{ + ATF_REQUIRE(atf_tc_has_config_var(tc, "test")); + ATF_REQUIRE(strcmp(atf_tc_get_config_var(tc, "test"), "foo") == 0); +} + +ATF_TC(config_multi_value); +ATF_TC_HEAD(config_multi_value, tc) +{ + atf_tc_set_md_var(tc, "descr", "Helper test case for the t_config test " + "program"); +} +ATF_TC_BODY(config_multi_value, tc) +{ + ATF_REQUIRE(atf_tc_has_config_var(tc, "test")); + ATF_REQUIRE(strcmp(atf_tc_get_config_var(tc, "test"), "foo bar") == 0); +} + +/* --------------------------------------------------------------------- + * Helper tests for "t_expect". + * --------------------------------------------------------------------- */ + +ATF_TC_WITHOUT_HEAD(expect_pass_and_pass); +ATF_TC_BODY(expect_pass_and_pass, tc) +{ + atf_tc_expect_pass(); + +} + +ATF_TC_WITHOUT_HEAD(expect_pass_but_fail_requirement); +ATF_TC_BODY(expect_pass_but_fail_requirement, tc) +{ + atf_tc_expect_pass(); + atf_tc_fail("Some reason"); +} + +ATF_TC_WITHOUT_HEAD(expect_pass_but_fail_check); +ATF_TC_BODY(expect_pass_but_fail_check, tc) +{ + atf_tc_expect_pass(); + atf_tc_fail_nonfatal("Some reason"); +} + +ATF_TC_WITHOUT_HEAD(expect_fail_and_fail_requirement); +ATF_TC_BODY(expect_fail_and_fail_requirement, tc) +{ + atf_tc_expect_fail("Fail %s", "reason"); + atf_tc_fail("The failure"); + atf_tc_expect_pass(); +} + +ATF_TC_WITHOUT_HEAD(expect_fail_and_fail_check); +ATF_TC_BODY(expect_fail_and_fail_check, tc) +{ + atf_tc_expect_fail("Fail first"); + atf_tc_fail_nonfatal("abc"); + atf_tc_expect_pass(); + + atf_tc_expect_fail("And fail again"); + atf_tc_fail_nonfatal("def"); + atf_tc_expect_pass(); +} + +ATF_TC_WITHOUT_HEAD(expect_fail_but_pass); +ATF_TC_BODY(expect_fail_but_pass, tc) +{ + atf_tc_expect_fail("Fail first"); + atf_tc_fail_nonfatal("abc"); + atf_tc_expect_pass(); + + atf_tc_expect_fail("Will not fail"); + atf_tc_expect_pass(); + + atf_tc_expect_fail("And fail again"); + atf_tc_fail_nonfatal("def"); + atf_tc_expect_pass(); +} + +ATF_TC_WITHOUT_HEAD(expect_exit_any_and_exit); +ATF_TC_BODY(expect_exit_any_and_exit, tc) +{ + atf_tc_expect_exit(-1, "Call will exit"); + exit(EXIT_SUCCESS); +} + +ATF_TC_WITHOUT_HEAD(expect_exit_code_and_exit); +ATF_TC_BODY(expect_exit_code_and_exit, tc) +{ + atf_tc_expect_exit(123, "Call will exit"); + exit(123); +} + +ATF_TC_WITHOUT_HEAD(expect_exit_but_pass); +ATF_TC_BODY(expect_exit_but_pass, tc) +{ + atf_tc_expect_exit(-1, "Call won't exit"); +} + +ATF_TC_WITHOUT_HEAD(expect_signal_any_and_signal); +ATF_TC_BODY(expect_signal_any_and_signal, tc) +{ + atf_tc_expect_signal(-1, "Call will signal"); + kill(getpid(), SIGKILL); +} + +ATF_TC_WITHOUT_HEAD(expect_signal_no_and_signal); +ATF_TC_BODY(expect_signal_no_and_signal, tc) +{ + atf_tc_expect_signal(SIGHUP, "Call will signal"); + kill(getpid(), SIGHUP); +} + +ATF_TC_WITHOUT_HEAD(expect_signal_but_pass); +ATF_TC_BODY(expect_signal_but_pass, tc) +{ + atf_tc_expect_signal(-1, "Call won't signal"); +} + +ATF_TC_WITHOUT_HEAD(expect_death_and_exit); +ATF_TC_BODY(expect_death_and_exit, tc) +{ + atf_tc_expect_death("Exit case"); + exit(123); +} + +ATF_TC_WITHOUT_HEAD(expect_death_and_signal); +ATF_TC_BODY(expect_death_and_signal, tc) +{ + atf_tc_expect_death("Signal case"); + kill(getpid(), SIGKILL); +} + +ATF_TC_WITHOUT_HEAD(expect_death_but_pass); +ATF_TC_BODY(expect_death_but_pass, tc) +{ + atf_tc_expect_death("Call won't die"); +} + +ATF_TC(expect_timeout_and_hang); +ATF_TC_HEAD(expect_timeout_and_hang, tc) +{ + atf_tc_set_md_var(tc, "timeout", "1"); +} +ATF_TC_BODY(expect_timeout_and_hang, tc) +{ + atf_tc_expect_timeout("Will overrun"); + sleep(5); +} + +ATF_TC(expect_timeout_but_pass); +ATF_TC_HEAD(expect_timeout_but_pass, tc) +{ + atf_tc_set_md_var(tc, "timeout", "1"); +} +ATF_TC_BODY(expect_timeout_but_pass, tc) +{ + atf_tc_expect_timeout("Will just exit"); +} + +/* --------------------------------------------------------------------- + * Helper tests for "t_meta_data". + * --------------------------------------------------------------------- */ + +ATF_TC_WITHOUT_HEAD(metadata_no_descr); +ATF_TC_BODY(metadata_no_descr, tc) +{ +} + +ATF_TC_WITHOUT_HEAD(metadata_no_head); +ATF_TC_BODY(metadata_no_head, tc) +{ +} + +/* --------------------------------------------------------------------- + * Helper tests for "t_srcdir". + * --------------------------------------------------------------------- */ + +ATF_TC(srcdir_exists); +ATF_TC_HEAD(srcdir_exists, tc) +{ + atf_tc_set_md_var(tc, "descr", "Helper test case for the t_srcdir test " + "program"); +} +ATF_TC_BODY(srcdir_exists, tc) +{ + atf_fs_path_t p; + bool b; + + RE(atf_fs_path_init_fmt(&p, "%s/datafile", + atf_tc_get_config_var(tc, "srcdir"))); + RE(atf_fs_exists(&p, &b)); + atf_fs_path_fini(&p); + if (!b) + atf_tc_fail("Cannot find datafile"); +} + +/* --------------------------------------------------------------------- + * Helper tests for "t_result". + * --------------------------------------------------------------------- */ + +ATF_TC_WITHOUT_HEAD(result_pass); +ATF_TC_BODY(result_pass, tc) +{ + printf("msg\n"); +} + +ATF_TC_WITHOUT_HEAD(result_fail); +ATF_TC_BODY(result_fail, tc) +{ + printf("msg\n"); + atf_tc_fail("Failure reason"); +} + +ATF_TC_WITHOUT_HEAD(result_skip); +ATF_TC_BODY(result_skip, tc) +{ + printf("msg\n"); + atf_tc_skip("Skipped reason"); +} + +ATF_TC(result_newlines_fail); +ATF_TC_HEAD(result_newlines_fail, tc) +{ + atf_tc_set_md_var(tc, "descr", "Helper test case for the t_result test " + "program"); +} +ATF_TC_BODY(result_newlines_fail, tc) +{ + atf_tc_fail("First line\nSecond line"); +} + +ATF_TC(result_newlines_skip); +ATF_TC_HEAD(result_newlines_skip, tc) +{ + atf_tc_set_md_var(tc, "descr", "Helper test case for the t_result test " + "program"); +} +ATF_TC_BODY(result_newlines_skip, tc) +{ + atf_tc_skip("First line\nSecond line"); +} + +/* --------------------------------------------------------------------- + * Main. + * --------------------------------------------------------------------- */ + +ATF_TP_ADD_TCS(tp) +{ + /* Add helper tests for t_cleanup. */ + ATF_TP_ADD_TC(tp, cleanup_pass); + ATF_TP_ADD_TC(tp, cleanup_fail); + ATF_TP_ADD_TC(tp, cleanup_skip); + ATF_TP_ADD_TC(tp, cleanup_curdir); + ATF_TP_ADD_TC(tp, cleanup_sigterm); + + /* Add helper tests for t_config. */ + ATF_TP_ADD_TC(tp, config_unset); + ATF_TP_ADD_TC(tp, config_empty); + ATF_TP_ADD_TC(tp, config_value); + ATF_TP_ADD_TC(tp, config_multi_value); + + /* Add helper tests for t_expect. */ + ATF_TP_ADD_TC(tp, expect_pass_and_pass); + ATF_TP_ADD_TC(tp, expect_pass_but_fail_requirement); + ATF_TP_ADD_TC(tp, expect_pass_but_fail_check); + ATF_TP_ADD_TC(tp, expect_fail_and_fail_requirement); + ATF_TP_ADD_TC(tp, expect_fail_and_fail_check); + ATF_TP_ADD_TC(tp, expect_fail_but_pass); + ATF_TP_ADD_TC(tp, expect_exit_any_and_exit); + ATF_TP_ADD_TC(tp, expect_exit_code_and_exit); + ATF_TP_ADD_TC(tp, expect_exit_but_pass); + ATF_TP_ADD_TC(tp, expect_signal_any_and_signal); + ATF_TP_ADD_TC(tp, expect_signal_no_and_signal); + ATF_TP_ADD_TC(tp, expect_signal_but_pass); + ATF_TP_ADD_TC(tp, expect_death_and_exit); + ATF_TP_ADD_TC(tp, expect_death_and_signal); + ATF_TP_ADD_TC(tp, expect_death_but_pass); + ATF_TP_ADD_TC(tp, expect_timeout_and_hang); + ATF_TP_ADD_TC(tp, expect_timeout_but_pass); + + /* Add helper tests for t_meta_data. */ + ATF_TP_ADD_TC(tp, metadata_no_descr); + ATF_TP_ADD_TC(tp, metadata_no_head); + + /* Add helper tests for t_srcdir. */ + ATF_TP_ADD_TC(tp, srcdir_exists); + + /* Add helper tests for t_result. */ + ATF_TP_ADD_TC(tp, result_pass); + ATF_TP_ADD_TC(tp, result_fail); + ATF_TP_ADD_TC(tp, result_skip); + ATF_TP_ADD_TC(tp, result_newlines_fail); + ATF_TP_ADD_TC(tp, result_newlines_skip); + + return atf_no_error(); +} diff --git a/external/bsd/atf/dist/test-programs/common.sh b/external/bsd/atf/dist/test-programs/common.sh new file mode 100644 index 000000000..ebeebdb2d --- /dev/null +++ b/external/bsd/atf/dist/test-programs/common.sh @@ -0,0 +1,43 @@ +# +# Automated Testing Framework (atf) +# +# Copyright (c) 2008 The NetBSD Foundation, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +# CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +get_helpers() +{ + srcdir=$(atf_get_srcdir) + + if [ ${#} -eq 0 ]; then + set -- c_helpers cpp_helpers sh_helpers + fi + + for h_name in "${@}"; do + echo ${srcdir}/${h_name} + done +} + +# vim: syntax=sh:expandtab:shiftwidth=4:softtabstop=4 diff --git a/external/bsd/atf/dist/test-programs/config_test.sh b/external/bsd/atf/dist/test-programs/config_test.sh new file mode 100644 index 000000000..a697bee2b --- /dev/null +++ b/external/bsd/atf/dist/test-programs/config_test.sh @@ -0,0 +1,62 @@ +# +# Automated Testing Framework (atf) +# +# Copyright (c) 2007 The NetBSD Foundation, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +# CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +atf_test_case vflag +vflag_head() +{ + atf_set "descr" "Tests that the -v flag works correctly to set" \ + "configuration variables" +} +vflag_body() +{ + for h in $(get_helpers); do + atf_check -s eq:0 -o ignore -e ignore ${h} -s $(atf_get_srcdir) \ + -r resfile config_unset + atf_check -s eq:0 -o ignore -e empty grep 'passed' resfile + + atf_check -s eq:0 -o ignore -e ignore ${h} -s $(atf_get_srcdir) \ + -r resfile -v 'test=' config_empty + atf_check -s eq:0 -o ignore -e empty grep 'passed' resfile + + atf_check -s eq:0 -o ignore -e ignore ${h} -s $(atf_get_srcdir) \ + -r resfile -v 'test=foo' config_value + atf_check -s eq:0 -o ignore -e empty grep 'passed' resfile + + atf_check -s eq:0 -o ignore -e ignore -x ${h} -s $(atf_get_srcdir) \ + -r resfile -v \'test=foo bar\' config_multi_value + atf_check -s eq:0 -o ignore -e empty grep 'passed' resfile + done +} + +atf_init_test_cases() +{ + atf_add_test_case vflag +} + +# vim: syntax=sh:expandtab:shiftwidth=4:softtabstop=4 diff --git a/external/bsd/atf/dist/test-programs/cpp_helpers.cpp b/external/bsd/atf/dist/test-programs/cpp_helpers.cpp new file mode 100644 index 000000000..d8a495e7c --- /dev/null +++ b/external/bsd/atf/dist/test-programs/cpp_helpers.cpp @@ -0,0 +1,359 @@ +// +// Automated Testing Framework (atf) +// +// Copyright (c) 2007 The NetBSD Foundation, Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +extern "C" { +#include +#include +} + +#include +#include +#include + +#include + +#include "atf-c++/detail/fs.hpp" + +// ------------------------------------------------------------------------ +// Helper tests for "t_config". +// ------------------------------------------------------------------------ + +ATF_TEST_CASE(config_unset); +ATF_TEST_CASE_HEAD(config_unset) +{ + set_md_var("descr", "Helper test case for the t_config test program"); +} +ATF_TEST_CASE_BODY(config_unset) +{ + ATF_REQUIRE(!has_config_var("test")); +} + +ATF_TEST_CASE(config_empty); +ATF_TEST_CASE_HEAD(config_empty) +{ + set_md_var("descr", "Helper test case for the t_config test program"); +} +ATF_TEST_CASE_BODY(config_empty) +{ + ATF_REQUIRE_EQ(get_config_var("test"), ""); +} + +ATF_TEST_CASE(config_value); +ATF_TEST_CASE_HEAD(config_value) +{ + set_md_var("descr", "Helper test case for the t_config test program"); +} +ATF_TEST_CASE_BODY(config_value) +{ + ATF_REQUIRE_EQ(get_config_var("test"), "foo"); +} + +ATF_TEST_CASE(config_multi_value); +ATF_TEST_CASE_HEAD(config_multi_value) +{ + set_md_var("descr", "Helper test case for the t_config test program"); +} +ATF_TEST_CASE_BODY(config_multi_value) +{ + ATF_REQUIRE_EQ(get_config_var("test"), "foo bar"); +} + +// ------------------------------------------------------------------------ +// Helper tests for "t_expect". +// ------------------------------------------------------------------------ + +ATF_TEST_CASE_WITHOUT_HEAD(expect_pass_and_pass); +ATF_TEST_CASE_BODY(expect_pass_and_pass) +{ + expect_pass(); +} + +ATF_TEST_CASE_WITHOUT_HEAD(expect_pass_but_fail_requirement); +ATF_TEST_CASE_BODY(expect_pass_but_fail_requirement) +{ + expect_pass(); + fail("Some reason"); +} + +ATF_TEST_CASE_WITHOUT_HEAD(expect_pass_but_fail_check); +ATF_TEST_CASE_BODY(expect_pass_but_fail_check) +{ + expect_pass(); + fail_nonfatal("Some reason"); +} + +ATF_TEST_CASE_WITHOUT_HEAD(expect_fail_and_fail_requirement); +ATF_TEST_CASE_BODY(expect_fail_and_fail_requirement) +{ + expect_fail("Fail reason"); + fail("The failure"); + expect_pass(); +} + +ATF_TEST_CASE_WITHOUT_HEAD(expect_fail_and_fail_check); +ATF_TEST_CASE_BODY(expect_fail_and_fail_check) +{ + expect_fail("Fail first"); + fail_nonfatal("abc"); + expect_pass(); + + expect_fail("And fail again"); + fail_nonfatal("def"); + expect_pass(); +} + +ATF_TEST_CASE_WITHOUT_HEAD(expect_fail_but_pass); +ATF_TEST_CASE_BODY(expect_fail_but_pass) +{ + expect_fail("Fail first"); + fail_nonfatal("abc"); + expect_pass(); + + expect_fail("Will not fail"); + expect_pass(); + + expect_fail("And fail again"); + fail_nonfatal("def"); + expect_pass(); +} + +ATF_TEST_CASE_WITHOUT_HEAD(expect_exit_any_and_exit); +ATF_TEST_CASE_BODY(expect_exit_any_and_exit) +{ + expect_exit(-1, "Call will exit"); + std::exit(EXIT_SUCCESS); +} + +ATF_TEST_CASE_WITHOUT_HEAD(expect_exit_code_and_exit); +ATF_TEST_CASE_BODY(expect_exit_code_and_exit) +{ + expect_exit(123, "Call will exit"); + std::exit(123); +} + +ATF_TEST_CASE_WITHOUT_HEAD(expect_exit_but_pass); +ATF_TEST_CASE_BODY(expect_exit_but_pass) +{ + expect_exit(-1, "Call won't exit"); +} + +ATF_TEST_CASE_WITHOUT_HEAD(expect_signal_any_and_signal); +ATF_TEST_CASE_BODY(expect_signal_any_and_signal) +{ + expect_signal(-1, "Call will signal"); + ::kill(getpid(), SIGKILL); +} + +ATF_TEST_CASE_WITHOUT_HEAD(expect_signal_no_and_signal); +ATF_TEST_CASE_BODY(expect_signal_no_and_signal) +{ + expect_signal(SIGHUP, "Call will signal"); + ::kill(getpid(), SIGHUP); +} + +ATF_TEST_CASE_WITHOUT_HEAD(expect_signal_but_pass); +ATF_TEST_CASE_BODY(expect_signal_but_pass) +{ + expect_signal(-1, "Call won't signal"); +} + +ATF_TEST_CASE_WITHOUT_HEAD(expect_death_and_exit); +ATF_TEST_CASE_BODY(expect_death_and_exit) +{ + expect_death("Exit case"); + std::exit(123); +} + +ATF_TEST_CASE_WITHOUT_HEAD(expect_death_and_signal); +ATF_TEST_CASE_BODY(expect_death_and_signal) +{ + expect_death("Signal case"); + kill(getpid(), SIGKILL); +} + +ATF_TEST_CASE_WITHOUT_HEAD(expect_death_but_pass); +ATF_TEST_CASE_BODY(expect_death_but_pass) +{ + expect_death("Call won't die"); +} + +ATF_TEST_CASE(expect_timeout_and_hang); +ATF_TEST_CASE_HEAD(expect_timeout_and_hang) +{ + set_md_var("timeout", "1"); +} +ATF_TEST_CASE_BODY(expect_timeout_and_hang) +{ + expect_timeout("Will overrun"); + ::sleep(5); +} + +ATF_TEST_CASE(expect_timeout_but_pass); +ATF_TEST_CASE_HEAD(expect_timeout_but_pass) +{ + set_md_var("timeout", "1"); +} +ATF_TEST_CASE_BODY(expect_timeout_but_pass) +{ + expect_timeout("Will just exit"); +} + +// ------------------------------------------------------------------------ +// Helper tests for "t_meta_data". +// ------------------------------------------------------------------------ + +ATF_TEST_CASE(metadata_no_descr); +ATF_TEST_CASE_HEAD(metadata_no_descr) +{ +} +ATF_TEST_CASE_BODY(metadata_no_descr) +{ +} + +ATF_TEST_CASE_WITHOUT_HEAD(metadata_no_head); +ATF_TEST_CASE_BODY(metadata_no_head) +{ +} + +// ------------------------------------------------------------------------ +// Helper tests for "t_srcdir". +// ------------------------------------------------------------------------ + +ATF_TEST_CASE(srcdir_exists); +ATF_TEST_CASE_HEAD(srcdir_exists) +{ + set_md_var("descr", "Helper test case for the t_srcdir test program"); +} +ATF_TEST_CASE_BODY(srcdir_exists) +{ + if (!atf::fs::exists(atf::fs::path(get_config_var("srcdir")) / + "datafile")) + ATF_FAIL("Cannot find datafile"); +} + +// ------------------------------------------------------------------------ +// Helper tests for "t_result". +// ------------------------------------------------------------------------ + +ATF_TEST_CASE(result_pass); +ATF_TEST_CASE_HEAD(result_pass) { } +ATF_TEST_CASE_BODY(result_pass) +{ + std::cout << "msg\n"; +} + +ATF_TEST_CASE(result_fail); +ATF_TEST_CASE_HEAD(result_fail) { } +ATF_TEST_CASE_BODY(result_fail) +{ + std::cout << "msg\n"; + ATF_FAIL("Failure reason"); +} + +ATF_TEST_CASE(result_skip); +ATF_TEST_CASE_HEAD(result_skip) { } +ATF_TEST_CASE_BODY(result_skip) +{ + std::cout << "msg\n"; + ATF_SKIP("Skipped reason"); +} + +ATF_TEST_CASE(result_newlines_fail); +ATF_TEST_CASE_HEAD(result_newlines_fail) +{ + set_md_var("descr", "Helper test case for the t_result test program"); +} +ATF_TEST_CASE_BODY(result_newlines_fail) +{ + ATF_FAIL("First line\nSecond line"); +} + +ATF_TEST_CASE(result_newlines_skip); +ATF_TEST_CASE_HEAD(result_newlines_skip) +{ + set_md_var("descr", "Helper test case for the t_result test program"); +} +ATF_TEST_CASE_BODY(result_newlines_skip) +{ + ATF_SKIP("First line\nSecond line"); +} + +ATF_TEST_CASE(result_exception); +ATF_TEST_CASE_HEAD(result_exception) { } +ATF_TEST_CASE_BODY(result_exception) +{ + throw std::runtime_error("This is unhandled"); +} + +// ------------------------------------------------------------------------ +// Main. +// ------------------------------------------------------------------------ + +ATF_INIT_TEST_CASES(tcs) +{ + // Add helper tests for t_config. + ATF_ADD_TEST_CASE(tcs, config_unset); + ATF_ADD_TEST_CASE(tcs, config_empty); + ATF_ADD_TEST_CASE(tcs, config_value); + ATF_ADD_TEST_CASE(tcs, config_multi_value); + + // Add helper tests for t_expect. + ATF_ADD_TEST_CASE(tcs, expect_pass_and_pass); + ATF_ADD_TEST_CASE(tcs, expect_pass_but_fail_requirement); + ATF_ADD_TEST_CASE(tcs, expect_pass_but_fail_check); + ATF_ADD_TEST_CASE(tcs, expect_fail_and_fail_requirement); + ATF_ADD_TEST_CASE(tcs, expect_fail_and_fail_check); + ATF_ADD_TEST_CASE(tcs, expect_fail_but_pass); + ATF_ADD_TEST_CASE(tcs, expect_exit_any_and_exit); + ATF_ADD_TEST_CASE(tcs, expect_exit_code_and_exit); + ATF_ADD_TEST_CASE(tcs, expect_exit_but_pass); + ATF_ADD_TEST_CASE(tcs, expect_signal_any_and_signal); + ATF_ADD_TEST_CASE(tcs, expect_signal_no_and_signal); + ATF_ADD_TEST_CASE(tcs, expect_signal_but_pass); + ATF_ADD_TEST_CASE(tcs, expect_death_and_exit); + ATF_ADD_TEST_CASE(tcs, expect_death_and_signal); + ATF_ADD_TEST_CASE(tcs, expect_death_but_pass); + ATF_ADD_TEST_CASE(tcs, expect_timeout_and_hang); + ATF_ADD_TEST_CASE(tcs, expect_timeout_but_pass); + + // Add helper tests for t_meta_data. + ATF_ADD_TEST_CASE(tcs, metadata_no_descr); + ATF_ADD_TEST_CASE(tcs, metadata_no_head); + + // Add helper tests for t_srcdir. + ATF_ADD_TEST_CASE(tcs, srcdir_exists); + + // Add helper tests for t_result. + ATF_ADD_TEST_CASE(tcs, result_pass); + ATF_ADD_TEST_CASE(tcs, result_fail); + ATF_ADD_TEST_CASE(tcs, result_skip); + ATF_ADD_TEST_CASE(tcs, result_newlines_fail); + ATF_ADD_TEST_CASE(tcs, result_newlines_skip); + ATF_ADD_TEST_CASE(tcs, result_exception); +} diff --git a/external/bsd/atf/dist/test-programs/expect_test.sh b/external/bsd/atf/dist/test-programs/expect_test.sh new file mode 100644 index 000000000..46293507d --- /dev/null +++ b/external/bsd/atf/dist/test-programs/expect_test.sh @@ -0,0 +1,155 @@ +# +# Automated Testing Framework (atf) +# +# Copyright (c) 2007 The NetBSD Foundation, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +# CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +check_result() { + file="${1}"; shift + + atf_check -s eq:0 -o match:"${*}" -e empty cat "${file}" + rm "${file}" +} + +atf_test_case expect_pass +expect_pass_body() { + for h in $(get_helpers); do + atf_check -s eq:0 -e ignore "${h}" -r result expect_pass_and_pass + check_result result "passed" + + atf_check -s eq:1 -e ignore "${h}" -r result \ + expect_pass_but_fail_requirement + check_result result "failed: Some reason" + + # atf-sh does not support non-fatal failures yet; skip checks for + # such conditions. + case "${h}" in *sh_helpers*) continue ;; esac + + atf_check -s eq:1 -o empty -e match:"Some reason" \ + "${h}" -r result expect_pass_but_fail_check + check_result result "failed: 1 checks failed" + done +} + +atf_test_case expect_fail +expect_fail_body() { + for h in $(get_helpers c_helpers cpp_helpers); do + atf_check -s eq:0 "${h}" -r result expect_fail_and_fail_requirement + check_result result "expected_failure: Fail reason: The failure" + + atf_check -s eq:1 -e match:"Expected check failure: Fail first: abc" \ + -e not-match:"And fail again" "${h}" -r result expect_fail_but_pass + check_result result "failed: .*expecting a failure" + + # atf-sh does not support non-fatal failures yet; skip checks for + # such conditions. + case "${h}" in *sh_helpers*) continue ;; esac + + atf_check -s eq:0 -e match:"Expected check failure: Fail first: abc" \ + -e match:"Expected check failure: And fail again: def" \ + "${h}" -r result expect_fail_and_fail_check + check_result result "expected_failure: And fail again: 2 checks" \ + "failed as expected" + done + + # atf-sh does not support non-fatal failures yet; skip checks for + # such conditions. + for h in $(get_helpers sh_helpers); do + atf_check -s eq:0 -e ignore "${h}" -r result \ + expect_fail_and_fail_requirement + check_result result "expected_failure: Fail reason: The failure" + + atf_check -s eq:1 -e ignore "${h}" -r result expect_fail_but_pass + check_result result "failed: .*expecting a failure" + done +} + +atf_test_case expect_exit +expect_exit_body() { + for h in $(get_helpers); do + atf_check -s eq:0 -e ignore "${h}" -r result expect_exit_any_and_exit + check_result result "expected_exit: Call will exit" + + atf_check -s eq:123 -e ignore "${h}" -r result expect_exit_code_and_exit + check_result result "expected_exit\(123\): Call will exit" + + atf_check -s eq:1 -e ignore "${h}" -r result expect_exit_but_pass + check_result result "failed: .*expected to exit" + done +} + +atf_test_case expect_signal +expect_signal_body() { + for h in $(get_helpers); do + atf_check -s signal:9 -e ignore "${h}" -r result \ + expect_signal_any_and_signal + check_result result "expected_signal: Call will signal" + + atf_check -s signal:hup -e ignore "${h}" -r result \ + expect_signal_no_and_signal + check_result result "expected_signal\(1\): Call will signal" + + atf_check -s eq:1 -e ignore "${h}" -r result \ + expect_signal_but_pass + check_result result "failed: .*termination signal" + done +} + +atf_test_case expect_death +expect_death_body() { + for h in $(get_helpers); do + atf_check -s eq:123 -e ignore "${h}" -r result expect_death_and_exit + check_result result "expected_death: Exit case" + + atf_check -s signal:kill -e ignore "${h}" -r result \ + expect_death_and_signal + check_result result "expected_death: Signal case" + + atf_check -s eq:1 -e ignore "${h}" -r result expect_death_but_pass + check_result result "failed: .*terminate abruptly" + done +} + +atf_test_case expect_timeout +expect_timeout_body() { + for h in $(get_helpers); do + atf_check -s eq:1 -e ignore "${h}" -r result expect_timeout_but_pass + check_result result "failed: Test case was expected to hang but it" \ + "continued execution" + done +} + +atf_init_test_cases() +{ + atf_add_test_case expect_pass + atf_add_test_case expect_fail + atf_add_test_case expect_exit + atf_add_test_case expect_signal + atf_add_test_case expect_death + atf_add_test_case expect_timeout +} + +# vim: syntax=sh:expandtab:shiftwidth=4:softtabstop=4 diff --git a/external/bsd/atf/dist/test-programs/meta_data_test.sh b/external/bsd/atf/dist/test-programs/meta_data_test.sh new file mode 100644 index 000000000..35b008647 --- /dev/null +++ b/external/bsd/atf/dist/test-programs/meta_data_test.sh @@ -0,0 +1,64 @@ +# +# Automated Testing Framework (atf) +# +# Copyright (c) 2010 The NetBSD Foundation, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +# CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +atf_test_case no_descr +no_descr_head() +{ + atf_set "descr" "Tests that the description may not be present" +} +no_descr_body() +{ + for h in $(get_helpers); do + atf_check -s eq:0 -o ignore -e ignore ${h} -s $(atf_get_srcdir) -l + atf_check -s eq:0 -o match:passed -e ignore ${h} -s $(atf_get_srcdir) \ + metadata_no_descr + done +} + +atf_test_case no_head +no_head_head() +{ + atf_set "descr" "Tests that the head may not be present" +} +no_head_body() +{ + for h in $(get_helpers); do + atf_check -s eq:0 -o ignore -e ignore ${h} -s $(atf_get_srcdir) -l + atf_check -s eq:0 -o match:passed -e ignore ${h} -s $(atf_get_srcdir) \ + metadata_no_head + done +} + +atf_init_test_cases() +{ + atf_add_test_case no_descr + atf_add_test_case no_head +} + +# vim: syntax=sh:expandtab:shiftwidth=4:softtabstop=4 diff --git a/external/bsd/atf/dist/test-programs/result_test.sh b/external/bsd/atf/dist/test-programs/result_test.sh new file mode 100644 index 000000000..b2b325c4d --- /dev/null +++ b/external/bsd/atf/dist/test-programs/result_test.sh @@ -0,0 +1,139 @@ +# +# Automated Testing Framework (atf) +# +# Copyright (c) 2007 The NetBSD Foundation, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +# CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +atf_test_case atf_run_warnings +atf_run_warnings_head() +{ + # The fact that this test case is in this test program is an abuse. + atf_set "descr" "Tests that the test case prints a warning because" \ + "it is not being run by atf-run" +} +atf_run_warnings_body() +{ + unset __RUNNING_INSIDE_ATF_RUN + srcdir="$(atf_get_srcdir)" + for h in $(get_helpers); do + atf_check -s eq:0 -o match:"passed" -e match:"WARNING.*atf-run" \ + "${h}" -s "${srcdir}" result_pass + done +} + +atf_test_case result_on_stdout +result_on_stdout_head() +{ + atf_set "descr" "Tests that the test case result is printed on stdout" \ + "by default" +} +result_on_stdout_body() +{ + srcdir="$(atf_get_srcdir)" + for h in $(get_helpers); do + atf_check -s eq:0 -o match:"passed" -o match:"msg" \ + -e ignore "${h}" -s "${srcdir}" result_pass + atf_check -s eq:1 -o match:"failed: Failure reason" -o match:"msg" \ + -e ignore "${h}" -s "${srcdir}" result_fail + atf_check -s eq:0 -o match:"skipped: Skipped reason" -o match:"msg" \ + -e ignore "${h}" -s "${srcdir}" result_skip + done +} + +atf_test_case result_to_file +result_to_file_head() +{ + atf_set "descr" "Tests that the test case result is sent to a file if -r" \ + "is used" +} +result_to_file_body() +{ + srcdir="$(atf_get_srcdir)" + for h in $(get_helpers); do + atf_check -s eq:0 -o inline:"msg\n" -e ignore "${h}" -s "${srcdir}" \ + -r resfile result_pass + atf_check -o inline:"passed\n" cat resfile + + atf_check -s eq:1 -o inline:"msg\n" -e ignore "${h}" -s "${srcdir}" \ + -r resfile result_fail + atf_check -o inline:"failed: Failure reason\n" cat resfile + + atf_check -s eq:0 -o inline:"msg\n" -e ignore "${h}" -s "${srcdir}" \ + -r resfile result_skip + atf_check -o inline:"skipped: Skipped reason\n" cat resfile + done +} + +atf_test_case result_to_file_fail +result_to_file_fail_head() +{ + atf_set "descr" "Tests controlled failure if the test program fails to" \ + "create the results file" + atf_set "require.user" "unprivileged" +} +result_to_file_fail_body() +{ + mkdir dir + chmod 444 dir + + srcdir="$(atf_get_srcdir)" + + for h in $(get_helpers c_helpers cpp_helpers); do + atf_check -s signal -o ignore \ + -e match:"FATAL ERROR: Cannot create.*'dir/resfile'" \ + "${h}" -s "${srcdir}" -r dir/resfile result_pass + done + + for h in $(get_helpers sh_helpers); do + atf_check -s exit -o ignore \ + -e match:"ERROR: Cannot create.*'dir/resfile'" \ + "${h}" -s "${srcdir}" -r dir/resfile result_pass + done +} + +atf_test_case result_exception +result_exception_head() +{ + atf_set "descr" "Tests that an unhandled exception is correctly captured" +} +result_exception_body() +{ + for h in $(get_helpers cpp_helpers); do + atf_check -s exit:1 -o match:'failed: .*This is unhandled' \ + "${h}" -s "${srcdir}" result_exception + done +} + +atf_init_test_cases() +{ + atf_add_test_case atf_run_warnings + atf_add_test_case result_on_stdout + atf_add_test_case result_to_file + atf_add_test_case result_to_file_fail + atf_add_test_case result_exception +} + +# vim: syntax=sh:expandtab:shiftwidth=4:softtabstop=4 diff --git a/external/bsd/atf/dist/test-programs/sh_helpers.sh b/external/bsd/atf/dist/test-programs/sh_helpers.sh new file mode 100644 index 000000000..eb55102df --- /dev/null +++ b/external/bsd/atf/dist/test-programs/sh_helpers.sh @@ -0,0 +1,394 @@ +# +# Automated Testing Framework (atf) +# +# Copyright (c) 2007 The NetBSD Foundation, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +# CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# ------------------------------------------------------------------------- +# Helper tests for "t_cleanup". +# ------------------------------------------------------------------------- + +atf_test_case cleanup_pass cleanup +cleanup_pass_head() +{ + atf_set "descr" "Helper test case for the t_cleanup test program" +} +cleanup_pass_body() +{ + touch $(atf_config_get tmpfile) +} +cleanup_pass_cleanup() +{ + if [ $(atf_config_get cleanup no) = yes ]; then + rm $(atf_config_get tmpfile) + fi +} + +atf_test_case cleanup_fail cleanup +cleanup_fail_head() +{ + atf_set "descr" "Helper test case for the t_cleanup test program" +} +cleanup_fail_body() +{ + touch $(atf_config_get tmpfile) + atf_fail "On purpose" +} +cleanup_fail_cleanup() +{ + if [ $(atf_config_get cleanup no) = yes ]; then + rm $(atf_config_get tmpfile) + fi +} + +atf_test_case cleanup_skip cleanup +cleanup_skip_head() +{ + atf_set "descr" "Helper test case for the t_cleanup test program" +} +cleanup_skip_body() +{ + touch $(atf_config_get tmpfile) + atf_skip "On purpose" +} +cleanup_skip_cleanup() +{ + if [ $(atf_config_get cleanup no) = yes ]; then + rm $(atf_config_get tmpfile) + fi +} + +atf_test_case cleanup_curdir cleanup +cleanup_curdir_head() +{ + atf_set "descr" "Helper test case for the t_cleanup test program" +} +cleanup_curdir_body() +{ + echo 1234 >oldvalue +} +cleanup_curdir_cleanup() +{ + test -f oldvalue && echo "Old value: $(cat oldvalue)" +} + +atf_test_case cleanup_sigterm cleanup +cleanup_sigterm_head() +{ + atf_set "descr" "Helper test case for the t_cleanup test program" +} +cleanup_sigterm_body() +{ + touch $(atf_config_get tmpfile) + kill $$ + touch $(atf_config_get tmpfile).no +} +cleanup_sigterm_cleanup() +{ + rm $(atf_config_get tmpfile) +} + +# ------------------------------------------------------------------------- +# Helper tests for "t_config". +# ------------------------------------------------------------------------- + +atf_test_case config_unset +config_unset_head() +{ + atf_set "descr" "Helper test case for the t_config test program" +} +config_unset_body() +{ + if atf_config_has 'test'; then + atf_fail "Test variable already defined" + fi +} + +atf_test_case config_empty +config_empty_head() +{ + atf_set "descr" "Helper test case for the t_config test program" +} +config_empty_body() +{ + atf_check_equal "$(atf_config_get 'test')" "" +} + +atf_test_case config_value +config_value_head() +{ + atf_set "descr" "Helper test case for the t_config test program" +} +config_value_body() +{ + atf_check_equal "$(atf_config_get 'test')" "foo" +} + +atf_test_case config_multi_value +config_multi_value_head() +{ + atf_set "descr" "Helper test case for the t_config test program" +} +config_multi_value_body() +{ + atf_check_equal "$(atf_config_get 'test')" "foo bar" +} + +# ------------------------------------------------------------------------- +# Helper tests for "t_expect". +# ------------------------------------------------------------------------- + +atf_test_case expect_pass_and_pass +expect_pass_and_pass_body() +{ + atf_expect_pass +} + +atf_test_case expect_pass_but_fail_requirement +expect_pass_but_fail_requirement_body() +{ + atf_expect_pass + atf_fail "Some reason" +} + +atf_test_case expect_pass_but_fail_check +expect_pass_but_fail_check_body() +{ + atf_fail "Non-fatal failures not implemented" +} + +atf_test_case expect_fail_and_fail_requirement +expect_fail_and_fail_requirement_body() +{ + atf_expect_fail "Fail reason" + atf_fail "The failure" + atf_expect_pass +} + +atf_test_case expect_fail_and_fail_check +expect_fail_and_fail_check_body() +{ + atf_fail "Non-fatal failures not implemented" +} + +atf_test_case expect_fail_but_pass +expect_fail_but_pass_body() +{ + atf_expect_fail "Fail first" + atf_expect_pass +} + +atf_test_case expect_exit_any_and_exit +expect_exit_any_and_exit_body() +{ + atf_expect_exit -1 "Call will exit" + exit 0 +} + +atf_test_case expect_exit_code_and_exit +expect_exit_code_and_exit_body() +{ + atf_expect_exit 123 "Call will exit" + exit 123 +} + +atf_test_case expect_exit_but_pass +expect_exit_but_pass_body() +{ + atf_expect_exit -1 "Call won't exit" +} + +atf_test_case expect_signal_any_and_signal +expect_signal_any_and_signal_body() +{ + atf_expect_signal -1 "Call will signal" + kill -9 $$ +} + +atf_test_case expect_signal_no_and_signal +expect_signal_no_and_signal_body() +{ + atf_expect_signal 1 "Call will signal" + kill -1 $$ +} + +atf_test_case expect_signal_but_pass +expect_signal_but_pass_body() +{ + atf_expect_signal -1 "Call won't signal" +} + +atf_test_case expect_death_and_exit +expect_death_and_exit_body() +{ + atf_expect_death "Exit case" + exit 123 +} + +atf_test_case expect_death_and_signal +expect_death_and_signal_body() +{ + atf_expect_death "Signal case" + kill -9 $$ +} + +atf_test_case expect_death_but_pass +expect_death_but_pass_body() +{ + atf_expect_death "Call won't die" +} + +atf_test_case expect_timeout_and_hang +expect_timeout_and_hang_head() +{ + atf_set "timeout" "1" +} +expect_timeout_and_hang_body() +{ + atf_expect_timeout "Will overrun" + sleep 5 +} + +atf_test_case expect_timeout_but_pass +expect_timeout_but_pass_head() +{ + atf_set "timeout" "1" +} +expect_timeout_but_pass_body() +{ + atf_expect_timeout "Will just exit" +} + +# ------------------------------------------------------------------------- +# Helper tests for "t_meta_data". +# ------------------------------------------------------------------------- + +atf_test_case metadata_no_descr +metadata_no_descr_head() +{ + : +} +metadata_no_descr_body() +{ + : +} + +atf_test_case metadata_no_head +metadata_no_head_body() +{ + : +} + +# ------------------------------------------------------------------------- +# Helper tests for "t_srcdir". +# ------------------------------------------------------------------------- + +atf_test_case srcdir_exists +srcdir_exists_head() +{ + atf_set "descr" "Helper test case for the t_srcdir test program" +} +srcdir_exists_body() +{ + [ -f "$(atf_get_srcdir)/datafile" ] || atf_fail "Cannot find datafile" +} + +# ------------------------------------------------------------------------- +# Helper tests for "t_result". +# ------------------------------------------------------------------------- + +atf_test_case result_pass +result_pass_body() +{ + echo "msg" +} + +atf_test_case result_fail +result_fail_body() +{ + echo "msg" + atf_fail "Failure reason" +} + +atf_test_case result_skip +result_skip_body() +{ + echo "msg" + atf_skip "Skipped reason" +} + +# ------------------------------------------------------------------------- +# Main. +# ------------------------------------------------------------------------- + +atf_init_test_cases() +{ + # Add helper tests for t_cleanup. + atf_add_test_case cleanup_pass + atf_add_test_case cleanup_fail + atf_add_test_case cleanup_skip + atf_add_test_case cleanup_curdir + atf_add_test_case cleanup_sigterm + + # Add helper tests for t_config. + atf_add_test_case config_unset + atf_add_test_case config_empty + atf_add_test_case config_value + atf_add_test_case config_multi_value + + # Add helper tests for t_expect. + atf_add_test_case expect_pass_and_pass + atf_add_test_case expect_pass_but_fail_requirement + atf_add_test_case expect_pass_but_fail_check + atf_add_test_case expect_fail_and_fail_requirement + atf_add_test_case expect_fail_and_fail_check + atf_add_test_case expect_fail_but_pass + atf_add_test_case expect_exit_any_and_exit + atf_add_test_case expect_exit_code_and_exit + atf_add_test_case expect_exit_but_pass + atf_add_test_case expect_signal_any_and_signal + atf_add_test_case expect_signal_no_and_signal + atf_add_test_case expect_signal_but_pass + atf_add_test_case expect_death_and_exit + atf_add_test_case expect_death_and_signal + atf_add_test_case expect_death_but_pass + atf_add_test_case expect_timeout_and_hang + atf_add_test_case expect_timeout_but_pass + + # Add helper tests for t_meta_data. + atf_add_test_case metadata_no_descr + atf_add_test_case metadata_no_head + + # Add helper tests for t_srcdir. + atf_add_test_case srcdir_exists + + # Add helper tests for t_result. + atf_add_test_case result_pass + atf_add_test_case result_fail + atf_add_test_case result_skip +} + +# vim: syntax=sh:expandtab:shiftwidth=4:softtabstop=4 diff --git a/external/bsd/atf/dist/test-programs/srcdir_test.sh b/external/bsd/atf/dist/test-programs/srcdir_test.sh new file mode 100644 index 000000000..11d6831f8 --- /dev/null +++ b/external/bsd/atf/dist/test-programs/srcdir_test.sh @@ -0,0 +1,149 @@ +# +# Automated Testing Framework (atf) +# +# Copyright (c) 2007 The NetBSD Foundation, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND +# CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +create_files() +{ + mkdir tmp + touch tmp/datafile +} + +atf_test_case default +default_head() +{ + atf_set "descr" "Checks that the program can find its files if" \ + "executed from the same directory" +} +default_body() +{ + create_files + + for hp in $(get_helpers); do + h=${hp##*/} + cp ${hp} tmp + atf_check -s eq:0 -o ignore -e ignore -x \ + "cd tmp && ./${h} srcdir_exists" + atf_check -s eq:1 -o empty -e ignore "${hp}" -r res srcdir_exists + atf_check -s eq:0 -o ignore -e empty grep "Cannot find datafile" res + done +} + +atf_test_case libtool +libtool_head() +{ + atf_set "descr" "Checks that the program can find its files if" \ + "executed from the source directory and if it" \ + "was built with libtool" +} +libtool_body() +{ + create_files + mkdir tmp/.libs + + for hp in $(get_helpers c_helpers cpp_helpers); do + h=${hp##*/} + cp ${hp} tmp + cp ${hp} tmp/.libs + atf_check -s eq:0 -o ignore -e ignore -x \ + "cd tmp && ./.libs/${h} srcdir_exists" + atf_check -s eq:1 -o empty -e ignore "${hp}" -r res srcdir_exists + atf_check -s eq:0 -o ignore -e empty grep "Cannot find datafile" res + done + + for hp in $(get_helpers c_helpers cpp_helpers); do + h=${hp##*/} + cp ${hp} tmp + cp ${hp} tmp/.libs/lt-${h} + atf_check -s eq:0 -o ignore -e ignore -x \ + "cd tmp && ./.libs/lt-${h} srcdir_exists" + atf_check -s eq:1 -o empty -e ignore "${hp}" -r res srcdir_exists + atf_check -s eq:0 -o ignore -e empty grep "Cannot find datafile" res + done +} + +atf_test_case sflag +sflag_head() +{ + atf_set "descr" "Checks that the program can find its files when" \ + "using the -s flag" +} +sflag_body() +{ + create_files + + for hp in $(get_helpers); do + h=${hp##*/} + cp ${hp} tmp + atf_check -s eq:0 -o ignore -e ignore -x \ + "cd tmp && ./${h} -s $(pwd)/tmp \ + srcdir_exists" + atf_check -s eq:1 -o empty -e save:stderr "${hp}" -r res srcdir_exists + atf_check -s eq:0 -o ignore -e empty grep "Cannot find datafile" res + atf_check -s eq:0 -o ignore -e ignore \ + "${hp}" -s "$(pwd)"/tmp srcdir_exists + done +} + +atf_test_case relative +relative_head() +{ + atf_set "descr" "Checks that passing a relative path through -s" \ + "works" +} +relative_body() +{ + create_files + + for hp in $(get_helpers); do + h=${hp##*/} + cp ${hp} tmp + + for p in tmp tmp/. ./tmp; do + echo "Helper is: ${h}" + echo "Using source directory: ${p}" + + atf_check -s eq:0 -o ignore -e ignore \ + "./tmp/${h}" -s "${p}" srcdir_exists + atf_check -s eq:1 -o empty -e save:stderr "${hp}" -r res \ + srcdir_exists + atf_check -s eq:0 -o ignore -e empty grep "Cannot find datafile" res + atf_check -s eq:0 -o ignore -e ignore \ + "${hp}" -s "${p}" srcdir_exists + done + done +} + +atf_init_test_cases() +{ + atf_add_test_case default + atf_add_test_case libtool + atf_add_test_case sflag + atf_add_test_case relative +} + +# vim: syntax=sh:expandtab:shiftwidth=4:softtabstop=4 diff --git a/external/bsd/atf/etc/Makefile b/external/bsd/atf/etc/Makefile new file mode 100644 index 000000000..552cd4344 --- /dev/null +++ b/external/bsd/atf/etc/Makefile @@ -0,0 +1,9 @@ +# $NetBSD: Makefile,v 1.2 2013/02/25 00:22:10 jmmv Exp $ + +.include + +.if !(${MKKYUA} != "no") +SUBDIR= atf +.endif + +.include diff --git a/external/bsd/atf/etc/atf/Makefile b/external/bsd/atf/etc/atf/Makefile new file mode 100644 index 000000000..fdb9a20ca --- /dev/null +++ b/external/bsd/atf/etc/atf/Makefile @@ -0,0 +1,13 @@ +# $NetBSD: Makefile,v 1.3 2010/11/07 17:46:45 jmmv Exp $ + +.include + +SRCDIR= ${NETBSDSRCDIR}/external/bsd/atf/dist +.PATH: ${SRCDIR}/atf-run/sample + +CONFIGFILES= NetBSD.conf atf-run.hooks common.conf +FILESDIR= /etc/atf +FILESMODE= 644 + +.include # For clean and cleandir +.include diff --git a/external/bsd/atf/etc/atf/NetBSD.conf b/external/bsd/atf/etc/atf/NetBSD.conf new file mode 100644 index 000000000..3bc49391a --- /dev/null +++ b/external/bsd/atf/etc/atf/NetBSD.conf @@ -0,0 +1,11 @@ +Content-Type: application/X-atf-config; version="1" + +# +# Configuration file for the NetBSD test suite. +# +# See atf-formats(5) for details on the syntax of this file and tests(7) for +# details on the NetBSD test suite. +# + +#variable1 = value1 +#variable2 = value2 diff --git a/external/bsd/atf/etc/atf/common.conf b/external/bsd/atf/etc/atf/common.conf new file mode 100644 index 000000000..5fb98fde4 --- /dev/null +++ b/external/bsd/atf/etc/atf/common.conf @@ -0,0 +1,11 @@ +Content-Type: application/X-atf-config; version="1" + +# +# Sample configuration file for properties affecting all test suites. +# + +# When running the test suite as root, some tests require to switch to +# an unprivileged user to perform extra checks. Set this variable to +# the user you want to use in those cases. If not set, those tests will +# be skipped. +unprivileged-user = "_tests" diff --git a/external/bsd/atf/lib/Makefile b/external/bsd/atf/lib/Makefile new file mode 100644 index 000000000..d38e08eb8 --- /dev/null +++ b/external/bsd/atf/lib/Makefile @@ -0,0 +1,5 @@ +# $NetBSD: Makefile,v 1.1 2009/01/19 07:13:04 jmmv Exp $ + +SUBDIR= libatf-c .WAIT libatf-c++ + +.include diff --git a/external/bsd/atf/lib/Makefile.inc b/external/bsd/atf/lib/Makefile.inc new file mode 100644 index 000000000..03a45fbc5 --- /dev/null +++ b/external/bsd/atf/lib/Makefile.inc @@ -0,0 +1,3 @@ +# $NetBSD: Makefile.inc,v 1.1 2013/03/14 07:10:06 jmmv Exp $ + +.include "../Makefile.inc" diff --git a/external/bsd/atf/lib/libatf-c++/Makefile b/external/bsd/atf/lib/libatf-c++/Makefile new file mode 100644 index 000000000..0b038f989 --- /dev/null +++ b/external/bsd/atf/lib/libatf-c++/Makefile @@ -0,0 +1,74 @@ +# $NetBSD: Makefile,v 1.19 2013/03/14 07:10:06 jmmv Exp $ + +NOLINT= # defined + +.include + +LIB= atf-c++ +LIBISCXX= yes + +LIBDPLIBS+= atf-c ${.CURDIR}/../libatf-c +.if ${HAVE_GCC} == 4 +LIBDPLIBS+= stdc++ ${.CURDIR}/../../../../../gnu/lib/libstdc++-v3_4 +.else +LIBDPLIBS+= stdc++ ${.CURDIR}/../../../../../external/gpl3/gcc/lib/libstdc++-v3 +.endif +LIBDPLIBS+= m ${.CURDIR}/../../../../../lib/libm + + +.PATH: ${SRCDIR} +.PATH: ${SRCDIR}/atf-c++ +.PATH: ${SRCDIR}/atf-c++/detail +.PATH: ${TOPDIR}/lib/libatf-c # For bconfig.h + +CPPFLAGS+= -I${.CURDIR}/../libatf-c +CPPFLAGS+= -I. + +CPPFLAGS+= -DHAVE_CONFIG_H + +WARNS?= 2 + +SRCS= application.cpp \ + build.cpp \ + check.cpp \ + config.cpp \ + env.cpp \ + exceptions.cpp \ + expand.cpp \ + fs.cpp \ + parser.cpp \ + process.cpp \ + tests.cpp \ + text.cpp \ + ui.cpp \ + utils.cpp + +INCS= build.hpp \ + check.hpp \ + config.hpp \ + macros.hpp \ + noncopyable.hpp \ + tests.hpp \ + utils.hpp +INCSDIR= /usr/include/atf-c++ + +INCS+= atf-c++.hpp +INCSDIR_atf-c++.hpp=/usr/include + +MAN= atf-c++-api.3 + +.if ${MKSHARE} != "no" +FILES+= atf-c++.pc +FILESDIR= /usr/lib/pkgconfig + +realall: atf-c++.pc +atf-c++.pc: Makefile atf-c++.pc.in bconfig.h + ${TOOL_SED} -e 's,__ATF_VERSION__,${ATF_VERSION},g' \ + -e 's,__CXX__,g++,g' \ + -e 's,__INCLUDEDIR__,/usr/include,g' \ + -e 's,__LIBDIR__,/usr/lib,g' \ + <${SRCDIR}/atf-c++/atf-c++.pc.in >atf-c++.pc +CLEANFILES+= atf-c++.pc +.endif + +.include diff --git a/external/bsd/atf/lib/libatf-c++/shlib_version b/external/bsd/atf/lib/libatf-c++/shlib_version new file mode 100644 index 000000000..2a86f7ac0 --- /dev/null +++ b/external/bsd/atf/lib/libatf-c++/shlib_version @@ -0,0 +1,3 @@ +# $NetBSD: shlib_version,v 1.1 2012/07/11 22:40:16 jmmv Exp $ +major=0 +minor=0 diff --git a/external/bsd/atf/lib/libatf-c/Makefile b/external/bsd/atf/lib/libatf-c/Makefile new file mode 100644 index 000000000..fea39b0f9 --- /dev/null +++ b/external/bsd/atf/lib/libatf-c/Makefile @@ -0,0 +1,99 @@ +# $NetBSD: Makefile,v 1.17 2013/03/14 07:10:06 jmmv Exp $ + +NOLINT= # defined + +.include + +LIB= atf-c + +CWARNFLAGS+= -Wno-missing-noreturn + +.PATH: ${SRCDIR} +.PATH: ${SRCDIR}/atf-c +.PATH: ${SRCDIR}/atf-c/detail + +CPPFLAGS+= -I${.CURDIR} +CPPFLAGS+= -I. + +CPPFLAGS+= -DHAVE_CONFIG_H +CPPFLAGS+= -DATF_ARCH=\"${MACHINE_ARCH}\" +CPPFLAGS+= -DATF_BUILD_CC=\"/usr/bin/cc\" +CPPFLAGS+= -DATF_BUILD_CFLAGS=\"\" +CPPFLAGS+= -DATF_BUILD_CPP=\"/usr/bin/cpp\" +CPPFLAGS+= -DATF_BUILD_CPPFLAGS=\"\" +CPPFLAGS+= -DATF_BUILD_CXX=\"/usr/bin/c++\" +CPPFLAGS+= -DATF_BUILD_CXXFLAGS=\"\" +CPPFLAGS+= -DATF_CONFDIR=\"/etc/atf\" +CPPFLAGS+= -DATF_INCLUDEDIR=\"/usr/include\" +CPPFLAGS+= -DATF_LIBDIR=\"/usr/lib\" +CPPFLAGS+= -DATF_LIBEXECDIR=\"/usr/libexec\" +CPPFLAGS+= -DATF_MACHINE=\"${MACHINE}\" +CPPFLAGS+= -DATF_M4=\"/usr/bin/m4\" +CPPFLAGS+= -DATF_PKGDATADIR=\"/usr/share/atf\" +CPPFLAGS+= -DATF_SHELL=\"/bin/sh\" +CPPFLAGS+= -DATF_WORKDIR=\"/tmp\" + +config.o: Makefile + +WARNS?= 4 + +SRCS= build.c \ + check.c \ + config.c \ + dynstr.c \ + env.c \ + error.c \ + fs.c \ + list.c \ + map.c \ + process.c \ + sanity.c \ + text.c \ + user.c \ + utils.c \ + tc.c \ + tp.c \ + tp_main.c + +INCS= build.h \ + check.h \ + config.h \ + defs.h \ + error.h \ + error_fwd.h \ + macros.h \ + tc.h \ + tp.h \ + utils.h +INCSDIR= /usr/include/atf-c + +INCS+= atf-c.h +INCSDIR_atf-c.h=/usr/include + +MAN= atf-c-api.3 + +CLEANFILES+= defs.h + +defs.h: defs.h.in + ${TOOL_SED} \ + -e 's|@ATTRIBUTE_FORMAT_PRINTF@|__attribute__((__format__(__printf__, a, b)))|g' \ + -e 's|@ATTRIBUTE_NORETURN@|__attribute__((__noreturn__))|g' \ + -e 's|@ATTRIBUTE_UNUSED@|__attribute__((__unused__))|g' \ + < ${.ALLSRC} > ${.TARGET}.tmp + mv ${.TARGET}.tmp ${.TARGET} + +.if ${MKSHARE} != "no" +FILES+= atf-c.pc +FILESDIR= /usr/lib/pkgconfig + +realall: atf-c.pc +atf-c.pc: Makefile atf-c.pc.in bconfig.h + ${TOOL_SED} -e 's,__ATF_VERSION__,${ATF_VERSION},g' \ + -e 's,__CC__,gcc,g' \ + -e 's,__INCLUDEDIR__,/usr/include,g' \ + -e 's,__LIBDIR__,/usr/lib,g' \ + <${SRCDIR}/atf-c/atf-c.pc.in >atf-c.pc +CLEANFILES+= atf-c.pc +.endif + +.include diff --git a/external/bsd/atf/lib/libatf-c/bconfig.h b/external/bsd/atf/lib/libatf-c/bconfig.h new file mode 100644 index 000000000..09d88e577 --- /dev/null +++ b/external/bsd/atf/lib/libatf-c/bconfig.h @@ -0,0 +1,114 @@ +/* bconfig.h. Generated from bconfig.h.in by configure. */ +/* bconfig.h.in. Generated from configure.ac by autoheader. */ + +/* Define to 1 if basename takes a constant pointer */ +/* #undef HAVE_CONST_BASENAME */ + +/* Define to 1 if dirname takes a constant pointer */ +/* #undef HAVE_CONST_DIRNAME */ + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if getcwd(NULL, 0) works */ +#define HAVE_GETCWD_DYN 1 + +/* Define to 1 if getopt allows a + sign for POSIX behavior */ +/* #undef HAVE_GNU_GETOPT */ + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if getopt has optreset */ +#define HAVE_OPTRESET 1 + +/* Define to 1 if you have the `putenv' function. */ +#define HAVE_PUTENV 1 + +/* Define to 1 if putenv is in std */ +/* #undef HAVE_PUTENV_IN_STD */ + +/* Define to 1 if you have the `setenv' function. */ +#define HAVE_SETENV 1 + +/* Define to 1 if setenv is in std */ +/* #undef HAVE_SETENV_IN_STD */ + +/* Define to 1 if snprintf is in std */ +/* #undef HAVE_SNPRINTF_IN_STD */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `unmount' function. */ +/* #undef HAVE_UNMOUNT */ + +/* Define to 1 if you have the `unsetenv' function. */ +#define HAVE_UNSETENV 1 + +/* Define to 1 if unsetenv is in std */ +/* #undef HAVE_UNSETENV_IN_STD */ + +/* Define to 1 if vsnprintf is in std */ +/* #undef HAVE_VSNPRINTF_IN_STD */ + +/* Define to the last valid signal number */ +#define LAST_SIGNO 63 + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#define LT_OBJDIR ".libs/" + +/* Define to 1 if your C compiler doesn't accept -c and -o together. */ +/* #undef NO_MINUS_C_MINUS_O */ + +/* Name of package */ +#define PACKAGE "atf" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "atf-devel@NetBSD.org" + +/* Define to the copyright string applicable to this package. */ +#define PACKAGE_COPYRIGHT "Copyright (c) 2007-2012 The NetBSD Foundation, Inc." + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "Automated Testing Framework" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "Automated Testing Framework 0.17" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "atf" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "http://code.google.com/p/kyua/wiki/ATF" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "0.17" + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Version number of package */ +#define VERSION "0.17" diff --git a/external/bsd/atf/lib/libatf-c/shlib_version b/external/bsd/atf/lib/libatf-c/shlib_version new file mode 100644 index 000000000..2a86f7ac0 --- /dev/null +++ b/external/bsd/atf/lib/libatf-c/shlib_version @@ -0,0 +1,3 @@ +# $NetBSD: shlib_version,v 1.1 2012/07/11 22:40:16 jmmv Exp $ +major=0 +minor=0 diff --git a/external/bsd/atf/libexec/Makefile b/external/bsd/atf/libexec/Makefile new file mode 100644 index 000000000..9ddbf72f7 --- /dev/null +++ b/external/bsd/atf/libexec/Makefile @@ -0,0 +1,5 @@ +# $NetBSD: Makefile,v 1.4 2010/10/20 09:20:10 jmmv Exp $ + +SUBDIR= atf-check + +.include diff --git a/external/bsd/atf/libexec/atf-check/Makefile b/external/bsd/atf/libexec/atf-check/Makefile new file mode 100644 index 000000000..0294c0772 --- /dev/null +++ b/external/bsd/atf/libexec/atf-check/Makefile @@ -0,0 +1,21 @@ +# $NetBSD: Makefile,v 1.2 2011/02/20 20:18:56 jmmv Exp $ + +.include + +SRCDIR= ${NETBSDSRCDIR}/external/bsd/atf/dist +.PATH: ${SRCDIR}/atf-sh + +BINDIR= /usr/libexec +PROG_CXX= atf-check +SRCS= atf-check.cpp +MAN= atf-check.1 + +LDADD+= -latf-c++ -latf-c +DPADD+= ${LIBATF_CXX} ${LIBATF_C} + +CPPFLAGS+= -DHAVE_CONFIG_H +CPPFLAGS+= -I${SRCDIR} + +WARNS?= 2 + +.include diff --git a/external/bsd/atf/prepare-import.sh b/external/bsd/atf/prepare-import.sh new file mode 100644 index 000000000..37ea0fce2 --- /dev/null +++ b/external/bsd/atf/prepare-import.sh @@ -0,0 +1,106 @@ +#!/bin/sh +# $NetBSD: prepare-import.sh,v 1.6 2012/01/16 22:42:40 jmmv Exp $ +# +# Use this script to recreate the 'dist' subdirectory from a newly released +# distfile. The script takes care of unpacking the distfile, removing any +# files that are not relevant to NetBSD and checking if there are any new +# files in the new release that need to be addressed. +# + +set -e + +ProgName=${0##*/} + +CLEAN_PATTERNS= +CLEAN_PATTERNS="${CLEAN_PATTERNS} *.m4" +CLEAN_PATTERNS="${CLEAN_PATTERNS} INSTALL TODO" +CLEAN_PATTERNS="${CLEAN_PATTERNS} Makefile* */Makefile* */*/Makefile*" +CLEAN_PATTERNS="${CLEAN_PATTERNS} admin" +CLEAN_PATTERNS="${CLEAN_PATTERNS} atf-*/atf-*.m4" +CLEAN_PATTERNS="${CLEAN_PATTERNS} bconfig.h.in" +CLEAN_PATTERNS="${CLEAN_PATTERNS} bootstrap" +CLEAN_PATTERNS="${CLEAN_PATTERNS} configure*" +CLEAN_PATTERNS="${CLEAN_PATTERNS} m4" + +err() { + echo "${ProgName}:" "${@}" 1>&2 + exit 1 +} + +log() { + echo "${ProgName}:" "${@}" +} + +backup_dist() { + if [ -d dist.old ]; then + log "Removing dist; dist.old exists" + rm -rf dist + else + log "Backing up dist as dist.old" + mv dist dist.old + fi +} + +extract_distfile() { + local distfile="${1}"; shift + local distname="${1}"; shift + + log "Extracting ${distfile}" + tar -xzf "${distfile}" + [ -d "${distname}" ] || err "Distfile did not create ${distname}" + log "Renaming ${distname} to dist" + mv "${distname}" dist +} + +get_distname() { + local distfile="${1}"; shift + basename "${distfile}" | sed -e 's,\.tar.*,,' +} + +cleanup_dist() { + log "Removing unnecessary files from dist" + ( cd dist && rm -rf ${CLEAN_PATTERNS} ) +} + +diff_dirs() { + local old_dir="${1}"; shift + local new_dir="${1}"; shift + + local old_list=$(mktemp -t atf-import.XXXXXX) + local new_list=$(mktemp -t atf-import.XXXXXX) + local diff=$(mktemp -t atf-import.XXXXXX) + trap "rm -f '${old_list}' '${new_list}' '${diff}'; exit 1" \ + HUP INT QUIT TERM + + ( cd "${old_dir}" && find . | sort >>"${old_list}" ) + ( cd "${new_dir}" && find . | sort >>"${new_list}" ) + + diff -u "${old_list}" "${new_list}" | grep '^+\.' >>"${diff}" || true + if [ -s "${diff}" ]; then + log "New files found" + diff -u "${old_list}" "${new_list}" | grep '^+\.' + log "Check if any files have to be cleaned up and update" \ + "the prepare-import.sh script accordingly" + else + log "No new files; all good!" + fi + + rm -f "${old_list}" "${new_list}" "${diff}" +} + +main() { + [ ${#} -eq 1 ] || err "Must provide a distfile name" + local distfile="${1}"; shift + + [ -f Makefile -a -f prepare-import.sh ] || \ + err "Must be run from the src/external/bsd/atf subdirectory" + + local distname="$(get_distname ${distfile})" + + backup_dist + extract_distfile "${distfile}" "${distname}" + cleanup_dist + diff_dirs dist.old dist +} + +main "${@}" diff --git a/external/bsd/atf/share/Makefile b/external/bsd/atf/share/Makefile new file mode 100644 index 000000000..05ac363e0 --- /dev/null +++ b/external/bsd/atf/share/Makefile @@ -0,0 +1,10 @@ +# $NetBSD: Makefile,v 1.3 2013/02/25 00:22:11 jmmv Exp $ + +.include + +SUBDIR= doc +.if !(${MKKYUA} != "no") +SUBDIR+= examples xml xsl +.endif + +.include diff --git a/external/bsd/atf/share/doc/Makefile b/external/bsd/atf/share/doc/Makefile new file mode 100644 index 000000000..1d3ffbf6c --- /dev/null +++ b/external/bsd/atf/share/doc/Makefile @@ -0,0 +1,5 @@ +# $NetBSD: Makefile,v 1.1 2009/01/19 07:13:04 jmmv Exp $ + +SUBDIR= atf + +.include diff --git a/external/bsd/atf/share/doc/atf/Makefile b/external/bsd/atf/share/doc/atf/Makefile new file mode 100644 index 000000000..11e9afb6d --- /dev/null +++ b/external/bsd/atf/share/doc/atf/Makefile @@ -0,0 +1,28 @@ +# $NetBSD: Makefile,v 1.4 2010/11/02 14:41:32 njoly Exp $ + +.include + +SRCDIR= ${NETBSDSRCDIR}/external/bsd/atf/dist +.PATH: ${SRCDIR} +.PATH: ${SRCDIR}/atf-c +.PATH: ${SRCDIR}/atf-c++ +.PATH: ${SRCDIR}/atf-sh +.PATH: ${SRCDIR}/doc + +.if ${MKDOC} != "no" +FILESDIR= /usr/share/doc/atf +FILES= AUTHORS COPYING NEWS README +.endif + +MAN= atf.7 atf-formats.5 atf-test-case.4 atf-test-program.1 + +CLEANFILES+= atf.7 atf.7.tmp +atf.7: atf.7.in + ${TOOL_SED} \ + -e 's,__DOCDIR__,/usr/share/doc/atf,g' \ + -e 's,__TESTSDIR__,/usr/tests,g' \ + <${SRCDIR}/doc/atf.7.in >atf.7.tmp + mv atf.7.tmp atf.7 + +.include +.include diff --git a/external/bsd/atf/share/examples/Makefile b/external/bsd/atf/share/examples/Makefile new file mode 100644 index 000000000..1d3ffbf6c --- /dev/null +++ b/external/bsd/atf/share/examples/Makefile @@ -0,0 +1,5 @@ +# $NetBSD: Makefile,v 1.1 2009/01/19 07:13:04 jmmv Exp $ + +SUBDIR= atf + +.include diff --git a/external/bsd/atf/share/examples/atf/Makefile b/external/bsd/atf/share/examples/atf/Makefile new file mode 100644 index 000000000..c5fea0b1a --- /dev/null +++ b/external/bsd/atf/share/examples/atf/Makefile @@ -0,0 +1,16 @@ +# $NetBSD: Makefile,v 1.3 2010/06/04 08:33:41 jmmv Exp $ + +.include + +.if ${MKSHARE} != "no" +SRCDIR= ${NETBSDSRCDIR}/external/bsd/atf/dist +.PATH: ${SRCDIR}/atf-report +.PATH: ${SRCDIR}/atf-run/sample + +FILESDIR= /usr/share/examples/atf +FILESMODE= 444 +FILES= atf-run.hooks \ + tests-results.css +.endif + +.include diff --git a/external/bsd/atf/share/xml/Makefile b/external/bsd/atf/share/xml/Makefile new file mode 100644 index 000000000..e64942c38 --- /dev/null +++ b/external/bsd/atf/share/xml/Makefile @@ -0,0 +1,5 @@ +# $NetBSD: Makefile,v 1.1 2009/01/19 07:13:05 jmmv Exp $ + +SUBDIR= atf + +.include diff --git a/external/bsd/atf/share/xml/atf/Makefile b/external/bsd/atf/share/xml/atf/Makefile new file mode 100644 index 000000000..6c0bef2c0 --- /dev/null +++ b/external/bsd/atf/share/xml/atf/Makefile @@ -0,0 +1,14 @@ +# $NetBSD: Makefile,v 1.3 2010/06/04 08:33:41 jmmv Exp $ + +.include + +.if ${MKSHARE} != "no" +SRCDIR= ${NETBSDSRCDIR}/external/bsd/atf/dist +.PATH: ${SRCDIR}/atf-report + +FILESDIR= /usr/share/xml/atf +FILESMODE= 444 +FILES= tests-results.dtd +.endif + +.include diff --git a/external/bsd/atf/share/xsl/Makefile b/external/bsd/atf/share/xsl/Makefile new file mode 100644 index 000000000..e64942c38 --- /dev/null +++ b/external/bsd/atf/share/xsl/Makefile @@ -0,0 +1,5 @@ +# $NetBSD: Makefile,v 1.1 2009/01/19 07:13:05 jmmv Exp $ + +SUBDIR= atf + +.include diff --git a/external/bsd/atf/share/xsl/atf/Makefile b/external/bsd/atf/share/xsl/atf/Makefile new file mode 100644 index 000000000..0ab1495a9 --- /dev/null +++ b/external/bsd/atf/share/xsl/atf/Makefile @@ -0,0 +1,14 @@ +# $NetBSD: Makefile,v 1.3 2010/06/04 08:33:41 jmmv Exp $ + +.include + +.if ${MKSHARE} != "no" +SRCDIR= ${NETBSDSRCDIR}/external/bsd/atf/dist +.PATH: ${SRCDIR}/atf-report + +FILESDIR= /usr/share/xsl/atf +FILESMODE= 444 +FILES= tests-results.xsl +.endif + +.include diff --git a/external/bsd/atf/tests/Makefile b/external/bsd/atf/tests/Makefile new file mode 100644 index 000000000..e64942c38 --- /dev/null +++ b/external/bsd/atf/tests/Makefile @@ -0,0 +1,5 @@ +# $NetBSD: Makefile,v 1.1 2009/01/19 07:13:05 jmmv Exp $ + +SUBDIR= atf + +.include diff --git a/external/bsd/atf/tests/atf/Makefile b/external/bsd/atf/tests/atf/Makefile new file mode 100644 index 000000000..a6d4b688e --- /dev/null +++ b/external/bsd/atf/tests/atf/Makefile @@ -0,0 +1,21 @@ +# $NetBSD: Makefile,v 1.7 2013/02/25 00:22:11 jmmv Exp $ + +.include + +TESTSDIR= ${TESTSBASE}/atf + +TESTS_SUBDIRS= atf-c \ + atf-c++ \ + atf-sh \ + test-programs + +.if !(${MKKYUA} != "no") +TESTS_SUBDIRS+= atf-config \ + atf-report \ + atf-run +.endif + +SRCDIR= ${NETBSDSRCDIR}/external/bsd/atf/dist +.PATH: ${SRCDIR} + +.include diff --git a/external/bsd/atf/tests/atf/atf-c++/Makefile b/external/bsd/atf/tests/atf/atf-c++/Makefile new file mode 100644 index 000000000..09a90ee21 --- /dev/null +++ b/external/bsd/atf/tests/atf/atf-c++/Makefile @@ -0,0 +1,36 @@ +# $NetBSD: Makefile,v 1.7 2012/07/11 22:40:16 jmmv Exp $ + +.include + +TESTS_SUBDIRS= detail + +TESTSDIR= ${TESTSBASE}/atf/atf-c++ +ATFFILE= yes + +SRCDIR= ${NETBSDSRCDIR}/external/bsd/atf/dist +.PATH: ${SRCDIR}/atf-c++ +.PATH: ${SRCDIR}/atf-c++/detail + +CPPFLAGS+= -DHAVE_CONFIG_H +CPPFLAGS+= -I${NETBSDSRCDIR}/lib/libatf-c++ + +FILESDIR= ${TESTSDIR} +FILES= macros_hpp_test.cpp +FILES+= unused_test.cpp + +TESTS_CXX= +.for test in atf_c++_test \ + build_test \ + check_test \ + config_test \ + macros_test \ + tests_test \ + utils_test +TESTS_CXX+= ${test} +SRCS.${test}= ${test}.cpp test_helpers.cpp +.endfor +.undef test + +TESTS_SH= pkg_config_test + +.include diff --git a/external/bsd/atf/tests/atf/atf-c++/detail/Makefile b/external/bsd/atf/tests/atf/atf-c++/detail/Makefile new file mode 100644 index 000000000..239534445 --- /dev/null +++ b/external/bsd/atf/tests/atf/atf-c++/detail/Makefile @@ -0,0 +1,31 @@ +# $NetBSD: Makefile,v 1.2 2013/02/15 17:08:35 jmmv Exp $ + +.include + +TESTSDIR= ${TESTSBASE}/atf/atf-c++/detail +ATFFILE= yes + +SRCDIR= ${NETBSDSRCDIR}/external/bsd/atf/dist +.PATH: ${SRCDIR}/atf-c++/detail + +CPPFLAGS+= -DHAVE_CONFIG_H +CPPFLAGS+= -I${NETBSDSRCDIR}/lib/libatf-c++ + +TESTS_CXX= +.for test in application_test \ + auto_array_test \ + env_test \ + exceptions_test \ + expand_test \ + fs_test \ + parser_test \ + process_test \ + sanity_test \ + text_test \ + ui_test +TESTS_CXX+= ${test} +SRCS.${test}= ${test}.cpp test_helpers.cpp +.endfor +.undef test + +.include diff --git a/external/bsd/atf/tests/atf/atf-c/Makefile b/external/bsd/atf/tests/atf/atf-c/Makefile new file mode 100644 index 000000000..6ae793c46 --- /dev/null +++ b/external/bsd/atf/tests/atf/atf-c/Makefile @@ -0,0 +1,38 @@ +# $NetBSD: Makefile,v 1.8 2012/07/11 22:40:16 jmmv Exp $ + +.include + +TESTS_SUBDIRS= detail + +TESTSDIR= ${TESTSBASE}/atf/atf-c +ATFFILE= yes + +SRCDIR= ${NETBSDSRCDIR}/external/bsd/atf/dist +.PATH: ${SRCDIR}/atf-c +.PATH: ${SRCDIR}/atf-c/detail + +CPPFLAGS+= -DHAVE_CONFIG_H +CPPFLAGS+= -I${NETBSDSRCDIR}/external/bsd/atf/lib/libatf-c + +FILESDIR= ${TESTSDIR} +FILES= macros_h_test.c +FILES+= unused_test.c + +TESTS_C= +.for test in atf_c_test \ + build_test \ + check_test \ + config_test \ + error_test \ + macros_test \ + tc_test \ + tp_test \ + utils_test +TESTS_C+= ${test} +SRCS.${test}= ${test}.c test_helpers.c +.endfor +.undef test + +TESTS_SH= pkg_config_test + +.include diff --git a/external/bsd/atf/tests/atf/atf-c/detail/Makefile b/external/bsd/atf/tests/atf/atf-c/detail/Makefile new file mode 100644 index 000000000..ce51c1891 --- /dev/null +++ b/external/bsd/atf/tests/atf/atf-c/detail/Makefile @@ -0,0 +1,38 @@ +# $NetBSD: Makefile,v 1.4 2013/02/15 17:08:35 jmmv Exp $ + +.include + +TESTSDIR= ${TESTSBASE}/atf/atf-c/detail +ATFFILE= yes + +SRCDIR= ${NETBSDSRCDIR}/external/bsd/atf/dist +.PATH: ${SRCDIR}/atf-c/detail + +CPPFLAGS+= -DHAVE_CONFIG_H +CPPFLAGS+= -I${NETBSDSRCDIR}/external/bsd/atf/lib/libatf-c + +PROGS= process_helpers +SRCS.process_helpers= process_helpers.c +MAN.process_helpers= # defined +BINDIR.process_helpers= ${TESTSDIR} + +TESTS_C= +.for test in dynstr_test \ + env_test \ + fs_test \ + list_test \ + map_test \ + process_test \ + sanity_test \ + text_test \ + user_test +TESTS_C+= ${test} +SRCS.${test}= ${test}.c test_helpers.c +.endfor +.undef test + +# Don't warn about functions which cannot be stack smash protected as +# there are a lot of them. +COPTS.dynstr_test.c= -Wno-stack-protector + +.include diff --git a/external/bsd/atf/tests/atf/atf-config/Makefile b/external/bsd/atf/tests/atf/atf-config/Makefile new file mode 100644 index 000000000..1517afa21 --- /dev/null +++ b/external/bsd/atf/tests/atf/atf-config/Makefile @@ -0,0 +1,15 @@ +# $NetBSD: Makefile,v 1.3 2010/07/13 21:12:38 jmmv Exp $ + +.include + +TESTSDIR= ${TESTSBASE}/atf/atf-config +ATFFILE= yes + +SRCDIR= ${NETBSDSRCDIR}/external/bsd/atf/dist +.PATH: ${SRCDIR}/atf-config + +CPPFLAGS+= -DHAVE_CONFIG_H + +TESTS_SH= integration_test + +.include diff --git a/external/bsd/atf/tests/atf/atf-report/Makefile b/external/bsd/atf/tests/atf/atf-report/Makefile new file mode 100644 index 000000000..a6e68b3e9 --- /dev/null +++ b/external/bsd/atf/tests/atf/atf-report/Makefile @@ -0,0 +1,23 @@ +# $NetBSD: Makefile,v 1.5 2010/10/20 09:20:11 jmmv Exp $ + +.include + +TESTSDIR= ${TESTSBASE}/atf/atf-report +ATFFILE= yes + +SRCDIR= ${NETBSDSRCDIR}/external/bsd/atf/dist +.PATH: ${SRCDIR}/atf-report +.PATH: ${SRCDIR}/atf-c++/detail + +TESTS_CXX= fail_helper +TESTS_CXX+= misc_helpers +TESTS_CXX+= pass_helper +TESTS_CXX+= reader_test +TESTS_SH= integration_test + +CPPFLAGS+= -DHAVE_CONFIG_H +CPPFLAGS+= -I${SRCDIR} + +SRCS.reader_test= reader_test.cpp reader.cpp test_helpers.cpp + +.include diff --git a/external/bsd/atf/tests/atf/atf-run/Makefile b/external/bsd/atf/tests/atf/atf-run/Makefile new file mode 100644 index 000000000..a0ea25898 --- /dev/null +++ b/external/bsd/atf/tests/atf/atf-run/Makefile @@ -0,0 +1,46 @@ +# $NetBSD: Makefile,v 1.6 2010/11/07 17:46:46 jmmv Exp $ + +.include + +TESTSDIR= ${TESTSBASE}/atf/atf-run +ATFFILE= yes + +SRCDIR= ${NETBSDSRCDIR}/external/bsd/atf/dist +.PATH: ${SRCDIR}/atf-run +.PATH: ${SRCDIR}/atf-c++ +.PATH: ${SRCDIR}/atf-c++/detail +.PATH: ${.CURDIR}/../../../lib/libatf-c + +CPPFLAGS+= -DHAVE_CONFIG_H +CPPFLAGS+= -I${SRCDIR}/atf-run +CPPFLAGS+= -I${SRCDIR} +CPPFLAGS+= -I${.CURDIR}/../../../lib/libatf-c + +TESTS_CXX= atffile_test +TESTS_CXX+= bad_metadata_helper +TESTS_CXX+= config_test +TESTS_CXX+= expect_helpers +TESTS_CXX+= fs_test +TESTS_CXX+= io_test +TESTS_CXX+= misc_helpers +TESTS_CXX+= pass_helper +TESTS_CXX+= requirements_test +TESTS_CXX+= several_tcs_helper +TESTS_CXX+= signals_test +TESTS_CXX+= test_program_test +TESTS_CXX+= user_test +TESTS_CXX+= zero_tcs_helper +TESTS_SH= integration_test + +SRCS.atffile_test= atffile_test.cpp atffile.cpp test_helpers.cpp +SRCS.config_test= config_test.cpp config.cpp test_helpers.cpp +SRCS.fs_test= fs_test.cpp fs.cpp test_helpers.cpp user.cpp +SRCS.io_test= io_test.cpp io.cpp signals.cpp test_helpers.cpp +SRCS.requirements_test= requirements_test.cpp requirements.cpp user.cpp +SRCS.signals_test= signals_test.cpp signals.cpp +SRCS.test_program_test= fs.cpp io.cpp requirements.cpp signals.cpp \ + test_helpers.cpp test_program_test.cpp \ + test-program.cpp timer.cpp user.cpp +SRCS.user_test= user_test.cpp user.cpp + +.include diff --git a/external/bsd/atf/tests/atf/atf-sh/Makefile b/external/bsd/atf/tests/atf/atf-sh/Makefile new file mode 100644 index 000000000..78bcb9a5f --- /dev/null +++ b/external/bsd/atf/tests/atf/atf-sh/Makefile @@ -0,0 +1,22 @@ +# $NetBSD: Makefile,v 1.5 2010/10/20 09:20:12 jmmv Exp $ + +.include + +TESTSDIR= ${TESTSBASE}/atf/atf-sh +ATFFILE= yes + +SRCDIR= ${NETBSDSRCDIR}/external/bsd/atf/dist +.PATH: ${SRCDIR}/atf-sh + +CPPFLAGS+= -DHAVE_CONFIG_H + +TESTS_SH= atf-check_test +TESTS_SH+= atf_check_test +TESTS_SH+= config_test +TESTS_SH+= integration_test +TESTS_SH+= misc_helpers +TESTS_SH+= normalize_test +TESTS_SH+= tc_test +TESTS_SH+= tp_test + +.include diff --git a/external/bsd/atf/tests/atf/test-programs/Makefile b/external/bsd/atf/tests/atf/test-programs/Makefile new file mode 100644 index 000000000..4d5b21a1b --- /dev/null +++ b/external/bsd/atf/tests/atf/test-programs/Makefile @@ -0,0 +1,24 @@ +# $NetBSD: Makefile,v 1.3 2013/02/15 17:08:35 jmmv Exp $ + +.include + +TESTSDIR= ${TESTSBASE}/atf/test-programs +ATFFILE= yes + +SRCDIR= ${NETBSDSRCDIR}/external/bsd/atf/dist +.PATH: ${SRCDIR}/test-programs + +CPPFLAGS+= -DHAVE_CONFIG_H +CPPFLAGS+= -I${SRCDIR}/libs -I${SRCDIR} + +TESTS_C= c_helpers + +TESTS_CXX= cpp_helpers + +TESTS_SH= sh_helpers +.for t in config_test expect_test meta_data_test result_test srcdir_test +TESTS_SH+= ${t} +TESTS_SH_SRC_${t}= common.sh ${t}.sh +.endfor + +.include diff --git a/external/bsd/atf/usr.bin/Makefile b/external/bsd/atf/usr.bin/Makefile new file mode 100644 index 000000000..7c2022491 --- /dev/null +++ b/external/bsd/atf/usr.bin/Makefile @@ -0,0 +1,10 @@ +# $NetBSD: Makefile,v 1.4 2013/02/25 00:22:11 jmmv Exp $ + +.include + +SUBDIR= atf-sh +.if !(${MKKYUA} != "no") +SUBDIR+= atf-config atf-report atf-run atf-version +.endif + +.include diff --git a/external/bsd/atf/usr.bin/Makefile.inc b/external/bsd/atf/usr.bin/Makefile.inc new file mode 100644 index 000000000..03a45fbc5 --- /dev/null +++ b/external/bsd/atf/usr.bin/Makefile.inc @@ -0,0 +1,3 @@ +# $NetBSD: Makefile.inc,v 1.1 2013/03/14 07:10:06 jmmv Exp $ + +.include "../Makefile.inc" diff --git a/external/bsd/atf/usr.bin/atf-config/Makefile b/external/bsd/atf/usr.bin/atf-config/Makefile new file mode 100644 index 000000000..abd750b92 --- /dev/null +++ b/external/bsd/atf/usr.bin/atf-config/Makefile @@ -0,0 +1,21 @@ +# $NetBSD: Makefile,v 1.5 2011/02/20 20:18:57 jmmv Exp $ + +.include + +SRCDIR= ${NETBSDSRCDIR}/external/bsd/atf/dist +.PATH: ${SRCDIR}/atf-config + +BINDIR= /usr/bin +PROG_CXX= atf-config +SRCS= atf-config.cpp +MAN= atf-config.1 + +LDADD+= -latf-c++ -latf-c +DPADD+= ${LIBATF_CXX} ${LIBATF_C} + +CPPFLAGS+= -DHAVE_CONFIG_H +CPPFLAGS+= -I${SRCDIR} + +WARNS?= 2 + +.include diff --git a/external/bsd/atf/usr.bin/atf-report/Makefile b/external/bsd/atf/usr.bin/atf-report/Makefile new file mode 100644 index 000000000..21ab3e91b --- /dev/null +++ b/external/bsd/atf/usr.bin/atf-report/Makefile @@ -0,0 +1,23 @@ +# $NetBSD: Makefile,v 1.6 2012/06/16 17:02:33 joerg Exp $ + +.include + +SRCDIR= ${NETBSDSRCDIR}/external/bsd/atf/dist +.PATH: ${SRCDIR}/atf-report + +BINDIR= /usr/bin +PROG_CXX= atf-report +SRCS= atf-report.cpp reader.cpp +MAN= atf-report.1 + +LDADD+= -latf-c++ -latf-c +DPADD+= ${LIBATF_CXX} ${LIBATF_C} + +CPPFLAGS+= -DHAVE_CONFIG_H +CPPFLAGS+= -I${SRCDIR} + +WARNS?= 2 + +CWARNFLAGS.clang+= -Wno-error=unused-private-field + +.include diff --git a/external/bsd/atf/usr.bin/atf-run/Makefile b/external/bsd/atf/usr.bin/atf-run/Makefile new file mode 100644 index 000000000..c972fc48f --- /dev/null +++ b/external/bsd/atf/usr.bin/atf-run/Makefile @@ -0,0 +1,35 @@ +# $NetBSD: Makefile,v 1.11 2012/06/16 17:02:33 joerg Exp $ + +.include + +SRCDIR= ${NETBSDSRCDIR}/external/bsd/atf/dist +.PATH: ${SRCDIR}/atf-run +.PATH: ${SRCDIR}/atf-run/share +.PATH: ${.CURDIR}/../../lib/libatf-c + +BINDIR= /usr/bin +PROG_CXX= atf-run +SRCS= atf-run.cpp atffile.cpp config.cpp fs.cpp io.cpp requirements.cpp \ + signals.cpp test-program.cpp timer.cpp user.cpp +MAN= atf-run.1 + +CPPFLAGS+= -DGDB=\"/usr/bin/gdb\" +CPPFLAGS+= -DHAVE_CONFIG_H +CPPFLAGS+= -I${SRCDIR} +CPPFLAGS+= -I${.CURDIR}/../../lib/libatf-c +LDADD+= -latf-c++ -latf-c +DPADD+= ${LIBATF_CXX} ${LIBATF_C} + +CWARNFLAGS.clang+= -Wno-error=unused-private-field + +COPTS.atf-run.cpp+= -Wno-stack-protector + +WARNS?= 2 + +.if ${MKSHARE} != "no" +FILESDIR= /usr/share/atf +FILESMODE= 444 +FILES= atf-run.hooks +.endif + +.include diff --git a/external/bsd/atf/usr.bin/atf-sh/Makefile b/external/bsd/atf/usr.bin/atf-sh/Makefile new file mode 100644 index 000000000..ebd23bdfe --- /dev/null +++ b/external/bsd/atf/usr.bin/atf-sh/Makefile @@ -0,0 +1,38 @@ +# $NetBSD: Makefile,v 1.9 2013/03/14 07:10:07 jmmv Exp $ + +.include + +.PATH: ${SRCDIR}/atf-sh +.PATH: ${TOPDIR}/lib/libatf-c # For bconfig.h. + +BINDIR= /usr/bin +PROG_CXX= atf-sh +SRCS= atf-sh.cpp +MAN= atf-sh.1 atf-sh-api.3 + +LDADD+= -latf-c++ -latf-c +DPADD+= ${LIBATF_CXX} ${LIBATF_C} + +CPPFLAGS+= -DHAVE_CONFIG_H +CPPFLAGS+= -I${SRCDIR} + +WARNS?= 2 + +.if ${MKSHARE} != "no" +FILESMODE= 444 + +FILES+= libatf-sh.subr +FILESDIR_libatf-sh.subr= /usr/share/atf + +FILES+= atf-sh.pc +FILESDIR_atf-sh.pc= /usr/lib/pkgconfig + +realall: atf-sh.pc +atf-sh.pc: Makefile atf-sh.pc.in bconfig.h + ${TOOL_SED} -e 's,__ATF_VERSION__,${ATF_VERSION},g' \ + -e 's,__EXEC_PREFIX__,/usr,g' \ + <${SRCDIR}/atf-sh/atf-sh.pc.in >atf-sh.pc +CLEANFILES+= atf-sh.pc +.endif + +.include diff --git a/external/bsd/atf/usr.bin/atf-version/Makefile b/external/bsd/atf/usr.bin/atf-version/Makefile new file mode 100644 index 000000000..3bbc6661b --- /dev/null +++ b/external/bsd/atf/usr.bin/atf-version/Makefile @@ -0,0 +1,22 @@ +# $NetBSD: Makefile,v 1.7 2011/02/20 20:18:57 jmmv Exp $ + +.include + +SRCDIR= ${NETBSDSRCDIR}/external/bsd/atf/dist +.PATH: ${SRCDIR}/admin ${SRCDIR}/atf-version + +BINDIR= /usr/bin +PROG_CXX= atf-version +SRCS= atf-version.cpp +MAN= atf-version.1 + +CPPFLAGS+= -DHAVE_CONFIG_H +CPPFLAGS+= -I${SRCDIR} +CPPFLAGS+= -I${.CURDIR}/../../lib/libatf-c +CPPFLAGS+= -I${.CURDIR} +LDADD+= -latf-c++ -latf-c +DPADD+= ${LIBATF_CXX} ${LIBATF_C} + +WARNS?= 2 + +.include diff --git a/external/bsd/atf/usr.bin/atf-version/revision.h b/external/bsd/atf/usr.bin/atf-version/revision.h new file mode 100644 index 000000000..1b10c23c1 --- /dev/null +++ b/external/bsd/atf/usr.bin/atf-version/revision.h @@ -0,0 +1,3 @@ +/* $NetBSD: revision.h,v 1.1 2010/07/03 08:14:13 jmmv Exp $ */ + +#define PACKAGE_REVISION_TYPE_DIST diff --git a/external/bsd/kyua-atf-compat/Makefile b/external/bsd/kyua-atf-compat/Makefile new file mode 100644 index 000000000..c4409019f --- /dev/null +++ b/external/bsd/kyua-atf-compat/Makefile @@ -0,0 +1,10 @@ +# $NetBSD: Makefile,v 1.1 2013/02/25 00:20:08 jmmv Exp $ + +SUBDIR= share tests usr.bin + +.for dir in share tests usr.bin +includes-${dir}: .PHONY + @true +.endfor + +.include diff --git a/external/bsd/kyua-atf-compat/Makefile.inc b/external/bsd/kyua-atf-compat/Makefile.inc new file mode 100644 index 000000000..ce25182fb --- /dev/null +++ b/external/bsd/kyua-atf-compat/Makefile.inc @@ -0,0 +1,14 @@ +# $NetBSD: Makefile.inc,v 1.1 2013/02/25 00:20:08 jmmv Exp $ + +SRCDIR= ${NETBSDSRCDIR}/external/bsd/kyua-atf-compat/dist +.PATH: ${SRCDIR} + +BUILD_SCRIPT = \ + sed -e 's,__ATF_CONFDIR__,/etc/atf,g' \ + -e 's,__ATF_SH__,/usr/bin/atf-sh,g' \ + -e 's,__BINDIR__,/usr/bin,g' \ + -e 's,__PKGDATADIR__,/usr/share/kyua-atf-compat,g' \ + -e 's,__SH__,/bin/sh,g' \ + ${SRCDIR}/$${src} >$${dst}.new && \ + chmod +x $${dst}.new && \ + mv $${dst}.new $${dst} diff --git a/external/bsd/kyua-atf-compat/dist/AUTHORS b/external/bsd/kyua-atf-compat/dist/AUTHORS new file mode 100644 index 000000000..0f707683a --- /dev/null +++ b/external/bsd/kyua-atf-compat/dist/AUTHORS @@ -0,0 +1 @@ +* Julio Merino diff --git a/external/bsd/kyua-atf-compat/dist/COPYING b/external/bsd/kyua-atf-compat/dist/COPYING new file mode 100644 index 000000000..be29aafc5 --- /dev/null +++ b/external/bsd/kyua-atf-compat/dist/COPYING @@ -0,0 +1,27 @@ +Copyright 2011, 2012 Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +* Neither the name of Google Inc. nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/external/bsd/kyua-atf-compat/dist/Kyuafile b/external/bsd/kyua-atf-compat/dist/Kyuafile new file mode 100644 index 000000000..88567ac48 --- /dev/null +++ b/external/bsd/kyua-atf-compat/dist/Kyuafile @@ -0,0 +1,7 @@ +syntax('kyuafile', 1) + +test_suite('kyua') + +atf_test_program{name='atf-run_test'} +atf_test_program{name='atf-report_test'} +atf_test_program{name='atf2kyua_test'} diff --git a/external/bsd/kyua-atf-compat/dist/NEWS b/external/bsd/kyua-atf-compat/dist/NEWS new file mode 100644 index 000000000..e315ff309 --- /dev/null +++ b/external/bsd/kyua-atf-compat/dist/NEWS @@ -0,0 +1,12 @@ +Changes in version 0.1 +====================== + +Experimental version released on June 10th, 2012. + +This is the first public release of the kyua-atf-compat package. + +This first release is paired with the 0.16 release of ATF, which +disables the build of atf-run and atf-report by default. The goal +of this package is, then, to provide compatibility utilities for +these disabled tools but using Kyua as the backend for the execution +of the tests. diff --git a/external/bsd/kyua-atf-compat/dist/README b/external/bsd/kyua-atf-compat/dist/README new file mode 100644 index 000000000..ee5f1d49d --- /dev/null +++ b/external/bsd/kyua-atf-compat/dist/README @@ -0,0 +1,22 @@ +Kyua (pronounced Q.A.) is a testing framework for both developers and +users. Kyua is different from most other testing frameworks in that it +puts the end user experience before anything else. There are multiple +reasons for users to run the tests themselves, and Kyua ensures that +they can do so in the most convenient way. + +This module, kyua-atf-compat, provides tools to ease the transition from +ATF to Kyua. In particular, this includes a tool to convert Atffile +files to Kyuafile files in an automated manner, and drop-in replacement +wrappers for both atf-run and atf-report. + +For further information on the contents of this distribution file, +please refer to the following other documents: + +* AUTHORS: List of authors and contributors to this project. +* COPYING: License information. +* INSTALL: Compilation and installation instructions. +* NEWS: List of major changes between formal releases. + +For general project information, please visit: + + http://code.google.com/p/kyua/ diff --git a/external/bsd/kyua-atf-compat/dist/atf-report.1 b/external/bsd/kyua-atf-compat/dist/atf-report.1 new file mode 100644 index 000000000..0407526ff --- /dev/null +++ b/external/bsd/kyua-atf-compat/dist/atf-report.1 @@ -0,0 +1,173 @@ +.\" Copyright 2012 Google Inc. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are +.\" met: +.\" +.\" * Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" * Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" * Neither the name of Google Inc. nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.Dd June 16, 2012 +.Dt ATF-REPORT 1 +.Os +.Sh NAME +.Nm atf-report +.Nd Kyua-based implementation of the deprecated atf-report +.Sh SYNOPSIS +.Nm +.Op Fl o Ar fmt1:path1 Op .. Fl o Ar fmtN:pathN +.Sh DESCRIPTION +.Em DISCLAIMER : +This version of +.Nm +provides a reimplementation of ATF's reporting engine built on top of Kyua. +This is a transitional script and should only be considered a helper to +migrate away from ATF. +Therefore, this version of +.Nm +mimics the +.Em behavior +of the original +.Nm +but +.Em NOT +the specific output of the command. +The output of this implementation is significantly different as that of the +original one. +Please migrate to using +.Sq kyua test +as soon as feasible. +See the +.Sx Migration path +section below for further details. +.Pp +.Nm +reads the output of +.Nm atf-run +and transforms it to different formats. +Some of these are user-friendly and others are machine-parseable, which +opens a wide range of possibilities to analyze the results of a test +suite's execution. +See +.Sx Output formats +below for more details on which these formats are. +.Pp +In the first synopsis form, +.Nm +reads the output of +.Nm atf-run +through its standard input and, if no +.Fl o +option is given, prints a user-friendly report on its standard +output using the +.Sq ticker +format. +If the +.Fl o +option is provided, it specifies the output format to use and its +destination. +.Pp +The following options are available: +.Bl -tag -width XoXfmtXpathXX +.It Fl o Ar fmt:path +Adds a new output format. +.Ar fmt +is one of the formats described later on in +.Sx Output formats . +.Ar path +specifies where the report will be written to. +Depending on the chosen format, this may refer to a single file or to +a directory. +For those formats that write to a single file, specifying a +.Sq - +as the path will redirect the report to the standard output. +.El +.Ss Output formats +The following output formats are allowed: +.Bl -tag -width tickerXX +.It ticker +A user-friendly report that shows the progress of the test suite's +execution as it operates. +This type of report should always be redirected to a virtual terminal, +not a file, as it may use control sequences that will make the output +unreadable in regular files. +.It html +A multi-file HTML report. +The specified output file will be a symlink into a directory containing +all the other support files for the HTML report. +.Pp +This format was not originally supported by +.Nm , +but is the right name for the compatibility +.Sq xml +support. +.It xml +A compatibility name for +.Sq html . +The original +.Nm +was only able to generate XML reports and relied on tools like +.Xr xsltproc 1 +to convert them to HTML. +The process was quite convoluted and inconvenient. +Kyua, on the other hand, is only able to create HTML reports at the +moment. +.El +.Pp +.Ss Migration path +Moving from +.Nm +to +.Sq kyua report +is rather simple. +.Pp +The most important thing to understand during the transition is that +.Sq kyua test +stores the output of the execution in a database and does not print a +machine-parseable log to its stdout. +Instead, +.Sq kyua report +is used as a second step to extract reports from the database for any +previously executed test. +.Pp +The following examples show how to convert some common +.Nm +invocations to their corresponding +.Sq kyua report +ones. +Because +.Nm +has always been tied to +.Xr atf-run 1 , +these examples also mention the latter. +.Bd -literal -offset indent +### Run all tests, with a summary at the end. +$ atf-run | atf-report +$ kyua test && kyua report + +### Generate a HTML report. +$ atf-run | atf-report -o xml:report.xml + ... plus some complex file manipulation and xsltproc magic ... +$ kyua test && kyua report-html -o path/to/report/ +.Ed +.Sh SEE ALSO +.Xr kyua 1 , +.Xr atf-run 1 diff --git a/external/bsd/kyua-atf-compat/dist/atf-report.sh b/external/bsd/kyua-atf-compat/dist/atf-report.sh new file mode 100644 index 000000000..c8d1034b4 --- /dev/null +++ b/external/bsd/kyua-atf-compat/dist/atf-report.sh @@ -0,0 +1,191 @@ +#! __SH__ +# Copyright 2012 Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Google Inc. nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# \file atf-report.sh +# Kyua-based compatibility replacement for atf-report. + + +. "${KYUA_ATF_COMPAT_PKGDATADIR:-__PKGDATADIR__}/lib.subr" + + +# Gets the action identifier from the output of 'kyua test'. +# +# \param file The file that contains the output of 'kyua test'. Can be +# /dev/stdout. +# +# \post Prints the action identifier. +get_action() { + local file="${1}"; shift + grep '^Committed action ' "${file}" | cut -d ' ' -f 3 +} + + +# Generates an HTML report. +# +# The original atf-report generates HTML reports that are made up of solely a +# single HTML page. Because of this, such reports can be written directly to +# the file specified by the user. +# +# Because Kyua generates "rich" HTML reports (i.e. reports that consist of more +# than one HTML page), we cannot perfectly emulate atf-report. Instead, we +# create an auxiliary directory to hold all the files, and then place a link to +# such files in the file specified by the user. The drawback is that HTML +# reports sent to stdout are no longer possible. +# +# \param output_file The name of the file to which to write the HTML report. +# This file will end up being a symlink to the real report. +report_html() { + local output_file="${1}"; shift + + [ "${output_file}" != "/dev/stdout" ] || \ + lib_usage_error "Cannot write HTML reports to stdout" + + local dir="$(dirname "${output_file}")" + local index_name="${output_file##*/}" + local files_name="$(echo "${index_name}" | sed -e 's,\.[a-zA-Z]*$,,').files" + + kyua report-html --action="$(get_action /dev/stdin)" \ + --output="${dir}/${files_name}" + + echo "Pointing ${index_name} to ${files_name}/index.html" + ( cd "${dir}" && ln -s "${files_name}/index.html" "${index_name}" ) +} + + +# Genereates an XML report. +# +# For our compatibility purposes, we assume that the XML report is just an HTML +# report. +# +# \param output_file The name of the file to which to write the HTML report. +# This file will end up being a symlink to the real report. +report_xml() { + local output_file="${1}"; shift + + lib_warning "XML output not supported; generating HTML instead" + report_html "${output_file}" +} + + +# Generates progressive textual reports. +# +# This wrapper attempts to emulate atf-report's ticker output by reading the +# output of 'kyua test' progressively and sending it to the screen as soon as it +# becomes available. The tail of the 'kyua test' report that includes summaries +# for the run is suppressed and is replaced with the more-detailed output of +# 'kyua report'. +# +# \param output_file The name of the file to which to write the textual report. +# Can be /dev/stdout. +report_ticker() { + local output_file="${1}"; shift + + local print=yes + while read line; do + [ -n "${line}" ] || print=no + + if [ "${print}" = yes ]; then + case "${line}" in + Committed*) + echo "${line}" >>"${Lib_TempDir}/output" + ;; + *) + echo "${line}" + ;; + esac + else + echo "${line}" >>"${Lib_TempDir}/output" + fi + done + + kyua report --action="$(get_action "${Lib_TempDir}/output")" \ + --output="${output_file}" +} + + +# Generates a report based on an output specification. +# +# \param output_spec The format:file specification of the output. +report() { + local output_spec="${1}"; shift + + local output_format="$(echo "${output_spec}" | cut -d : -f 1)" + local output_file="$(echo "${output_spec}" | cut -d : -f 2)" + [ "${output_file}" != - ] || output_file=/dev/stdout + + case "${output_format}" in + html|ticker|xml) + "report_${output_format}" "${output_file}" + ;; + + *) + lib_usage_error "Unknown output format '${output_format}'" + ;; + esac +} + + +# Prints program usage to stdout. +# +# \param progname The name of the program to use for the syntax help. +usage() { + local progname="${1}"; shift + echo "Usage: ${progname} [-o output-spec]" +} + + +# Entry point for the program. +# +# \param ... The user-provided arguments. +main() +{ + local output_spec="ticker:-" + while getopts ':o:' arg "${@}"; do + case "${arg}" in + o) + output_spec="${OPTARG}" + ;; + \?) + lib_usage_error "Unknown option -${OPTARG}" + ;; + esac + done + shift $((${OPTIND} - 1)) + + [ ${#} -eq 0 ] || lib_usage_error "No arguments allowed" + + lib_init_tempdir + + report "${output_spec}" + + lib_cleanup +} + + +main "${@}" diff --git a/external/bsd/kyua-atf-compat/dist/atf-report_test.sh b/external/bsd/kyua-atf-compat/dist/atf-report_test.sh new file mode 100644 index 000000000..70870a7fb --- /dev/null +++ b/external/bsd/kyua-atf-compat/dist/atf-report_test.sh @@ -0,0 +1,250 @@ +#! __ATF_SH__ +# Copyright 2012 Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Google Inc. nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +. "${KYUA_ATF_COMPAT_PKGDATADIR:-__PKGDATADIR__}/tests_lib.subr" + + +atf_test_case ticker__no_tests +ticker__no_tests_body() { + cat >Kyuafile <expout < Summary +Action: 1 +Test cases: 0 total, 0 skipped, 0 expected failures, 0 broken, 0 failed +Total time: X.XXXs +EOF + atf_check -s exit:0 -o save:report.log -e empty atf-report Kyuafile <expout < skipped: Skipped reason [X.XXXs] +program2:fail -> failed: On purpose [X.XXXs] +program2:skip -> skipped: Skipped reason [X.XXXs] +program2:pass -> passed [X.XXXs] +===> Skipped tests +program1:skip -> skipped: Skipped reason [X.XXXs] +program2:skip -> skipped: Skipped reason [X.XXXs] +===> Failed tests +program2:fail -> failed: On purpose [X.XXXs] +===> Summary +Action: 1 +Test cases: 4 total, 2 skipped, 0 expected failures, 0 broken, 1 failed +Total time: X.XXXs +EOF + atf_check -s exit:0 -o save:report.log -e empty atf-report Kyuafile <expout < Summary +Action: 1 +Test cases: 0 total, 0 skipped, 0 expected failures, 0 broken, 0 failed +Total time: X.XXXs +EOF + atf_check -s exit:0 -o empty -e empty \ + atf-report -o ticker:my-report.log Kyuafile <Kyuafile <Kyuafile <Kyuafile <.conf . +.It +Configuration variables defined in the user-specific configuration file +shared among all test suites. +This lives in +.Pa ${HOME}/.atf/common.conf . +.It +Configuration variables defined in the user-specific test-suite-specific +configuration file. +This lives in +.Pa ${HOME}/.atf/.conf . +.It +Configuration variables provided as part of the command line through the +.Fl v +option. +.El +.Pp +The value of +.Va ATF_CONFDIR +in the above list is determined by the build settings of the +.Nm +script, but its value can be overriden by setting such variable in the +environment. +.Pp +The following configuration variables are globally recognized: +.Bl -tag -width XunprivilegedXuserXX +.It Va unprivileged-user +The name of the system user that atf-run will drop root privileges into +for test cases defining +.Sq require.user=unprivileged . +Note that this is +.Em not provided for security purposes ; +this feature is only for the convenience of the user. +.El +.Ss Migration path +Moving from +.Nm +to +.Sq kyua test +is rather simple. +.Pp +The first step is converting all of your Atffiles to Kyuafiles. +The +.Xr atf2kyua 1 +script will help you in performing this initial conversion. +.Pp +Once all the Kyuafiles are in place, the following examples show how to +convert some common +.Nm +invocations to their corresponding +.Sq kyua test +ones. +.Bd -literal -offset indent +### Run all tests. +$ atf-run +$ kyua test + +### Run specific test programs. +$ atf-run dir1/foo_test bar_test +$ kyua test dir1/foo_test bar_test + +### Set configuration variables; foo is the name of your test suite. +$ atf-run -v unprivileged-user=nobody -v iterations=10 +$ kyua test -v unprivileged-user=nobody -v test_suite.foo.iterations=10 +.Ed +.Pp +That said, +.Xr kyua 1 +is way more flexible than +.Nm +ever was. +Please see Kyua's documentation or built-in command-line help to explore +all the additional features included. +.Sh SEE ALSO +.Xr kyua 1 , +.Xr atf-report 1 diff --git a/external/bsd/kyua-atf-compat/dist/atf-run.sh b/external/bsd/kyua-atf-compat/dist/atf-run.sh new file mode 100644 index 000000000..3dda25fec --- /dev/null +++ b/external/bsd/kyua-atf-compat/dist/atf-run.sh @@ -0,0 +1,197 @@ +#! __SH__ +# Copyright 2012 Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Google Inc. nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# \file atf-run.sh +# Kyua-based compatibility replacement for atf-run. + + +. "${KYUA_ATF_COMPAT_PKGDATADIR:-__PKGDATADIR__}/lib.subr" + + +# Path to ATF's configuration directory. +ATF_CONFDIR="${ATF_CONFDIR:-__ATF_CONFDIR__}" + + +# Path to the bin directory where we got installed. +BINDIR="${KYUA_ATF_COMPAT_BINDIR:-__BINDIR__}" + + +# Loads configuration variables from a set of files. +# +# \param dir The directory from which to load the configuration files. +# \param output_var The name of the variable that will accumulate all the +# --variable flags to represent the configuration file. +load_configs() { + local dir="${1}"; shift + local output_var="${1}"; shift + + local all_vars= + for file in "${dir}"/*; do + [ "${file}" != "${dir}/*" ] || break + + lib_info "Loading configuration from ${file}" + + local prefix + case "${file}" in + *common.conf) prefix= ;; + *) prefix="test_suites.$(basename "${file}" | sed -e 's,.conf$,,')." ;; + esac + + local ws='[ ]*' # That's a space and a tab. + local name='[a-zA-Z][-_a-zA-Z0-9]*' + local repl="--variable='${prefix}\\1=\\2'" + local vars="$(grep "^${ws}${name}${ws}=" "${file}" | \ + sed -e 's,#(.*)$,,;s,unprivileged-user,unprivileged_user,g' \ + -e "s,^${ws}\(${name}\)${ws}=${ws}'\([^']*\)'${ws}$,${repl}," \ + -e "s,^${ws}\(${name}\)${ws}=${ws}\"\([^\"]*\)\"${ws}$,${repl}," \ + -e "s,^${ws}\(${name}\)${ws}=${ws}\(.*\)$,${repl},")" + + lib_info "Extracted arguments: ${vars}" + all_vars="${all_vars} ${vars}" + done + eval ${output_var}=\'"${all_vars}"\' +} + + +# Transforms an atf-run -v specification to Kyua's semantics. +# +# \param raw The key=value argument to -v. +# \param ... The names of all the possible test suites. For test-suite specific +# variables, we expand them to all their possibilities as Kyua needs to know +# what test suite a particular variable belongs to. +# +# \post Prints one or more --variable arguments that match the input variable +# name. +convert_variable() { + local raw="${1}"; shift + + case "${raw}" in + unprivileged-user=*) + echo "--variable=${raw}" | \ + sed -e 's,unprivileged-user,unprivileged_user,g' + ;; + *) + for test_suite in "${@}"; do + echo "--variable=test_suites.${test_suite}.${raw}" + done + ;; + esac +} + + +# Collects all the test suite names defined in a subtree. +# +# \param dir The subtree to scan for Kyuafiles. +# +# \post Prints the names of all found test suites. +grab_test_suites() { + local dir="${1}"; shift + + find "${dir}" -name Kyuafile -exec grep "test_suite('" "{}" \; | \ + cut -d "'" -f 2 +} + + +# Gets the path to the compatibility Kyuafile. +# +# If a Kyuafile is found in the current directory, use that directly. +# Otherwise, generate a fake Kyuafile in a temporary directory and return +# that instead. +# +# \param [out] output_var The name of the variable to set with the path +# of the Kyuafile to be used. +select_kyuafile() { + local output_var="${1}"; shift + + if [ -f Kyuafile ]; then + eval ${output_var}=\'"$(pwd)/Kyuafile"\' + elif [ -f Atffile ]; then + "${BINDIR}/atf2kyua" -s "$(pwd)" -t "${Lib_TempDir}" || \ + lib_error "Cannot generate fake Kyuafile" + eval ${output_var}=\'"${Lib_TempDir}/Kyuafile"\' + else + lib_error "Cannot find Atffile nor Kyuafile" + fi +} + + +# Prints program usage to stdout. +# +# \param progname The name of the program to use for the syntax help. +usage() { + local progname="${1}"; shift + echo "Usage: ${progname} [-v var-value] [program1 [.. programN]]" +} + + +# Entry point for the program. +# +# \param ... The user-provided arguments. +main() { + local vflags= + + while getopts ':v:' arg "${@}"; do + case "${arg}" in + v) + vflags="${OPTARG} ${cli_variables}" + ;; + \?) + lib_usage_error "Unknown option -${OPTARG}" + ;; + esac + done + shift $((${OPTIND} - 1)) + + lib_init_tempdir + + load_configs "${ATF_CONFDIR}" "system_variables" # Sets system_variables. + load_configs "${HOME}/.atf" "user_variables" # Sets user_variables. + + local kyuafile_path + select_kyuafile "kyuafile_path" # Sets kyuafile_path. + + local test_suites="$(grab_test_suites "$(dirname "${kyuafile_path}")")" + + cli_variables= + for vflag in ${vflags}; do + local values="$(convert_variable "${vflag}" ${test_suites})" + cli_variables="${values} ${cli_variables}" + done + + kyua ${system_variables} ${user_variables} ${cli_variables} \ + test --kyuafile="${kyuafile_path}" --build-root="$(pwd)" "${@}" + local ret="${?}" + + lib_cleanup + + return "${ret}" +} + + +main "${@}" diff --git a/external/bsd/kyua-atf-compat/dist/atf-run_test.sh b/external/bsd/kyua-atf-compat/dist/atf-run_test.sh new file mode 100644 index 000000000..665800a1c --- /dev/null +++ b/external/bsd/kyua-atf-compat/dist/atf-run_test.sh @@ -0,0 +1,233 @@ +#! __ATF_SH__ +# Copyright 2012 Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Google Inc. nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +. "${KYUA_ATF_COMPAT_PKGDATADIR:-__PKGDATADIR__}/tests_lib.subr" + + +atf_test_case all_pass +all_pass_body() { + create_test_program program1 pass skip + create_atffile Atffile 'prop: test-suite = "suite"' \ + 'tp: program1' 'tp: subdir' + + mkdir subdir + create_test_program subdir/program2 skip + create_atffile subdir/Atffile 'prop: test-suite = "suite"' \ + 'tp: program2' + + atf_check -s exit:0 -e ignore \ + -o match:'program1:pass -> passed' \ + -o match:'program1:skip -> skipped' \ + -o match:'subdir/program2:skip -> skipped' \ + -o match:'Committed action 1' \ + atf-run +} + + +atf_test_case some_fail +some_fail_body() { + create_test_program program1 pass skip + create_atffile Atffile 'prop: test-suite = "suite"' \ + 'tp: program1' 'tp: subdir' + + mkdir subdir + create_atffile subdir/Atffile 'tp-glob: *' + + mkdir subdir/nested + create_test_program subdir/nested/program2 skip fail + create_atffile subdir/nested/Atffile 'prop: test-suite = "suite"' \ + 'tp-glob: program2*' + + atf_check -s exit:1 -e ignore \ + -o match:'program1:pass -> passed' \ + -o match:'program1:skip -> skipped' \ + -o match:'subdir/nested/program2:fail -> failed' \ + -o match:'subdir/nested/program2:skip -> skipped' \ + -o match:'Committed action 1' \ + atf-run +} + +atf_test_case prefer_kyuafiles +prefer_kyuafiles_body() { + create_test_program program1 pass skip + cat >Kyuafile <Atffile + + atf_check -s exit:0 -e ignore \ + -o match:'program1:pass -> passed' \ + -o match:'program1:skip -> skipped' \ + atf-run +} + + +atf_test_case selectors +selectors_body() { + create_test_program program1 pass skip + create_atffile Atffile 'prop: test-suite = "suite"' \ + 'tp: program1' 'tp: subdir' + + mkdir subdir + create_atffile subdir/Atffile 'tp-glob: *' + + mkdir subdir/nested + create_test_program subdir/nested/program2 skip fail + create_atffile subdir/nested/Atffile 'prop: test-suite = "suite"' \ + 'tp-glob: program2*' + + atf_check -s exit:1 -e ignore \ + -o match:'program1:pass -> passed' \ + -o match:'program1:skip -> skipped' \ + -o match:'subdir/nested/program2:fail -> failed' \ + -o match:'subdir/nested/program2:skip -> skipped' \ + -o match:'Committed action 1' \ + atf-run + + atf_check -s exit:0 -e ignore \ + -o match:'program1:pass -> passed' \ + -o not-match:'program1:skip -> skipped' \ + -o not-match:'subdir/nested/program2:fail -> failed' \ + -o match:'subdir/nested/program2:skip -> skipped' \ + -o match:'Committed action 2' \ + atf-run program1:pass subdir/nested/program2:skip + + atf_check -s exit:1 -e ignore \ + -o not-match:'program1:pass -> passed' \ + -o not-match:'program1:skip -> skipped' \ + -o match:'subdir/nested/program2:fail -> failed' \ + -o match:'subdir/nested/program2:skip -> skipped' \ + -o match:'Committed action 3' \ + atf-run subdir/nested/program2 +} + + +atf_test_case config__priorities +config__priorities_body() +{ + mkdir system + export ATF_CONFDIR="$(pwd)/system" + mkdir user + mkdir user/.atf + export HOME="$(pwd)/user" + + create_test_program helper config + create_atffile Atffile 'prop: test-suite = "irrelevant"' 'tp: helper' + + echo "Checking system-wide configuration only" + create_config system/common.conf ' unprivileged-user = "nobody"' + atf_check -s exit:0 -o 'match:helper:config -> passed' -e ignore atf-run + atf_check -s exit:0 -o 'inline:unprivileged-user = nobody\n' \ + cat config.out + + echo "Checking user-specific overrides" + create_config user/.atf/common.conf ' unprivileged-user = "root"' + atf_check -s exit:0 -o 'match:helper:config -> passed' -e ignore atf-run + atf_check -s exit:0 -o 'inline:unprivileged-user = root\n' \ + cat config.out + + echo "Checking command-line overrides" + atf_check -s exit:0 -o 'match:helper:config -> passed' -e ignore atf-run \ + -v"unprivileged-user=$(id -u -n)" + atf_check -s exit:0 -o "inline:unprivileged-user = $(id -u -n)\n" \ + cat config.out +} + + +atf_test_case config__test_suites__files +config__test_suites__files_body() +{ + mkdir system + export ATF_CONFDIR="$(pwd)/system" + + create_config system/suite1.conf 'var1 = "var1-for-suite1"' \ + 'var2 = "var2-for-suite1"' + create_config system/suite2.conf 'var1 = "var1-for-suite2"' \ + 'var2 = "var2-for-suite2"' + + create_test_program helper1 config + create_atffile Atffile 'prop: test-suite = "suite1"' 'tp: helper1' \ + 'tp: subdir' + mkdir subdir + create_test_program subdir/helper2 config + create_atffile subdir/Atffile 'prop: test-suite = "suite2"' 'tp: helper2' + + atf_check -s exit:0 -o ignore -e ignore atf-run helper1 + atf_check -s exit:0 -o 'match:var1 = var1-for-suite1' \ + -o 'match:var2 = var2-for-suite1' -o 'not-match:suite2' \ + cat config.out + + atf_check -s exit:0 -o ignore -e ignore atf-run subdir/helper2 + atf_check -s exit:0 -o 'match:var1 = var1-for-suite2' \ + -o 'match:var2 = var2-for-suite2' -o 'not-match:suite1' \ + cat config.out +} + + +atf_test_case config__test_suites__vflags +config__test_suites__vflags_body() +{ + create_test_program helper1 config + create_atffile Atffile 'prop: test-suite = "suite1"' 'tp: helper1' \ + 'tp: subdir' + mkdir subdir + create_test_program subdir/helper2 config + create_atffile subdir/Atffile 'prop: test-suite = "suite2"' 'tp: helper2' + + atf_check -s exit:0 -o ignore -e ignore atf-run -v var1=foo helper1 + atf_check -s exit:0 -o 'match:var1 = foo' cat config.out + + atf_check -s exit:0 -o ignore -e ignore atf-run -v var1=bar helper1 + atf_check -s exit:0 -o 'match:var1 = bar' cat config.out +} + + +atf_test_case unknown_option +unknown_option_body() { + atf_check -s exit:1 -o empty -e match:'E: Unknown option -Z' \ + atf-run -Z -A +} + + +atf_init_test_cases() { + atf_add_test_case all_pass + atf_add_test_case some_fail + atf_add_test_case selectors + + atf_add_test_case prefer_kyuafiles + + atf_add_test_case config__priorities + atf_add_test_case config__test_suites__files + atf_add_test_case config__test_suites__vflags + + atf_add_test_case unknown_option +} diff --git a/external/bsd/kyua-atf-compat/dist/atf2kyua.1 b/external/bsd/kyua-atf-compat/dist/atf2kyua.1 new file mode 100644 index 000000000..02ccfb073 --- /dev/null +++ b/external/bsd/kyua-atf-compat/dist/atf2kyua.1 @@ -0,0 +1,64 @@ +.\" Copyright 2012 Google Inc. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are +.\" met: +.\" +.\" * Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" * Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" * Neither the name of Google Inc. nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.Dd June 16, 2012 +.Dt ATF2KYUA 1 +.Os +.Sh NAME +.Nm atf2kyua +.Nd Converts Atffiles to Kyuafiles for a particular test suite. +.Sh SYNOPSIS +.Nm +.Op Fl s Ar source_path +.Op Fl t Ar target_path +.Sh DESCRIPTION +.Nm +is a script that generates Kyuafiles for all the corresponding Atffiles in +the specified test suite. +.Pp +By default, +.Nm +will look for Atffiles in the current directory and generate the new +Kyuafiles next to where the Atffiles live. +These behaviors can both be changed by the options described below. +.Pp +The following options are available: +.Bl -tag -width XsXsourceXpathXX +.It Fl s Ar source_path +Path to where the test suite file resides; i.e. the path from which to +start the traversal looking for Atffiles. +If not given, defaults to the current directory. +.It Fl t Ar target_path +Path to where the generated Kyuafiles will be written. +If the target directory is changed to not match the source directory, the +layout of the target directory end up being the same as that of the source +directory. +If not given, defaults to the value of the source path. +.El +.Sh SEE ALSO +.Xr kyua 1 , +.Xr atf 7 diff --git a/external/bsd/kyua-atf-compat/dist/atf2kyua.sh b/external/bsd/kyua-atf-compat/dist/atf2kyua.sh new file mode 100644 index 000000000..e969a057b --- /dev/null +++ b/external/bsd/kyua-atf-compat/dist/atf2kyua.sh @@ -0,0 +1,181 @@ +#! __SH__ +# Copyright 2011 Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Google Inc. nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# \file atf2kyua.sh +# Converts Atffiles to Kyuafiles for a particular test suite. + + +. "${KYUA_ATF_COMPAT_PKGDATADIR:-__PKGDATADIR__}/lib.subr" + + +# Prunes all Kyuafiles from a test suite in preparation for regeneration. +# +# \param target_root The path to the test suite. +remove_kyuafiles() { + local target_root="${1}"; shift + + if [ -d "${target_root}" ]; then + lib_info "Removing stale Kyuafiles from ${target_root}" + find "${target_root}" -name Kyuafile -exec rm -f {} \; + fi +} + + +# Obtains the list of test programs and subdirectories referenced by an Atffile. +# +# Any globs within the Atffile are expanded relative to the directory in which +# the Atffile lives. +# +# \param atffile The path to the Atffile to process. +# +# \post Prints the list of files referenced by the Atffile on stdout. +extract_files() { + local atffile="${1}"; shift + + local dir="$(dirname "${atffile}")" + + local globs="$(grep '^tp-glob:' "${atffile}" | cut -d ' ' -f 2-)" + local files="$(grep '^tp:' "${atffile}" | cut -d ' ' -f 2-)" + + for file in ${files} $(cd "$(dirname "${atffile}")" && echo ${globs}); do + if test -d "${dir}/${file}" -o -x "${dir}/${file}"; then + echo "${file}" + fi + done +} + + +# Converts an Atffile to a Kyuafile. +# +# \param atffile The path to the Atfffile to convert. +# \param kyuafile The path to where the Kyuafile will be written. +convert_atffile() { + local atffile="${1}"; shift + local kyuafile="${1}"; shift + + lib_info "Converting ${atffile} -> ${kyuafile}" + + local test_suite="$(grep 'prop:.*test-suite.*' "${atffile}" \ + | cut -d \" -f 2)" + + local dir="$(dirname "${atffile}")" + + local subdirs= + local test_programs= + for file in $(extract_files "${atffile}"); do + if test -f "${dir}/${file}/Atffile"; then + subdirs="${subdirs} ${file}" + elif test -x "${dir}/${file}"; then + test_programs="${test_programs} ${file}" + fi + done + + mkdir -p "$(dirname "${kyuafile}")" + + echo "syntax('kyuafile', 1)" >"${kyuafile}" + echo >>"${kyuafile}" + echo "test_suite('${test_suite}')" >>"${kyuafile}" + if [ -n "${subdirs}" ]; then + echo >>"${kyuafile}" + for dir in ${subdirs}; do + echo "include('${dir}/Kyuafile')" >>"${kyuafile}" + done + fi + if [ -n "${test_programs}" ]; then + echo >>"${kyuafile}" + for tp in ${test_programs}; do + echo "atf_test_program{name='${tp}'}" >>"${kyuafile}" + done + fi +} + + +# Adds Kyuafiles to a test suite by converting any existing Atffiles. +# +# \param source_root The path to the existing test suite root. Must contain +# an Atffile and the test programs. +# \param target_root The path to the directory where the Kyuafiles will be +# written. The layout will mimic that of source_root. +add_kyuafiles() { + local source_root="${1}"; shift + local target_root="${1}"; shift + + for atffile in $(cd "${source_root}" && find . -name Atffile); do + local subdir="$(echo "${atffile}" | sed 's,Atffile$,,;s,^\./,,')" + convert_atffile "${source_root}/${subdir}Atffile" \ + "${target_root}/${subdir}Kyuafile" + done +} + + +# Prints program usage to stdout. +# +# \param progname The name of the program to use for the syntax help. +usage() { + local progname="${1}"; shift + echo "Usage: ${progname} [-s source_root] [-t target_root]" +} + + +# Entry point for the program. +# +# \param ... The user-provided arguments. +main() { + local source_root= + local target_root= + + while getopts ':s:t:' arg "${@}"; do + case "${arg}" in + s) + source_root="${OPTARG}" + ;; + t) + target_root="${OPTARG}" + ;; + \?) + lib_usage_error "Unknown option -${OPTARG}" + ;; + esac + done + shift $((${OPTIND} - 1)) + + [ -n "${source_root}" ] || source_root=. + [ -n "${target_root}" ] || target_root="${source_root}" + + [ ${#} -eq 0 ] || lib_usage_error "No arguments allowed" + + [ -f "${source_root}/Atffile" ] || \ + lib_error "${source_root} is not a test suite; missing Atffile" + + remove_kyuafiles "${target_root}" + add_kyuafiles "${source_root}" "${target_root}" +} + + +main "${@}" diff --git a/external/bsd/kyua-atf-compat/dist/atf2kyua_test.sh b/external/bsd/kyua-atf-compat/dist/atf2kyua_test.sh new file mode 100644 index 000000000..530b5dd55 --- /dev/null +++ b/external/bsd/kyua-atf-compat/dist/atf2kyua_test.sh @@ -0,0 +1,246 @@ +#! __ATF_SH__ +# Copyright 2012 Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Google Inc. nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +. "${KYUA_ATF_COMPAT_PKGDATADIR:-__PKGDATADIR__}/tests_lib.subr" + + +# Performs a conversion test of an Atffile without recursion. +# +# \param source_root The directory in which to create the fake test suite. Must +# exist. +# \param target_root The directory in which the generated Kyuafiles will be +# stored. May not exist. +# \param ... Additional parameters to pass to atf2kyua. +one_level_test() { + local source_root="${1}"; shift + local target_root="${1}"; shift + + cd "${source_root}" + create_test_program p1 pass + create_test_program p2 pass + create_atffile "Atffile" 'prop: test-suite = "foo"' 'tp: p1' 'tp: p2' + cd - + + atf_check -s exit:0 -e ignore atf2kyua "${@}" + + cd "${target_root}" + cat >expected <expected <expected <expected <expected <>"${outfile}" + fi + done +} + + +atf_init_test_cases() { + for test_name in ${ENABLED_TESTS}; do + atf_add_test_case "${test_name}" + done +} diff --git a/external/bsd/kyua-atf-compat/dist/lib.subr b/external/bsd/kyua-atf-compat/dist/lib.subr new file mode 100644 index 000000000..43e33ff0a --- /dev/null +++ b/external/bsd/kyua-atf-compat/dist/lib.subr @@ -0,0 +1,134 @@ +# Copyright 2012 Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Google Inc. nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# \file lib.subr +# Common initialization and functions for shell scripts. + + +set -e + + +# Directory where the running script lives. +Lib_DirName="$(dirname ${0})" + + +# Base name of the running script. +Lib_ProgName="${0##*/}" + + +# Path to the temporary directory for this execution. +Lib_TempDir= + + +# List of cleanup functions to execute on exit. +_Lib_Cleanup_Hooks= + + +# Catch unexpected exits and perform the required cleanups. In particular, +# ensure that the temporary directory in Lib_TempDir, if any, is removed. +trap 'lib_cleanup ; exit 2' HUP INT QUIT TERM + + +# Prints an informational message. +# +# \param ... The message to print. Can be provided as multiple words and, in +# that case, they are joined together by a single whitespace. +lib_info() { + echo "${Lib_ProgName}: I: $*" 1>&2 +} + + +# Prints a runtime error and exits. +# +# \param ... The message to print. Can be provided as multiple words and, in +# that case, they are joined together by a single whitespace. +lib_error() { + echo "${Lib_ProgName}: E: $*" 1>&2 + exit 1 +} + + +# Prints a runtime warning. +# +# \param ... The message to print. Can be provided as multiple words and, in +# that case, they are joined together by a single whitespace. +lib_warning() { + echo "${Lib_ProgName}: W: $*" 1>&2 +} + + +# Prints an usage error and exits. +# +# \param ... The message to print. Can be provided as multiple words and, in +# that case, they are joined together by a single whitespace. +lib_usage_error() { + echo "${Lib_ProgName}: E: $*" 1>&2 + usage "${Lib_ProgName}" 1>&2 + exit 1 +} + + +# Executes the registered cleanup hooks. +lib_cleanup() { + local hook + for hook in ${_Lib_Cleanup_Hooks}; do + "${hook}" + done +} + + +# Installs a new cleanup hook. +# +# \param ... The names of the cleanup functions to register. +lib_register_cleanup() { + _Lib_Cleanup_Hooks="${_Lib_Cleanup_Hooks} ${*}" +} + + +# Creates a temporary directory for this execution. +# +# The temporary directory is unique to this script and execution. A cleanup +# hook is installed to delete such directory whenever lib_cleanup is called or +# when the program abruptly exits. +# +# \post Lib_TempDir is set to the path of the created temporary directory. +lib_init_tempdir() { + Lib_TempDir=$(mktemp -d -t "${_Lib_ProgName}.XXXXXX") + lib_register_cleanup "lib_clean_tempdir" +} + + +# Cleanup hook to delete the temporary directory. +# +# This operation is idempotent. +lib_clean_tempdir() { + if [ -n "${Lib_TempDir}" ]; then + rm -rf "${Lib_TempDir}" + Lib_TempDir= + fi +} diff --git a/external/bsd/kyua-atf-compat/dist/tests_lib.subr b/external/bsd/kyua-atf-compat/dist/tests_lib.subr new file mode 100644 index 000000000..a771c0566 --- /dev/null +++ b/external/bsd/kyua-atf-compat/dist/tests_lib.subr @@ -0,0 +1,98 @@ +# Copyright 2012 Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Google Inc. nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# \file tests_lib.subr +# Common routines for test programs. + + +# Creates an Atffile file. +# +# \param destfile The path to the file to be created. +# \param ... The lines to append to the Atffile. +create_atffile() { + local destfile="${1}"; shift + + cat >"${destfile}" <>"${destfile}" + done +} + + +# Creates an ATF configuration file. +# +# \param destfile The path to the file to be created. +# \param ... The lines to append to the configuration file. +create_config() { + local destfile="${1}"; shift + + cat >"${destfile}" <>"${destfile}" + done +} + + +# Creates a fake test program. +# +# \param destfile The path to the test program to be created. +# \param ... List of the test cases to include in the fake test program. +create_test_program() { + local destfile="${1}"; shift + + sed -e "s,@CONTROL_DIR@,$(pwd),g" \ + -e "s,@ENABLED_TESTS@,${*},g" \ + <"$(atf_get_srcdir)/helpers" >"${destfile}" + chmod +x "${destfile}" +} + + +# Strips timestamps from the output of 'kyua test' or 'kyua report'. +# +# The timestamps are all replaced with X.XXXs so that they can later be compared +# against prerecorded golden output. +# +# \param file The file in which to replace the timestamps. The replacement is +# performed in place. The reason is that the calls to atf-run and +# atf-report should be validated on their own WITHOUT piping them through +# any manipulation function. +strip_timestamps() { + local file="${1}"; shift + + sed -e 's,[0-9][0-9]*\.[0-9][0-9]*s,X.XXXs,g' <"${file}" >"${file}.new" + mv "${file}.new" "${file}" +} diff --git a/external/bsd/kyua-atf-compat/prepare-import.sh b/external/bsd/kyua-atf-compat/prepare-import.sh new file mode 100755 index 000000000..2462b8f8f --- /dev/null +++ b/external/bsd/kyua-atf-compat/prepare-import.sh @@ -0,0 +1,103 @@ +#!/bin/sh +# $NetBSD: prepare-import.sh,v 1.1 2013/02/25 00:20:08 jmmv Exp $ +# +# Use this script to recreate the 'dist' subdirectory from a newly released +# distfile. The script takes care of unpacking the distfile, removing any +# files that are not relevant to NetBSD and checking if there are any new +# files in the new release that need to be addressed. +# + +set -e + +ProgName=${0##*/} + +CLEAN_PATTERNS= +CLEAN_PATTERNS="${CLEAN_PATTERNS} *.m4" +CLEAN_PATTERNS="${CLEAN_PATTERNS} INSTALL TODO" +CLEAN_PATTERNS="${CLEAN_PATTERNS} Makefile*" +CLEAN_PATTERNS="${CLEAN_PATTERNS} admin" +CLEAN_PATTERNS="${CLEAN_PATTERNS} configure*" + +err() { + echo "${ProgName}:" "${@}" 1>&2 + exit 1 +} + +log() { + echo "${ProgName}:" "${@}" +} + +backup_dist() { + if [ -d dist.old ]; then + log "Removing dist; dist.old exists" + rm -rf dist + else + log "Backing up dist as dist.old" + mv dist dist.old + fi +} + +extract_distfile() { + local distfile="${1}"; shift + local distname="${1}"; shift + + log "Extracting ${distfile}" + tar -xzf "${distfile}" + [ -d "${distname}" ] || err "Distfile did not create ${distname}" + log "Renaming ${distname} to dist" + mv "${distname}" dist +} + +get_distname() { + local distfile="${1}"; shift + basename "${distfile}" | sed -e 's,\.tar.*,,' +} + +cleanup_dist() { + log "Removing unnecessary files from dist" + ( cd dist && rm -rf ${CLEAN_PATTERNS} ) +} + +diff_dirs() { + local old_dir="${1}"; shift + local new_dir="${1}"; shift + + local old_list=$(mktemp -t kyua-atf-compat-import.XXXXXX) + local new_list=$(mktemp -t kyua-atf-compat-import.XXXXXX) + local diff=$(mktemp -t kyua-atf-compat-import.XXXXXX) + trap "rm -f '${old_list}' '${new_list}' '${diff}'; exit 1" \ + HUP INT QUIT TERM + + ( cd "${old_dir}" && find . | sort >>"${old_list}" ) + ( cd "${new_dir}" && find . | sort >>"${new_list}" ) + + diff -u "${old_list}" "${new_list}" | grep '^+\.' >>"${diff}" || true + if [ -s "${diff}" ]; then + log "New files found" + diff -u "${old_list}" "${new_list}" | grep '^+\.' + log "Check if any files have to be cleaned up and update" \ + "the prepare-import.sh script accordingly" + else + log "No new files; all good!" + fi + + rm -f "${old_list}" "${new_list}" "${diff}" +} + +main() { + [ ${#} -eq 1 ] || err "Must provide a distfile name" + local distfile="${1}"; shift + + [ -f Makefile -a -f prepare-import.sh ] || \ + err "Must be run from the src/external/bsd/kyua-atf-compat" \ + "subdirectory" + + local distname="$(get_distname ${distfile})" + + backup_dist + extract_distfile "${distfile}" "${distname}" + cleanup_dist + diff_dirs dist.old dist +} + +main "${@}" diff --git a/external/bsd/kyua-atf-compat/share/Makefile b/external/bsd/kyua-atf-compat/share/Makefile new file mode 100644 index 000000000..44bfda42a --- /dev/null +++ b/external/bsd/kyua-atf-compat/share/Makefile @@ -0,0 +1,5 @@ +# $NetBSD: Makefile,v 1.1 2013/02/25 00:20:08 jmmv Exp $ + +SUBDIR= doc kyua-atf-compat + +.include diff --git a/external/bsd/kyua-atf-compat/share/Makefile.inc b/external/bsd/kyua-atf-compat/share/Makefile.inc new file mode 100644 index 000000000..9abb6dddf --- /dev/null +++ b/external/bsd/kyua-atf-compat/share/Makefile.inc @@ -0,0 +1,3 @@ +# $NetBSD: Makefile.inc,v 1.1 2013/02/25 00:20:08 jmmv Exp $ + +.include "../Makefile.inc" diff --git a/external/bsd/kyua-atf-compat/share/doc/Makefile b/external/bsd/kyua-atf-compat/share/doc/Makefile new file mode 100644 index 000000000..cc698bc15 --- /dev/null +++ b/external/bsd/kyua-atf-compat/share/doc/Makefile @@ -0,0 +1,5 @@ +# $NetBSD: Makefile,v 1.1 2013/02/25 00:20:09 jmmv Exp $ + +SUBDIR= kyua-atf-compat + +.include diff --git a/external/bsd/kyua-atf-compat/share/doc/Makefile.inc b/external/bsd/kyua-atf-compat/share/doc/Makefile.inc new file mode 100644 index 000000000..f21f556b5 --- /dev/null +++ b/external/bsd/kyua-atf-compat/share/doc/Makefile.inc @@ -0,0 +1,3 @@ +# $NetBSD: Makefile.inc,v 1.1 2013/02/25 00:20:09 jmmv Exp $ + +.include "../Makefile.inc" diff --git a/external/bsd/kyua-atf-compat/share/doc/kyua-atf-compat/Makefile b/external/bsd/kyua-atf-compat/share/doc/kyua-atf-compat/Makefile new file mode 100644 index 000000000..cdfd447d3 --- /dev/null +++ b/external/bsd/kyua-atf-compat/share/doc/kyua-atf-compat/Makefile @@ -0,0 +1,11 @@ +# $NetBSD: Makefile,v 1.1 2013/02/25 00:20:09 jmmv Exp $ + +.include + +.if ${MKSHARE} != "no" +FILESDIR= /usr/share/doc/kyua-atf-compat +FILESMODE= 444 +FILES= AUTHORS COPYING NEWS README +.endif + +.include diff --git a/external/bsd/kyua-atf-compat/share/kyua-atf-compat/Makefile b/external/bsd/kyua-atf-compat/share/kyua-atf-compat/Makefile new file mode 100644 index 000000000..e49bdd22d --- /dev/null +++ b/external/bsd/kyua-atf-compat/share/kyua-atf-compat/Makefile @@ -0,0 +1,9 @@ +# $NetBSD: Makefile,v 1.1 2013/02/25 00:20:09 jmmv Exp $ + +.include + +FILES= lib.subr tests_lib.subr +FILESDIR= /usr/share/kyua-atf-compat +FILESMODE= 444 + +.include diff --git a/external/bsd/kyua-atf-compat/tests/Makefile b/external/bsd/kyua-atf-compat/tests/Makefile new file mode 100644 index 000000000..cc698bc15 --- /dev/null +++ b/external/bsd/kyua-atf-compat/tests/Makefile @@ -0,0 +1,5 @@ +# $NetBSD: Makefile,v 1.1 2013/02/25 00:20:09 jmmv Exp $ + +SUBDIR= kyua-atf-compat + +.include diff --git a/external/bsd/kyua-atf-compat/tests/Makefile.inc b/external/bsd/kyua-atf-compat/tests/Makefile.inc new file mode 100644 index 000000000..f21f556b5 --- /dev/null +++ b/external/bsd/kyua-atf-compat/tests/Makefile.inc @@ -0,0 +1,3 @@ +# $NetBSD: Makefile.inc,v 1.1 2013/02/25 00:20:09 jmmv Exp $ + +.include "../Makefile.inc" diff --git a/external/bsd/kyua-atf-compat/tests/kyua-atf-compat/Makefile b/external/bsd/kyua-atf-compat/tests/kyua-atf-compat/Makefile new file mode 100644 index 000000000..e10b4868f --- /dev/null +++ b/external/bsd/kyua-atf-compat/tests/kyua-atf-compat/Makefile @@ -0,0 +1,22 @@ +# $NetBSD: Makefile,v 1.1 2013/02/25 00:20:09 jmmv Exp $ + +.include + +TESTSDIR= ${TESTSBASE}/kyua-atf-compat + +.for test in atf-report_test atf-run_test atf2kyua_test +TESTS_SH+= ${test} +TESTS_SH_SRC_${test}= ${test}.tmp.sh +${test}.tmp.sh: ${test}.sh + src=${test}.sh dst=${test}.tmp.sh; ${BUILD_SCRIPT} +CLEANFILES+= ${test}.tmp.sh ${test}.tmp.sh.new +.endfor + +FILES= helpers +FILESDIR_helpers= ${TESTSDIR} +realall: helpers +helpers: helpers.sh + src=helpers.sh dst=helpers; ${BUILD_SCRIPT} +CLEANFILES+= helpers helpers.new + +.include diff --git a/external/bsd/kyua-atf-compat/usr.bin/Makefile b/external/bsd/kyua-atf-compat/usr.bin/Makefile new file mode 100644 index 000000000..36274c503 --- /dev/null +++ b/external/bsd/kyua-atf-compat/usr.bin/Makefile @@ -0,0 +1,5 @@ +# $NetBSD: Makefile,v 1.1 2013/02/25 00:20:09 jmmv Exp $ + +SUBDIR= atf-report atf-run atf2kyua + +.include diff --git a/external/bsd/kyua-atf-compat/usr.bin/Makefile.inc b/external/bsd/kyua-atf-compat/usr.bin/Makefile.inc new file mode 100644 index 000000000..f21f556b5 --- /dev/null +++ b/external/bsd/kyua-atf-compat/usr.bin/Makefile.inc @@ -0,0 +1,3 @@ +# $NetBSD: Makefile.inc,v 1.1 2013/02/25 00:20:09 jmmv Exp $ + +.include "../Makefile.inc" diff --git a/external/bsd/kyua-atf-compat/usr.bin/atf-report/Makefile b/external/bsd/kyua-atf-compat/usr.bin/atf-report/Makefile new file mode 100644 index 000000000..53c25e8e5 --- /dev/null +++ b/external/bsd/kyua-atf-compat/usr.bin/atf-report/Makefile @@ -0,0 +1,17 @@ +# $NetBSD: Makefile,v 1.1 2013/02/25 00:20:09 jmmv Exp $ + +.include + +FILES= atf-report +FILESDIR= /usr/bin +FILESMODE= ${BINMODE} + +realall: atf-report +atf-report: atf-report.sh + src=atf-report.sh dst=atf-report; ${BUILD_SCRIPT} +CLEANFILES+= atf-report atf-report.new + +MAN= atf-report.1 + +.include +.include diff --git a/external/bsd/kyua-atf-compat/usr.bin/atf-run/Makefile b/external/bsd/kyua-atf-compat/usr.bin/atf-run/Makefile new file mode 100644 index 000000000..ba8adcb87 --- /dev/null +++ b/external/bsd/kyua-atf-compat/usr.bin/atf-run/Makefile @@ -0,0 +1,17 @@ +# $NetBSD: Makefile,v 1.1 2013/02/25 00:20:10 jmmv Exp $ + +.include + +FILES= atf-run +FILESDIR= /usr/bin +FILESMODE= ${BINMODE} + +realall: atf-run +atf-run: atf-run.sh + src=atf-run.sh dst=atf-run; ${BUILD_SCRIPT} +CLEANFILES+= atf-run atf-run.new + +MAN= atf-run.1 + +.include +.include diff --git a/external/bsd/kyua-atf-compat/usr.bin/atf2kyua/Makefile b/external/bsd/kyua-atf-compat/usr.bin/atf2kyua/Makefile new file mode 100644 index 000000000..1f3dfc970 --- /dev/null +++ b/external/bsd/kyua-atf-compat/usr.bin/atf2kyua/Makefile @@ -0,0 +1,17 @@ +# $NetBSD: Makefile,v 1.1 2013/02/25 00:20:10 jmmv Exp $ + +.include + +FILES= atf2kyua +FILESDIR= /usr/bin +FILESMODE= ${BINMODE} + +realall: atf2kyua +atf2kyua: atf2kyua.sh + src=atf2kyua.sh dst=atf2kyua; ${BUILD_SCRIPT} +CLEANFILES+= atf2kyua atf2kyua.new + +MAN= atf2kyua.1 + +.include +.include diff --git a/external/bsd/kyua-cli/Makefile b/external/bsd/kyua-cli/Makefile new file mode 100644 index 000000000..be5f2e6ec --- /dev/null +++ b/external/bsd/kyua-cli/Makefile @@ -0,0 +1,10 @@ +# $NetBSD: Makefile,v 1.2 2013/02/24 03:06:15 jmmv Exp $ + +SUBDIR= etc lib .WAIT share tests usr.bin + +.for dir in share tests usr.bin +includes-${dir}: .PHONY + @true +.endfor + +.include diff --git a/external/bsd/kyua-cli/Makefile.inc b/external/bsd/kyua-cli/Makefile.inc new file mode 100644 index 000000000..a88e0b2d2 --- /dev/null +++ b/external/bsd/kyua-cli/Makefile.inc @@ -0,0 +1,69 @@ +# $NetBSD: Makefile.inc,v 1.1 2013/02/23 14:16:49 jmmv Exp $ + +.include + +TOPDIR= ${NETBSDSRCDIR}/external/bsd/kyua-cli +SRCDIR= ${TOPDIR}/dist + +# Name of the private libraries (without their lib prefix) to depend on. +KYUA_LIBS?= + +# Layout of installed files. +KYUA_BINDIR= /usr/bin +KYUA_CONFDIR= /etc/kyua +KYUA_DOCDIR= /usr/share/doc/kyua-cli +KYUA_EXAMPLESDIR= /usr/share/examples/kyua-cli +KYUA_MISCDIR= /usr/share/kyua-cli/misc +KYUA_STOREDIR= /usr/share/kyua-cli/store +KYUA_TESTERSDIR= /usr/libexec +KYUA_TESTSDIR= ${TESTSBASE} + +KYUA_TARNAME!= grep 'define PACKAGE_TARNAME' ${TOPDIR}/config.h \ + | cut -d '"' -f 2 +KYUA_VERSION!= grep 'define VERSION' ${TOPDIR}/config.h | cut -d '"' -f 2 + +CPPFLAGS+= -DHAVE_CONFIG_H + +# Not all source files need these settings, but it's just easier to +# set them in all cases. +CPPFLAGS+= -DKYUA_CONFDIR=\"${KYUA_CONFDIR}\" +CPPFLAGS+= -DKYUA_DOCDIR=\"${KYUA_DOCDIR}\" +CPPFLAGS+= -DKYUA_EXAMPLESDIR=\"${KYUA_EXAMPLESDIR}\" +CPPFLAGS+= -DKYUA_MISCDIR=\"${KYUA_MISCDIR}\" +CPPFLAGS+= -DKYUA_STOREDIR=\"${KYUA_STOREDIR}\" +CPPFLAGS+= -DKYUA_TESTERSDIR=\"${KYUA_TESTERSDIR}\" +CPPFLAGS+= -DKYUA_TESTSDIR=\"${KYUA_TESTSDIR}\" + +CPPFLAGS+= -I${TOPDIR} # For config.h. +CPPFLAGS+= -I${TOPDIR}/lib # For utils/defs.hpp. +CPPFLAGS+= -I${SRCDIR} + +PRIVATELIBDIR!= cd ${TOPDIR}/lib; ${PRINTOBJDIR} +.for lib in ${KYUA_LIBS} +LDADD+= ${PRIVATELIBDIR}/${lib}/lib${lib}.a +DPADD+= ${PRIVATELIBDIR}/${lib}/lib${lib}.a +.endfor + +.if !empty(KYUA_LIBS:Mutils) +LDADD+= -llutok -lsqlite3 +DPADD+= ${LIBLUTOK} ${LIBSQLITE} +.endif + +.if defined(__MINIX) +LDADD+= -llua -lstdc++ -lgcc_s +DPADD+= ${LIBLUA} ${LIBSTDCXX} ${LIBGCC_S} +LDFLAGS+= -Wl,--allow-multiple-definition +.endif # defined(__MINIX) + +BUILD_MANPAGE = \ + sed -e 's,__CONFDIR__,${KYUA_CONFDIR},g' \ + -e 's,__DOCDIR__,${KYUA_DOCDIR},g' \ + -e 's,__EGDIR__,${KYUA_EXAMPLESDIR},g' \ + -e 's,__MISCDIR__,${KYUA_MISCDIR},g' \ + -e 's,__PACKAGE__,${KYUA_TARNAME},g' \ + -e 's,__STOREDIR__,${KYUA_STOREDIR},g' \ + -e 's,__TESTERSDIR__,${KYUA_TESTERSDIR},g' \ + -e 's,__TESTSDIR__,${KYUA_TESTSDIR},g' \ + -e 's,__VERSION__,${KYUA_VERSION},g' \ + <${SRCDIR}/doc/$${name}.in >$${name}.tmp; \ + mv $${name}.tmp $${name} diff --git a/external/bsd/kyua-cli/config.h b/external/bsd/kyua-cli/config.h new file mode 100644 index 000000000..ce092262c --- /dev/null +++ b/external/bsd/kyua-cli/config.h @@ -0,0 +1,98 @@ +/* config.h. Generated from config.h.in by configure. */ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to the optind value to reset getopt processing */ +#define GETOPT_OPTIND_RESET_VALUE 1 + +/* Define to 1 if getcwd(NULL, 0) works */ +#define HAVE_GETCWD_DYN 1 + +/* Define to 1 if getopt has optreset */ +#define HAVE_GETOPT_WITH_OPTRESET 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `putenv' function. */ +#define HAVE_PUTENV 1 + +/* Define to 1 if you have the `setenv' function. */ +#define HAVE_SETENV 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `sysctlbyname' function. */ +/* #undef HAVE_SYSCTLBYNAME */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_PARAM_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SYSCTL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `unsetenv' function. */ +#define HAVE_UNSETENV 1 + +/* Name of the system architecture (aka processor type) */ +#define KYUA_ARCHITECTURE "x86_64" + +/* Name of the system platform (aka machine name) */ +#define KYUA_PLATFORM "amd64" + +/* Define to the last valid signal number */ +#define LAST_SIGNO 63 + +/* Define to the name of the sysctl MIB */ +#define MEMORY_QUERY_SYSCTL_MIB "hw.usermem64" + +/* Define to the memory query type */ +#define MEMORY_QUERY_TYPE "sysctlbyname" + +/* Name of package */ +#define PACKAGE "kyua-cli" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "kyua-discuss@googlegroups.com" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "Kyua - Command line interface" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "Kyua - Command line interface 0.6" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "kyua-cli" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "http://code.google.com/p/kyua/" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "0.6" + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Version number of package */ +#define VERSION "0.6" diff --git a/external/bsd/kyua-cli/dist/AUTHORS b/external/bsd/kyua-cli/dist/AUTHORS new file mode 100644 index 000000000..0f707683a --- /dev/null +++ b/external/bsd/kyua-cli/dist/AUTHORS @@ -0,0 +1 @@ +* Julio Merino diff --git a/external/bsd/kyua-cli/dist/COPYING b/external/bsd/kyua-cli/dist/COPYING new file mode 100644 index 000000000..068376603 --- /dev/null +++ b/external/bsd/kyua-cli/dist/COPYING @@ -0,0 +1,27 @@ +Copyright 2010, 2011, 2012, 2013 Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +* Neither the name of Google Inc. nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/external/bsd/kyua-cli/dist/Kyuafile b/external/bsd/kyua-cli/dist/Kyuafile new file mode 100644 index 000000000..5a8332669 --- /dev/null +++ b/external/bsd/kyua-cli/dist/Kyuafile @@ -0,0 +1,14 @@ +syntax(2) + +test_suite("kyua") + +-- This is broken in platforms where /bin/sh is not bash. See Issue 24 for +-- details. We should fix this, but it does not seem to be Kyua's problem. +--include("bootstrap/Kyuafile") + +include("cli/Kyuafile") +include("engine/Kyuafile") +include("examples/Kyuafile") +include("integration/Kyuafile") +include("store/Kyuafile") +include("utils/Kyuafile") diff --git a/external/bsd/kyua-cli/dist/NEWS b/external/bsd/kyua-cli/dist/NEWS new file mode 100644 index 000000000..0fd8283f5 --- /dev/null +++ b/external/bsd/kyua-cli/dist/NEWS @@ -0,0 +1,255 @@ +Changes in version 0.6 +====================== + +Experimental version released on February 22nd, 2013. + +* Issue 36: Changed 'kyua help' to not fail when the configuration file + is bogus. Help should always work. + +* Issue 37: Simplified the syntax() calls in configuration and Kyuafile + files to only specify the requested version instead of also the format + name. The format name is implied by the file being loaded, so there + is no use in the caller having to specify it. The version number of + these file formats has been bumped to 2. + +* Issue 39: Added per-test-case metadata values to the HTML reports. + +* Issue 40: Rewrote the documentation as manual pages and removed the + previous GNU Info document. + +* Issue 47: Started using the independent testers in the kyua-testers + package to run the test cases. Kyua does not implement the logic to + invoke test cases any more, which provides for better modularity, + extensibility and robustness. + +* Issue 57: Added support to specify arbitrary metadata properties for + test programs right from the Kyuafile. This is to make plain test + programs more versatile, by allowing them to specify any of the + requirements (allowed architectures, required files, etc.) supported + by Kyua. + +* Reduced automatic screen line wrapping of messages to the 'help' + command and the output of tables by 'db-exec'. Wrapping any other + messages (specially anything going to stderr) was very annoying + because it prevented natural copy/pasting of text. + +* Increased the granularity of the error codes returned by kyua(1) to + denote different error conditions. This avoids the overload of '1' to + indicate both "expected" errors from specific subcommands and + unexpected errors caused by the internals of the code. The manual now + correctly explain how the exit codes behave on a command basis. + +* Optimized the database schema to make report generation almost + instantaneous. + +* Bumped the database schema to 2. The database now records the + metadata of both test programs and test cases generically, without + knowledge of their interface. + +* Added the 'db-migrate' command to provide a mechanism to upgrade a + database with an old schema to the current schema. + +* Removed the GDB build-time configuration variable. This is now part + of the kyua-testers package. + +* Rewrote the Kyuafile parsing code in C++, which results in a much + simpler implementation. As a side-effect, this gets rid of the + external Lua files required by 'kyua', which in turn make the tool + self-contained. + +* Added caching of various configure test results (particularly in those + tests that need to execute a test program) so that cross-compilers can + predefine the results of the tests without having to run the + executables. + + +Changes in version 0.5 +====================== + +Experimental version released on July 10th, 2012. + +* Issue 15: Added automatic stacktrace gathering of crashing test cases. + This relies on GDB and is a best-effort operation. + +* Issue 32: Added the '--build-root' option to the debug, list and test + commands. This allows executing test programs from a different + directory than where the Kyuafile scripts live. See the 'Build roots' + section in the manual for more details. + +* Issue 33: Removed the kyuaify.sh script. This has been renamed to + atf2kyua and moved to the kyua-atf-compat module, where it ships as a + first-class utility (with a manual page and tests). + +* Issue 34: Changed the HTML reports to include the stdout and stderr of + every test case. + +* Fixed the build when using a "build directory" and a clean source tree + from the repository. + + +Changes in version 0.4 +====================== + +Experimental version released on June 6th, 2012. + +* Added the 'report-html' command to generate HTML reports of the + execution of any recorded action. + +* Changed the '--output' flag of the 'report' command to only take a + path to the target file, not its format. Different formats are better + supported by implementing different subcommands, as the options they + may receive will vary from format to format. + +* Added a '--with-atf' flag to the configure script to control whether + the ATF tests get built or not. May be useful for packaging systems + that do not have ATF in them yet. Disabling ATF also cuts down the + build time of Kyua significantly, but with the obvious drawbacks. + +* Grouped 'kyua' subcommands by topic both in the output of 'help' and + in the documentation. In general, the user needs to be aware of + commands that rely on a current project and those commands that rely + purely on the database to generate reports. + +* Made 'help' print the descriptions of options and commands properly + tabulated. + +* Changed most informational messages to automatically wrap on screen + boundaries. + +* Rewrote the configuration file parsing module for extensibility. This + will allow future versions of Kyua to provide additional user-facing + options in the configuration file. + + No syntax changes have been made, so existing configuration files + (version 1) will continue to be parsed without problems. There is one + little exception though: all variables under the top-level + 'test_suites' tree must be declared as strings. + + Similarly, the '-v' and '--variable' flags to the command line must + now carry a 'test_suites.' prefix when referencing any variables under + such tree. + + +Changes in version 0.3 +====================== + +Experimental version released on February 24th, 2012. + +* Made the 'test' command record the results of the executed test + cases into a SQLite database. As a side effect, 'test' now supports a + '--store' option to indicate where the database lives. + +* Added the 'report' command to generate plain-text reports of the + test results stored in the database. The interface of this command is + certainly subject to change at this point. + +* Added the 'db-exec' command to directly interact with the store + database. + +* Issue 28: Added support for the 'require.memory' test case property + introduced in ATF 0.15. + +* Renamed the user-specific configuration file from ~/.kyuarc to + ~/.kyua/kyua.conf for consistency with other files stored in the + ~/.kyua/ subdirectory. + +* Switched to use Lutok instead of our own wrappers over the Lua C + library. Lutok is just what used to be our own utils::lua module, but + is now distributed separately. + +* Removed the 'Atffile's from the source tree. Kyua is stable enough + to generate trustworthy reports, and we do not want to give the + impression that atf-run / atf-report are still supported. + +* Enabled logging to stderr for our own test programs. This makes it + slightly easier to debug problems in our own code when we get a + failing test. + + +Changes in version 0.2 +====================== + +Experimental version released on August 24th, 2011. + +The biggest change in this release is the ability for Kyua to run test +programs implemented using different frameworks. What this means is +that, now, a Kyua test suite can include not only ATF-based test +programs, but also "legacy" (aka plain) test programs that do not use +any framework. I.e. if you have tests that are simple programs that +exit with 0 on success and 1 on failure, you can plug them in into a +Kyua test suite. + +Other than this, there have been several user-visible changes. The most +important are the addition of the new 'config' and 'debug' subcommands +to the 'kyua' binary. The former can be used to inspect the runtime +configuration of Kyua after parsing, and the latter is useful to +interact with failing tests cases in order to get more data about the +failure itself. + +Without further ado, here comes the itemized list of changes: + +* Generalized the run-time engine to support executing test programs + that implement different interfaces. Test programs that use the ATF + libraries are just a special case of this. (Issue 18.) + +* Added support to the engine to run "plain" test programs: i.e. test + programs that do not use any framework and report their pass/fail + status as an exit code. This is to simplify the integration of legacy + test programs into a test suite, and also to demonstrate that the + run-time engine is generic enough to support different test + interfaces. (Issue 18.) + +* Added the 'debug' subcommand. This command allows end users to tweak + the execution of a specific test case and to poke into the behavior of + its execution. At the moment, all this command allows is to view the + stdout and stderr of the command in real time (which the 'test' + command currently completely hides). + +* Added the 'config' subcommand. This command allows the end user to + inspect the current configuration variables after evaluation, without + having to read through configuration files. (Issue 11.) + +* Removed the test_suites_var function from configuration files. This + was used to set the value of test-suite-sepecific variables, but it + was ugly-looking. It is now possible to use the more natural syntax + 'test_suites.. = '. (Issue 11.) + +* Added a mechanism to disable the loading of configuration files + altogether. Needed for testing purposes and for scriptability. + Available by passing the '--config=none' flag. + +* Enabled detection of unused parameters and variables in the code and + fixed all warnings. (Issue 23.) + +* Changed the behavior of "developer mode". Compiler warnings are now + enabled unconditionally regardless of whether we are in developer mode + or not; developer mode is now only used to perform strict warning + checks and to enable assertions. Additionally, developer mode is now + only automatically enabled when building from the repository, not for + formal releases. (Issue 22.) + +* Fixed many build and portability problems to Debian sid with GCC 4.6.3 + and Ubuntu 10.04.1 LTS. (Issues 20, 21, 26.) + + +Changes in version 0.1 +====================== + +Experimental version released on June 23rd, 2011. + +This is the first public release of the kyua-cli package. + +The scope of this release is to provide functional replacement for the +'atf-run' utility included in the atf package. At this point, 'kyua' +can reliably run the NetBSD 5.99.53 test suite delivering the same +results as 'atf-run'. + +The reporting facilities of this release are quite limited. There is +no replacement for 'atf-report' yet, and there is no easy way of +debugging failing test programs other than running them by hand. These +features will mark future milestones and therefore be part of other +releases. + +Be aware that this release has suffered very limited field testing. +The test suite for kyua-cli is quite comprehensive, but some bugs may +be left in any place. diff --git a/external/bsd/kyua-cli/dist/README b/external/bsd/kyua-cli/dist/README new file mode 100644 index 000000000..c9406d362 --- /dev/null +++ b/external/bsd/kyua-cli/dist/README @@ -0,0 +1,21 @@ +Kyua (pronounced Q.A.) is a testing framework for both developers and +users. Kyua is different from most other testing frameworks in that it +puts the end user experience before anything else. There are multiple +reasons for users to run the tests themselves, and Kyua ensures that +they can do so in the most convenient way. + +This module, kyua-cli, provides the command-line interface to the Kyua +runtime system. The major purpose of this tool is to run test cases and +generate unified reports for their results. + +For further information on the contents of this distribution file, +please refer to the following other documents: + +* AUTHORS: List of authors and contributors to this project. +* COPYING: License information. +* INSTALL: Compilation and installation instructions. +* NEWS: List of major changes between formal releases. + +For general project information, please visit: + + http://code.google.com/p/kyua/ diff --git a/external/bsd/kyua-cli/dist/bootstrap/Kyuafile b/external/bsd/kyua-cli/dist/bootstrap/Kyuafile new file mode 100644 index 000000000..0f161b2d6 --- /dev/null +++ b/external/bsd/kyua-cli/dist/bootstrap/Kyuafile @@ -0,0 +1,5 @@ +syntax(2) + +test_suite("kyua") + +plain_test_program{name="testsuite"} diff --git a/external/bsd/kyua-cli/dist/bootstrap/atf_helpers.cpp b/external/bsd/kyua-cli/dist/bootstrap/atf_helpers.cpp new file mode 100644 index 000000000..a46311bee --- /dev/null +++ b/external/bsd/kyua-cli/dist/bootstrap/atf_helpers.cpp @@ -0,0 +1,72 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include +#include +#include + +#include + + +ATF_TEST_CASE_WITHOUT_HEAD(fails); +ATF_TEST_CASE_BODY(fails) +{ + fail("Failed on purpose"); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(passes); +ATF_TEST_CASE_BODY(passes) +{ +} + + +ATF_TEST_CASE_WITHOUT_HEAD(skips); +ATF_TEST_CASE_BODY(skips) +{ + skip("Skipped on purpose"); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + std::string enabled; + + const char* tests = std::getenv("TESTS"); + if (tests == NULL) + enabled = "fails passes skips"; + else + enabled = tests; + + if (enabled.find("fails") != std::string::npos) + ATF_ADD_TEST_CASE(tcs, fails); + if (enabled.find("passes") != std::string::npos) + ATF_ADD_TEST_CASE(tcs, passes); + if (enabled.find("skips") != std::string::npos) + ATF_ADD_TEST_CASE(tcs, skips); +} diff --git a/external/bsd/kyua-cli/dist/bootstrap/package.m4 b/external/bsd/kyua-cli/dist/bootstrap/package.m4 new file mode 100644 index 000000000..500a02d72 --- /dev/null +++ b/external/bsd/kyua-cli/dist/bootstrap/package.m4 @@ -0,0 +1,6 @@ +# Signature of the current package. +m4_define(AT_PACKAGE_NAME, Kyua - Command line interface) +m4_define(AT_PACKAGE_TARNAME, kyua-cli) +m4_define(AT_PACKAGE_VERSION, 0.6) +m4_define(AT_PACKAGE_STRING, Kyua - Command line interface 0.6) +m4_define(AT_PACKAGE_BUGREPORT, kyua-discuss@googlegroups.com) diff --git a/external/bsd/kyua-cli/dist/bootstrap/plain_helpers.cpp b/external/bsd/kyua-cli/dist/bootstrap/plain_helpers.cpp new file mode 100644 index 000000000..1b57a059d --- /dev/null +++ b/external/bsd/kyua-cli/dist/bootstrap/plain_helpers.cpp @@ -0,0 +1,146 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include +#include +#include + +#include "utils/defs.hpp" + + +namespace { + + +/// Prints a fake but valid test case list and then aborts. +/// +/// \param unused_argc The original argument count of the program. +/// \param argv The original arguments of the program. +/// +/// \return Nothing because this dies before returning. +static int +helper_abort_test_cases_list(int UTILS_UNUSED_PARAM(argc), char** argv) +{ + for (const char* const* arg = argv; *arg != NULL; arg++) { + if (std::strcmp(*arg, "-l") == 0) { + std::cout << "Content-Type: application/X-atf-tp; " + "version=\"1\"\n\n"; + std::cout << "ident: foo\n"; + } + } + std::abort(); +} + + +/// Just returns without printing anything as the test case list. +/// +/// \param unused_argc The original argument count of the program. +/// \param unused_argv The original arguments of the program. +/// +/// \return Always 0, as required for test programs. +static int +helper_empty_test_cases_list(int UTILS_UNUSED_PARAM(argc), + char** UTILS_UNUSED_PARAM(argv)) +{ + return EXIT_SUCCESS; +} + + +/// Prints a correctly-formatted test case list but empty. +/// +/// \param unused_argc The original argument count of the program. +/// \param argv The original arguments of the program. +/// +/// \return Always 0, as required for test programs. +static int +helper_zero_test_cases(int UTILS_UNUSED_PARAM(argc), char** argv) +{ + for (const char* const* arg = argv; *arg != NULL; arg++) { + if (std::strcmp(*arg, "-l") == 0) + std::cout << "Content-Type: application/X-atf-tp; " + "version=\"1\"\n\n"; + } + return EXIT_SUCCESS; +} + + +/// Mapping of the name of a helper to its implementation. +struct helper { + /// The name of the helper, as will be provided by the user on the CLI. + const char* name; + + /// A pointer to the function implementing the helper. + int (*hook)(int, char**); +}; + + +/// NULL-terminated table mapping helper names to their implementations. +static const helper helpers[] = { + { "abort_test_cases_list", helper_abort_test_cases_list, }, + { "empty_test_cases_list", helper_empty_test_cases_list, }, + { "zero_test_cases", helper_zero_test_cases, }, + { NULL, NULL, }, +}; + + +} // anonymous namespace + + +/// Entry point to the ATF-less helpers. +/// +/// The caller must select a helper to execute by defining the HELPER +/// environment variable to the name of the desired helper. Think of this main +/// method as a subprogram dispatcher, to avoid having many individual helper +/// binaries. +/// +/// \todo Maybe we should really have individual helper binaries. It would +/// avoid a significant amount of complexity here and in the tests, at the +/// expense of some extra files and extra build logic. +/// +/// \param argc The user argument count; delegated to the helper. +/// \param argv The user arguments; delegated to the helper. +/// +/// \return The exit code of the helper, which depends on the requested helper. +int +main(int argc, char** argv) +{ + const char* command = std::getenv("HELPER"); + if (command == NULL) { + std::cerr << "Usage error: HELPER must be set to a helper name\n"; + std::exit(EXIT_FAILURE); + } + + const struct helper* iter = helpers; + for (; iter->name != NULL && std::strcmp(iter->name, command) != 0; iter++) + ; + if (iter->name == NULL) { + std::cerr << "Usage error: unknown command " << command << "\n"; + std::exit(EXIT_FAILURE); + } + + return iter->hook(argc, argv); +} diff --git a/external/bsd/kyua-cli/dist/bootstrap/testsuite b/external/bsd/kyua-cli/dist/bootstrap/testsuite new file mode 100755 index 000000000..151dda2a8 --- /dev/null +++ b/external/bsd/kyua-cli/dist/bootstrap/testsuite @@ -0,0 +1,2860 @@ +#! /bin/sh +# Generated from bootstrap/testsuite.at by GNU Autoconf 2.69. +# +# Copyright (C) 2009-2012 Free Software Foundation, Inc. +# +# This test suite is free software; the Free Software Foundation gives +# unlimited permission to copy, distribute and modify it. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1 +test -x / || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + export CONFIG_SHELL + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +exit 255 +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, +$0: including any error possibly output before this +$0: message. Then install a modern shell, or manually run +$0: the script under such a shell if you do have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # If we had to re-execute with $CONFIG_SHELL, we're ensured to have + # already done that, so ensure we don't try to do so again and fall + # in an infinite loop. This has already happened in practice. + _as_can_reexec=no; export _as_can_reexec + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + + + + +SHELL=${CONFIG_SHELL-/bin/sh} + +# How were we run? +at_cli_args="$@" + + +# Not all shells have the 'times' builtin; the subshell is needed to make +# sure we discard the 'times: not found' message from the shell. +at_times_p=false +(times) >/dev/null 2>&1 && at_times_p=: + +# CLI Arguments to pass to the debugging scripts. +at_debug_args= +# -e sets to true +at_errexit_p=false +# Shall we be verbose? ':' means no, empty means yes. +at_verbose=: +at_quiet= +# Running several jobs in parallel, 0 means as many as test groups. +at_jobs=1 +at_traceon=: +at_trace_echo=: +at_check_filter_trace=: + +# Shall we keep the debug scripts? Must be `:' when the suite is +# run by a debug script, so that the script doesn't remove itself. +at_debug_p=false +# Display help message? +at_help_p=false +# Display the version message? +at_version_p=false +# List test groups? +at_list_p=false +# --clean +at_clean=false +# Test groups to run +at_groups= +# Whether to rerun failed tests. +at_recheck= +# Whether a write failure occurred +at_write_fail=0 + +# The directory we run the suite in. Default to . if no -C option. +at_dir=`pwd` +# An absolute reference to this testsuite script. +case $as_myself in + [\\/]* | ?:[\\/]* ) at_myself=$as_myself ;; + * ) at_myself=$at_dir/$as_myself ;; +esac +# Whether -C is in effect. +at_change_dir=false + +# Whether to enable colored test results. +at_color=no +# List of the tested programs. +at_tested='kyua' +# As many question marks as there are digits in the last test group number. +# Used to normalize the test group numbers so that `ls' lists them in +# numerical order. +at_format='??' +# Description of all the test groups. +at_help_all="1;testsuite.at:70;test program crashes in test list;; +2;testsuite.at:81;test program prints an empty test list;; +3;testsuite.at:92;test program with zero test cases;; +4;testsuite.at:103;run test case that passes;; +5;testsuite.at:115;run test case that fails;; +6;testsuite.at:128;run test case that skips;; +7;testsuite.at:141;run two test cases, success;; +8;testsuite.at:154;run two test cases, failure;; +9;testsuite.at:167;run mixed test cases;; +10;testsuite.at:181;run tests from build directories;; +" +# List of the all the test groups. +at_groups_all=`$as_echo "$at_help_all" | sed 's/;.*//'` + +# at_fn_validate_ranges NAME... +# ----------------------------- +# Validate and normalize the test group number contained in each variable +# NAME. Leading zeroes are treated as decimal. +at_fn_validate_ranges () +{ + for at_grp + do + eval at_value=\$$at_grp + if test $at_value -lt 1 || test $at_value -gt 10; then + $as_echo "invalid test group: $at_value" >&2 + exit 1 + fi + case $at_value in + 0*) # We want to treat leading 0 as decimal, like expr and test, but + # AS_VAR_ARITH treats it as octal if it uses $(( )). + # With XSI shells, ${at_value#${at_value%%[1-9]*}} avoids the + # expr fork, but it is not worth the effort to determine if the + # shell supports XSI when the user can just avoid leading 0. + eval $at_grp='`expr $at_value + 0`' ;; + esac + done +} + +at_prev= +for at_option +do + # If the previous option needs an argument, assign it. + if test -n "$at_prev"; then + at_option=$at_prev=$at_option + at_prev= + fi + + case $at_option in + *=?*) at_optarg=`expr "X$at_option" : '[^=]*=\(.*\)'` ;; + *) at_optarg= ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $at_option in + --help | -h ) + at_help_p=: + ;; + + --list | -l ) + at_list_p=: + ;; + + --version | -V ) + at_version_p=: + ;; + + --clean | -c ) + at_clean=: + ;; + + --color ) + at_color=always + ;; + --color=* ) + case $at_optarg in + no | never | none) at_color=never ;; + auto | tty | if-tty) at_color=auto ;; + always | yes | force) at_color=always ;; + *) at_optname=`echo " $at_option" | sed 's/^ //; s/=.*//'` + as_fn_error $? "unrecognized argument to $at_optname: $at_optarg" ;; + esac + ;; + + --debug | -d ) + at_debug_p=: + ;; + + --errexit | -e ) + at_debug_p=: + at_errexit_p=: + ;; + + --verbose | -v ) + at_verbose=; at_quiet=: + ;; + + --trace | -x ) + at_traceon='set -x' + at_trace_echo=echo + at_check_filter_trace=at_fn_filter_trace + ;; + + [0-9] | [0-9][0-9] | [0-9][0-9][0-9] | [0-9][0-9][0-9][0-9]) + at_fn_validate_ranges at_option + as_fn_append at_groups "$at_option$as_nl" + ;; + + # Ranges + [0-9]- | [0-9][0-9]- | [0-9][0-9][0-9]- | [0-9][0-9][0-9][0-9]-) + at_range_start=`echo $at_option |tr -d X-` + at_fn_validate_ranges at_range_start + at_range=`$as_echo "$at_groups_all" | \ + sed -ne '/^'$at_range_start'$/,$p'` + as_fn_append at_groups "$at_range$as_nl" + ;; + + -[0-9] | -[0-9][0-9] | -[0-9][0-9][0-9] | -[0-9][0-9][0-9][0-9]) + at_range_end=`echo $at_option |tr -d X-` + at_fn_validate_ranges at_range_end + at_range=`$as_echo "$at_groups_all" | \ + sed -ne '1,/^'$at_range_end'$/p'` + as_fn_append at_groups "$at_range$as_nl" + ;; + + [0-9]-[0-9] | [0-9]-[0-9][0-9] | [0-9]-[0-9][0-9][0-9] | \ + [0-9]-[0-9][0-9][0-9][0-9] | [0-9][0-9]-[0-9][0-9] | \ + [0-9][0-9]-[0-9][0-9][0-9] | [0-9][0-9]-[0-9][0-9][0-9][0-9] | \ + [0-9][0-9][0-9]-[0-9][0-9][0-9] | \ + [0-9][0-9][0-9]-[0-9][0-9][0-9][0-9] | \ + [0-9][0-9][0-9][0-9]-[0-9][0-9][0-9][0-9] ) + at_range_start=`expr $at_option : '\(.*\)-'` + at_range_end=`expr $at_option : '.*-\(.*\)'` + if test $at_range_start -gt $at_range_end; then + at_tmp=$at_range_end + at_range_end=$at_range_start + at_range_start=$at_tmp + fi + at_fn_validate_ranges at_range_start at_range_end + at_range=`$as_echo "$at_groups_all" | \ + sed -ne '/^'$at_range_start'$/,/^'$at_range_end'$/p'` + as_fn_append at_groups "$at_range$as_nl" + ;; + + # Directory selection. + --directory | -C ) + at_prev=--directory + ;; + --directory=* ) + at_change_dir=: + at_dir=$at_optarg + if test x- = "x$at_dir" ; then + at_dir=./- + fi + ;; + + # Parallel execution. + --jobs | -j ) + at_jobs=0 + ;; + --jobs=* | -j[0-9]* ) + if test -n "$at_optarg"; then + at_jobs=$at_optarg + else + at_jobs=`expr X$at_option : 'X-j\(.*\)'` + fi + case $at_jobs in *[!0-9]*) + at_optname=`echo " $at_option" | sed 's/^ //; s/[0-9=].*//'` + as_fn_error $? "non-numeric argument to $at_optname: $at_jobs" ;; + esac + ;; + + # Keywords. + --keywords | -k ) + at_prev=--keywords + ;; + --keywords=* ) + at_groups_selected=$at_help_all + at_save_IFS=$IFS + IFS=, + set X $at_optarg + shift + IFS=$at_save_IFS + for at_keyword + do + at_invert= + case $at_keyword in + '!'*) + at_invert="-v" + at_keyword=`expr "X$at_keyword" : 'X!\(.*\)'` + ;; + esac + # It is on purpose that we match the test group titles too. + at_groups_selected=`$as_echo "$at_groups_selected" | + grep -i $at_invert "^[1-9][^;]*;.*[; ]$at_keyword[ ;]"` + done + # Smash the keywords. + at_groups_selected=`$as_echo "$at_groups_selected" | sed 's/;.*//'` + as_fn_append at_groups "$at_groups_selected$as_nl" + ;; + --recheck) + at_recheck=: + ;; + + *=*) + at_envvar=`expr "x$at_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $at_envvar in + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$at_envvar'" ;; + esac + at_value=`$as_echo "$at_optarg" | sed "s/'/'\\\\\\\\''/g"` + # Export now, but save eval for later and for debug scripts. + export $at_envvar + as_fn_append at_debug_args " $at_envvar='$at_value'" + ;; + + *) $as_echo "$as_me: invalid option: $at_option" >&2 + $as_echo "Try \`$0 --help' for more information." >&2 + exit 1 + ;; + esac +done + +# Verify our last option didn't require an argument +if test -n "$at_prev"; then : + as_fn_error $? "\`$at_prev' requires an argument" +fi + +# The file containing the suite. +at_suite_log=$at_dir/$as_me.log + +# Selected test groups. +if test -z "$at_groups$at_recheck"; then + at_groups=$at_groups_all +else + if test -n "$at_recheck" && test -r "$at_suite_log"; then + at_oldfails=`sed -n ' + /^Failed tests:$/,/^Skipped tests:$/{ + s/^[ ]*\([1-9][0-9]*\):.*/\1/p + } + /^Unexpected passes:$/,/^## Detailed failed tests/{ + s/^[ ]*\([1-9][0-9]*\):.*/\1/p + } + /^## Detailed failed tests/q + ' "$at_suite_log"` + as_fn_append at_groups "$at_oldfails$as_nl" + fi + # Sort the tests, removing duplicates. + at_groups=`$as_echo "$at_groups" | sort -nu | sed '/^$/d'` +fi + +if test x"$at_color" = xalways \ + || { test x"$at_color" = xauto && test -t 1; }; then + at_red=`printf '\033[0;31m'` + at_grn=`printf '\033[0;32m'` + at_lgn=`printf '\033[1;32m'` + at_blu=`printf '\033[1;34m'` + at_std=`printf '\033[m'` +else + at_red= at_grn= at_lgn= at_blu= at_std= +fi + +# Help message. +if $at_help_p; then + cat <<_ATEOF || at_write_fail=1 +Usage: $0 [OPTION]... [VARIABLE=VALUE]... [TESTS] + +Run all the tests, or the selected TESTS, given by numeric ranges, and +save a detailed log file. Upon failure, create debugging scripts. + +Do not change environment variables directly. Instead, set them via +command line arguments. Set \`AUTOTEST_PATH' to select the executables +to exercise. Each relative directory is expanded as build and source +directories relative to the top level of this distribution. +E.g., from within the build directory /tmp/foo-1.0, invoking this: + + $ $0 AUTOTEST_PATH=bin + +is equivalent to the following, assuming the source directory is /src/foo-1.0: + + PATH=/tmp/foo-1.0/bin:/src/foo-1.0/bin:\$PATH $0 +_ATEOF +cat <<_ATEOF || at_write_fail=1 + +Operation modes: + -h, --help print the help message, then exit + -V, --version print version number, then exit + -c, --clean remove all the files this test suite might create and exit + -l, --list describes all the tests, or the selected TESTS +_ATEOF +cat <<_ATEOF || at_write_fail=1 + +Execution tuning: + -C, --directory=DIR + change to directory DIR before starting + --color[=never|auto|always] + enable colored test results on terminal, or always + -j, --jobs[=N] + Allow N jobs at once; infinite jobs with no arg (default 1) + -k, --keywords=KEYWORDS + select the tests matching all the comma-separated KEYWORDS + multiple \`-k' accumulate; prefixed \`!' negates a KEYWORD + --recheck select all tests that failed or passed unexpectedly last time + -e, --errexit abort as soon as a test fails; implies --debug + -v, --verbose force more detailed output + default for debugging scripts + -d, --debug inhibit clean up and top-level logging + default for debugging scripts + -x, --trace enable tests shell tracing +_ATEOF +cat <<_ATEOF || at_write_fail=1 + +Report bugs to . +_ATEOF + exit $at_write_fail +fi + +# List of tests. +if $at_list_p; then + cat <<_ATEOF || at_write_fail=1 +Kyua - Command line interface 0.6 test suite: bootstrapping tests test groups: + + NUM: FILE-NAME:LINE TEST-GROUP-NAME + KEYWORDS + +_ATEOF + # Pass an empty line as separator between selected groups and help. + $as_echo "$at_groups$as_nl$as_nl$at_help_all" | + awk 'NF == 1 && FS != ";" { + selected[$ 1] = 1 + next + } + /^$/ { FS = ";" } + NF > 0 { + if (selected[$ 1]) { + printf " %3d: %-18s %s\n", $ 1, $ 2, $ 3 + if ($ 4) { + lmax = 79 + indent = " " + line = indent + len = length (line) + n = split ($ 4, a, " ") + for (i = 1; i <= n; i++) { + l = length (a[i]) + 1 + if (i > 1 && len + l > lmax) { + print line + line = indent " " a[i] + len = length (line) + } else { + line = line " " a[i] + len += l + } + } + if (n) + print line + } + } + }' || at_write_fail=1 + exit $at_write_fail +fi +if $at_version_p; then + $as_echo "$as_me (Kyua - Command line interface 0.6)" && + cat <<\_ATEOF || at_write_fail=1 + +Copyright (C) 2012 Free Software Foundation, Inc. +This test suite is free software; the Free Software Foundation gives +unlimited permission to copy, distribute and modify it. +_ATEOF + exit $at_write_fail +fi + +# Should we print banners? Yes if more than one test is run. +case $at_groups in #( + *$as_nl* ) + at_print_banners=: ;; #( + * ) at_print_banners=false ;; +esac +# Text for banner N, set to a single space once printed. + +# Take any -C into account. +if $at_change_dir ; then + test x != "x$at_dir" && cd "$at_dir" \ + || as_fn_error $? "unable to change directory" + at_dir=`pwd` +fi + +# Load the config files for any default variable assignments. +for at_file in atconfig atlocal +do + test -r $at_file || continue + . ./$at_file || as_fn_error $? "invalid content: $at_file" +done + +# Autoconf <=2.59b set at_top_builddir instead of at_top_build_prefix: +: "${at_top_build_prefix=$at_top_builddir}" + +# Perform any assignments requested during argument parsing. +eval "$at_debug_args" + +# atconfig delivers names relative to the directory the test suite is +# in, but the groups themselves are run in testsuite-dir/group-dir. +if test -n "$at_top_srcdir"; then + builddir=../.. + for at_dir_var in srcdir top_srcdir top_build_prefix + do + eval at_val=\$at_$at_dir_var + case $at_val in + [\\/$]* | ?:[\\/]* ) at_prefix= ;; + *) at_prefix=../../ ;; + esac + eval "$at_dir_var=\$at_prefix\$at_val" + done +fi + +## -------------------- ## +## Directory structure. ## +## -------------------- ## + +# This is the set of directories and files used by this script +# (non-literals are capitalized): +# +# TESTSUITE - the testsuite +# TESTSUITE.log - summarizes the complete testsuite run +# TESTSUITE.dir/ - created during a run, remains after -d or failed test +# + at-groups/ - during a run: status of all groups in run +# | + NNN/ - during a run: meta-data about test group NNN +# | | + check-line - location (source file and line) of current AT_CHECK +# | | + status - exit status of current AT_CHECK +# | | + stdout - stdout of current AT_CHECK +# | | + stder1 - stderr, including trace +# | | + stderr - stderr, with trace filtered out +# | | + test-source - portion of testsuite that defines group +# | | + times - timestamps for computing duration +# | | + pass - created if group passed +# | | + xpass - created if group xpassed +# | | + fail - created if group failed +# | | + xfail - created if group xfailed +# | | + skip - created if group skipped +# + at-stop - during a run: end the run if this file exists +# + at-source-lines - during a run: cache of TESTSUITE line numbers for extraction +# + 0..NNN/ - created for each group NNN, remains after -d or failed test +# | + TESTSUITE.log - summarizes the group results +# | + ... - files created during the group + +# The directory the whole suite works in. +# Should be absolute to let the user `cd' at will. +at_suite_dir=$at_dir/$as_me.dir +# The file containing the suite ($at_dir might have changed since earlier). +at_suite_log=$at_dir/$as_me.log +# The directory containing helper files per test group. +at_helper_dir=$at_suite_dir/at-groups +# Stop file: if it exists, do not start new jobs. +at_stop_file=$at_suite_dir/at-stop +# The fifo used for the job dispatcher. +at_job_fifo=$at_suite_dir/at-job-fifo + +if $at_clean; then + test -d "$at_suite_dir" && + find "$at_suite_dir" -type d ! -perm -700 -exec chmod u+rwx \{\} \; + rm -f -r "$at_suite_dir" "$at_suite_log" + exit $? +fi + +# Don't take risks: use only absolute directories in PATH. +# +# For stand-alone test suites (ie. atconfig was not found), +# AUTOTEST_PATH is relative to `.'. +# +# For embedded test suites, AUTOTEST_PATH is relative to the top level +# of the package. Then expand it into build/src parts, since users +# may create executables in both places. +AUTOTEST_PATH=`$as_echo "$AUTOTEST_PATH" | sed "s|:|$PATH_SEPARATOR|g"` +at_path= +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $AUTOTEST_PATH $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -n "$at_path" && as_fn_append at_path $PATH_SEPARATOR +case $as_dir in + [\\/]* | ?:[\\/]* ) + as_fn_append at_path "$as_dir" + ;; + * ) + if test -z "$at_top_build_prefix"; then + # Stand-alone test suite. + as_fn_append at_path "$as_dir" + else + # Embedded test suite. + as_fn_append at_path "$at_top_build_prefix$as_dir$PATH_SEPARATOR" + as_fn_append at_path "$at_top_srcdir/$as_dir" + fi + ;; +esac + done +IFS=$as_save_IFS + + +# Now build and simplify PATH. +# +# There might be directories that don't exist, but don't redirect +# builtins' (eg., cd) stderr directly: Ultrix's sh hates that. +at_new_path= +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $at_path +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -d "$as_dir" || continue +case $as_dir in + [\\/]* | ?:[\\/]* ) ;; + * ) as_dir=`(cd "$as_dir" && pwd) 2>/dev/null` ;; +esac +case $PATH_SEPARATOR$at_new_path$PATH_SEPARATOR in + *$PATH_SEPARATOR$as_dir$PATH_SEPARATOR*) ;; + $PATH_SEPARATOR$PATH_SEPARATOR) at_new_path=$as_dir ;; + *) as_fn_append at_new_path "$PATH_SEPARATOR$as_dir" ;; +esac + done +IFS=$as_save_IFS + +PATH=$at_new_path +export PATH + +# Setting up the FDs. + + + +# 5 is the log file. Not to be overwritten if `-d'. +if $at_debug_p; then + at_suite_log=/dev/null +else + : >"$at_suite_log" +fi +exec 5>>"$at_suite_log" + +# Banners and logs. +$as_echo "## ------------------------------------------------------------------ ## +## Kyua - Command line interface 0.6 test suite: bootstrapping tests. ## +## ------------------------------------------------------------------ ##" +{ + $as_echo "## ------------------------------------------------------------------ ## +## Kyua - Command line interface 0.6 test suite: bootstrapping tests. ## +## ------------------------------------------------------------------ ##" + echo + + $as_echo "$as_me: command line was:" + $as_echo " \$ $0 $at_cli_args" + echo + + # If ChangeLog exists, list a few lines in case it might help determining + # the exact version. + if test -n "$at_top_srcdir" && test -f "$at_top_srcdir/ChangeLog"; then + $as_echo "## ---------- ## +## ChangeLog. ## +## ---------- ##" + echo + sed 's/^/| /;10q' "$at_top_srcdir/ChangeLog" + echo + fi + + { +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} + echo + + # Contents of the config files. + for at_file in atconfig atlocal + do + test -r $at_file || continue + $as_echo "$as_me: $at_file:" + sed 's/^/| /' $at_file + echo + done +} >&5 + + +## ------------------------- ## +## Autotest shell functions. ## +## ------------------------- ## + +# at_fn_banner NUMBER +# ------------------- +# Output banner NUMBER, provided the testsuite is running multiple groups and +# this particular banner has not yet been printed. +at_fn_banner () +{ + $at_print_banners || return 0 + eval at_banner_text=\$at_banner_text_$1 + test "x$at_banner_text" = "x " && return 0 + eval "at_banner_text_$1=\" \"" + if test -z "$at_banner_text"; then + $at_first || echo + else + $as_echo "$as_nl$at_banner_text$as_nl" + fi +} # at_fn_banner + +# at_fn_check_prepare_notrace REASON LINE +# --------------------------------------- +# Perform AT_CHECK preparations for the command at LINE for an untraceable +# command; REASON is the reason for disabling tracing. +at_fn_check_prepare_notrace () +{ + $at_trace_echo "Not enabling shell tracing (command contains $1)" + $as_echo "$2" >"$at_check_line_file" + at_check_trace=: at_check_filter=: + : >"$at_stdout"; : >"$at_stderr" +} + +# at_fn_check_prepare_trace LINE +# ------------------------------ +# Perform AT_CHECK preparations for the command at LINE for a traceable +# command. +at_fn_check_prepare_trace () +{ + $as_echo "$1" >"$at_check_line_file" + at_check_trace=$at_traceon at_check_filter=$at_check_filter_trace + : >"$at_stdout"; : >"$at_stderr" +} + +# at_fn_check_prepare_dynamic COMMAND LINE +# ---------------------------------------- +# Decide if COMMAND at LINE is traceable at runtime, and call the appropriate +# preparation function. +at_fn_check_prepare_dynamic () +{ + case $1 in + *$as_nl*) + at_fn_check_prepare_notrace 'an embedded newline' "$2" ;; + *) + at_fn_check_prepare_trace "$2" ;; + esac +} + +# at_fn_filter_trace +# ------------------ +# Remove the lines in the file "$at_stderr" generated by "set -x" and print +# them to stderr. +at_fn_filter_trace () +{ + mv "$at_stderr" "$at_stder1" + grep '^ *+' "$at_stder1" >&2 + grep -v '^ *+' "$at_stder1" >"$at_stderr" +} + +# at_fn_log_failure FILE-LIST +# --------------------------- +# Copy the files in the list on stdout with a "> " prefix, and exit the shell +# with a failure exit code. +at_fn_log_failure () +{ + for file + do $as_echo "$file:"; sed 's/^/> /' "$file"; done + echo 1 > "$at_status_file" + exit 1 +} + +# at_fn_check_skip EXIT-CODE LINE +# ------------------------------- +# Check whether EXIT-CODE is a special exit code (77 or 99), and if so exit +# the test group subshell with that same exit code. Use LINE in any report +# about test failure. +at_fn_check_skip () +{ + case $1 in + 99) echo 99 > "$at_status_file"; at_failed=: + $as_echo "$2: hard failure"; exit 99;; + 77) echo 77 > "$at_status_file"; exit 77;; + esac +} + +# at_fn_check_status EXPECTED EXIT-CODE LINE +# ------------------------------------------ +# Check whether EXIT-CODE is the EXPECTED exit code, and if so do nothing. +# Otherwise, if it is 77 or 99, exit the test group subshell with that same +# exit code; if it is anything else print an error message referring to LINE, +# and fail the test. +at_fn_check_status () +{ + case $2 in + $1 ) ;; + 77) echo 77 > "$at_status_file"; exit 77;; + 99) echo 99 > "$at_status_file"; at_failed=: + $as_echo "$3: hard failure"; exit 99;; + *) $as_echo "$3: exit code was $2, expected $1" + at_failed=:;; + esac +} + +# at_fn_diff_devnull FILE +# ----------------------- +# Emit a diff between /dev/null and FILE. Uses "test -s" to avoid useless diff +# invocations. +at_fn_diff_devnull () +{ + test -s "$1" || return 0 + $at_diff "$at_devnull" "$1" +} + +# at_fn_test NUMBER +# ----------------- +# Parse out test NUMBER from the tail of this file. +at_fn_test () +{ + eval at_sed=\$at_sed$1 + sed "$at_sed" "$at_myself" > "$at_test_source" +} + +# at_fn_create_debugging_script +# ----------------------------- +# Create the debugging script $at_group_dir/run which will reproduce the +# current test group. +at_fn_create_debugging_script () +{ + { + echo "#! /bin/sh" && + echo 'test "${ZSH_VERSION+set}" = set && alias -g '\''${1+"$@"}'\''='\''"$@"'\''' && + $as_echo "cd '$at_dir'" && + $as_echo "exec \${CONFIG_SHELL-$SHELL} \"$at_myself\" -v -d $at_debug_args $at_group \${1+\"\$@\"}" && + echo 'exit 1' + } >"$at_group_dir/run" && + chmod +x "$at_group_dir/run" +} + +## -------------------------------- ## +## End of autotest shell functions. ## +## -------------------------------- ## +{ + $as_echo "## ---------------- ## +## Tested programs. ## +## ---------------- ##" + echo +} >&5 + +# Report what programs are being tested. +for at_program in : $at_tested +do + test "$at_program" = : && continue + case $at_program in + [\\/]* | ?:[\\/]* ) $at_program_=$at_program ;; + * ) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -f "$as_dir/$at_program" && break + done +IFS=$as_save_IFS + + at_program_=$as_dir/$at_program ;; + esac + if test -f "$at_program_"; then + { + $as_echo "$at_srcdir/testsuite.at:29: $at_program_ --version" + "$at_program_" --version &5 2>&1 + else + as_fn_error $? "cannot find $at_program" "$LINENO" 5 + fi +done + +{ + $as_echo "## ------------------ ## +## Running the tests. ## +## ------------------ ##" +} >&5 + +at_start_date=`date` +at_start_time=`date +%s 2>/dev/null` +$as_echo "$as_me: starting at: $at_start_date" >&5 + +# Create the master directory if it doesn't already exist. +as_dir="$at_suite_dir"; as_fn_mkdir_p || + as_fn_error $? "cannot create \`$at_suite_dir'" "$LINENO" 5 + +# Can we diff with `/dev/null'? DU 5.0 refuses. +if diff /dev/null /dev/null >/dev/null 2>&1; then + at_devnull=/dev/null +else + at_devnull=$at_suite_dir/devnull + >"$at_devnull" +fi + +# Use `diff -u' when possible. +if at_diff=`diff -u "$at_devnull" "$at_devnull" 2>&1` && test -z "$at_diff" +then + at_diff='diff -u' +else + at_diff=diff +fi + +# Get the last needed group. +for at_group in : $at_groups; do :; done + +# Extract the start and end lines of each test group at the tail +# of this file +awk ' +BEGIN { FS="" } +/^#AT_START_/ { + start = NR +} +/^#AT_STOP_/ { + test = substr ($ 0, 10) + print "at_sed" test "=\"1," start "d;" (NR-1) "q\"" + if (test == "'"$at_group"'") exit +}' "$at_myself" > "$at_suite_dir/at-source-lines" && +. "$at_suite_dir/at-source-lines" || + as_fn_error $? "cannot create test line number cache" "$LINENO" 5 +rm -f "$at_suite_dir/at-source-lines" + +# Set number of jobs for `-j'; avoid more jobs than test groups. +set X $at_groups; shift; at_max_jobs=$# +if test $at_max_jobs -eq 0; then + at_jobs=1 +fi +if test $at_jobs -ne 1 && + { test $at_jobs -eq 0 || test $at_jobs -gt $at_max_jobs; }; then + at_jobs=$at_max_jobs +fi + +# If parallel mode, don't output banners, don't split summary lines. +if test $at_jobs -ne 1; then + at_print_banners=false + at_quiet=: +fi + +# Set up helper dirs. +rm -rf "$at_helper_dir" && +mkdir "$at_helper_dir" && +cd "$at_helper_dir" && +{ test -z "$at_groups" || mkdir $at_groups; } || +as_fn_error $? "testsuite directory setup failed" "$LINENO" 5 + +# Functions for running a test group. We leave the actual +# test group execution outside of a shell function in order +# to avoid hitting zsh 4.x exit status bugs. + +# at_fn_group_prepare +# ------------------- +# Prepare for running a test group. +at_fn_group_prepare () +{ + # The directory for additional per-group helper files. + at_job_dir=$at_helper_dir/$at_group + # The file containing the location of the last AT_CHECK. + at_check_line_file=$at_job_dir/check-line + # The file containing the exit status of the last command. + at_status_file=$at_job_dir/status + # The files containing the output of the tested commands. + at_stdout=$at_job_dir/stdout + at_stder1=$at_job_dir/stder1 + at_stderr=$at_job_dir/stderr + # The file containing the code for a test group. + at_test_source=$at_job_dir/test-source + # The file containing dates. + at_times_file=$at_job_dir/times + + # Be sure to come back to the top test directory. + cd "$at_suite_dir" + + # Clearly separate the test groups when verbose. + $at_first || $at_verbose echo + + at_group_normalized=$at_group + + eval 'while :; do + case $at_group_normalized in #( + '"$at_format"'*) break;; + esac + at_group_normalized=0$at_group_normalized + done' + + + # Create a fresh directory for the next test group, and enter. + # If one already exists, the user may have invoked ./run from + # within that directory; we remove the contents, but not the + # directory itself, so that we aren't pulling the rug out from + # under the shell's notion of the current directory. + at_group_dir=$at_suite_dir/$at_group_normalized + at_group_log=$at_group_dir/$as_me.log + if test -d "$at_group_dir"; then + find "$at_group_dir" -type d ! -perm -700 -exec chmod u+rwx {} \; + rm -fr "$at_group_dir"/* "$at_group_dir"/.[!.] "$at_group_dir"/.??* +fi || + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: test directory for $at_group_normalized could not be cleaned" >&5 +$as_echo "$as_me: WARNING: test directory for $at_group_normalized could not be cleaned" >&2;} + # Be tolerant if the above `rm' was not able to remove the directory. + as_dir="$at_group_dir"; as_fn_mkdir_p + + echo 0 > "$at_status_file" + + # In verbose mode, append to the log file *and* show on + # the standard output; in quiet mode only write to the log. + if test -z "$at_verbose"; then + at_tee_pipe='tee -a "$at_group_log"' + else + at_tee_pipe='cat >> "$at_group_log"' + fi +} + +# at_fn_group_banner ORDINAL LINE DESC PAD [BANNER] +# ------------------------------------------------- +# Declare the test group ORDINAL, located at LINE with group description DESC, +# and residing under BANNER. Use PAD to align the status column. +at_fn_group_banner () +{ + at_setup_line="$2" + test -n "$5" && at_fn_banner $5 + at_desc="$3" + case $1 in + [0-9]) at_desc_line=" $1: ";; + [0-9][0-9]) at_desc_line=" $1: " ;; + *) at_desc_line="$1: " ;; + esac + as_fn_append at_desc_line "$3$4" + $at_quiet $as_echo_n "$at_desc_line" + echo "# -*- compilation -*-" >> "$at_group_log" +} + +# at_fn_group_postprocess +# ----------------------- +# Perform cleanup after running a test group. +at_fn_group_postprocess () +{ + # Be sure to come back to the suite directory, in particular + # since below we might `rm' the group directory we are in currently. + cd "$at_suite_dir" + + if test ! -f "$at_check_line_file"; then + sed "s/^ */$as_me: WARNING: /" <<_ATEOF + A failure happened in a test group before any test could be + run. This means that test suite is improperly designed. Please + report this failure to . +_ATEOF + $as_echo "$at_setup_line" >"$at_check_line_file" + at_status=99 + fi + $at_verbose $as_echo_n "$at_group. $at_setup_line: " + $as_echo_n "$at_group. $at_setup_line: " >> "$at_group_log" + case $at_xfail:$at_status in + yes:0) + at_msg="UNEXPECTED PASS" + at_res=xpass + at_errexit=$at_errexit_p + at_color=$at_red + ;; + no:0) + at_msg="ok" + at_res=pass + at_errexit=false + at_color=$at_grn + ;; + *:77) + at_msg='skipped ('`cat "$at_check_line_file"`')' + at_res=skip + at_errexit=false + at_color=$at_blu + ;; + no:* | *:99) + at_msg='FAILED ('`cat "$at_check_line_file"`')' + at_res=fail + at_errexit=$at_errexit_p + at_color=$at_red + ;; + yes:*) + at_msg='expected failure ('`cat "$at_check_line_file"`')' + at_res=xfail + at_errexit=false + at_color=$at_lgn + ;; + esac + echo "$at_res" > "$at_job_dir/$at_res" + # In parallel mode, output the summary line only afterwards. + if test $at_jobs -ne 1 && test -n "$at_verbose"; then + $as_echo "$at_desc_line $at_color$at_msg$at_std" + else + # Make sure there is a separator even with long titles. + $as_echo " $at_color$at_msg$at_std" + fi + at_log_msg="$at_group. $at_desc ($at_setup_line): $at_msg" + case $at_status in + 0|77) + # $at_times_file is only available if the group succeeded. + # We're not including the group log, so the success message + # is written in the global log separately. But we also + # write to the group log in case they're using -d. + if test -f "$at_times_file"; then + at_log_msg="$at_log_msg ("`sed 1d "$at_times_file"`')' + rm -f "$at_times_file" + fi + $as_echo "$at_log_msg" >> "$at_group_log" + $as_echo "$at_log_msg" >&5 + + # Cleanup the group directory, unless the user wants the files + # or the success was unexpected. + if $at_debug_p || test $at_res = xpass; then + at_fn_create_debugging_script + if test $at_res = xpass && $at_errexit; then + echo stop > "$at_stop_file" + fi + else + if test -d "$at_group_dir"; then + find "$at_group_dir" -type d ! -perm -700 -exec chmod u+rwx \{\} \; + rm -fr "$at_group_dir" + fi + rm -f "$at_test_source" + fi + ;; + *) + # Upon failure, include the log into the testsuite's global + # log. The failure message is written in the group log. It + # is later included in the global log. + $as_echo "$at_log_msg" >> "$at_group_log" + + # Upon failure, keep the group directory for autopsy, and create + # the debugging script. With -e, do not start any further tests. + at_fn_create_debugging_script + if $at_errexit; then + echo stop > "$at_stop_file" + fi + ;; + esac +} + + +## ------------ ## +## Driver loop. ## +## ------------ ## + + +if (set -m && set +m && set +b) >/dev/null 2>&1; then + set +b + at_job_control_on='set -m' at_job_control_off='set +m' at_job_group=- +else + at_job_control_on=: at_job_control_off=: at_job_group= +fi + +for at_signal in 1 2 15; do + trap 'set +x; set +e + $at_job_control_off + at_signal='"$at_signal"' + echo stop > "$at_stop_file" + trap "" $at_signal + at_pgids= + for at_pgid in `jobs -p 2>/dev/null`; do + at_pgids="$at_pgids $at_job_group$at_pgid" + done + test -z "$at_pgids" || kill -$at_signal $at_pgids 2>/dev/null + wait + if test "$at_jobs" -eq 1 || test -z "$at_verbose"; then + echo >&2 + fi + at_signame=`kill -l $at_signal 2>&1 || echo $at_signal` + set x $at_signame + test 1 -gt 2 && at_signame=$at_signal + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: caught signal $at_signame, bailing out" >&5 +$as_echo "$as_me: WARNING: caught signal $at_signame, bailing out" >&2;} + as_fn_arith 128 + $at_signal && exit_status=$as_val + as_fn_exit $exit_status' $at_signal +done + +rm -f "$at_stop_file" +at_first=: + +if test $at_jobs -ne 1 && + rm -f "$at_job_fifo" && + test -n "$at_job_group" && + ( mkfifo "$at_job_fifo" && trap 'exit 1' PIPE STOP TSTP ) 2>/dev/null +then + # FIFO job dispatcher. + + trap 'at_pids= + for at_pid in `jobs -p`; do + at_pids="$at_pids $at_job_group$at_pid" + done + if test -n "$at_pids"; then + at_sig=TSTP + test "${TMOUT+set}" = set && at_sig=STOP + kill -$at_sig $at_pids 2>/dev/null + fi + kill -STOP $$ + test -z "$at_pids" || kill -CONT $at_pids 2>/dev/null' TSTP + + echo + # Turn jobs into a list of numbers, starting from 1. + at_joblist=`$as_echo "$at_groups" | sed -n 1,${at_jobs}p` + + set X $at_joblist + shift + for at_group in $at_groups; do + $at_job_control_on 2>/dev/null + ( + # Start one test group. + $at_job_control_off + if $at_first; then + exec 7>"$at_job_fifo" + else + exec 6<&- + fi + trap 'set +x; set +e + trap "" PIPE + echo stop > "$at_stop_file" + echo >&7 + as_fn_exit 141' PIPE + at_fn_group_prepare + if cd "$at_group_dir" && + at_fn_test $at_group && + . "$at_test_source" + then :; else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unable to parse test group: $at_group" >&5 +$as_echo "$as_me: WARNING: unable to parse test group: $at_group" >&2;} + at_failed=: + fi + at_fn_group_postprocess + echo >&7 + ) & + $at_job_control_off + if $at_first; then + at_first=false + exec 6<"$at_job_fifo" 7>"$at_job_fifo" + fi + shift # Consume one token. + if test $# -gt 0; then :; else + read at_token <&6 || break + set x $* + fi + test -f "$at_stop_file" && break + done + exec 7>&- + # Read back the remaining ($at_jobs - 1) tokens. + set X $at_joblist + shift + if test $# -gt 0; then + shift + for at_job + do + read at_token + done <&6 + fi + exec 6<&- + wait +else + # Run serially, avoid forks and other potential surprises. + for at_group in $at_groups; do + at_fn_group_prepare + if cd "$at_group_dir" && + at_fn_test $at_group && + . "$at_test_source"; then :; else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unable to parse test group: $at_group" >&5 +$as_echo "$as_me: WARNING: unable to parse test group: $at_group" >&2;} + at_failed=: + fi + at_fn_group_postprocess + test -f "$at_stop_file" && break + at_first=false + done +fi + +# Wrap up the test suite with summary statistics. +cd "$at_helper_dir" + +# Use ?..???? when the list must remain sorted, the faster * otherwise. +at_pass_list=`for f in */pass; do echo $f; done | sed '/\*/d; s,/pass,,'` +at_skip_list=`for f in */skip; do echo $f; done | sed '/\*/d; s,/skip,,'` +at_xfail_list=`for f in */xfail; do echo $f; done | sed '/\*/d; s,/xfail,,'` +at_xpass_list=`for f in ?/xpass ??/xpass ???/xpass ????/xpass; do + echo $f; done | sed '/?/d; s,/xpass,,'` +at_fail_list=`for f in ?/fail ??/fail ???/fail ????/fail; do + echo $f; done | sed '/?/d; s,/fail,,'` + +set X $at_pass_list $at_xpass_list $at_xfail_list $at_fail_list $at_skip_list +shift; at_group_count=$# +set X $at_xpass_list; shift; at_xpass_count=$#; at_xpass_list=$* +set X $at_xfail_list; shift; at_xfail_count=$# +set X $at_fail_list; shift; at_fail_count=$#; at_fail_list=$* +set X $at_skip_list; shift; at_skip_count=$# + +as_fn_arith $at_group_count - $at_skip_count && at_run_count=$as_val +as_fn_arith $at_xpass_count + $at_fail_count && at_unexpected_count=$as_val +as_fn_arith $at_xfail_count + $at_fail_count && at_total_fail_count=$as_val + +# Back to the top directory. +cd "$at_dir" +rm -rf "$at_helper_dir" + +# Compute the duration of the suite. +at_stop_date=`date` +at_stop_time=`date +%s 2>/dev/null` +$as_echo "$as_me: ending at: $at_stop_date" >&5 +case $at_start_time,$at_stop_time in + [0-9]*,[0-9]*) + as_fn_arith $at_stop_time - $at_start_time && at_duration_s=$as_val + as_fn_arith $at_duration_s / 60 && at_duration_m=$as_val + as_fn_arith $at_duration_m / 60 && at_duration_h=$as_val + as_fn_arith $at_duration_s % 60 && at_duration_s=$as_val + as_fn_arith $at_duration_m % 60 && at_duration_m=$as_val + at_duration="${at_duration_h}h ${at_duration_m}m ${at_duration_s}s" + $as_echo "$as_me: test suite duration: $at_duration" >&5 + ;; +esac + +echo +$as_echo "## ------------- ## +## Test results. ## +## ------------- ##" +echo +{ + echo + $as_echo "## ------------- ## +## Test results. ## +## ------------- ##" + echo +} >&5 + +if test $at_run_count = 1; then + at_result="1 test" + at_were=was +else + at_result="$at_run_count tests" + at_were=were +fi +if $at_errexit_p && test $at_unexpected_count != 0; then + if test $at_xpass_count = 1; then + at_result="$at_result $at_were run, one passed" + else + at_result="$at_result $at_were run, one failed" + fi + at_result="$at_result unexpectedly and inhibited subsequent tests." + at_color=$at_red +else + # Don't you just love exponential explosion of the number of cases? + at_color=$at_red + case $at_xpass_count:$at_fail_count:$at_xfail_count in + # So far, so good. + 0:0:0) at_result="$at_result $at_were successful." at_color=$at_grn ;; + 0:0:*) at_result="$at_result behaved as expected." at_color=$at_lgn ;; + + # Some unexpected failures + 0:*:0) at_result="$at_result $at_were run, +$at_fail_count failed unexpectedly." ;; + + # Some failures, both expected and unexpected + 0:*:1) at_result="$at_result $at_were run, +$at_total_fail_count failed ($at_xfail_count expected failure)." ;; + 0:*:*) at_result="$at_result $at_were run, +$at_total_fail_count failed ($at_xfail_count expected failures)." ;; + + # No unexpected failures, but some xpasses + *:0:*) at_result="$at_result $at_were run, +$at_xpass_count passed unexpectedly." ;; + + # No expected failures, but failures and xpasses + *:1:0) at_result="$at_result $at_were run, +$at_unexpected_count did not behave as expected ($at_fail_count unexpected failure)." ;; + *:*:0) at_result="$at_result $at_were run, +$at_unexpected_count did not behave as expected ($at_fail_count unexpected failures)." ;; + + # All of them. + *:*:1) at_result="$at_result $at_were run, +$at_xpass_count passed unexpectedly, +$at_total_fail_count failed ($at_xfail_count expected failure)." ;; + *:*:*) at_result="$at_result $at_were run, +$at_xpass_count passed unexpectedly, +$at_total_fail_count failed ($at_xfail_count expected failures)." ;; + esac + + if test $at_skip_count = 0 && test $at_run_count -gt 1; then + at_result="All $at_result" + fi +fi + +# Now put skips in the mix. +case $at_skip_count in + 0) ;; + 1) at_result="$at_result +1 test was skipped." ;; + *) at_result="$at_result +$at_skip_count tests were skipped." ;; +esac + +if test $at_unexpected_count = 0; then + echo "$at_color$at_result$at_std" + echo "$at_result" >&5 +else + echo "${at_color}ERROR: $at_result$at_std" >&2 + echo "ERROR: $at_result" >&5 + { + echo + $as_echo "## ------------------------ ## +## Summary of the failures. ## +## ------------------------ ##" + + # Summary of failed and skipped tests. + if test $at_fail_count != 0; then + echo "Failed tests:" + $SHELL "$at_myself" $at_fail_list --list + echo + fi + if test $at_skip_count != 0; then + echo "Skipped tests:" + $SHELL "$at_myself" $at_skip_list --list + echo + fi + if test $at_xpass_count != 0; then + echo "Unexpected passes:" + $SHELL "$at_myself" $at_xpass_list --list + echo + fi + if test $at_fail_count != 0; then + $as_echo "## ---------------------- ## +## Detailed failed tests. ## +## ---------------------- ##" + echo + for at_group in $at_fail_list + do + at_group_normalized=$at_group + + eval 'while :; do + case $at_group_normalized in #( + '"$at_format"'*) break;; + esac + at_group_normalized=0$at_group_normalized + done' + + cat "$at_suite_dir/$at_group_normalized/$as_me.log" + echo + done + echo + fi + if test -n "$at_top_srcdir"; then + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## ${at_top_build_prefix}config.log ## +_ASBOX + sed 's/^/| /' ${at_top_build_prefix}config.log + echo + fi + } >&5 + + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## $as_me.log was created. ## +_ASBOX + + echo + if $at_debug_p; then + at_msg='per-test log files' + else + at_msg="\`${at_testdir+${at_testdir}/}$as_me.log'" + fi + $as_echo "Please send $at_msg and all information you think might help: + + To: + Subject: [Kyua - Command line interface 0.6] $as_me: $at_fail_list${at_fail_list:+ failed${at_xpass_list:+, }}$at_xpass_list${at_xpass_list:+ passed unexpectedly} + +You may investigate any problem if you feel able to do so, in which +case the test suite provides a good starting point. Its output may +be found below \`${at_testdir+${at_testdir}/}$as_me.dir'. +" + exit 1 +fi + +exit 0 + +## ------------- ## +## Actual tests. ## +## ------------- ## +#AT_START_1 +at_fn_group_banner 1 'testsuite.at:70' \ + "test program crashes in test list" " " +at_xfail=no +( + $as_echo "1. $at_setup_line: testing $at_desc ..." + $at_traceon + + + + + cat >Kyuafile <<'_ATEOF' + +syntax(2) +test_suite("bootstrap") +atf_test_program{name="plain_helpers"} +_ATEOF + + ln -s $({ + old=$(pwd) + cd "${at_suite_dir}" + # We need to locate a build product, not a source file, because the + # test suite may be run outside of the source tree (think distcheck). + while test $(pwd) != '/' -a ! -e engine/test_case_test; do + cd .. + done + topdir=$(pwd) + cd ${old} + echo ${topdir} +})/bootstrap/plain_helpers plain_helpers + +{ set +x +$as_echo "$at_srcdir/testsuite.at:74: HOME=\$(pwd) HELPER=\"abort_test_cases_list\" kyua --config=none test --store=bootstrap.db" +at_fn_check_prepare_notrace 'a $(...) command substitution' "testsuite.at:74" +( $at_check_trace; HOME=$(pwd) HELPER="abort_test_cases_list" kyua --config=none test --store=bootstrap.db +) >>"$at_stdout" 2>>"$at_stderr" 5>&- +at_status=$? at_failed=false +$at_check_filter +at_fn_diff_devnull "$at_stderr" || at_failed=: +echo stdout:; tee stdout <"$at_stdout" +at_fn_check_status 1 $at_status "$at_srcdir/testsuite.at:74" +$at_failed && at_fn_log_failure +$at_traceon; } + +re='plain_helpers:__test_cases_list__.*broken.*Test program list did not return success' +{ set +x +$as_echo "$at_srcdir/testsuite.at:76: grep \"\${re}\" stdout" +at_fn_check_prepare_notrace 'a ${...} parameter expansion' "testsuite.at:76" +( $at_check_trace; grep "${re}" stdout +) >>"$at_stdout" 2>>"$at_stderr" 5>&- +at_status=$? at_failed=false +$at_check_filter +at_fn_diff_devnull "$at_stderr" || at_failed=: +echo stdout:; cat "$at_stdout" +at_fn_check_status 0 $at_status "$at_srcdir/testsuite.at:76" +$at_failed && at_fn_log_failure +$at_traceon; } + + + set +x + $at_times_p && times >"$at_times_file" +) 5>&1 2>&1 7>&- | eval $at_tee_pipe +read at_status <"$at_status_file" +#AT_STOP_1 +#AT_START_2 +at_fn_group_banner 2 'testsuite.at:81' \ + "test program prints an empty test list" " " +at_xfail=no +( + $as_echo "2. $at_setup_line: testing $at_desc ..." + $at_traceon + + + + + cat >Kyuafile <<'_ATEOF' + +syntax(2) +test_suite("bootstrap") +atf_test_program{name="plain_helpers"} +_ATEOF + + ln -s $({ + old=$(pwd) + cd "${at_suite_dir}" + # We need to locate a build product, not a source file, because the + # test suite may be run outside of the source tree (think distcheck). + while test $(pwd) != '/' -a ! -e engine/test_case_test; do + cd .. + done + topdir=$(pwd) + cd ${old} + echo ${topdir} +})/bootstrap/plain_helpers plain_helpers + +{ set +x +$as_echo "$at_srcdir/testsuite.at:85: HOME=\$(pwd) HELPER=\"empty_test_cases_list\" kyua --config=none test --store=bootstrap.db" +at_fn_check_prepare_notrace 'a $(...) command substitution' "testsuite.at:85" +( $at_check_trace; HOME=$(pwd) HELPER="empty_test_cases_list" kyua --config=none test --store=bootstrap.db +) >>"$at_stdout" 2>>"$at_stderr" 5>&- +at_status=$? at_failed=false +$at_check_filter +at_fn_diff_devnull "$at_stderr" || at_failed=: +echo stdout:; tee stdout <"$at_stdout" +at_fn_check_status 1 $at_status "$at_srcdir/testsuite.at:85" +$at_failed && at_fn_log_failure +$at_traceon; } + +re='plain_helpers:__test_cases_list__.*broken.*failed to read.*unexpected EOF' +{ set +x +$as_echo "$at_srcdir/testsuite.at:87: grep \"\${re}\" stdout" +at_fn_check_prepare_notrace 'a ${...} parameter expansion' "testsuite.at:87" +( $at_check_trace; grep "${re}" stdout +) >>"$at_stdout" 2>>"$at_stderr" 5>&- +at_status=$? at_failed=false +$at_check_filter +at_fn_diff_devnull "$at_stderr" || at_failed=: +echo stdout:; cat "$at_stdout" +at_fn_check_status 0 $at_status "$at_srcdir/testsuite.at:87" +$at_failed && at_fn_log_failure +$at_traceon; } + + + set +x + $at_times_p && times >"$at_times_file" +) 5>&1 2>&1 7>&- | eval $at_tee_pipe +read at_status <"$at_status_file" +#AT_STOP_2 +#AT_START_3 +at_fn_group_banner 3 'testsuite.at:92' \ + "test program with zero test cases" " " +at_xfail=no +( + $as_echo "3. $at_setup_line: testing $at_desc ..." + $at_traceon + + + + + cat >Kyuafile <<'_ATEOF' + +syntax(2) +test_suite("bootstrap") +atf_test_program{name="plain_helpers"} +_ATEOF + + ln -s $({ + old=$(pwd) + cd "${at_suite_dir}" + # We need to locate a build product, not a source file, because the + # test suite may be run outside of the source tree (think distcheck). + while test $(pwd) != '/' -a ! -e engine/test_case_test; do + cd .. + done + topdir=$(pwd) + cd ${old} + echo ${topdir} +})/bootstrap/plain_helpers plain_helpers + +{ set +x +$as_echo "$at_srcdir/testsuite.at:96: HOME=\$(pwd) HELPER=\"zero_test_cases\" kyua --config=none test --store=bootstrap.db" +at_fn_check_prepare_notrace 'a $(...) command substitution' "testsuite.at:96" +( $at_check_trace; HOME=$(pwd) HELPER="zero_test_cases" kyua --config=none test --store=bootstrap.db +) >>"$at_stdout" 2>>"$at_stderr" 5>&- +at_status=$? at_failed=false +$at_check_filter +at_fn_diff_devnull "$at_stderr" || at_failed=: +echo stdout:; tee stdout <"$at_stdout" +at_fn_check_status 1 $at_status "$at_srcdir/testsuite.at:96" +$at_failed && at_fn_log_failure +$at_traceon; } + +re='plain_helpers:__test_cases_list__.*broken.*Empty test cases list' +{ set +x +$as_echo "$at_srcdir/testsuite.at:98: grep \"\${re}\" stdout" +at_fn_check_prepare_notrace 'a ${...} parameter expansion' "testsuite.at:98" +( $at_check_trace; grep "${re}" stdout +) >>"$at_stdout" 2>>"$at_stderr" 5>&- +at_status=$? at_failed=false +$at_check_filter +at_fn_diff_devnull "$at_stderr" || at_failed=: +echo stdout:; cat "$at_stdout" +at_fn_check_status 0 $at_status "$at_srcdir/testsuite.at:98" +$at_failed && at_fn_log_failure +$at_traceon; } + + + set +x + $at_times_p && times >"$at_times_file" +) 5>&1 2>&1 7>&- | eval $at_tee_pipe +read at_status <"$at_status_file" +#AT_STOP_3 +#AT_START_4 +at_fn_group_banner 4 'testsuite.at:103' \ + "run test case that passes" " " +at_xfail=no +( + $as_echo "4. $at_setup_line: testing $at_desc ..." + $at_traceon + + + + + cat >Kyuafile <<'_ATEOF' + +syntax(2) +test_suite("bootstrap") +atf_test_program{name="atf_helpers"} +_ATEOF + + ln -s $({ + old=$(pwd) + cd "${at_suite_dir}" + # We need to locate a build product, not a source file, because the + # test suite may be run outside of the source tree (think distcheck). + while test $(pwd) != '/' -a ! -e engine/test_case_test; do + cd .. + done + topdir=$(pwd) + cd ${old} + echo ${topdir} +})/bootstrap/atf_helpers atf_helpers + +{ set +x +$as_echo "$at_srcdir/testsuite.at:107: HOME=\$(pwd) TESTS=\"passes\" kyua --config=none test --store=bootstrap.db " +at_fn_check_prepare_notrace 'a $(...) command substitution' "testsuite.at:107" +( $at_check_trace; HOME=$(pwd) TESTS="passes" kyua --config=none test --store=bootstrap.db +) >>"$at_stdout" 2>>"$at_stderr" 5>&- +at_status=$? at_failed=false +$at_check_filter +at_fn_diff_devnull "$at_stderr" || at_failed=: +echo stdout:; tee stdout <"$at_stdout" +at_fn_check_status 0 $at_status "$at_srcdir/testsuite.at:107" +$at_failed && at_fn_log_failure +$at_traceon; } + +{ set +x +$as_echo "$at_srcdir/testsuite.at:108: grep \"atf_helpers:fails\" stdout" +at_fn_check_prepare_trace "testsuite.at:108" +( $at_check_trace; grep "atf_helpers:fails" stdout +) >>"$at_stdout" 2>>"$at_stderr" 5>&- +at_status=$? at_failed=false +$at_check_filter +at_fn_diff_devnull "$at_stderr" || at_failed=: +at_fn_diff_devnull "$at_stdout" || at_failed=: +at_fn_check_status 1 $at_status "$at_srcdir/testsuite.at:108" +$at_failed && at_fn_log_failure +$at_traceon; } + +{ set +x +$as_echo "$at_srcdir/testsuite.at:109: grep \"atf_helpers:passes.*passed\" stdout" +at_fn_check_prepare_trace "testsuite.at:109" +( $at_check_trace; grep "atf_helpers:passes.*passed" stdout +) >>"$at_stdout" 2>>"$at_stderr" 5>&- +at_status=$? at_failed=false +$at_check_filter +at_fn_diff_devnull "$at_stderr" || at_failed=: +echo stdout:; cat "$at_stdout" +at_fn_check_status 0 $at_status "$at_srcdir/testsuite.at:109" +$at_failed && at_fn_log_failure +$at_traceon; } + +{ set +x +$as_echo "$at_srcdir/testsuite.at:110: grep \"atf_helpers:skips\" stdout" +at_fn_check_prepare_trace "testsuite.at:110" +( $at_check_trace; grep "atf_helpers:skips" stdout +) >>"$at_stdout" 2>>"$at_stderr" 5>&- +at_status=$? at_failed=false +$at_check_filter +at_fn_diff_devnull "$at_stderr" || at_failed=: +at_fn_diff_devnull "$at_stdout" || at_failed=: +at_fn_check_status 1 $at_status "$at_srcdir/testsuite.at:110" +$at_failed && at_fn_log_failure +$at_traceon; } + + + set +x + $at_times_p && times >"$at_times_file" +) 5>&1 2>&1 7>&- | eval $at_tee_pipe +read at_status <"$at_status_file" +#AT_STOP_4 +#AT_START_5 +at_fn_group_banner 5 'testsuite.at:115' \ + "run test case that fails" " " +at_xfail=no +( + $as_echo "5. $at_setup_line: testing $at_desc ..." + $at_traceon + + + + + cat >Kyuafile <<'_ATEOF' + +syntax(2) +test_suite("bootstrap") +atf_test_program{name="atf_helpers"} +_ATEOF + + ln -s $({ + old=$(pwd) + cd "${at_suite_dir}" + # We need to locate a build product, not a source file, because the + # test suite may be run outside of the source tree (think distcheck). + while test $(pwd) != '/' -a ! -e engine/test_case_test; do + cd .. + done + topdir=$(pwd) + cd ${old} + echo ${topdir} +})/bootstrap/atf_helpers atf_helpers + +{ set +x +$as_echo "$at_srcdir/testsuite.at:119: HOME=\$(pwd) TESTS=\"fails\" kyua --config=none test --store=bootstrap.db " +at_fn_check_prepare_notrace 'a $(...) command substitution' "testsuite.at:119" +( $at_check_trace; HOME=$(pwd) TESTS="fails" kyua --config=none test --store=bootstrap.db +) >>"$at_stdout" 2>>"$at_stderr" 5>&- +at_status=$? at_failed=false +$at_check_filter +at_fn_diff_devnull "$at_stderr" || at_failed=: +echo stdout:; tee stdout <"$at_stdout" +at_fn_check_status 1 $at_status "$at_srcdir/testsuite.at:119" +$at_failed && at_fn_log_failure +$at_traceon; } + +{ set +x +$as_echo "$at_srcdir/testsuite.at:120: grep \"atf_helpers:fails.*failed.*Failed on purpose\" stdout" +at_fn_check_prepare_trace "testsuite.at:120" +( $at_check_trace; grep "atf_helpers:fails.*failed.*Failed on purpose" stdout +) >>"$at_stdout" 2>>"$at_stderr" 5>&- +at_status=$? at_failed=false +$at_check_filter +at_fn_diff_devnull "$at_stderr" || at_failed=: +echo stdout:; cat "$at_stdout" +at_fn_check_status 0 $at_status "$at_srcdir/testsuite.at:120" +$at_failed && at_fn_log_failure +$at_traceon; } + +{ set +x +$as_echo "$at_srcdir/testsuite.at:122: grep \"atf_helpers:passes\" stdout" +at_fn_check_prepare_trace "testsuite.at:122" +( $at_check_trace; grep "atf_helpers:passes" stdout +) >>"$at_stdout" 2>>"$at_stderr" 5>&- +at_status=$? at_failed=false +$at_check_filter +at_fn_diff_devnull "$at_stderr" || at_failed=: +at_fn_diff_devnull "$at_stdout" || at_failed=: +at_fn_check_status 1 $at_status "$at_srcdir/testsuite.at:122" +$at_failed && at_fn_log_failure +$at_traceon; } + +{ set +x +$as_echo "$at_srcdir/testsuite.at:123: grep \"atf_helpers:skips\" stdout" +at_fn_check_prepare_trace "testsuite.at:123" +( $at_check_trace; grep "atf_helpers:skips" stdout +) >>"$at_stdout" 2>>"$at_stderr" 5>&- +at_status=$? at_failed=false +$at_check_filter +at_fn_diff_devnull "$at_stderr" || at_failed=: +at_fn_diff_devnull "$at_stdout" || at_failed=: +at_fn_check_status 1 $at_status "$at_srcdir/testsuite.at:123" +$at_failed && at_fn_log_failure +$at_traceon; } + + + set +x + $at_times_p && times >"$at_times_file" +) 5>&1 2>&1 7>&- | eval $at_tee_pipe +read at_status <"$at_status_file" +#AT_STOP_5 +#AT_START_6 +at_fn_group_banner 6 'testsuite.at:128' \ + "run test case that skips" " " +at_xfail=no +( + $as_echo "6. $at_setup_line: testing $at_desc ..." + $at_traceon + + + + + cat >Kyuafile <<'_ATEOF' + +syntax(2) +test_suite("bootstrap") +atf_test_program{name="atf_helpers"} +_ATEOF + + ln -s $({ + old=$(pwd) + cd "${at_suite_dir}" + # We need to locate a build product, not a source file, because the + # test suite may be run outside of the source tree (think distcheck). + while test $(pwd) != '/' -a ! -e engine/test_case_test; do + cd .. + done + topdir=$(pwd) + cd ${old} + echo ${topdir} +})/bootstrap/atf_helpers atf_helpers + +{ set +x +$as_echo "$at_srcdir/testsuite.at:132: HOME=\$(pwd) TESTS=\"skips\" kyua --config=none test --store=bootstrap.db " +at_fn_check_prepare_notrace 'a $(...) command substitution' "testsuite.at:132" +( $at_check_trace; HOME=$(pwd) TESTS="skips" kyua --config=none test --store=bootstrap.db +) >>"$at_stdout" 2>>"$at_stderr" 5>&- +at_status=$? at_failed=false +$at_check_filter +at_fn_diff_devnull "$at_stderr" || at_failed=: +echo stdout:; tee stdout <"$at_stdout" +at_fn_check_status 0 $at_status "$at_srcdir/testsuite.at:132" +$at_failed && at_fn_log_failure +$at_traceon; } + +{ set +x +$as_echo "$at_srcdir/testsuite.at:133: grep \"atf_helpers:fails\" stdout" +at_fn_check_prepare_trace "testsuite.at:133" +( $at_check_trace; grep "atf_helpers:fails" stdout +) >>"$at_stdout" 2>>"$at_stderr" 5>&- +at_status=$? at_failed=false +$at_check_filter +at_fn_diff_devnull "$at_stderr" || at_failed=: +at_fn_diff_devnull "$at_stdout" || at_failed=: +at_fn_check_status 1 $at_status "$at_srcdir/testsuite.at:133" +$at_failed && at_fn_log_failure +$at_traceon; } + +{ set +x +$as_echo "$at_srcdir/testsuite.at:134: grep \"atf_helpers:passes\" stdout" +at_fn_check_prepare_trace "testsuite.at:134" +( $at_check_trace; grep "atf_helpers:passes" stdout +) >>"$at_stdout" 2>>"$at_stderr" 5>&- +at_status=$? at_failed=false +$at_check_filter +at_fn_diff_devnull "$at_stderr" || at_failed=: +at_fn_diff_devnull "$at_stdout" || at_failed=: +at_fn_check_status 1 $at_status "$at_srcdir/testsuite.at:134" +$at_failed && at_fn_log_failure +$at_traceon; } + +{ set +x +$as_echo "$at_srcdir/testsuite.at:135: grep \"atf_helpers:skips.*skipped.*Skipped on purpose\" stdout" +at_fn_check_prepare_trace "testsuite.at:135" +( $at_check_trace; grep "atf_helpers:skips.*skipped.*Skipped on purpose" stdout +) >>"$at_stdout" 2>>"$at_stderr" 5>&- +at_status=$? at_failed=false +$at_check_filter +at_fn_diff_devnull "$at_stderr" || at_failed=: +echo stdout:; cat "$at_stdout" +at_fn_check_status 0 $at_status "$at_srcdir/testsuite.at:135" +$at_failed && at_fn_log_failure +$at_traceon; } + + + set +x + $at_times_p && times >"$at_times_file" +) 5>&1 2>&1 7>&- | eval $at_tee_pipe +read at_status <"$at_status_file" +#AT_STOP_6 +#AT_START_7 +at_fn_group_banner 7 'testsuite.at:141' \ + "run two test cases, success" " " +at_xfail=no +( + $as_echo "7. $at_setup_line: testing $at_desc ..." + $at_traceon + + + + + cat >Kyuafile <<'_ATEOF' + +syntax(2) +test_suite("bootstrap") +atf_test_program{name="atf_helpers"} +_ATEOF + + ln -s $({ + old=$(pwd) + cd "${at_suite_dir}" + # We need to locate a build product, not a source file, because the + # test suite may be run outside of the source tree (think distcheck). + while test $(pwd) != '/' -a ! -e engine/test_case_test; do + cd .. + done + topdir=$(pwd) + cd ${old} + echo ${topdir} +})/bootstrap/atf_helpers atf_helpers + +{ set +x +$as_echo "$at_srcdir/testsuite.at:145: HOME=\$(pwd) TESTS=\"passes skips\" kyua --config=none test --store=bootstrap.db " +at_fn_check_prepare_notrace 'a $(...) command substitution' "testsuite.at:145" +( $at_check_trace; HOME=$(pwd) TESTS="passes skips" kyua --config=none test --store=bootstrap.db +) >>"$at_stdout" 2>>"$at_stderr" 5>&- +at_status=$? at_failed=false +$at_check_filter +at_fn_diff_devnull "$at_stderr" || at_failed=: +echo stdout:; tee stdout <"$at_stdout" +at_fn_check_status 0 $at_status "$at_srcdir/testsuite.at:145" +$at_failed && at_fn_log_failure +$at_traceon; } + +{ set +x +$as_echo "$at_srcdir/testsuite.at:146: grep \"atf_helpers:fails\" stdout" +at_fn_check_prepare_trace "testsuite.at:146" +( $at_check_trace; grep "atf_helpers:fails" stdout +) >>"$at_stdout" 2>>"$at_stderr" 5>&- +at_status=$? at_failed=false +$at_check_filter +at_fn_diff_devnull "$at_stderr" || at_failed=: +at_fn_diff_devnull "$at_stdout" || at_failed=: +at_fn_check_status 1 $at_status "$at_srcdir/testsuite.at:146" +$at_failed && at_fn_log_failure +$at_traceon; } + +{ set +x +$as_echo "$at_srcdir/testsuite.at:147: grep \"atf_helpers:passes.*passed\" stdout" +at_fn_check_prepare_trace "testsuite.at:147" +( $at_check_trace; grep "atf_helpers:passes.*passed" stdout +) >>"$at_stdout" 2>>"$at_stderr" 5>&- +at_status=$? at_failed=false +$at_check_filter +at_fn_diff_devnull "$at_stderr" || at_failed=: +echo stdout:; cat "$at_stdout" +at_fn_check_status 0 $at_status "$at_srcdir/testsuite.at:147" +$at_failed && at_fn_log_failure +$at_traceon; } + +{ set +x +$as_echo "$at_srcdir/testsuite.at:148: grep \"atf_helpers:skips.*skipped.*Skipped on purpose\" stdout" +at_fn_check_prepare_trace "testsuite.at:148" +( $at_check_trace; grep "atf_helpers:skips.*skipped.*Skipped on purpose" stdout +) >>"$at_stdout" 2>>"$at_stderr" 5>&- +at_status=$? at_failed=false +$at_check_filter +at_fn_diff_devnull "$at_stderr" || at_failed=: +echo stdout:; cat "$at_stdout" +at_fn_check_status 0 $at_status "$at_srcdir/testsuite.at:148" +$at_failed && at_fn_log_failure +$at_traceon; } + + + set +x + $at_times_p && times >"$at_times_file" +) 5>&1 2>&1 7>&- | eval $at_tee_pipe +read at_status <"$at_status_file" +#AT_STOP_7 +#AT_START_8 +at_fn_group_banner 8 'testsuite.at:154' \ + "run two test cases, failure" " " +at_xfail=no +( + $as_echo "8. $at_setup_line: testing $at_desc ..." + $at_traceon + + + + + cat >Kyuafile <<'_ATEOF' + +syntax(2) +test_suite("bootstrap") +atf_test_program{name="atf_helpers"} +_ATEOF + + ln -s $({ + old=$(pwd) + cd "${at_suite_dir}" + # We need to locate a build product, not a source file, because the + # test suite may be run outside of the source tree (think distcheck). + while test $(pwd) != '/' -a ! -e engine/test_case_test; do + cd .. + done + topdir=$(pwd) + cd ${old} + echo ${topdir} +})/bootstrap/atf_helpers atf_helpers + +{ set +x +$as_echo "$at_srcdir/testsuite.at:158: HOME=\$(pwd) TESTS=\"fails passes\" kyua --config=none test --store=bootstrap.db " +at_fn_check_prepare_notrace 'a $(...) command substitution' "testsuite.at:158" +( $at_check_trace; HOME=$(pwd) TESTS="fails passes" kyua --config=none test --store=bootstrap.db +) >>"$at_stdout" 2>>"$at_stderr" 5>&- +at_status=$? at_failed=false +$at_check_filter +at_fn_diff_devnull "$at_stderr" || at_failed=: +echo stdout:; tee stdout <"$at_stdout" +at_fn_check_status 1 $at_status "$at_srcdir/testsuite.at:158" +$at_failed && at_fn_log_failure +$at_traceon; } + +{ set +x +$as_echo "$at_srcdir/testsuite.at:159: grep \"atf_helpers:fails.*failure.*Failed on purpose\" stdout" +at_fn_check_prepare_trace "testsuite.at:159" +( $at_check_trace; grep "atf_helpers:fails.*failure.*Failed on purpose" stdout +) >>"$at_stdout" 2>>"$at_stderr" 5>&- +at_status=$? at_failed=false +$at_check_filter +at_fn_diff_devnull "$at_stderr" || at_failed=: +at_fn_diff_devnull "$at_stdout" || at_failed=: +at_fn_check_status 1 $at_status "$at_srcdir/testsuite.at:159" +$at_failed && at_fn_log_failure +$at_traceon; } + +{ set +x +$as_echo "$at_srcdir/testsuite.at:161: grep \"atf_helpers:passes.*passed\" stdout" +at_fn_check_prepare_trace "testsuite.at:161" +( $at_check_trace; grep "atf_helpers:passes.*passed" stdout +) >>"$at_stdout" 2>>"$at_stderr" 5>&- +at_status=$? at_failed=false +$at_check_filter +at_fn_diff_devnull "$at_stderr" || at_failed=: +echo stdout:; cat "$at_stdout" +at_fn_check_status 0 $at_status "$at_srcdir/testsuite.at:161" +$at_failed && at_fn_log_failure +$at_traceon; } + +{ set +x +$as_echo "$at_srcdir/testsuite.at:162: grep \"atf_helpers:skips\" stdout" +at_fn_check_prepare_trace "testsuite.at:162" +( $at_check_trace; grep "atf_helpers:skips" stdout +) >>"$at_stdout" 2>>"$at_stderr" 5>&- +at_status=$? at_failed=false +$at_check_filter +at_fn_diff_devnull "$at_stderr" || at_failed=: +at_fn_diff_devnull "$at_stdout" || at_failed=: +at_fn_check_status 1 $at_status "$at_srcdir/testsuite.at:162" +$at_failed && at_fn_log_failure +$at_traceon; } + + + set +x + $at_times_p && times >"$at_times_file" +) 5>&1 2>&1 7>&- | eval $at_tee_pipe +read at_status <"$at_status_file" +#AT_STOP_8 +#AT_START_9 +at_fn_group_banner 9 'testsuite.at:167' \ + "run mixed test cases" " " +at_xfail=no +( + $as_echo "9. $at_setup_line: testing $at_desc ..." + $at_traceon + + + + + cat >Kyuafile <<'_ATEOF' + +syntax(2) +test_suite("bootstrap") +atf_test_program{name="atf_helpers"} +_ATEOF + + ln -s $({ + old=$(pwd) + cd "${at_suite_dir}" + # We need to locate a build product, not a source file, because the + # test suite may be run outside of the source tree (think distcheck). + while test $(pwd) != '/' -a ! -e engine/test_case_test; do + cd .. + done + topdir=$(pwd) + cd ${old} + echo ${topdir} +})/bootstrap/atf_helpers atf_helpers + +{ set +x +$as_echo "$at_srcdir/testsuite.at:171: HOME=\$(pwd) TESTS=\"fails passes skips\" kyua --config=none test --store=bootstrap.db " +at_fn_check_prepare_notrace 'a $(...) command substitution' "testsuite.at:171" +( $at_check_trace; HOME=$(pwd) TESTS="fails passes skips" kyua --config=none test --store=bootstrap.db +) >>"$at_stdout" 2>>"$at_stderr" 5>&- +at_status=$? at_failed=false +$at_check_filter +at_fn_diff_devnull "$at_stderr" || at_failed=: +echo stdout:; tee stdout <"$at_stdout" +at_fn_check_status 1 $at_status "$at_srcdir/testsuite.at:171" +$at_failed && at_fn_log_failure +$at_traceon; } + +{ set +x +$as_echo "$at_srcdir/testsuite.at:172: grep \"atf_helpers:fails.*failure.*Failed on purpose\" stdout" +at_fn_check_prepare_trace "testsuite.at:172" +( $at_check_trace; grep "atf_helpers:fails.*failure.*Failed on purpose" stdout +) >>"$at_stdout" 2>>"$at_stderr" 5>&- +at_status=$? at_failed=false +$at_check_filter +at_fn_diff_devnull "$at_stderr" || at_failed=: +at_fn_diff_devnull "$at_stdout" || at_failed=: +at_fn_check_status 1 $at_status "$at_srcdir/testsuite.at:172" +$at_failed && at_fn_log_failure +$at_traceon; } + +{ set +x +$as_echo "$at_srcdir/testsuite.at:174: grep \"atf_helpers:passes.*passed\" stdout" +at_fn_check_prepare_trace "testsuite.at:174" +( $at_check_trace; grep "atf_helpers:passes.*passed" stdout +) >>"$at_stdout" 2>>"$at_stderr" 5>&- +at_status=$? at_failed=false +$at_check_filter +at_fn_diff_devnull "$at_stderr" || at_failed=: +echo stdout:; cat "$at_stdout" +at_fn_check_status 0 $at_status "$at_srcdir/testsuite.at:174" +$at_failed && at_fn_log_failure +$at_traceon; } + +{ set +x +$as_echo "$at_srcdir/testsuite.at:175: grep \"atf_helpers:skips.*skipped.*Skipped on purpose\" stdout" +at_fn_check_prepare_trace "testsuite.at:175" +( $at_check_trace; grep "atf_helpers:skips.*skipped.*Skipped on purpose" stdout +) >>"$at_stdout" 2>>"$at_stderr" 5>&- +at_status=$? at_failed=false +$at_check_filter +at_fn_diff_devnull "$at_stderr" || at_failed=: +echo stdout:; cat "$at_stdout" +at_fn_check_status 0 $at_status "$at_srcdir/testsuite.at:175" +$at_failed && at_fn_log_failure +$at_traceon; } + + + set +x + $at_times_p && times >"$at_times_file" +) 5>&1 2>&1 7>&- | eval $at_tee_pipe +read at_status <"$at_status_file" +#AT_STOP_9 +#AT_START_10 +at_fn_group_banner 10 'testsuite.at:181' \ + "run tests from build directories" " " +at_xfail=no +( + $as_echo "10. $at_setup_line: testing $at_desc ..." + $at_traceon + + + + + cat >Kyuafile <<'_ATEOF' + +syntax(2) +test_suite("bootstrap") +atf_test_program{name="atf_helpers"} +_ATEOF + + ln -s $({ + old=$(pwd) + cd "${at_suite_dir}" + # We need to locate a build product, not a source file, because the + # test suite may be run outside of the source tree (think distcheck). + while test $(pwd) != '/' -a ! -e engine/test_case_test; do + cd .. + done + topdir=$(pwd) + cd ${old} + echo ${topdir} +})/bootstrap/atf_helpers atf_helpers + +{ set +x +$as_echo "$at_srcdir/testsuite.at:185: mkdir src" +at_fn_check_prepare_trace "testsuite.at:185" +( $at_check_trace; mkdir src +) >>"$at_stdout" 2>>"$at_stderr" 5>&- +at_status=$? at_failed=false +$at_check_filter +at_fn_diff_devnull "$at_stderr" || at_failed=: +at_fn_diff_devnull "$at_stdout" || at_failed=: +at_fn_check_status 0 $at_status "$at_srcdir/testsuite.at:185" +$at_failed && at_fn_log_failure +$at_traceon; } + +{ set +x +$as_echo "$at_srcdir/testsuite.at:186: mv Kyuafile src" +at_fn_check_prepare_trace "testsuite.at:186" +( $at_check_trace; mv Kyuafile src +) >>"$at_stdout" 2>>"$at_stderr" 5>&- +at_status=$? at_failed=false +$at_check_filter +at_fn_diff_devnull "$at_stderr" || at_failed=: +at_fn_diff_devnull "$at_stdout" || at_failed=: +at_fn_check_status 0 $at_status "$at_srcdir/testsuite.at:186" +$at_failed && at_fn_log_failure +$at_traceon; } + +{ set +x +$as_echo "$at_srcdir/testsuite.at:187: mkdir obj" +at_fn_check_prepare_trace "testsuite.at:187" +( $at_check_trace; mkdir obj +) >>"$at_stdout" 2>>"$at_stderr" 5>&- +at_status=$? at_failed=false +$at_check_filter +at_fn_diff_devnull "$at_stderr" || at_failed=: +at_fn_diff_devnull "$at_stdout" || at_failed=: +at_fn_check_status 0 $at_status "$at_srcdir/testsuite.at:187" +$at_failed && at_fn_log_failure +$at_traceon; } + +{ set +x +$as_echo "$at_srcdir/testsuite.at:188: mv atf_helpers obj" +at_fn_check_prepare_trace "testsuite.at:188" +( $at_check_trace; mv atf_helpers obj +) >>"$at_stdout" 2>>"$at_stderr" 5>&- +at_status=$? at_failed=false +$at_check_filter +at_fn_diff_devnull "$at_stderr" || at_failed=: +at_fn_diff_devnull "$at_stdout" || at_failed=: +at_fn_check_status 0 $at_status "$at_srcdir/testsuite.at:188" +$at_failed && at_fn_log_failure +$at_traceon; } + +{ set +x +$as_echo "$at_srcdir/testsuite.at:189: HOME=\$(pwd) TESTS=\"fails passes skips\" kyua --config=none test --store=bootstrap.db --kyuafile=src/Kyuafile --build-root=obj" +at_fn_check_prepare_notrace 'a $(...) command substitution' "testsuite.at:189" +( $at_check_trace; HOME=$(pwd) TESTS="fails passes skips" kyua --config=none test --store=bootstrap.db --kyuafile=src/Kyuafile --build-root=obj +) >>"$at_stdout" 2>>"$at_stderr" 5>&- +at_status=$? at_failed=false +$at_check_filter +at_fn_diff_devnull "$at_stderr" || at_failed=: +echo stdout:; tee stdout <"$at_stdout" +at_fn_check_status 1 $at_status "$at_srcdir/testsuite.at:189" +$at_failed && at_fn_log_failure +$at_traceon; } + +{ set +x +$as_echo "$at_srcdir/testsuite.at:192: grep \"atf_helpers:fails.*failure.*Failed on purpose\" stdout" +at_fn_check_prepare_trace "testsuite.at:192" +( $at_check_trace; grep "atf_helpers:fails.*failure.*Failed on purpose" stdout +) >>"$at_stdout" 2>>"$at_stderr" 5>&- +at_status=$? at_failed=false +$at_check_filter +at_fn_diff_devnull "$at_stderr" || at_failed=: +at_fn_diff_devnull "$at_stdout" || at_failed=: +at_fn_check_status 1 $at_status "$at_srcdir/testsuite.at:192" +$at_failed && at_fn_log_failure +$at_traceon; } + +{ set +x +$as_echo "$at_srcdir/testsuite.at:194: grep \"atf_helpers:passes.*passed\" stdout" +at_fn_check_prepare_trace "testsuite.at:194" +( $at_check_trace; grep "atf_helpers:passes.*passed" stdout +) >>"$at_stdout" 2>>"$at_stderr" 5>&- +at_status=$? at_failed=false +$at_check_filter +at_fn_diff_devnull "$at_stderr" || at_failed=: +echo stdout:; cat "$at_stdout" +at_fn_check_status 0 $at_status "$at_srcdir/testsuite.at:194" +$at_failed && at_fn_log_failure +$at_traceon; } + +{ set +x +$as_echo "$at_srcdir/testsuite.at:195: grep \"atf_helpers:skips.*skipped.*Skipped on purpose\" stdout" +at_fn_check_prepare_trace "testsuite.at:195" +( $at_check_trace; grep "atf_helpers:skips.*skipped.*Skipped on purpose" stdout +) >>"$at_stdout" 2>>"$at_stderr" 5>&- +at_status=$? at_failed=false +$at_check_filter +at_fn_diff_devnull "$at_stderr" || at_failed=: +echo stdout:; cat "$at_stdout" +at_fn_check_status 0 $at_status "$at_srcdir/testsuite.at:195" +$at_failed && at_fn_log_failure +$at_traceon; } + + + set +x + $at_times_p && times >"$at_times_file" +) 5>&1 2>&1 7>&- | eval $at_tee_pipe +read at_status <"$at_status_file" +#AT_STOP_10 diff --git a/external/bsd/kyua-cli/dist/bootstrap/testsuite.at b/external/bsd/kyua-cli/dist/bootstrap/testsuite.at new file mode 100644 index 000000000..148dededd --- /dev/null +++ b/external/bsd/kyua-cli/dist/bootstrap/testsuite.at @@ -0,0 +1,198 @@ +dnl Copyright 2010 Google Inc. +dnl All rights reserved. +dnl +dnl Redistribution and use in source and binary forms, with or without +dnl modification, are permitted provided that the following conditions are +dnl met: +dnl +dnl * Redistributions of source code must retain the above copyright +dnl notice, this list of conditions and the following disclaimer. +dnl * Redistributions in binary form must reproduce the above copyright +dnl notice, this list of conditions and the following disclaimer in the +dnl documentation and/or other materials provided with the distribution. +dnl * Neither the name of Google Inc. nor the names of its contributors +dnl may be used to endorse or promote products derived from this software +dnl without specific prior written permission. +dnl +dnl THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +dnl "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +dnl LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +dnl A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +dnl OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +dnl SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +dnl LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +dnl DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +dnl THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +dnl (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +dnl OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +AT_INIT([bootstrapping tests]) + + +m4_define([GUESS_TOPDIR], { + old=$(pwd) + cd "${at_suite_dir}" + # We need to locate a build product, not a source file, because the + # test suite may be run outside of the source tree (think distcheck). + while test $(pwd) != '/' -a ! -e engine/test_case_test; do + cd .. + done + topdir=$(pwd) + cd ${old} + echo ${topdir} +}) + + +m4_define([CREATE_ATF_HELPERS], [ + AT_DATA([Kyuafile], [ +syntax(2) +test_suite("bootstrap") +atf_test_program{name="atf_helpers"} +]) + ln -s $(GUESS_TOPDIR)/bootstrap/atf_helpers atf_helpers +]) +m4_define([RUN_ATF_HELPERS], + [HOME=$(pwd) TESTS="$1" kyua --config=none test --store=bootstrap.db $2]) + + +m4_define([CREATE_PLAIN_HELPERS], [ + AT_DATA([Kyuafile], [ +syntax(2) +test_suite("bootstrap") +atf_test_program{name="plain_helpers"} +]) + ln -s $(GUESS_TOPDIR)/bootstrap/plain_helpers plain_helpers +]) +m4_define([RUN_PLAIN_HELPER], + [HOME=$(pwd) HELPER="$1" kyua --config=none test --store=bootstrap.db]) + + +AT_SETUP([test program crashes in test list]) +AT_TESTED([kyua]) + +CREATE_PLAIN_HELPERS +AT_CHECK([RUN_PLAIN_HELPER([abort_test_cases_list])], [1], [stdout], []) +re='plain_helpers:__test_cases_list__.*broken.*Test program list did not return success' +AT_CHECK([grep "${re}" stdout], [0], [ignore], []) + +AT_CLEANUP + + +AT_SETUP([test program prints an empty test list]) +AT_TESTED([kyua]) + +CREATE_PLAIN_HELPERS +AT_CHECK([RUN_PLAIN_HELPER([empty_test_cases_list])], [1], [stdout], []) +re='plain_helpers:__test_cases_list__.*broken.*failed to read.*unexpected EOF' +AT_CHECK([grep "${re}" stdout], [0], [ignore], []) + +AT_CLEANUP + + +AT_SETUP([test program with zero test cases]) +AT_TESTED([kyua]) + +CREATE_PLAIN_HELPERS +AT_CHECK([RUN_PLAIN_HELPER([zero_test_cases])], [1], [stdout], []) +re='plain_helpers:__test_cases_list__.*broken.*Empty test cases list' +AT_CHECK([grep "${re}" stdout], [0], [ignore], []) + +AT_CLEANUP + + +AT_SETUP([run test case that passes]) +AT_TESTED([kyua]) + +CREATE_ATF_HELPERS +AT_CHECK([RUN_ATF_HELPERS([passes])], [0], [stdout], []) +AT_CHECK([grep "atf_helpers:fails" stdout], [1], [], []) +AT_CHECK([grep "atf_helpers:passes.*passed" stdout], [0], [ignore], []) +AT_CHECK([grep "atf_helpers:skips" stdout], [1], [], []) + +AT_CLEANUP + + +AT_SETUP([run test case that fails]) +AT_TESTED([kyua]) + +CREATE_ATF_HELPERS +AT_CHECK([RUN_ATF_HELPERS([fails])], [1], [stdout], []) +AT_CHECK([grep "atf_helpers:fails.*failed.*Failed on purpose" stdout], + [0], [ignore], []) +AT_CHECK([grep "atf_helpers:passes" stdout], [1], [], []) +AT_CHECK([grep "atf_helpers:skips" stdout], [1], [], []) + +AT_CLEANUP + + +AT_SETUP([run test case that skips]) +AT_TESTED([kyua]) + +CREATE_ATF_HELPERS +AT_CHECK([RUN_ATF_HELPERS([skips])], [0], [stdout], []) +AT_CHECK([grep "atf_helpers:fails" stdout], [1], [], []) +AT_CHECK([grep "atf_helpers:passes" stdout], [1], [], []) +AT_CHECK([grep "atf_helpers:skips.*skipped.*Skipped on purpose" stdout], + [0], [ignore], []) + +AT_CLEANUP + + +AT_SETUP([run two test cases, success]) +AT_TESTED([kyua]) + +CREATE_ATF_HELPERS +AT_CHECK([RUN_ATF_HELPERS([passes skips])], [0], [stdout], []) +AT_CHECK([grep "atf_helpers:fails" stdout], [1], [], []) +AT_CHECK([grep "atf_helpers:passes.*passed" stdout], [0], [ignore], []) +AT_CHECK([grep "atf_helpers:skips.*skipped.*Skipped on purpose" stdout], + [0], [ignore], []) + +AT_CLEANUP + + +AT_SETUP([run two test cases, failure]) +AT_TESTED([kyua]) + +CREATE_ATF_HELPERS +AT_CHECK([RUN_ATF_HELPERS([fails passes])], [1], [stdout], []) +AT_CHECK([grep "atf_helpers:fails.*failure.*Failed on purpose" stdout], + [1], [], []) +AT_CHECK([grep "atf_helpers:passes.*passed" stdout], [0], [ignore], []) +AT_CHECK([grep "atf_helpers:skips" stdout], [1], [], []) + +AT_CLEANUP + + +AT_SETUP([run mixed test cases]) +AT_TESTED([kyua]) + +CREATE_ATF_HELPERS +AT_CHECK([RUN_ATF_HELPERS([fails passes skips])], [1], [stdout], []) +AT_CHECK([grep "atf_helpers:fails.*failure.*Failed on purpose" stdout], + [1], [], []) +AT_CHECK([grep "atf_helpers:passes.*passed" stdout], [0], [ignore], []) +AT_CHECK([grep "atf_helpers:skips.*skipped.*Skipped on purpose" stdout], + [0], [ignore], []) + +AT_CLEANUP + + +AT_SETUP([run tests from build directories]) +AT_TESTED([kyua]) + +CREATE_ATF_HELPERS +AT_CHECK([mkdir src], [0], [], []) +AT_CHECK([mv Kyuafile src], [0], [], []) +AT_CHECK([mkdir obj], [0], [], []) +AT_CHECK([mv atf_helpers obj], [0], [], []) +AT_CHECK([RUN_ATF_HELPERS([fails passes skips], + [--kyuafile=src/Kyuafile --build-root=obj])], + [1], [stdout], []) +AT_CHECK([grep "atf_helpers:fails.*failure.*Failed on purpose" stdout], + [1], [], []) +AT_CHECK([grep "atf_helpers:passes.*passed" stdout], [0], [ignore], []) +AT_CHECK([grep "atf_helpers:skips.*skipped.*Skipped on purpose" stdout], + [0], [ignore], []) + +AT_CLEANUP diff --git a/external/bsd/kyua-cli/dist/cli/Kyuafile b/external/bsd/kyua-cli/dist/cli/Kyuafile new file mode 100644 index 000000000..14a7a87e1 --- /dev/null +++ b/external/bsd/kyua-cli/dist/cli/Kyuafile @@ -0,0 +1,17 @@ +syntax(2) + +test_suite("kyua") + +atf_test_program{name="cmd_about_test"} +atf_test_program{name="cmd_config_test"} +atf_test_program{name="cmd_db_exec_test"} +atf_test_program{name="cmd_db_migrate_test"} +atf_test_program{name="cmd_debug_test"} +atf_test_program{name="cmd_help_test"} +atf_test_program{name="cmd_list_test"} +atf_test_program{name="cmd_report_html_test"} +atf_test_program{name="cmd_report_test"} +atf_test_program{name="cmd_test_test"} +atf_test_program{name="common_test"} +atf_test_program{name="config_test"} +atf_test_program{name="main_test"} diff --git a/external/bsd/kyua-cli/dist/cli/cmd_about.cpp b/external/bsd/kyua-cli/dist/cli/cmd_about.cpp new file mode 100644 index 000000000..6302c85ad --- /dev/null +++ b/external/bsd/kyua-cli/dist/cli/cmd_about.cpp @@ -0,0 +1,141 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "cli/cmd_about.hpp" + +#include +#include +#include +#include + +#include "cli/common.ipp" +#include "utils/cmdline/exceptions.hpp" +#include "utils/cmdline/parser.ipp" +#include "utils/cmdline/ui.hpp" +#include "utils/defs.hpp" +#include "utils/env.hpp" +#include "utils/format/macros.hpp" +#include "utils/fs/path.hpp" +#include "utils/sanity.hpp" + +#if defined(HAVE_CONFIG_H) +# include "config.h" +#endif + +namespace cmdline = utils::cmdline; +namespace config = utils::config; +namespace fs = utils::fs; + +using cli::cmd_about; + + +namespace { + + +/// Print the contents of a document. +/// +/// If the file cannot be opened for whatever reason, an error message is +/// printed to the output of the program instead of the contents of the file. +/// +/// \param ui Object to interact with the I/O of the program. +/// \param file The file to print. +/// +/// \return True if the file was printed, false otherwise. +static bool +cat_file(cmdline::ui* ui, const fs::path& file) +{ + std::ifstream input(file.c_str()); + if (!input) { + ui->err(F("Failed to open %s") % file); + return false; + } + + std::string line; + while (std::getline(input, line).good()) + ui->out(line); + input.close(); + return true; +} + + +} // anonymous namespace + + +/// Default constructor for cmd_about. +cmd_about::cmd_about(void) : cli_command( + "about", "[authors|license|version]", 0, 1, + "Shows general program information") +{ +} + + +/// Entry point for the "about" subcommand. +/// +/// \param ui Object to interact with the I/O of the program. +/// \param cmdline Representation of the command line to the subcommand. +/// \param unused_user_config The runtime configuration of the program. +/// +/// \return 0 if everything is OK, 1 if any of the necessary documents cannot be +/// opened. +int +cmd_about::run(cmdline::ui* ui, const cmdline::parsed_cmdline& cmdline, + const config::tree& UTILS_UNUSED_PARAM(user_config)) +{ + const fs::path docdir(utils::getenv_with_default( + "KYUA_DOCDIR", KYUA_DOCDIR)); + + bool success = true; + + if (cmdline.arguments().empty()) { + ui->out(PACKAGE " (" PACKAGE_NAME ") " PACKAGE_VERSION); + ui->out(""); + ui->out("License terms:"); + ui->out(""); + success &= cat_file(ui, docdir / "COPYING"); + ui->out(""); + ui->out("Brought to you by:"); + ui->out(""); + success &= cat_file(ui, docdir / "AUTHORS"); + ui->out(""); + ui->out(F("Homepage: %s") % PACKAGE_URL); + } else { + const std::string& topic = cmdline.arguments()[0]; + + if (topic == "authors") { + success &= cat_file(ui, docdir / "AUTHORS"); + } else if (topic == "license") { + success &= cat_file(ui, docdir / "COPYING"); + } else if (topic == "version") { + ui->out(PACKAGE " (" PACKAGE_NAME ") " PACKAGE_VERSION); + } else { + throw cmdline::usage_error(F("Invalid about topic '%s'") % topic); + } + } + + return success ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/external/bsd/kyua-cli/dist/cli/cmd_about.hpp b/external/bsd/kyua-cli/dist/cli/cmd_about.hpp new file mode 100644 index 000000000..eb9eb1d1e --- /dev/null +++ b/external/bsd/kyua-cli/dist/cli/cmd_about.hpp @@ -0,0 +1,57 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file cli/cmd_about.hpp +/// Provides the cmd_about class. + +#if !defined(CLI_CMD_ABOUT_HPP) +#define CLI_CMD_ABOUT_HPP + +#include "cli/common.hpp" + +namespace cli { + + +/// Implementation of the "about" subcommand. +class cmd_about : public cli_command +{ + /// Path to the directory containing the distribution documents. + const std::string _docdir; + +public: + cmd_about(void); + + int run(utils::cmdline::ui*, const utils::cmdline::parsed_cmdline&, + const utils::config::tree&); +}; + + +} // namespace cli + + +#endif // !defined(CLI_CMD_ABOUT_HPP) diff --git a/external/bsd/kyua-cli/dist/cli/cmd_about_test.cpp b/external/bsd/kyua-cli/dist/cli/cmd_about_test.cpp new file mode 100644 index 000000000..9a11365ab --- /dev/null +++ b/external/bsd/kyua-cli/dist/cli/cmd_about_test.cpp @@ -0,0 +1,252 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "cli/cmd_about.hpp" + +#if defined(HAVE_CONFIG_H) +# include "config.h" +#endif + +#include + +#include + +#include "cli/common.ipp" +#include "engine/config.hpp" +#include "utils/cmdline/exceptions.hpp" +#include "utils/cmdline/parser.hpp" +#include "utils/cmdline/ui_mock.hpp" +#include "utils/env.hpp" +#include "utils/fs/operations.hpp" +#include "utils/fs/path.hpp" + +namespace cmdline = utils::cmdline; +namespace fs = utils::fs; + +using cli::cmd_about; + + +ATF_TEST_CASE_WITHOUT_HEAD(all_topics__ok); +ATF_TEST_CASE_BODY(all_topics__ok) +{ + cmdline::args_vector args; + args.push_back("about"); + + fs::mkdir(fs::path("fake-docs"), 0755); + atf::utils::create_file("fake-docs/AUTHORS", "Content of AUTHORS\n"); + atf::utils::create_file("fake-docs/COPYING", "Content of COPYING\n"); + + utils::setenv("KYUA_DOCDIR", "fake-docs"); + cmd_about cmd; + cmdline::ui_mock ui; + ATF_REQUIRE_EQ(EXIT_SUCCESS, cmd.main(&ui, args, engine::default_config())); + ATF_REQUIRE(atf::utils::grep_string(PACKAGE_NAME, ui.out_log()[0])); + ATF_REQUIRE(atf::utils::grep_string(PACKAGE_VERSION, ui.out_log()[0])); + ATF_REQUIRE(atf::utils::grep_collection("Content of AUTHORS", + ui.out_log())); + ATF_REQUIRE(atf::utils::grep_collection("Content of COPYING", + ui.out_log())); + ATF_REQUIRE(atf::utils::grep_collection("Homepage", ui.out_log())); + ATF_REQUIRE(ui.err_log().empty()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(all_topics__missing_docs); +ATF_TEST_CASE_BODY(all_topics__missing_docs) +{ + cmdline::args_vector args; + args.push_back("about"); + + utils::setenv("KYUA_DOCDIR", "fake-docs"); + cmd_about cmd; + cmdline::ui_mock ui; + ATF_REQUIRE_EQ(EXIT_FAILURE, cmd.main(&ui, args, engine::default_config())); + + ATF_REQUIRE(atf::utils::grep_string(PACKAGE_NAME, ui.out_log()[0])); + ATF_REQUIRE(atf::utils::grep_string(PACKAGE_VERSION, ui.out_log()[0])); + + ATF_REQUIRE(atf::utils::grep_collection("Homepage", ui.out_log())); + + ATF_REQUIRE(atf::utils::grep_collection("Failed to open.*AUTHORS", + ui.err_log())); + ATF_REQUIRE(atf::utils::grep_collection("Failed to open.*COPYING", + ui.err_log())); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(topic_authors__ok); +ATF_TEST_CASE_BODY(topic_authors__ok) +{ + cmdline::args_vector args; + args.push_back("about"); + args.push_back("authors"); + + fs::mkdir(fs::path("fake-docs"), 0755); + atf::utils::create_file("fake-docs/AUTHORS", "Content of AUTHORS\n"); + + utils::setenv("KYUA_DOCDIR", "fake-docs"); + cmd_about cmd; + cmdline::ui_mock ui; + ATF_REQUIRE_EQ(EXIT_SUCCESS, cmd.main(&ui, args, engine::default_config())); + ATF_REQUIRE(!atf::utils::grep_string(PACKAGE_NAME, ui.out_log()[0])); + ATF_REQUIRE(atf::utils::grep_collection("Content of AUTHORS", + ui.out_log())); + ATF_REQUIRE(!atf::utils::grep_collection("COPYING", ui.out_log())); + ATF_REQUIRE(!atf::utils::grep_collection("Homepage", ui.out_log())); + ATF_REQUIRE(ui.err_log().empty()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(topic_authors__missing_doc); +ATF_TEST_CASE_BODY(topic_authors__missing_doc) +{ + cmdline::args_vector args; + args.push_back("about"); + args.push_back("authors"); + + utils::setenv("KYUA_DOCDIR", "fake-docs"); + cmd_about cmd; + cmdline::ui_mock ui; + ATF_REQUIRE_EQ(EXIT_FAILURE, cmd.main(&ui, args, engine::default_config())); + + ATF_REQUIRE_EQ(0, ui.out_log().size()); + + ATF_REQUIRE(atf::utils::grep_collection("Failed to open.*AUTHORS", + ui.err_log())); + ATF_REQUIRE(!atf::utils::grep_collection("Failed to open.*COPYING", + ui.err_log())); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(topic_license__ok); +ATF_TEST_CASE_BODY(topic_license__ok) +{ + cmdline::args_vector args; + args.push_back("about"); + args.push_back("license"); + + fs::mkdir(fs::path("fake-docs"), 0755); + atf::utils::create_file("fake-docs/COPYING", "Content of COPYING\n"); + + utils::setenv("KYUA_DOCDIR", "fake-docs"); + cmd_about cmd; + cmdline::ui_mock ui; + ATF_REQUIRE_EQ(EXIT_SUCCESS, cmd.main(&ui, args, engine::default_config())); + ATF_REQUIRE(!atf::utils::grep_string(PACKAGE_NAME, ui.out_log()[0])); + ATF_REQUIRE(!atf::utils::grep_collection("AUTHORS", ui.out_log())); + ATF_REQUIRE(atf::utils::grep_collection("Content of COPYING", + ui.out_log())); + ATF_REQUIRE(!atf::utils::grep_collection("Homepage", ui.out_log())); + ATF_REQUIRE(ui.err_log().empty()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(topic_license__missing_doc); +ATF_TEST_CASE_BODY(topic_license__missing_doc) +{ + cmdline::args_vector args; + args.push_back("about"); + args.push_back("license"); + + utils::setenv("KYUA_DOCDIR", "fake-docs"); + cmd_about cmd; + cmdline::ui_mock ui; + ATF_REQUIRE_EQ(EXIT_FAILURE, cmd.main(&ui, args, engine::default_config())); + + ATF_REQUIRE_EQ(0, ui.out_log().size()); + + ATF_REQUIRE(!atf::utils::grep_collection("Failed to open.*AUTHORS", + ui.err_log())); + ATF_REQUIRE(atf::utils::grep_collection("Failed to open.*COPYING", + ui.err_log())); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(topic_version__ok); +ATF_TEST_CASE_BODY(topic_version__ok) +{ + cmdline::args_vector args; + args.push_back("about"); + args.push_back("version"); + + utils::setenv("KYUA_DOCDIR", "fake-docs"); + cmd_about cmd; + cmdline::ui_mock ui; + ATF_REQUIRE_EQ(EXIT_SUCCESS, cmd.main(&ui, args, engine::default_config())); + ATF_REQUIRE_EQ(1, ui.out_log().size()); + ATF_REQUIRE(atf::utils::grep_string(PACKAGE_NAME, ui.out_log()[0])); + ATF_REQUIRE(atf::utils::grep_string(PACKAGE_VERSION, ui.out_log()[0])); + ATF_REQUIRE(ui.err_log().empty()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(invalid_args); +ATF_TEST_CASE_BODY(invalid_args) +{ + cmdline::args_vector args; + args.push_back("about"); + args.push_back("first"); + args.push_back("second"); + + cmd_about cmd; + cmdline::ui_mock ui; + ATF_REQUIRE_THROW_RE(cmdline::usage_error, "Too many arguments", + cmd.main(&ui, args, engine::default_config())); + ATF_REQUIRE(ui.out_log().empty()); + ATF_REQUIRE(ui.err_log().empty()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(invalid_topic); +ATF_TEST_CASE_BODY(invalid_topic) +{ + cmdline::args_vector args; + args.push_back("about"); + args.push_back("foo"); + + cmd_about cmd; + cmdline::ui_mock ui; + ATF_REQUIRE_THROW_RE(cmdline::usage_error, "Invalid about topic 'foo'", + cmd.main(&ui, args, engine::default_config())); + ATF_REQUIRE(ui.out_log().empty()); + ATF_REQUIRE(ui.err_log().empty()); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, all_topics__ok); + ATF_ADD_TEST_CASE(tcs, all_topics__missing_docs); + ATF_ADD_TEST_CASE(tcs, topic_authors__ok); + ATF_ADD_TEST_CASE(tcs, topic_authors__missing_doc); + ATF_ADD_TEST_CASE(tcs, topic_license__ok); + ATF_ADD_TEST_CASE(tcs, topic_license__missing_doc); + ATF_ADD_TEST_CASE(tcs, topic_version__ok); + ATF_ADD_TEST_CASE(tcs, invalid_args); + ATF_ADD_TEST_CASE(tcs, invalid_topic); +} diff --git a/external/bsd/kyua-cli/dist/cli/cmd_config.cpp b/external/bsd/kyua-cli/dist/cli/cmd_config.cpp new file mode 100644 index 000000000..aac8d748a --- /dev/null +++ b/external/bsd/kyua-cli/dist/cli/cmd_config.cpp @@ -0,0 +1,120 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "cli/cmd_config.hpp" + +#include + +#include "cli/common.ipp" +#include "utils/config/tree.ipp" +#include "utils/format/macros.hpp" + +namespace cmdline = utils::cmdline; +namespace config = utils::config; + +using cli::cmd_config; + + +namespace { + + +/// Prints all configuration variables. +/// +/// \param ui Object to interact with the I/O of the program. +/// \param properties The key/value map representing all the configuration +/// variables. +/// +/// \return 0 for success. +static int +print_all(cmdline::ui* ui, const config::properties_map& properties) +{ + for (config::properties_map::const_iterator iter = properties.begin(); + iter != properties.end(); iter++) + ui->out(F("%s = %s") % (*iter).first % (*iter).second); + return EXIT_SUCCESS; +} + + +/// Prints the configuration variables that the user requests. +/// +/// \param ui Object to interact with the I/O of the program. +/// \param properties The key/value map representing all the configuration +/// variables. +/// \param filters The names of the configuration variables to print. +/// +/// \return 0 if all specified filters are valid; 1 otherwise. +static int +print_some(cmdline::ui* ui, const config::properties_map& properties, + const cmdline::args_vector& filters) +{ + bool ok = true; + + for (cmdline::args_vector::const_iterator iter = filters.begin(); + iter != filters.end(); iter++) { + const config::properties_map::const_iterator match = + properties.find(*iter); + if (match == properties.end()) { + cmdline::print_warning(ui, F("'%s' is not defined") % *iter); + ok = false; + } else + ui->out(F("%s = %s") % (*match).first % (*match).second); + } + + return ok ? EXIT_SUCCESS : EXIT_FAILURE; +} + + +} // anonymous namespace + + +/// Default constructor for cmd_config. +cmd_config::cmd_config(void) : cli_command( + "config", "[variable1 .. variableN]", 0, -1, + "Inspects the values of configuration variables") +{ +} + + +/// Entry point for the "config" subcommand. +/// +/// \param ui Object to interact with the I/O of the program. +/// \param cmdline Representation of the command line to the subcommand. +/// \param user_config The runtime configuration of the program. +/// +/// \return 0 if everything is OK, 1 if any of the necessary documents cannot be +/// opened. +int +cmd_config::run(cmdline::ui* ui, const cmdline::parsed_cmdline& cmdline, + const config::tree& user_config) +{ + const config::properties_map properties = user_config.all_properties(); + if (cmdline.arguments().empty()) + return print_all(ui, properties); + else + return print_some(ui, properties, cmdline.arguments()); +} diff --git a/external/bsd/kyua-cli/dist/cli/cmd_config.hpp b/external/bsd/kyua-cli/dist/cli/cmd_config.hpp new file mode 100644 index 000000000..70cf81d17 --- /dev/null +++ b/external/bsd/kyua-cli/dist/cli/cmd_config.hpp @@ -0,0 +1,54 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file cli/cmd_config.hpp +/// Provides the cmd_config class. + +#if !defined(CLI_CMD_CONFIG_HPP) +#define CLI_CMD_CONFIG_HPP + +#include "cli/common.hpp" + +namespace cli { + + +/// Implementation of the "config" subcommand. +class cmd_config : public cli_command +{ +public: + cmd_config(void); + + int run(utils::cmdline::ui*, const utils::cmdline::parsed_cmdline&, + const utils::config::tree&); +}; + + +} // namespace cli + + +#endif // !defined(CLI_CMD_CONFIG_HPP) diff --git a/external/bsd/kyua-cli/dist/cli/cmd_config_test.cpp b/external/bsd/kyua-cli/dist/cli/cmd_config_test.cpp new file mode 100644 index 000000000..f88f284e0 --- /dev/null +++ b/external/bsd/kyua-cli/dist/cli/cmd_config_test.cpp @@ -0,0 +1,141 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "cli/cmd_config.hpp" + +#include + +#include + +#include "cli/common.ipp" +#include "engine/config.hpp" +#include "utils/cmdline/globals.hpp" +#include "utils/cmdline/ui_mock.hpp" +#include "utils/config/tree.ipp" +#include "utils/optional.ipp" + +namespace cmdline = utils::cmdline; +namespace config = utils::config; + +using cli::cmd_config; +using utils::none; + + +namespace { + + +/// Instantiates a fake user configuration for testing purposes. +/// +/// The user configuration is populated with a collection of test-suite +/// properties and some hardcoded values for the generic configuration options. +/// +/// \return A new user configuration object. +static config::tree +fake_config(void) +{ + config::tree user_config = engine::default_config(); + user_config.set_string("architecture", "the-architecture"); + user_config.set_string("platform", "the-platform"); + //user_config.set_string("unprivileged_user", ""); + user_config.set_string("test_suites.foo.bar", "first"); + user_config.set_string("test_suites.foo.baz", "second"); + return user_config; +} + + +} // anonymous namespace + + +ATF_TEST_CASE_WITHOUT_HEAD(all); +ATF_TEST_CASE_BODY(all) +{ + cmdline::args_vector args; + args.push_back("config"); + + cmd_config cmd; + cmdline::ui_mock ui; + ATF_REQUIRE_EQ(EXIT_SUCCESS, cmd.main(&ui, args, fake_config())); + + ATF_REQUIRE_EQ(4, ui.out_log().size()); + ATF_REQUIRE_EQ("architecture = the-architecture", ui.out_log()[0]); + ATF_REQUIRE_EQ("platform = the-platform", ui.out_log()[1]); + ATF_REQUIRE_EQ("test_suites.foo.bar = first", ui.out_log()[2]); + ATF_REQUIRE_EQ("test_suites.foo.baz = second", ui.out_log()[3]); + ATF_REQUIRE(ui.err_log().empty()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(some__ok); +ATF_TEST_CASE_BODY(some__ok) +{ + cmdline::args_vector args; + args.push_back("config"); + args.push_back("platform"); + args.push_back("test_suites.foo.baz"); + + cmd_config cmd; + cmdline::ui_mock ui; + ATF_REQUIRE_EQ(EXIT_SUCCESS, cmd.main(&ui, args, fake_config())); + + ATF_REQUIRE_EQ(2, ui.out_log().size()); + ATF_REQUIRE_EQ("platform = the-platform", ui.out_log()[0]); + ATF_REQUIRE_EQ("test_suites.foo.baz = second", ui.out_log()[1]); + ATF_REQUIRE(ui.err_log().empty()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(some__fail); +ATF_TEST_CASE_BODY(some__fail) +{ + cmdline::args_vector args; + args.push_back("config"); + args.push_back("platform"); + args.push_back("unknown"); + args.push_back("test_suites.foo.baz"); + + cmdline::init("progname"); + + cmd_config cmd; + cmdline::ui_mock ui; + ATF_REQUIRE_EQ(EXIT_FAILURE, cmd.main(&ui, args, fake_config())); + + ATF_REQUIRE_EQ(2, ui.out_log().size()); + ATF_REQUIRE_EQ("platform = the-platform", ui.out_log()[0]); + ATF_REQUIRE_EQ("test_suites.foo.baz = second", ui.out_log()[1]); + ATF_REQUIRE_EQ(1, ui.err_log().size()); + ATF_REQUIRE(atf::utils::grep_string("unknown.*not defined", + ui.err_log()[0])); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, all); + ATF_ADD_TEST_CASE(tcs, some__ok); + ATF_ADD_TEST_CASE(tcs, some__fail); +} diff --git a/external/bsd/kyua-cli/dist/cli/cmd_db_exec.cpp b/external/bsd/kyua-cli/dist/cli/cmd_db_exec.cpp new file mode 100644 index 000000000..80531f15a --- /dev/null +++ b/external/bsd/kyua-cli/dist/cli/cmd_db_exec.cpp @@ -0,0 +1,186 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "cli/cmd_db_exec.hpp" + +#include +#include +#include +#include +#include + +#include "cli/common.ipp" +#include "store/backend.hpp" +#include "utils/defs.hpp" +#include "utils/format/macros.hpp" +#include "utils/sanity.hpp" +#include "utils/sqlite/database.hpp" +#include "utils/sqlite/exceptions.hpp" +#include "utils/sqlite/statement.hpp" + +namespace cmdline = utils::cmdline; +namespace config = utils::config; +namespace sqlite = utils::sqlite; + +using cli::cmd_db_exec; + + +namespace { + + +/// Concatenates a vector into a string using ' ' as a separator. +/// +/// \param args The objects to join. This cannot be empty. +/// +/// \return The concatenation of all the objects in the set. +static std::string +flatten_args(const cmdline::args_vector& args) +{ + std::ostringstream output; + std::copy(args.begin(), args.end(), + std::ostream_iterator< std::string >(output, " ")); + + std::string result = output.str(); + result.erase(result.end() - 1); + return result; +} + + +} // anonymous namespace + + +/// Formats a particular cell of a statement result. +/// +/// \param stmt The statement whose cell to format. +/// \param index The index of the cell to format. +/// +/// \return A textual representation of the cell. +std::string +cli::format_cell(sqlite::statement& stmt, const int index) +{ + switch (stmt.column_type(index)) { + case sqlite::type_blob: { + const sqlite::blob blob = stmt.column_blob(index); + return F("BLOB of %s bytes") % blob.size; + } + + case sqlite::type_float: + return F("%s") % stmt.column_double(index); + + case sqlite::type_integer: + return F("%s") % stmt.column_int64(index); + + case sqlite::type_null: + return "NULL"; + + case sqlite::type_text: + return stmt.column_text(index); + } + + UNREACHABLE; +} + + +/// Formats the column names of a statement for output as CSV. +/// +/// \param stmt The statement whose columns to format. +/// +/// \return A comma-separated list of column names. +std::string +cli::format_headers(sqlite::statement& stmt) +{ + std::string output; + int i = 0; + for (; i < stmt.column_count() - 1; ++i) + output += stmt.column_name(i) + ','; + output += stmt.column_name(i); + return output; +} + + +/// Formats a row of a statement for output as CSV. +/// +/// \param stmt The statement whose current row to format. +/// +/// \return A comma-separated list of values. +std::string +cli::format_row(sqlite::statement& stmt) +{ + std::string output; + int i = 0; + for (; i < stmt.column_count() - 1; ++i) + output += cli::format_cell(stmt, i) + ','; + output += cli::format_cell(stmt, i); + return output; +} + + +/// Default constructor for cmd_db_exec. +cmd_db_exec::cmd_db_exec(void) : cli_command( + "db-exec", "sql_statement", 1, -1, + "Executes an arbitrary SQL statement in the store database and prints " + "the resulting table") +{ + add_option(store_option); + add_option(cmdline::bool_option("no-headers", "Do not show headers in the " + "output table")); +} + + +/// Entry point for the "db-exec" subcommand. +/// +/// \param ui Object to interact with the I/O of the program. +/// \param cmdline Representation of the command line to the subcommand. +/// \param unused_user_config The runtime configuration of the program. +/// +/// \return 0 if everything is OK, 1 if the statement is invalid or if there is +/// any other problem. +int +cmd_db_exec::run(cmdline::ui* ui, const cmdline::parsed_cmdline& cmdline, + const config::tree& UTILS_UNUSED_PARAM(user_config)) +{ + try { + store::backend backend = store::backend::open_rw( + cli::store_path(cmdline)); + sqlite::statement stmt = backend.database().create_statement( + flatten_args(cmdline.arguments())); + + if (stmt.step()) { + if (!cmdline.has_option("no-headers")) + ui->out(cli::format_headers(stmt)); + do + ui->out(cli::format_row(stmt)); + while (stmt.step()); + } + + return EXIT_SUCCESS; + } catch (const sqlite::error& e) { + cmdline::print_error(ui, F("SQLite error: %s") % e.what()); + return EXIT_FAILURE; + } +} diff --git a/external/bsd/kyua-cli/dist/cli/cmd_db_exec.hpp b/external/bsd/kyua-cli/dist/cli/cmd_db_exec.hpp new file mode 100644 index 000000000..7560156a3 --- /dev/null +++ b/external/bsd/kyua-cli/dist/cli/cmd_db_exec.hpp @@ -0,0 +1,67 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file cli/cmd_db_exec.hpp +/// Provides the cmd_db_exec class. + +#if !defined(CLI_CMD_DB_EXEC_HPP) +#define CLI_CMD_DB_EXEC_HPP + +#include + +#include "cli/common.hpp" + +namespace utils { +namespace sqlite { +class statement; +} // namespace sqlite +} // namespace utils + +namespace cli { + + +std::string format_cell(utils::sqlite::statement&, const int); +std::string format_headers(utils::sqlite::statement&); +std::string format_row(utils::sqlite::statement&); + + +/// Implementation of the "db-exec" subcommand. +class cmd_db_exec : public cli_command +{ +public: + cmd_db_exec(void); + + int run(utils::cmdline::ui*, const utils::cmdline::parsed_cmdline&, + const utils::config::tree&); +}; + + +} // namespace cli + + +#endif // !defined(CLI_CMD_DB_EXEC_HPP) diff --git a/external/bsd/kyua-cli/dist/cli/cmd_db_exec_test.cpp b/external/bsd/kyua-cli/dist/cli/cmd_db_exec_test.cpp new file mode 100644 index 000000000..71c32e53d --- /dev/null +++ b/external/bsd/kyua-cli/dist/cli/cmd_db_exec_test.cpp @@ -0,0 +1,165 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "cli/cmd_db_exec.hpp" + +#include + +#include + +#include "utils/format/macros.hpp" +#include "utils/sqlite/database.hpp" +#include "utils/sqlite/statement.ipp" + +namespace sqlite = utils::sqlite; + + +namespace { + + +/// Performs a test for the cli::format_cell() function. +/// +/// \tparam Cell The type of the value to insert into the test column. +/// \param column_type The SQL type of the test column. +/// \param value The value to insert into the test column. +/// \param exp_value The expected return value of cli::format_cell(). +template< class Cell > +static void +do_format_cell_test(const std::string column_type, + const Cell& value, const std::string& exp_value) +{ + sqlite::database db = sqlite::database::in_memory(); + + sqlite::statement create = db.create_statement( + F("CREATE TABLE test (column %s)") % column_type); + create.step_without_results(); + + sqlite::statement insert = db.create_statement( + "INSERT INTO test (column) VALUES (:column)"); + insert.bind(":column", value); + insert.step_without_results(); + + sqlite::statement query = db.create_statement("SELECT * FROM test"); + ATF_REQUIRE(query.step()); + ATF_REQUIRE_EQ(exp_value, cli::format_cell(query, 0)); + ATF_REQUIRE(!query.step()); +} + + +} // anonymous namespace + + +ATF_TEST_CASE_WITHOUT_HEAD(format_cell__blob); +ATF_TEST_CASE_BODY(format_cell__blob) +{ + const char* contents = "Some random contents"; + do_format_cell_test( + "BLOB", sqlite::blob(contents, std::strlen(contents)), + F("BLOB of %s bytes") % strlen(contents)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(format_cell__float); +ATF_TEST_CASE_BODY(format_cell__float) +{ + do_format_cell_test("FLOAT", 3.5, "3.5"); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(format_cell__integer); +ATF_TEST_CASE_BODY(format_cell__integer) +{ + do_format_cell_test("INTEGER", 123456, "123456"); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(format_cell__null); +ATF_TEST_CASE_BODY(format_cell__null) +{ + do_format_cell_test("TEXT", sqlite::null(), "NULL"); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(format_cell__text); +ATF_TEST_CASE_BODY(format_cell__text) +{ + do_format_cell_test("TEXT", "Hello, world", "Hello, world"); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(format_headers); +ATF_TEST_CASE_BODY(format_headers) +{ + sqlite::database db = sqlite::database::in_memory(); + + sqlite::statement create = db.create_statement( + "CREATE TABLE test (c1 TEXT, c2 TEXT, c3 TEXT)"); + create.step_without_results(); + + sqlite::statement query = db.create_statement( + "SELECT c1, c2, c3 AS c3bis FROM test"); + ATF_REQUIRE_EQ("c1,c2,c3bis", cli::format_headers(query)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(format_row); +ATF_TEST_CASE_BODY(format_row) +{ + sqlite::database db = sqlite::database::in_memory(); + + sqlite::statement create = db.create_statement( + "CREATE TABLE test (c1 TEXT, c2 BLOB)"); + create.step_without_results(); + + const char* memory = "BLOB contents"; + sqlite::statement insert = db.create_statement( + "INSERT INTO test VALUES (:v1, :v2)"); + insert.bind(":v1", "A string"); + insert.bind(":v2", sqlite::blob(memory, std::strlen(memory))); + insert.step_without_results(); + + sqlite::statement query = db.create_statement("SELECT * FROM test"); + query.step(); + ATF_REQUIRE_EQ( + (F("A string,BLOB of %s bytes") % std::strlen(memory)).str(), + cli::format_row(query)); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, format_cell__blob); + ATF_ADD_TEST_CASE(tcs, format_cell__float); + ATF_ADD_TEST_CASE(tcs, format_cell__integer); + ATF_ADD_TEST_CASE(tcs, format_cell__null); + ATF_ADD_TEST_CASE(tcs, format_cell__text); + + ATF_ADD_TEST_CASE(tcs, format_headers); + + ATF_ADD_TEST_CASE(tcs, format_row); +} diff --git a/external/bsd/kyua-cli/dist/cli/cmd_db_migrate.cpp b/external/bsd/kyua-cli/dist/cli/cmd_db_migrate.cpp new file mode 100644 index 000000000..0bc6b706a --- /dev/null +++ b/external/bsd/kyua-cli/dist/cli/cmd_db_migrate.cpp @@ -0,0 +1,75 @@ +// Copyright 2013 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "cli/cmd_db_migrate.hpp" + +#include + +#include "cli/common.ipp" +#include "store/backend.hpp" +#include "store/exceptions.hpp" +#include "utils/defs.hpp" +#include "utils/format/macros.hpp" + +namespace cmdline = utils::cmdline; +namespace config = utils::config; + +using cli::cmd_db_migrate; + + +/// Default constructor for cmd_db_migrate. +cmd_db_migrate::cmd_db_migrate(void) : cli_command( + "db-migrate", "", 0, 0, + "Upgrades the schema of an existing store database to the currently " + "implemented version. A backup of the database is created, but this " + "operation is not reversible.") +{ + add_option(store_option); +} + + +/// Entry point for the "db-migrate" subcommand. +/// +/// \param ui Object to interact with the I/O of the program. +/// \param cmdline Representation of the command line to the subcommand. +/// \param unused_user_config The runtime configuration of the program. +/// +/// \return 0 if everything is OK, 1 if the statement is invalid or if there is +/// any other problem. +int +cmd_db_migrate::run(cmdline::ui* ui, const cmdline::parsed_cmdline& cmdline, + const config::tree& UTILS_UNUSED_PARAM(user_config)) +{ + try { + store::migrate_schema(cli::store_path(cmdline)); + return EXIT_SUCCESS; + } catch (const store::error& e) { + cmdline::print_error(ui, F("Migration failed: %s") % e.what()); + return EXIT_FAILURE; + } +} diff --git a/external/bsd/kyua-cli/dist/cli/cmd_db_migrate.hpp b/external/bsd/kyua-cli/dist/cli/cmd_db_migrate.hpp new file mode 100644 index 000000000..884c3867a --- /dev/null +++ b/external/bsd/kyua-cli/dist/cli/cmd_db_migrate.hpp @@ -0,0 +1,54 @@ +// Copyright 2013 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file cli/cmd_db_migrate.hpp +/// Provides the cmd_db_migrate class. + +#if !defined(CLI_CMD_DB_MIGRATE_HPP) +#define CLI_CMD_DB_MIGRATE_HPP + +#include "cli/common.hpp" + +namespace cli { + + +/// Implementation of the "db-migrate" subcommand. +class cmd_db_migrate : public cli_command +{ +public: + cmd_db_migrate(void); + + int run(utils::cmdline::ui*, const utils::cmdline::parsed_cmdline&, + const utils::config::tree&); +}; + + +} // namespace cli + + +#endif // !defined(CLI_CMD_DB_MIGRATE_HPP) diff --git a/external/bsd/kyua-cli/dist/cli/cmd_db_migrate_test.cpp b/external/bsd/kyua-cli/dist/cli/cmd_db_migrate_test.cpp new file mode 100644 index 000000000..2ed8dfc00 --- /dev/null +++ b/external/bsd/kyua-cli/dist/cli/cmd_db_migrate_test.cpp @@ -0,0 +1,51 @@ +// Copyright 2013 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "cli/cmd_db_migrate.hpp" + +#include + +#include + +#include "utils/format/macros.hpp" +#include "utils/sqlite/database.hpp" +#include "utils/sqlite/statement.ipp" + +namespace sqlite = utils::sqlite; + + +ATF_TEST_CASE_WITHOUT_HEAD(todo); +ATF_TEST_CASE_BODY(todo) +{ +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, todo); +} diff --git a/external/bsd/kyua-cli/dist/cli/cmd_debug.cpp b/external/bsd/kyua-cli/dist/cli/cmd_debug.cpp new file mode 100644 index 000000000..b79ce97f1 --- /dev/null +++ b/external/bsd/kyua-cli/dist/cli/cmd_debug.cpp @@ -0,0 +1,93 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "cli/cmd_debug.hpp" + +#include + +#include "cli/common.ipp" +#include "engine/drivers/debug_test.hpp" +#include "engine/filters.hpp" +#include "utils/cmdline/exceptions.hpp" +#include "utils/cmdline/parser.ipp" +#include "utils/format/macros.hpp" + +namespace cmdline = utils::cmdline; +namespace config = utils::config; +namespace debug_test = engine::drivers::debug_test; + +using cli::cmd_debug; + + +/// Default constructor for cmd_debug. +cmd_debug::cmd_debug(void) : cli_command( + "debug", "test_case", 1, 1, + "Executes a single test case providing facilities for debugging") +{ + add_option(build_root_option); + add_option(kyuafile_option); + + add_option(cmdline::path_option( + "stdout", "Where to direct the standard output of the test case", + "path", "/dev/stdout")); + + add_option(cmdline::path_option( + "stderr", "Where to direct the standard error of the test case", + "path", "/dev/stderr")); +} + + +/// Entry point for the "debug" subcommand. +/// +/// \param ui Object to interact with the I/O of the program. +/// \param cmdline Representation of the command line to the subcommand. +/// \param user_config The runtime debuguration of the program. +/// +/// \return 0 if everything is OK, 1 if any of the necessary documents cannot be +/// opened. +int +cmd_debug::run(cmdline::ui* ui, const cmdline::parsed_cmdline& cmdline, + const config::tree& user_config) +{ + const std::string& test_case_name = cmdline.arguments()[0]; + if (test_case_name.find(':') == std::string::npos) + throw cmdline::usage_error(F("'%s' is not a test case identifier " + "(missing ':'?)") % test_case_name); + const engine::test_filter filter = engine::test_filter::parse( + test_case_name); + + const debug_test::result result = debug_test::drive( + kyuafile_path(cmdline), build_root_path(cmdline), filter, user_config, + cmdline.get_option< cmdline::path_option >("stdout"), + cmdline.get_option< cmdline::path_option >("stderr")); + + ui->out(F("%s -> %s") % cli::format_test_case_id(result.test_case) % + cli::format_result(result.test_result)); + + return result.test_result.good() ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/external/bsd/kyua-cli/dist/cli/cmd_debug.hpp b/external/bsd/kyua-cli/dist/cli/cmd_debug.hpp new file mode 100644 index 000000000..99bd10054 --- /dev/null +++ b/external/bsd/kyua-cli/dist/cli/cmd_debug.hpp @@ -0,0 +1,54 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file cli/cmd_debug.hpp +/// Provides the cmd_debug class. + +#if !defined(CLI_CMD_DEBUG_HPP) +#define CLI_CMD_DEBUG_HPP + +#include "cli/common.hpp" + +namespace cli { + + +/// Implementation of the "debug" subcommand. +class cmd_debug : public cli_command +{ +public: + cmd_debug(void); + + int run(utils::cmdline::ui*, const utils::cmdline::parsed_cmdline&, + const utils::config::tree&); +}; + + +} // namespace cli + + +#endif // !defined(CLI_CMD_DEBUG_HPP) diff --git a/external/bsd/kyua-cli/dist/cli/cmd_debug_test.cpp b/external/bsd/kyua-cli/dist/cli/cmd_debug_test.cpp new file mode 100644 index 000000000..2bfad5196 --- /dev/null +++ b/external/bsd/kyua-cli/dist/cli/cmd_debug_test.cpp @@ -0,0 +1,81 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "cli/cmd_debug.hpp" + +#include + +#include + +#include "cli/common.ipp" +#include "engine/config.hpp" +#include "utils/cmdline/exceptions.hpp" +#include "utils/cmdline/parser.hpp" +#include "utils/cmdline/ui_mock.hpp" + +namespace cmdline = utils::cmdline; + + +ATF_TEST_CASE_WITHOUT_HEAD(invalid_filter); +ATF_TEST_CASE_BODY(invalid_filter) +{ + cmdline::args_vector args; + args.push_back("debug"); + args.push_back("incorrect:"); + + cli::cmd_debug cmd; + cmdline::ui_mock ui; + // TODO(jmmv): This error should really be cmdline::usage_error. + ATF_REQUIRE_THROW_RE(std::runtime_error, "Test case.*'incorrect:'.*empty", + cmd.main(&ui, args, engine::default_config())); + ATF_REQUIRE(ui.out_log().empty()); + ATF_REQUIRE(ui.err_log().empty()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(filter_without_test_case); +ATF_TEST_CASE_BODY(filter_without_test_case) +{ + cmdline::args_vector args; + args.push_back("debug"); + args.push_back("program"); + + cli::cmd_debug cmd; + cmdline::ui_mock ui; + ATF_REQUIRE_THROW_RE(cmdline::error, "'program'.*not a test case", + cmd.main(&ui, args, engine::default_config())); + ATF_REQUIRE(ui.out_log().empty()); + ATF_REQUIRE(ui.err_log().empty()); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, invalid_filter); + ATF_ADD_TEST_CASE(tcs, filter_without_test_case); +} diff --git a/external/bsd/kyua-cli/dist/cli/cmd_help.cpp b/external/bsd/kyua-cli/dist/cli/cmd_help.cpp new file mode 100644 index 000000000..6d79d745e --- /dev/null +++ b/external/bsd/kyua-cli/dist/cli/cmd_help.cpp @@ -0,0 +1,247 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "cli/cmd_help.hpp" + +#include +#include + +#include "cli/common.ipp" +#include "utils/cmdline/commands_map.ipp" +#include "utils/cmdline/exceptions.hpp" +#include "utils/cmdline/globals.hpp" +#include "utils/cmdline/options.hpp" +#include "utils/cmdline/parser.hpp" +#include "utils/cmdline/ui.hpp" +#include "utils/defs.hpp" +#include "utils/format/macros.hpp" +#include "utils/sanity.hpp" +#include "utils/text/table.hpp" + +namespace cmdline = utils::cmdline; +namespace config = utils::config; +namespace text = utils::text; + +using cli::cmd_help; + + +namespace { + + +/// Creates a table with the help of a set of options. +/// +/// \param options The set of options to describe. May be empty. +/// +/// \return A 2-column wide table with the description of the options. +static text::table +options_help(const cmdline::options_vector& options) +{ + text::table table(2); + + for (cmdline::options_vector::const_iterator iter = options.begin(); + iter != options.end(); iter++) { + const cmdline::base_option* option = *iter; + + std::string description = option->description(); + if (option->needs_arg() && option->has_default_value()) + description += F(" (default: %s)") % option->default_value(); + + text::table_row row; + + if (option->has_short_name()) + row.push_back(F("%s, %s") % option->format_short_name() % + option->format_long_name()); + else + row.push_back(F("%s") % option->format_long_name()); + row.push_back(F("%s.") % description); + + table.add_row(row); + } + + return table; +} + + +/// Prints the summary of commands and generic options. +/// +/// \param ui Object to interact with the I/O of the program. +/// \param options The set of program-wide options for which to print help. +/// \param commands The set of commands for which to print help. +static void +general_help(cmdline::ui* ui, const cmdline::options_vector* options, + const cmdline::commands_map< cli::cli_command >* commands) +{ + PRE(!commands->empty()); + + ui->out_tag_wrap( + "Usage: ", + F("%s [general_options] command [command_options] [args]") % + cmdline::progname(), false); + + const text::table options_table = options_help(*options); + text::widths_vector::value_type first_width = + options_table.column_width(0); + + std::map< std::string, text::table > command_tables; + + for (cmdline::commands_map< cli::cli_command >::const_iterator + iter = commands->begin(); iter != commands->end(); iter++) { + const std::string& category = (*iter).first; + const std::set< std::string >& command_names = (*iter).second; + + command_tables.insert(std::map< std::string, text::table >::value_type( + category, text::table(2))); + text::table& table = command_tables.find(category)->second; + + for (std::set< std::string >::const_iterator i2 = command_names.begin(); + i2 != command_names.end(); i2++) { + const cli::cli_command* command = commands->find(*i2); + text::table_row row; + row.push_back(command->name()); + row.push_back(F("%s.") % command->short_description()); + table.add_row(row); + } + + if (table.column_width(0) > first_width) + first_width = table.column_width(0); + } + + text::table_formatter formatter; + formatter.set_column_width(0, first_width); + formatter.set_column_width(1, text::table_formatter::width_refill); + formatter.set_separator(" "); + + if (!options_table.empty()) { + ui->out_wrap(""); + ui->out_wrap("Available general options:"); + ui->out_table(options_table, formatter, " "); + } + + // Iterate using the same loop as above to preserve ordering. + for (cmdline::commands_map< cli::cli_command >::const_iterator + iter = commands->begin(); iter != commands->end(); iter++) { + const std::string& category = (*iter).first; + ui->out_wrap(""); + ui->out_wrap(F("%s commands:") % + (category.empty() ? "Generic" : category)); + ui->out_table(command_tables.find(category)->second, formatter, " "); + } + + ui->out_wrap(""); + ui->out_wrap("See kyua(1) for more details."); +} + + +/// Prints help for a particular subcommand. +/// +/// \param ui Object to interact with the I/O of the program. +/// \param general_options The options that apply to all commands. +/// \param command Pointer to the command to describe. +static void +subcommand_help(cmdline::ui* ui, + const utils::cmdline::options_vector* general_options, + const cli::cli_command* command) +{ + ui->out_tag_wrap( + "Usage: ", F("%s [general_options] %s%s%s") % + cmdline::progname() % command->name() % + (command->options().empty() ? "" : " [command_options]") % + (command->arg_list().empty() ? "" : (" " + command->arg_list())), + false); + ui->out_wrap(""); + ui->out_wrap(F("%s.") % command->short_description()); + + const text::table general_table = options_help(*general_options); + const text::table command_table = options_help(command->options()); + + const text::widths_vector::value_type first_width = + std::max(general_table.column_width(0), command_table.column_width(0)); + text::table_formatter formatter; + formatter.set_column_width(0, first_width); + formatter.set_column_width(1, text::table_formatter::width_refill); + formatter.set_separator(" "); + + if (!general_table.empty()) { + ui->out_wrap(""); + ui->out_wrap("Available general options:"); + ui->out_table(general_table, formatter, " "); + } + + if (!command_table.empty()) { + ui->out_wrap(""); + ui->out_wrap("Available command options:"); + ui->out_table(command_table, formatter, " "); + } + + ui->out_wrap(""); + ui->out_wrap(F("See kyua-%s(1) for more details.") % command->name()); +} + + +} // anonymous namespace + + +/// Default constructor for cmd_help. +/// +/// \param options_ The set of program-wide options for which to provide help. +/// \param commands_ The set of commands for which to provide help. +cmd_help::cmd_help(const cmdline::options_vector* options_, + const cmdline::commands_map< cli_command >* commands_) : + cli_command("help", "[subcommand]", 0, 1, "Shows usage information"), + _options(options_), + _commands(commands_) +{ +} + + +/// Entry point for the "help" subcommand. +/// +/// \param ui Object to interact with the I/O of the program. +/// \param cmdline Representation of the command line to the subcommand. +/// \param unused_user_config The runtime configuration of the program. +/// +/// \return 0 to indicate success. +int +cmd_help::run(utils::cmdline::ui* ui, const cmdline::parsed_cmdline& cmdline, + const config::tree& UTILS_UNUSED_PARAM(user_config)) +{ + if (cmdline.arguments().empty()) { + general_help(ui, _options, _commands); + } else { + INV(cmdline.arguments().size() == 1); + const std::string& cmdname = cmdline.arguments()[0]; + const cli::cli_command* command = _commands->find(cmdname); + if (command == NULL) + throw cmdline::usage_error(F("The command %s does not exist") % + cmdname); + else + subcommand_help(ui, _options, command); + } + + return EXIT_SUCCESS; +} diff --git a/external/bsd/kyua-cli/dist/cli/cmd_help.hpp b/external/bsd/kyua-cli/dist/cli/cmd_help.hpp new file mode 100644 index 000000000..45d50af39 --- /dev/null +++ b/external/bsd/kyua-cli/dist/cli/cmd_help.hpp @@ -0,0 +1,62 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file cli/cmd_help.hpp +/// Provides the cmd_help class. + +#if !defined(CLI_CMD_HELP_HPP) +#define CLI_CMD_HELP_HPP + +#include "cli/common.hpp" +#include "utils/cmdline/commands_map.hpp" + +namespace cli { + + +/// Implementation of the "help" subcommand. +class cmd_help : public cli_command +{ + /// The set of program-wide options for which to provide help. + const utils::cmdline::options_vector* _options; + + /// The set of commands for which to provide help. + const utils::cmdline::commands_map< cli_command >* _commands; + +public: + cmd_help(const utils::cmdline::options_vector*, + const utils::cmdline::commands_map< cli_command >*); + + int run(utils::cmdline::ui*, const utils::cmdline::parsed_cmdline&, + const utils::config::tree&); +}; + + +} // namespace cli + + +#endif // !defined(CLI_CMD_HELP_HPP) diff --git a/external/bsd/kyua-cli/dist/cli/cmd_help_test.cpp b/external/bsd/kyua-cli/dist/cli/cmd_help_test.cpp new file mode 100644 index 000000000..eb99d76bd --- /dev/null +++ b/external/bsd/kyua-cli/dist/cli/cmd_help_test.cpp @@ -0,0 +1,345 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "cli/cmd_help.hpp" + +#include +#include +#include + +#include + +#include "cli/common.ipp" +#include "engine/config.hpp" +#include "utils/cmdline/commands_map.ipp" +#include "utils/cmdline/exceptions.hpp" +#include "utils/cmdline/globals.hpp" +#include "utils/cmdline/options.hpp" +#include "utils/cmdline/parser.hpp" +#include "utils/cmdline/ui_mock.hpp" +#include "utils/defs.hpp" +#include "utils/sanity.hpp" + +namespace cmdline = utils::cmdline; +namespace config = utils::config; + +using cli::cmd_help; + + +namespace { + + +/// Mock command with a simple definition (no options, no arguments). +/// +/// Attempting to run this command will result in a crash. It is only provided +/// to validate the generation of interactive help. +class cmd_mock_simple : public cli::cli_command { +public: + /// Constructs a new mock command. + /// + /// \param name_ The name of the command to create. + cmd_mock_simple(const char* name_) : cli::cli_command( + name_, "", 0, 0, "Simple command") + { + } + + /// Runs the mock command. + /// + /// \param unused_ui Object to interact with the I/O of the program. + /// \param unused_cmdline Representation of the command line to the + /// subcommand. + /// \param unused_user_config The runtime configuration of the program. + /// + /// \return Nothing because this function is never called. + int + run(cmdline::ui* UTILS_UNUSED_PARAM(ui), + const cmdline::parsed_cmdline& UTILS_UNUSED_PARAM(cmdline), + const config::tree& UTILS_UNUSED_PARAM(user_config)) + { + UNREACHABLE; + } +}; + + +/// Mock command with a complex definition (some options, some arguments). +/// +/// Attempting to run this command will result in a crash. It is only provided +/// to validate the generation of interactive help. +class cmd_mock_complex : public cli::cli_command { +public: + /// Constructs a new mock command. + /// + /// \param name_ The name of the command to create. + cmd_mock_complex(const char* name_) : cli::cli_command( + name_, "[arg1 .. argN]", 0, 2, "Complex command") + { + add_option(cmdline::bool_option("flag_a", "Flag A")); + add_option(cmdline::bool_option('b', "flag_b", "Flag B")); + add_option(cmdline::string_option('c', "flag_c", "Flag C", "c_arg")); + add_option(cmdline::string_option("flag_d", "Flag D", "d_arg", "foo")); + } + + /// Runs the mock command. + /// + /// \param unused_ui Object to interact with the I/O of the program. + /// \param unused_cmdline Representation of the command line to the + /// subcommand. + /// \param unused_user_config The runtime configuration of the program. + /// + /// \return Nothing because this function is never called. + int + run(cmdline::ui* UTILS_UNUSED_PARAM(ui), + const cmdline::parsed_cmdline& UTILS_UNUSED_PARAM(cmdline), + const config::tree& UTILS_UNUSED_PARAM(user_config)) + { + UNREACHABLE; + } +}; + + +/// Initializes the cmdline library and generates the set of test commands. +/// +/// \param [out] commands A mapping that is updated to contain the commands to +/// use for testing. +static void +setup(cmdline::commands_map< cli::cli_command >& commands) +{ + cmdline::init("progname"); + + commands.insert(new cmd_mock_simple("mock_simple")); + commands.insert(new cmd_mock_complex("mock_complex")); + + commands.insert(new cmd_mock_simple("mock_simple_2"), "First"); + commands.insert(new cmd_mock_complex("mock_complex_2"), "First"); + + commands.insert(new cmd_mock_simple("mock_simple_3"), "Second"); +} + + +/// Performs a test on the global help (not that of a subcommand). +/// +/// \param general_options The genral options supported by the tool, if any. +/// \param expected_options Expected lines of help output documenting the +/// options in general_options. +/// \param ui The cmdline::mock_ui object to which to write the output. +static void +global_test(const cmdline::options_vector& general_options, + const std::vector< std::string >& expected_options, + cmdline::ui_mock& ui) +{ + cmdline::commands_map< cli::cli_command > mock_commands; + setup(mock_commands); + + cmdline::args_vector args; + args.push_back("help"); + + cmd_help cmd(&general_options, &mock_commands); + ATF_REQUIRE_EQ(EXIT_SUCCESS, cmd.main(&ui, args, engine::default_config())); + + std::vector< std::string > expected; + + expected.push_back("Usage: progname [general_options] command " + "[command_options] [args]"); + if (!general_options.empty()) { + expected.push_back(""); + expected.push_back("Available general options:"); + std::copy(expected_options.begin(), expected_options.end(), + std::back_inserter(expected)); + } + expected.push_back(""); + expected.push_back("Generic commands:"); + expected.push_back(" mock_complex Complex command."); + expected.push_back(" mock_simple Simple command."); + expected.push_back(""); + expected.push_back("First commands:"); + expected.push_back(" mock_complex_2 Complex command."); + expected.push_back(" mock_simple_2 Simple command."); + expected.push_back(""); + expected.push_back("Second commands:"); + expected.push_back(" mock_simple_3 Simple command."); + expected.push_back(""); + expected.push_back("See kyua(1) for more details."); + + ATF_REQUIRE(expected == ui.out_log()); + ATF_REQUIRE(ui.err_log().empty()); +} + + +} // anonymous namespace + + +ATF_TEST_CASE_WITHOUT_HEAD(global__no_options); +ATF_TEST_CASE_BODY(global__no_options) +{ + cmdline::ui_mock ui; + + cmdline::options_vector general_options; + + global_test(general_options, std::vector< std::string >(), ui); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(global__some_options); +ATF_TEST_CASE_BODY(global__some_options) +{ + cmdline::ui_mock ui; + + cmdline::options_vector general_options; + const cmdline::bool_option flag_a("flag_a", "Flag A"); + general_options.push_back(&flag_a); + const cmdline::string_option flag_c('c', "lc", "Flag C", "X"); + general_options.push_back(&flag_c); + + std::vector< std::string > expected; + expected.push_back(" --flag_a Flag A."); + expected.push_back(" -c X, --lc=X Flag C."); + + global_test(general_options, expected, ui); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(subcommand__simple); +ATF_TEST_CASE_BODY(subcommand__simple) +{ + cmdline::options_vector general_options; + + cmdline::commands_map< cli::cli_command > mock_commands; + setup(mock_commands); + + cmdline::args_vector args; + args.push_back("help"); + args.push_back("mock_simple"); + + cmd_help cmd(&general_options, &mock_commands); + cmdline::ui_mock ui; + ATF_REQUIRE_EQ(EXIT_SUCCESS, cmd.main(&ui, args, engine::default_config())); + ATF_REQUIRE(atf::utils::grep_collection("^Usage: progname \\[general_options\\] " + "mock_simple$", ui.out_log())); + ATF_REQUIRE(!atf::utils::grep_collection("Available.*options", ui.out_log())); + ATF_REQUIRE(atf::utils::grep_collection("^See kyua-mock_simple\\(1\\) for more " + "details.", ui.out_log())); + ATF_REQUIRE(ui.err_log().empty()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(subcommand__complex); +ATF_TEST_CASE_BODY(subcommand__complex) +{ + cmdline::options_vector general_options; + const cmdline::bool_option global_a("global_a", "Global A"); + general_options.push_back(&global_a); + const cmdline::string_option global_c('c', "global_c", "Global C", + "c_global"); + general_options.push_back(&global_c); + + cmdline::commands_map< cli::cli_command > mock_commands; + setup(mock_commands); + + cmdline::args_vector args; + args.push_back("help"); + args.push_back("mock_complex"); + + cmd_help cmd(&general_options, &mock_commands); + cmdline::ui_mock ui; + ATF_REQUIRE_EQ(EXIT_SUCCESS, cmd.main(&ui, args, engine::default_config())); + ATF_REQUIRE(atf::utils::grep_collection( + "^Usage: progname \\[general_options\\] mock_complex " + "\\[command_options\\] \\[arg1 .. argN\\]$", ui.out_log())); + ATF_REQUIRE(atf::utils::grep_collection("Available general options", + ui.out_log())); + ATF_REQUIRE(atf::utils::grep_collection("--global_a", ui.out_log())); + ATF_REQUIRE(atf::utils::grep_collection("--global_c=c_global", + ui.out_log())); + ATF_REQUIRE(atf::utils::grep_collection("Available command options", + ui.out_log())); + ATF_REQUIRE(atf::utils::grep_collection("--flag_a *Flag A", + ui.out_log())); + ATF_REQUIRE(atf::utils::grep_collection("-b.*--flag_b *Flag B", + ui.out_log())); + ATF_REQUIRE(atf::utils::grep_collection( + "-c c_arg.*--flag_c=c_arg *Flag C", ui.out_log())); + ATF_REQUIRE(atf::utils::grep_collection( + "--flag_d=d_arg *Flag D.*default.*foo", ui.out_log())); + ATF_REQUIRE(atf::utils::grep_collection( + "^See kyua-mock_complex\\(1\\) for more details.", ui.out_log())); + ATF_REQUIRE(ui.err_log().empty()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(subcommand__unknown); +ATF_TEST_CASE_BODY(subcommand__unknown) +{ + cmdline::options_vector general_options; + + cmdline::commands_map< cli::cli_command > mock_commands; + setup(mock_commands); + + cmdline::args_vector args; + args.push_back("help"); + args.push_back("foobar"); + + cmd_help cmd(&general_options, &mock_commands); + cmdline::ui_mock ui; + ATF_REQUIRE_THROW_RE(cmdline::usage_error, "command foobar.*not exist", + cmd.main(&ui, args, engine::default_config())); + ATF_REQUIRE(ui.out_log().empty()); + ATF_REQUIRE(ui.err_log().empty()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(invalid_args); +ATF_TEST_CASE_BODY(invalid_args) +{ + cmdline::options_vector general_options; + + cmdline::commands_map< cli::cli_command > mock_commands; + setup(mock_commands); + + cmdline::args_vector args; + args.push_back("help"); + args.push_back("mock_simple"); + args.push_back("mock_complex"); + + cmd_help cmd(&general_options, &mock_commands); + cmdline::ui_mock ui; + ATF_REQUIRE_THROW_RE(cmdline::usage_error, "Too many arguments", + cmd.main(&ui, args, engine::default_config())); + ATF_REQUIRE(ui.out_log().empty()); + ATF_REQUIRE(ui.err_log().empty()); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, global__no_options); + ATF_ADD_TEST_CASE(tcs, global__some_options); + ATF_ADD_TEST_CASE(tcs, subcommand__simple); + ATF_ADD_TEST_CASE(tcs, subcommand__complex); + ATF_ADD_TEST_CASE(tcs, subcommand__unknown); + ATF_ADD_TEST_CASE(tcs, invalid_args); +} diff --git a/external/bsd/kyua-cli/dist/cli/cmd_list.cpp b/external/bsd/kyua-cli/dist/cli/cmd_list.cpp new file mode 100644 index 000000000..296da1228 --- /dev/null +++ b/external/bsd/kyua-cli/dist/cli/cmd_list.cpp @@ -0,0 +1,154 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "cli/cmd_list.hpp" + +#include +#include +#include + +#include "cli/common.ipp" +#include "engine/drivers/list_tests.hpp" +#include "engine/filters.hpp" +#include "engine/test_case.hpp" +#include "engine/test_program.hpp" +#include "utils/cmdline/options.hpp" +#include "utils/cmdline/parser.ipp" +#include "utils/cmdline/ui.hpp" +#include "utils/defs.hpp" +#include "utils/format/macros.hpp" +#include "utils/fs/path.hpp" + +namespace cmdline = utils::cmdline; +namespace config = utils::config; +namespace fs = utils::fs; +namespace list_tests = engine::drivers::list_tests; + + +namespace { + + +/// Hooks for list_tests to print test cases as they come. +class progress_hooks : public list_tests::base_hooks { + /// The ui object to which to print the test cases. + cmdline::ui* _ui; + + /// Whether to print test case details or just their names. + bool _verbose; + +public: + /// Initializes the hooks. + /// + /// \param ui_ The ui object to which to print the test cases. + /// \param verbose_ Whether to print test case details or just their names. + progress_hooks(cmdline::ui* ui_, const bool verbose_) : + _ui(ui_), + _verbose(verbose_) + { + } + + /// Reports a test case as soon as it is found. + /// + /// \param test_case The test case to report. + void + got_test_case(const engine::test_case& test_case) + { + cli::detail::list_test_case(_ui, _verbose, test_case); + } +}; + + +} // anonymous namespace + + +/// Lists a single test case. +/// +/// \param [out] ui Object to interact with the I/O of the program. +/// \param verbose Whether to be verbose or not. +/// \param test_case The test case to print. +void +cli::detail::list_test_case(cmdline::ui* ui, const bool verbose, + const engine::test_case& test_case) +{ + const std::string id = format_test_case_id(test_case); + if (!verbose) { + ui->out(id); + } else { + ui->out(F("%s (%s)") % id % + test_case.container_test_program().test_suite_name()); + + // TODO(jmmv): Running these for every test case is probably not the + // fastest thing to do. + const engine::metadata default_md = engine::metadata_builder().build(); + const engine::properties_map default_props = default_md.to_properties(); + + const engine::metadata& test_md = test_case.get_metadata(); + const engine::properties_map test_props = test_md.to_properties(); + + for (engine::properties_map::const_iterator iter = test_props.begin(); + iter != test_props.end(); iter++) { + const engine::properties_map::const_iterator default_iter = + default_props.find((*iter).first); + if (default_iter == default_props.end() || + (*iter).second != (*default_iter).second) + ui->out(F(" %s = %s") % (*iter).first % (*iter).second); + } + } +} + + +/// Default constructor for cmd_list. +cli::cmd_list::cmd_list(void) : + cli_command("list", "[test-program ...]", 0, -1, + "Lists test cases and their meta-data") +{ + add_option(build_root_option); + add_option(kyuafile_option); + add_option(cmdline::bool_option('v', "verbose", "Show properties")); +} + + +/// Entry point for the "list" subcommand. +/// +/// \param ui Object to interact with the I/O of the program. +/// \param cmdline Representation of the command line to the subcommand. +/// \param unused_user_config The runtime configuration of the program. +/// +/// \return 0 to indicate success. +int +cli::cmd_list::run(cmdline::ui* ui, const cmdline::parsed_cmdline& cmdline, + const config::tree& UTILS_UNUSED_PARAM(user_config)) +{ + progress_hooks hooks(ui, cmdline.has_option("verbose")); + const list_tests::result result = list_tests::drive( + kyuafile_path(cmdline), build_root_path(cmdline), + parse_filters(cmdline.arguments()), hooks); + + return report_unused_filters(result.unused_filters, ui) ? + EXIT_FAILURE : EXIT_SUCCESS; +} diff --git a/external/bsd/kyua-cli/dist/cli/cmd_list.hpp b/external/bsd/kyua-cli/dist/cli/cmd_list.hpp new file mode 100644 index 000000000..09f971632 --- /dev/null +++ b/external/bsd/kyua-cli/dist/cli/cmd_list.hpp @@ -0,0 +1,75 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file cli/cmd_list.hpp +/// Provides the cmd_list class. + +#if !defined(CLI_CMD_LIST_HPP) +#define CLI_CMD_LIST_HPP + +#include + +#include "cli/common.hpp" + +namespace engine { +class filters_state; +class test_case; +class test_program; +} // namespace engine + +namespace utils { +namespace fs { +class path; +} // namespace fs +} // namespace utils + +namespace cli { + + +namespace detail { + +void list_test_case(utils::cmdline::ui*, const bool, const engine::test_case&); + +} // namespace detail + + +/// Implementation of the "list" subcommand. +class cmd_list : public cli_command +{ +public: + cmd_list(void); + + int run(utils::cmdline::ui*, const utils::cmdline::parsed_cmdline&, + const utils::config::tree&); +}; + + +} // namespace cli + + +#endif // !defined(CLI_CMD_LIST_HPP) diff --git a/external/bsd/kyua-cli/dist/cli/cmd_list_test.cpp b/external/bsd/kyua-cli/dist/cli/cmd_list_test.cpp new file mode 100644 index 000000000..a656d604e --- /dev/null +++ b/external/bsd/kyua-cli/dist/cli/cmd_list_test.cpp @@ -0,0 +1,107 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "cli/cmd_list.hpp" + +#include + +#include "engine/test_case.hpp" +#include "engine/test_program.hpp" +#include "utils/cmdline/exceptions.hpp" +#include "utils/cmdline/parser.hpp" +#include "utils/cmdline/ui_mock.hpp" + +namespace cmdline = utils::cmdline; +namespace fs = utils::fs; + + +ATF_TEST_CASE_WITHOUT_HEAD(list_test_case__no_verbose); +ATF_TEST_CASE_BODY(list_test_case__no_verbose) +{ + const engine::metadata md = engine::metadata_builder() + .set_description("This should not be shown") + .build(); + const engine::test_program test_program( + "mock", fs::path("the/test-program"), fs::path("root"), "suite", md); + const engine::test_case test_case("mock", test_program, "abc", md); + + cmdline::ui_mock ui; + cli::detail::list_test_case(&ui, false, test_case); + ATF_REQUIRE_EQ(1, ui.out_log().size()); + ATF_REQUIRE_EQ("the/test-program:abc", ui.out_log()[0]); + ATF_REQUIRE(ui.err_log().empty()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(list_test_case__verbose__no_properties); +ATF_TEST_CASE_BODY(list_test_case__verbose__no_properties) +{ + const engine::metadata md = engine::metadata_builder().build(); + const engine::test_program test_program("mock", fs::path("hello/world"), + fs::path("root"), "the-suite", md); + const engine::test_case test_case("mock", test_program, "my_name", md); + + cmdline::ui_mock ui; + cli::detail::list_test_case(&ui, true, test_case); + ATF_REQUIRE_EQ(1, ui.out_log().size()); + ATF_REQUIRE_EQ("hello/world:my_name (the-suite)", ui.out_log()[0]); + ATF_REQUIRE(ui.err_log().empty()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(list_test_case__verbose__some_properties); +ATF_TEST_CASE_BODY(list_test_case__verbose__some_properties) +{ + const engine::metadata md = engine::metadata_builder() + .add_custom("X-my-property", "value") + .set_description("Some description") + .set_has_cleanup(true) + .build(); + const engine::test_program test_program("mock", fs::path("hello/world"), + fs::path("root"), "the-suite", md); + const engine::test_case test_case("mock", test_program, "my_name", md); + + cmdline::ui_mock ui; + cli::detail::list_test_case(&ui, true, test_case); + ATF_REQUIRE_EQ(4, ui.out_log().size()); + ATF_REQUIRE_EQ("hello/world:my_name (the-suite)", ui.out_log()[0]); + ATF_REQUIRE_EQ(" custom.X-my-property = value", ui.out_log()[1]); + ATF_REQUIRE_EQ(" description = Some description", ui.out_log()[2]); + ATF_REQUIRE_EQ(" has_cleanup = true", ui.out_log()[3]); + ATF_REQUIRE(ui.err_log().empty()); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, list_test_case__no_verbose); + ATF_ADD_TEST_CASE(tcs, list_test_case__verbose__no_properties); + ATF_ADD_TEST_CASE(tcs, list_test_case__verbose__some_properties); + + // Tests for cmd_list::run are located in integration/cmd_list_test. +} diff --git a/external/bsd/kyua-cli/dist/cli/cmd_report.cpp b/external/bsd/kyua-cli/dist/cli/cmd_report.cpp new file mode 100644 index 000000000..ea3ffaa65 --- /dev/null +++ b/external/bsd/kyua-cli/dist/cli/cmd_report.cpp @@ -0,0 +1,392 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "cli/cmd_report.hpp" + +#include +#include +#include +#include +#include + +#include "cli/common.ipp" +#include "engine/action.hpp" +#include "engine/context.hpp" +#include "engine/drivers/scan_action.hpp" +#include "engine/test_result.hpp" +#include "utils/cmdline/exceptions.hpp" +#include "utils/cmdline/parser.ipp" +#include "utils/defs.hpp" +#include "utils/format/macros.hpp" +#include "utils/optional.ipp" + +namespace cmdline = utils::cmdline; +namespace config = utils::config; +namespace datetime = utils::datetime; +namespace fs = utils::fs; +namespace scan_action = engine::drivers::scan_action; + +using cli::cmd_report; +using utils::optional; + + +namespace { + + +/// Collection of result types. +/// +/// This is a vector rather than a set because we want to respect the order in +/// which the user provided the types. +typedef std::vector< engine::test_result::result_type > result_types; + + +/// Converts a set of result type names to identifiers. +/// +/// \param names The collection of names to process; may be empty. +/// +/// \return The result type identifiers corresponding to the input names. +/// +/// \throw std::runtime_error If any name in the input names is invalid. +static result_types +parse_types(const std::vector< std::string >& names) +{ + using engine::test_result; + typedef std::map< std::string, test_result::result_type > types_map; + types_map valid_types; + valid_types["broken"] = test_result::broken; + valid_types["failed"] = test_result::failed; + valid_types["passed"] = test_result::passed; + valid_types["skipped"] = test_result::skipped; + valid_types["xfail"] = test_result::expected_failure; + + result_types types; + for (std::vector< std::string >::const_iterator iter = names.begin(); + iter != names.end(); ++iter) { + const types_map::const_iterator match = valid_types.find(*iter); + if (match == valid_types.end()) + throw std::runtime_error(F("Unknown result type '%s'") % *iter); + else + types.push_back((*match).second); + } + return types; +} + + +/// Generates a plain-text report intended to be printed to the console. +class console_hooks : public scan_action::base_hooks { + /// Indirection to print the output to the correct file stream. + cli::file_writer _writer; + + /// Whether to include the runtime context in the output or not. + const bool _show_context; + + /// Collection of result types to include in the report. + const result_types& _results_filters; + + /// The action ID loaded. + int64_t _action_id; + + /// The total run time of the tests. + datetime::delta _runtime; + + /// Representation of a single result. + struct result_data { + /// The relative path to the test program. + fs::path binary_path; + + /// The name of the test case. + std::string test_case_name; + + /// The result of the test case. + engine::test_result result; + + /// The duration of the test case execution. + datetime::delta duration; + + /// Constructs a new results data. + /// + /// \param binary_path_ The relative path to the test program. + /// \param test_case_name_ The name of the test case. + /// \param result_ The result of the test case. + /// \param duration_ The duration of the test case execution. + result_data(const fs::path& binary_path_, + const std::string& test_case_name_, + const engine::test_result& result_, + const datetime::delta& duration_) : + binary_path(binary_path_), test_case_name(test_case_name_), + result(result_), duration(duration_) + { + } + }; + + /// Results received, broken down by their type. + /// + /// Note that this may not include all results, as keeping the whole list in + /// memory may be too much. + std::map< engine::test_result::result_type, + std::vector< result_data > > _results; + + /// Prints the execution context to the output. + /// + /// \param context The context to dump. + void + print_context(const engine::context& context) + { + _writer("===> Execution context"); + + _writer(F("Current directory: %s") % context.cwd()); + const std::map< std::string, std::string >& env = context.env(); + if (env.empty()) + _writer("No environment variables recorded"); + else { + _writer("Environment variables:"); + for (std::map< std::string, std::string >::const_iterator + iter = env.begin(); iter != env.end(); iter++) { + _writer(F(" %s=%s") % (*iter).first % (*iter).second); + } + } + } + + /// Counts how many results of a given type have been received. + std::size_t + count_results(const engine::test_result::result_type type) + { + const std::map< engine::test_result::result_type, + std::vector< result_data > >::const_iterator iter = + _results.find(type); + if (iter == _results.end()) + return 0; + else + return (*iter).second.size(); + } + + /// Prints a set of results. + void + print_results(const engine::test_result::result_type type, + const char* title) + { + const std::map< engine::test_result::result_type, + std::vector< result_data > >::const_iterator iter2 = + _results.find(type); + if (iter2 == _results.end()) + return; + const std::vector< result_data >& all = (*iter2).second; + + _writer(F("===> %s") % title); + for (std::vector< result_data >::const_iterator iter = all.begin(); + iter != all.end(); iter++) { + _writer(F("%s:%s -> %s [%s]") % (*iter).binary_path % + (*iter).test_case_name % + cli::format_result((*iter).result) % + cli::format_delta((*iter).duration)); + } + } + +public: + /// Constructor for the hooks. + /// + /// \param ui_ The user interface object of the caller command. + /// \param outfile_ The file to which to send the output. + /// \param show_context_ Whether to include the runtime context in + /// the output or not. + /// \param results_filters_ The result types to include in the report. + /// Cannot be empty. + console_hooks(cmdline::ui* ui_, const fs::path& outfile_, + const bool show_context_, + const result_types& results_filters_) : + _writer(ui_, outfile_), + _show_context(show_context_), + _results_filters(results_filters_) + { + PRE(!results_filters_.empty()); + } + + /// Callback executed when an action is found. + /// + /// \param action_id The identifier of the loaded action. + /// \param action The action loaded from the database. + void + got_action(const int64_t action_id, const engine::action& action) + { + _action_id = action_id; + if (_show_context) + print_context(action.runtime_context()); + } + + /// Callback executed when a test results is found. + /// + /// \param iter Container for the test result's data. + void + got_result(store::results_iterator& iter) + { + _runtime += iter.duration(); + const engine::test_result result = iter.result(); + _results[result.type()].push_back( + result_data(iter.test_program()->relative_path(), + iter.test_case_name(), iter.result(), iter.duration())); + } + + /// Prints the tests summary. + void + print_tests(void) + { + using engine::test_result; + typedef std::map< test_result::result_type, const char* > types_map; + + types_map titles; + titles[engine::test_result::broken] = "Broken tests"; + titles[engine::test_result::expected_failure] = "Expected failures"; + titles[engine::test_result::failed] = "Failed tests"; + titles[engine::test_result::passed] = "Passed tests"; + titles[engine::test_result::skipped] = "Skipped tests"; + + for (result_types::const_iterator iter = _results_filters.begin(); + iter != _results_filters.end(); ++iter) { + const types_map::const_iterator match = titles.find(*iter); + INV_MSG(match != titles.end(), "Conditional does not match user " + "input validation in parse_types()"); + print_results((*match).first, (*match).second); + } + + const std::size_t broken = count_results(test_result::broken); + const std::size_t failed = count_results(test_result::failed); + const std::size_t passed = count_results(test_result::passed); + const std::size_t skipped = count_results(test_result::skipped); + const std::size_t xfail = count_results(test_result::expected_failure); + const std::size_t total = broken + failed + passed + skipped + xfail; + + _writer("===> Summary"); + _writer(F("Action: %s") % _action_id); + _writer(F("Test cases: %s total, %s skipped, %s expected failures, " + "%s broken, %s failed") % + total % skipped % xfail % broken % failed); + _writer(F("Total time: %s") % cli::format_delta(_runtime)); + } +}; + + +} // anonymous namespace + + +const fs::path cli::file_writer::_stdout_path("/dev/stdout"); +const fs::path cli::file_writer::_stderr_path("/dev/stderr"); + + +/// Constructs a new file_writer wrapper. +/// +/// \param ui_ The UI object of the caller command. +/// \param path_ The path to the output file. +cli::file_writer::file_writer(cmdline::ui* const ui_, const fs::path& path_) : + _ui(ui_), _output_path(path_) +{ + if (path_ != _stdout_path && path_ != _stderr_path) { + _output_file.reset(new std::ofstream(path_.c_str())); + if (!*(_output_file)) { + throw std::runtime_error(F("Cannot open output file %s") % path_); + } + } +} + +/// Destructor. +cli::file_writer::~file_writer(void) +{ +} + +/// Writes a message to the selected output. +/// +/// \param message The message to write; should not include a termination +/// new line. +void +cli::file_writer::operator()(const std::string& message) +{ + if (_output_path == _stdout_path) + _ui->out(message); + else if (_output_path == _stderr_path) + _ui->err(message); + else { + INV(_output_file.get() != NULL); + (*_output_file) << message << '\n'; + } +} + + +/// Default constructor for cmd_report. +cmd_report::cmd_report(void) : cli_command( + "report", "", 0, 0, + "Generates a user-friendly, plain-text report with the result of a " + "previous action") +{ + add_option(store_option); + add_option(cmdline::bool_option( + "show-context", "Include the execution context in the report")); + add_option(cmdline::int_option( + "action", "The action to report; if not specified, defaults to the " + "latest action in the database", "id")); + add_option(cmdline::path_option( + "output", "The file to which to write the report", + "path", "/dev/stdout")); + add_option(cmdline::list_option( + "results-filter", "Comma-separated list of result types to include in " + "the report", "types", "skipped,xfail,broken,failed")); +} + + +/// Entry point for the "report" subcommand. +/// +/// \param ui Object to interact with the I/O of the program. +/// \param cmdline Representation of the command line to the subcommand. +/// \param unused_user_config The runtime configuration of the program. +/// +/// \return 0 if everything is OK, 1 if the statement is invalid or if there is +/// any other problem. +int +cmd_report::run(cmdline::ui* ui, const cmdline::parsed_cmdline& cmdline, + const config::tree& UTILS_UNUSED_PARAM(user_config)) +{ + optional< int64_t > action_id; + if (cmdline.has_option("action")) + action_id = cmdline.get_option< cmdline::int_option >("action"); + + result_types types = parse_types( + cmdline.get_option< cmdline::list_option >("results-filter")); + if (types.empty()) { + types.push_back(engine::test_result::passed); + types.push_back(engine::test_result::skipped); + types.push_back(engine::test_result::expected_failure); + types.push_back(engine::test_result::broken); + types.push_back(engine::test_result::failed); + } + + console_hooks hooks( + ui, cmdline.get_option< cmdline::path_option >("output"), + cmdline.has_option("show-context"), types); + scan_action::drive(store_path(cmdline), action_id, hooks); + hooks.print_tests(); + + return EXIT_SUCCESS; +} diff --git a/external/bsd/kyua-cli/dist/cli/cmd_report.hpp b/external/bsd/kyua-cli/dist/cli/cmd_report.hpp new file mode 100644 index 000000000..66c9b849e --- /dev/null +++ b/external/bsd/kyua-cli/dist/cli/cmd_report.hpp @@ -0,0 +1,96 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file cli/cmd_report.hpp +/// Provides the cmd_report class. + +#if !defined(CLI_CMD_REPORT_HPP) +#define CLI_CMD_REPORT_HPP + +#include +#include + +#include "cli/common.hpp" +#include "utils/cmdline/options.hpp" +#include "utils/cmdline/ui.hpp" +#include "utils/fs/path.hpp" +#include "utils/noncopyable.hpp" + +namespace cli { + + +/// Wrapper class to send messages through the UI or to a file. +/// +/// The cmdline::ui object provides methods to write messages to stdout and +/// stderr. We are interested in using these methods when dumping a report to +/// any of these channels, because this provides us proper logging among other +/// goodies during testing. However, these are unsuitable to write the output +/// to an arbitrary file, which is a necessity for reports. +/// +/// Therefore, this class provides a mechanism to write stdout and stderr +/// messages through the cmdline::ui object if the user so wishes, but otherwise +/// prints messages to the user selected file. +class file_writer : utils::noncopyable { + /// The UI object to write stdout and stderr messages through. + utils::cmdline::ui* const _ui; + + /// The path to the output file. + const utils::fs::path _output_path; + + /// The output file, if not stdout nor stderr. + std::auto_ptr< std::ofstream > _output_file; + + /// Constant that represents the path to stdout. + static const utils::fs::path _stdout_path; + + /// Constant that represents the path to stderr. + static const utils::fs::path _stderr_path; + +public: + file_writer(utils::cmdline::ui* const, const utils::fs::path&); + ~file_writer(void); + + void operator()(const std::string&); +}; + + +/// Implementation of the "report" subcommand. +class cmd_report : public cli_command +{ +public: + cmd_report(void); + + int run(utils::cmdline::ui*, const utils::cmdline::parsed_cmdline&, + const utils::config::tree&); +}; + + +} // namespace cli + + +#endif // !defined(CLI_CMD_REPORT_HPP) diff --git a/external/bsd/kyua-cli/dist/cli/cmd_report_html.cpp b/external/bsd/kyua-cli/dist/cli/cmd_report_html.cpp new file mode 100644 index 000000000..7fb14ee1f --- /dev/null +++ b/external/bsd/kyua-cli/dist/cli/cmd_report_html.cpp @@ -0,0 +1,368 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "cli/cmd_report_html.hpp" + +#include +#include +#include + +#include "cli/common.ipp" +#include "engine/action.hpp" +#include "engine/context.hpp" +#include "engine/drivers/scan_action.hpp" +#include "engine/test_result.hpp" +#include "utils/cmdline/options.hpp" +#include "utils/cmdline/parser.ipp" +#include "utils/datetime.hpp" +#include "utils/env.hpp" +#include "utils/format/macros.hpp" +#include "utils/fs/exceptions.hpp" +#include "utils/fs/operations.hpp" +#include "utils/fs/path.hpp" +#include "utils/optional.ipp" +#include "utils/text/templates.hpp" + +namespace cmdline = utils::cmdline; +namespace config = utils::config; +namespace datetime = utils::datetime; +namespace fs = utils::fs; +namespace scan_action = engine::drivers::scan_action; +namespace text = utils::text; + +using utils::optional; + + +namespace { + + +/// Creates the report's top directory and fails if it exists. +/// +/// \param directory The directory to create. +/// \param force Whether to wipe an existing directory or not. +/// +/// \throw std::runtime_error If the directory already exists; this is a user +/// error that the user must correct. +/// \throw fs::error If the directory creation fails for any other reason. +static void +create_top_directory(const fs::path& directory, const bool force) +{ + if (force) { + if (fs::exists(directory)) + fs::rm_r(directory); + } + + try { + fs::mkdir(directory, 0755); + } catch (const fs::system_error& e) { + if (e.original_errno() == EEXIST) + throw std::runtime_error(F("Output directory '%s' already exists; " + "maybe use --force?") % + directory); + else + throw e; + } +} + + +/// Generates a flat unique filename for a given test case. +/// +/// \param test_case The test case for which to genereate the name. +/// +/// \return A filename unique within a directory with a trailing HTML extension. +static std::string +test_case_filename(const engine::test_case& test_case) +{ + static const char* special_characters = "/:"; + + std::string name = cli::format_test_case_id(test_case); + std::string::size_type pos = name.find_first_of(special_characters); + while (pos != std::string::npos) { + name.replace(pos, 1, "_"); + pos = name.find_first_of(special_characters, pos + 1); + } + return name + ".html"; +} + + +/// Adds a string to string map to the templates. +/// +/// \param [in,out] templates The templates to add the map to. +/// \param props The map to add to the templates. +/// \param key_vector Name of the template vector that holds the keys. +/// \param value_vector Name of the template vector that holds the values. +static void +add_map(text::templates_def& templates, const config::properties_map& props, + const std::string& key_vector, const std::string& value_vector) +{ + templates.add_vector(key_vector); + templates.add_vector(value_vector); + + for (config::properties_map::const_iterator iter = props.begin(); + iter != props.end(); ++iter) { + templates.add_to_vector(key_vector, (*iter).first); + templates.add_to_vector(value_vector, (*iter).second); + } +} + + +/// Generates an HTML report. +class html_hooks : public scan_action::base_hooks { + /// User interface object where to report progress. + cmdline::ui* _ui; + + /// The top directory in which to create the HTML files. + fs::path _directory; + + /// Templates accumulator to generate the index.html file. + text::templates_def _summary_templates; + + /// Generates a common set of templates for all of our files. + /// + /// \return A new templates object with common parameters. + static text::templates_def + common_templates(void) + { + text::templates_def templates; + templates.add_variable("css", "report.css"); + return templates; + } + + /// Adds a test case result to the summary. + /// + /// \param test_case The test case to be added. + /// \param result The result of the test case. + void + add_to_summary(const engine::test_case& test_case, + const engine::test_result& result) + { + std::string test_cases_vector; + std::string test_cases_file_vector; + switch (result.type()) { + case engine::test_result::broken: + test_cases_vector = "broken_test_cases"; + test_cases_file_vector = "broken_test_cases_file"; + break; + + case engine::test_result::expected_failure: + test_cases_vector = "xfail_test_cases"; + test_cases_file_vector = "xfail_test_cases_file"; + break; + + case engine::test_result::failed: + test_cases_vector = "failed_test_cases"; + test_cases_file_vector = "failed_test_cases_file"; + break; + + case engine::test_result::passed: + test_cases_vector = "passed_test_cases"; + test_cases_file_vector = "passed_test_cases_file"; + break; + + case engine::test_result::skipped: + test_cases_vector = "skipped_test_cases"; + test_cases_file_vector = "skipped_test_cases_file"; + break; + } + INV(!test_cases_vector.empty()); + INV(!test_cases_file_vector.empty()); + + _summary_templates.add_to_vector(test_cases_vector, + cli::format_test_case_id(test_case)); + _summary_templates.add_to_vector(test_cases_file_vector, + test_case_filename(test_case)); + } + + /// Instantiate a template to generate an HTML file in the output directory. + /// + /// \param templates The templates to use. + /// \param template_name The name of the template. This is automatically + /// searched for in the installed directory, so do not provide a path. + /// \param output_name The name of the output file. This is a basename to + /// be created within the output directory. + /// + /// \throw text::error If there is any problem applying the templates. + void + generate(const text::templates_def& templates, + const std::string& template_name, + const std::string& output_name) const + { + const fs::path miscdir(utils::getenv_with_default( + "KYUA_MISCDIR", KYUA_MISCDIR)); + const fs::path template_file = miscdir / template_name; + const fs::path output_path(_directory / output_name); + + _ui->out(F("Generating %s") % output_path); + text::instantiate(templates, template_file, output_path); + } + +public: + /// Constructor for the hooks. + /// + /// \param ui_ User interface object where to report progress. + /// \param directory_ The directory in which to create the HTML files. + html_hooks(cmdline::ui* ui_, const fs::path& directory_) : + _ui(ui_), + _directory(directory_), + _summary_templates(common_templates()) + { + // Keep in sync with add_to_summary(). + _summary_templates.add_vector("broken_test_cases"); + _summary_templates.add_vector("broken_test_cases_file"); + _summary_templates.add_vector("xfail_test_cases"); + _summary_templates.add_vector("xfail_test_cases_file"); + _summary_templates.add_vector("failed_test_cases"); + _summary_templates.add_vector("failed_test_cases_file"); + _summary_templates.add_vector("passed_test_cases"); + _summary_templates.add_vector("passed_test_cases_file"); + _summary_templates.add_vector("skipped_test_cases"); + _summary_templates.add_vector("skipped_test_cases_file"); + } + + /// Callback executed when an action is found. + /// + /// \param action_id The identifier of the loaded action. + /// \param action The action loaded from the database. + void + got_action(const int64_t action_id, + const engine::action& action) + { + _summary_templates.add_variable("action_id", F("%s") % action_id); + + const engine::context& context = action.runtime_context(); + text::templates_def templates = common_templates(); + templates.add_variable("action_id", F("%s") % action_id); + templates.add_variable("cwd", context.cwd().str()); + add_map(templates, context.env(), "env_var", "env_var_value"); + generate(templates, "context.html", "context.html"); + } + + /// Callback executed when a test results is found. + /// + /// \param iter Container for the test result's data. + void + got_result(store::results_iterator& iter) + { + const engine::test_program_ptr test_program = iter.test_program(); + const engine::test_result result = iter.result(); + + const engine::test_case& test_case = *test_program->find( + iter.test_case_name()); + + add_to_summary(test_case, result); + + text::templates_def templates = common_templates(); + templates.add_variable("test_case", + cli::format_test_case_id(test_case)); + templates.add_variable("test_program", + test_program->absolute_path().str()); + templates.add_variable("result", cli::format_result(result)); + templates.add_variable("duration", cli::format_delta(iter.duration())); + + add_map(templates, test_case.get_metadata().to_properties(), + "metadata_var", "metadata_value"); + + { + const std::string stdout_text = iter.stdout_contents(); + if (!stdout_text.empty()) + templates.add_variable("stdout", stdout_text); + } + { + const std::string stderr_text = iter.stderr_contents(); + if (!stderr_text.empty()) + templates.add_variable("stderr", stderr_text); + } + + generate(templates, "test_result.html", test_case_filename(test_case)); + } + + /// Writes the index.html file in the output directory. + /// + /// This should only be called once all the processing has been done; + /// i.e. when the scan_action driver returns. + void + write_summary(void) + { + const std::size_t bad_count = + _summary_templates.get_vector("broken_test_cases").size() + + _summary_templates.get_vector("failed_test_cases").size(); + _summary_templates.add_variable("bad_tests_count", F("%s") % bad_count); + + generate(text::templates_def(), "report.css", "report.css"); + generate(_summary_templates, "index.html", "index.html"); + } +}; + + +} // anonymous namespace + + +/// Default constructor for cmd_report_html. +cli::cmd_report_html::cmd_report_html(void) : cli_command( + "report-html", "", 0, 0, + "Generates an HTML report with the result of a previous action") +{ + add_option(store_option); + add_option(cmdline::int_option( + "action", "The action to report; if not specified, defaults to the " + "latest action in the database", "id")); + add_option(cmdline::bool_option( + "force", "Wipe the output directory before generating the new report; " + "use care")); + add_option(cmdline::path_option( + "output", "The directory in which to store the HTML files", + "path", "html")); +} + + +/// Entry point for the "report-html" subcommand. +/// +/// \param ui Object to interact with the I/O of the program. +/// \param cmdline Representation of the command line to the subcommand. +/// \param unused_user_config The runtime configuration of the program. +/// +/// \return 0 if everything is OK, 1 if the statement is invalid or if there is +/// any other problem. +int +cli::cmd_report_html::run(cmdline::ui* ui, + const cmdline::parsed_cmdline& cmdline, + const config::tree& UTILS_UNUSED_PARAM(user_config)) +{ + optional< int64_t > action_id; + if (cmdline.has_option("action")) + action_id = cmdline.get_option< cmdline::int_option >("action"); + + const fs::path directory = + cmdline.get_option< cmdline::path_option >("output"); + create_top_directory(directory, cmdline.has_option("force")); + html_hooks hooks(ui, directory); + scan_action::drive(store_path(cmdline), action_id, hooks); + hooks.write_summary(); + + return EXIT_SUCCESS; +} diff --git a/external/bsd/kyua-cli/dist/cli/cmd_report_html.hpp b/external/bsd/kyua-cli/dist/cli/cmd_report_html.hpp new file mode 100644 index 000000000..d01bc884e --- /dev/null +++ b/external/bsd/kyua-cli/dist/cli/cmd_report_html.hpp @@ -0,0 +1,55 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file cli/cmd_report_html.hpp +/// Provides the cmd_report_html class. + +#if !defined(CLI_CMD_REPORT_HTML_HPP) +#define CLI_CMD_REPORT_HTML_HPP + +#include "cli/common.hpp" +#include "utils/cmdline/ui.hpp" + +namespace cli { + + +/// Implementation of the "report-html" subcommand. +class cmd_report_html : public cli_command +{ +public: + cmd_report_html(void); + + int run(utils::cmdline::ui*, const utils::cmdline::parsed_cmdline&, + const utils::config::tree&); +}; + + +} // namespace cli + + +#endif // !defined(CLI_CMD_REPORT_HTML_HPP) diff --git a/external/bsd/kyua-cli/dist/cli/cmd_report_html_test.cpp b/external/bsd/kyua-cli/dist/cli/cmd_report_html_test.cpp new file mode 100644 index 000000000..bf707402d --- /dev/null +++ b/external/bsd/kyua-cli/dist/cli/cmd_report_html_test.cpp @@ -0,0 +1,47 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "cli/cmd_report_html.hpp" + +#include + +#include "utils/cmdline/ui_mock.hpp" + +namespace cmdline = utils::cmdline; + + +ATF_TEST_CASE_WITHOUT_HEAD(TODO); +ATF_TEST_CASE_BODY(TODO) +{ +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, TODO); +} diff --git a/external/bsd/kyua-cli/dist/cli/cmd_report_test.cpp b/external/bsd/kyua-cli/dist/cli/cmd_report_test.cpp new file mode 100644 index 000000000..46d907e76 --- /dev/null +++ b/external/bsd/kyua-cli/dist/cli/cmd_report_test.cpp @@ -0,0 +1,91 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "cli/cmd_report.hpp" + +#include + +#include "utils/fs/path.hpp" +#include "utils/cmdline/exceptions.hpp" +#include "utils/cmdline/ui_mock.hpp" + +namespace cmdline = utils::cmdline; +namespace fs = utils::fs; + + +ATF_TEST_CASE_WITHOUT_HEAD(file_writer__stdout); +ATF_TEST_CASE_BODY(file_writer__stdout) +{ + cmdline::ui_mock ui; + { + cli::file_writer writer(&ui, fs::path("/dev/stdout")); + writer("A simple message"); + } + + ATF_REQUIRE_EQ(1, ui.out_log().size()); + ATF_REQUIRE_EQ("A simple message", ui.out_log()[0]); + ATF_REQUIRE(ui.err_log().empty()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(file_writer__stderr); +ATF_TEST_CASE_BODY(file_writer__stderr) +{ + cmdline::ui_mock ui; + { + cli::file_writer writer(&ui, fs::path("/dev/stderr")); + writer("A simple message"); + } + + ATF_REQUIRE(ui.out_log().empty()); + ATF_REQUIRE_EQ(1, ui.err_log().size()); + ATF_REQUIRE_EQ("A simple message", ui.err_log()[0]); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(file_writer__other); +ATF_TEST_CASE_BODY(file_writer__other) +{ + cmdline::ui_mock ui; + { + cli::file_writer writer(&ui, fs::path("custom")); + writer("A simple message"); + } + + ATF_REQUIRE(ui.out_log().empty()); + ATF_REQUIRE(ui.err_log().empty()); + ATF_REQUIRE(atf::utils::grep_file("A simple message", "custom")); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, file_writer__stdout); + ATF_ADD_TEST_CASE(tcs, file_writer__stderr); + ATF_ADD_TEST_CASE(tcs, file_writer__other); +} diff --git a/external/bsd/kyua-cli/dist/cli/cmd_test.cpp b/external/bsd/kyua-cli/dist/cli/cmd_test.cpp new file mode 100644 index 000000000..f68f6572e --- /dev/null +++ b/external/bsd/kyua-cli/dist/cli/cmd_test.cpp @@ -0,0 +1,149 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "cli/cmd_test.hpp" + +#include + +#include "cli/common.ipp" +#include "engine/drivers/run_tests.hpp" +#include "engine/test_case.hpp" +#include "engine/test_result.hpp" +#include "utils/cmdline/options.hpp" +#include "utils/cmdline/parser.ipp" +#include "utils/cmdline/ui.hpp" +#include "utils/datetime.hpp" +#include "utils/format/macros.hpp" + +namespace cmdline = utils::cmdline; +namespace config = utils::config; +namespace datetime = utils::datetime; +namespace fs = utils::fs; +namespace run_tests = engine::drivers::run_tests; + +using cli::cmd_test; + + +namespace { + + +/// Hooks to print a progress report of the execution of the tests. +class print_hooks : public run_tests::base_hooks { + /// Object to interact with the I/O of the program. + cmdline::ui* _ui; + +public: + /// The amount of positive test results found so far. + unsigned long good_count; + + /// The amount of negative test results found so far. + unsigned long bad_count; + + /// Constructor for the hooks. + /// + /// \param ui_ Object to interact with the I/O of the program. + print_hooks(cmdline::ui* ui_) : + _ui(ui_), + good_count(0), + bad_count(0) + { + } + + /// Called when the processing of a test case begins. + /// + /// \param test_case The test case. + virtual void + got_test_case(const engine::test_case_ptr& test_case) + { + _ui->out(F("%s -> ") % cli::format_test_case_id(*test_case), false); + } + + /// Called when a result of a test case becomes available. + /// + /// \param unused_test_case The test case. + /// \param result The result of the execution of the test case. + /// \param duration The time it took to run the test. + virtual void + got_result(const engine::test_case_ptr& UTILS_UNUSED_PARAM(test_case), + const engine::test_result& result, + const datetime::delta& duration) + { + _ui->out(F("%s [%s]") % cli::format_result(result) % + cli::format_delta(duration)); + if (result.good()) + good_count++; + else + bad_count++; + } +}; + + +} // anonymous namespace + + +/// Default constructor for cmd_test. +cmd_test::cmd_test(void) : cli_command( + "test", "[test-program ...]", 0, -1, "Run tests") +{ + add_option(build_root_option); + add_option(kyuafile_option); + add_option(store_option); +} + + +/// Entry point for the "test" subcommand. +/// +/// \param ui Object to interact with the I/O of the program. +/// \param cmdline Representation of the command line to the subcommand. +/// \param user_config The runtime configuration of the program. +/// +/// \return 0 if all tests passed, 1 otherwise. +int +cmd_test::run(cmdline::ui* ui, const cmdline::parsed_cmdline& cmdline, + const config::tree& user_config) +{ + print_hooks hooks(ui); + const run_tests::result result = run_tests::drive( + kyuafile_path(cmdline), build_root_path(cmdline), store_path(cmdline), + parse_filters(cmdline.arguments()), user_config, hooks); + + int exit_code; + if (hooks.good_count > 0 || hooks.bad_count > 0) { + ui->out(""); + ui->out(F("%s/%s passed (%s failed)") % hooks.good_count % + (hooks.good_count + hooks.bad_count) % hooks.bad_count); + + exit_code = (hooks.bad_count == 0 ? EXIT_SUCCESS : EXIT_FAILURE); + } else + exit_code = EXIT_SUCCESS; + + ui->out(F("Committed action %s") % result.action_id); + + return report_unused_filters(result.unused_filters, ui) ? + EXIT_FAILURE : exit_code; +} diff --git a/external/bsd/kyua-cli/dist/cli/cmd_test.hpp b/external/bsd/kyua-cli/dist/cli/cmd_test.hpp new file mode 100644 index 000000000..64e9e245b --- /dev/null +++ b/external/bsd/kyua-cli/dist/cli/cmd_test.hpp @@ -0,0 +1,54 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file cli/cmd_test.hpp +/// Provides the cmd_test class. + +#if !defined(CLI_CMD_TEST_HPP) +#define CLI_CMD_TEST_HPP + +#include "cli/common.hpp" + +namespace cli { + + +/// Implementation of the "test" subcommand. +class cmd_test : public cli_command +{ +public: + cmd_test(void); + + int run(utils::cmdline::ui*, const utils::cmdline::parsed_cmdline&, + const utils::config::tree&); +}; + + +} // namespace cli + + +#endif // !defined(CLI_CMD_TEST_HPP) diff --git a/external/bsd/kyua-cli/dist/cli/cmd_test_test.cpp b/external/bsd/kyua-cli/dist/cli/cmd_test_test.cpp new file mode 100644 index 000000000..45511d179 --- /dev/null +++ b/external/bsd/kyua-cli/dist/cli/cmd_test_test.cpp @@ -0,0 +1,62 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "cli/cmd_test.hpp" + +#include + +#include "cli/common.ipp" +#include "engine/config.hpp" +#include "utils/cmdline/exceptions.hpp" +#include "utils/cmdline/parser.hpp" +#include "utils/cmdline/ui_mock.hpp" + +namespace cmdline = utils::cmdline; + + +ATF_TEST_CASE_WITHOUT_HEAD(invalid_filter); +ATF_TEST_CASE_BODY(invalid_filter) +{ + cmdline::args_vector args; + args.push_back("test"); + args.push_back("correct"); + args.push_back("incorrect:"); + + cli::cmd_test cmd; + cmdline::ui_mock ui; + ATF_REQUIRE_THROW_RE(cmdline::error, "Test case.*'incorrect:'.*empty", + cmd.main(&ui, args, engine::default_config())); + ATF_REQUIRE(ui.out_log().empty()); + ATF_REQUIRE(ui.err_log().empty()); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, invalid_filter); +} diff --git a/external/bsd/kyua-cli/dist/cli/common.cpp b/external/bsd/kyua-cli/dist/cli/common.cpp new file mode 100644 index 000000000..4817e7b04 --- /dev/null +++ b/external/bsd/kyua-cli/dist/cli/common.cpp @@ -0,0 +1,277 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "cli/common.hpp" + +#include + +#include "engine/filters.hpp" +#include "engine/test_case.hpp" +#include "engine/test_program.hpp" +#include "engine/test_result.hpp" +#include "utils/cmdline/exceptions.hpp" +#include "utils/cmdline/parser.ipp" +#include "utils/datetime.hpp" +#include "utils/env.hpp" +#include "utils/format/macros.hpp" +#include "utils/logging/macros.hpp" +#include "utils/fs/exceptions.hpp" +#include "utils/fs/operations.hpp" +#include "utils/fs/path.hpp" +#include "utils/optional.ipp" + +namespace cmdline = utils::cmdline; +namespace datetime = utils::datetime; +namespace fs = utils::fs; + +using utils::none; +using utils::optional; + + +/// Standard definition of the option to specify the build root. +const cmdline::path_option cli::build_root_option( + "build-root", + "Path to the built test programs, if different from the location of the " + "Kyuafile scripts", + "path"); + + +/// Standard definition of the option to specify a Kyuafile. +const cmdline::path_option cli::kyuafile_option( + 'k', "kyuafile", + "Path to the test suite definition", + "file", "Kyuafile"); + + +/// Standard definition of the option to specify the store. +const cmdline::path_option cli::store_option( + 's', "store", + "Path to the store database", + "file", "~/.kyua/store.db"); + + +/// Gets the path to the build root, if any. +/// +/// This is just syntactic sugar to simplify quierying the 'build_root_option'. +/// +/// \param cmdline The parsed command line. +/// +/// \return The path to the build root, if specified; none otherwise. +optional< fs::path > +cli::build_root_path(const cmdline::parsed_cmdline& cmdline) +{ + optional< fs::path > build_root; + if (cmdline.has_option(build_root_option.long_name())) + build_root = cmdline.get_option< cmdline::path_option >( + build_root_option.long_name()); + return build_root; +} + + +/// Gets the value of the HOME environment variable with path validation. +/// +/// \return The value of the HOME environment variable if it is a valid path; +/// none if it is not defined or if it contains an invalid path. +optional< fs::path > +cli::get_home(void) +{ + const optional< std::string > home = utils::getenv("HOME"); + if (home) { + try { + return utils::make_optional(fs::path(home.get())); + } catch (const fs::error& e) { + LW(F("Invalid value '%s' in HOME environment variable: %s") % + home.get() % e.what()); + return none; + } + } else + return none; +} + + +/// Gets the path to the Kyuafile to be loaded. +/// +/// This is just syntactic sugar to simplify quierying the 'kyuafile_option'. +/// +/// \param cmdline The parsed command line. +/// +/// \return The path to the Kyuafile to be loaded. +fs::path +cli::kyuafile_path(const cmdline::parsed_cmdline& cmdline) +{ + return cmdline.get_option< cmdline::path_option >( + kyuafile_option.long_name()); +} + + +/// Gets the path to the store to be used. +/// +/// This has the side-effect of creating the directory in which to store the +/// database if and only if the path to the database matches the default value. +/// When the user does not specify an override for the location of the database, +/// he should not care about the directory existing. Any of this is not a big +/// deal though, because logs are also stored within ~/.kyua and thus we will +/// most likely end up creating the directory anyway. +/// +/// \param cmdline The parsed command line. +/// +/// \return The path to the store to be used. +/// +/// \throw fs::error If the creation of the directory fails. +fs::path +cli::store_path(const cmdline::parsed_cmdline& cmdline) +{ + fs::path store = cmdline.get_option< cmdline::path_option >( + store_option.long_name()); + if (store == fs::path(store_option.default_value())) { + const optional< fs::path > home = cli::get_home(); + if (home) { + store = home.get() / ".kyua/store.db"; + fs::mkdir_p(store.branch_path(), 0777); + } else { + store = fs::path("kyua-store.db"); + LW("HOME not defined; creating store database in current " + "directory"); + } + } + LI(F("Store database set to: %s") % store); + return store; +} + + +/// Parses a set of command-line arguments to construct test filters. +/// +/// \param args The command-line arguments representing test filters. +/// +/// \throw cmdline:error If any of the arguments is invalid, or if they +/// represent a non-disjoint collection of filters. +std::set< engine::test_filter > +cli::parse_filters(const cmdline::args_vector& args) +{ + std::set< engine::test_filter > filters; + + try { + for (cmdline::args_vector::const_iterator iter = args.begin(); + iter != args.end(); iter++) { + const engine::test_filter filter(engine::test_filter::parse(*iter)); + if (filters.find(filter) != filters.end()) + throw cmdline::error(F("Duplicate filter '%s'") % filter.str()); + filters.insert(filter); + } + check_disjoint_filters(filters); + } catch (const std::runtime_error& e) { + throw cmdline::error(e.what()); + } + + return filters; +} + + +/// Reports the filters that have not matched any tests as errors. +/// +/// \param unused The collection of unused filters to report. +/// \param ui The user interface object through which errors are to be reported. +/// +/// \return True if there are any unused filters. The caller should report this +/// as an error to the user by means of a non-successful exit code. +bool +cli::report_unused_filters(const std::set< engine::test_filter >& unused, + cmdline::ui* ui) +{ + for (std::set< engine::test_filter >::const_iterator iter = unused.begin(); + iter != unused.end(); iter++) { + cmdline::print_warning(ui, F("No test cases matched by the filter '%s'") + % (*iter).str()); + } + + return !unused.empty(); +} + + +/// Formats a time delta for user presentation. +/// +/// \param delta The time delta to format. +/// +/// \return A user-friendly representation of the time delta. +std::string +cli::format_delta(const datetime::delta& delta) +{ + return F("%.3ss") % (delta.seconds + (delta.useconds / 1000000.0)); +} + + +/// Formats a test case result for user presentation. +/// +/// \param result The result to format. +/// +/// \return A user-friendly representation of the result. +std::string +cli::format_result(const engine::test_result& result) +{ + std::string text; + + using engine::test_result; + switch (result.type()) { + case test_result::broken: text = "broken"; break; + case test_result::expected_failure: text = "expected_failure"; break; + case test_result::failed: text = "failed"; break; + case test_result::passed: text = "passed"; break; + case test_result::skipped: text = "skipped"; break; + } + INV(!text.empty()); + + if (!result.reason().empty()) + text += ": " + result.reason(); + + return text; +} + + +/// Formats the identifier of a test case for user presentation. +/// +/// \param test_case The test case whose identifier to format. +/// +/// \return A string representing the test case uniquely within a test suite. +std::string +cli::format_test_case_id(const engine::test_case& test_case) +{ + return F("%s:%s") % test_case.container_test_program().relative_path() % + test_case.name(); +} + + +/// Formats a filter using the same syntax of a test case. +/// +/// \param test_filter The filter to format. +/// +/// \return A string representing the test filter. +std::string +cli::format_test_case_id(const engine::test_filter& test_filter) +{ + return F("%s:%s") % test_filter.test_program % test_filter.test_case; +} diff --git a/external/bsd/kyua-cli/dist/cli/common.hpp b/external/bsd/kyua-cli/dist/cli/common.hpp new file mode 100644 index 000000000..a5064c78b --- /dev/null +++ b/external/bsd/kyua-cli/dist/cli/common.hpp @@ -0,0 +1,100 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file cli/common.hpp +/// Utility functions to implement CLI subcommands. + +#if !defined(CLI_COMMON_HPP) +#define CLI_COMMON_HPP + +#include +#include + +#include "utils/cmdline/base_command.hpp" +#include "utils/cmdline/options.hpp" +#include "utils/cmdline/parser.hpp" +#include "utils/cmdline/ui.hpp" +#include "utils/config/tree.hpp" +#include "utils/datetime.hpp" +#include "utils/fs/path.hpp" +#include "utils/optional.hpp" + +namespace utils { +namespace fs { +class path; +} // namespace fs +} // namespace utils + +namespace engine { +struct test_filter; +class test_case; +class test_result; +} // namespace engine + +namespace cli { + + +extern const utils::cmdline::path_option build_root_option; +extern const utils::cmdline::path_option kyuafile_option; +extern const utils::cmdline::path_option store_option; +extern const utils::cmdline::property_option variable_option; + + +/// Base type for commands defined in the cli module. +/// +/// All commands in Kyua receive a configuration object as their runtime +/// data parameter because the configuration file applies to all the +/// commands. +typedef utils::cmdline::base_command< utils::config::tree > cli_command; + + +/// Scoped, strictly owned pointer to a cli_command. +typedef std::auto_ptr< cli_command > cli_command_ptr; + + +utils::optional< utils::fs::path > get_home(void); + +utils::optional< utils::fs::path > build_root_path( + const utils::cmdline::parsed_cmdline&); +utils::fs::path kyuafile_path(const utils::cmdline::parsed_cmdline&); +utils::fs::path store_path(const utils::cmdline::parsed_cmdline&); + +std::set< engine::test_filter > parse_filters( + const utils::cmdline::args_vector&); +bool report_unused_filters(const std::set< engine::test_filter >&, + utils::cmdline::ui*); + +std::string format_delta(const utils::datetime::delta&); +std::string format_result(const engine::test_result&); +std::string format_test_case_id(const engine::test_case&); +std::string format_test_case_id(const engine::test_filter&); + + +} // namespace cli + +#endif // !defined(CLI_COMMON_HPP) diff --git a/external/bsd/kyua-cli/dist/cli/common.ipp b/external/bsd/kyua-cli/dist/cli/common.ipp new file mode 100644 index 000000000..0945d0285 --- /dev/null +++ b/external/bsd/kyua-cli/dist/cli/common.ipp @@ -0,0 +1,30 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "cli/common.hpp" +#include "utils/cmdline/base_command.ipp" diff --git a/external/bsd/kyua-cli/dist/cli/common_test.cpp b/external/bsd/kyua-cli/dist/cli/common_test.cpp new file mode 100644 index 000000000..9ecc9c8b6 --- /dev/null +++ b/external/bsd/kyua-cli/dist/cli/common_test.cpp @@ -0,0 +1,378 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "cli/common.hpp" + +#include + +#include + +#include "engine/exceptions.hpp" +#include "engine/filters.hpp" +#include "engine/test_case.hpp" +#include "engine/test_program.hpp" +#include "engine/test_result.hpp" +#include "utils/cmdline/exceptions.hpp" +#include "utils/cmdline/globals.hpp" +#include "utils/cmdline/parser.ipp" +#include "utils/cmdline/ui_mock.hpp" +#include "utils/datetime.hpp" +#include "utils/env.hpp" +#include "utils/fs/exceptions.hpp" +#include "utils/fs/operations.hpp" +#include "utils/fs/path.hpp" +#include "utils/optional.ipp" +#include "utils/sanity.hpp" + +namespace cmdline = utils::cmdline; +namespace config = utils::config; +namespace datetime = utils::datetime; +namespace fs = utils::fs; + +using utils::optional; + + +namespace { + + +/// Syntactic sugar to instantiate engine::test_filter objects. +inline engine::test_filter +mkfilter(const char* test_program, const char* test_case) +{ + return engine::test_filter(fs::path(test_program), test_case); +} + + +} // anonymous namespace + + +ATF_TEST_CASE_WITHOUT_HEAD(build_root_path__default); +ATF_TEST_CASE_BODY(build_root_path__default) +{ + std::map< std::string, std::vector< std::string > > options; + const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector()); + + ATF_REQUIRE(!cli::build_root_path(mock_cmdline)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(build_root_path__explicit); +ATF_TEST_CASE_BODY(build_root_path__explicit) +{ + std::map< std::string, std::vector< std::string > > options; + options["build-root"].push_back("/my//path"); + const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector()); + + ATF_REQUIRE(cli::build_root_path(mock_cmdline)); + ATF_REQUIRE_EQ("/my/path", cli::build_root_path(mock_cmdline).get().str()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(get_home__ok); +ATF_TEST_CASE_BODY(get_home__ok) +{ + const fs::path home("/foo/bar"); + utils::setenv("HOME", home.str()); + const optional< fs::path > computed = cli::get_home(); + ATF_REQUIRE(computed); + ATF_REQUIRE_EQ(home, computed.get()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(get_home__missing); +ATF_TEST_CASE_BODY(get_home__missing) +{ + utils::unsetenv("HOME"); + ATF_REQUIRE(!cli::get_home()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(get_home__invalid); +ATF_TEST_CASE_BODY(get_home__invalid) +{ + utils::setenv("HOME", ""); + ATF_REQUIRE(!cli::get_home()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(kyuafile_path__default); +ATF_TEST_CASE_BODY(kyuafile_path__default) +{ + std::map< std::string, std::vector< std::string > > options; + options["kyuafile"].push_back(cli::kyuafile_option.default_value()); + const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector()); + + ATF_REQUIRE_EQ(cli::kyuafile_option.default_value(), + cli::kyuafile_path(mock_cmdline).str()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(kyuafile_path__explicit); +ATF_TEST_CASE_BODY(kyuafile_path__explicit) +{ + std::map< std::string, std::vector< std::string > > options; + options["kyuafile"].push_back("/my//path"); + const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector()); + + ATF_REQUIRE_EQ("/my/path", cli::kyuafile_path(mock_cmdline).str()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(store_path__default__create_directory__ok); +ATF_TEST_CASE_BODY(store_path__default__create_directory__ok) +{ + std::map< std::string, std::vector< std::string > > options; + options["store"].push_back(cli::store_option.default_value()); + const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector()); + + const fs::path home("homedir"); + utils::setenv("HOME", home.str()); + + ATF_REQUIRE(!fs::exists(home / ".kyua")); + ATF_REQUIRE_EQ(home / ".kyua/store.db", cli::store_path(mock_cmdline)); + ATF_REQUIRE(fs::exists(home / ".kyua")); +} + + +ATF_TEST_CASE(store_path__default__create_directory__fail); +ATF_TEST_CASE_HEAD(store_path__default__create_directory__fail) +{ + set_md_var("require.user", "unprivileged"); +} +ATF_TEST_CASE_BODY(store_path__default__create_directory__fail) +{ + std::map< std::string, std::vector< std::string > > options; + options["store"].push_back(cli::store_option.default_value()); + const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector()); + + const fs::path home("homedir"); + utils::setenv("HOME", home.str()); + fs::mkdir(home, 0555); + + ATF_REQUIRE_THROW(fs::error, cli::store_path(mock_cmdline).str()); + ATF_REQUIRE(!fs::exists(home / ".kyua")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(store_path__default__no_home); +ATF_TEST_CASE_BODY(store_path__default__no_home) +{ + std::map< std::string, std::vector< std::string > > options; + options["store"].push_back(cli::store_option.default_value()); + const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector()); + + utils::unsetenv("HOME"); + + ATF_REQUIRE_EQ("kyua-store.db", cli::store_path(mock_cmdline).str()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(store_path__explicit); +ATF_TEST_CASE_BODY(store_path__explicit) +{ + std::map< std::string, std::vector< std::string > > options; + options["store"].push_back("/my//path"); + const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector()); + + const fs::path home("homedir"); + ATF_REQUIRE_EQ("/my/path", cli::store_path(mock_cmdline).str()); + ATF_REQUIRE(!fs::exists(home / ".kyua")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(parse_filters__none); +ATF_TEST_CASE_BODY(parse_filters__none) +{ + const cmdline::args_vector args; + const std::set< engine::test_filter > filters = cli::parse_filters(args); + ATF_REQUIRE(filters.empty()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(parse_filters__ok); +ATF_TEST_CASE_BODY(parse_filters__ok) +{ + cmdline::args_vector args; + args.push_back("foo"); + args.push_back("bar/baz"); + args.push_back("other:abc"); + args.push_back("other:bcd"); + const std::set< engine::test_filter > filters = cli::parse_filters(args); + + std::set< engine::test_filter > exp_filters; + exp_filters.insert(mkfilter("foo", "")); + exp_filters.insert(mkfilter("bar/baz", "")); + exp_filters.insert(mkfilter("other", "abc")); + exp_filters.insert(mkfilter("other", "bcd")); + + ATF_REQUIRE(exp_filters == filters); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(parse_filters__duplicate); +ATF_TEST_CASE_BODY(parse_filters__duplicate) +{ + cmdline::args_vector args; + args.push_back("foo/bar//baz"); + args.push_back("hello/world:yes"); + args.push_back("foo//bar/baz"); + ATF_REQUIRE_THROW_RE(cmdline::error, "Duplicate.*'foo/bar/baz'", + cli::parse_filters(args)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(parse_filters__nondisjoint); +ATF_TEST_CASE_BODY(parse_filters__nondisjoint) +{ + cmdline::args_vector args; + args.push_back("foo/bar"); + args.push_back("hello/world:yes"); + args.push_back("foo/bar:baz"); + ATF_REQUIRE_THROW_RE(cmdline::error, "'foo/bar'.*'foo/bar:baz'.*disjoint", + cli::parse_filters(args)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(report_unused_filters__none); +ATF_TEST_CASE_BODY(report_unused_filters__none) +{ + std::set< engine::test_filter > unused; + + cmdline::ui_mock ui; + ATF_REQUIRE(!cli::report_unused_filters(unused, &ui)); + ATF_REQUIRE(ui.out_log().empty()); + ATF_REQUIRE(ui.err_log().empty()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(report_unused_filters__some); +ATF_TEST_CASE_BODY(report_unused_filters__some) +{ + std::set< engine::test_filter > unused; + unused.insert(mkfilter("a/b", "")); + unused.insert(mkfilter("hey/d", "yes")); + + cmdline::ui_mock ui; + cmdline::init("progname"); + ATF_REQUIRE(cli::report_unused_filters(unused, &ui)); + ATF_REQUIRE(ui.out_log().empty()); + ATF_REQUIRE_EQ(2, ui.err_log().size()); + ATF_REQUIRE( atf::utils::grep_collection("No.*matched.*'a/b'", + ui.err_log())); + ATF_REQUIRE( atf::utils::grep_collection("No.*matched.*'hey/d:yes'", + ui.err_log())); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(format_delta); +ATF_TEST_CASE_BODY(format_delta) +{ + ATF_REQUIRE_EQ("0.000s", cli::format_delta(datetime::delta())); + ATF_REQUIRE_EQ("0.012s", cli::format_delta(datetime::delta(0, 12300))); + ATF_REQUIRE_EQ("0.999s", cli::format_delta(datetime::delta(0, 999000))); + ATF_REQUIRE_EQ("51.321s", cli::format_delta(datetime::delta(51, 321000))); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(format_result__no_reason); +ATF_TEST_CASE_BODY(format_result__no_reason) +{ + ATF_REQUIRE_EQ("passed", cli::format_result( + engine::test_result(engine::test_result::passed))); + ATF_REQUIRE_EQ("failed", cli::format_result( + engine::test_result(engine::test_result::failed))); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(format_result__with_reason); +ATF_TEST_CASE_BODY(format_result__with_reason) +{ + ATF_REQUIRE_EQ("broken: Something", cli::format_result( + engine::test_result(engine::test_result::broken, "Something"))); + ATF_REQUIRE_EQ("expected_failure: A B C", cli::format_result( + engine::test_result(engine::test_result::expected_failure, "A B C"))); + ATF_REQUIRE_EQ("failed: More text", cli::format_result( + engine::test_result(engine::test_result::failed, "More text"))); + ATF_REQUIRE_EQ("skipped: Bye", cli::format_result( + engine::test_result(engine::test_result::skipped, "Bye"))); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(format_test_case_id__test_case); +ATF_TEST_CASE_BODY(format_test_case_id__test_case) +{ + const engine::test_program test_program( + "mock", fs::path("foo/bar/baz"), fs::path("unused-root"), + "unused-suite-name", engine::metadata_builder().build()); + const engine::test_case test_case("mock", test_program, "abc", + engine::metadata_builder().build()); + ATF_REQUIRE_EQ("foo/bar/baz:abc", cli::format_test_case_id(test_case)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(format_test_case_id__test_filter); +ATF_TEST_CASE_BODY(format_test_case_id__test_filter) +{ + const engine::test_filter filter(fs::path("foo/bar"), "baz"); + ATF_REQUIRE_EQ("foo/bar:baz", cli::format_test_case_id(filter)); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, build_root_path__default); + ATF_ADD_TEST_CASE(tcs, build_root_path__explicit); + + ATF_ADD_TEST_CASE(tcs, get_home__ok); + ATF_ADD_TEST_CASE(tcs, get_home__missing); + ATF_ADD_TEST_CASE(tcs, get_home__invalid); + + ATF_ADD_TEST_CASE(tcs, kyuafile_path__default); + ATF_ADD_TEST_CASE(tcs, kyuafile_path__explicit); + + ATF_ADD_TEST_CASE(tcs, store_path__default__create_directory__ok); + ATF_ADD_TEST_CASE(tcs, store_path__default__create_directory__fail); + ATF_ADD_TEST_CASE(tcs, store_path__default__no_home); + ATF_ADD_TEST_CASE(tcs, store_path__explicit); + + ATF_ADD_TEST_CASE(tcs, parse_filters__none); + ATF_ADD_TEST_CASE(tcs, parse_filters__ok); + ATF_ADD_TEST_CASE(tcs, parse_filters__duplicate); + ATF_ADD_TEST_CASE(tcs, parse_filters__nondisjoint); + + ATF_ADD_TEST_CASE(tcs, report_unused_filters__none); + ATF_ADD_TEST_CASE(tcs, report_unused_filters__some); + + ATF_ADD_TEST_CASE(tcs, format_delta); + + ATF_ADD_TEST_CASE(tcs, format_result__no_reason); + ATF_ADD_TEST_CASE(tcs, format_result__with_reason); + + ATF_ADD_TEST_CASE(tcs, format_test_case_id__test_case); + ATF_ADD_TEST_CASE(tcs, format_test_case_id__test_filter); +} diff --git a/external/bsd/kyua-cli/dist/cli/config.cpp b/external/bsd/kyua-cli/dist/cli/config.cpp new file mode 100644 index 000000000..3931df774 --- /dev/null +++ b/external/bsd/kyua-cli/dist/cli/config.cpp @@ -0,0 +1,222 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "cli/config.hpp" + +#include "cli/common.hpp" +#include "engine/config.hpp" +#include "engine/exceptions.hpp" +#include "utils/cmdline/parser.ipp" +#include "utils/config/tree.ipp" +#include "utils/format/macros.hpp" +#include "utils/fs/exceptions.hpp" +#include "utils/fs/operations.hpp" +#include "utils/fs/path.hpp" +#include "utils/env.hpp" +#include "utils/logging/macros.hpp" +#include "utils/optional.ipp" + +namespace cmdline = utils::cmdline; +namespace config = utils::config; +namespace fs = utils::fs; + +using utils::optional; + + +namespace { + + +/// Basename of the configuration file. +static const char* config_basename = "kyua.conf"; + + +/// Magic string to disable loading of configuration files. +static const char* none_config = "none"; + + +/// Textual description of the default configuration files. +/// +/// This is just an auxiliary string required to define the option below, which +/// requires a pointer to a static C string. +/// +/// \todo If the user overrides the KYUA_CONFDIR environment variable, we don't +/// reflect this fact here. We don't want to query the variable during program +/// initialization due to the side-effects it may have. Therefore, fixing this +/// is tricky as it may require a whole rethink of this module. +static const std::string config_lookup_names = + (fs::path("~/.kyua") / config_basename).str() + " or " + + (fs::path(KYUA_CONFDIR) / config_basename).str(); + + +/// Loads the configuration file for this session, if any. +/// +/// This is a helper function that does not apply user-specified overrides. See +/// the documentation for cli::load_config() for more details. +/// +/// \param cmdline The parsed command line. +/// +/// \return The loaded configuration file, or the configuration defaults if the +/// loading is disabled. +/// +/// \throw engine::error If the parsing of the configuration file fails. +/// TODO(jmmv): I'm not sure if this is the raised exception. And even if +/// it is, we should make it more accurate. +config::tree +load_config_file(const cmdline::parsed_cmdline& cmdline) +{ + // TODO(jmmv): We should really be able to use cmdline.has_option here to + // detect whether the option was provided or not instead of checking against + // the default value. + const fs::path filename = cmdline.get_option< cmdline::path_option >( + cli::config_option.long_name()); + if (filename.str() == none_config) { + LD("Configuration loading disabled; using defaults"); + return engine::default_config(); + } else if (filename.str() != cli::config_option.default_value()) + return engine::load_config(filename); + + const optional< fs::path > home = cli::get_home(); + if (home) { + const fs::path path = home.get() / ".kyua" / config_basename; + try { + if (fs::exists(path)) + return engine::load_config(path); + } catch (const fs::error& e) { + // Fall through. If we fail to load the user-specific configuration + // file because it cannot be openend, we try to load the system-wide + // one. + LW(F("Failed to load user-specific configuration file '%s': %s") % + path % e.what()); + } + } + + const fs::path confdir(utils::getenv_with_default( + "KYUA_CONFDIR", KYUA_CONFDIR)); + + const fs::path path = confdir / config_basename; + if (fs::exists(path)) { + return engine::load_config(path); + } else { + return engine::default_config(); + } +} + + +/// Loads the configuration file for this session, if any. +/// +/// This is a helper function for cli::load_config() that attempts to load the +/// configuration unconditionally. +/// +/// \param cmdline The parsed command line. +/// +/// \return The loaded configuration file data. +/// +/// \throw engine::error If the parsing of the configuration file fails. +static config::tree +load_required_config(const cmdline::parsed_cmdline& cmdline) +{ + config::tree user_config = load_config_file(cmdline); + + if (cmdline.has_option(cli::variable_option.long_name())) { + typedef std::pair< std::string, std::string > override_pair; + + const std::vector< override_pair >& overrides = + cmdline.get_multi_option< cmdline::property_option >( + cli::variable_option.long_name()); + + for (std::vector< override_pair >::const_iterator + iter = overrides.begin(); iter != overrides.end(); iter++) { + try { + user_config.set_string((*iter).first, (*iter).second); + } catch (const config::error& e) { + // TODO(jmmv): Raising this type from here is obviously the + // wrong thing to do. + throw engine::error(e.what()); + } + } + } + + return user_config; +} + + +} // anonymous namespace + + +/// Standard definition of the option to specify a configuration file. +/// +/// You must use load_config() to load a configuration file while honoring the +/// value of this flag. +const cmdline::path_option cli::config_option( + 'c', "config", + (std::string("Path to the configuration file; '") + none_config + + "' to disable loading").c_str(), + "file", config_lookup_names.c_str()); + + +/// Standard definition of the option to specify a configuration variable. +const cmdline::property_option cli::variable_option( + 'v', "variable", + "Overrides a particular configuration variable", + "K=V"); + + +/// Loads the configuration file for this session, if any. +/// +/// The algorithm implemented here is as follows: +/// 1) If ~/.kyua/kyua.conf exists, load it. +/// 2) Otherwise, if sysconfdir/kyua.conf exists, load it. +/// 3) Otherwise, use the built-in settings. +/// 4) Lastly, apply any user-provided overrides. +/// +/// \param cmdline The parsed command line. +/// \param required Whether the loading of the configuration file must succeed. +/// Some commands should run regardless, and therefore we need to set this +/// to false for those commands. +/// +/// \return The loaded configuration file data. If required was set to false, +/// this might be the default configuration data if the requested file could not +/// be properly loaded. +/// +/// \throw engine::error If the parsing of the configuration file fails. +config::tree +cli::load_config(const cmdline::parsed_cmdline& cmdline, + const bool required) +{ + try { + return load_required_config(cmdline); + } catch (const engine::error& e) { + if (required) { + throw; + } else { + LW(F("Ignoring failure to load configuration because the requested " + "command should not fail: %s") % e.what()); + return engine::default_config(); + } + } +} diff --git a/external/bsd/kyua-cli/dist/cli/config.hpp b/external/bsd/kyua-cli/dist/cli/config.hpp new file mode 100644 index 000000000..55e3f4b52 --- /dev/null +++ b/external/bsd/kyua-cli/dist/cli/config.hpp @@ -0,0 +1,55 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file cli/config.hpp +/// Utility functions to load configuration files. +/// +/// \todo All this should probably just be merged into the main module +/// as nothing else should have access to this. + +#if !defined(CLI_CONFIG_HPP) +#define CLI_CONFIG_HPP + +#include "utils/cmdline/options.hpp" +#include "utils/cmdline/parser.hpp" +#include "utils/config/tree.hpp" + +namespace cli { + + +extern const utils::cmdline::path_option config_option; +extern const utils::cmdline::property_option variable_option; + + +utils::config::tree load_config(const utils::cmdline::parsed_cmdline&, + const bool); + + +} // namespace cli + +#endif // !defined(CLI_CONFIG_HPP) diff --git a/external/bsd/kyua-cli/dist/cli/config_test.cpp b/external/bsd/kyua-cli/dist/cli/config_test.cpp new file mode 100644 index 000000000..bf8c6aca9 --- /dev/null +++ b/external/bsd/kyua-cli/dist/cli/config_test.cpp @@ -0,0 +1,348 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "cli/config.hpp" + +#include + +#include "engine/config.hpp" +#include "engine/exceptions.hpp" +#include "utils/env.hpp" +#include "utils/format/macros.hpp" +#include "utils/fs/operations.hpp" +#include "utils/fs/path.hpp" + +namespace cmdline = utils::cmdline; +namespace config = utils::config; +namespace fs = utils::fs; + + +namespace { + + +/// Creates a configuration file for testing purposes. +/// +/// To ensure that the loaded file is the one created by this function, use +/// validate_mock_config(). +/// +/// \param name The name of the configuration file to create. +/// \param cookie The magic value to set in the configuration file, or NULL if a +/// broken configuration file is desired. +static void +create_mock_config(const char* name, const char* cookie) +{ + if (cookie != NULL) { + atf::utils::create_file( + name, + F("syntax(2)\n" + "test_suites.suite.magic_value = '%s'\n") % cookie); + } else { + atf::utils::create_file(name, "syntax(200)\n"); + } +} + + +/// Creates an invalid system configuration. +/// +/// \param cookie The magic value to set in the configuration file, or NULL if a +/// broken configuration file is desired. +static void +mock_system_config(const char* cookie) +{ + fs::mkdir(fs::path("system-dir"), 0755); + utils::setenv("KYUA_CONFDIR", (fs::current_path() / "system-dir").str()); + create_mock_config("system-dir/kyua.conf", cookie); +} + + +/// Creates an invalid user configuration. +/// +/// \param cookie The magic value to set in the configuration file, or NULL if a +/// broken configuration file is desired. +static void +mock_user_config(const char* cookie) +{ + fs::mkdir(fs::path("user-dir"), 0755); + fs::mkdir(fs::path("user-dir/.kyua"), 0755); + utils::setenv("HOME", (fs::current_path() / "user-dir").str()); + create_mock_config("user-dir/.kyua/kyua.conf", cookie); +} + + +/// Ensures that a loaded configuration was created with create_mock_config(). +/// +/// \param user_config The configuration to validate. +/// \param cookie The magic value to expect in the configuration file. +static void +validate_mock_config(const config::tree& user_config, const char* cookie) +{ + const config::properties_map& properties = user_config.all_properties( + "test_suites.suite", true); + const config::properties_map::const_iterator iter = + properties.find("magic_value"); + ATF_REQUIRE(iter != properties.end()); + ATF_REQUIRE_EQ(cookie, (*iter).second); +} + + +/// Ensures that two configuration trees are equal. +/// +/// \param exp_tree The expected configuration tree. +/// \param actual_tree The configuration tree being validated against exp_tree. +static void +require_eq(const config::tree& exp_tree, const config::tree& actual_tree) +{ + ATF_REQUIRE(exp_tree.all_properties() == actual_tree.all_properties()); +} + + +} // anonymous namespace + + +ATF_TEST_CASE_WITHOUT_HEAD(load_config__none); +ATF_TEST_CASE_BODY(load_config__none) +{ + utils::setenv("KYUA_CONFDIR", "/the/system/does/not/exist"); + utils::setenv("HOME", "/the/user/does/not/exist"); + + std::map< std::string, std::vector< std::string > > options; + options["config"].push_back(cli::config_option.default_value()); + const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector()); + + require_eq(engine::default_config(), + cli::load_config(mock_cmdline, true)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(load_config__explicit__ok); +ATF_TEST_CASE_BODY(load_config__explicit__ok) +{ + mock_system_config(NULL); + mock_user_config(NULL); + + create_mock_config("test-file", "hello"); + + std::map< std::string, std::vector< std::string > > options; + options["config"].push_back("test-file"); + const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector()); + + const config::tree user_config = cli::load_config(mock_cmdline, true); + validate_mock_config(user_config, "hello"); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(load_config__explicit__disable); +ATF_TEST_CASE_BODY(load_config__explicit__disable) +{ + mock_system_config(NULL); + mock_user_config(NULL); + + std::map< std::string, std::vector< std::string > > options; + options["config"].push_back("none"); + const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector()); + + require_eq(engine::default_config(), + cli::load_config(mock_cmdline, true)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(load_config__explicit__fail); +ATF_TEST_CASE_BODY(load_config__explicit__fail) +{ + mock_system_config("ok1"); + mock_user_config("ok2"); + + create_mock_config("test-file", NULL); + + std::map< std::string, std::vector< std::string > > options; + options["config"].push_back("test-file"); + const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector()); + + ATF_REQUIRE_THROW_RE(engine::error, "200", + cli::load_config(mock_cmdline, true)); + + const config::tree config = cli::load_config(mock_cmdline, false); + require_eq(engine::default_config(), config); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(load_config__user__ok); +ATF_TEST_CASE_BODY(load_config__user__ok) +{ + mock_system_config(NULL); + mock_user_config("I am the user config"); + + std::map< std::string, std::vector< std::string > > options; + options["config"].push_back(cli::config_option.default_value()); + const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector()); + + const config::tree user_config = cli::load_config(mock_cmdline, true); + validate_mock_config(user_config, "I am the user config"); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(load_config__user__fail); +ATF_TEST_CASE_BODY(load_config__user__fail) +{ + mock_system_config("valid"); + mock_user_config(NULL); + + std::map< std::string, std::vector< std::string > > options; + options["config"].push_back(cli::config_option.default_value()); + const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector()); + + ATF_REQUIRE_THROW_RE(engine::error, "200", + cli::load_config(mock_cmdline, true)); + + const config::tree config = cli::load_config(mock_cmdline, false); + require_eq(engine::default_config(), config); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(load_config__user__bad_home); +ATF_TEST_CASE_BODY(load_config__user__bad_home) +{ + mock_system_config("Fallback system config"); + utils::setenv("HOME", ""); + + std::map< std::string, std::vector< std::string > > options; + options["config"].push_back(cli::config_option.default_value()); + const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector()); + + const config::tree user_config = cli::load_config(mock_cmdline, true); + validate_mock_config(user_config, "Fallback system config"); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(load_config__system__ok); +ATF_TEST_CASE_BODY(load_config__system__ok) +{ + mock_system_config("I am the system config"); + utils::setenv("HOME", "/the/user/does/not/exist"); + + std::map< std::string, std::vector< std::string > > options; + options["config"].push_back(cli::config_option.default_value()); + const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector()); + + const config::tree user_config = cli::load_config(mock_cmdline, true); + validate_mock_config(user_config, "I am the system config"); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(load_config__system__fail); +ATF_TEST_CASE_BODY(load_config__system__fail) +{ + mock_system_config(NULL); + utils::setenv("HOME", "/the/user/does/not/exist"); + + std::map< std::string, std::vector< std::string > > options; + options["config"].push_back(cli::config_option.default_value()); + const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector()); + + ATF_REQUIRE_THROW_RE(engine::error, "200", + cli::load_config(mock_cmdline, true)); + + const config::tree config = cli::load_config(mock_cmdline, false); + require_eq(engine::default_config(), config); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(load_config__overrides__no); +ATF_TEST_CASE_BODY(load_config__overrides__no) +{ + utils::setenv("KYUA_CONFDIR", fs::current_path().str()); + + std::map< std::string, std::vector< std::string > > options; + options["config"].push_back(cli::config_option.default_value()); + options["variable"].push_back("architecture=1"); + options["variable"].push_back("platform=2"); + const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector()); + + const config::tree user_config = cli::load_config(mock_cmdline, true); + ATF_REQUIRE_EQ("1", + user_config.lookup< config::string_node >("architecture")); + ATF_REQUIRE_EQ("2", + user_config.lookup< config::string_node >("platform")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(load_config__overrides__yes); +ATF_TEST_CASE_BODY(load_config__overrides__yes) +{ + atf::utils::create_file( + "config", + "syntax(2)\n" + "architecture = 'do not see me'\n" + "platform = 'see me'\n"); + + std::map< std::string, std::vector< std::string > > options; + options["config"].push_back("config"); + options["variable"].push_back("architecture=overriden"); + const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector()); + + const config::tree user_config = cli::load_config(mock_cmdline, true); + ATF_REQUIRE_EQ("overriden", + user_config.lookup< config::string_node >("architecture")); + ATF_REQUIRE_EQ("see me", + user_config.lookup< config::string_node >("platform")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(load_config__overrides__fail); +ATF_TEST_CASE_BODY(load_config__overrides__fail) +{ + utils::setenv("KYUA_CONFDIR", fs::current_path().str()); + + std::map< std::string, std::vector< std::string > > options; + options["config"].push_back(cli::config_option.default_value()); + options["variable"].push_back(".a=d"); + const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector()); + + ATF_REQUIRE_THROW_RE(engine::error, "Empty component in key.*'\\.a'", + cli::load_config(mock_cmdline, true)); + + const config::tree config = cli::load_config(mock_cmdline, false); + require_eq(engine::default_config(), config); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, load_config__none); + ATF_ADD_TEST_CASE(tcs, load_config__explicit__ok); + ATF_ADD_TEST_CASE(tcs, load_config__explicit__disable); + ATF_ADD_TEST_CASE(tcs, load_config__explicit__fail); + ATF_ADD_TEST_CASE(tcs, load_config__user__ok); + ATF_ADD_TEST_CASE(tcs, load_config__user__fail); + ATF_ADD_TEST_CASE(tcs, load_config__user__bad_home); + ATF_ADD_TEST_CASE(tcs, load_config__system__ok); + ATF_ADD_TEST_CASE(tcs, load_config__system__fail); + ATF_ADD_TEST_CASE(tcs, load_config__overrides__no); + ATF_ADD_TEST_CASE(tcs, load_config__overrides__yes); + ATF_ADD_TEST_CASE(tcs, load_config__overrides__fail); +} diff --git a/external/bsd/kyua-cli/dist/cli/main.cpp b/external/bsd/kyua-cli/dist/cli/main.cpp new file mode 100644 index 000000000..8263c1f6f --- /dev/null +++ b/external/bsd/kyua-cli/dist/cli/main.cpp @@ -0,0 +1,328 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "cli/main.hpp" + +#if defined(HAVE_CONFIG_H) +# include "config.h" +#endif + +extern "C" { +#include +#include +} + +#include +#include +#include +#include + +#include "cli/cmd_about.hpp" +#include "cli/cmd_config.hpp" +#include "cli/cmd_db_exec.hpp" +#include "cli/cmd_db_migrate.hpp" +#include "cli/cmd_debug.hpp" +#include "cli/cmd_help.hpp" +#include "cli/cmd_list.hpp" +#include "cli/cmd_report.hpp" +#include "cli/cmd_report_html.hpp" +#include "cli/cmd_test.hpp" +#include "cli/common.ipp" +#include "cli/config.hpp" +#include "store/exceptions.hpp" +#include "utils/cmdline/commands_map.ipp" +#include "utils/cmdline/exceptions.hpp" +#include "utils/cmdline/globals.hpp" +#include "utils/cmdline/options.hpp" +#include "utils/cmdline/parser.ipp" +#include "utils/cmdline/ui.hpp" +#include "utils/config/tree.ipp" +#include "utils/env.hpp" +#include "utils/format/macros.hpp" +#include "utils/fs/operations.hpp" +#include "utils/fs/path.hpp" +#include "utils/logging/macros.hpp" +#include "utils/logging/operations.hpp" +#include "utils/optional.ipp" +#include "utils/sanity.hpp" +#include "utils/signals/exceptions.hpp" + +namespace cmdline = utils::cmdline; +namespace config = utils::config; +namespace fs = utils::fs; +namespace logging = utils::logging; +namespace signals = utils::signals; + +using utils::none; +using utils::optional; + + +namespace { + + +/// Executes the given subcommand with proper usage_error reporting. +/// +/// \param ui Object to interact with the I/O of the program. +/// \param command The subcommand to execute. +/// \param args The part of the command line passed to the subcommand. The +/// first item of this collection must match the command name. +/// \param user_config The runtime configuration to pass to the subcommand. +/// +/// \return The exit code of the command. Typically 0 on success, some other +/// integer otherwise. +/// +/// \throw cmdline::usage_error If the user input to the subcommand is invalid. +/// This error does not encode the command name within it, so this function +/// extends the message in the error to specify which subcommand was +/// affected. +/// \throw std::exception This propagates any uncaught exception. Such +/// exceptions are bugs, but we let them propagate so that the runtime will +/// abort and dump core. +static int +run_subcommand(cmdline::ui* ui, cli::cli_command* command, + const cmdline::args_vector& args, + const config::tree& user_config) +{ + try { + PRE(command->name() == args[0]); + return command->main(ui, args, user_config); + } catch (const cmdline::usage_error& e) { + throw std::pair< std::string, cmdline::usage_error >( + command->name(), e); + } +} + + +/// Exception-safe version of main. +/// +/// This function provides the real meat of the entry point of the program. It +/// is allowed to throw some known exceptions which are parsed by the caller. +/// Doing so keeps this function simpler and allow tests to actually validate +/// that the errors reported are accurate. +/// +/// \return The exit code of the program. Should be EXIT_SUCCESS on success and +/// EXIT_FAILURE on failure. The caller extends this to additional integers for +/// errors reported through exceptions. +/// +/// \param ui Object to interact with the I/O of the program. +/// \param argc The number of arguments passed on the command line. +/// \param argv NULL-terminated array containing the command line arguments. +/// \param mock_command An extra command provided for testing purposes; should +/// just be NULL other than for tests. +/// +/// \throw cmdline::usage_error If the user ran the program with invalid +/// arguments. +/// \throw std::exception This propagates any uncaught exception. Such +/// exceptions are bugs, but we let them propagate so that the runtime will +/// abort and dump core. +static int +safe_main(cmdline::ui* ui, int argc, const char* const argv[], + cli::cli_command_ptr mock_command) +{ + cmdline::options_vector options; + options.push_back(&cli::config_option); + options.push_back(&cli::variable_option); + const cmdline::string_option loglevel_option( + "loglevel", "Level of the messages to log", "level", "info"); + options.push_back(&loglevel_option); + const cmdline::path_option logfile_option( + "logfile", "Path to the log file", "file", + cli::detail::default_log_name().c_str()); + options.push_back(&logfile_option); + + cmdline::commands_map< cli::cli_command > commands; + + commands.insert(new cli::cmd_about()); + commands.insert(new cli::cmd_config()); + commands.insert(new cli::cmd_db_exec()); + commands.insert(new cli::cmd_db_migrate()); + commands.insert(new cli::cmd_help(&options, &commands)); + + commands.insert(new cli::cmd_debug(), "Workspace"); + commands.insert(new cli::cmd_list(), "Workspace"); + commands.insert(new cli::cmd_test(), "Workspace"); + + commands.insert(new cli::cmd_report(), "Reporting"); + commands.insert(new cli::cmd_report_html(), "Reporting"); + + if (mock_command.get() != NULL) + commands.insert(mock_command); + + const cmdline::parsed_cmdline cmdline = cmdline::parse(argc, argv, options); + + const fs::path logfile(cmdline.get_option< cmdline::path_option >( + "logfile")); + fs::mkdir_p(logfile.branch_path(), 0755); + LD(F("Log file is %s") % logfile); + utils::install_crash_handlers(logfile.str()); + try { + logging::set_persistency(cmdline.get_option< cmdline::string_option >( + "loglevel"), logfile); + } catch (const std::range_error& e) { + throw cmdline::usage_error(e.what()); + } + + if (cmdline.arguments().empty()) + throw cmdline::usage_error("No command provided"); + const std::string cmdname = cmdline.arguments()[0]; + + const config::tree user_config = cli::load_config(cmdline, + cmdname != "help"); + + cli::cli_command* command = commands.find(cmdname); + if (command == NULL) + throw cmdline::usage_error(F("Unknown command '%s'") % cmdname); + return run_subcommand(ui, command, cmdline.arguments(), user_config); +} + + +} // anonymous namespace + + +/// Gets the name of the default log file. +/// +/// \return The path to the log file. +fs::path +cli::detail::default_log_name(void) +{ + // Update doc/troubleshooting.texi if you change this algorithm. + const optional< std::string > home(utils::getenv("HOME")); + if (home) { + return logging::generate_log_name(fs::path(home.get()) / ".kyua" / + "logs", cmdline::progname()); + } else { + const optional< std::string > tmpdir(utils::getenv("TMPDIR")); + if (tmpdir) { + return logging::generate_log_name(fs::path(tmpdir.get()), + cmdline::progname()); + } else { + return logging::generate_log_name(fs::path("/tmp"), + cmdline::progname()); + } + } +} + + +/// Testable entry point, with catch-all exception handlers. +/// +/// This entry point does not perform any initialization of global state; it is +/// provided to allow unit-testing of the utility's entry point. +/// +/// \param ui Object to interact with the I/O of the program. +/// \param argc The number of arguments passed on the command line. +/// \param argv NULL-terminated array containing the command line arguments. +/// \param mock_command An extra command provided for testing purposes; should +/// just be NULL other than for tests. +/// +/// \return 0 on success, some other integer on error. +/// +/// \throw std::exception This propagates any uncaught exception. Such +/// exceptions are bugs, but we let them propagate so that the runtime will +/// abort and dump core. +int +cli::main(cmdline::ui* ui, const int argc, const char* const* const argv, + cli_command_ptr mock_command) +{ + try { + const int exit_code = safe_main(ui, argc, argv, mock_command); + + // Codes above 1 are reserved to report conditions captured as + // exceptions below. + INV(exit_code == EXIT_SUCCESS || exit_code == EXIT_FAILURE); + + return exit_code; + } catch (const signals::interrupted_error& e) { + cmdline::print_error(ui, e.what()); + // Re-deliver the interruption signal to self so that we terminate with + // the right status. At this point we should NOT have any custom signal + // handlers in place. + ::kill(getpid(), e.signo()); + LD("Interrupt signal re-delivery did not terminate program"); + // If we reach this, something went wrong because we did not exit as + // intended. Return an internal error instead. (Would be nicer to + // abort in principle, but it wouldn't be a nice experience if it ever + // happened.) + return 2; + } catch (const std::pair< std::string, cmdline::usage_error >& e) { + const std::string message = F("Usage error for command %s: %s.") % + e.first % e.second.what(); + LE(message); + ui->err(message); + ui->err(F("Type '%s help %s' for usage information.") % + cmdline::progname() % e.first); + return 3; + } catch (const cmdline::usage_error& e) { + const std::string message = F("Usage error: %s.") % e.what(); + LE(message); + ui->err(message); + ui->err(F("Type '%s help' for usage information.") % + cmdline::progname()); + return 3; + } catch (const store::old_schema_error& e) { + const std::string message = F("The database has schema version %s, " + "which is too old; please use db-migrate " + "to upgrade it") % e.old_version(); + cmdline::print_error(ui, message); + return 2; + } catch (const std::runtime_error& e) { + cmdline::print_error(ui, e.what()); + return 2; + } +} + + +/// Delegate for ::main(). +/// +/// This function is supposed to be called directly from the top-level ::main() +/// function. It takes care of initializing internal libraries and then calls +/// main(ui, argc, argv). +/// +/// \pre This function can only be called once. +/// +/// \throw std::exception This propagates any uncaught exception. Such +/// exceptions are bugs, but we let them propagate so that the runtime will +/// abort and dump core. +int +cli::main(const int argc, const char* const* const argv) +{ + logging::set_inmemory(); + + LI(F("%s %s") % PACKAGE % VERSION); + + std::string plain_args; + for (const char* const* arg = argv; *arg != NULL; arg++) + plain_args += F(" %s") % *arg; + LI(F("Command line:%s") % plain_args); + + cmdline::init(argv[0]); + cmdline::ui ui; + + const int exit_code = main(&ui, argc, argv); + LI(F("Clean exit with code %s") % exit_code); + return exit_code; +} diff --git a/external/bsd/kyua-cli/dist/cli/main.hpp b/external/bsd/kyua-cli/dist/cli/main.hpp new file mode 100644 index 000000000..bd0b53009 --- /dev/null +++ b/external/bsd/kyua-cli/dist/cli/main.hpp @@ -0,0 +1,67 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file cli/main.hpp +/// Entry point for the program. +/// +/// These entry points are separate from the top-level ::main() function to +/// allow unit-testing of the main code. + +#if !defined(CLI_MAIN_HPP) +#define CLI_MAIN_HPP + +#include "cli/common.hpp" +#include "utils/cmdline/ui.hpp" + +namespace utils { +namespace fs { +class path; +} // namespace fs +} // namespace utils + +namespace cli { + + +namespace detail { + + +utils::fs::path default_log_name(void); + + +} // namespace detail + + +int main(utils::cmdline::ui*, const int, const char* const* const, + cli_command_ptr = cli_command_ptr()); +int main(const int, const char* const* const); + + +} // namespace cli + + +#endif // !defined(CLI_MAIN_HPP) diff --git a/external/bsd/kyua-cli/dist/cli/main_test.cpp b/external/bsd/kyua-cli/dist/cli/main_test.cpp new file mode 100644 index 000000000..1c10ec9bc --- /dev/null +++ b/external/bsd/kyua-cli/dist/cli/main_test.cpp @@ -0,0 +1,501 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "cli/main.hpp" + +extern "C" { +#include +} + +#include + +#include + +#include "utils/cmdline/base_command.ipp" +#include "utils/cmdline/exceptions.hpp" +#include "utils/cmdline/globals.hpp" +#include "utils/cmdline/options.hpp" +#include "utils/cmdline/parser.hpp" +#include "utils/cmdline/ui_mock.hpp" +#include "utils/datetime.hpp" +#include "utils/defs.hpp" +#include "utils/env.hpp" +#include "utils/fs/operations.hpp" +#include "utils/fs/path.hpp" +#include "utils/logging/macros.hpp" +#include "utils/logging/operations.hpp" +#include "utils/process/child.ipp" +#include "utils/process/status.hpp" + +namespace cmdline = utils::cmdline; +namespace config = utils::config; +namespace datetime = utils::datetime; +namespace fs = utils::fs; +namespace logging = utils::logging; +namespace process = utils::process; + + +namespace { + + +/// Fake command implementation that crashes during its execution. +class cmd_mock_crash : public cli::cli_command { +public: + /// Constructs a new mock command. + /// + /// All command parameters are set to irrelevant values. + cmd_mock_crash(void) : + cli::cli_command("mock_error", "", 0, 0, "Mock command that crashes") + { + } + + /// Runs the mock command. + /// + /// \param unused_ui Object to interact with the I/O of the program. + /// \param unused_cmdline Representation of the command line to the + /// subcommand. + /// \param unused_user_config The runtime configuration of the program. + /// + /// \return Nothing because this function always aborts. + int + run(cmdline::ui* UTILS_UNUSED_PARAM(ui), + const cmdline::parsed_cmdline& UTILS_UNUSED_PARAM(cmdline), + const config::tree& UTILS_UNUSED_PARAM(user_config)) + { + std::abort(); + } +}; + + +/// Fake command implementation that throws an exception during its execution. +class cmd_mock_error : public cli::cli_command { + /// Whether the command raises an exception captured by the parent or not. + /// + /// If this is true, the command will raise a std::runtime_error exception + /// or a subclass of it. The main program is in charge of capturing these + /// and reporting them appropriately. If false, this raises another + /// exception that does not inherit from std::runtime_error. + bool _unhandled; + +public: + /// Constructs a new mock command. + /// + /// \param unhandled If true, make run raise an exception not catched by the + /// main program. + cmd_mock_error(const bool unhandled) : + cli::cli_command("mock_error", "", 0, 0, + "Mock command that raises an error"), + _unhandled(unhandled) + { + } + + /// Runs the mock command. + /// + /// \param unused_ui Object to interact with the I/O of the program. + /// \param unused_cmdline Representation of the command line to the + /// subcommand. + /// \param unused_user_config The runtime configuration of the program. + /// + /// \return Nothing because this function always aborts. + /// + /// \throw std::logic_error If _unhandled is true. + /// \throw std::runtime_error If _unhandled is false. + int + run(cmdline::ui* UTILS_UNUSED_PARAM(ui), + const cmdline::parsed_cmdline& UTILS_UNUSED_PARAM(cmdline), + const config::tree& UTILS_UNUSED_PARAM(user_config)) + { + if (_unhandled) + throw std::logic_error("This is unhandled"); + else + throw std::runtime_error("Runtime error"); + } +}; + + +/// Fake command implementation that prints messages during its execution. +class cmd_mock_write : public cli::cli_command { +public: + /// Constructs a new mock command. + /// + /// All command parameters are set to irrelevant values. + cmd_mock_write(void) : cli::cli_command( + "mock_write", "", 0, 0, "Mock command that prints output") + { + } + + /// Runs the mock command. + /// + /// \param ui Object to interact with the I/O of the program. + /// \param unused_cmdline Representation of the command line to the + /// subcommand. + /// \param unused_user_config The runtime configuration of the program. + /// + /// \return Nothing because this function always aborts. + int + run(cmdline::ui* ui, + const cmdline::parsed_cmdline& UTILS_UNUSED_PARAM(cmdline), + const config::tree& UTILS_UNUSED_PARAM(user_config)) + { + ui->out("stdout message from subcommand"); + ui->err("stderr message from subcommand"); + return EXIT_FAILURE; + } +}; + + +} // anonymous namespace + + +ATF_TEST_CASE_WITHOUT_HEAD(detail__default_log_name__home); +ATF_TEST_CASE_BODY(detail__default_log_name__home) +{ + datetime::set_mock_now(2011, 2, 21, 21, 10, 30, 0); + cmdline::init("progname1"); + + utils::setenv("HOME", "/home//fake"); + utils::setenv("TMPDIR", "/do/not/use/this"); + ATF_REQUIRE_EQ( + fs::path("/home/fake/.kyua/logs/progname1.20110221-211030.log"), + cli::detail::default_log_name()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(detail__default_log_name__tmpdir); +ATF_TEST_CASE_BODY(detail__default_log_name__tmpdir) +{ + datetime::set_mock_now(2011, 2, 21, 21, 10, 50, 987); + cmdline::init("progname2"); + + utils::unsetenv("HOME"); + utils::setenv("TMPDIR", "/a/b//c"); + ATF_REQUIRE_EQ(fs::path("/a/b/c/progname2.20110221-211050.log"), + cli::detail::default_log_name()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(detail__default_log_name__hardcoded); +ATF_TEST_CASE_BODY(detail__default_log_name__hardcoded) +{ + datetime::set_mock_now(2011, 2, 21, 21, 15, 00, 123456); + cmdline::init("progname3"); + + utils::unsetenv("HOME"); + utils::unsetenv("TMPDIR"); + ATF_REQUIRE_EQ(fs::path("/tmp/progname3.20110221-211500.log"), + cli::detail::default_log_name()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(main__no_args); +ATF_TEST_CASE_BODY(main__no_args) +{ + logging::set_inmemory(); + cmdline::init("progname"); + + const int argc = 1; + const char* const argv[] = {"progname", NULL}; + + cmdline::ui_mock ui; + ATF_REQUIRE_EQ(3, cli::main(&ui, argc, argv)); + ATF_REQUIRE(ui.out_log().empty()); + ATF_REQUIRE(atf::utils::grep_collection("Usage error: No command provided", + ui.err_log())); + ATF_REQUIRE(atf::utils::grep_collection("Type.*progname help", + ui.err_log())); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(main__unknown_command); +ATF_TEST_CASE_BODY(main__unknown_command) +{ + logging::set_inmemory(); + cmdline::init("progname"); + + const int argc = 2; + const char* const argv[] = {"progname", "foo", NULL}; + + cmdline::ui_mock ui; + ATF_REQUIRE_EQ(3, cli::main(&ui, argc, argv)); + ATF_REQUIRE(ui.out_log().empty()); + ATF_REQUIRE(atf::utils::grep_collection("Usage error: Unknown command.*foo", + ui.err_log())); + ATF_REQUIRE(atf::utils::grep_collection("Type.*progname help", + ui.err_log())); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(main__logfile__default); +ATF_TEST_CASE_BODY(main__logfile__default) +{ + logging::set_inmemory(); + datetime::set_mock_now(2011, 2, 21, 21, 30, 00, 0); + cmdline::init("progname"); + + const int argc = 1; + const char* const argv[] = {"progname", NULL}; + + cmdline::ui_mock ui; + ATF_REQUIRE(!fs::exists(fs::path( + ".kyua/logs/progname.20110221-213000.log"))); + ATF_REQUIRE_EQ(3, cli::main(&ui, argc, argv)); + ATF_REQUIRE(fs::exists(fs::path( + ".kyua/logs/progname.20110221-213000.log"))); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(main__logfile__override); +ATF_TEST_CASE_BODY(main__logfile__override) +{ + logging::set_inmemory(); + datetime::set_mock_now(2011, 2, 21, 21, 30, 00, 321); + cmdline::init("progname"); + + const int argc = 2; + const char* const argv[] = {"progname", "--logfile=test.log", NULL}; + + cmdline::ui_mock ui; + ATF_REQUIRE(!fs::exists(fs::path("test.log"))); + ATF_REQUIRE_EQ(3, cli::main(&ui, argc, argv)); + ATF_REQUIRE(!fs::exists(fs::path( + ".kyua/logs/progname.20110221-213000.log"))); + ATF_REQUIRE(fs::exists(fs::path("test.log"))); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(main__loglevel__default); +ATF_TEST_CASE_BODY(main__loglevel__default) +{ + logging::set_inmemory(); + cmdline::init("progname"); + + const int argc = 2; + const char* const argv[] = {"progname", "--logfile=test.log", NULL}; + + LD("Mock debug message"); + LE("Mock error message"); + LI("Mock info message"); + LW("Mock warning message"); + + cmdline::ui_mock ui; + ATF_REQUIRE_EQ(3, cli::main(&ui, argc, argv)); + ATF_REQUIRE(!atf::utils::grep_file("Mock debug message", "test.log")); + ATF_REQUIRE(atf::utils::grep_file("Mock error message", "test.log")); + ATF_REQUIRE(atf::utils::grep_file("Mock info message", "test.log")); + ATF_REQUIRE(atf::utils::grep_file("Mock warning message", "test.log")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(main__loglevel__higher); +ATF_TEST_CASE_BODY(main__loglevel__higher) +{ + logging::set_inmemory(); + cmdline::init("progname"); + + const int argc = 3; + const char* const argv[] = {"progname", "--logfile=test.log", + "--loglevel=debug", NULL}; + + LD("Mock debug message"); + LE("Mock error message"); + LI("Mock info message"); + LW("Mock warning message"); + + cmdline::ui_mock ui; + ATF_REQUIRE_EQ(3, cli::main(&ui, argc, argv)); + ATF_REQUIRE(atf::utils::grep_file("Mock debug message", "test.log")); + ATF_REQUIRE(atf::utils::grep_file("Mock error message", "test.log")); + ATF_REQUIRE(atf::utils::grep_file("Mock info message", "test.log")); + ATF_REQUIRE(atf::utils::grep_file("Mock warning message", "test.log")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(main__loglevel__lower); +ATF_TEST_CASE_BODY(main__loglevel__lower) +{ + logging::set_inmemory(); + cmdline::init("progname"); + + const int argc = 3; + const char* const argv[] = {"progname", "--logfile=test.log", + "--loglevel=warning", NULL}; + + LD("Mock debug message"); + LE("Mock error message"); + LI("Mock info message"); + LW("Mock warning message"); + + cmdline::ui_mock ui; + ATF_REQUIRE_EQ(3, cli::main(&ui, argc, argv)); + ATF_REQUIRE(!atf::utils::grep_file("Mock debug message", "test.log")); + ATF_REQUIRE(atf::utils::grep_file("Mock error message", "test.log")); + ATF_REQUIRE(!atf::utils::grep_file("Mock info message", "test.log")); + ATF_REQUIRE(atf::utils::grep_file("Mock warning message", "test.log")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(main__loglevel__error); +ATF_TEST_CASE_BODY(main__loglevel__error) +{ + logging::set_inmemory(); + cmdline::init("progname"); + + const int argc = 3; + const char* const argv[] = {"progname", "--logfile=test.log", + "--loglevel=i-am-invalid", NULL}; + + cmdline::ui_mock ui; + ATF_REQUIRE_EQ(3, cli::main(&ui, argc, argv)); + ATF_REQUIRE(atf::utils::grep_collection("Usage error.*i-am-invalid", + ui.err_log())); + ATF_REQUIRE(!fs::exists(fs::path("test.log"))); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(main__subcommand__ok); +ATF_TEST_CASE_BODY(main__subcommand__ok) +{ + logging::set_inmemory(); + cmdline::init("progname"); + + const int argc = 2; + const char* const argv[] = {"progname", "mock_write", NULL}; + + cmdline::ui_mock ui; + ATF_REQUIRE_EQ(EXIT_FAILURE, + cli::main(&ui, argc, argv, + cli::cli_command_ptr(new cmd_mock_write()))); + ATF_REQUIRE_EQ(1, ui.out_log().size()); + ATF_REQUIRE_EQ("stdout message from subcommand", ui.out_log()[0]); + ATF_REQUIRE_EQ(1, ui.err_log().size()); + ATF_REQUIRE_EQ("stderr message from subcommand", ui.err_log()[0]); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(main__subcommand__invalid_args); +ATF_TEST_CASE_BODY(main__subcommand__invalid_args) +{ + logging::set_inmemory(); + cmdline::init("progname"); + + const int argc = 3; + const char* const argv[] = {"progname", "mock_write", "bar", NULL}; + + cmdline::ui_mock ui; + ATF_REQUIRE_EQ(3, + cli::main(&ui, argc, argv, + cli::cli_command_ptr(new cmd_mock_write()))); + ATF_REQUIRE(ui.out_log().empty()); + ATF_REQUIRE(atf::utils::grep_collection( + "Usage error for command mock_write: Too many arguments.", + ui.err_log())); + ATF_REQUIRE(atf::utils::grep_collection("Type.*progname help", + ui.err_log())); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(main__subcommand__runtime_error); +ATF_TEST_CASE_BODY(main__subcommand__runtime_error) +{ + logging::set_inmemory(); + cmdline::init("progname"); + + const int argc = 2; + const char* const argv[] = {"progname", "mock_error", NULL}; + + cmdline::ui_mock ui; + ATF_REQUIRE_EQ(2, cli::main(&ui, argc, argv, + cli::cli_command_ptr(new cmd_mock_error(false)))); + ATF_REQUIRE(ui.out_log().empty()); + ATF_REQUIRE(atf::utils::grep_collection("progname: E: Runtime error.", + ui.err_log())); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(main__subcommand__unhandled_exception); +ATF_TEST_CASE_BODY(main__subcommand__unhandled_exception) +{ + logging::set_inmemory(); + cmdline::init("progname"); + + const int argc = 2; + const char* const argv[] = {"progname", "mock_error", NULL}; + + cmdline::ui_mock ui; + ATF_REQUIRE_THROW(std::logic_error, cli::main(&ui, argc, argv, + cli::cli_command_ptr(new cmd_mock_error(true)))); +} + + +static void +do_subcommand_crash(void) +{ + logging::set_inmemory(); + cmdline::init("progname"); + + const int argc = 2; + const char* const argv[] = {"progname", "mock_error", NULL}; + + cmdline::ui_mock ui; + cli::main(&ui, argc, argv, + cli::cli_command_ptr(new cmd_mock_crash())); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(main__subcommand__crash); +ATF_TEST_CASE_BODY(main__subcommand__crash) +{ + const process::status status = process::child::fork_files( + do_subcommand_crash, fs::path("stdout.txt"), + fs::path("stderr.txt"))->wait(); + ATF_REQUIRE(status.signaled()); + ATF_REQUIRE_EQ(SIGABRT, status.termsig()); + ATF_REQUIRE(atf::utils::grep_file("Fatal signal", "stderr.txt")); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, detail__default_log_name__home); + ATF_ADD_TEST_CASE(tcs, detail__default_log_name__tmpdir); + ATF_ADD_TEST_CASE(tcs, detail__default_log_name__hardcoded); + + ATF_ADD_TEST_CASE(tcs, main__no_args); + ATF_ADD_TEST_CASE(tcs, main__unknown_command); + ATF_ADD_TEST_CASE(tcs, main__logfile__default); + ATF_ADD_TEST_CASE(tcs, main__logfile__override); + ATF_ADD_TEST_CASE(tcs, main__loglevel__default); + ATF_ADD_TEST_CASE(tcs, main__loglevel__higher); + ATF_ADD_TEST_CASE(tcs, main__loglevel__lower); + ATF_ADD_TEST_CASE(tcs, main__loglevel__error); + ATF_ADD_TEST_CASE(tcs, main__subcommand__ok); + ATF_ADD_TEST_CASE(tcs, main__subcommand__invalid_args); + ATF_ADD_TEST_CASE(tcs, main__subcommand__runtime_error); + ATF_ADD_TEST_CASE(tcs, main__subcommand__unhandled_exception); + ATF_ADD_TEST_CASE(tcs, main__subcommand__crash); +} diff --git a/external/bsd/kyua-cli/dist/doc/kyua-about.1.in b/external/bsd/kyua-cli/dist/doc/kyua-about.1.in new file mode 100644 index 000000000..2461b41b8 --- /dev/null +++ b/external/bsd/kyua-cli/dist/doc/kyua-about.1.in @@ -0,0 +1,93 @@ +.\" Copyright 2012 Google Inc. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are +.\" met: +.\" +.\" * Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" * Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" * Neither the name of Google Inc. nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.Dd September 9, 2012 +.Dt KYUA-ABOUT 1 +.Os +.Sh NAME +.Nm about +.Nd Shows general program information +.Sh SYNOPSIS +.Nm +.Op Ar authors | license | version +.Sh DESCRIPTION +The +.Sq about +command provides generic information about the +.Xr kyua 1 +tool. +In the default synopsis form (no arguments), the information printed +includes: +.Bl -enum +.It +The name of the package, which is +.Sq __PACKAGE__ . +.It +The version number, which is +.Sq __VERSION__ . +.It +License information. +.It +Authors information. +.It +A link to the project web site. +.El +.Pp +You can customize the information printed by this command by specifying +the desired topic as the single argument to the command. +This can be one of: +.Bl -tag -width authorsXX +.It Ar authors +Displays the list of authors and contributors only. +.It Ar license +Displays the license information and the list of copyrights. +.It Ar version +Displays the package name and the version number in a format that is +compatible with the output of GNU tools that support a +.Fl -version +flag. +Use this whenever you have to query the version number of the package. +.El +.Sh FILES +The following files are read by the +.Nm +command: +.Bl -tag -width XX +.It Pa __DOCDIR__/AUTHORS +List of authors and contributors. +.It Pa __DOCDIR__/COPYING +License information. +.El +.Sh EXIT STATUS +The +.Nm +command always returns 0. +.Pp +Additional exit codes may be returned as described in +.Xr kyua 1 . +.Sh SEE ALSO +.Xr kyua 1 diff --git a/external/bsd/kyua-cli/dist/doc/kyua-build-root.7.in b/external/bsd/kyua-cli/dist/doc/kyua-build-root.7.in new file mode 100644 index 000000000..e9760ea19 --- /dev/null +++ b/external/bsd/kyua-cli/dist/doc/kyua-build-root.7.in @@ -0,0 +1,114 @@ +.\" Copyright 2012 Google Inc. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are +.\" met: +.\" +.\" * Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" * Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" * Neither the name of Google Inc. nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.Dd September 9, 2012 +.Dt KYUA-BUILD-ROOT 7 +.Os +.Sh NAME +.Nm build-root +.Nd Mechanics of build directories +.Sh DESCRIPTION +.Em Build directories +(or object directories, target directories, product directories, etc.) is +the concept that allows a developer to keep the source tree clean from +build products by asking the build system to place such build products +under a separate subtree. +.Pp +Most build systems today support build directories. For example, the GNU +Automake/Autoconf build system exposes such concept when invoked as +follows: +.Bd -literal -offset indent +$ cd my-project-1.0 +$ mkdir build +$ cd build +$ ../configure +$ make +.Ed +.Pp +Under such invocation, all the results of the build are left in the +.Pa my-project-1.0/build/ +subdirectory while maintaining the contents of +.Pa my-project-1.0/ +intact. +.Pp +Because build directories are an integral part of most build systems, and +because they are a tool that developers use frequently, +.Xr kyua 1 +supports build directories too. This manifests in the form of +.Xr kyua 1 +being able to run tests from build directories while reading the (often +immutable) test suite definition from the source tree. +.Pp +One important property of build directories is that they follow (or need to +follow) the exact same layout as the source tree. For example, consider +the following directory listings: +.Bd -literal -offset indent +src/Kyuafile +src/bin/ls/ +src/bin/ls/Kyuafile +src/bin/ls/ls.c +src/bin/ls/ls_test.c +src/sbin/su/ +src/sbin/su/Kyuafile +src/sbin/su/su.c +src/sbin/su/su_test.c + +obj/bin/ls/ +obj/bin/ls/ls* +obj/bin/ls/ls_test* +obj/sbin/su/ +obj/sbin/su/su* +obj/sbin/su/su_test* +.Ed +.Pp +Note how the directory layout within +.Pa src/ +matches that of +.Pa obj/ . +The +.Pa src/ +directory contains only source files and the definition of the test suite +(the Kyuafiles), while the +.Pa obj/ +directory contains only the binaries generated during a build. +.Pp +All commands that deal with the workspace support the +.Fl -build-root Ar path +option. When this option is provided, the directory specified by the +option is considered to be the root of the build directory. For example, +considering our previous fake tree layout, we could invoke +.Xr kyua-test 1 +as any of the following: +.Bd -literal -offset indent +$ kyua test --kyuafile=src/Kyuafile --build-root=obj +$ cd src && kyua test --build-root=../obj +.Ed +.Sh SEE ALSO +.Xr kyua 1 , +.Xr kyua-debug 1 , +.Xr kyua-list 1 , +.Xr kyua-test 1 diff --git a/external/bsd/kyua-cli/dist/doc/kyua-config.1.in b/external/bsd/kyua-cli/dist/doc/kyua-config.1.in new file mode 100644 index 000000000..1d7f06cb4 --- /dev/null +++ b/external/bsd/kyua-cli/dist/doc/kyua-config.1.in @@ -0,0 +1,59 @@ +.\" Copyright 2012 Google Inc. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are +.\" met: +.\" +.\" * Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" * Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" * Neither the name of Google Inc. nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.Dd September 9, 2012 +.Dt KYUA-CONFIG 1 +.Os +.Sh NAME +.Nm config +.Nd Inspects the values of the loaded configuration +.Sh SYNOPSIS +.Nm +.Op Ar variable1 .. variableN +.Sh DESCRIPTION +The +.Nm +command provides a way to list all defined configuration variables and +their current values. +.Pp +This command is intended to help you in resolving the values of the +configuration variables without having to scan over configuration files. +.Pp +In the default synopsis form (no arguments), the command prints all +configuration variables. +If any arguments are provided, the command will only print the +requested variables. +.Sh EXIT STATUS +The +.Nm +command returns 0 on success or 1 if any of the specified configuration +variables does not exist. +.Pp +Additional exit codes may be returned as described in +.Xr kyua 1 . +.Sh SEE ALSO +.Xr kyua 1 diff --git a/external/bsd/kyua-cli/dist/doc/kyua-db-exec.1.in b/external/bsd/kyua-cli/dist/doc/kyua-db-exec.1.in new file mode 100644 index 000000000..b422045d6 --- /dev/null +++ b/external/bsd/kyua-cli/dist/doc/kyua-db-exec.1.in @@ -0,0 +1,73 @@ +.\" Copyright 2012 Google Inc. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are +.\" met: +.\" +.\" * Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" * Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" * Neither the name of Google Inc. nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.Dd September 9, 2012 +.Dt KYUA-DB-EXEC 1 +.Os +.Sh NAME +.Nm db-exec +.Nd Executes a SQL statement in the store database +.Sh SYNOPSIS +.Nm +.Op Fl -no-headers +.Op Fl -store Ar file +.Ar statement +.Sh DESCRIPTION +The +.Nm +command provides a way to execute an arbitrary SQL statement within the +database. This command is mostly intended to aid in debugging, but can +also be used to extract information from the database when the current +interfaces do not provide the desired functionality. +.Pp +The +.Nm +command takes one or more arguments, all of which are concatenated to form +a single SQL statement. Once the staement is executed, +.Nm +prints the resulting table on the screen, if any. +.Pp +The following subcommand options are recognized: +.Bl -tag -width XX +.It Fl -no-headers +Avoids printing the headers of the table in the output of the command. +.It Fl -store Ar path , Fl s Ar path +Specifies the database to use. Defaults to +.Pa ~/.kyua/store.db . +The database is created if it does not exist. +.El +.Sh EXIT STATUS +The +.Nm +command returns 0 on success or 1 if the SQL statement is invalid or fails +to run. +.Pp +Additional exit codes may be returned as described in +.Xr kyua 1 . +.Sh SEE ALSO +.Xr kyua 1 , +.Xr kyua-test 1 diff --git a/external/bsd/kyua-cli/dist/doc/kyua-db-migrate.1.in b/external/bsd/kyua-cli/dist/doc/kyua-db-migrate.1.in new file mode 100644 index 000000000..5a015c7aa --- /dev/null +++ b/external/bsd/kyua-cli/dist/doc/kyua-db-migrate.1.in @@ -0,0 +1,60 @@ +.\" Copyright 2013 Google Inc. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are +.\" met: +.\" +.\" * Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" * Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" * Neither the name of Google Inc. nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.Dd January 25, 2013 +.Dt KYUA-DB-MIGRATE 1 +.Os +.Sh NAME +.Nm db-migrate +.Nd Upgrades the schema of an existing database +.Sh SYNOPSIS +.Nm +.Op Fl -store Ar file +.Sh DESCRIPTION +The +.Nm +command migrates the schema of an existing database to the latest +version implemented in +.Xr kyua 1 . +.Pp +This operation is not reversible. However, a backup of the database is +created in the same directory where the database lives. +.Pp +The following subcommand options are recognized: +.Bl -tag -width XX +.It Fl -store Ar path , Fl s Ar path +Specifies the database to use. +.El +.Sh EXIT STATUS +The +.Nm +command returns 0 on success or 1 if the migration fails. +.Pp +Additional exit codes may be returned as described in +.Xr kyua 1 . +.Sh SEE ALSO +.Xr kyua 1 diff --git a/external/bsd/kyua-cli/dist/doc/kyua-debug.1.in b/external/bsd/kyua-cli/dist/doc/kyua-debug.1.in new file mode 100644 index 000000000..74a2ff5fc --- /dev/null +++ b/external/bsd/kyua-cli/dist/doc/kyua-debug.1.in @@ -0,0 +1,127 @@ +.\" Copyright 2012 Google Inc. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are +.\" met: +.\" +.\" * Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" * Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" * Neither the name of Google Inc. nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.Dd September 9, 2012 +.Dt KYUA-DEBUG 1 +.Os +.Sh NAME +.Nm debug +.Nd Executes a single test case with facilities for debugging +.Sh SYNOPSIS +.Nm +.Op Fl -build-root Ar path +.Op Fl -kyuafile Ar file +.Op Fl -stdout Ar path +.Op Fl -stderr Ar path +.Ar test_case +.Sh DESCRIPTION +The +.Nm +command provides a mechanism to execute a single test case bypassing some +of the Kyua infrastructure and allowing the user to poke into the execution +behavior of the test. +.Pp +The test case to run is selected by providing a test filter that matches a +single test case; see +.Xr kyua-test-filters 7 . +The test case is executed and its result is printed as the last line of the +output of the tool. +.Pp +At the moment, the +.Nm +command allows the following aspects of a test case execution to be +tweaked: +.Bl -bullet +.It +Redirection of the test case's stdout and stderr to the console (the +default) or to arbitraty files. See the +.Fl -stdout +and +.Fl -stderr +options below. +.El +.Pp +The following subcommand options are recognized: +.Bl -tag -width XX +.It Fl -build-root Ar path +Specifies the build root in which to find the test programs referenced +by the Kyuafile, if different from the Kyuafile's directory. See +.Xr kyua-build-root 7 +for more information. +.It Fl -kyuafile Ar file , Fl k Ar file +Specifies the Kyuafile to process. Defaults to +.Pa Kyuafile +file in the current directory. +.It Fl -stderr Ar path +Specifies the file to which to send the standard error of the test +program's body. The default is +.Pa /dev/stderr , +which is a special that redirects the output to the console. +.It Fl -stdout Ar path +Specifies the file to which to send the standard output of the test +program's body. The default is +.Pa /dev/stdout , +which is a special that redirects the output to the console. +.El +.Pp +For example, consider the following Kyua session: +.Bd -literal -offset indent +$ kyua test +kernel/fs:mkdir -> passed +kernel/fs:rmdir -> failed: Invalid argument + +1/2 passed (1 failed) +.Ed +.Pp +At this point, we do not have a lot of information regarding the +failure of the +.Sq kernel/fs:rmdir +test. We can run this test through the +.Nm +command to inspect its output a bit closer, hoping that the test case is +kind enough to log its progress: +.Bd -literal -offset indent +$ kyua debug kernel/fs:rmdir +Trying rmdir('foo') +Trying rmdir(NULL) +kernel/fs:rmdir -> failed: Invalid argument +.Ed +.Pp +Luckily, the offending test case was printing status lines as it +progressed, so we could see the last attempted call and we can know match +the failure message to the problem. +.Sh EXIT STATUS +The +.Nm +command returns 0 if the test case passes or 1 if the test case fails. +.Pp +Additional exit codes may be returned as described in +.Xr kyua 1 . +.Sh SEE ALSO +.Xr kyua 1 , +.Xr kyua-build-root 7 , +.Xr kyua-test-filters 7 diff --git a/external/bsd/kyua-cli/dist/doc/kyua-help.1.in b/external/bsd/kyua-cli/dist/doc/kyua-help.1.in new file mode 100644 index 000000000..c1c9e6157 --- /dev/null +++ b/external/bsd/kyua-cli/dist/doc/kyua-help.1.in @@ -0,0 +1,63 @@ +.\" Copyright 2012 Google Inc. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are +.\" met: +.\" +.\" * Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" * Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" * Neither the name of Google Inc. nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.Dd September 9, 2012 +.Dt KYUA-HELP 1 +.Os +.Sh NAME +.Nm help +.Nd Shows usage information +.Sh SYNOPSIS +.Nm +.Op Ar command +.Sh DESCRIPTION +The +.Nm +command provides interactive help on all supported commands and options. +If, for some reason, you happen to spot a discrepancy in the output of this +command and this document, the command is the authoritative source of +information. +.Pp +If no arguments are provided, the command prints the list of common options +and the list of supported subcommands. +.Pp +If the +.Ar command +argument is provided to, this single argument is the name of a valid +subcommand. In that case, +.Nm +prints a textual description of the command, the list of common options and +the list of subcommand-specific options. +.Sh EXIT STATUS +The +.Nm +command always returns 0. +.Pp +Additional exit codes may be returned as described in +.Xr kyua 1 . +.Sh SEE ALSO +.Xr kyua 1 diff --git a/external/bsd/kyua-cli/dist/doc/kyua-list.1.in b/external/bsd/kyua-cli/dist/doc/kyua-list.1.in new file mode 100644 index 000000000..53b7e91ae --- /dev/null +++ b/external/bsd/kyua-cli/dist/doc/kyua-list.1.in @@ -0,0 +1,83 @@ +.\" Copyright 2012 Google Inc. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are +.\" met: +.\" +.\" * Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" * Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" * Neither the name of Google Inc. nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.Dd September 9, 2012 +.Dt KYUA-LIST 1 +.Os +.Sh NAME +.Nm list +.Nd Lists test cases and their metadata +.Sh SYNOPSIS +.Nm +.Op Fl -build-root Ar path +.Op Fl -kyuafile Ar file +.Op Fl -verbose +.Ar test_case1 Op Ar .. test_caseN +.Sh DESCRIPTION +The +.Nm +command scans all the test programs and test cases in a test suite and +prints a list of all their names, optionally accompanied by any metadata +properties they have. +.Pp +The optional arguments to +.Nm +are used to select which test programs or test cases to run. These are +filters and are explained in more detail in +.Xr kyua-test-filters 7 . +.Pp +This command must be run within a test suite or a test suite must be +provided with the +.Fl -kyuafile +flag. +.Pp +The following subcommand options are recognized: +.Bl -tag -width XX +.It Fl -build-root Ar path +Specifies the build root in which to find the test programs referenced +by the Kyuafile, if different from the Kyuafile's directory. See +.Xr kyua-build-root 7 +for more information. +.It Fl -kyuafile Ar path , Fl k Ar path +Specifies the Kyuafile to process. Defaults to a +.Pa Kyuafile +file in the current directory. +.It Fl -verbose , Fl v +Prints metadata properties for every test case. +.El +.Sh EXIT STATUS +The +.Nm +command returns 0 on success or 1 if any of the given test case filters +does not match any test case. +.Pp +Additional exit codes may be returned as described in +.Xr kyua 1 . +.Sh SEE ALSO +.Xr kyua 1 , +.Xr kyua-build-root 7 , +.Xr kyua-test-filters 7 diff --git a/external/bsd/kyua-cli/dist/doc/kyua-report-html.1.in b/external/bsd/kyua-cli/dist/doc/kyua-report-html.1.in new file mode 100644 index 000000000..ab5250126 --- /dev/null +++ b/external/bsd/kyua-cli/dist/doc/kyua-report-html.1.in @@ -0,0 +1,81 @@ +.\" Copyright 2012 Google Inc. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are +.\" met: +.\" +.\" * Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" * Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" * Neither the name of Google Inc. nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.Dd September 9, 2012 +.Dt KYUA-REPORT-HTML 1 +.Os +.Sh NAME +.Nm report-html +.Nd Generates an HTML report with the results of a test action +.Sh SYNOPSIS +.Nm +.Op Fl -action Ar id +.Op Fl -force +.Op Fl -output Ar path +.Op Fl -store Ar file +.Sh DESCRIPTION +The +.Nm +command provides a simple mechanism to generate HTML reports of the +execution of a test suite. The command processes an action stored in the +database and then populates a directory with multiple HTML and supporting +files to describe the results recorded in that action. +.Pp +The HTML output is static and self-contained, so it can easily be served by +any simple web server. The command expects the target directory to not +exist, because it would overwrite any contents if not careful. +.Pp +The following subcommand options are recognized: +.Bl -tag -width XX +.It Fl -action Ar id +Specifies the action for which to generate a report. If not provided, +defaults to the latest action stored in the database. +.It Fl -force +Forces the deletion of the output directory if it exists. Use care, as +this effectively means a +.Sq rm -rf . +.It Fl -output Ar directory +Specifies the target directory into which to generate the HTML files. The +directory must not exist unless the +.Fl -force +option is provided. The default is +.Pa ./html . +.It Fl -store Ar path , Fl s Ar path +Specifies the database to use. Defaults to +.Pa ~/.kyua/store.db . +The database is created if it does not exist. +.El +.Sh EXIT STATUS +The +.Nm +command always returns 0. +.Pp +Additional exit codes may be returned as described in +.Xr kyua 1 . +.Sh SEE ALSO +.Xr kyua 1 , +.Xr kyua-report 1 diff --git a/external/bsd/kyua-cli/dist/doc/kyua-report.1.in b/external/bsd/kyua-cli/dist/doc/kyua-report.1.in new file mode 100644 index 000000000..def13e727 --- /dev/null +++ b/external/bsd/kyua-cli/dist/doc/kyua-report.1.in @@ -0,0 +1,97 @@ +.\" Copyright 2012 Google Inc. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are +.\" met: +.\" +.\" * Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" * Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" * Neither the name of Google Inc. nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.Dd September 9, 2012 +.Dt KYUA-REPORT 1 +.Os +.Sh NAME +.Nm report +.Nd Generates a plain-text report with the results of a test action +.Sh SYNOPSIS +.Nm +.Op Fl -action Ar id +.Op Fl -output Ar path +.Op Fl -results-filter Ar types +.Op Fl -show-context +.Op Fl -store Ar file +.Sh DESCRIPTION +The +.Nm +command provides the mechanism to generate user-friendly, plain-text +reports of the execution of a test suite. The command processes an action +stored in the database and then creates a textual summary of the test case +results recorded in that action. These reports are not intended to be +machine-parseable. +.Pp +The following subcommand options are recognized: +.Bl -tag -width XX +.It Fl -action Ar id +Specifies the action for which to generate a report. If not provided, +defaults to the latest action stored in the database. +.It Fl -output Ar path +Specifies the path to which the report should be written to. The special +values +.Pa /dev/stdout +and +.Pa /dev/stderr +can be used to specify the standard output and the standard error +respectively. +.It Fl -results-filter Ar types +Comma-separated list of the test result types to include in the report. +The ordering of the values is respected so that you can determine how you +want the list of tests to be shown. +.Pp +The valid values are: +.Sq broken , +.Sq failed , +.Sq passed , +.Sq skipped +and +.Sq xfail . +If the parameter supplied to the option is empty, filtering is suppressed +and all result types are shown in the report. +.Pp +The default value for this flag includes all the test results except the +passed tests. Showing the passed tests by default clutters the report with +too much information, so only abnormal conditions are included. +.It Fl -show-context +Prints the runtime context of the action. +.It Fl -store Ar path , Fl s Ar path +Specifies the database to use. Defaults to +.Pa ~/.kyua/store.db . +The database is created if it does not exist. +.El +.Sh EXIT STATUS +The +.Nm +command always returns 0. +.Pp +Additional exit codes may be returned as described in +.Xr kyua 1 . +.Sh SEE ALSO +.Xr kyua 1 , +.Xr kyua-report-html 1 diff --git a/external/bsd/kyua-cli/dist/doc/kyua-test-filters.7.in b/external/bsd/kyua-cli/dist/doc/kyua-test-filters.7.in new file mode 100644 index 000000000..a889d5dc5 --- /dev/null +++ b/external/bsd/kyua-cli/dist/doc/kyua-test-filters.7.in @@ -0,0 +1,52 @@ +.\" Copyright 2012 Google Inc. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are +.\" met: +.\" +.\" * Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" * Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" * Neither the name of Google Inc. nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.Dd September 9, 2012 +.Dt KYUA-TEST-FILTERS 7 +.Os +.Sh NAME +.Nm test-filters +.Nd Syntax of the command-line test filters +.Sh DESCRIPTION +A +.Em filter +is a string that is used to match test cases or test programs in a test suite. +Filters have the following form: +.Bd -literal -offset indent +test_program_name[:test_case_name] +.Ed +.Pp +Where +.Sq test_program_name +is the name of a test program or a subdirectory in the test suite, and +.Sq test_case_name +is the name of a test case. +.Sh SEE ALSO +.Xr kyua 1 , +.Xr kyua-debug 1 , +.Xr kyua-list 1 , +.Xr kyua-test 1 diff --git a/external/bsd/kyua-cli/dist/doc/kyua-test.1.in b/external/bsd/kyua-cli/dist/doc/kyua-test.1.in new file mode 100644 index 000000000..e14d56e12 --- /dev/null +++ b/external/bsd/kyua-cli/dist/doc/kyua-test.1.in @@ -0,0 +1,88 @@ +.\" Copyright 2012 Google Inc. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are +.\" met: +.\" +.\" * Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" * Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" * Neither the name of Google Inc. nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.Dd September 9, 2012 +.Dt KYUA-TEST 1 +.Os +.Sh NAME +.Nm test +.Nd Runs tests +.Sh SYNOPSIS +.Nm +.Op Fl -build-root Ar path +.Op Fl -kyuafile Ar file +.Op Fl -store Ar file +.Op Ar test_filter1 .. test_filterN +.Sh DESCRIPTION +The +.Nm +command runs the tests of a test suite and records the results into the +store in the form of a new action. +.Pp +The optional arguments to +.Nm +are used to select which test programs or test cases to run. These are +filters and are explained in more detail in +.Xr kyua-test-filters 7 . +.Pp +The following subcommand options are recognized: +.Bl -tag -width XX +.It Fl -build-root Ar path +Specifies the build root in which to find the test programs referenced by +the Kyuafile, if different from the Kyuafile's directory. See +.Xr kyua-build-root 7 +for more information. +.It Fl -kyuafile Ar path , Fl k Ar path +Specifies the Kyuafile to process. Defaults to a +.Pa Kyuafile +file in the current directory. +.It Fl -store Ar path , Fl s Ar path +Specifies the database to use. Defaults to +.Pa ~/.kyua/store.db . +The database is created if it does not exist. +.El +.Pp +Because +.Nm +records the result of the execution into the database, it does not provide +much feedback on the activity of the program. You can later inspect the +results in more detail by using +.Xr kyua-report 1 +or you can execute a single test case with debugging functionality by using +.Xr kyua-debug 1 . +.Sh EXIT STATUS +The +.Nm +command returns 0 if all executed test cases pass or 1 if any of the +executed test cases fails or if any of the given test case filters does not +match any test case. +.Pp +Additional exit codes may be returned as described in +.Xr kyua 1 . +.Sh SEE ALSO +.Xr kyua 1 , +.Xr kyua-report 1 diff --git a/external/bsd/kyua-cli/dist/doc/kyua.1.in b/external/bsd/kyua-cli/dist/doc/kyua.1.in new file mode 100644 index 000000000..5898dd7cf --- /dev/null +++ b/external/bsd/kyua-cli/dist/doc/kyua.1.in @@ -0,0 +1,367 @@ +.\" Copyright 2011 Google Inc. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are +.\" met: +.\" +.\" * Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" * Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" * Neither the name of Google Inc. nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.Dd February 7, 2013 +.Dt KYUA 1 +.Os +.Sh NAME +.Nm kyua +.Nd Command-line interface to Kyua quality assurance toolkit +.Sh SYNOPSIS +.Nm +.Op Fl -config Ar file +.Op Fl -logfile Ar file +.Op Fl -loglevel Ar level +.Op Fl -variable Ar name=value +.Ar command +.Op Ar command_options +.Op Ar command_arguments +.Sh DESCRIPTION +Kyua is a quality assurance toolkit: a package that provides libraries to +aid in the creation of test cases, and tools to execute such test cases and +generate reports of their results. +.Pp +This manual page describes +.Nm +(note the lowercase), which is the command-line interface to the Kyua +package. +.Pp +If you are here because all you want to know is how to run the tests in +.Pa __TESTSDIR__ , +you most likely want to read the +.Xr tests 7 +manual page instead if your system provides one. +.Pp +As can be observed in the synopsis, the interface of +.Nm +implements a common subcommand-based interface. The arguments to the tool +specify, in this order: a set of common options that all the commands +accept, a required +.Ar command +name that specifies what +.Nm +should do, and +a set of possibly-optional +.Ar command_options +and +.Ar command_arguments +that are specific to the chosen command. +.Ss Options supported by all commands +The following options are recognized by all the commands. +Keep in mind that these must always be specified before the command name. +.Bl -tag -width XX +.It Fl -config Ar path , Fl c Ar path +Specifies the configuration file to process, which must be in the format +described in +.Xr kyua.conf 5 . +The special value +.Sq none +explicitly disables the loading of any configuration file. +.Pp +Defaults to +.Pa ~/.kyua/kyua.conf +if it exists, otherwise to +.Pa __CONFDIR__/kyua.conf +if it exists, +or else to +.Sq none . +.It Fl -logfile Ar path +Specifies the location of the file to which +.Nm +will log run time events useful for postmortem debugging. +.Pp +The default depends on different environment variables as described in +.Sx Logging , +but typically the file will be stored within the user's home directory. +.It Fl -loglevel Ar level +Specifies the maximum logging level to record in the log file. +See +.Sx Logging +for more details. +.Pp +The default is +.Sq info . +.It Fl -variable Ar name=value , Fl v Ar name=value +Sets the +.Ar name +configuration variable to +.Ar value . +The values set through this option have preference over the values set in the +configuration file. +.Pp +The specified variable can either be a builtin variable or a test-suite +specific variable. See +.Xr kyua.conf 5 +for more details. +.El +.Ss Available commands +The following commands are generic and do not have any relation to the execution +of tests or the inspection of their results: +.Bl -tag -width reportXhtmlXX -offset indent +.It Ar about +Shows general program information. +See +.Xr kyua-about 1 . +.It Ar config +Inspects the values of the configuration variables. +See +.Xr kyua-config 1 . +.It Ar db-exec +Executes an arbitrary SQL statement in the store database and prints the +resulting table. +See +.Xr kyua-db-exec 1 . +.It Ar help +Shows usage information. +See +.Xr kyua-help 1 . +.El +.Pp +The following commands are used to generate reports based on the data previously +stored in the database: +.Bl -tag -width reportXhtmlXX -offset indent +.It Ar report +Generates a plain-text report. +See +.Xr kyua-report 1 . +.It Ar report-html +Generates an HTML report. +See +.Xr kyua-report-html 1 . +.El +.Pp +The following commands are used to interact with a test suite: +.Bl -tag -width reportXhtmlXX -offset indent +.It Ar debug +Executes a single test case in a controlled environment for debugging purposes. +See +.Xr kyua-debug 1 . +.It Ar list +Lists test cases and their metadata. +See +.Xr kyua-list 1 . +.It Ar test +Runs tests. +See +.Xr kyua-test 1 . +.El +.Ss Logging +.Nm +has a logging facility that collects all kinds of events at run time. +These events are always logged to a file so that the log is available when +it is most needed: right after a non-reproducible problem happens. +The only way to disable logging is by sending the log to +.Pa /dev/null . +.Pp +The location of the log file can be manually specified with the +.Fl -logfile +option, which applies to all commands. If no file is explicitly specified, the +location of the log files is chosen in this order: +.Bl -enum -offset indent +.It +.Pa ${HOME}/.kyua/logs/ +if +.Va HOME +is defined. +.It +.Pa ${TMPDIR}/ +if +.Va TMPDIR +is defined. +.It +.Pa /tmp/ . +.El +.Pp +And the default naming scheme of the log files is: +.Sq ..log . +.Pp +The messages stored in the log file have a level (or severity) attached to +them. These are: +.Bl -tag -width warningXX -offset indent +.It error +Fatal error messages. The program generally terminates after these, either +in a clean manner or by crashing. +.It warning +Non-fatal error messages. These generally report a condition that must be +addressed but the application can continue to run. +.It info +Informational messages. These tell the user what the program was doing at +a general level of operation. +.It debug +Detailed informational messages. These are often useful when debugging +problems in the application, as they contain lots of internal details. +.El +.Pp +The default log level is +.Sq info +unless expicitly overriden with +.Fl -loglevel . +.Pp +The log file is a plain text file containing one line per log record. The +format of each line is as follows: +.Bd -literal -offset indent +timestamp entry_type pid file:line: message +.Ed +.Pp +.Ar entry_type +can be one of: +.Sq E +for an error, +.Sq W +for a warning, +.Sq I +for an informational message and +.Sq D +for a debug message. +.Ss Bug reporting +If you think you have encountered a bug in +.Nm , +please take the time to let the developers know about it. This will ensure +that the bug is addressed and potentially fixed in the next Kyua release. +.Pp +The first step in reporting a bug is to check if there already is a similar +bug in the database. You can check what issues are currently in the +database by going to: +.Bd -literal -offset indent +http://code.google.com/p/kyua/issues/list +.Ed +.Pp +If there is no existing issue that describes an issue similar to the +one you are experiencing, you can open a new one by visiting: +.Bd -literal -offset indent +http://code.google.com/p/kyua/issues/entry +.Ed +.Pp +When doing so, please include as much detail as possible. Among other +things, explain what operating system and platform you are running +.Nm +on, what were you trying to do, what exact messages you saw on the screen, +how did you expect the program to behave, and any other details that you +may find relevant. +.Pp +Also, please include a copy of the log file corresponding to the problem +you are experiencing. Unless you have changed the location of the log +files, you can most likely find them in +.Pa ~/.kyua/logs/ . +If the problem is reproducible, it is good idea to regenerate the log file +with an increased log level so as to provide more information. For +example: +.Bd -literal -offset indent +$ kyua --logfile=problem.log --loglevel=debug \\ + [rest of the command line] +.Ed +.Sh ENVIRONMENT +The following variables are recognized and can be freely tuned by the end user: +.Bl -tag -width COLUMNSXX +.It Va COLUMNS +The width of the screen, in number of characters. +.Nm +uses this to wrap long lines. +If not present, the width of the screen is determined from the terminal +stdout is connected to, and, if the guessing fails, this defaults to infinity. +.It Va HOME +Path to the user's home directory. +.Nm +uses this location to determine paths to configuration files and default log +files. +.It Va TMPDIR +Path to the system-wide temporary directory. +.Nm +uses this location to place the work directory of test cases, among other +things. +.Pp +The default value of this variable depends on the operating system. In +general, it is +.Pa /tmp . +.El +.Pp +The following variables are also recognized, but you should not need to set them +during normal operation. +They are only provided to override the value of built-in values, which is useful +when testing +.Nm +itself: +.Bl -tag -width KYUAXCONFDIRXX +.It Va KYUA_CONFDIR +Path to the system-wide configuration files for +.Nm . +.Pp +Defaults to +.Pa __CONFDIR__ . +.It Va KYUA_DOCDIR +Path to the location of installed documentation. +.Pp +Defaults to +.Pa __DOCDIR__ . +.It Va KYUA_MISCDIR +Path to the location of the installed miscellaneous scripts and data +files provided by +.Nm . +.Pp +Defaults to +.Pa __MISCDIR__ . +.It Va KYUA_STOREDIR +Path to the location of the installed store support files; e.g. the +directory containing the SQL database schema. +.Pp +Defaults to +.Pa __STOREDIR__ . +.It Va KYUA_TESTERSDIR +Path to the location of the installed testers; e.g. the directory containing +programs like +.Pa plain_tester . +Defaults to +.Pa __TESTERSDIR__ . +.El +.Sh FILES +.Bl -tag -width XXXX +.It Pa ~/.kyua/kyua.conf +User-specific configuration file. +.It Pa ~/.kyua/logs/ +Default location for the collected log files. +.It Pa __CONFDIR__/kyua.conf +System-wide configuration file. +.El +.Sh EXIT STATUS +.Nm +returns 0 on success, 1 on a controlled error condition in the given +subcommand, 2 on a general unexpected error and 3 on a usage error. +.Pp +The documentation of the subcommands in the corresponding manual pages only +details the difference between a successful exit (0) and the detection of a +controlled error (1). Even though when those manual pages do not describe +any other exit statuses, codes above 1 can be returned. +.Sh SEE ALSO +.Xr atf 7 , +.Xr tests 7 +.Sh AUTHORS +For more details on the people that made +.Nm +possible and the license terms, run: +.Bd -literal -offset indent +$ kyua about +.Ed diff --git a/external/bsd/kyua-cli/dist/doc/kyua.conf.5.in b/external/bsd/kyua-cli/dist/doc/kyua.conf.5.in new file mode 100644 index 000000000..7420c62af --- /dev/null +++ b/external/bsd/kyua-cli/dist/doc/kyua.conf.5.in @@ -0,0 +1,125 @@ +.\" Copyright 2012 Google Inc. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are +.\" met: +.\" +.\" * Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" * Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" * Neither the name of Google Inc. nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.Dd February 9, 2013 +.Dt KYUA.CONF 5 +.Os +.Sh NAME +.Nm kyua.conf +.Nd Configuration file for the kyua tool +.Sh SYNOPSIS +.Fn syntax "int version" +.Pp +Variables: +.Va architecture , +.Va platform , +.Va test_suites , +.Va unprivileged_user . +.Sh DESCRIPTION +The configuration of Kyua is a simple collection of key/value pairs called +configuration variables. There are configuration variables that have a +special meaning to the runtime engine implemented by +.Xr kyua 1 , +and there are variables that only have meaning in the context of particular +test suites. +.Pp +Configuration files are Lua scripts. +In their most basic form, their whole purpose is to assign values to +variables, but the user has the freedom to implement any logic he desires +to compute such values. +The general structure of a configuration file is: +.Bd -literal -offset indent +syntax(2) + +-- Assign internal variables. +architecture = 'foo' +platform = 'bar' + +-- Assign test-suite variables. All of these must be strings. +test_suites.NetBSD.file_systems = 'ffs ext2fs' +test_suites.X11.graphics_driver = 'vesa' +.Ed +.Ss File versioning +Every +.Nm +file starts with a call to +.Fn syntax "int version" . +This call determines the specific schema used by the file so that future +backwards-incompatible modifications to the file can be introduced. +.Pp +Any new +.Nm +file should set +.Fa version +to +.Sq 2 . +.Ss Runtime configuration variables +The following variables are internally recognized by +.Xr kyua 1 : +.Bl -tag -width XX +.It Va architecture +Name of the system architecture (aka processor type). +.It Va platform +Name of the system platform (aka machine type). +.It Va unprivileged_user +Name or UID of the unprivileged user. +.Pp +If set, the given user must exist in the system and his privileges will be +used to run test cases that need regular privileges when +.Xr kyua 1 +is executed as root. +.El +.Ss Test-suite configuration variables +Each test suite is able to recognize arbitrary configuration variables, and +their type and meaning is specific to the test suite. Because the +existence and naming of these variables depends on every test suite, this +manual page cannot detail them; please refer to the documentation of the +test suite you are working with for more details on this topic. +.Pp +Test-suite specific configuration variables are defined inside the +.Va test_suites +dictionary. +The general syntax is: +.Bd -literal -offset indent +test_suites.. = +.Ed +.Pp +where +.Va test_suite_name +is the name of the test suite, +.Va variable_name +is the name of the variable to set, and +.Va value +is a value. +The value can be a string, an integer or a boolean. +.Sh FILES +.Bl -tag -width XX +.It __EGDIR__/kyua.conf +Sample configuration file. +.El +.Sh SEE ALSO +.Xr kyua 1 diff --git a/external/bsd/kyua-cli/dist/doc/kyuafile.5.in b/external/bsd/kyua-cli/dist/doc/kyuafile.5.in new file mode 100644 index 000000000..6730bf46d --- /dev/null +++ b/external/bsd/kyua-cli/dist/doc/kyuafile.5.in @@ -0,0 +1,191 @@ +.\" Copyright 2012 Google Inc. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are +.\" met: +.\" +.\" * Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" * Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" * Neither the name of Google Inc. nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.Dd February 9, 2013 +.Dt KYUAFILE 5 +.Os +.Sh NAME +.Nm Kyuafile +.Nd Test suite description files +.Sh SYNOPSIS +.Fn atf_test_program "string name" "[string test_suite]" "[string metadata]" +.Fn include "string path" +.Fn plain_test_program "string name" "[string test_suite]" "[string metadata]" +.Fn syntax "int version" +.Fn test_suite "string name" +.Sh DESCRIPTION +A test suite is a collection of test programs and is represented by a +hierarchical layout of test binaries on the file system. Any subtree of +the file system can represent a test suite, provided that it includes one +or more +.Nm Ns s , +which are the test suite definition files. +.Pp +A +.Nm +is a Lua script whose purpose is to describe the structure of the test +suite it belongs to. To do so, the script has access to a collection of +special functions provided by +.Xr kyua 1 . +.Pp +A typical +.Nm +will look similar to this: +.Bd -literal -offset indent +syntax(2) + +test_suite('first') + +-- Declare the test programs that are in this directory. +atf_test_program{name='foo_test'} +atf_test_program{name='bar_test', test_suite='second'} +plain_test_program{name='legacy_test'} +plain_test_program{name='legacy2_test', allowed_architectures='amd64 i386', + required_files='/bin/ls', timeout=30} + +-- Recurse into any subdirectories that may have other tests. +include('dir1/Kyuafile') +include('dir2/Kyuafile') +.Ed +.Ss File versioning +Every +.Nm +file starts with a call to +.Fn syntax "int version" . +This call determines the specific schema used by the file so that future +backwards-incompatible modifications to the file can be introduced. +.Pp +Any new +.Nm +file should set +.Fa version +to +.Sq 2 . +.Ss Test suite definition +Every +.Nm +should define the name of the test suite it belongs to by calling the +.Fn test_suite +function at the very beginning. +Individual test programs can override this value in their definition, but +the most common style is to list a single test suite name for the whole +file. +.Pp +The purpose of the test suite name definition is to tell +.Xr kyua 1 +scoping for the run-time configuration variables that these programs +accept. +.Ss Test program registration +A +.Nm +can register test programs by means of a variety of +.Fn *_test_program +functions, all of which take the name of a test program and a set of +optional metadata properties that describe such test program. +.Pp +The test programs to be registered must live in the current directory; in +other words, the various +.Fn *_test_program +calls cannot reference test programs in other directories. +The rationale for this is to force all +.Nm +files to be self-contained, and to simplify their internal representation. +.Pp +ATF-based test programs (those that implement the +.Xr kyua-atf-interface 7 +interface) can be registered with the +.Fn atf_test_program +table constructor. This function takes the +.Fa name +of the test program, an optional +.Fa test_suite +name that overrides the global test suite name and a collection of optional +metadata settings for all the test cases in the test program. Any metadata +properties defined by the test cases themselves override the metadata values +defined here. +.Pp +Plain test programs (those that implement the +.Xr kyua-plain-interface 7 +interface) can be registered with the +.Fn plain_test_program +table constructor. This function takes the +.Fa name +of the test program an optional +.Fa test_suite +name that overrides the global test suite name and a collection of optional +metadata settings for the test program. +.Pp +Please see +.Xr kyua-tester-list 5 +for the list of metadata properties that can be given to test programs. +All the properties that can be given to a test case can also be given to a test +program. +.Ss Recursion +To reference test programs in another subdirectory, a different +.Nm +must be created in that directory and it must be included into the original +.Nm +by means of the +.Fn include +function. +.Pp +Note that each file is processed in its own Lua environment: there is no +mechanism to pass state from one file to the other. The reason for this is +that there is no such thing as a +.Dq top-level +.Nm +in a test suite: the user has to be able to run the test suite from any +directory in a given hierarchy, and this execution must not depend on files +that live in parent directories. +.Ss Top-level Kyuafile +Every system has a top directory into which test suites get installed. The +default is +.Pa __TESTSDIR__ . +Within this directory live test suites, each of which is in an independent +subdirectory. Each subdirectory can be provided separately by independent +third-party packages. +.Pp +Kyua allows running all the installed test suites at once in order to +provide comprehensive cross-component reports. In order to do this, there +is a special file in the top directory that knows how to inspect the +subdirectories in search for other Kyuafiles and include them. +.Pp +The +.Sx FILES +section includes more details on where this file lives. +.Sh FILES +.Bl -tag -width XX +.It Pa __TESTSDIR__/Kyuafile . +Top-level +.Nm +for the current system. +.It Pa __EGDIR__/Kyuafile.top . +Sample file to serve as a top-level +.Nm . +.El +.Sh SEE ALSO +.Xr kyua 1 diff --git a/external/bsd/kyua-cli/dist/engine/Kyuafile b/external/bsd/kyua-cli/dist/engine/Kyuafile new file mode 100644 index 000000000..052b27c0e --- /dev/null +++ b/external/bsd/kyua-cli/dist/engine/Kyuafile @@ -0,0 +1,17 @@ +syntax(2) + +test_suite("kyua") + +atf_test_program{name="action_test"} +atf_test_program{name="config_test"} +atf_test_program{name="context_test"} +atf_test_program{name="exceptions_test"} +atf_test_program{name="filters_test"} +atf_test_program{name="kyuafile_test"} +atf_test_program{name="metadata_test"} +atf_test_program{name="test_case_test"} +atf_test_program{name="test_program_test"} +atf_test_program{name="test_result_test"} +atf_test_program{name="testers_test"} + +include("drivers/Kyuafile") diff --git a/external/bsd/kyua-cli/dist/engine/action.cpp b/external/bsd/kyua-cli/dist/engine/action.cpp new file mode 100644 index 000000000..5488f5693 --- /dev/null +++ b/external/bsd/kyua-cli/dist/engine/action.cpp @@ -0,0 +1,123 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "engine/action.hpp" + +#include "engine/context.hpp" +#include "utils/format/macros.hpp" + +namespace fs = utils::fs; + + +/// Internal implementation of an action. +struct engine::action::impl { + /// The runtime context of the action. + context _context; + + /// Constructor. + /// + /// \param context_ The runtime context. + impl(const context& context_) : + _context(context_) + { + } + + /// Equality comparator. + /// + /// \param other The object to compare to. + /// + /// \return True if the two objects are equal; false otherwise. + bool + operator==(const impl& other) const + { + return _context == other._context; + } +}; + + +/// Constructs a new action. +/// +/// \param context_ The runtime context in which the action runs. +engine::action::action(const context& context_) : + _pimpl(new impl(context_)) +{ +} + + +/// Destructor. +engine::action::~action(void) +{ +} + + +/// Returns the context attached to this action. +/// +/// \return A reference to the context. +const engine::context& +engine::action::runtime_context(void) const +{ + return _pimpl->_context; +} + + +/// Equality comparator. +/// +/// \param other The other object to compare this one to. +/// +/// \return True if this object and other are equal; false otherwise. +bool +engine::action::operator==(const action& other) const +{ + return *_pimpl == *other._pimpl; +} + + +/// Inequality comparator. +/// +/// \param other The other object to compare this one to. +/// +/// \return True if this object and other are different; false otherwise. +bool +engine::action::operator!=(const action& other) const +{ + return !(*this == other); +} + + +/// Injects the object into a stream. +/// +/// \param output The stream into which to inject the object. +/// \param object The object to format. +/// +/// \return The output stream. +std::ostream& +engine::operator<<(std::ostream& output, const action& object) +{ + output << F("action{context=%s}") % object.runtime_context(); + return output; +} diff --git a/external/bsd/kyua-cli/dist/engine/action.hpp b/external/bsd/kyua-cli/dist/engine/action.hpp new file mode 100644 index 000000000..4bf1fb7c8 --- /dev/null +++ b/external/bsd/kyua-cli/dist/engine/action.hpp @@ -0,0 +1,71 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file engine/action.hpp +/// Representation of user-initiated actions. + +#if !defined(ENGINE_ACTION_HPP) +#define ENGINE_ACTION_HPP + +#include +#include + +namespace engine { + + +class context; + + +/// Representation of an action. +/// +/// The instances of this class are unique (i.e. copying the objects only yields +/// a shallow copy that shares the same internal implementation). This is a +/// requirement for the 'store' API model. +class action { + struct impl; + + /// Pointer to the shared internal implementation. + std::tr1::shared_ptr< impl > _pimpl; + +public: + explicit action(const context&); + ~action(void); + + const context& runtime_context(void) const; + + bool operator==(const action&) const; + bool operator!=(const action&) const; +}; + + +std::ostream& operator<<(std::ostream&, const action&); + + +} // namespace engine + +#endif // !defined(ENGINE_ACTION_HPP) diff --git a/external/bsd/kyua-cli/dist/engine/action_test.cpp b/external/bsd/kyua-cli/dist/engine/action_test.cpp new file mode 100644 index 000000000..5e33dd746 --- /dev/null +++ b/external/bsd/kyua-cli/dist/engine/action_test.cpp @@ -0,0 +1,104 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "engine/action.hpp" + +#include +#include +#include + +#include + +#include "engine/context.hpp" +#include "utils/fs/path.hpp" + +namespace fs = utils::fs; + + +namespace { + + +/// Generates a context with fake data for testing purposes only. +/// +/// \param cwd The work directory held in the context. This contains an +/// irrelevant default value if not provided. +/// +/// \return The fake context. +static engine::context +fake_context(const char* cwd = "/foo/bar") +{ + std::map< std::string, std::string > env; + env["foo"] = "bar"; + return engine::context(fs::path(cwd), env); +} + + +} // anonymous namespace + + +ATF_TEST_CASE_WITHOUT_HEAD(ctor_and_getters); +ATF_TEST_CASE_BODY(ctor_and_getters) +{ + const engine::context context = fake_context(); + const engine::action action(context); + ATF_REQUIRE(context == action.runtime_context()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(operators_eq_and_ne); +ATF_TEST_CASE_BODY(operators_eq_and_ne) +{ + const engine::action action1(fake_context("foo/bar")); + const engine::action action2(fake_context("foo/bar")); + const engine::action action3(fake_context("foo/baz")); + ATF_REQUIRE( action1 == action2); + ATF_REQUIRE(!(action1 != action2)); + ATF_REQUIRE(!(action1 == action3)); + ATF_REQUIRE( action1 != action3); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(output); +ATF_TEST_CASE_BODY(output) +{ + const engine::context context = fake_context(); + const engine::action action(context); + + std::ostringstream str; + str << action; + ATF_REQUIRE_EQ("action{context=context{cwd='/foo/bar', env=[foo='bar']}}", + str.str()); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, ctor_and_getters); + ATF_ADD_TEST_CASE(tcs, operators_eq_and_ne); + ATF_ADD_TEST_CASE(tcs, output); +} diff --git a/external/bsd/kyua-cli/dist/engine/config.cpp b/external/bsd/kyua-cli/dist/engine/config.cpp new file mode 100644 index 000000000..787a3151a --- /dev/null +++ b/external/bsd/kyua-cli/dist/engine/config.cpp @@ -0,0 +1,235 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "engine/config.hpp" + +#if defined(HAVE_CONFIG_H) +# include "config.h" +#endif + +#include + +#include "engine/exceptions.hpp" +#include "utils/config/exceptions.hpp" +#include "utils/config/parser.hpp" +#include "utils/config/tree.ipp" +#include "utils/passwd.hpp" +#include "utils/text/exceptions.hpp" +#include "utils/text/operations.ipp" + +namespace config = utils::config; +namespace fs = utils::fs; +namespace passwd = utils::passwd; +namespace text = utils::text; + + +namespace { + + +/// Defines the schema of a configuration tree. +/// +/// \param [in,out] tree The tree to populate. The tree should be empty on +/// entry to prevent collisions with the keys defined in here. +static void +init_tree(config::tree& tree) +{ + tree.define< config::string_node >("architecture"); + tree.define< config::string_node >("platform"); + tree.define< engine::user_node >("unprivileged_user"); + tree.define_dynamic("test_suites"); +} + + +/// Fills in a configuration tree with default values. +/// +/// \param [in,out] tree The tree to populate. init_tree() must have been +/// called on it beforehand. +static void +set_defaults(config::tree& tree) +{ + tree.set< config::string_node >("architecture", KYUA_ARCHITECTURE); + tree.set< config::string_node >("platform", KYUA_PLATFORM); +} + + +/// Configuration parser specialization for Kyua configuration files. +class config_parser : public config::parser { + /// Initializes the configuration tree. + /// + /// This is a callback executed when the configuration script invokes the + /// syntax() method. We populate the configuration tree from here with the + /// schema version requested by the file. + /// + /// \param [in,out] tree The tree to populate. + /// \param syntax_version The version of the file format as specified in the + /// configuration file. + /// + /// \throw config::syntax_error If the syntax_format/syntax_version + /// combination is not supported. + void + setup(config::tree& tree, const int syntax_version) + { + if (syntax_version < 1 || syntax_version > 2) + throw config::syntax_error(F("Unsupported config version %s") % + syntax_version); + + init_tree(tree); + set_defaults(tree); + } + +public: + /// Initializes the parser. + /// + /// \param [out] tree_ The tree in which the results of the parsing will be + /// stored when parse() is called. Should be empty on entry. Because + /// we grab a reference to this object, the tree must remain valid for + /// the existence of the parser object. + explicit config_parser(config::tree& tree_) : + config::parser(tree_) + { + } +}; + + +} // anonymous namespace + + +/// Copies the node. +/// +/// \return A dynamically-allocated node. +config::detail::base_node* +engine::user_node::deep_copy(void) const +{ + std::auto_ptr< user_node > new_node(new user_node()); + new_node->_value = _value; + return new_node.release(); +} + + +/// Pushes the node's value onto the Lua stack. +/// +/// \param state The Lua state onto which to push the value. +void +engine::user_node::push_lua(lutok::state& state) const +{ + state.push_string(value().name); +} + + +/// Sets the value of the node from an entry in the Lua stack. +/// +/// \param state The Lua state from which to get the value. +/// \param value_index The stack index in which the value resides. +/// +/// \throw value_error If the value in state(value_index) cannot be +/// processed by this node. +void +engine::user_node::set_lua(lutok::state& state, const int value_index) +{ + if (state.is_number(value_index)) { + config::typed_leaf_node< passwd::user >::set( + passwd::find_user_by_uid(state.to_integer(-1))); + } else if (state.is_string(value_index)) { + config::typed_leaf_node< passwd::user >::set( + passwd::find_user_by_name(state.to_string(-1))); + } else + throw config::value_error("Invalid user identifier"); +} + + +void +engine::user_node::set_string(const std::string& raw_value) +{ + try { + config::typed_leaf_node< passwd::user >::set( + passwd::find_user_by_name(raw_value)); + } catch (const std::runtime_error& e) { + int uid; + try { + uid = text::to_type< int >(raw_value); + } catch (const text::value_error& e2) { + throw error(F("Cannot find user with name '%s'") % raw_value); + } + + try { + config::typed_leaf_node< passwd::user >::set( + passwd::find_user_by_uid(uid)); + } catch (const std::runtime_error& e2) { + throw error(F("Cannot find user with UID %s") % uid); + } + } +} + + +std::string +engine::user_node::to_string(void) const +{ + return config::typed_leaf_node< passwd::user >::value().name; +} + + +/// Constructs a config with the built-in settings. +config::tree +engine::default_config(void) +{ + config::tree tree; + init_tree(tree); + set_defaults(tree); + return tree; +} + + +/// Constructs a config with the built-in settings. +config::tree +engine::empty_config(void) +{ + config::tree tree; + init_tree(tree); + return tree; +} + + +/// Parses a test suite configuration file. +/// +/// \param file The file to parse. +/// +/// \return High-level representation of the configuration file. +/// +/// \throw load_error If there is any problem loading the file. This includes +/// file access errors and syntax errors. +config::tree +engine::load_config(const utils::fs::path& file) +{ + config::tree tree; + try { + config_parser(tree).parse(file); + } catch (const config::error& e) { + throw load_error(file, e.what()); + } + return tree; +} diff --git a/external/bsd/kyua-cli/dist/engine/config.hpp b/external/bsd/kyua-cli/dist/engine/config.hpp new file mode 100644 index 000000000..0212b4472 --- /dev/null +++ b/external/bsd/kyua-cli/dist/engine/config.hpp @@ -0,0 +1,62 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file engine/config.hpp +/// Test suite configuration parsing and representation. + +#if !defined(ENGINE_CONFIG_HPP) +#define ENGINE_CONFIG_HPP + +#include "utils/config/tree.hpp" +#include "utils/fs/path.hpp" +#include "utils/passwd.hpp" + +namespace engine { + + +/// Tree node to hold a system user identifier. +class user_node : public utils::config::typed_leaf_node< utils::passwd::user > { +public: + virtual base_node* deep_copy(void) const; + + void push_lua(lutok::state&) const; + void set_lua(lutok::state&, const int); + + void set_string(const std::string&); + std::string to_string(void) const; +}; + + +utils::config::tree default_config(void); +utils::config::tree empty_config(void); +utils::config::tree load_config(const utils::fs::path&); + + +} // namespace engine + +#endif // !defined(ENGINE_CONFIG_HPP) diff --git a/external/bsd/kyua-cli/dist/engine/config_test.cpp b/external/bsd/kyua-cli/dist/engine/config_test.cpp new file mode 100644 index 000000000..9dedd7aee --- /dev/null +++ b/external/bsd/kyua-cli/dist/engine/config_test.cpp @@ -0,0 +1,181 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "engine/config.hpp" + +#if defined(HAVE_CONFIG_H) +# include "config.h" +#endif + +#include +#include + +#include + +#include "engine/exceptions.hpp" +#include "utils/cmdline/exceptions.hpp" +#include "utils/cmdline/parser.hpp" +#include "utils/config/tree.ipp" +#include "utils/passwd.hpp" + +namespace config = utils::config; +namespace fs = utils::fs; +namespace passwd = utils::passwd; + +using utils::none; +using utils::optional; + + +namespace { + + +/// Replaces the system user database with a fake one for testing purposes. +static void +set_mock_users(void) +{ + std::vector< passwd::user > users; + users.push_back(passwd::user("user1", 100, 150)); + users.push_back(passwd::user("user2", 200, 250)); + passwd::set_mock_users_for_testing(users); +} + + +/// Checks that the default values of a config object match our expectations. +/// +/// This fails the test case if any field of the input config object is not +/// what we expect. +/// +/// \param config The configuration to validate. +static void +validate_defaults(const config::tree& config) +{ + ATF_REQUIRE_EQ( + KYUA_ARCHITECTURE, + config.lookup< config::string_node >("architecture")); + + ATF_REQUIRE_EQ( + KYUA_PLATFORM, + config.lookup< config::string_node >("platform")); + + ATF_REQUIRE(!config.is_set("unprivileged_user")); + + ATF_REQUIRE(config.all_properties("test_suites").empty()); +} + + +} // anonymous namespace + + +ATF_TEST_CASE_WITHOUT_HEAD(config__defaults); +ATF_TEST_CASE_BODY(config__defaults) +{ + const config::tree user_config = engine::default_config(); + validate_defaults(user_config); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(config__load__defaults); +ATF_TEST_CASE_BODY(config__load__defaults) +{ + atf::utils::create_file("config", "syntax(2)\n"); + + const config::tree user_config = engine::load_config(fs::path("config")); + validate_defaults(user_config); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(config__load__overrides); +ATF_TEST_CASE_BODY(config__load__overrides) +{ + set_mock_users(); + + atf::utils::create_file( + "config", + "syntax(2)\n" + "architecture = 'test-architecture'\n" + "platform = 'test-platform'\n" + "unprivileged_user = 'user2'\n" + "test_suites.mysuite.myvar = 'myvalue'\n"); + + const config::tree user_config = engine::load_config(fs::path("config")); + + ATF_REQUIRE_EQ("test-architecture", + user_config.lookup_string("architecture")); + ATF_REQUIRE_EQ("test-platform", + user_config.lookup_string("platform")); + + const passwd::user& user = user_config.lookup< engine::user_node >( + "unprivileged_user"); + ATF_REQUIRE_EQ("user2", user.name); + ATF_REQUIRE_EQ(200, user.uid); + + config::properties_map exp_test_suites; + exp_test_suites["test_suites.mysuite.myvar"] = "myvalue"; + + ATF_REQUIRE(exp_test_suites == user_config.all_properties("test_suites")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(config__load__lua_error); +ATF_TEST_CASE_BODY(config__load__lua_error) +{ + atf::utils::create_file("config", "this syntax is invalid\n"); + + ATF_REQUIRE_THROW(engine::load_error, engine::load_config( + fs::path("config"))); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(config__load__bad_syntax__version); +ATF_TEST_CASE_BODY(config__load__bad_syntax__version) +{ + atf::utils::create_file("config", "syntax(123)\n"); + + ATF_REQUIRE_THROW_RE(engine::load_error, + "Unsupported config version 123", + engine::load_config(fs::path("config"))); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(config__load__missing_file); +ATF_TEST_CASE_BODY(config__load__missing_file) +{ + ATF_REQUIRE_THROW_RE(engine::load_error, "Load of 'missing' failed", + engine::load_config(fs::path("missing"))); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, config__defaults); + ATF_ADD_TEST_CASE(tcs, config__load__defaults); + ATF_ADD_TEST_CASE(tcs, config__load__overrides); + ATF_ADD_TEST_CASE(tcs, config__load__lua_error); + ATF_ADD_TEST_CASE(tcs, config__load__bad_syntax__version); + ATF_ADD_TEST_CASE(tcs, config__load__missing_file); +} diff --git a/external/bsd/kyua-cli/dist/engine/context.cpp b/external/bsd/kyua-cli/dist/engine/context.cpp new file mode 100644 index 000000000..eb2ee22d1 --- /dev/null +++ b/external/bsd/kyua-cli/dist/engine/context.cpp @@ -0,0 +1,167 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "engine/context.hpp" + +#include "utils/env.hpp" +#include "utils/format/macros.hpp" +#include "utils/fs/operations.hpp" +#include "utils/text/operations.ipp" + +namespace fs = utils::fs; +namespace text = utils::text; + + +/// Internal implementation of a context. +struct engine::context::impl { + /// The current working directory. + fs::path _cwd; + + /// The environment variables. + std::map< std::string, std::string > _env; + + /// Constructor. + /// + /// \param cwd_ The current working directory. + /// \param env_ The environment variables. + impl(const fs::path& cwd_, + const std::map< std::string, std::string >& env_) : + _cwd(cwd_), + _env(env_) + { + } + + /// Equality comparator. + /// + /// \param other The object to compare to. + /// + /// \return True if the two objects are equal; false otherwise. + bool + operator==(const impl& other) const + { + return _cwd == other._cwd && _env == other._env; + } +}; + + +/// Constructs a new context. +/// +/// \param cwd_ The current working directory. +/// \param env_ The environment variables. +engine::context::context(const fs::path& cwd_, + const std::map< std::string, std::string >& env_) : + _pimpl(new impl(cwd_, env_)) +{ +} + + +/// Destructor. +engine::context::~context(void) +{ +} + + +/// Constructs a new context based on the current environment. +engine::context +engine::context::current(void) +{ + return context(fs::current_path(), utils::getallenv()); +} + + +/// Returns the current working directory of the context. +/// +/// \return A path. +const fs::path& +engine::context::cwd(void) const +{ + return _pimpl->_cwd; +} + + +/// Returns the environment variables of the context. +/// +/// \return A variable name to variable value mapping. +const std::map< std::string, std::string >& +engine::context::env(void) const +{ + return _pimpl->_env; +} + + +/// Equality comparator. +/// +/// \param other The other object to compare this one to. +/// +/// \return True if this object and other are equal; false otherwise. +bool +engine::context::operator==(const context& other) const +{ + return *_pimpl == *other._pimpl; +} + + +/// Inequality comparator. +/// +/// \param other The other object to compare this one to. +/// +/// \return True if this object and other are different; false otherwise. +bool +engine::context::operator!=(const context& other) const +{ + return !(*this == other); +} + + +/// Injects the object into a stream. +/// +/// \param output The stream into which to inject the object. +/// \param object The object to format. +/// +/// \return The output stream. +std::ostream& +engine::operator<<(std::ostream& output, const context& object) +{ + output << F("context{cwd=%s, env=[") + % text::quote(object.cwd().str(), '\''); + + const std::map< std::string, std::string >& env = object.env(); + bool first = true; + for (std::map< std::string, std::string >::const_iterator + iter = env.begin(); iter != env.end(); ++iter) { + if (!first) + output << ", "; + first = false; + + output << F("%s=%s") % (*iter).first + % text::quote((*iter).second, '\''); + } + + output << "]}"; + return output; +} diff --git a/external/bsd/kyua-cli/dist/engine/context.hpp b/external/bsd/kyua-cli/dist/engine/context.hpp new file mode 100644 index 000000000..e75f7f3ec --- /dev/null +++ b/external/bsd/kyua-cli/dist/engine/context.hpp @@ -0,0 +1,75 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file engine/context.hpp +/// Representation of runtime contexts. + +#if !defined(ENGINE_CONTEXT_HPP) +#define ENGINE_CONTEXT_HPP + +#include +#include +#include +#include + +#include "utils/fs/path.hpp" + +namespace engine { + + +/// Representation of a runtime context. +/// +/// The instances of this class are unique (i.e. copying the objects only yields +/// a shallow copy that shares the same internal implementation). This is a +/// requirement for the 'store' API model. +class context { + struct impl; + + /// Pointer to the shared internal implementation. + std::tr1::shared_ptr< impl > _pimpl; + +public: + context(const utils::fs::path&, + const std::map< std::string, std::string >&); + ~context(void); + static context current(void); + + const utils::fs::path& cwd(void) const; + const std::map< std::string, std::string >& env(void) const; + + bool operator==(const context&) const; + bool operator!=(const context&) const; +}; + + +std::ostream& operator<<(std::ostream&, const context&); + + +} // namespace engine + +#endif // !defined(ENGINE_CONTEXT_HPP) diff --git a/external/bsd/kyua-cli/dist/engine/context_test.cpp b/external/bsd/kyua-cli/dist/engine/context_test.cpp new file mode 100644 index 000000000..83f09cbb8 --- /dev/null +++ b/external/bsd/kyua-cli/dist/engine/context_test.cpp @@ -0,0 +1,118 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "engine/context.hpp" + +#include +#include +#include + +#include + +#include "utils/env.hpp" +#include "utils/fs/operations.hpp" +#include "utils/fs/path.hpp" + +namespace fs = utils::fs; + + +ATF_TEST_CASE_WITHOUT_HEAD(ctor_and_getters); +ATF_TEST_CASE_BODY(ctor_and_getters) +{ + std::map< std::string, std::string > env; + env["foo"] = "first"; + env["bar"] = "second"; + const engine::context context(fs::path("/foo/bar"), env); + ATF_REQUIRE_EQ(fs::path("/foo/bar"), context.cwd()); + ATF_REQUIRE(env == context.env()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(current); +ATF_TEST_CASE_BODY(current) +{ + const engine::context context = engine::context::current(); + ATF_REQUIRE_EQ(fs::current_path(), context.cwd()); + ATF_REQUIRE(utils::getallenv() == context.env()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(operators_eq_and_ne); +ATF_TEST_CASE_BODY(operators_eq_and_ne) +{ + std::map< std::string, std::string > env; + env["foo"] = "first"; + const engine::context context1(fs::path("/foo/bar"), env); + const engine::context context2(fs::path("/foo/bar"), env); + const engine::context context3(fs::path("/foo/baz"), env); + env["bar"] = "second"; + const engine::context context4(fs::path("/foo/bar"), env); + ATF_REQUIRE( context1 == context2); + ATF_REQUIRE(!(context1 != context2)); + ATF_REQUIRE(!(context1 == context3)); + ATF_REQUIRE( context1 != context3); + ATF_REQUIRE(!(context1 == context4)); + ATF_REQUIRE( context1 != context4); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(output__empty_env); +ATF_TEST_CASE_BODY(output__empty_env) +{ + const std::map< std::string, std::string > env; + const engine::context context(fs::path("/foo/bar"), env); + + std::ostringstream str; + str << context; + ATF_REQUIRE_EQ("context{cwd='/foo/bar', env=[]}", str.str()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(output__some_env); +ATF_TEST_CASE_BODY(output__some_env) +{ + std::map< std::string, std::string > env; + env["foo"] = "first"; + env["bar"] = "second' var"; + const engine::context context(fs::path("/foo/bar"), env); + + std::ostringstream str; + str << context; + ATF_REQUIRE_EQ("context{cwd='/foo/bar', env=[bar='second\\' var', " + "foo='first']}", str.str()); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, ctor_and_getters); + ATF_ADD_TEST_CASE(tcs, current); + ATF_ADD_TEST_CASE(tcs, operators_eq_and_ne); + ATF_ADD_TEST_CASE(tcs, output__empty_env); + ATF_ADD_TEST_CASE(tcs, output__some_env); +} diff --git a/external/bsd/kyua-cli/dist/engine/drivers/Kyuafile b/external/bsd/kyua-cli/dist/engine/drivers/Kyuafile new file mode 100644 index 000000000..d431b0574 --- /dev/null +++ b/external/bsd/kyua-cli/dist/engine/drivers/Kyuafile @@ -0,0 +1,8 @@ +syntax(2) + +test_suite("kyua") + +atf_test_program{name="debug_test_test"} +atf_test_program{name="list_tests_test"} +atf_test_program{name="run_tests_test"} +atf_test_program{name="scan_action_test"} diff --git a/external/bsd/kyua-cli/dist/engine/drivers/debug_test.cpp b/external/bsd/kyua-cli/dist/engine/drivers/debug_test.cpp new file mode 100644 index 000000000..ca3c94c28 --- /dev/null +++ b/external/bsd/kyua-cli/dist/engine/drivers/debug_test.cpp @@ -0,0 +1,144 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "engine/drivers/debug_test.hpp" + +#include + +#include "engine/filters.hpp" +#include "engine/kyuafile.hpp" +#include "engine/test_case.hpp" +#include "engine/test_program.hpp" +#include "engine/test_result.hpp" +#include "utils/defs.hpp" +#include "utils/format/macros.hpp" +#include "utils/fs/auto_cleaners.hpp" +#include "utils/optional.ipp" +#include "utils/signals/interrupts.hpp" + +namespace config = utils::config; +namespace fs = utils::fs; +namespace debug_test = engine::drivers::debug_test; +namespace signals = utils::signals; + +using utils::none; +using utils::optional; + + +namespace { + + +/// Looks for a single test case in the Kyuafile. +/// +/// \param filter A filter to match the desired test case. +/// \param kyuafile The test suite in which to look for the test case. +/// +/// \return A pointer to the test case if found. +/// +/// \throw std::runtime_error If the provided filter matches more than one test +/// case or if the test case cannot be found. +static const engine::test_case_ptr +find_test_case(const engine::test_filter& filter, + const engine::kyuafile& kyuafile) +{ + engine::test_case_ptr found;; + + for (engine::test_programs_vector::const_iterator p = + kyuafile.test_programs().begin(); p != kyuafile.test_programs().end(); + p++) { + const engine::test_program_ptr& test_program = *p; + + if (!filter.matches_test_program(test_program->relative_path())) + continue; + + const engine::test_cases_vector test_cases = test_program->test_cases(); + + for (engine::test_cases_vector::const_iterator + iter = test_cases.begin(); iter != test_cases.end(); iter++) { + const engine::test_case_ptr tc = *iter; + + if (filter.matches_test_case(test_program->relative_path(), + tc->name())) { + if (found.get() != NULL) + throw std::runtime_error(F("The filter '%s' matches more " + "than one test case") % + filter.str()); + found = tc; + } + } + } + + if (found.get() == NULL) + throw std::runtime_error(F("Unknown test case '%s'") % filter.str()); + + return found; +} + + +} // anonymous namespace + + +/// Executes the operation. +/// +/// \param kyuafile_path The path to the Kyuafile to be loaded. +/// \param build_root If not none, path to the built test programs. +/// \param filter The test case filter to locate the test to debug. +/// \param user_config The end-user configuration properties. +/// \param stdout_path The name of the file into which to store the test case +/// stdout. +/// \param stderr_path The name of the file into which to store the test case +/// stderr. +/// +/// \returns A structure with all results computed by this driver. +debug_test::result +debug_test::drive(const fs::path& kyuafile_path, + const optional< fs::path > build_root, + const test_filter& filter, + const config::tree& user_config, + const fs::path& stdout_path, + const fs::path& stderr_path) +{ + const engine::kyuafile kyuafile = engine::kyuafile::load( + kyuafile_path, build_root); + const engine::test_case_ptr test_case = find_test_case(filter, kyuafile); + engine::test_case_hooks dummy_hooks; + + signals::interrupts_handler interrupts; + + const fs::auto_directory work_directory = fs::auto_directory::mkdtemp( + "kyua.XXXXXX"); + + const engine::test_result test_result = debug_test_case( + test_case.get(), user_config, dummy_hooks, work_directory.directory(), + stdout_path, stderr_path); + + signals::check_interrupt(); + return result(test_filter( + test_case->container_test_program().relative_path(), + test_case->name()), test_result); +} diff --git a/external/bsd/kyua-cli/dist/engine/drivers/debug_test.hpp b/external/bsd/kyua-cli/dist/engine/drivers/debug_test.hpp new file mode 100644 index 000000000..b96463a7f --- /dev/null +++ b/external/bsd/kyua-cli/dist/engine/drivers/debug_test.hpp @@ -0,0 +1,81 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file engine/drivers/debug_test.hpp +/// Driver to run a single test in a controlled manner. +/// +/// This driver module implements the logic to execute a particular test +/// with hooks into the runtime procedure. This is to permit debugging the +/// behavior of the test. + +#if !defined(ENGINE_DRIVERS_DEBUG_TEST_HPP) +#define ENGINE_DRIVERS_DEBUG_TEST_HPP + +#include "engine/filters.hpp" +#include "engine/test_case.hpp" +#include "engine/test_result.hpp" +#include "utils/config/tree.hpp" +#include "utils/fs/path.hpp" +#include "utils/optional.hpp" + +namespace engine { +namespace drivers { +namespace debug_test { + + +/// Tuple containing the results of this driver. +struct result { + /// A filter matching the executed test case only. + test_filter test_case; + + /// The result of the test case. + engine::test_result test_result; + + /// Initializer for the tuple's fields. + /// + /// \param test_case_ The matched test case. + /// \param test_result_ The result of the test case. + result(const engine::test_filter& test_case_, + const engine::test_result& test_result_) : + test_case(test_case_), + test_result(test_result_) + { + } +}; + + +result drive(const utils::fs::path&, const utils::optional< utils::fs::path >, + const test_filter&, const utils::config::tree&, + const utils::fs::path&, const utils::fs::path&); + + +} // namespace debug_test +} // namespace drivers +} // namespace engine + +#endif // !defined(ENGINE_DRIVERS_DEBUG_TEST_HPP) diff --git a/external/bsd/kyua-cli/dist/engine/drivers/debug_test_test.cpp b/external/bsd/kyua-cli/dist/engine/drivers/debug_test_test.cpp new file mode 100644 index 000000000..68a472f1b --- /dev/null +++ b/external/bsd/kyua-cli/dist/engine/drivers/debug_test_test.cpp @@ -0,0 +1,48 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "engine/drivers/debug_test.hpp" + +#include + + +ATF_TEST_CASE_WITHOUT_HEAD(TODO); +ATF_TEST_CASE_BODY(TODO) +{ + // The debug_tests driver contains the code that was formerly in + // cli/cmd_debug. That code did not have unit tests, and this was left + // empty during the migration. + // TODO(jmmv): Add tests. + skip("Not implemented"); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, TODO); +} diff --git a/external/bsd/kyua-cli/dist/engine/drivers/list_tests.cpp b/external/bsd/kyua-cli/dist/engine/drivers/list_tests.cpp new file mode 100644 index 000000000..95dfb62d6 --- /dev/null +++ b/external/bsd/kyua-cli/dist/engine/drivers/list_tests.cpp @@ -0,0 +1,110 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "engine/drivers/list_tests.hpp" + +#include "engine/exceptions.hpp" +#include "engine/filters.hpp" +#include "engine/kyuafile.hpp" +#include "engine/test_program.hpp" +#include "utils/optional.ipp" + +namespace fs = utils::fs; +namespace list_tests = engine::drivers::list_tests; + +using utils::none; +using utils::optional; + + +namespace { + + +/// Lists a single test program. +/// +/// \param program The test program to print. +/// \param filters [in,out] The filters used to select which test cases to +/// print. These filters are updated on output to mark which of them +/// actually matched a test case. +/// \param hooks The runtime hooks. +static void +list_test_program(const engine::test_program& program, + engine::filters_state& filters, + list_tests::base_hooks& hooks) +{ + const engine::test_cases_vector test_cases = program.test_cases(); + + for (engine::test_cases_vector::const_iterator iter = test_cases.begin(); + iter != test_cases.end(); iter++) { + const engine::test_case_ptr tc = *iter; + + if (filters.match_test_case(program.relative_path(), tc->name())) + hooks.got_test_case(*tc); + } +} + + +} // anonymous namespace + + +/// Pure abstract destructor. +list_tests::base_hooks::~base_hooks(void) +{ +} + + +/// Executes the operation. +/// +/// \param kyuafile_path The path to the Kyuafile to be loaded. +/// \param build_root If not none, path to the built test programs. +/// \param raw_filters The test case filters as provided by the user. +/// \param hooks The hooks for this execution. +/// +/// \returns A structure with all results computed by this driver. +list_tests::result +list_tests::drive(const fs::path& kyuafile_path, + const optional< fs::path > build_root, + const std::set< engine::test_filter >& raw_filters, + base_hooks& hooks) +{ + const engine::kyuafile kyuafile = engine::kyuafile::load( + kyuafile_path, build_root); + filters_state filters(raw_filters); + + for (test_programs_vector::const_iterator iter = + kyuafile.test_programs().begin(); + iter != kyuafile.test_programs().end(); iter++) { + const test_program_ptr& test_program = *iter; + + if (!filters.match_test_program(test_program->relative_path())) + continue; + + list_test_program(*test_program, filters, hooks); + } + + return result(filters.unused()); +} diff --git a/external/bsd/kyua-cli/dist/engine/drivers/list_tests.hpp b/external/bsd/kyua-cli/dist/engine/drivers/list_tests.hpp new file mode 100644 index 000000000..d75773361 --- /dev/null +++ b/external/bsd/kyua-cli/dist/engine/drivers/list_tests.hpp @@ -0,0 +1,89 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file engine/drivers/list_tests.hpp +/// Driver to obtain a list of test cases out of a test suite. +/// +/// This driver module implements the logic to extract a list of test cases out +/// of a particular test suite. + +#if !defined(ENGINE_DRIVERS_LIST_TESTS_HPP) +#define ENGINE_DRIVERS_LIST_TESTS_HPP + +#include + +#include "engine/filters.hpp" +#include "engine/test_case.hpp" +#include "engine/test_program.hpp" +#include "utils/fs/path.hpp" +#include "utils/optional.hpp" + +namespace engine { +namespace drivers { +namespace list_tests { + + +/// Abstract definition of the hooks for this driver. +class base_hooks { +public: + virtual ~base_hooks(void) = 0; + + /// Called when a test case is identified in a test suite. + /// + /// \param test_case The data describing the test case. + virtual void got_test_case(const engine::test_case& test_case) = 0; +}; + + +/// Tuple containing the results of this driver. +struct result { + /// Filters that did not match any available test case. + /// + /// The presence of any filters here probably indicates a usage error. If a + /// test filter does not match any test case, it is probably a typo. + std::set< test_filter > unused_filters; + + /// Initializer for the tuple's fields. + /// + /// \param unused_filters_ The filters that did not match any test case. + result(const std::set< test_filter >& unused_filters_) : + unused_filters(unused_filters_) + { + } +}; + + +result drive(const utils::fs::path&, const utils::optional< utils::fs::path >, + const std::set< test_filter >&, base_hooks&); + + +} // namespace list_tests +} // namespace drivers +} // namespace engine + +#endif // !defined(ENGINE_DRIVERS_LIST_TESTS_HPP) diff --git a/external/bsd/kyua-cli/dist/engine/drivers/list_tests_helpers.cpp b/external/bsd/kyua-cli/dist/engine/drivers/list_tests_helpers.cpp new file mode 100644 index 000000000..3aabab0d7 --- /dev/null +++ b/external/bsd/kyua-cli/dist/engine/drivers/list_tests_helpers.cpp @@ -0,0 +1,80 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include + +#include + + +ATF_TEST_CASE(crash_list); +ATF_TEST_CASE_HEAD(crash_list) +{ + std::abort(); +} +ATF_TEST_CASE_BODY(crash_list) +{ + std::abort(); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(no_properties); +ATF_TEST_CASE_BODY(no_properties) +{ + std::abort(); +} + + +ATF_TEST_CASE(some_properties); +ATF_TEST_CASE_HEAD(some_properties) +{ + set_md_var("descr", "This is a description"); + set_md_var("require.progs", "non-existent /bin/ls"); +} +ATF_TEST_CASE_BODY(some_properties) +{ + std::abort(); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + std::string enabled; + + const char* tests = std::getenv("TESTS"); + if (tests == NULL) + enabled = "crash_list no_properties some_properties"; + else + enabled = tests; + + if (enabled.find("crash_list") != std::string::npos) + ATF_ADD_TEST_CASE(tcs, crash_list); + if (enabled.find("no_properties") != std::string::npos) + ATF_ADD_TEST_CASE(tcs, no_properties); + if (enabled.find("some_properties") != std::string::npos) + ATF_ADD_TEST_CASE(tcs, some_properties); +} diff --git a/external/bsd/kyua-cli/dist/engine/drivers/list_tests_test.cpp b/external/bsd/kyua-cli/dist/engine/drivers/list_tests_test.cpp new file mode 100644 index 000000000..6e49c1be6 --- /dev/null +++ b/external/bsd/kyua-cli/dist/engine/drivers/list_tests_test.cpp @@ -0,0 +1,236 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "engine/drivers/list_tests.hpp" + +extern "C" { +#include + +#include +} + +#include +#include + +#include + +#include "cli/cmd_list.hpp" +#include "cli/common.ipp" +#include "engine/exceptions.hpp" +#include "engine/filters.hpp" +#include "utils/env.hpp" +#include "utils/format/macros.hpp" +#include "utils/optional.ipp" + +namespace list_tests = engine::drivers::list_tests; +namespace fs = utils::fs; + +using utils::none; +using utils::optional; + + +namespace { + + +/// Gets the path to the helpers for this test program. +/// +/// \param test_case A pointer to the currently running test case. +/// +/// \return The path to the helpers binary. +static fs::path +helpers(const atf::tests::tc* test_case) +{ + return fs::path(test_case->get_config_var("srcdir")) / + "list_tests_helpers"; +} + + +/// Hooks to capture the incremental listing of test cases. +class capture_hooks : public list_tests::base_hooks { +public: + /// Set of the listed test cases in a program:test_case form. + std::set< std::string > test_cases; + + /// Called when a test case is identified in a test suite. + /// + /// \param test_case The data describing the test case. + virtual void + got_test_case(const engine::test_case& test_case) + { + test_cases.insert(F("%s:%s") % + test_case.container_test_program().relative_path() % + test_case.name()); + } +}; + + +/// Creates a mock test suite. +/// +/// \param tc Pointer to the caller test case; needed to obtain the srcdir +/// variable of the caller. +/// \param source_root Basename of the directory that will contain the +/// Kyuafiles. +/// \param build_root Basename of the directory that will contain the test +/// programs. May or may not be the same as source_root. +static void +create_helpers(const atf::tests::tc* tc, const fs::path& source_root, + const fs::path& build_root) +{ + ATF_REQUIRE(::mkdir(source_root.c_str(), 0755) != -1); + ATF_REQUIRE(::mkdir((source_root / "dir").c_str(), 0755) != -1); + if (source_root != build_root) { + ATF_REQUIRE(::mkdir(build_root.c_str(), 0755) != -1); + ATF_REQUIRE(::mkdir((build_root / "dir").c_str(), 0755) != -1); + } + ATF_REQUIRE(::symlink(helpers(tc).c_str(), + (build_root / "dir/program").c_str()) != -1); + + atf::utils::create_file( + (source_root / "Kyuafile").str(), + "syntax(2)\n" + "include('dir/Kyuafile')\n"); + + atf::utils::create_file( + (source_root / "dir/Kyuafile").str(), + "syntax(2)\n" + "atf_test_program{name='program', test_suite='suite-name'}\n"); +} + + +/// Runs the mock test suite. +/// +/// \param source_root Path to the directory that contains the Kyuafiles. +/// \param build_root If not none, path to the directory that contains the test +/// programs. +/// \param hooks The hooks to use during the listing. +/// \param filter_program If not null, the filter on the test program name. +/// \param filter_test_case If not null, the filter on the test case name. +/// +/// \return The result data of the driver. +static list_tests::result +run_helpers(const fs::path& source_root, + const optional< fs::path > build_root, + list_tests::base_hooks& hooks, + const char* filter_program = NULL, + const char* filter_test_case = NULL) +{ + std::set< engine::test_filter > filters; + if (filter_program != NULL && filter_test_case != NULL) + filters.insert(engine::test_filter(fs::path(filter_program), + filter_test_case)); + + return list_tests::drive(source_root / "Kyuafile", build_root, filters, + hooks); +} + + +} // anonymous namespace + + +ATF_TEST_CASE_WITHOUT_HEAD(one_test_case); +ATF_TEST_CASE_BODY(one_test_case) +{ + utils::setenv("TESTS", "some_properties"); + capture_hooks hooks; + create_helpers(this, fs::path("root"), fs::path("root")); + run_helpers(fs::path("root"), none, hooks); + + std::set< std::string > exp_test_cases; + exp_test_cases.insert("dir/program:some_properties"); + ATF_REQUIRE(exp_test_cases == hooks.test_cases); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(many_test_cases); +ATF_TEST_CASE_BODY(many_test_cases) +{ + utils::setenv("TESTS", "no_properties some_properties"); + capture_hooks hooks; + create_helpers(this, fs::path("root"), fs::path("root")); + run_helpers(fs::path("root"), none, hooks); + + std::set< std::string > exp_test_cases; + exp_test_cases.insert("dir/program:no_properties"); + exp_test_cases.insert("dir/program:some_properties"); + ATF_REQUIRE(exp_test_cases == hooks.test_cases); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(filter_match); +ATF_TEST_CASE_BODY(filter_match) +{ + utils::setenv("TESTS", "no_properties some_properties"); + capture_hooks hooks; + create_helpers(this, fs::path("root"), fs::path("root")); + run_helpers(fs::path("root"), none, hooks, "dir/program", + "some_properties"); + + std::set< std::string > exp_test_cases; + exp_test_cases.insert("dir/program:some_properties"); + ATF_REQUIRE(exp_test_cases == hooks.test_cases); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(build_root); +ATF_TEST_CASE_BODY(build_root) +{ + utils::setenv("TESTS", "no_properties some_properties"); + capture_hooks hooks; + create_helpers(this, fs::path("source"), fs::path("build")); + run_helpers(fs::path("source"), utils::make_optional(fs::path("build")), + hooks); + + std::set< std::string > exp_test_cases; + exp_test_cases.insert("dir/program:no_properties"); + exp_test_cases.insert("dir/program:some_properties"); + ATF_REQUIRE(exp_test_cases == hooks.test_cases); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(crash); +ATF_TEST_CASE_BODY(crash) +{ + utils::setenv("TESTS", "crash_list some_properties"); + capture_hooks hooks; + create_helpers(this, fs::path("root"), fs::path("root")); + run_helpers(fs::path("root"), none, hooks, "dir/program"); + + std::set< std::string > exp_test_cases; + exp_test_cases.insert("dir/program:__test_cases_list__"); + ATF_REQUIRE(exp_test_cases == hooks.test_cases); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, one_test_case); + ATF_ADD_TEST_CASE(tcs, many_test_cases); + ATF_ADD_TEST_CASE(tcs, filter_match); + ATF_ADD_TEST_CASE(tcs, build_root); + ATF_ADD_TEST_CASE(tcs, crash); +} diff --git a/external/bsd/kyua-cli/dist/engine/drivers/run_tests.cpp b/external/bsd/kyua-cli/dist/engine/drivers/run_tests.cpp new file mode 100644 index 000000000..b49452ee0 --- /dev/null +++ b/external/bsd/kyua-cli/dist/engine/drivers/run_tests.cpp @@ -0,0 +1,208 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "engine/drivers/run_tests.hpp" + +#include "engine/action.hpp" +#include "engine/context.hpp" +#include "engine/filters.hpp" +#include "engine/kyuafile.hpp" +#include "engine/test_program.hpp" +#include "engine/test_result.hpp" +#include "store/backend.hpp" +#include "store/transaction.hpp" +#include "utils/datetime.hpp" +#include "utils/defs.hpp" +#include "utils/format/macros.hpp" +#include "utils/fs/auto_cleaners.hpp" +#include "utils/logging/macros.hpp" +#include "utils/optional.ipp" +#include "utils/signals/interrupts.hpp" + +namespace config = utils::config; +namespace datetime = utils::datetime; +namespace fs = utils::fs; +namespace run_tests = engine::drivers::run_tests; +namespace signals = utils::signals; + +using utils::optional; + + +namespace { + + +/// Test case hooks to save the output into the database. +class file_saver_hooks : public engine::test_case_hooks { + /// Open write transaction for the test case's data. + store::transaction& _tx; + + /// Identifier of the test case being stored. + const int64_t _test_case_id; + +public: + /// Constructs a new set of hooks. + /// + /// \param tx_ Open write transaction for the test case's data. + /// \param test_case_id_ Identifier of the test case being stored. + file_saver_hooks(store::transaction& tx_, + const int64_t test_case_id_) : + _tx(tx_), _test_case_id(test_case_id_) + { + } + + /// Stores the stdout of the test case into the database. + /// + /// \param file Path to the stdout of the test case. + void + got_stdout(const fs::path& file) + { + _tx.put_test_case_file("__STDOUT__", file, _test_case_id); + } + + /// Stores the stderr of the test case into the database. + /// + /// \param file Path to the stderr of the test case. + void + got_stderr(const fs::path& file) + { + _tx.put_test_case_file("__STDERR__", file, _test_case_id); + } +}; + + +/// Runs a test program in a controlled manner. +/// +/// If the test program fails to provide a list of test cases, a fake test case +/// named '__test_program__' is created and it is reported as broken. +/// +/// \param program The test program to execute. +/// \param user_config The configuration variables provided by the user. +/// \param filters The matching state of the filters. +/// \param hooks The user hooks to receive asynchronous notifications. +/// \param work_directory Temporary directory to use. +/// \param tx The store transaction into which to put the results. +/// \param action_id The action this program belongs to. +void +run_test_program(const engine::test_program& program, + const config::tree& user_config, + engine::filters_state& filters, + run_tests::base_hooks& hooks, + const fs::path& work_directory, + store::transaction& tx, + const int64_t action_id) +{ + LI(F("Processing test program '%s'") % program.relative_path()); + const int64_t test_program_id = tx.put_test_program(program, action_id); + + const engine::test_cases_vector& test_cases = program.test_cases(); + for (engine::test_cases_vector::const_iterator iter = test_cases.begin(); + iter != test_cases.end(); iter++) { + const engine::test_case_ptr test_case = *iter; + + if (!filters.match_test_case(program.relative_path(), + test_case->name())) + continue; + + const int64_t test_case_id = tx.put_test_case(*test_case, + test_program_id); + file_saver_hooks test_hooks(tx, test_case_id); + hooks.got_test_case(test_case); + const datetime::timestamp start_time = datetime::timestamp::now(); + const engine::test_result result = run_test_case( + test_case.get(), user_config, test_hooks, work_directory); + const datetime::timestamp end_time = datetime::timestamp::now(); + tx.put_result(result, test_case_id, start_time, end_time); + hooks.got_result(test_case, result, end_time - start_time); + + signals::check_interrupt(); + } +} + + +} // anonymous namespace + + +/// Pure abstract destructor. +run_tests::base_hooks::~base_hooks(void) +{ +} + + +/// Executes the operation. +/// +/// \param kyuafile_path The path to the Kyuafile to be loaded. +/// \param build_root If not none, path to the built test programs. +/// \param store_path The path to the store to be used. +/// \param raw_filters The test case filters as provided by the user. +/// \param user_config The end-user configuration properties. +/// \param hooks The hooks for this execution. +/// +/// \returns A structure with all results computed by this driver. +run_tests::result +run_tests::drive(const fs::path& kyuafile_path, + const optional< fs::path > build_root, + const fs::path& store_path, + const std::set< engine::test_filter >& raw_filters, + const config::tree& user_config, + base_hooks& hooks) +{ + const engine::kyuafile kyuafile = engine::kyuafile::load( + kyuafile_path, build_root); + filters_state filters(raw_filters); + store::backend db = store::backend::open_rw(store_path); + store::transaction tx = db.start(); + + engine::context context = engine::context::current(); + const int64_t context_id = tx.put_context(context); + + engine::action action(context); + const int64_t action_id = tx.put_action(action, context_id); + + signals::interrupts_handler interrupts; + + const fs::auto_directory work_directory = fs::auto_directory::mkdtemp( + "kyua.XXXXXX"); + + for (test_programs_vector::const_iterator iter = + kyuafile.test_programs().begin(); + iter != kyuafile.test_programs().end(); iter++) { + const test_program_ptr& test_program = *iter; + + if (!filters.match_test_program(test_program->relative_path())) + continue; + + run_test_program(*test_program, user_config, filters, hooks, + work_directory.directory(), tx, action_id); + + signals::check_interrupt(); + } + + tx.commit(); + + return result(action_id, filters.unused()); +} diff --git a/external/bsd/kyua-cli/dist/engine/drivers/run_tests.hpp b/external/bsd/kyua-cli/dist/engine/drivers/run_tests.hpp new file mode 100644 index 000000000..9ce40be76 --- /dev/null +++ b/external/bsd/kyua-cli/dist/engine/drivers/run_tests.hpp @@ -0,0 +1,112 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file engine/drivers/run_tests.hpp +/// Driver to run a collection of tests. +/// +/// This driver module implements the logic to execute a collection of tests. +/// The presentation layer is able to monitor progress by hooking into +/// particular points of the driver. + +#if !defined(ENGINE_DRIVERS_RUN_TESTS_HPP) +#define ENGINE_DRIVERS_RUN_TESTS_HPP + +extern "C" { +#include +} + +#include + +#include "engine/filters.hpp" +#include "engine/test_case.hpp" +#include "utils/config/tree.hpp" +#include "utils/datetime.hpp" +#include "utils/fs/path.hpp" +#include "utils/optional.hpp" + +namespace engine { +class test_result; +namespace drivers { +namespace run_tests { + + +/// Abstract definition of the hooks for this driver. +class base_hooks { +public: + virtual ~base_hooks(void) = 0; + + /// Called when the processing of a test case begins. + /// + /// \param test_case The test case. + virtual void got_test_case(const engine::test_case_ptr& test_case) = 0; + + /// Called when a result of a test case becomes available. + /// + /// \param test_case The test case. + /// \param result The result of the execution of the test case. + /// \param duration The time it took to run the test. + virtual void got_result(const engine::test_case_ptr& test_case, + const engine::test_result& result, + const utils::datetime::delta& duration) = 0; +}; + + +/// Tuple containing the results of this driver. +struct result { + /// The identifier assigned to the operation. + int64_t action_id; + + /// Filters that did not match any available test case. + /// + /// The presence of any filters here probably indicates a usage error. If a + /// test filter does not match any test case, it is probably a typo. + std::set< test_filter > unused_filters; + + /// Initializer for the tuple's fields. + /// + /// \param action_id_ The identifier assigned to the operation. + /// \param unused_filters_ The filters that did not match any test case. + result(const int64_t action_id_, + const std::set< test_filter >& unused_filters_) : + action_id(action_id_), + unused_filters(unused_filters_) + { + } +}; + + +result drive(const utils::fs::path&, const utils::optional< utils::fs::path >, + const utils::fs::path&, const std::set< test_filter >&, + const utils::config::tree&, base_hooks&); + + +} // namespace run_tests +} // namespace drivers +} // namespace engine + +#endif // !defined(ENGINE_DRIVERS_RUN_TESTS_HPP) diff --git a/external/bsd/kyua-cli/dist/engine/drivers/run_tests_test.cpp b/external/bsd/kyua-cli/dist/engine/drivers/run_tests_test.cpp new file mode 100644 index 000000000..c5bd77d73 --- /dev/null +++ b/external/bsd/kyua-cli/dist/engine/drivers/run_tests_test.cpp @@ -0,0 +1,48 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "engine/drivers/run_tests.hpp" + +#include + + +ATF_TEST_CASE_WITHOUT_HEAD(TODO); +ATF_TEST_CASE_BODY(TODO) +{ + // The run_tests driver contains the code that was formerly in + // cli/cmd_test. That code did not have unit tests, and this was left empty + // during the migration. + // TODO(jmmv): Add tests. + skip("Not implemented"); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, TODO); +} diff --git a/external/bsd/kyua-cli/dist/engine/drivers/scan_action.cpp b/external/bsd/kyua-cli/dist/engine/drivers/scan_action.cpp new file mode 100644 index 000000000..67bee65bb --- /dev/null +++ b/external/bsd/kyua-cli/dist/engine/drivers/scan_action.cpp @@ -0,0 +1,111 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "engine/drivers/scan_action.hpp" + +#include "engine/action.hpp" +#include "engine/exceptions.hpp" +#include "engine/test_result.hpp" +#include "store/backend.hpp" +#include "store/exceptions.hpp" +#include "store/transaction.hpp" +#include "utils/optional.ipp" + +namespace fs = utils::fs; +namespace scan_action = engine::drivers::scan_action; + +using utils::optional; + + +namespace { + + +/// Gets an action from the store. +/// +/// \param tx The open store transaction. +/// \param [in,out] action_id The specific action to get, or none to fetch the +/// latest available action. This is updated to contain the action id of +/// the returned action. +/// +/// \return The fetched action. +/// +/// \throw error If there is any problem while loading the action. +static engine::action +get_action(store::transaction& tx, optional< int64_t >& action_id) +{ + try { + if (action_id) + return tx.get_action(action_id.get()); + else { + const std::pair< int64_t, engine::action > latest_action = + tx.get_latest_action(); + action_id = latest_action.first; + return latest_action.second; + } + } catch (const store::error& e) { + throw engine::error(e.what()); + } +} + + +} // anonymous namespace + + +/// Pure abstract destructor. +scan_action::base_hooks::~base_hooks(void) +{ +} + + +/// Executes the operation. +/// +/// \param store_path The path to the database store. +/// \param action_id The identifier of the action to scan; if none, scans the +/// latest action in the store. +/// \param hooks The hooks for this execution. +/// +/// \returns A structure with all results computed by this driver. +scan_action::result +scan_action::drive(const fs::path& store_path, + optional< int64_t > action_id, + base_hooks& hooks) +{ + store::backend db = store::backend::open_ro(store_path); + store::transaction tx = db.start(); + + const engine::action action = get_action(tx, action_id); + hooks.got_action(action_id.get(), action); + + store::results_iterator iter = tx.get_action_results(action_id.get()); + while (iter) { + hooks.got_result(iter); + ++iter; + } + + return result(); +} diff --git a/external/bsd/kyua-cli/dist/engine/drivers/scan_action.hpp b/external/bsd/kyua-cli/dist/engine/drivers/scan_action.hpp new file mode 100644 index 000000000..30970b670 --- /dev/null +++ b/external/bsd/kyua-cli/dist/engine/drivers/scan_action.hpp @@ -0,0 +1,97 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file engine/drivers/scan_action.hpp +/// Driver to scan the contents of an action. +/// +/// This driver module implements the logic to scan the contents of an stored +/// action and to notify the presentation layer as soon as data becomes +/// available. This is to prevent reading all the data from the action at once, +/// which could take too much memory. + +#if !defined(ENGINE_DRIVERS_SCAN_ACTION_HPP) +#define ENGINE_DRIVERS_SCAN_ACTION_HPP + +extern "C" { +#include +} + +#include "engine/test_program.hpp" +#include "store/transaction.hpp" +#include "utils/datetime.hpp" +#include "utils/fs/path.hpp" +#include "utils/optional.hpp" + +namespace engine { + +class action; +class test_result; + +namespace drivers { +namespace scan_action { + + +/// Abstract definition of the hooks for this driver. +class base_hooks { +public: + virtual ~base_hooks(void) = 0; + + /// Callback executed when an action is found. + /// + /// \param action_id The identifier of the loaded action. + /// \param action The action loaded from the database. + virtual void got_action(const int64_t action_id, + const engine::action& action) = 0; + + /// Callback executed when a test results is found. + /// + /// \param iter Container for the test result's data. Some of the data are + /// lazily fetched, hence why we receive the object instead of the + /// individual elements. + virtual void got_result(store::results_iterator& iter) = 0; +}; + + +/// Tuple containing the results of this driver. +struct result { + /// Initializer for the tuple's fields. + result(void) + { + } +}; + + +result drive(const utils::fs::path&, utils::optional< int64_t >, + base_hooks&); + + +} // namespace scan_action +} // namespace drivers +} // namespace engine + +#endif // !defined(ENGINE_DRIVERS_SCAN_ACTION_HPP) diff --git a/external/bsd/kyua-cli/dist/engine/drivers/scan_action_test.cpp b/external/bsd/kyua-cli/dist/engine/drivers/scan_action_test.cpp new file mode 100644 index 000000000..5e98cec80 --- /dev/null +++ b/external/bsd/kyua-cli/dist/engine/drivers/scan_action_test.cpp @@ -0,0 +1,224 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "engine/drivers/scan_action.hpp" + +#include + +#include + +#include "engine/action.hpp" +#include "engine/context.hpp" +#include "engine/test_result.hpp" +#include "store/backend.hpp" +#include "store/exceptions.hpp" +#include "store/transaction.hpp" +#include "utils/datetime.hpp" +#include "utils/format/macros.hpp" +#include "utils/optional.ipp" +#include "utils/sanity.hpp" + +namespace datetime = utils::datetime; +namespace fs = utils::fs; +namespace scan_action = engine::drivers::scan_action; + +using utils::none; +using utils::optional; + + +namespace { + + +/// Records the callback values for futher investigation. +class capture_hooks : public scan_action::base_hooks { +public: + /// The captured action ID, if any. + optional< int64_t > _action_id; + + /// The captured action, if any. + optional< engine::action > _action; + + /// The captured results, flattened as "program:test_case:result". + std::set< std::string > _results; + + /// Callback executed when an action is found. + /// + /// \param action_id The identifier of the loaded action. + /// \param action The action loaded from the database. + void got_action(const int64_t action_id, + const engine::action& action) + { + PRE(!_action_id); + _action_id = action_id; + PRE(!_action); + _action = action; + } + + /// Callback executed when a test results is found. + /// + /// \param iter Container for the test result's data. + void got_result(store::results_iterator& iter) + { + const char* type; + switch (iter.result().type()) { + case engine::test_result::passed: type = "passed"; break; + case engine::test_result::skipped: type = "skipped"; break; + default: + UNREACHABLE_MSG("Formatting unimplemented"); + } + _results.insert(F("%s:%s:%s:%s:%s:%s") % + iter.test_program()->absolute_path() % + iter.test_case_name() % type % iter.result().reason() % + iter.duration().seconds % iter.duration().useconds); + } +}; + + +/// Populates a test database with a new action. +/// +/// It is OK to call this function multiple times on the same file. Doing this +/// will generate a new action every time on the test database. +/// +/// \param db_name The database to update. +/// \param count A number that indicates how many elements to insert in the +/// action. Can be used to determine from the caller which particular +/// action has been loaded. +/// +/// \return The identifier of the committed action. +static int64_t +populate_db(const char* db_name, const int count) +{ + store::backend backend = store::backend::open_rw(fs::path(db_name)); + + store::transaction tx = backend.start(); + + std::map< std::string, std::string > env; + for (int i = 0; i < count; i++) + env[F("VAR%s") % i] = F("Value %s") % i; + const engine::context context(fs::path("/root"), env); + const engine::action action(context); + const int64_t context_id = tx.put_context(context); + const int64_t action_id = tx.put_action(action, context_id); + + for (int i = 0; i < count; i++) { + const engine::test_program test_program( + "plain", fs::path(F("dir/prog_%s") % i), fs::path("/root"), + F("suite_%s") % i, engine::metadata_builder().build()); + const int64_t tp_id = tx.put_test_program(test_program, action_id); + + for (int j = 0; j < count; j++) { + const engine::test_case test_case( + "plain", test_program, "main", + engine::metadata_builder().build()); + const engine::test_result result(engine::test_result::skipped, + F("Count %s") % j); + const int64_t tc_id = tx.put_test_case(test_case, tp_id); + const datetime::timestamp start = + datetime::timestamp::from_microseconds(1000010); + const datetime::timestamp end = + datetime::timestamp::from_microseconds(5000020 + i + j); + tx.put_result(result, tc_id, start, end); + } + } + + tx.commit(); + + return action_id; +} + + +} // anonymous namespace + + +ATF_TEST_CASE_WITHOUT_HEAD(latest_action); +ATF_TEST_CASE_BODY(latest_action) +{ + (void)populate_db("test.db", 3); + const int64_t action_id = populate_db("test.db", 2); + + capture_hooks hooks; + scan_action::drive(fs::path("test.db"), none, hooks); + + ATF_REQUIRE_EQ(action_id, hooks._action_id.get()); + + std::map< std::string, std::string > env; + env["VAR0"] = "Value 0"; + env["VAR1"] = "Value 1"; + const engine::context context(fs::path("/root"), env); + const engine::action action(context); + ATF_REQUIRE(action == hooks._action.get()); + + std::set< std::string > results; + results.insert("/root/dir/prog_0:main:skipped:Count 0:4:10"); + results.insert("/root/dir/prog_0:main:skipped:Count 1:4:11"); + results.insert("/root/dir/prog_1:main:skipped:Count 0:4:11"); + results.insert("/root/dir/prog_1:main:skipped:Count 1:4:12"); + ATF_REQUIRE(results == hooks._results); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(explicit_action); +ATF_TEST_CASE_BODY(explicit_action) +{ + (void)populate_db("test.db", 5); + const int64_t action_id = populate_db("test.db", 1); + (void)populate_db("test.db", 2); + + capture_hooks hooks; + scan_action::drive(fs::path("test.db"), + optional< int64_t >(action_id), hooks); + + ATF_REQUIRE_EQ(action_id, hooks._action_id.get()); + + std::map< std::string, std::string > env; + env["VAR0"] = "Value 0"; + const engine::context context(fs::path("/root"), env); + const engine::action action(context); + ATF_REQUIRE(action == hooks._action.get()); + + std::set< std::string > results; + results.insert("/root/dir/prog_0:main:skipped:Count 0:4:10"); + ATF_REQUIRE(results == hooks._results); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(missing_db); +ATF_TEST_CASE_BODY(missing_db) +{ + capture_hooks hooks; + ATF_REQUIRE_THROW(store::error, + scan_action::drive(fs::path("test.db"), none, hooks)); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, latest_action); + ATF_ADD_TEST_CASE(tcs, explicit_action); + ATF_ADD_TEST_CASE(tcs, missing_db); +} diff --git a/external/bsd/kyua-cli/dist/engine/exceptions.cpp b/external/bsd/kyua-cli/dist/engine/exceptions.cpp new file mode 100644 index 000000000..8fb3eb17f --- /dev/null +++ b/external/bsd/kyua-cli/dist/engine/exceptions.cpp @@ -0,0 +1,96 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "engine/exceptions.hpp" + +#include "utils/format/macros.hpp" + +namespace fs = utils::fs; + +/// Constructs a new error with a plain-text message. +/// +/// \param message The plain-text error message. +engine::error::error(const std::string& message) : + std::runtime_error(message) +{ +} + + +/// Destructor for the error. +engine::error::~error(void) throw() +{ +} + + +/// Constructs a new format_error. +/// +/// \param message The plain-text error message. +engine::format_error::format_error(const std::string& message) : + error(message) +{ +} + + +/// Destructor for the error. +engine::format_error::~format_error(void) throw() +{ +} + + +/// Constructs a new load_error. +/// +/// \param file_ The file in which the error was encountered. +/// \param reason_ Description of the load problem. +engine::load_error::load_error(const fs::path& file_, + const std::string& reason_) : + error(F("Load of '%s' failed: %s") % file_ % reason_), + file(file_), + reason(reason_) +{ +} + + +/// Destructor for the error. +engine::load_error::~load_error(void) throw() +{ +} + + +/// Constructs a new not_found_error. +/// +/// \param message The plain-text error message. +engine::not_found_error::not_found_error(const std::string& message) : + error(message) +{ +} + + +/// Destructor for the error. +engine::not_found_error::~not_found_error(void) throw() +{ +} diff --git a/external/bsd/kyua-cli/dist/engine/exceptions.hpp b/external/bsd/kyua-cli/dist/engine/exceptions.hpp new file mode 100644 index 000000000..015ad903d --- /dev/null +++ b/external/bsd/kyua-cli/dist/engine/exceptions.hpp @@ -0,0 +1,83 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file engine/exceptions.hpp +/// Exception types raised by the engine module. + +#if !defined(ENGINE_EXCEPTIONS_HPP) +#define ENGINE_EXCEPTIONS_HPP + +#include + +#include "utils/fs/path.hpp" + +namespace engine { + + +/// Base exception for engine errors. +class error : public std::runtime_error { +public: + explicit error(const std::string&); + virtual ~error(void) throw(); +}; + + +/// Error while parsing external data. +class format_error : public error { +public: + explicit format_error(const std::string&); + virtual ~format_error(void) throw(); +}; + + +/// Error while parsing external data. +class load_error : public error { +public: + /// The path to the file that caused the load error. + utils::fs::path file; + + /// The reason for the error; may not include the file name. + std::string reason; + + explicit load_error(const utils::fs::path&, const std::string&); + virtual ~load_error(void) throw(); +}; + + +/// A requested element could not be found. +class not_found_error : public error { +public: + explicit not_found_error(const std::string&); + virtual ~not_found_error(void) throw(); +}; + + +} // namespace engine + + +#endif // !defined(ENGINE_EXCEPTIONS_HPP) diff --git a/external/bsd/kyua-cli/dist/engine/exceptions_test.cpp b/external/bsd/kyua-cli/dist/engine/exceptions_test.cpp new file mode 100644 index 000000000..d1c927438 --- /dev/null +++ b/external/bsd/kyua-cli/dist/engine/exceptions_test.cpp @@ -0,0 +1,78 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "engine/exceptions.hpp" + +#include + +#include + +namespace fs = utils::fs; + + +ATF_TEST_CASE_WITHOUT_HEAD(error); +ATF_TEST_CASE_BODY(error) +{ + const engine::error e("Some text"); + ATF_REQUIRE(std::strcmp("Some text", e.what()) == 0); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(format_error); +ATF_TEST_CASE_BODY(format_error) +{ + const engine::format_error e("Some other text"); + ATF_REQUIRE(std::strcmp("Some other text", e.what()) == 0); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(load_error); +ATF_TEST_CASE_BODY(load_error) +{ + const engine::load_error e(fs::path("/my/file"), "foo"); + ATF_REQUIRE_EQ(fs::path("/my/file"), e.file); + ATF_REQUIRE_EQ("foo", e.reason); + ATF_REQUIRE(std::strcmp("Load of '/my/file' failed: foo", e.what()) == 0); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(not_found_error); +ATF_TEST_CASE_BODY(not_found_error) +{ + const engine::not_found_error e("Missing foo"); + ATF_REQUIRE(std::strcmp("Missing foo", e.what()) == 0); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, error); + ATF_ADD_TEST_CASE(tcs, format_error); + ATF_ADD_TEST_CASE(tcs, load_error); + ATF_ADD_TEST_CASE(tcs, not_found_error); +} diff --git a/external/bsd/kyua-cli/dist/engine/filters.cpp b/external/bsd/kyua-cli/dist/engine/filters.cpp new file mode 100644 index 000000000..e4b037ab4 --- /dev/null +++ b/external/bsd/kyua-cli/dist/engine/filters.cpp @@ -0,0 +1,371 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "engine/filters.hpp" + +#include +#include + +#include "engine/test_case.hpp" +#include "utils/format/macros.hpp" +#include "utils/fs/exceptions.hpp" +#include "utils/logging/macros.hpp" +#include "utils/optional.ipp" +#include "utils/sanity.hpp" + +namespace fs = utils::fs; + +using utils::none; +using utils::optional; + + +/// Constructs a filter. +/// +/// \param test_program_ The name of the test program or of the subdirectory to +/// match. +/// \param test_case_ The name of the test case to match. +engine::test_filter::test_filter(const fs::path& test_program_, + const std::string& test_case_) : + test_program(test_program_), + test_case(test_case_) +{ +} + + +/// Parses a user-provided test filter. +/// +/// \param str The user-provided string representing a filter for tests. Must +/// be of the form <test_program%gt;[:<test_case%gt;]. +/// +/// \return The parsed filter. +/// +/// \throw std::runtime_error If the provided filter is invalid. +engine::test_filter +engine::test_filter::parse(const std::string& str) +{ + if (str.empty()) + throw std::runtime_error("Test filter cannot be empty"); + + const std::string::size_type pos = str.find(':'); + if (pos == 0) + throw std::runtime_error(F("Program name component in '%s' is empty") + % str); + if (pos == str.length() - 1) + throw std::runtime_error(F("Test case component in '%s' is empty") + % str); + + try { + const fs::path test_program_(str.substr(0, pos)); + if (test_program_.is_absolute()) + throw std::runtime_error(F("Program name '%s' must be relative " + "to the test suite, not absolute") % + test_program_.str()); + if (pos == std::string::npos) { + LD(F("Parsed user filter '%s': test program '%s', no test case") % + str % test_program_.str()); + return test_filter(test_program_, ""); + } else { + const std::string test_case_(str.substr(pos + 1)); + LD(F("Parsed user filter '%s': test program '%s', test case '%s'") % + str % test_program_.str() % test_case_); + return test_filter(test_program_, test_case_); + } + } catch (const fs::error& e) { + throw std::runtime_error(F("Invalid path in filter '%s': %s") % str % + e.what()); + } +} + + +/// Formats a filter for user presentation. +/// +/// \return A user-friendly string representing the filter. Note that this does +/// not necessarily match the string the user provided: in particular, the path +/// may have been internally normalized. +std::string +engine::test_filter::str(void) const +{ + if (!test_case.empty()) + return F("%s:%s") % test_program % test_case; + else + return test_program.str(); +} + + +/// Checks if this filter contains another. +/// +/// \param other The filter to compare to. +/// +/// \return True if this filter contains the other filter or if they are equal. +bool +engine::test_filter::contains(const test_filter& other) const +{ + if (*this == other) + return true; + else + return test_case.empty() && test_program.is_parent_of( + other.test_program); +} + + +/// Checks if this filter matches a given test program name or subdirectory. +/// +/// \param test_program_ The test program to compare to. +/// +/// \return Whether the filter matches the test program. This is a superset of +/// matches_test_case. +bool +engine::test_filter::matches_test_program(const fs::path& test_program_) const +{ + if (test_program == test_program_) + return true; + else { + // Check if the filter matches a subdirectory of the test program. + // The test case must be empty because we don't want foo:bar to match + // foo/baz. + return (test_case.empty() && test_program.is_parent_of(test_program_)); + } +} + + +/// Checks if this filter matches a given test case identifier. +/// +/// \param test_program_ The test program to compare to. +/// \param test_case_ The test case to compare to. +/// +/// \return Whether the filter matches the test case. +bool +engine::test_filter::matches_test_case(const fs::path& test_program_, + const std::string& test_case_) const +{ + if (matches_test_program(test_program_)) { + return test_case.empty() || test_case == test_case_; + } else + return false; +} + + +/// Less-than comparison for sorting purposes. +/// +/// \param other The filter to compare to. +/// +/// \return True if this filter sorts before the other filter. +bool +engine::test_filter::operator<(const test_filter& other) const +{ + return ( + test_program < other.test_program || + (test_program == other.test_program && test_case < other.test_case)); +} + + +/// Equality comparison. +/// +/// \param other The filter to compare to. +/// +/// \return True if this filter is equal to the other filter. +bool +engine::test_filter::operator==(const test_filter& other) const +{ + return test_program == other.test_program && test_case == other.test_case; +} + + +/// Non-equality comparison. +/// +/// \param other The filter to compare to. +/// +/// \return True if this filter is different than the other filter. +bool +engine::test_filter::operator!=(const test_filter& other) const +{ + return !(*this == other); +} + + +/// Constructs a new set of filters. +/// +/// \param filters_ The filters themselves; if empty, no filters are applied. +engine::test_filters::test_filters(const std::set< test_filter >& filters_) : + _filters(filters_) +{ +} + + +/// Checks if a given test program matches the set of filters. +/// +/// This is provided as an optimization only, and the results of this function +/// are less specific than those of match_test_case. Checking for the matching +/// of a test program should be done before loading the list of test cases from +/// a program, so as to avoid the delay in executing the test program, but +/// match_test_case must still be called afterwards. +/// +/// \param name The test program to check against the filters. +/// +/// \return True if the provided identifier matches any filter. +bool +engine::test_filters::match_test_program(const fs::path& name) const +{ + if (_filters.empty()) + return true; + + bool matches = false; + for (std::set< test_filter >::const_iterator iter = _filters.begin(); + !matches && iter != _filters.end(); iter++) { + matches = (*iter).matches_test_program(name); + } + return matches; +} + + +/// Checks if a given test case identifier matches the set of filters. +/// +/// \param test_program The test program to check against the filters. +/// \param test_case The test case to check against the filters. +/// +/// \return A boolean indicating if the test case is matched by any filter and, +/// if true, a string containing the filter name. The string is empty when +/// there are no filters defined. +engine::test_filters::match +engine::test_filters::match_test_case(const fs::path& test_program, + const std::string& test_case) const +{ + if (_filters.empty()) { + INV(match_test_program(test_program)); + return match(true, none); + } + + optional< test_filter > found = none; + for (std::set< test_filter >::const_iterator iter = _filters.begin(); + !found && iter != _filters.end(); iter++) { + if ((*iter).matches_test_case(test_program, test_case)) + found = *iter; + } + INV(!found || match_test_program(test_program)); + return match(static_cast< bool >(found), found); +} + + +/// Calculates the filters that have not matched any tests. +/// +/// \param matched The filters that did match some tests. This must be a subset +/// of the filters held by this object. +/// +/// \return The set of filters that have not been used. +std::set< engine::test_filter > +engine::test_filters::difference(const std::set< test_filter >& matched) const +{ + PRE(std::includes(_filters.begin(), _filters.end(), + matched.begin(), matched.end())); + + std::set< test_filter > filters; + std::set_difference(_filters.begin(), _filters.end(), + matched.begin(), matched.end(), + std::inserter(filters, filters.begin())); + return filters; +} + + +/// Checks if a collection of filters is disjoint. +/// +/// \param filters The filters to check. +/// +/// \throw std::runtime_error If the filters are not disjoint. +void +engine::check_disjoint_filters(const std::set< engine::test_filter >& filters) +{ + // Yes, this is an O(n^2) algorithm. However, we can assume that the number + // of test filters (which are provided by the user on the command line) on a + // particular run is in the order of tens, and thus this should not cause + // any serious performance trouble. + for (std::set< test_filter >::const_iterator i1 = filters.begin(); + i1 != filters.end(); i1++) { + for (std::set< test_filter >::const_iterator i2 = filters.begin(); + i2 != filters.end(); i2++) { + const test_filter& filter1 = *i1; + const test_filter& filter2 = *i2; + + if (i1 != i2 && filter1.contains(filter2)) { + throw std::runtime_error( + F("Filters '%s' and '%s' are not disjoint") % + filter1.str() % filter2.str()); + } + } + } +} + + +/// Constructs a filters_state instance. +/// +/// \param filters_ The set of filters to track. +engine::filters_state::filters_state( + const std::set< engine::test_filter >& filters_) : + _filters(test_filters(filters_)) +{ +} + + +/// Checks whether these filters match the given test program. +/// +/// \param test_program The test program to match against. +/// +/// \return True if these filters match the given test program name. +bool +engine::filters_state::match_test_program(const fs::path& test_program) const +{ + return _filters.match_test_program(test_program); +} + + +/// Checks whether these filters match the given test case. +/// +/// \param test_program The test program to match against. +/// \param test_case The test case to match against. +/// +/// \return True if these filters match the given test case identifier. +bool +engine::filters_state::match_test_case(const fs::path& test_program, + const std::string& test_case) +{ + engine::test_filters::match match = _filters.match_test_case( + test_program, test_case); + if (match.first && match.second) + _used_filters.insert(match.second.get()); + return match.first; +} + + +/// Calculates the unused filters in this set. +/// +/// \return Returns the set of filters that have not matched any tests. This +/// information is useful to report usage errors to the user. +std::set< engine::test_filter > +engine::filters_state::unused(void) const +{ + return _filters.difference(_used_filters); +} diff --git a/external/bsd/kyua-cli/dist/engine/filters.hpp b/external/bsd/kyua-cli/dist/engine/filters.hpp new file mode 100644 index 000000000..d1f5d25dc --- /dev/null +++ b/external/bsd/kyua-cli/dist/engine/filters.hpp @@ -0,0 +1,127 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file engine/filters.hpp +/// Representation and manipulation of filters for test cases. +/// +/// All the filter classes in this module are supposed to be purely functional: +/// they are mere filters that decide whether they match or not the input data +/// fed to them. User-interface filter manipulation must go somewhere else. + +#if !defined(ENGINE_FILTERS_HPP) +#define ENGINE_FILTERS_HPP + +#include +#include +#include + +#include "utils/fs/path.hpp" +#include "utils/optional.ipp" + + +namespace engine { + + +/// Filter for test cases. +/// +/// A filter is one of: the name of a directory containing test cases, the name +/// of a test program, or the name of a test program plus the name of a test +/// case. +struct test_filter { + /// The name of the test program or subdirectory to match. + utils::fs::path test_program; + + /// The name of the test case to match; if empty, represents any test case. + std::string test_case; + + test_filter(const utils::fs::path&, const std::string&); + static test_filter parse(const std::string&); + + std::string str(void) const; + + bool contains(const test_filter&) const; + bool matches_test_program(const utils::fs::path&) const; + bool matches_test_case(const utils::fs::path&, const std::string&) const; + + bool operator<(const test_filter&) const; + bool operator==(const test_filter&) const; + bool operator!=(const test_filter&) const; +}; + + +/// Collection of user-provided filters to select test cases. +/// +/// An empty collection of filters is considered to match any test case. +/// +/// In general, the filters maintained by this class should be disjoint. If +/// they are not, some filters may never have a chance to do a match, which is +/// most likely the fault of the user. To check for non-disjoint filters before +/// constructing this object, use check_disjoint_filters. +class test_filters { + /// The user-provided filters. + std::set< test_filter > _filters; + +public: + explicit test_filters(const std::set< test_filter >&); + + /// Return type of match_test_case. Indicates whether the filters have + /// matched a particular test case and, if they have, which filter did the + /// match (if any). + typedef std::pair< bool, utils::optional< test_filter > > match; + + bool match_test_program(const utils::fs::path&) const; + match match_test_case(const utils::fs::path&, const std::string&) const; + + std::set< test_filter > difference(const std::set< test_filter >&) const; +}; + + +void check_disjoint_filters(const std::set< test_filter >&); + + +/// Tracks state of the filters that have matched tests during execution. +class filters_state { + /// The user-provided filters. + test_filters _filters; + + /// Collection of filters that have matched test cases so far. + std::set< test_filter > _used_filters; + +public: + explicit filters_state(const std::set< test_filter >&); + + bool match_test_program(const utils::fs::path&) const; + bool match_test_case(const utils::fs::path&, const std::string&); + + std::set< test_filter > unused(void) const; +}; + + +} // namespace engine + +#endif // !defined(ENGINE_FILTERS_HPP) diff --git a/external/bsd/kyua-cli/dist/engine/filters_test.cpp b/external/bsd/kyua-cli/dist/engine/filters_test.cpp new file mode 100644 index 000000000..49b73186f --- /dev/null +++ b/external/bsd/kyua-cli/dist/engine/filters_test.cpp @@ -0,0 +1,570 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "engine/filters.hpp" + +#include + +#include + +#include "engine/test_case.hpp" + +namespace fs = utils::fs; + + +namespace { + + +/// Syntactic sugar to instantiate engine::test_filter objects. +inline engine::test_filter +mkfilter(const char* test_program, const char* test_case) +{ + return engine::test_filter(fs::path(test_program), test_case); +} + + +} // anonymous namespace + + +ATF_TEST_CASE_WITHOUT_HEAD(test_filter__public_fields); +ATF_TEST_CASE_BODY(test_filter__public_fields) +{ + const engine::test_filter filter(fs::path("foo/bar"), "baz"); + ATF_REQUIRE_EQ(fs::path("foo/bar"), filter.test_program); + ATF_REQUIRE_EQ("baz", filter.test_case); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(test_filter__parse__ok); +ATF_TEST_CASE_BODY(test_filter__parse__ok) +{ + const engine::test_filter filter(engine::test_filter::parse("foo")); + ATF_REQUIRE_EQ(fs::path("foo"), filter.test_program); + ATF_REQUIRE(filter.test_case.empty()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(test_filter__parse__empty); +ATF_TEST_CASE_BODY(test_filter__parse__empty) +{ + ATF_REQUIRE_THROW_RE(std::runtime_error, "empty", + engine::test_filter::parse("")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(test_filter__parse__absolute); +ATF_TEST_CASE_BODY(test_filter__parse__absolute) +{ + ATF_REQUIRE_THROW_RE(std::runtime_error, "'/foo/bar'.*relative", + engine::test_filter::parse("/foo//bar")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(test_filter__parse__bad_program_name); +ATF_TEST_CASE_BODY(test_filter__parse__bad_program_name) +{ + ATF_REQUIRE_THROW_RE(std::runtime_error, "Program name.*':foo'", + engine::test_filter::parse(":foo")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(test_filter__parse__bad_test_case); +ATF_TEST_CASE_BODY(test_filter__parse__bad_test_case) +{ + ATF_REQUIRE_THROW_RE(std::runtime_error, "Test case.*'bar/baz:'", + engine::test_filter::parse("bar/baz:")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(test_filter__parse__bad_path); +ATF_TEST_CASE_BODY(test_filter__parse__bad_path) +{ + // TODO(jmmv): Not implemented. At the moment, the only reason for a path + // to be invalid is if it is empty... but we are checking this exact + // condition ourselves as part of the input validation. So we can't mock in + // an argument with an invalid non-empty path... +} + + +ATF_TEST_CASE_WITHOUT_HEAD(test_filter__str); +ATF_TEST_CASE_BODY(test_filter__str) +{ + const engine::test_filter filter(fs::path("foo/bar"), "baz"); + ATF_REQUIRE_EQ("foo/bar:baz", filter.str()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(test_filter__contains__same); +ATF_TEST_CASE_BODY(test_filter__contains__same) +{ + { + const engine::test_filter f(fs::path("foo/bar"), "baz"); + ATF_REQUIRE(f.contains(f)); + } + { + const engine::test_filter f(fs::path("foo/bar"), ""); + ATF_REQUIRE(f.contains(f)); + } + { + const engine::test_filter f(fs::path("foo"), ""); + ATF_REQUIRE(f.contains(f)); + } +} + + +ATF_TEST_CASE_WITHOUT_HEAD(test_filter__contains__different); +ATF_TEST_CASE_BODY(test_filter__contains__different) +{ + { + const engine::test_filter f1(fs::path("foo"), ""); + const engine::test_filter f2(fs::path("foo"), "bar"); + ATF_REQUIRE( f1.contains(f2)); + ATF_REQUIRE(!f2.contains(f1)); + } + { + const engine::test_filter f1(fs::path("foo/bar"), ""); + const engine::test_filter f2(fs::path("foo/bar"), "baz"); + ATF_REQUIRE( f1.contains(f2)); + ATF_REQUIRE(!f2.contains(f1)); + } + { + const engine::test_filter f1(fs::path("foo/bar"), ""); + const engine::test_filter f2(fs::path("foo/baz"), ""); + ATF_REQUIRE(!f1.contains(f2)); + ATF_REQUIRE(!f2.contains(f1)); + } + { + const engine::test_filter f1(fs::path("foo"), ""); + const engine::test_filter f2(fs::path("foo/bar"), ""); + ATF_REQUIRE( f1.contains(f2)); + ATF_REQUIRE(!f2.contains(f1)); + } + { + const engine::test_filter f1(fs::path("foo"), "bar"); + const engine::test_filter f2(fs::path("foo/bar"), ""); + ATF_REQUIRE(!f1.contains(f2)); + ATF_REQUIRE(!f2.contains(f1)); + } +} + + +ATF_TEST_CASE_WITHOUT_HEAD(test_filter__matches_test_program) +ATF_TEST_CASE_BODY(test_filter__matches_test_program) +{ + { + const engine::test_filter f(fs::path("top"), "unused"); + ATF_REQUIRE( f.matches_test_program(fs::path("top"))); + ATF_REQUIRE(!f.matches_test_program(fs::path("top2"))); + } + + { + const engine::test_filter f(fs::path("dir1/dir2"), ""); + ATF_REQUIRE( f.matches_test_program(fs::path("dir1/dir2/foo"))); + ATF_REQUIRE( f.matches_test_program(fs::path("dir1/dir2/bar"))); + ATF_REQUIRE( f.matches_test_program(fs::path("dir1/dir2/bar/baz"))); + ATF_REQUIRE( f.matches_test_program(fs::path("dir1/dir2/bar/baz"))); + ATF_REQUIRE(!f.matches_test_program(fs::path("dir1"))); + ATF_REQUIRE(!f.matches_test_program(fs::path("dir1/bar/baz"))); + ATF_REQUIRE(!f.matches_test_program(fs::path("dir2/bar/baz"))); + } + + { + const engine::test_filter f(fs::path("dir1/dir2"), "unused"); + ATF_REQUIRE( f.matches_test_program(fs::path("dir1/dir2"))); + ATF_REQUIRE(!f.matches_test_program(fs::path("dir1/dir2/foo"))); + ATF_REQUIRE(!f.matches_test_program(fs::path("dir1/dir2/bar"))); + ATF_REQUIRE(!f.matches_test_program(fs::path("dir1/dir2/bar/baz"))); + ATF_REQUIRE(!f.matches_test_program(fs::path("dir1/dir2/bar/baz"))); + ATF_REQUIRE(!f.matches_test_program(fs::path("dir1"))); + ATF_REQUIRE(!f.matches_test_program(fs::path("dir1/bar/baz"))); + ATF_REQUIRE(!f.matches_test_program(fs::path("dir2/bar/baz"))); + } +} + + +ATF_TEST_CASE_WITHOUT_HEAD(test_filter__matches_test_case) +ATF_TEST_CASE_BODY(test_filter__matches_test_case) +{ + { + const engine::test_filter f(fs::path("top"), "foo"); + ATF_REQUIRE( f.matches_test_case(fs::path("top"), "foo")); + ATF_REQUIRE(!f.matches_test_case(fs::path("top"), "bar")); + } + + { + const engine::test_filter f(fs::path("top"), ""); + ATF_REQUIRE( f.matches_test_case(fs::path("top"), "foo")); + ATF_REQUIRE( f.matches_test_case(fs::path("top"), "bar")); + ATF_REQUIRE(!f.matches_test_case(fs::path("top2"), "foo")); + } + + { + const engine::test_filter f(fs::path("d1/d2/prog"), "t1"); + ATF_REQUIRE( f.matches_test_case(fs::path("d1/d2/prog"), "t1")); + ATF_REQUIRE(!f.matches_test_case(fs::path("d1/d2/prog"), "t2")); + } + + { + const engine::test_filter f(fs::path("d1/d2"), ""); + ATF_REQUIRE( f.matches_test_case(fs::path("d1/d2/prog"), "t1")); + ATF_REQUIRE( f.matches_test_case(fs::path("d1/d2/prog"), "t2")); + ATF_REQUIRE( f.matches_test_case(fs::path("d1/d2/prog2"), "t2")); + ATF_REQUIRE(!f.matches_test_case(fs::path("d1/d3"), "foo")); + ATF_REQUIRE(!f.matches_test_case(fs::path("d2"), "foo")); + } +} + + +ATF_TEST_CASE_WITHOUT_HEAD(test_filter__operator_lt) +ATF_TEST_CASE_BODY(test_filter__operator_lt) +{ + { + const engine::test_filter f1(fs::path("d1/d2"), ""); + ATF_REQUIRE(!(f1 < f1)); + } + { + const engine::test_filter f1(fs::path("d1/d2"), ""); + const engine::test_filter f2(fs::path("d1/d3"), ""); + ATF_REQUIRE( (f1 < f2)); + ATF_REQUIRE(!(f2 < f1)); + } + { + const engine::test_filter f1(fs::path("d1/d2"), ""); + const engine::test_filter f2(fs::path("d1/d2"), "foo"); + ATF_REQUIRE( (f1 < f2)); + ATF_REQUIRE(!(f2 < f1)); + } + { + const engine::test_filter f1(fs::path("d1/d2"), "bar"); + const engine::test_filter f2(fs::path("d1/d2"), "foo"); + ATF_REQUIRE( (f1 < f2)); + ATF_REQUIRE(!(f2 < f1)); + } + { + const engine::test_filter f1(fs::path("d1/d2"), "bar"); + const engine::test_filter f2(fs::path("d1/d3"), ""); + ATF_REQUIRE( (f1 < f2)); + ATF_REQUIRE(!(f2 < f1)); + } +} + + +ATF_TEST_CASE_WITHOUT_HEAD(test_filter__operator_eq) +ATF_TEST_CASE_BODY(test_filter__operator_eq) +{ + const engine::test_filter f1(fs::path("d1/d2"), ""); + const engine::test_filter f2(fs::path("d1/d2"), "bar"); + ATF_REQUIRE( (f1 == f1)); + ATF_REQUIRE(!(f1 == f2)); + ATF_REQUIRE(!(f2 == f1)); + ATF_REQUIRE( (f2 == f2)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(test_filter__operator_ne) +ATF_TEST_CASE_BODY(test_filter__operator_ne) +{ + const engine::test_filter f1(fs::path("d1/d2"), ""); + const engine::test_filter f2(fs::path("d1/d2"), "bar"); + ATF_REQUIRE(!(f1 != f1)); + ATF_REQUIRE( (f1 != f2)); + ATF_REQUIRE( (f2 != f1)); + ATF_REQUIRE(!(f2 != f2)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(test_filters__match_test_case__no_filters) +ATF_TEST_CASE_BODY(test_filters__match_test_case__no_filters) +{ + const std::set< engine::test_filter > raw_filters; + + const engine::test_filters filters(raw_filters); + engine::test_filters::match match; + + match = filters.match_test_case(fs::path("foo"), "baz"); + ATF_REQUIRE(match.first); + ATF_REQUIRE(!match.second); + + match = filters.match_test_case(fs::path("foo/bar"), "baz"); + ATF_REQUIRE(match.first); + ATF_REQUIRE(!match.second); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(test_filters__match_test_case__some_filters) +ATF_TEST_CASE_BODY(test_filters__match_test_case__some_filters) +{ + std::set< engine::test_filter > raw_filters; + raw_filters.insert(mkfilter("top_test", "")); + raw_filters.insert(mkfilter("subdir_1", "")); + raw_filters.insert(mkfilter("subdir_2/a_test", "")); + raw_filters.insert(mkfilter("subdir_2/b_test", "foo")); + + const engine::test_filters filters(raw_filters); + engine::test_filters::match match; + + match = filters.match_test_case(fs::path("top_test"), "a"); + ATF_REQUIRE(match.first); + ATF_REQUIRE_EQ("top_test", match.second.get().str()); + + match = filters.match_test_case(fs::path("subdir_1/foo"), "a"); + ATF_REQUIRE(match.first); + ATF_REQUIRE_EQ("subdir_1", match.second.get().str()); + + match = filters.match_test_case(fs::path("subdir_1/bar"), "z"); + ATF_REQUIRE(match.first); + ATF_REQUIRE_EQ("subdir_1", match.second.get().str()); + + match = filters.match_test_case(fs::path("subdir_2/a_test"), "bar"); + ATF_REQUIRE(match.first); + ATF_REQUIRE_EQ("subdir_2/a_test", match.second.get().str()); + + match = filters.match_test_case(fs::path("subdir_2/b_test"), "foo"); + ATF_REQUIRE(match.first); + ATF_REQUIRE_EQ("subdir_2/b_test:foo", match.second.get().str()); + + match = filters.match_test_case(fs::path("subdir_2/b_test"), "bar"); + ATF_REQUIRE(!match.first); + + match = filters.match_test_case(fs::path("subdir_2/c_test"), "foo"); + ATF_REQUIRE(!match.first); + + match = filters.match_test_case(fs::path("subdir_3"), "hello"); + ATF_REQUIRE(!match.first); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(test_filters__match_test_program__no_filters) +ATF_TEST_CASE_BODY(test_filters__match_test_program__no_filters) +{ + const std::set< engine::test_filter > raw_filters; + + const engine::test_filters filters(raw_filters); + ATF_REQUIRE(filters.match_test_program(fs::path("foo"))); + ATF_REQUIRE(filters.match_test_program(fs::path("foo/bar"))); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(test_filters__match_test_program__some_filters) +ATF_TEST_CASE_BODY(test_filters__match_test_program__some_filters) +{ + std::set< engine::test_filter > raw_filters; + raw_filters.insert(mkfilter("top_test", "")); + raw_filters.insert(mkfilter("subdir_1", "")); + raw_filters.insert(mkfilter("subdir_2/a_test", "")); + raw_filters.insert(mkfilter("subdir_2/b_test", "foo")); + + const engine::test_filters filters(raw_filters); + ATF_REQUIRE( filters.match_test_program(fs::path("top_test"))); + ATF_REQUIRE( filters.match_test_program(fs::path("subdir_1/foo"))); + ATF_REQUIRE( filters.match_test_program(fs::path("subdir_1/bar"))); + ATF_REQUIRE( filters.match_test_program(fs::path("subdir_2/a_test"))); + ATF_REQUIRE( filters.match_test_program(fs::path("subdir_2/b_test"))); + ATF_REQUIRE(!filters.match_test_program(fs::path("subdir_2/c_test"))); + ATF_REQUIRE(!filters.match_test_program(fs::path("subdir_3"))); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(test_filters__difference__no_filters); +ATF_TEST_CASE_BODY(test_filters__difference__no_filters) +{ + const std::set< engine::test_filter > in_filters; + const std::set< engine::test_filter > used; + const std::set< engine::test_filter > diff = engine::test_filters( + in_filters).difference(used); + ATF_REQUIRE(diff.empty()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(test_filters__difference__some_filters__all_used); +ATF_TEST_CASE_BODY(test_filters__difference__some_filters__all_used) +{ + std::set< engine::test_filter > in_filters; + in_filters.insert(mkfilter("a", "")); + in_filters.insert(mkfilter("b", "c")); + + const std::set< engine::test_filter > used = in_filters; + + const std::set< engine::test_filter > diff = engine::test_filters( + in_filters).difference(used); + ATF_REQUIRE(diff.empty()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(test_filters__difference__some_filters__some_unused); +ATF_TEST_CASE_BODY(test_filters__difference__some_filters__some_unused) +{ + std::set< engine::test_filter > in_filters; + in_filters.insert(mkfilter("a", "")); + in_filters.insert(mkfilter("b", "c")); + in_filters.insert(mkfilter("d", "")); + in_filters.insert(mkfilter("e", "f")); + + std::set< engine::test_filter > used; + used.insert(mkfilter("b", "c")); + used.insert(mkfilter("d", "")); + + const std::set< engine::test_filter > diff = engine::test_filters( + in_filters).difference(used); + ATF_REQUIRE_EQ(2, diff.size()); + ATF_REQUIRE(diff.find(mkfilter("a", "")) != diff.end()); + ATF_REQUIRE(diff.find(mkfilter("e", "f")) != diff.end()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(check_disjoint_filters__ok); +ATF_TEST_CASE_BODY(check_disjoint_filters__ok) +{ + std::set< engine::test_filter > filters; + filters.insert(mkfilter("a", "")); + filters.insert(mkfilter("b", "")); + filters.insert(mkfilter("c", "a")); + filters.insert(mkfilter("c", "b")); + + engine::check_disjoint_filters(filters); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(check_disjoint_filters__fail); +ATF_TEST_CASE_BODY(check_disjoint_filters__fail) +{ + std::set< engine::test_filter > filters; + filters.insert(mkfilter("a", "")); + filters.insert(mkfilter("b", "")); + filters.insert(mkfilter("c", "a")); + filters.insert(mkfilter("d", "b")); + filters.insert(mkfilter("c", "")); + + ATF_REQUIRE_THROW_RE(std::runtime_error, "'c'.*'c:a'.*not disjoint", + engine::check_disjoint_filters(filters)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(filters_state__match_test_program); +ATF_TEST_CASE_BODY(filters_state__match_test_program) +{ + std::set< engine::test_filter > filters; + filters.insert(mkfilter("foo/bar", "")); + filters.insert(mkfilter("baz", "tc")); + engine::filters_state state(filters); + + ATF_REQUIRE(state.match_test_program(fs::path("foo/bar/something"))); + ATF_REQUIRE(state.match_test_program(fs::path("baz"))); + + ATF_REQUIRE(!state.match_test_program(fs::path("foo/baz"))); + ATF_REQUIRE(!state.match_test_program(fs::path("hello"))); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(filters_state__match_test_case); +ATF_TEST_CASE_BODY(filters_state__match_test_case) +{ + std::set< engine::test_filter > filters; + filters.insert(mkfilter("foo/bar", "")); + filters.insert(mkfilter("baz", "tc")); + engine::filters_state state(filters); + + ATF_REQUIRE(state.match_test_case(fs::path("foo/bar/something"), "any")); + ATF_REQUIRE(state.match_test_case(fs::path("baz"), "tc")); + + ATF_REQUIRE(!state.match_test_case(fs::path("foo/baz/something"), "tc")); + ATF_REQUIRE(!state.match_test_case(fs::path("baz"), "tc2")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(filters_state__unused__none); +ATF_TEST_CASE_BODY(filters_state__unused__none) +{ + std::set< engine::test_filter > filters; + filters.insert(mkfilter("a/b", "")); + filters.insert(mkfilter("baz", "tc")); + filters.insert(mkfilter("hey/d", "yes")); + engine::filters_state state(filters); + + state.match_test_case(fs::path("a/b/c"), "any"); + state.match_test_case(fs::path("baz"), "tc"); + state.match_test_case(fs::path("hey/d"), "yes"); + + ATF_REQUIRE(state.unused().empty()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(filters_state__unused__some); +ATF_TEST_CASE_BODY(filters_state__unused__some) +{ + std::set< engine::test_filter > filters; + filters.insert(mkfilter("a/b", "")); + filters.insert(mkfilter("baz", "tc")); + filters.insert(mkfilter("hey/d", "yes")); + engine::filters_state state(filters); + + state.match_test_program(fs::path("a/b/c")); + state.match_test_case(fs::path("baz"), "tc"); + + std::set< engine::test_filter > exp_unused; + exp_unused.insert(mkfilter("a/b", "")); + exp_unused.insert(mkfilter("hey/d", "yes")); + + ATF_REQUIRE(exp_unused == state.unused()); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, test_filter__public_fields); + ATF_ADD_TEST_CASE(tcs, test_filter__parse__ok); + ATF_ADD_TEST_CASE(tcs, test_filter__parse__empty); + ATF_ADD_TEST_CASE(tcs, test_filter__parse__absolute); + ATF_ADD_TEST_CASE(tcs, test_filter__parse__bad_program_name); + ATF_ADD_TEST_CASE(tcs, test_filter__parse__bad_test_case); + ATF_ADD_TEST_CASE(tcs, test_filter__parse__bad_path); + ATF_ADD_TEST_CASE(tcs, test_filter__str); + ATF_ADD_TEST_CASE(tcs, test_filter__contains__same); + ATF_ADD_TEST_CASE(tcs, test_filter__contains__different); + ATF_ADD_TEST_CASE(tcs, test_filter__matches_test_program); + ATF_ADD_TEST_CASE(tcs, test_filter__matches_test_case); + ATF_ADD_TEST_CASE(tcs, test_filter__operator_lt); + ATF_ADD_TEST_CASE(tcs, test_filter__operator_eq); + ATF_ADD_TEST_CASE(tcs, test_filter__operator_ne); + + ATF_ADD_TEST_CASE(tcs, test_filters__match_test_case__no_filters); + ATF_ADD_TEST_CASE(tcs, test_filters__match_test_case__some_filters); + ATF_ADD_TEST_CASE(tcs, test_filters__match_test_program__no_filters); + ATF_ADD_TEST_CASE(tcs, test_filters__match_test_program__some_filters); + ATF_ADD_TEST_CASE(tcs, test_filters__difference__no_filters); + ATF_ADD_TEST_CASE(tcs, test_filters__difference__some_filters__all_used); + ATF_ADD_TEST_CASE(tcs, test_filters__difference__some_filters__some_unused); + + ATF_ADD_TEST_CASE(tcs, check_disjoint_filters__ok); + ATF_ADD_TEST_CASE(tcs, check_disjoint_filters__fail); + + ATF_ADD_TEST_CASE(tcs, filters_state__match_test_program); + ATF_ADD_TEST_CASE(tcs, filters_state__match_test_case); + ATF_ADD_TEST_CASE(tcs, filters_state__unused__none); + ATF_ADD_TEST_CASE(tcs, filters_state__unused__some); +} diff --git a/external/bsd/kyua-cli/dist/engine/kyuafile.cpp b/external/bsd/kyua-cli/dist/engine/kyuafile.cpp new file mode 100644 index 000000000..a2f244d6f --- /dev/null +++ b/external/bsd/kyua-cli/dist/engine/kyuafile.cpp @@ -0,0 +1,630 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "engine/kyuafile.hpp" + +#include +#include +#include + +#include +#include +#include +#include + +#include "engine/exceptions.hpp" +#include "engine/test_program.hpp" +#include "engine/testers.hpp" +#include "utils/datetime.hpp" +#include "utils/format/macros.hpp" +#include "utils/fs/lua_module.hpp" +#include "utils/fs/operations.hpp" +#include "utils/logging/macros.hpp" +#include "utils/noncopyable.hpp" +#include "utils/optional.ipp" +#include "utils/sanity.hpp" + +namespace datetime = utils::datetime; +namespace fs = utils::fs; + +using utils::none; +using utils::optional; + + +// History of Kyuafile file versions: +// +// 2 - Changed the syntax() call to take only a version number, instead of the +// word 'config' as the first argument and the version as the second one. +// Files now start with syntax(2) instead of syntax('kyuafile', 1). +// +// 1 - Initial version. + + +namespace { + + +static int lua_atf_test_program(lutok::state&); +static int lua_current_kyuafile(lutok::state&); +static int lua_include(lutok::state&); +static int lua_plain_test_program(lutok::state&); +static int lua_syntax(lutok::state&); +static int lua_test_suite(lutok::state&); + + +/// Concatenates two paths while avoiding paths to start with './'. +/// +/// \param root Path to the directory containing the file. +/// \param file Path to concatenate to root. Cannot be absolute. +/// +/// \return The concatenated path. +static fs::path +relativize(const fs::path& root, const fs::path& file) +{ + PRE(!file.is_absolute()); + + if (root == fs::path(".")) + return file; + else + return root / file; +} + + +/// Implementation of a parser for Kyuafiles. +/// +/// The main purpose of having this as a class is to keep track of global state +/// within the Lua files and allowing the Lua callbacks to easily access such +/// data. +class parser : utils::noncopyable { + /// Lua state to parse a single Kyuafile file. + lutok::state _state; + + /// Root directory of the test suite represented by the Kyuafile. + const fs::path _source_root; + + /// Root directory of the test programs. + const fs::path _build_root; + + /// Name of the Kyuafile to load relative to _source_root. + const fs::path _relative_filename; + + /// Version of the Kyuafile file format requested by the parsed file. + /// + /// This is set once the Kyuafile invokes the syntax() call. + optional< int > _version; + + /// Name of the test suite defined by the Kyuafile. + /// + /// This is set once the Kyuafile invokes the test_suite() call. + optional< std::string > _test_suite; + + /// Collection of test programs defined by the Kyuafile. + /// + /// This acts as an accumulator for all the *_test_program() calls within + /// the Kyuafile. + engine::test_programs_vector _test_programs; + +public: + /// Initializes the parser and the Lua state. + /// + /// \param source_root_ The root directory of the test suite represented by + /// the Kyuafile. + /// \param build_root_ The root directory of the test programs. + /// \param relative_filename_ Name of the Kyuafile to load relative to + /// source_root_. + parser(const fs::path& source_root_, const fs::path& build_root_, + const fs::path& relative_filename_) : + _source_root(source_root_), _build_root(build_root_), + _relative_filename(relative_filename_) + { + lutok::stack_cleaner cleaner(_state); + + _state.push_cxx_function(lua_syntax); + _state.set_global("syntax"); + *_state.new_userdata< parser* >() = this; + _state.set_global("_parser"); + + _state.push_cxx_function(lua_atf_test_program); + _state.set_global("atf_test_program"); + _state.push_cxx_function(lua_current_kyuafile); + _state.set_global("current_kyuafile"); + _state.push_cxx_function(lua_include); + _state.set_global("include"); + _state.push_cxx_function(lua_plain_test_program); + _state.set_global("plain_test_program"); + _state.push_cxx_function(lua_test_suite); + _state.set_global("test_suite"); + + _state.open_base(); + _state.open_string(); + _state.open_table(); + fs::open_fs(_state); + } + + /// Destructor. + ~parser(void) + { + } + + /// Gets the parser object associated to a Lua state. + /// + /// \param state The Lua state from which to obtain the parser object. + /// + /// \return A pointer to the parser. + static parser* + get_from_state(lutok::state& state) + { + lutok::stack_cleaner cleaner(state); + state.get_global("_parser"); + return *state.to_userdata< parser* >(); + } + + /// Callback for the Kyuafile current_kyuafile() function. + /// + /// \return Returns the absolute path to the current Kyuafile. + fs::path + callback_current_kyuafile(void) const + { + const fs::path file = relativize(_source_root, _relative_filename); + if (file.is_absolute()) + return file; + else + return file.to_absolute(); + } + + /// Callback for the Kyuafile include() function. + /// + /// \post _test_programs is extended with the the test programs defined by + /// the included file. + /// + /// \param raw_file Path to the file to include. + void + callback_include(const fs::path& raw_file) + { + const fs::path file = relativize(_relative_filename.branch_path(), + raw_file); + const engine::test_programs_vector subtps = + parser(_source_root, _build_root, file).parse(); + + std::copy(subtps.begin(), subtps.end(), + std::back_inserter(_test_programs)); + } + + /// Callback for the Kyuafile syntax() function. + /// + /// \post _version is set to the requested version. + /// + /// \param version Version of the Kyuafile syntax requested by the file. + /// + /// \throw std::runtime_error If the format or the version are invalid, or + /// if syntax() has already been called. + void + callback_syntax(const int version) + { + if (_version) + throw std::runtime_error("Can only call syntax() once"); + + if (version < 1 || version > 2) + throw std::runtime_error(F("Unsupported file version %s") % + version); + + _version = utils::make_optional(version); + } + + /// Callback for the various Kyuafile *_test_program() functions. + /// + /// \post _test_programs is extended to include the newly defined test + /// program. + /// + /// \param interface Name of the test program interface. + /// \param raw_path Path to the test program, relative to the Kyuafile. + /// This has to be adjusted according to the relative location of this + /// Kyuafile to _source_root. + /// \param test_suite_override Name of the test suite this test program + /// belongs to, if explicitly defined at the test program level. + /// \param metadata Metadata variables passed to the test program. + /// + /// \throw std::runtime_error If the test program definition is invalid or + /// if the test program does not exist. + void + callback_test_program(const std::string& interface, + const fs::path& raw_path, + const std::string& test_suite_override, + const engine::metadata& metadata) + { + if (raw_path.is_absolute()) + throw std::runtime_error(F("Got unexpected absolute path for test " + "program '%s'") % raw_path); + else if (raw_path.str() != raw_path.leaf_name()) + throw std::runtime_error(F("Test program '%s' cannot contain path " + "components") % raw_path); + + const fs::path path = relativize(_relative_filename.branch_path(), + raw_path); + + if (!fs::exists(_build_root / path)) + throw std::runtime_error(F("Non-existent test program '%s'") % + path); + + const std::string test_suite = test_suite_override.empty() + ? _test_suite.get() : test_suite_override; + _test_programs.push_back(engine::test_program_ptr( + new engine::test_program(interface, path, _build_root, test_suite, + metadata))); + } + + /// Callback for the Kyuafile test_suite() function. + /// + /// \post _version is set to the requested version. + /// + /// \param name Name of the test suite. + /// + /// \throw std::runtime_error If test_suite() has already been called. + void + callback_test_suite(const std::string& name) + { + if (_test_suite) + throw std::runtime_error("Can only call test_suite() once"); + _test_suite = utils::make_optional(name); + } + + /// Parses the Kyuafile. + /// + /// \pre Can only be invoked once. + /// + /// \return The collection of test programs defined by the Kyuafile. + /// + /// \throw load_error If there is any problem parsing the file. + const engine::test_programs_vector& + parse(void) + { + PRE(_test_programs.empty()); + + const fs::path load_path = relativize(_source_root, _relative_filename); + try { + lutok::do_file(_state, load_path.str()); + } catch (const std::runtime_error& e) { + // It is tempting to think that all of our various auxiliary + // functions above could raise load_error by themselves thus making + // this exception rewriting here unnecessary. Howver, that would + // not work because the helper functions above are executed within a + // Lua context, and we lose their type when they are propagated out + // of it. + throw engine::load_error(load_path, e.what()); + } + + if (!_version) + throw engine::load_error(load_path, "syntax() never called"); + + return _test_programs; + } +}; + + +/// Gets a string field from a Lua table. +/// +/// \pre state(-1) contains a table. +/// +/// \param state The Lua state. +/// \param field The name of the field to query. +/// \param error The error message to raise when an error condition is +/// encoutered. +/// +/// \return The string value from the table. +/// +/// \throw std::runtime_error If there is any problem accessing the table. +static inline std::string +get_table_string(lutok::state& state, const char* field, + const std::string& error) +{ + PRE(state.is_table()); + + lutok::stack_cleaner cleaner(state); + + state.push_string(field); + state.get_table(); + if (!state.is_string()) + throw std::runtime_error(error); + return state.to_string(); +} + + +/// Checks if the given interface name is valid. +/// +/// \param interface The name of the interface to validate. +/// +/// \throw std::runtime_error If the given interface is not supported. +static void +ensure_valid_interface(const std::string& interface) +{ + try { + (void)engine::tester_path(interface); + } catch (const engine::error& e) { + throw std::runtime_error(F("Unsupported test interface '%s'") % + interface); + } +} + + +/// Glue to invoke parser::callback_test_program() from Lua. +/// +/// This is a helper function for the various *_test_program() calls, as they +/// only differ in the interface of the defined test program. +/// +/// \pre state(-1) A table with the arguments that define the test program. The +/// special argument 'test_suite' provides an override to the global test suite +/// name. The rest of the arguments are part of the test program metadata. +/// +/// \param state The Lua state that executed the function. +/// \param interface Name of the test program interface. +/// +/// \return Number of return values left on the Lua stack. +/// +/// \throw std::runtime_error If the arguments to the function are invalid. +static int +lua_generic_test_program(lutok::state& state, const std::string& interface) +{ + if (!state.is_table()) + throw std::runtime_error( + F("%s_test_program expects a table of properties as its single " + "argument") % interface); + + ensure_valid_interface(interface); + + lutok::stack_cleaner cleaner(state); + + state.push_string("name"); + state.get_table(); + if (!state.is_string()) + throw std::runtime_error("Test program name not defined or not a " + "string"); + const fs::path path(state.to_string()); + state.pop(1); + + state.push_string("test_suite"); + state.get_table(); + std::string test_suite; + if (state.is_nil()) { + // Leave empty to use the global test-suite value. + } else if (state.is_string()) { + test_suite = state.to_string(); + } else { + throw std::runtime_error(F("Found non-string value in the test_suite " + "property of test program '%s'") % path); + } + state.pop(1); + + engine::metadata_builder mdbuilder; + state.push_nil(); + while (state.next()) { + if (!state.is_string(-2)) + throw std::runtime_error(F("Found non-string metadata property " + "name in test program '%s'") % + path); + const std::string property = state.to_string(-2); + + if (property != "name" && property != "test_suite") { + if (!state.is_number(-1) && !state.is_string(-1)) + throw std::runtime_error( + F("Metadata property '%s' in test program '%s' cannot be " + "converted to a string") % property % path); + const std::string value = state.to_string(-1); + + mdbuilder.set_string(property, value); + } + + state.pop(1); + } + + parser::get_from_state(state)->callback_test_program( + interface, path, test_suite, mdbuilder.build()); + return 0; +} + + +/// Specialization of lua_generic_test_program for ATF test programs. +/// +/// \param state The Lua state that executed the function. +/// +/// \return Number of return values left on the Lua stack. +static int +lua_atf_test_program(lutok::state& state) +{ + return lua_generic_test_program(state, "atf"); +} + + +/// Glue to invoke parser::callback_current_kyuafile() from Lua. +/// +/// \param state The Lua state that executed the function. +/// +/// \return Number of return values left on the Lua stack. +static int +lua_current_kyuafile(lutok::state& state) +{ + state.push_string(parser::get_from_state(state)-> + callback_current_kyuafile().str()); + return 1; +} + + +/// Glue to invoke parser::callback_include() from Lua. +/// +/// \param state The Lua state that executed the function. +/// +/// \return Number of return values left on the Lua stack. +static int +lua_include(lutok::state& state) +{ + parser::get_from_state(state)->callback_include( + fs::path(state.to_string())); + return 0; +} + + +/// Specialization of lua_generic_test_program for plain test programs. +/// +/// \param state The Lua state that executed the function. +/// +/// \return Number of return values left on the Lua stack. +static int +lua_plain_test_program(lutok::state& state) +{ + return lua_generic_test_program(state, "plain"); +} + + +/// Glue to invoke parser::callback_syntax() from Lua. +/// +/// \pre state(-2) The syntax format name, if a v1 file. +/// \pre state(-1) The syntax format version. +/// +/// \param state The Lua state that executed the function. +/// +/// \return Number of return values left on the Lua stack. +static int +lua_syntax(lutok::state& state) +{ + if (!state.is_number(-1)) + throw std::runtime_error("Last argument to syntax must be a number"); + const int syntax_version = state.to_integer(-1); + + if (syntax_version == 1) { + if (state.get_top() != 2) + throw std::runtime_error("Version 1 files need two arguments to " + "syntax()"); + if (!state.is_string(-2) || state.to_string(-2) != "kyuafile") + throw std::runtime_error("First argument to syntax must be " + "'kyuafile' for version 1 files"); + } else { + if (state.get_top() != 1) + throw std::runtime_error("syntax() only takes one argument"); + } + + parser::get_from_state(state)->callback_syntax(syntax_version); + return 0; +} + + +/// Glue to invoke parser::callback_test_suite() from Lua. +/// +/// \param state The Lua state that executed the function. +/// +/// \return Number of return values left on the Lua stack. +static int +lua_test_suite(lutok::state& state) +{ + parser::get_from_state(state)->callback_test_suite(state.to_string()); + return 0; +} + + +} // anonymous namespace + + +/// Constructs a kyuafile form initialized data. +/// +/// Use load() to parse a test suite configuration file and construct a +/// kyuafile object. +/// +/// \param source_root_ The root directory for the test suite represented by the +/// Kyuafile. In other words, the directory containing the first Kyuafile +/// processed. +/// \param build_root_ The root directory for the test programs themselves. In +/// general, this will be the same as source_root_. If different, the +/// specified directory must follow the exact same layout of source_root_. +/// \param tps_ Collection of test programs that belong to this test suite. +engine::kyuafile::kyuafile(const fs::path& source_root_, + const fs::path& build_root_, + const test_programs_vector& tps_) : + _source_root(source_root_), + _build_root(build_root_), + _test_programs(tps_) +{ +} + + +/// Destructor. +engine::kyuafile::~kyuafile(void) +{ +} + + +/// Parses a test suite configuration file. +/// +/// \param file The file to parse. +/// \param user_build_root If not none, specifies a path to a directory +/// containing the test programs themselves. The layout of the build root +/// must match the layout of the source root (which is just the directory +/// from which the Kyuafile is being read). +/// +/// \return High-level representation of the configuration file. +/// +/// \throw load_error If there is any problem loading the file. This includes +/// file access errors and syntax errors. +engine::kyuafile +engine::kyuafile::load(const fs::path& file, + const optional< fs::path > user_build_root) +{ + const fs::path source_root_ = file.branch_path(); + const fs::path build_root_ = user_build_root ? + user_build_root.get() : source_root_; + + return kyuafile(source_root_, build_root_, + parser(source_root_, build_root_, + fs::path(file.leaf_name())).parse()); +} + + +/// Gets the root directory of the test suite. +/// +/// \return A path. +const fs::path& +engine::kyuafile::source_root(void) const +{ + return _source_root; +} + + +/// Gets the root directory of the test programs. +/// +/// \return A path. +const fs::path& +engine::kyuafile::build_root(void) const +{ + return _build_root; +} + + +/// Gets the collection of test programs that belong to this test suite. +/// +/// \return Collection of test program executable names. +const engine::test_programs_vector& +engine::kyuafile::test_programs(void) const +{ + return _test_programs; +} diff --git a/external/bsd/kyua-cli/dist/engine/kyuafile.hpp b/external/bsd/kyua-cli/dist/engine/kyuafile.hpp new file mode 100644 index 000000000..d0227d622 --- /dev/null +++ b/external/bsd/kyua-cli/dist/engine/kyuafile.hpp @@ -0,0 +1,90 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file engine/kyuafile.hpp +/// Test suite configuration parsing and representation. + +#if !defined(ENGINE_KYUAFILE_HPP) +#define ENGINE_KYUAFILE_HPP + +#include +#include + +#include + +#include "engine/test_program.hpp" +#include "utils/fs/path.hpp" +#include "utils/optional.hpp" + +namespace engine { + + +/// Representation of the configuration of a test suite. +/// +/// Test suites are collections of related test programs. They are described by +/// a configuration file. +/// +/// Test suites have two path references: one to the "source root" and another +/// one to the "build root". The source root points to the directory from which +/// the Kyuafile is being read, and all recursive inclusions are resolved +/// relative to that directory. The build root points to the directory +/// containing the generated test programs and is prepended to the absolute path +/// of the test programs referenced by the Kyuafiles. In general, the build +/// root will be the same as the source root; however, when using a build system +/// that supports "build directories", providing this option comes in handy to +/// allow running the tests without much hassle. +/// +/// This class provides the parser for test suite configuration files and +/// methods to access the parsed data. +class kyuafile { + /// Path to the directory containing the top-level Kyuafile loaded. + utils::fs::path _source_root; + + /// Path to the directory containing the test programs. + utils::fs::path _build_root; + + /// Collection of the test programs defined in the Kyuafile. + test_programs_vector _test_programs; + +public: + explicit kyuafile(const utils::fs::path&, const utils::fs::path&, + const test_programs_vector&); + ~kyuafile(void); + + static kyuafile load(const utils::fs::path&, + const utils::optional< utils::fs::path >); + + const utils::fs::path& source_root(void) const; + const utils::fs::path& build_root(void) const; + const test_programs_vector& test_programs(void) const; +}; + + +} // namespace engine + +#endif // !defined(ENGINE_KYUAFILE_HPP) diff --git a/external/bsd/kyua-cli/dist/engine/kyuafile_test.cpp b/external/bsd/kyua-cli/dist/engine/kyuafile_test.cpp new file mode 100644 index 000000000..00091c54d --- /dev/null +++ b/external/bsd/kyua-cli/dist/engine/kyuafile_test.cpp @@ -0,0 +1,418 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "engine/kyuafile.hpp" + +#include +#include + +#include +#include +#include +#include + +#include "engine/exceptions.hpp" +#include "engine/test_program.hpp" +#include "utils/datetime.hpp" +#include "utils/format/macros.hpp" +#include "utils/fs/operations.hpp" +#include "utils/optional.ipp" + +namespace datetime = utils::datetime; +namespace fs = utils::fs; + +using utils::none; + + +ATF_TEST_CASE_WITHOUT_HEAD(kyuafile__load__empty); +ATF_TEST_CASE_BODY(kyuafile__load__empty) +{ + atf::utils::create_file("config", "syntax(2)\n"); + + const engine::kyuafile suite = engine::kyuafile::load( + fs::path("config"), none); + ATF_REQUIRE_EQ(fs::path("."), suite.source_root()); + ATF_REQUIRE_EQ(fs::path("."), suite.build_root()); + ATF_REQUIRE_EQ(0, suite.test_programs().size()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(kyuafile__load__some_programs); +ATF_TEST_CASE_BODY(kyuafile__load__some_programs) +{ + atf::utils::create_file( + "config", + "syntax(2)\n" + "test_suite('one-suite')\n" + "atf_test_program{name='1st'}\n" + "atf_test_program{name='2nd', test_suite='first'}\n" + "plain_test_program{name='3rd'}\n" + "plain_test_program{name='4th', test_suite='second'}\n" + "include('dir/config')\n"); + + fs::mkdir(fs::path("dir"), 0755); + atf::utils::create_file( + "dir/config", + "syntax(2)\n" + "atf_test_program{name='1st', test_suite='other-suite'}\n" + "include('subdir/config')\n"); + + fs::mkdir(fs::path("dir/subdir"), 0755); + atf::utils::create_file( + "dir/subdir/config", + "syntax(2)\n" + "atf_test_program{name='5th', test_suite='last-suite'}\n"); + + atf::utils::create_file("1st", ""); + atf::utils::create_file("2nd", ""); + atf::utils::create_file("3rd", ""); + atf::utils::create_file("4th", ""); + atf::utils::create_file("dir/1st", ""); + atf::utils::create_file("dir/subdir/5th", ""); + + const engine::kyuafile suite = engine::kyuafile::load( + fs::path("config"), none); + ATF_REQUIRE_EQ(fs::path("."), suite.source_root()); + ATF_REQUIRE_EQ(fs::path("."), suite.build_root()); + ATF_REQUIRE_EQ(6, suite.test_programs().size()); + + ATF_REQUIRE_EQ("atf", suite.test_programs()[0]->interface_name()); + ATF_REQUIRE_EQ(fs::path("1st"), suite.test_programs()[0]->relative_path()); + ATF_REQUIRE_EQ("one-suite", suite.test_programs()[0]->test_suite_name()); + + ATF_REQUIRE_EQ("atf", suite.test_programs()[1]->interface_name()); + ATF_REQUIRE_EQ(fs::path("2nd"), suite.test_programs()[1]->relative_path()); + ATF_REQUIRE_EQ("first", suite.test_programs()[1]->test_suite_name()); + + ATF_REQUIRE_EQ("plain", suite.test_programs()[2]->interface_name()); + ATF_REQUIRE_EQ(fs::path("3rd"), suite.test_programs()[2]->relative_path()); + ATF_REQUIRE_EQ("one-suite", suite.test_programs()[2]->test_suite_name()); + + ATF_REQUIRE_EQ("plain", suite.test_programs()[3]->interface_name()); + ATF_REQUIRE_EQ(fs::path("4th"), suite.test_programs()[3]->relative_path()); + ATF_REQUIRE_EQ("second", suite.test_programs()[3]->test_suite_name()); + + ATF_REQUIRE_EQ("atf", suite.test_programs()[4]->interface_name()); + ATF_REQUIRE_EQ(fs::path("dir/1st"), + suite.test_programs()[4]->relative_path()); + ATF_REQUIRE_EQ("other-suite", suite.test_programs()[4]->test_suite_name()); + + ATF_REQUIRE_EQ("atf", suite.test_programs()[5]->interface_name()); + ATF_REQUIRE_EQ(fs::path("dir/subdir/5th"), + suite.test_programs()[5]->relative_path()); + ATF_REQUIRE_EQ("last-suite", suite.test_programs()[5]->test_suite_name()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(kyuafile__load__metadata); +ATF_TEST_CASE_BODY(kyuafile__load__metadata) +{ + atf::utils::create_file( + "config", + "syntax(2)\n" + "atf_test_program{name='1st', test_suite='first'," + " allowed_architectures='amd64 i386', timeout=15}\n" + "plain_test_program{name='2nd', test_suite='second'," + " required_files='foo /bar//baz', required_user='root'}\n"); + atf::utils::create_file("1st", ""); + atf::utils::create_file("2nd", ""); + + const engine::kyuafile suite = engine::kyuafile::load( + fs::path("config"), none); + ATF_REQUIRE_EQ(2, suite.test_programs().size()); + + ATF_REQUIRE_EQ("atf", suite.test_programs()[0]->interface_name()); + ATF_REQUIRE_EQ(fs::path("1st"), suite.test_programs()[0]->relative_path()); + ATF_REQUIRE_EQ("first", suite.test_programs()[0]->test_suite_name()); + const engine::metadata md1 = engine::metadata_builder() + .add_allowed_architecture("amd64") + .add_allowed_architecture("i386") + .set_timeout(datetime::delta(15, 0)) + .build(); + ATF_REQUIRE_EQ(md1, suite.test_programs()[0]->get_metadata()); + + ATF_REQUIRE_EQ("plain", suite.test_programs()[1]->interface_name()); + ATF_REQUIRE_EQ(fs::path("2nd"), suite.test_programs()[1]->relative_path()); + ATF_REQUIRE_EQ("second", suite.test_programs()[1]->test_suite_name()); + const engine::metadata md2 = engine::metadata_builder() + .add_required_file(fs::path("foo")) + .add_required_file(fs::path("/bar/baz")) + .set_required_user("root") + .build(); + ATF_REQUIRE_EQ(md2, suite.test_programs()[1]->get_metadata()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(kyuafile__load__current_directory); +ATF_TEST_CASE_BODY(kyuafile__load__current_directory) +{ + atf::utils::create_file( + "config", + "syntax(2)\n" + "atf_test_program{name='one', test_suite='first'}\n" + "include('config2')\n"); + + atf::utils::create_file( + "config2", + "syntax(2)\n" + "test_suite('second')\n" + "atf_test_program{name='two'}\n"); + + atf::utils::create_file("one", ""); + atf::utils::create_file("two", ""); + + const engine::kyuafile suite = engine::kyuafile::load( + fs::path("config"), none); + ATF_REQUIRE_EQ(fs::path("."), suite.source_root()); + ATF_REQUIRE_EQ(fs::path("."), suite.build_root()); + ATF_REQUIRE_EQ(2, suite.test_programs().size()); + ATF_REQUIRE_EQ(fs::path("one"), suite.test_programs()[0]->relative_path()); + ATF_REQUIRE_EQ("first", suite.test_programs()[0]->test_suite_name()); + ATF_REQUIRE_EQ(fs::path("two"), + suite.test_programs()[1]->relative_path()); + ATF_REQUIRE_EQ("second", suite.test_programs()[1]->test_suite_name()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(kyuafile__load__other_directory); +ATF_TEST_CASE_BODY(kyuafile__load__other_directory) +{ + fs::mkdir(fs::path("root"), 0755); + atf::utils::create_file( + "root/config", + "syntax(2)\n" + "test_suite('abc')\n" + "atf_test_program{name='one'}\n" + "include('dir/config')\n"); + + fs::mkdir(fs::path("root/dir"), 0755); + atf::utils::create_file( + "root/dir/config", + "syntax(2)\n" + "test_suite('foo')\n" + "atf_test_program{name='two', test_suite='def'}\n" + "atf_test_program{name='three'}\n"); + + atf::utils::create_file("root/one", ""); + atf::utils::create_file("root/dir/two", ""); + atf::utils::create_file("root/dir/three", ""); + + const engine::kyuafile suite = engine::kyuafile::load( + fs::path("root/config"), none); + ATF_REQUIRE_EQ(fs::path("root"), suite.source_root()); + ATF_REQUIRE_EQ(fs::path("root"), suite.build_root()); + ATF_REQUIRE_EQ(3, suite.test_programs().size()); + ATF_REQUIRE_EQ(fs::path("one"), suite.test_programs()[0]->relative_path()); + ATF_REQUIRE_EQ("abc", suite.test_programs()[0]->test_suite_name()); + ATF_REQUIRE_EQ(fs::path("dir/two"), + suite.test_programs()[1]->relative_path()); + ATF_REQUIRE_EQ("def", suite.test_programs()[1]->test_suite_name()); + ATF_REQUIRE_EQ(fs::path("dir/three"), + suite.test_programs()[2]->relative_path()); + ATF_REQUIRE_EQ("foo", suite.test_programs()[2]->test_suite_name()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(kyuafile__load__build_directory); +ATF_TEST_CASE_BODY(kyuafile__load__build_directory) +{ + fs::mkdir(fs::path("srcdir"), 0755); + atf::utils::create_file( + "srcdir/config", + "syntax(2)\n" + "test_suite('abc')\n" + "atf_test_program{name='one'}\n" + "include('dir/config')\n"); + + fs::mkdir(fs::path("srcdir/dir"), 0755); + atf::utils::create_file( + "srcdir/dir/config", + "syntax(2)\n" + "test_suite('foo')\n" + "atf_test_program{name='two', test_suite='def'}\n" + "atf_test_program{name='three'}\n"); + + fs::mkdir(fs::path("builddir"), 0755); + atf::utils::create_file("builddir/one", ""); + fs::mkdir(fs::path("builddir/dir"), 0755); + atf::utils::create_file("builddir/dir/two", ""); + atf::utils::create_file("builddir/dir/three", ""); + + const engine::kyuafile suite = engine::kyuafile::load( + fs::path("srcdir/config"), utils::make_optional(fs::path("builddir"))); + ATF_REQUIRE_EQ(fs::path("srcdir"), suite.source_root()); + ATF_REQUIRE_EQ(fs::path("builddir"), suite.build_root()); + ATF_REQUIRE_EQ(3, suite.test_programs().size()); + ATF_REQUIRE_EQ(fs::path("builddir/one").to_absolute(), + suite.test_programs()[0]->absolute_path()); + ATF_REQUIRE_EQ(fs::path("one"), suite.test_programs()[0]->relative_path()); + ATF_REQUIRE_EQ("abc", suite.test_programs()[0]->test_suite_name()); + ATF_REQUIRE_EQ(fs::path("builddir/dir/two").to_absolute(), + suite.test_programs()[1]->absolute_path()); + ATF_REQUIRE_EQ(fs::path("dir/two"), + suite.test_programs()[1]->relative_path()); + ATF_REQUIRE_EQ("def", suite.test_programs()[1]->test_suite_name()); + ATF_REQUIRE_EQ(fs::path("builddir/dir/three").to_absolute(), + suite.test_programs()[2]->absolute_path()); + ATF_REQUIRE_EQ(fs::path("dir/three"), + suite.test_programs()[2]->relative_path()); + ATF_REQUIRE_EQ("foo", suite.test_programs()[2]->test_suite_name()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(kyuafile__load__test_program_not_basename); +ATF_TEST_CASE_BODY(kyuafile__load__test_program_not_basename) +{ + atf::utils::create_file( + "config", + "syntax(2)\n" + "test_suite('abc')\n" + "atf_test_program{name='one'}\n" + "atf_test_program{name='./ls'}\n"); + + atf::utils::create_file("one", ""); + ATF_REQUIRE_THROW_RE(engine::load_error, "./ls.*path components", + engine::kyuafile::load(fs::path("config"), none)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(kyuafile__load__lua_error); +ATF_TEST_CASE_BODY(kyuafile__load__lua_error) +{ + atf::utils::create_file("config", "this syntax is invalid\n"); + + ATF_REQUIRE_THROW(engine::load_error, engine::kyuafile::load( + fs::path("config"), none)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(kyuafile__load__syntax__not_called); +ATF_TEST_CASE_BODY(kyuafile__load__syntax__not_called) +{ + atf::utils::create_file("config", ""); + + ATF_REQUIRE_THROW_RE(engine::load_error, "syntax.* never called", + engine::kyuafile::load(fs::path("config"), none)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(kyuafile__load__syntax__deprecated_format); +ATF_TEST_CASE_BODY(kyuafile__load__syntax__deprecated_format) +{ + atf::utils::create_file("config", "syntax('kyuafile', 1)\n"); + (void)engine::kyuafile::load(fs::path("config"), none); + + atf::utils::create_file("config", "syntax('foo', 1)\n"); + ATF_REQUIRE_THROW_RE(engine::load_error, "must be 'kyuafile'", + engine::kyuafile::load(fs::path("config"), none)); + + atf::utils::create_file("config", "syntax('config', 2)\n"); + ATF_REQUIRE_THROW_RE(engine::load_error, "only takes one argument", + engine::kyuafile::load(fs::path("config"), none)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(kyuafile__load__syntax__twice); +ATF_TEST_CASE_BODY(kyuafile__load__syntax__twice) +{ + atf::utils::create_file( + "config", + "syntax(2)\n" + "syntax(2)\n"); + + ATF_REQUIRE_THROW_RE(engine::load_error, "Can only call syntax.* once", + engine::kyuafile::load(fs::path("config"), none)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(kyuafile__load__syntax__bad_version); +ATF_TEST_CASE_BODY(kyuafile__load__syntax__bad_version) +{ + atf::utils::create_file("config", "syntax(12)\n"); + + ATF_REQUIRE_THROW_RE(engine::load_error, "Unsupported file version 12", + engine::kyuafile::load(fs::path("config"), none)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(kyuafile__load__test_suite__twice); +ATF_TEST_CASE_BODY(kyuafile__load__test_suite__twice) +{ + atf::utils::create_file( + "config", + "syntax(2)\n" + "test_suite('foo')\n" + "test_suite('bar')\n"); + + ATF_REQUIRE_THROW_RE(engine::load_error, "Can only call test_suite.* once", + engine::kyuafile::load(fs::path("config"), none)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(kyuafile__load__missing_file); +ATF_TEST_CASE_BODY(kyuafile__load__missing_file) +{ + ATF_REQUIRE_THROW_RE(engine::load_error, "Load of 'missing' failed", + engine::kyuafile::load(fs::path("missing"), none)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(kyuafile__load__missing_test_program); +ATF_TEST_CASE_BODY(kyuafile__load__missing_test_program) +{ + atf::utils::create_file( + "config", + "syntax(2)\n" + "atf_test_program{name='one', test_suite='first'}\n" + "atf_test_program{name='two', test_suite='first'}\n"); + + atf::utils::create_file("one", ""); + + ATF_REQUIRE_THROW_RE(engine::load_error, "Non-existent.*'two'", + engine::kyuafile::load(fs::path("config"), none)); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, kyuafile__load__empty); + ATF_ADD_TEST_CASE(tcs, kyuafile__load__some_programs); + ATF_ADD_TEST_CASE(tcs, kyuafile__load__metadata); + ATF_ADD_TEST_CASE(tcs, kyuafile__load__current_directory); + ATF_ADD_TEST_CASE(tcs, kyuafile__load__other_directory); + ATF_ADD_TEST_CASE(tcs, kyuafile__load__build_directory); + ATF_ADD_TEST_CASE(tcs, kyuafile__load__test_program_not_basename); + ATF_ADD_TEST_CASE(tcs, kyuafile__load__lua_error); + ATF_ADD_TEST_CASE(tcs, kyuafile__load__syntax__not_called); + ATF_ADD_TEST_CASE(tcs, kyuafile__load__syntax__deprecated_format); + ATF_ADD_TEST_CASE(tcs, kyuafile__load__syntax__twice); + ATF_ADD_TEST_CASE(tcs, kyuafile__load__syntax__bad_version); + ATF_ADD_TEST_CASE(tcs, kyuafile__load__test_suite__twice); + ATF_ADD_TEST_CASE(tcs, kyuafile__load__missing_file); + ATF_ADD_TEST_CASE(tcs, kyuafile__load__missing_test_program); +} diff --git a/external/bsd/kyua-cli/dist/engine/metadata.cpp b/external/bsd/kyua-cli/dist/engine/metadata.cpp new file mode 100644 index 000000000..ae6f301f7 --- /dev/null +++ b/external/bsd/kyua-cli/dist/engine/metadata.cpp @@ -0,0 +1,1115 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "engine/metadata.hpp" + +#include + +#include "engine/exceptions.hpp" +#include "utils/config/exceptions.hpp" +#include "utils/config/nodes.ipp" +#include "utils/config/tree.ipp" +#include "utils/datetime.hpp" +#include "utils/defs.hpp" +#include "utils/format/macros.hpp" +#include "utils/fs/exceptions.hpp" +#include "utils/fs/operations.hpp" +#include "utils/fs/path.hpp" +#include "utils/memory.hpp" +#include "utils/passwd.hpp" +#include "utils/sanity.hpp" +#include "utils/text/exceptions.hpp" +#include "utils/text/operations.hpp" +#include "utils/units.hpp" + +namespace config = utils::config; +namespace datetime = utils::datetime; +namespace fs = utils::fs; +namespace passwd = utils::passwd; +namespace text = utils::text; +namespace units = utils::units; + + +/// The default timeout value for test cases that do not provide one. +/// TODO(jmmv): We should not be doing this; see issue 5 for details. +datetime::delta engine::default_timeout(300, 0); + + +namespace { + + +/// A leaf node that holds a bytes quantity. +class bytes_node : public config::native_leaf_node< units::bytes > { +public: + /// Copies the node. + /// + /// \return A dynamically-allocated node. + virtual base_node* + deep_copy(void) const + { + std::auto_ptr< bytes_node > new_node(new bytes_node()); + new_node->_value = _value; + return new_node.release(); + } + + /// Pushes the node's value onto the Lua stack. + /// + /// \param unused_state The Lua state onto which to push the value. + void + push_lua(lutok::state& UTILS_UNUSED_PARAM(state)) const + { + UNREACHABLE; + } + + /// Sets the value of the node from an entry in the Lua stack. + /// + /// \param unused_state The Lua state from which to get the value. + /// \param unused_index The stack index in which the value resides. + void + set_lua(lutok::state& UTILS_UNUSED_PARAM(state), + const int UTILS_UNUSED_PARAM(index)) + { + UNREACHABLE; + } +}; + + +/// A leaf node that holds a time delta. +class delta_node : public config::typed_leaf_node< datetime::delta > { +public: + /// Copies the node. + /// + /// \return A dynamically-allocated node. + virtual base_node* + deep_copy(void) const + { + std::auto_ptr< delta_node > new_node(new delta_node()); + new_node->_value = _value; + return new_node.release(); + } + + /// Sets the value of the node from a raw string representation. + /// + /// \param raw_value The value to set the node to. + /// + /// \throw value_error If the value is invalid. + void + set_string(const std::string& raw_value) + { + unsigned int seconds; + try { + seconds = text::to_type< unsigned int >(raw_value); + } catch (const text::error& e) { + throw config::value_error(F("Invalid time delta %s") % raw_value); + } + set(datetime::delta(seconds, 0)); + } + + /// Converts the contents of the node to a string. + /// + /// \pre The node must have a value. + /// + /// \return A string representation of the value held by the node. + std::string + to_string(void) const + { + return F("%s") % value().seconds; + } + + /// Pushes the node's value onto the Lua stack. + /// + /// \param unused_state The Lua state onto which to push the value. + void + push_lua(lutok::state& UTILS_UNUSED_PARAM(state)) const + { + UNREACHABLE; + } + + /// Sets the value of the node from an entry in the Lua stack. + /// + /// \param unused_state The Lua state from which to get the value. + /// \param unused_index The stack index in which the value resides. + void + set_lua(lutok::state& UTILS_UNUSED_PARAM(state), + const int UTILS_UNUSED_PARAM(index)) + { + UNREACHABLE; + } +}; + + +/// A leaf node that holds a "required user" property. +/// +/// This node is just a string, but it provides validation of the only allowed +/// values. +class user_node : public config::string_node { + /// Copies the node. + /// + /// \return A dynamically-allocated node. + virtual base_node* + deep_copy(void) const + { + std::auto_ptr< user_node > new_node(new user_node()); + new_node->_value = _value; + return new_node.release(); + } + + /// Checks a given user textual representation for validity. + /// + /// \param user The value to validate. + /// + /// \throw config::value_error If the value is not valid. + void + validate(const value_type& user) const + { + if (!user.empty() && user != "root" && user != "unprivileged") + throw config::value_error("Invalid required user value"); + } +}; + + +/// A leaf node that holds a set of paths. +/// +/// This node type is used to represent the value of the required files and +/// required programs, for example, and these do not allow relative paths. We +/// check this here. +class paths_set_node : public config::base_set_node< fs::path > { + /// Copies the node. + /// + /// \return A dynamically-allocated node. + virtual base_node* + deep_copy(void) const + { + std::auto_ptr< paths_set_node > new_node(new paths_set_node()); + new_node->_value = _value; + return new_node.release(); + } + + /// Converts a single path to the native type. + /// + /// \param raw_value The value to parse. + /// + /// \return The parsed value. + /// + /// \throw config::value_error If the value is invalid. + fs::path + parse_one(const std::string& raw_value) const + { + try { + return fs::path(raw_value); + } catch (const fs::error& e) { + throw config::value_error(e.what()); + } + } + + /// Checks a collection of paths for validity. + /// + /// \param paths The value to validate. + /// + /// \throw config::value_error If the value is not valid. + void + validate(const value_type& paths) const + { + for (value_type::const_iterator iter = paths.begin(); + iter != paths.end(); ++iter) { + const fs::path& path = *iter; + if (!path.is_absolute() && path.ncomponents() > 1) + throw config::value_error(F("Relative path '%s' not allowed") % + *iter); + } + } +}; + + +/// Initializes a tree to hold test case requirements. +/// +/// \param [in,out] tree The tree to initialize. +static void +init_tree(config::tree& tree) +{ + tree.define< config::strings_set_node >("allowed_architectures"); + tree.set< config::strings_set_node >("allowed_architectures", + engine::strings_set()); + + tree.define< config::strings_set_node >("allowed_platforms"); + tree.set< config::strings_set_node >("allowed_platforms", + engine::strings_set()); + + tree.define_dynamic("custom"); + + tree.define< config::string_node >("description"); + tree.set< config::string_node >("description", ""); + + tree.define< config::bool_node >("has_cleanup"); + tree.set< config::bool_node >("has_cleanup", false); + + tree.define< config::strings_set_node >("required_configs"); + tree.set< config::strings_set_node >("required_configs", + engine::strings_set()); + + tree.define< paths_set_node >("required_files"); + tree.set< paths_set_node >("required_files", engine::paths_set()); + + tree.define< bytes_node >("required_memory"); + tree.set< bytes_node >("required_memory", units::bytes(0)); + + tree.define< paths_set_node >("required_programs"); + tree.set< paths_set_node >("required_programs", engine::paths_set()); + + tree.define< user_node >("required_user"); + tree.set< user_node >("required_user", ""); + + tree.define< delta_node >("timeout"); + tree.set< delta_node >("timeout", engine::default_timeout); +} + + +/// Looks up a value in a tree with error rewriting. +/// +/// \tparam NodeType The type of the node. +/// \param tree The tree in which to insert the value. +/// \param key The key to set. +/// +/// \return A read-write reference to the value in the node. +/// +/// \throw engine::error If the key is not known or if the value is not valid. +template< class NodeType > +typename NodeType::value_type& +lookup_rw(config::tree& tree, const std::string& key) +{ + try { + return tree.lookup_rw< NodeType >(key); + } catch (const config::unknown_key_error& e) { + throw engine::error(F("Unknown metadata property %s") % key); + } catch (const config::value_error& e) { + throw engine::error(F("Invalid value for metadata property %s: %s") % + key % e.what()); + } +} + + +/// Sets a value in a tree with error rewriting. +/// +/// \tparam NodeType The type of the node. +/// \param tree The tree in which to insert the value. +/// \param key The key to set. +/// \param value The value to set the node to. +/// +/// \throw engine::error If the key is not known or if the value is not valid. +template< class NodeType > +void +set(config::tree& tree, const std::string& key, + const typename NodeType::value_type& value) +{ + try { + tree.set< NodeType >(key, value); + } catch (const config::unknown_key_error& e) { + throw engine::error(F("Unknown metadata property %s") % key); + } catch (const config::value_error& e) { + throw engine::error(F("Invalid value for metadata property %s: %s") % + key % e.what()); + } +} + + +/// Checks if all required configuration variables are present. +/// +/// \param required_configs Set of required variable names. +/// \param user_config Runtime user configuration. +/// \param test_suite_name Name of the test suite the test belongs to. +/// +/// \return Empty if all variables are present or an error message otherwise. +static std::string +check_required_configs(const engine::strings_set& required_configs, + const config::tree& user_config, + const std::string& test_suite_name) +{ + for (engine::strings_set::const_iterator iter = required_configs.begin(); + iter != required_configs.end(); iter++) { + std::string property; + // TODO(jmmv): All this rewrite logic belongs in the ATF interface. + if ((*iter) == "unprivileged-user" || (*iter) == "unprivileged_user") + property = "unprivileged_user"; + else + property = F("test_suites.%s.%s") % test_suite_name % (*iter); + + if (!user_config.is_set(property)) + return F("Required configuration property '%s' not defined") % + (*iter); + } + return ""; +} + + +/// Checks if the allowed architectures match the current architecture. +/// +/// \param allowed_architectures Set of allowed architectures. +/// \param user_config Runtime user configuration. +/// +/// \return Empty if the current architecture is in the list or an error +/// message otherwise. +static std::string +check_allowed_architectures(const engine::strings_set& allowed_architectures, + const config::tree& user_config) +{ + if (!allowed_architectures.empty()) { + const std::string architecture = + user_config.lookup< config::string_node >("architecture"); + if (allowed_architectures.find(architecture) == + allowed_architectures.end()) + return F("Current architecture '%s' not supported") % architecture; + } + return ""; +} + + +/// Checks if the allowed platforms match the current architecture. +/// +/// \param allowed_platforms Set of allowed platforms. +/// \param user_config Runtime user configuration. +/// +/// \return Empty if the current platform is in the list or an error message +/// otherwise. +static std::string +check_allowed_platforms(const engine::strings_set& allowed_platforms, + const config::tree& user_config) +{ + if (!allowed_platforms.empty()) { + const std::string platform = + user_config.lookup< config::string_node >("platform"); + if (allowed_platforms.find(platform) == allowed_platforms.end()) + return F("Current platform '%s' not supported") % platform; + } + return ""; +} + + +/// Checks if the current user matches the required user. +/// +/// \param required_user Name of the required user category. +/// \param user_config Runtime user configuration. +/// +/// \return Empty if the current user fits the required user characteristics or +/// an error message otherwise. +static std::string +check_required_user(const std::string& required_user, + const config::tree& user_config) +{ + if (!required_user.empty()) { + const passwd::user user = passwd::current_user(); + if (required_user == "root") { + if (!user.is_root()) + return "Requires root privileges"; + } else if (required_user == "unprivileged") { + if (user.is_root()) + if (!user_config.is_set("unprivileged_user")) + return "Requires an unprivileged user but the " + "unprivileged-user configuration variable is not " + "defined"; + } else + UNREACHABLE_MSG("Value of require.user not properly validated"); + } + return ""; +} + + +/// Checks if all required files exist. +/// +/// \param required_files Set of paths. +/// +/// \return Empty if the required files all exist or an error message otherwise. +static std::string +check_required_files(const engine::paths_set& required_files) +{ + for (engine::paths_set::const_iterator iter = required_files.begin(); + iter != required_files.end(); iter++) { + INV((*iter).is_absolute()); + if (!fs::exists(*iter)) + return F("Required file '%s' not found") % *iter; + } + return ""; +} + + +/// Checks if all required programs exist. +/// +/// \param required_programs Set of paths. +/// +/// \return Empty if the required programs all exist or an error message +/// otherwise. +static std::string +check_required_programs(const engine::paths_set& required_programs) +{ + for (engine::paths_set::const_iterator iter = required_programs.begin(); + iter != required_programs.end(); iter++) { + if ((*iter).is_absolute()) { + if (!fs::exists(*iter)) + return F("Required program '%s' not found") % *iter; + } else { + if (!fs::find_in_path((*iter).c_str())) + return F("Required program '%s' not found in PATH") % *iter; + } + } + return ""; +} + + +/// Checks if the current system has the specified amount of memory. +/// +/// \param required_memory Amount of required physical memory, or zero if not +/// applicable. +/// +/// \return Empty if the current system has the required amount of memory or an +/// error message otherwise. +static std::string +check_required_memory(const units::bytes& required_memory) +{ + if (required_memory > 0) { + const units::bytes physical_memory = utils::physical_memory(); + if (physical_memory > 0 && physical_memory < required_memory) + return F("Requires %s bytes of physical memory but only %s " + "available") % + required_memory.format() % physical_memory.format(); + } + return ""; +} + + +} // anonymous namespace + + +/// Internal implementation of the metadata class. +struct engine::metadata::impl { + /// Metadata properties. + config::tree props; + + /// Constructor. + /// + /// \param props_ Metadata properties of the test. + impl(const utils::config::tree& props_) : + props(props_) + { + } + + /// Equality comparator. + /// + /// \param other The other object to compare this one to. + /// + /// \return True if this object and other are equal; false otherwise. + bool + operator==(const impl& other) const + { + return props == other.props; + } +}; + + +/// Constructor. +/// +/// \param props Metadata properties of the test. +engine::metadata::metadata(const utils::config::tree& props) : + _pimpl(new impl(props)) +{ +} + + +/// Destructor. +engine::metadata::~metadata(void) +{ +} + + +/// Returns the architectures allowed by the test. +/// +/// \return Set of architectures, or empty if this does not apply. +const engine::strings_set& +engine::metadata::allowed_architectures(void) const +{ + return _pimpl->props.lookup< config::strings_set_node >( + "allowed_architectures"); +} + + +/// Returns the platforms allowed by the test. +/// +/// \return Set of platforms, or empty if this does not apply. +const engine::strings_set& +engine::metadata::allowed_platforms(void) const +{ + return _pimpl->props.lookup< config::strings_set_node >("allowed_platforms"); +} + + +/// Returns all the user-defined metadata properties. +/// +/// \return A key/value map of properties. +engine::properties_map +engine::metadata::custom(void) const +{ + return _pimpl->props.all_properties("custom", true); +} + + +/// Returns the description of the test. +/// +/// \return Textual description; may be empty. +const std::string& +engine::metadata::description(void) const +{ + return _pimpl->props.lookup< config::string_node >("description"); +} + + +/// Returns whether the test has a cleanup part or not. +/// +/// \return True if there is a cleanup part; false otherwise. +bool +engine::metadata::has_cleanup(void) const +{ + return _pimpl->props.lookup< config::bool_node >("has_cleanup"); +} + + +/// Returns the list of configuration variables needed by the test. +/// +/// \return Set of configuration variables. +const engine::strings_set& +engine::metadata::required_configs(void) const +{ + return _pimpl->props.lookup< config::strings_set_node >("required_configs"); +} + + +/// Returns the list of files needed by the test. +/// +/// \return Set of paths. +const engine::paths_set& +engine::metadata::required_files(void) const +{ + return _pimpl->props.lookup< paths_set_node >("required_files"); +} + + +/// Returns the amount of memory required by the test. +/// +/// \return Number of bytes, or 0 if this does not apply. +const units::bytes& +engine::metadata::required_memory(void) const +{ + return _pimpl->props.lookup< bytes_node >("required_memory"); +} + + +/// Returns the list of programs needed by the test. +/// +/// \return Set of paths. +const engine::paths_set& +engine::metadata::required_programs(void) const +{ + return _pimpl->props.lookup< paths_set_node >("required_programs"); +} + + +/// Returns the user required by the test. +/// +/// \return One of unprivileged, root or empty. +const std::string& +engine::metadata::required_user(void) const +{ + return _pimpl->props.lookup< user_node >("required_user"); +} + + +/// Returns the timeout of the test. +/// +/// \return A time delta; should be compared to default_timeout to see if it has +/// been overriden. +const datetime::delta& +engine::metadata::timeout(void) const +{ + return _pimpl->props.lookup< delta_node >("timeout"); +} + + +/// Externalizes the metadata to a set of key/value textual pairs. +/// +/// \return A key/value representation of the metadata. +engine::properties_map +engine::metadata::to_properties(void) const +{ + return _pimpl->props.all_properties(); +} + + +/// Equality comparator. +/// +/// \param other The other object to compare this one to. +/// +/// \return True if this object and other are equal; false otherwise. +bool +engine::metadata::operator==(const metadata& other) const +{ + return _pimpl == other._pimpl || *_pimpl == *other._pimpl; +} + + +/// Inequality comparator. +/// +/// \param other The other object to compare this one to. +/// +/// \return True if this object and other are different; false otherwise. +bool +engine::metadata::operator!=(const metadata& other) const +{ + return !(*this == other); +} + + +/// Injects the object into a stream. +/// +/// \param output The stream into which to inject the object. +/// \param object The object to format. +/// +/// \return The output stream. +std::ostream& +engine::operator<<(std::ostream& output, const metadata& object) +{ + output << "metadata{"; + + bool first = true; + const engine::properties_map props = object.to_properties(); + for (engine::properties_map::const_iterator iter = props.begin(); + iter != props.end(); ++iter) { + if (!first) + output << ", "; + output << F("%s=%s") % (*iter).first % + text::quote((*iter).second, '\''); + first = false; + } + + output << "}"; + return output; +} + + +/// Internal implementation of the metadata_builder class. +struct engine::metadata_builder::impl { + /// Collection of requirements. + config::tree props; + + /// Whether we have created a metadata object or not. + bool built; + + /// Constructor. + impl(void) : + built(false) + { + init_tree(props); + } + + /// Constructor. + impl(const engine::metadata& base) : + props(base._pimpl->props.deep_copy()), + built(false) + { + } +}; + + +/// Constructor. +engine::metadata_builder::metadata_builder(void) : + _pimpl(new impl()) +{ +} + + +/// Constructor. +engine::metadata_builder::metadata_builder(const engine::metadata& base) : + _pimpl(new impl(base)) +{ +} + + +/// Destructor. +engine::metadata_builder::~metadata_builder(void) +{ +} + + +/// Accumulates an additional allowed architecture. +/// +/// \param arch The architecture. +/// +/// \return A reference to this builder. +/// +/// \throw engine::error If the value is invalid. +engine::metadata_builder& +engine::metadata_builder::add_allowed_architecture(const std::string& arch) +{ + lookup_rw< config::strings_set_node >( + _pimpl->props, "allowed_architectures").insert(arch); + return *this; +} + + +/// Accumulates an additional allowed platform. +/// +/// \param platform The platform. +/// +/// \return A reference to this builder. +/// +/// \throw engine::error If the value is invalid. +engine::metadata_builder& +engine::metadata_builder::add_allowed_platform(const std::string& platform) +{ + lookup_rw< config::strings_set_node >( + _pimpl->props, "allowed_platforms").insert(platform); + return *this; +} + + +/// Accumulates a single user-defined property. +/// +/// \param key Name of the property to define. +/// \param value Value of the property. +/// +/// \return A reference to this builder. +/// +/// \throw engine::error If the value is invalid. +engine::metadata_builder& +engine::metadata_builder::add_custom(const std::string& key, + const std::string& value) +{ + _pimpl->props.set_string(F("custom.%s") % key, value); + return *this; +} + + +/// Accumulates an additional required configuration variable. +/// +/// \param var The name of the configuration variable. +/// +/// \return A reference to this builder. +/// +/// \throw engine::error If the value is invalid. +engine::metadata_builder& +engine::metadata_builder::add_required_config(const std::string& var) +{ + lookup_rw< config::strings_set_node >( + _pimpl->props, "required_configs").insert(var); + return *this; +} + + +/// Accumulates an additional required file. +/// +/// \param path The path to the file. +/// +/// \return A reference to this builder. +/// +/// \throw engine::error If the value is invalid. +engine::metadata_builder& +engine::metadata_builder::add_required_file(const fs::path& path) +{ + lookup_rw< paths_set_node >(_pimpl->props, "required_files").insert(path); + return *this; +} + + +/// Accumulates an additional required program. +/// +/// \param path The path to the program. +/// +/// \return A reference to this builder. +/// +/// \throw engine::error If the value is invalid. +engine::metadata_builder& +engine::metadata_builder::add_required_program(const fs::path& path) +{ + lookup_rw< paths_set_node >(_pimpl->props, + "required_programs").insert(path); + return *this; +} + + +/// Sets the architectures allowed by the test. +/// +/// \param as Set of architectures. +/// +/// \return A reference to this builder. +/// +/// \throw engine::error If the value is invalid. +engine::metadata_builder& +engine::metadata_builder::set_allowed_architectures(const strings_set& as) +{ + set< config::strings_set_node >(_pimpl->props, "allowed_architectures", as); + return *this; +} + + +/// Sets the platforms allowed by the test. +/// +/// \return ps Set of platforms. +/// +/// \return A reference to this builder. +/// +/// \throw engine::error If the value is invalid. +engine::metadata_builder& +engine::metadata_builder::set_allowed_platforms(const strings_set& ps) +{ + set< config::strings_set_node >(_pimpl->props, "allowed_platforms", ps); + return *this; +} + + +/// Sets the user-defined properties. +/// +/// \param props The custom properties to set. +/// +/// \return A reference to this builder. +/// +/// \throw engine::error If the value is invalid. +engine::metadata_builder& +engine::metadata_builder::set_custom(const properties_map& props) +{ + for (properties_map::const_iterator iter = props.begin(); + iter != props.end(); ++iter) + _pimpl->props.set_string(F("custom.%s") % (*iter).first, + (*iter).second); + return *this; +} + + +/// Sets the description of the test. +/// +/// \param description Textual description of the test. +/// +/// \return A reference to this builder. +/// +/// \throw engine::error If the value is invalid. +engine::metadata_builder& +engine::metadata_builder::set_description(const std::string& description) +{ + set< config::string_node >(_pimpl->props, "description", description); + return *this; +} + + +/// Sets whether the test has a cleanup part or not. +/// +/// \param cleanup True if the test has a cleanup part; false otherwise. +/// +/// \return A reference to this builder. +/// +/// \throw engine::error If the value is invalid. +engine::metadata_builder& +engine::metadata_builder::set_has_cleanup(const bool cleanup) +{ + set< config::bool_node >(_pimpl->props, "has_cleanup", cleanup); + return *this; +} + + +/// Sets the list of configuration variables needed by the test. +/// +/// \param vars Set of configuration variables. +/// +/// \return A reference to this builder. +/// +/// \throw engine::error If the value is invalid. +engine::metadata_builder& +engine::metadata_builder::set_required_configs(const strings_set& vars) +{ + set< config::strings_set_node >(_pimpl->props, "required_configs", vars); + return *this; +} + + +/// Sets the list of files needed by the test. +/// +/// \param files Set of paths. +/// +/// \return A reference to this builder. +/// +/// \throw engine::error If the value is invalid. +engine::metadata_builder& +engine::metadata_builder::set_required_files(const paths_set& files) +{ + set< paths_set_node >(_pimpl->props, "required_files", files); + return *this; +} + + +/// Sets the amount of memory required by the test. +/// +/// \param bytes Number of bytes. +/// +/// \return A reference to this builder. +/// +/// \throw engine::error If the value is invalid. +engine::metadata_builder& +engine::metadata_builder::set_required_memory(const units::bytes& bytes) +{ + set< bytes_node >(_pimpl->props, "required_memory", bytes); + return *this; +} + + +/// Sets the list of programs needed by the test. +/// +/// \param progs Set of paths. +/// +/// \return A reference to this builder. +/// +/// \throw engine::error If the value is invalid. +engine::metadata_builder& +engine::metadata_builder::set_required_programs(const paths_set& progs) +{ + set< paths_set_node >(_pimpl->props, "required_programs", progs); + return *this; +} + + +/// Sets the user required by the test. +/// +/// \param user One of unprivileged, root or empty. +/// +/// \return A reference to this builder. +/// +/// \throw engine::error If the value is invalid. +engine::metadata_builder& +engine::metadata_builder::set_required_user(const std::string& user) +{ + set< user_node >(_pimpl->props, "required_user", user); + return *this; +} + + +/// Sets a metadata property by name from its textual representation. +/// +/// \param key The property to set. +/// \param value The value to set the property to. +/// +/// \return A reference to this builder. +/// +/// \throw engine::error If the value is invalid or the key does not exist. +engine::metadata_builder& +engine::metadata_builder::set_string(const std::string& key, + const std::string& value) +{ + try { + _pimpl->props.set_string(key, value); + } catch (const config::unknown_key_error& e) { + throw engine::format_error(F("Unknown metadata property %s") % key); + } catch (const config::value_error& e) { + throw engine::format_error( + F("Invalid value for metadata property %s: %s") % key % e.what()); + } + return *this; +} + + +/// Sets the timeout of the test. +/// +/// \param timeout The timeout to set. +/// +/// \return A reference to this builder. +/// +/// \throw engine::error If the value is invalid. +engine::metadata_builder& +engine::metadata_builder::set_timeout(const datetime::delta& timeout) +{ + set< delta_node >(_pimpl->props, "timeout", timeout); + return *this; +} + + +/// Creates a new metadata object. +/// +/// \pre This has not yet been called. We only support calling this function +/// once due to the way the internal tree works: we pass around references, not +/// deep copies, so if we allowed a second build, we'd encourage reusing the +/// same builder to construct different metadata objects, and this could have +/// unintended consequences. +/// +/// \return The constructed metadata object. +engine::metadata +engine::metadata_builder::build(void) const +{ + PRE(!_pimpl->built); + _pimpl->built = true; + + return metadata(_pimpl->props); +} + + +/// Checks if all the requirements specified by the test case are met. +/// +/// \param md The test metadata. +/// \param cfg The engine configuration. +/// \param test_suite Name of the test suite the test belongs to. +/// +/// \return A string describing the reason for skipping the test, or empty if +/// the test should be executed. +std::string +engine::check_reqs(const engine::metadata& md, const config::tree& cfg, + const std::string& test_suite) +{ + std::string reason; + + reason = check_required_configs(md.required_configs(), cfg, test_suite); + if (!reason.empty()) + return reason; + + reason = check_allowed_architectures(md.allowed_architectures(), cfg); + if (!reason.empty()) + return reason; + + reason = check_allowed_platforms(md.allowed_platforms(), cfg); + if (!reason.empty()) + return reason; + + reason = check_required_user(md.required_user(), cfg); + if (!reason.empty()) + return reason; + + reason = check_required_files(md.required_files()); + if (!reason.empty()) + return reason; + + reason = check_required_programs(md.required_programs()); + if (!reason.empty()) + return reason; + + reason = check_required_memory(md.required_memory()); + if (!reason.empty()) + return reason; + + INV(reason.empty()); + return reason; +} diff --git a/external/bsd/kyua-cli/dist/engine/metadata.hpp b/external/bsd/kyua-cli/dist/engine/metadata.hpp new file mode 100644 index 000000000..cbf73a8b3 --- /dev/null +++ b/external/bsd/kyua-cli/dist/engine/metadata.hpp @@ -0,0 +1,149 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file engine/metadata.hpp +/// Representation of the metadata of a test program or test case. + +#if !defined(ENGINE_METADATA_HPP) +#define ENGINE_METADATA_HPP + +#include +#include +#include +#include +#include + +#include + +#include "utils/noncopyable.hpp" + +namespace utils { +namespace config { class tree; } +namespace datetime { class delta; } +namespace fs { class path; } +namespace units { class bytes; } +} // namespace utils + +namespace engine { + + +// TODO(jmmv): All these types should probably be in individual header files so +// that we could include them without pulling in additional dependencies. +/// Collection of paths. +typedef std::set< utils::fs::path > paths_set; +/// Collection of strings. +typedef std::set< std::string > strings_set; +/// Collection of test properties in their textual form. +typedef std::map< std::string, std::string > properties_map; + + +extern utils::datetime::delta default_timeout; + + +class metadata_builder; + + +/// Collection of metadata properties of a test. +class metadata { + struct impl; + + /// Pointer to the shared internal implementation. + std::tr1::shared_ptr< impl > _pimpl; + + friend class metadata_builder; + +public: + metadata(const utils::config::tree&); + ~metadata(void); + + const strings_set& allowed_architectures(void) const; + const strings_set& allowed_platforms(void) const; + properties_map custom(void) const; + const std::string& description(void) const; + bool has_cleanup(void) const; + const strings_set& required_configs(void) const; + const paths_set& required_files(void) const; + const utils::units::bytes& required_memory(void) const; + const paths_set& required_programs(void) const; + const std::string& required_user(void) const; + const utils::datetime::delta& timeout(void) const; + + engine::properties_map to_properties(void) const; + + bool operator==(const metadata&) const; + bool operator!=(const metadata&) const; +}; + + +std::ostream& operator<<(std::ostream&, const metadata&); + + +/// Builder for a metadata object. +class metadata_builder : utils::noncopyable { + struct impl; + + /// Pointer to the shared internal implementation. + std::auto_ptr< impl > _pimpl; + +public: + metadata_builder(void); + explicit metadata_builder(const engine::metadata&); + ~metadata_builder(void); + + metadata_builder& add_allowed_architecture(const std::string&); + metadata_builder& add_allowed_platform(const std::string&); + metadata_builder& add_custom(const std::string&, const std::string&); + metadata_builder& add_required_config(const std::string&); + metadata_builder& add_required_file(const utils::fs::path&); + metadata_builder& add_required_program(const utils::fs::path&); + + metadata_builder& set_allowed_architectures(const strings_set&); + metadata_builder& set_allowed_platforms(const strings_set&); + metadata_builder& set_custom(const properties_map&); + metadata_builder& set_description(const std::string&); + metadata_builder& set_has_cleanup(const bool); + metadata_builder& set_required_configs(const strings_set&); + metadata_builder& set_required_files(const paths_set&); + metadata_builder& set_required_memory(const utils::units::bytes&); + metadata_builder& set_required_programs(const paths_set&); + metadata_builder& set_required_user(const std::string&); + metadata_builder& set_string(const std::string&, const std::string&); + metadata_builder& set_timeout(const utils::datetime::delta&); + + metadata build(void) const; +}; + + +std::string check_reqs(const engine::metadata&, const utils::config::tree&, + const std::string&); + + +} // namespace engine + + +#endif // !defined(ENGINE_METADATA_HPP) diff --git a/external/bsd/kyua-cli/dist/engine/metadata_test.cpp b/external/bsd/kyua-cli/dist/engine/metadata_test.cpp new file mode 100644 index 000000000..8bc14d158 --- /dev/null +++ b/external/bsd/kyua-cli/dist/engine/metadata_test.cpp @@ -0,0 +1,785 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "engine/metadata.hpp" + +#include + +#include + +#include "engine/config.hpp" +#include "utils/config/tree.ipp" +#include "utils/datetime.hpp" +#include "utils/env.hpp" +#include "utils/fs/operations.hpp" +#include "utils/fs/path.hpp" +#include "utils/memory.hpp" +#include "utils/passwd.hpp" +#include "utils/units.hpp" + +namespace config = utils::config; +namespace datetime = utils::datetime; +namespace fs = utils::fs; +namespace passwd = utils::passwd; +namespace units = utils::units; + + +ATF_TEST_CASE_WITHOUT_HEAD(defaults); +ATF_TEST_CASE_BODY(defaults) +{ + const engine::metadata md = engine::metadata_builder().build(); + ATF_REQUIRE(md.allowed_architectures().empty()); + ATF_REQUIRE(md.allowed_platforms().empty()); + ATF_REQUIRE(md.allowed_platforms().empty()); + ATF_REQUIRE(md.custom().empty()); + ATF_REQUIRE(md.description().empty()); + ATF_REQUIRE(!md.has_cleanup()); + ATF_REQUIRE(md.required_configs().empty()); + ATF_REQUIRE(md.required_files().empty()); + ATF_REQUIRE_EQ(units::bytes(0), md.required_memory()); + ATF_REQUIRE(md.required_programs().empty()); + ATF_REQUIRE(md.required_user().empty()); + ATF_REQUIRE(engine::default_timeout == md.timeout()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(add); +ATF_TEST_CASE_BODY(add) +{ + engine::strings_set architectures; + architectures.insert("1-architecture"); + architectures.insert("2-architecture"); + + engine::strings_set platforms; + platforms.insert("1-platform"); + platforms.insert("2-platform"); + + engine::properties_map custom; + custom["1-custom"] = "first"; + custom["2-custom"] = "second"; + + engine::strings_set configs; + configs.insert("1-config"); + configs.insert("2-config"); + + engine::paths_set files; + files.insert(fs::path("1-file")); + files.insert(fs::path("2-file")); + + engine::paths_set programs; + programs.insert(fs::path("1-program")); + programs.insert(fs::path("2-program")); + + const engine::metadata md = engine::metadata_builder() + .add_allowed_architecture("1-architecture") + .add_allowed_platform("1-platform") + .add_custom("1-custom", "first") + .add_custom("2-custom", "second") + .add_required_config("1-config") + .add_required_file(fs::path("1-file")) + .add_required_program(fs::path("1-program")) + .add_allowed_architecture("2-architecture") + .add_allowed_platform("2-platform") + .add_required_config("2-config") + .add_required_file(fs::path("2-file")) + .add_required_program(fs::path("2-program")) + .build(); + + ATF_REQUIRE(architectures == md.allowed_architectures()); + ATF_REQUIRE(platforms == md.allowed_platforms()); + ATF_REQUIRE(custom == md.custom()); + ATF_REQUIRE(configs == md.required_configs()); + ATF_REQUIRE(files == md.required_files()); + ATF_REQUIRE(programs == md.required_programs()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(copy); +ATF_TEST_CASE_BODY(copy) +{ + const engine::metadata md1 = engine::metadata_builder() + .add_allowed_architecture("1-architecture") + .add_allowed_platform("1-platform") + .build(); + + const engine::metadata md2 = engine::metadata_builder(md1) + .add_allowed_architecture("2-architecture") + .build(); + + ATF_REQUIRE_EQ(1, md1.allowed_architectures().size()); + ATF_REQUIRE_EQ(2, md2.allowed_architectures().size()); + ATF_REQUIRE_EQ(1, md1.allowed_platforms().size()); + ATF_REQUIRE_EQ(1, md2.allowed_platforms().size()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(override_all_with_setters); +ATF_TEST_CASE_BODY(override_all_with_setters) +{ + engine::strings_set architectures; + architectures.insert("the-architecture"); + + engine::strings_set platforms; + platforms.insert("the-platforms"); + + engine::properties_map custom; + custom["first"] = "hello"; + custom["second"] = "bye"; + + const std::string description = "Some long text"; + + engine::strings_set configs; + configs.insert("the-configs"); + + engine::paths_set files; + files.insert(fs::path("the-files")); + + const units::bytes memory(12345); + + engine::paths_set programs; + programs.insert(fs::path("the-programs")); + + const std::string user = "root"; + + const datetime::delta timeout(123, 0); + + const engine::metadata md = engine::metadata_builder() + .set_allowed_architectures(architectures) + .set_allowed_platforms(platforms) + .set_custom(custom) + .set_description(description) + .set_has_cleanup(true) + .set_required_configs(configs) + .set_required_files(files) + .set_required_memory(memory) + .set_required_programs(programs) + .set_required_user(user) + .set_timeout(timeout) + .build(); + + ATF_REQUIRE(architectures == md.allowed_architectures()); + ATF_REQUIRE(platforms == md.allowed_platforms()); + ATF_REQUIRE(custom == md.custom()); + ATF_REQUIRE_EQ(description, md.description()); + ATF_REQUIRE(md.has_cleanup()); + ATF_REQUIRE(configs == md.required_configs()); + ATF_REQUIRE(files == md.required_files()); + ATF_REQUIRE_EQ(memory, md.required_memory()); + ATF_REQUIRE(programs == md.required_programs()); + ATF_REQUIRE_EQ(user, md.required_user()); + ATF_REQUIRE(timeout == md.timeout()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(override_all_with_set_string); +ATF_TEST_CASE_BODY(override_all_with_set_string) +{ + engine::strings_set architectures; + architectures.insert("a1"); + architectures.insert("a2"); + + engine::strings_set platforms; + platforms.insert("p1"); + platforms.insert("p2"); + + engine::properties_map custom; + custom["user-defined"] = "the-value"; + + const std::string description = "Another long text"; + + engine::strings_set configs; + configs.insert("config-var"); + + engine::paths_set files; + files.insert(fs::path("plain")); + files.insert(fs::path("/absolute/path")); + + const units::bytes memory(1024 * 1024); + + engine::paths_set programs; + programs.insert(fs::path("program")); + programs.insert(fs::path("/absolute/prog")); + + const std::string user = "unprivileged"; + + const datetime::delta timeout(45, 0); + + const engine::metadata md = engine::metadata_builder() + .set_string("allowed_architectures", "a1 a2") + .set_string("allowed_platforms", "p1 p2") + .set_string("custom.user-defined", "the-value") + .set_string("description", "Another long text") + .set_string("has_cleanup", "true") + .set_string("required_configs", "config-var") + .set_string("required_files", "plain /absolute/path") + .set_string("required_memory", "1M") + .set_string("required_programs", "program /absolute/prog") + .set_string("required_user", "unprivileged") + .set_string("timeout", "45") + .build(); + + ATF_REQUIRE(architectures == md.allowed_architectures()); + ATF_REQUIRE(platforms == md.allowed_platforms()); + ATF_REQUIRE(custom == md.custom()); + ATF_REQUIRE_EQ(description, md.description()); + ATF_REQUIRE(md.has_cleanup()); + ATF_REQUIRE(configs == md.required_configs()); + ATF_REQUIRE(files == md.required_files()); + ATF_REQUIRE_EQ(memory, md.required_memory()); + ATF_REQUIRE(programs == md.required_programs()); + ATF_REQUIRE_EQ(user, md.required_user()); + ATF_REQUIRE(timeout == md.timeout()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(operators_eq_and_ne__empty); +ATF_TEST_CASE_BODY(operators_eq_and_ne__empty) +{ + const engine::metadata md1 = engine::metadata_builder().build(); + const engine::metadata md2 = engine::metadata_builder().build(); + ATF_REQUIRE( md1 == md2); + ATF_REQUIRE(!(md1 != md2)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(operators_eq_and_ne__copy); +ATF_TEST_CASE_BODY(operators_eq_and_ne__copy) +{ + const engine::metadata md1 = engine::metadata_builder() + .add_custom("X-foo", "bar") + .build(); + const engine::metadata md2 = md1; + ATF_REQUIRE( md1 == md2); + ATF_REQUIRE(!(md1 != md2)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(operators_eq_and_ne__equal); +ATF_TEST_CASE_BODY(operators_eq_and_ne__equal) +{ + const engine::metadata md1 = engine::metadata_builder() + .add_allowed_architecture("a") + .add_allowed_architecture("b") + .add_custom("X-foo", "bar") + .build(); + const engine::metadata md2 = engine::metadata_builder() + .add_allowed_architecture("b") + .add_allowed_architecture("a") + .add_custom("X-foo", "bar") + .build(); + ATF_REQUIRE( md1 == md2); + ATF_REQUIRE(!(md1 != md2)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(operators_eq_and_ne__different); +ATF_TEST_CASE_BODY(operators_eq_and_ne__different) +{ + const engine::metadata md1 = engine::metadata_builder() + .add_custom("X-foo", "bar") + .build(); + const engine::metadata md2 = engine::metadata_builder() + .add_custom("X-foo", "bar") + .add_custom("X-baz", "foo bar") + .build(); + ATF_REQUIRE(!(md1 == md2)); + ATF_REQUIRE( md1 != md2); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(output__defaults); +ATF_TEST_CASE_BODY(output__defaults) +{ + std::ostringstream str; + str << engine::metadata_builder().build(); + ATF_REQUIRE_EQ("metadata{allowed_architectures='', allowed_platforms='', " + "description='', has_cleanup='false', required_configs='', " + "required_files='', required_memory='0', " + "required_programs='', required_user='', timeout='300'}", + str.str()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(output__some_values); +ATF_TEST_CASE_BODY(output__some_values) +{ + std::ostringstream str; + str << engine::metadata_builder() + .add_allowed_architecture("abc") + .add_required_file(fs::path("foo")) + .add_required_file(fs::path("bar")) + .set_required_memory(units::bytes(1024)) + .build(); + ATF_REQUIRE_EQ( + "metadata{allowed_architectures='abc', allowed_platforms='', " + "description='', has_cleanup='false', required_configs='', " + "required_files='bar foo', required_memory='1024', " + "required_programs='', required_user='', timeout='300'}", + str.str()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__none); +ATF_TEST_CASE_BODY(check_reqs__none) +{ + const engine::metadata md = engine::metadata_builder().build(); + ATF_REQUIRE(engine::check_reqs(md, engine::empty_config(), "").empty()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__allowed_architectures__one_ok); +ATF_TEST_CASE_BODY(check_reqs__allowed_architectures__one_ok) +{ + const engine::metadata md = engine::metadata_builder() + .add_allowed_architecture("x86_64") + .build(); + + config::tree user_config = engine::default_config(); + user_config.set_string("architecture", "x86_64"); + user_config.set_string("platform", ""); + ATF_REQUIRE(engine::check_reqs(md, user_config, "").empty()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__allowed_architectures__one_fail); +ATF_TEST_CASE_BODY(check_reqs__allowed_architectures__one_fail) +{ + const engine::metadata md = engine::metadata_builder() + .add_allowed_architecture("x86_64") + .build(); + + config::tree user_config = engine::default_config(); + user_config.set_string("architecture", "i386"); + user_config.set_string("platform", ""); + ATF_REQUIRE_MATCH("Current architecture 'i386' not supported", + engine::check_reqs(md, user_config, "")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__allowed_architectures__many_ok); +ATF_TEST_CASE_BODY(check_reqs__allowed_architectures__many_ok) +{ + const engine::metadata md = engine::metadata_builder() + .add_allowed_architecture("x86_64") + .add_allowed_architecture("i386") + .add_allowed_architecture("powerpc") + .build(); + + config::tree user_config = engine::default_config(); + user_config.set_string("architecture", "i386"); + user_config.set_string("platform", ""); + ATF_REQUIRE(engine::check_reqs(md, user_config, "").empty()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__allowed_architectures__many_fail); +ATF_TEST_CASE_BODY(check_reqs__allowed_architectures__many_fail) +{ + const engine::metadata md = engine::metadata_builder() + .add_allowed_architecture("x86_64") + .add_allowed_architecture("i386") + .add_allowed_architecture("powerpc") + .build(); + + config::tree user_config = engine::default_config(); + user_config.set_string("architecture", "arm"); + user_config.set_string("platform", ""); + ATF_REQUIRE_MATCH("Current architecture 'arm' not supported", + engine::check_reqs(md, user_config, "")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__allowed_platforms__one_ok); +ATF_TEST_CASE_BODY(check_reqs__allowed_platforms__one_ok) +{ + const engine::metadata md = engine::metadata_builder() + .add_allowed_platform("amd64") + .build(); + + config::tree user_config = engine::default_config(); + user_config.set_string("architecture", ""); + user_config.set_string("platform", "amd64"); + ATF_REQUIRE(engine::check_reqs(md, user_config, "").empty()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__allowed_platforms__one_fail); +ATF_TEST_CASE_BODY(check_reqs__allowed_platforms__one_fail) +{ + const engine::metadata md = engine::metadata_builder() + .add_allowed_platform("amd64") + .build(); + + config::tree user_config = engine::default_config(); + user_config.set_string("architecture", ""); + user_config.set_string("platform", "i386"); + ATF_REQUIRE_MATCH("Current platform 'i386' not supported", + engine::check_reqs(md, user_config, "")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__allowed_platforms__many_ok); +ATF_TEST_CASE_BODY(check_reqs__allowed_platforms__many_ok) +{ + const engine::metadata md = engine::metadata_builder() + .add_allowed_platform("amd64") + .add_allowed_platform("i386") + .add_allowed_platform("macppc") + .build(); + + config::tree user_config = engine::default_config(); + user_config.set_string("architecture", ""); + user_config.set_string("platform", "i386"); + ATF_REQUIRE(engine::check_reqs(md, user_config, "").empty()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__allowed_platforms__many_fail); +ATF_TEST_CASE_BODY(check_reqs__allowed_platforms__many_fail) +{ + const engine::metadata md = engine::metadata_builder() + .add_allowed_platform("amd64") + .add_allowed_platform("i386") + .add_allowed_platform("macppc") + .build(); + + config::tree user_config = engine::default_config(); + user_config.set_string("architecture", ""); + user_config.set_string("platform", "shark"); + ATF_REQUIRE_MATCH("Current platform 'shark' not supported", + engine::check_reqs(md, user_config, "")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_configs__one_ok); +ATF_TEST_CASE_BODY(check_reqs__required_configs__one_ok) +{ + const engine::metadata md = engine::metadata_builder() + .add_required_config("my-var") + .build(); + + config::tree user_config = engine::default_config(); + user_config.set_string("test_suites.suite.aaa", "value1"); + user_config.set_string("test_suites.suite.my-var", "value2"); + user_config.set_string("test_suites.suite.zzz", "value3"); + ATF_REQUIRE(engine::check_reqs(md, user_config, "suite").empty()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_configs__one_fail); +ATF_TEST_CASE_BODY(check_reqs__required_configs__one_fail) +{ + const engine::metadata md = engine::metadata_builder() + .add_required_config("unprivileged_user") + .build(); + + config::tree user_config = engine::default_config(); + user_config.set_string("test_suites.suite.aaa", "value1"); + user_config.set_string("test_suites.suite.my-var", "value2"); + user_config.set_string("test_suites.suite.zzz", "value3"); + ATF_REQUIRE_MATCH("Required configuration property 'unprivileged_user' not " + "defined", + engine::check_reqs(md, user_config, "suite")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_configs__many_ok); +ATF_TEST_CASE_BODY(check_reqs__required_configs__many_ok) +{ + const engine::metadata md = engine::metadata_builder() + .add_required_config("foo") + .add_required_config("bar") + .add_required_config("baz") + .build(); + + config::tree user_config = engine::default_config(); + user_config.set_string("test_suites.suite.aaa", "value1"); + user_config.set_string("test_suites.suite.foo", "value2"); + user_config.set_string("test_suites.suite.bar", "value3"); + user_config.set_string("test_suites.suite.baz", "value4"); + user_config.set_string("test_suites.suite.zzz", "value5"); + ATF_REQUIRE(engine::check_reqs(md, user_config, "suite").empty()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_configs__many_fail); +ATF_TEST_CASE_BODY(check_reqs__required_configs__many_fail) +{ + const engine::metadata md = engine::metadata_builder() + .add_required_config("foo") + .add_required_config("bar") + .add_required_config("baz") + .build(); + + config::tree user_config = engine::default_config(); + user_config.set_string("test_suites.suite.aaa", "value1"); + user_config.set_string("test_suites.suite.foo", "value2"); + user_config.set_string("test_suites.suite.zzz", "value3"); + ATF_REQUIRE_MATCH("Required configuration property 'bar' not defined", + engine::check_reqs(md, user_config, "suite")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_configs__special); +ATF_TEST_CASE_BODY(check_reqs__required_configs__special) +{ + const engine::metadata md = engine::metadata_builder() + .add_required_config("unprivileged-user") + .build(); + + config::tree user_config = engine::default_config(); + ATF_REQUIRE_MATCH("Required configuration property 'unprivileged-user' " + "not defined", + engine::check_reqs(md, user_config, "")); + user_config.set< engine::user_node >( + "unprivileged_user", passwd::user("foo", 1, 2)); + ATF_REQUIRE(engine::check_reqs(md, user_config, "foo").empty()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_user__root__ok); +ATF_TEST_CASE_BODY(check_reqs__required_user__root__ok) +{ + const engine::metadata md = engine::metadata_builder() + .set_required_user("root") + .build(); + + config::tree user_config = engine::default_config(); + ATF_REQUIRE(!user_config.is_set("unprivileged_user")); + + passwd::set_current_user_for_testing(passwd::user("", 0, 1)); + ATF_REQUIRE(engine::check_reqs(md, user_config, "").empty()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_user__root__fail); +ATF_TEST_CASE_BODY(check_reqs__required_user__root__fail) +{ + const engine::metadata md = engine::metadata_builder() + .set_required_user("root") + .build(); + + passwd::set_current_user_for_testing(passwd::user("", 123, 1)); + ATF_REQUIRE_MATCH("Requires root privileges", + engine::check_reqs(md, engine::empty_config(), "")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_user__unprivileged__same); +ATF_TEST_CASE_BODY(check_reqs__required_user__unprivileged__same) +{ + const engine::metadata md = engine::metadata_builder() + .set_required_user("unprivileged") + .build(); + + config::tree user_config = engine::default_config(); + ATF_REQUIRE(!user_config.is_set("unprivileged_user")); + + passwd::set_current_user_for_testing(passwd::user("", 123, 1)); + ATF_REQUIRE(engine::check_reqs(md, user_config, "").empty()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_user__unprivileged__ok); +ATF_TEST_CASE_BODY(check_reqs__required_user__unprivileged__ok) +{ + const engine::metadata md = engine::metadata_builder() + .set_required_user("unprivileged") + .build(); + + config::tree user_config = engine::default_config(); + user_config.set< engine::user_node >( + "unprivileged_user", passwd::user("", 123, 1)); + + passwd::set_current_user_for_testing(passwd::user("", 0, 1)); + ATF_REQUIRE(engine::check_reqs(md, user_config, "").empty()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_user__unprivileged__fail); +ATF_TEST_CASE_BODY(check_reqs__required_user__unprivileged__fail) +{ + const engine::metadata md = engine::metadata_builder() + .set_required_user("unprivileged") + .build(); + + config::tree user_config = engine::default_config(); + ATF_REQUIRE(!user_config.is_set("unprivileged_user")); + + passwd::set_current_user_for_testing(passwd::user("", 0, 1)); + ATF_REQUIRE_MATCH("Requires.*unprivileged.*unprivileged-user", + engine::check_reqs(md, user_config, "")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_files__ok); +ATF_TEST_CASE_BODY(check_reqs__required_files__ok) +{ + const engine::metadata md = engine::metadata_builder() + .add_required_file(fs::current_path() / "test-file") + .build(); + + atf::utils::create_file("test-file", ""); + + ATF_REQUIRE(engine::check_reqs(md, engine::empty_config(), "").empty()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_files__fail); +ATF_TEST_CASE_BODY(check_reqs__required_files__fail) +{ + const engine::metadata md = engine::metadata_builder() + .add_required_file(fs::path("/non-existent/file")) + .build(); + + ATF_REQUIRE_MATCH("'/non-existent/file' not found$", + engine::check_reqs(md, engine::empty_config(), "")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_memory__ok); +ATF_TEST_CASE_BODY(check_reqs__required_memory__ok) +{ + const engine::metadata md = engine::metadata_builder() + .set_required_memory(units::bytes::parse("1m")) + .build(); + + ATF_REQUIRE(engine::check_reqs(md, engine::empty_config(), "").empty()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_memory__fail); +ATF_TEST_CASE_BODY(check_reqs__required_memory__fail) +{ + const engine::metadata md = engine::metadata_builder() + .set_required_memory(units::bytes::parse("100t")) + .build(); + + if (utils::physical_memory() == 0) + skip("Don't know how to query the amount of physical memory"); + ATF_REQUIRE_MATCH("Requires 100.00T .*memory", + engine::check_reqs(md, engine::empty_config(), "")); +} + + +ATF_TEST_CASE(check_reqs__required_programs__ok); +ATF_TEST_CASE_HEAD(check_reqs__required_programs__ok) +{ + set_md_var("require.progs", "/bin/ls /bin/mv"); +} +ATF_TEST_CASE_BODY(check_reqs__required_programs__ok) +{ + const engine::metadata md = engine::metadata_builder() + .add_required_program(fs::path("/bin/ls")) + .add_required_program(fs::path("foo")) + .add_required_program(fs::path("/bin/mv")) + .build(); + + fs::mkdir(fs::path("bin"), 0755); + atf::utils::create_file("bin/foo", ""); + utils::setenv("PATH", (fs::current_path() / "bin").str()); + + ATF_REQUIRE(engine::check_reqs(md, engine::empty_config(), "").empty()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_programs__fail_absolute); +ATF_TEST_CASE_BODY(check_reqs__required_programs__fail_absolute) +{ + const engine::metadata md = engine::metadata_builder() + .add_required_program(fs::path("/non-existent/program")) + .build(); + + ATF_REQUIRE_MATCH("'/non-existent/program' not found$", + engine::check_reqs(md, engine::empty_config(), "")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(check_reqs__required_programs__fail_relative); +ATF_TEST_CASE_BODY(check_reqs__required_programs__fail_relative) +{ + const engine::metadata md = engine::metadata_builder() + .add_required_program(fs::path("foo")) + .add_required_program(fs::path("bar")) + .build(); + + fs::mkdir(fs::path("bin"), 0755); + atf::utils::create_file("bin/foo", ""); + utils::setenv("PATH", (fs::current_path() / "bin").str()); + + ATF_REQUIRE_MATCH("'bar' not found in PATH$", + engine::check_reqs(md, engine::empty_config(), "")); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, defaults); + ATF_ADD_TEST_CASE(tcs, add); + ATF_ADD_TEST_CASE(tcs, copy); + ATF_ADD_TEST_CASE(tcs, override_all_with_setters); + ATF_ADD_TEST_CASE(tcs, override_all_with_set_string); + + ATF_ADD_TEST_CASE(tcs, operators_eq_and_ne__empty); + ATF_ADD_TEST_CASE(tcs, operators_eq_and_ne__copy); + ATF_ADD_TEST_CASE(tcs, operators_eq_and_ne__equal); + ATF_ADD_TEST_CASE(tcs, operators_eq_and_ne__different); + + ATF_ADD_TEST_CASE(tcs, output__defaults); + ATF_ADD_TEST_CASE(tcs, output__some_values); + + // TODO(jmmv): Add tests for error conditions (invalid keys and invalid + // values). + + ATF_ADD_TEST_CASE(tcs, check_reqs__none); + ATF_ADD_TEST_CASE(tcs, check_reqs__allowed_architectures__one_ok); + ATF_ADD_TEST_CASE(tcs, check_reqs__allowed_architectures__one_fail); + ATF_ADD_TEST_CASE(tcs, check_reqs__allowed_architectures__many_ok); + ATF_ADD_TEST_CASE(tcs, check_reqs__allowed_architectures__many_fail); + ATF_ADD_TEST_CASE(tcs, check_reqs__allowed_platforms__one_ok); + ATF_ADD_TEST_CASE(tcs, check_reqs__allowed_platforms__one_fail); + ATF_ADD_TEST_CASE(tcs, check_reqs__allowed_platforms__many_ok); + ATF_ADD_TEST_CASE(tcs, check_reqs__allowed_platforms__many_fail); + ATF_ADD_TEST_CASE(tcs, check_reqs__required_configs__one_ok); + ATF_ADD_TEST_CASE(tcs, check_reqs__required_configs__one_fail); + ATF_ADD_TEST_CASE(tcs, check_reqs__required_configs__many_ok); + ATF_ADD_TEST_CASE(tcs, check_reqs__required_configs__many_fail); + ATF_ADD_TEST_CASE(tcs, check_reqs__required_configs__special); + ATF_ADD_TEST_CASE(tcs, check_reqs__required_user__root__ok); + ATF_ADD_TEST_CASE(tcs, check_reqs__required_user__root__fail); + ATF_ADD_TEST_CASE(tcs, check_reqs__required_user__unprivileged__same); + ATF_ADD_TEST_CASE(tcs, check_reqs__required_user__unprivileged__ok); + ATF_ADD_TEST_CASE(tcs, check_reqs__required_user__unprivileged__fail); + ATF_ADD_TEST_CASE(tcs, check_reqs__required_files__ok); + ATF_ADD_TEST_CASE(tcs, check_reqs__required_files__fail); + ATF_ADD_TEST_CASE(tcs, check_reqs__required_memory__ok); + ATF_ADD_TEST_CASE(tcs, check_reqs__required_memory__fail); + ATF_ADD_TEST_CASE(tcs, check_reqs__required_programs__ok); + ATF_ADD_TEST_CASE(tcs, check_reqs__required_programs__fail_absolute); + ATF_ADD_TEST_CASE(tcs, check_reqs__required_programs__fail_relative); +} diff --git a/external/bsd/kyua-cli/dist/engine/test_case.cpp b/external/bsd/kyua-cli/dist/engine/test_case.cpp new file mode 100644 index 000000000..c8a2aca82 --- /dev/null +++ b/external/bsd/kyua-cli/dist/engine/test_case.cpp @@ -0,0 +1,482 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "engine/test_case.hpp" + +extern "C" { +#include +} + +#include + +#include "engine/config.hpp" +#include "engine/exceptions.hpp" +#include "engine/test_program.hpp" +#include "engine/test_result.hpp" +#include "engine/testers.hpp" +#include "utils/config/tree.ipp" +#include "utils/datetime.hpp" +#include "utils/defs.hpp" +#include "utils/format/macros.hpp" +#include "utils/logging/operations.hpp" +#include "utils/fs/auto_cleaners.hpp" +#include "utils/fs/operations.hpp" +#include "utils/fs/path.hpp" +#include "utils/optional.ipp" +#include "utils/passwd.hpp" +#include "utils/text/operations.ipp" + +namespace config = utils::config; +namespace fs = utils::fs; +namespace logging = utils::logging; +namespace passwd = utils::passwd; +namespace text = utils::text; + +using utils::none; +using utils::optional; + + +namespace { + + +/// Generates the set of configuration variables for the tester. +/// +/// \param metadata The metadata of the test. +/// \param user_config The configuration variables provided by the user. +/// \param test_suite The name of the test suite. +/// +/// \return The mapping of configuration variables for the tester. +static config::properties_map +generate_tester_config(const engine::metadata& metadata, + const config::tree& user_config, + const std::string& test_suite) +{ + config::properties_map props; + + try { + props = user_config.all_properties(F("test_suites.%s") % test_suite, + true); + } catch (const config::unknown_key_error& unused_error) { + // Ignore: not all test suites have entries in the configuration. + } + + if (user_config.is_set("unprivileged_user")) { + const passwd::user& user = + user_config.lookup< engine::user_node >("unprivileged_user"); + props["unprivileged-user"] = user.name; + } + + // TODO(jmmv): This is an ugly hack to cope with an atf-specific + // property. We should not be doing this at all, so just consider this + // a temporary optimization... + if (metadata.has_cleanup()) + props["has.cleanup"] = "true"; + else + props["has.cleanup"] = "false"; + + return props; +} + + +/// Creates a tester. +/// +/// \param interface_name The name of the tester interface to use. +/// \param metadata Metadata of the test case. +/// \param user_config User-provided configuration variables. +/// +/// \return The created tester, on which the test() method can be executed. +static engine::tester +create_tester(const std::string& interface_name, + const engine::metadata& metadata, const config::tree& user_config) +{ + optional< passwd::user > user; + if (user_config.is_set("unprivileged_user") && + metadata.required_user() == "unprivileged") + user = user_config.lookup< engine::user_node >("unprivileged_user"); + + return engine::tester(interface_name, user, + utils::make_optional(metadata.timeout())); +} + + +} // anonymous namespace + + +/// Destructor. +engine::test_case_hooks::~test_case_hooks(void) +{ +} + + +/// Called once the test case's stdout is ready for processing. +/// +/// It is important to note that this file is only available within this +/// callback. Attempting to read the file once the execute function has +/// returned will result in an error because the file might have been deleted. +/// +/// \param unused_file The path to the file containing the stdout. +void +engine::test_case_hooks::got_stdout(const fs::path& UTILS_UNUSED_PARAM(file)) +{ +} + + +/// Called once the test case's stderr is ready for processing. +/// +/// It is important to note that this file is only available within this +/// callback. Attempting to read the file once the execute function has +/// returned will result in an error because the file might have been deleted. +/// +/// \param unused_file The path to the file containing the stderr. +void +engine::test_case_hooks::got_stderr(const fs::path& UTILS_UNUSED_PARAM(file)) +{ +} + + +/// Internal implementation for a test_case. +struct engine::test_case::impl { + /// Name of the interface implemented by the test program. + const std::string interface_name; + + /// Test program this test case belongs to. + const test_program& _test_program; + + /// Name of the test case; must be unique within the test program. + std::string name; + + /// Test case metadata. + metadata md; + + /// Fake result to return instead of running the test case. + optional< test_result > fake_result; + + /// Constructor. + /// + /// \param interface_name_ Name of the interface implemented by the test + /// program. + /// \param test_program_ The test program this test case belongs to. + /// \param name_ The name of the test case within the test program. + /// \param md_ Metadata of the test case. + /// \param fake_result_ Fake result to return instead of running the test + /// case. + impl(const std::string& interface_name_, + const test_program& test_program_, + const std::string& name_, + const metadata& md_, + const optional< test_result >& fake_result_) : + interface_name(interface_name_), + _test_program(test_program_), + name(name_), + md(md_), + fake_result(fake_result_) + { + } + + /// Equality comparator. + /// + /// \param other The other object to compare this one to. + /// + /// \return True if this object and other are equal; false otherwise. + bool + operator==(const impl& other) const + { + return (interface_name == other.interface_name && + (_test_program.absolute_path() == + other._test_program.absolute_path()) && + name == other.name && + md == other.md && + fake_result == other.fake_result); + } +}; + + +/// Constructs a new test case. +/// +/// \param interface_name_ Name of the interface implemented by the test +/// program. +/// \param test_program_ The test program this test case belongs to. This is a +/// static reference (instead of a test_program_ptr) because the test +/// program must exist in order for the test case to exist. +/// \param name_ The name of the test case within the test program. Must be +/// unique. +/// \param md_ Metadata of the test case. +engine::test_case::test_case(const std::string& interface_name_, + const test_program& test_program_, + const std::string& name_, + const metadata& md_) : + _pimpl(new impl(interface_name_, test_program_, name_, md_, none)) +{ +} + + + +/// Constructs a new fake test case. +/// +/// A fake test case is a test case that is not really defined by the test +/// program. Such test cases have a name surrounded by '__' and, when executed, +/// they return a fixed, pre-recorded result. +/// +/// This is necessary for the cases where listing the test cases of a test +/// program fails. In this scenario, we generate a single test case within +/// the test program that unconditionally returns a failure. +/// +/// TODO(jmmv): Need to get rid of this. We should be able to report the +/// status of test programs independently of test cases, as some interfaces +/// don't know about the latter at all. +/// +/// \param interface_name_ Name of the interface implemented by the test +/// program. +/// \param test_program_ The test program this test case belongs to. +/// \param name_ The name to give to this fake test case. This name has to be +/// prefixed and suffixed by '__' to clearly denote that this is internal. +/// \param description_ The description of the test case, if any. +/// \param test_result_ The fake result to return when this test case is run. +engine::test_case::test_case( + const std::string& interface_name_, + const test_program& test_program_, + const std::string& name_, + const std::string& description_, + const engine::test_result& test_result_) : + _pimpl(new impl(interface_name_, test_program_, name_, + metadata_builder().set_description(description_).build(), + utils::make_optional(test_result_))) +{ + PRE_MSG(name_.length() > 4 && name_.substr(0, 2) == "__" && + name_.substr(name_.length() - 2) == "__", + "Invalid fake name provided to fake test case"); +} + + +/// Destroys a test case. +engine::test_case::~test_case(void) +{ +} + + +/// Gets the name of the interface implemented by the test program. +/// +/// \return An interface name. +const std::string& +engine::test_case::interface_name(void) const +{ + return _pimpl->interface_name; +} + + +/// Gets the test program this test case belongs to. +/// +/// \return A reference to the container test program. +const engine::test_program& +engine::test_case::container_test_program(void) const +{ + return _pimpl->_test_program; +} + + +/// Gets the test case name. +/// +/// \return The test case name, relative to the test program. +const std::string& +engine::test_case::name(void) const +{ + return _pimpl->name; +} + + +/// Gets the test case metadata. +/// +/// \return The test case metadata. +const engine::metadata& +engine::test_case::get_metadata(void) const +{ + return _pimpl->md; +} + + +/// Gets the fake result pre-stored for this test case. +/// +/// \return A fake result, or none if not defined. +optional< engine::test_result > +engine::test_case::fake_result(void) const +{ + return _pimpl->fake_result; +} + + +/// Equality comparator. +/// +/// \warning Because test cases reference their container test programs, and +/// test programs include test cases, we cannot perform a full comparison here: +/// otherwise, we'd enter an inifinte loop. Therefore, out of necessity, this +/// does NOT compare whether the container test programs of the affected test +/// cases are the same. +/// +/// \param other The other object to compare this one to. +/// +/// \return True if this object and other are equal; false otherwise. +bool +engine::test_case::operator==(const test_case& other) const +{ + return _pimpl == other._pimpl || *_pimpl == *other._pimpl; +} + + +/// Inequality comparator. +/// +/// \param other The other object to compare this one to. +/// +/// \return True if this object and other are different; false otherwise. +bool +engine::test_case::operator!=(const test_case& other) const +{ + return !(*this == other); +} + + +/// Injects the object into a stream. +/// +/// \param output The stream into which to inject the object. +/// \param object The object to format. +/// +/// \return The output stream. +std::ostream& +engine::operator<<(std::ostream& output, const test_case& object) +{ + // We skip injecting container_test_program() on purpose to avoid a loop. + output << F("test_case{interface=%s, name=%s, metadata=%s}") + % text::quote(object.interface_name(), '\'') + % text::quote(object.name(), '\'') + % object.get_metadata(); + return output; +} + + +/// Runs the test case in debug mode. +/// +/// Debug mode gives the caller more control on the execution of the test. It +/// should not be used for normal execution of tests; instead, call run(). +/// +/// \param test_case The test case to debug. +/// \param user_config The user configuration that defines the execution of this +/// test case. +/// \param hooks Hooks to introspect the execution of the test case. +/// \param work_directory A directory that can be used to place temporary files. +/// \param stdout_path The file to which to redirect the stdout of the test. +/// For interactive debugging, '/dev/stdout' is probably a reasonable value. +/// \param stderr_path The file to which to redirect the stdout of the test. +/// For interactive debugging, '/dev/stderr' is probably a reasonable value. +/// +/// \return The result of the execution of the test case. +engine::test_result +engine::debug_test_case(const test_case* test_case, + const config::tree& user_config, + test_case_hooks& hooks, + const fs::path& work_directory, + const fs::path& stdout_path, + const fs::path& stderr_path) +{ + if (test_case->fake_result()) + return test_case->fake_result().get(); + + const std::string skip_reason = check_reqs( + test_case->get_metadata(), user_config, + test_case->container_test_program().test_suite_name()); + if (!skip_reason.empty()) + return test_result(test_result::skipped, skip_reason); + + if (!fs::exists(test_case->container_test_program().absolute_path())) + return test_result(test_result::broken, "Test program does not exist"); + + const fs::auto_file result_file(work_directory / "result.txt"); + + const engine::test_program& test_program = + test_case->container_test_program(); + + const engine::tester tester = create_tester( + test_program.interface_name(), test_case->get_metadata(), user_config); + tester.test(test_program.absolute_path(), test_case->name(), + result_file.file(), stdout_path, stderr_path, + generate_tester_config(test_case->get_metadata(), user_config, + test_program.test_suite_name())); + + hooks.got_stdout(stdout_path); + hooks.got_stderr(stderr_path); + + std::ifstream result_input(result_file.file().c_str()); + return engine::test_result::parse(result_input); +} + + +/// Runs the test case. +/// +/// \param test_case The test case to run. +/// \param user_config The user configuration that defines the execution of this +/// test case. +/// \param hooks Hooks to introspect the execution of the test case. +/// \param work_directory A directory that can be used to place temporary files. +/// +/// \return The result of the execution of the test case. +engine::test_result +engine::run_test_case(const test_case* test_case, + const config::tree& user_config, + test_case_hooks& hooks, + const fs::path& work_directory) +{ + if (test_case->fake_result()) + return test_case->fake_result().get(); + + const std::string skip_reason = check_reqs( + test_case->get_metadata(), user_config, + test_case->container_test_program().test_suite_name()); + if (!skip_reason.empty()) + return test_result(test_result::skipped, skip_reason); + + if (!fs::exists(test_case->container_test_program().absolute_path())) + return test_result(test_result::broken, "Test program does not exist"); + + const fs::auto_file stdout_file(work_directory / "stdout.txt"); + const fs::auto_file stderr_file(work_directory / "stderr.txt"); + const fs::auto_file result_file(work_directory / "result.txt"); + + const engine::test_program& test_program = + test_case->container_test_program(); + + const engine::tester tester = create_tester( + test_program.interface_name(), test_case->get_metadata(), user_config); + tester.test(test_program.absolute_path(), test_case->name(), + result_file.file(), stdout_file.file(), stderr_file.file(), + generate_tester_config(test_case->get_metadata(), user_config, + test_program.test_suite_name())); + + hooks.got_stdout(stdout_file.file()); + hooks.got_stderr(stderr_file.file()); + + std::ifstream result_input(result_file.file().c_str()); + return engine::test_result::parse(result_input); +} diff --git a/external/bsd/kyua-cli/dist/engine/test_case.hpp b/external/bsd/kyua-cli/dist/engine/test_case.hpp new file mode 100644 index 000000000..12f50437f --- /dev/null +++ b/external/bsd/kyua-cli/dist/engine/test_case.hpp @@ -0,0 +1,112 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file engine/test_case.hpp +/// Interface to interact with test cases. + +#if !defined(ENGINE_TEST_CASE_HPP) +#define ENGINE_TEST_CASE_HPP + +#include +#include +#include + +#include "engine/metadata.hpp" +#include "utils/config/tree.hpp" +#include "utils/fs/path.hpp" +#include "utils/optional.hpp" + +namespace engine { + + +class test_result; +class test_program; + + +/// Hooks to introspect the execution of a test case. +/// +/// There is no guarantee that these hooks will be called during the execution +/// of the test case. There are conditions in which they don't make sense. +/// +/// Note that this class is not abstract. All hooks have default, empty +/// implementations. The purpose of this is to simplify some tests that need to +/// pass hooks but that are not interested in the results. We might want to +/// rethink this and provide an "empty subclass" of a base abstract template. +class test_case_hooks { +public: + virtual ~test_case_hooks(void); + + virtual void got_stdout(const utils::fs::path&); + virtual void got_stderr(const utils::fs::path&); +}; + + +/// Representation of a test case. +class test_case { + struct impl; + + /// Pointer to the shared internal implementation. + std::tr1::shared_ptr< impl > _pimpl; + +public: + test_case(const std::string&, const test_program&, + const std::string&, const metadata&); + test_case(const std::string&, const test_program&, + const std::string&, const std::string&, + const engine::test_result&); + ~test_case(void); + + const std::string& interface_name(void) const; + const test_program& container_test_program(void) const; + const std::string& name(void) const; + const metadata& get_metadata(void) const; + utils::optional< test_result > fake_result(void) const; + + bool operator==(const test_case&) const; + bool operator!=(const test_case&) const; +}; + + +std::ostream& operator<<(std::ostream&, const test_case&); + + +/// Pointer to a test case. +typedef std::tr1::shared_ptr< test_case > test_case_ptr; + + +test_result debug_test_case(const test_case*, const utils::config::tree&, + test_case_hooks&, const utils::fs::path&, + const utils::fs::path&, const utils::fs::path&); +test_result run_test_case(const test_case*, const utils::config::tree&, + test_case_hooks&, const utils::fs::path&); + + +} // namespace engine + + +#endif // !defined(ENGINE_TEST_CASE_HPP) diff --git a/external/bsd/kyua-cli/dist/engine/test_case_atf_helpers.cpp b/external/bsd/kyua-cli/dist/engine/test_case_atf_helpers.cpp new file mode 100644 index 000000000..7f2dfb361 --- /dev/null +++ b/external/bsd/kyua-cli/dist/engine/test_case_atf_helpers.cpp @@ -0,0 +1,273 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +extern "C" { +#include + +#include +#include +} + +#include +#include +#include +#include + +#include + +#include "utils/env.hpp" +#include "utils/fs/operations.hpp" +#include "utils/fs/path.hpp" +#include "utils/optional.ipp" + +namespace fs = utils::fs; + + +namespace { + + +/// Creates an empty file in the given directory. +/// +/// \param test_case The test case currently running. +/// \param directory The name of the configuration variable that holds the path +/// to the directory in which to create the cookie file. +/// \param name The name of the cookie file to create. +static void +create_cookie(const atf::tests::tc* test_case, const char* directory, + const char* name) +{ + if (!test_case->has_config_var(directory)) + test_case->fail(std::string(name) + " not provided"); + + const fs::path control_dir(test_case->get_config_var(directory)); + std::ofstream file((control_dir / name).c_str()); + if (!file) + test_case->fail("Failed to create the control cookie"); + file.close(); +} + + +} // anonymous namespace + + +ATF_TEST_CASE_WITH_CLEANUP(check_cleanup_workdir); +ATF_TEST_CASE_HEAD(check_cleanup_workdir) +{ + set_md_var("require.config", "control_dir"); +} +ATF_TEST_CASE_BODY(check_cleanup_workdir) +{ + std::ofstream cookie("workdir_cookie"); + cookie << "1234\n"; + cookie.close(); + skip("cookie created"); +} +ATF_TEST_CASE_CLEANUP(check_cleanup_workdir) +{ + const fs::path control_dir(get_config_var("control_dir")); + + std::ifstream cookie("workdir_cookie"); + if (!cookie) { + std::ofstream((control_dir / "missing_cookie").c_str()).close(); + std::exit(EXIT_FAILURE); + } + + std::string value; + cookie >> value; + if (value != "1234") { + std::ofstream((control_dir / "invalid_cookie").c_str()).close(); + std::exit(EXIT_FAILURE); + } + + std::ofstream((control_dir / "cookie_ok").c_str()).close(); + std::exit(EXIT_SUCCESS); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(check_unprivileged); +ATF_TEST_CASE_BODY(check_unprivileged) +{ + if (::getuid() == 0) + fail("Running as root, but I shouldn't be"); + + std::ofstream file("cookie"); + if (!file) + fail("Failed to create the cookie; work directory probably owned by " + "root"); + file.close(); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(crash); +ATF_TEST_CASE_BODY(crash) +{ + std::abort(); +} + + +ATF_TEST_CASE_WITH_CLEANUP(crash_cleanup); +ATF_TEST_CASE_HEAD(crash_cleanup) +{ +} +ATF_TEST_CASE_BODY(crash_cleanup) +{ +} +ATF_TEST_CASE_CLEANUP(crash_cleanup) +{ + std::abort(); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(create_cookie_in_control_dir); +ATF_TEST_CASE_BODY(create_cookie_in_control_dir) +{ + create_cookie(this, "control_dir", "cookie"); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(create_cookie_in_workdir); +ATF_TEST_CASE_BODY(create_cookie_in_workdir) +{ + std::ofstream file("cookie"); + if (!file) + fail("Failed to create the cookie"); + file.close(); +} + + +ATF_TEST_CASE_WITH_CLEANUP(create_cookie_from_cleanup); +ATF_TEST_CASE_HEAD(create_cookie_from_cleanup) +{ +} +ATF_TEST_CASE_BODY(create_cookie_from_cleanup) +{ +} +ATF_TEST_CASE_CLEANUP(create_cookie_from_cleanup) +{ + create_cookie(this, "control_dir", "cookie"); +} + + +ATF_TEST_CASE_WITH_CLEANUP(output); +ATF_TEST_CASE_HEAD(output) +{ +} +ATF_TEST_CASE_BODY(output) +{ + std::cout << "Body message to stdout\n"; + std::cerr << "Body message to stderr\n"; +} +ATF_TEST_CASE_CLEANUP(output) +{ + std::cout << "Cleanup message to stdout\n"; + std::cerr << "Cleanup message to stderr\n"; +} + + +ATF_TEST_CASE_WITHOUT_HEAD(pass); +ATF_TEST_CASE_BODY(pass) +{ +} + + +ATF_TEST_CASE(spawn_blocking_child); +ATF_TEST_CASE_HEAD(spawn_blocking_child) +{ + set_md_var("require.config", "control_dir"); +} +ATF_TEST_CASE_BODY(spawn_blocking_child) +{ + pid_t pid = ::fork(); + if (pid == -1) + fail("Cannot fork subprocess"); + else if (pid == 0) { + for (;;) + ::pause(); + } else { + const fs::path name = fs::path(get_config_var("control_dir")) / "pid"; + std::ofstream pidfile(name.c_str()); + ATF_REQUIRE(pidfile); + pidfile << pid; + pidfile.close(); + } +} + + +ATF_TEST_CASE(timeout_body); +ATF_TEST_CASE_HEAD(timeout_body) +{ + if (has_config_var("timeout")) + set_md_var("timeout", get_config_var("timeout")); +} +ATF_TEST_CASE_BODY(timeout_body) +{ + ::sleep(10); + create_cookie(this, "control_dir", "cookie"); +} + + +ATF_TEST_CASE_WITH_CLEANUP(timeout_cleanup); +ATF_TEST_CASE_HEAD(timeout_cleanup) +{ + if (has_config_var("timeout")) + set_md_var("timeout", get_config_var("timeout")); +} +ATF_TEST_CASE_BODY(timeout_cleanup) +{ +} +ATF_TEST_CASE_CLEANUP(timeout_cleanup) +{ + ::sleep(10); + create_cookie(this, "control_dir", "cookie"); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(validate_isolation); +ATF_TEST_CASE_BODY(validate_isolation) +{ + ATF_REQUIRE(utils::getenv("HOME").get() != "fake-value"); + ATF_REQUIRE(!utils::getenv("LANG")); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, check_cleanup_workdir); + ATF_ADD_TEST_CASE(tcs, check_unprivileged); + ATF_ADD_TEST_CASE(tcs, crash); + ATF_ADD_TEST_CASE(tcs, crash_cleanup); + ATF_ADD_TEST_CASE(tcs, create_cookie_in_control_dir); + ATF_ADD_TEST_CASE(tcs, create_cookie_in_workdir); + ATF_ADD_TEST_CASE(tcs, create_cookie_from_cleanup); + ATF_ADD_TEST_CASE(tcs, output); + ATF_ADD_TEST_CASE(tcs, pass); + ATF_ADD_TEST_CASE(tcs, spawn_blocking_child); + ATF_ADD_TEST_CASE(tcs, timeout_body); + ATF_ADD_TEST_CASE(tcs, timeout_cleanup); + ATF_ADD_TEST_CASE(tcs, validate_isolation); +} diff --git a/external/bsd/kyua-cli/dist/engine/test_case_plain_helpers.cpp b/external/bsd/kyua-cli/dist/engine/test_case_plain_helpers.cpp new file mode 100644 index 000000000..037ca8fd9 --- /dev/null +++ b/external/bsd/kyua-cli/dist/engine/test_case_plain_helpers.cpp @@ -0,0 +1,195 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +extern "C" { +#include + +#include +} + +#include +#include +#include +#include + +#include "utils/defs.hpp" +#include "utils/env.hpp" +#include "utils/fs/operations.hpp" +#include "utils/fs/path.hpp" +#include "utils/optional.ipp" + +namespace fs = utils::fs; + +using utils::optional; + + +namespace { + + +/// Logs an error message and exits the test with an error code. +/// +/// \param str The error message to log. +static void +fail(const char* str) +{ + std::cerr << str << '\n'; + std::exit(EXIT_FAILURE); +} + + +/// A test case that crashes. +static void +test_crash(void) +{ + std::abort(); +} + + +/// A test case that exits with a non-zero exit code, and not 1. +static void +test_fail(void) +{ + std::exit(8); +} + + +/// A test case that passes. +static void +test_pass(void) +{ +} + + +/// A test case that spawns a subchild that gets stuck. +/// +/// This test case is used by the caller to validate that the whole process tree +/// is terminated when the test case is killed. +static void +test_spawn_blocking_child(void) +{ + pid_t pid = ::fork(); + if (pid == -1) + fail("Cannot fork subprocess"); + else if (pid == 0) { + for (;;) + ::pause(); + } else { + const fs::path name = fs::path(utils::getenv("CONTROL_DIR").get()) / + "pid"; + std::ofstream pidfile(name.c_str()); + if (!pidfile) + fail("Failed to create the pidfile"); + pidfile << pid; + pidfile.close(); + } +} + + +/// A test case that times out. +/// +/// Note that the timeout is defined in the Kyuafile, as the plain interface has +/// no means for test programs to specify this by themselves. +static void +test_timeout(void) +{ + ::sleep(10); + const fs::path control_dir = fs::path(utils::getenv("CONTROL_DIR").get()); + std::ofstream file((control_dir / "cookie").c_str()); + if (!file) + fail("Failed to create the control cookie"); + file.close(); +} + + +/// A test case that performs basic checks on the runtime environment. +/// +/// If the runtime environment does not look clean (according to the rules in +/// the Kyua runtime properties), the test fails. +static void +test_validate_isolation(void) +{ + if (utils::getenv("HOME").get() == "fake-value") + fail("HOME not reset"); + if (utils::getenv("LANG")) + fail("LANG not unset"); +} + + +} // anonymous namespace + + +/// Entry point to the test program. +/// +/// The caller can select which test case to run by defining the TEST_CASE +/// environment variable. This is not "standard", in the sense this is not a +/// generic property of the plain test case interface. +/// +/// \todo It may be worth to split this binary into separate, smaller binaries, +/// one for every "test case". We use this program as a dispatcher for +/// different "main"s, the only reason being to keep the amount of helper test +/// programs to a minimum. However, putting this each function in its own +/// binary could simplify many other things. +/// +/// \param argc The number of CLI arguments. +/// \param unused_argv The CLI arguments themselves. These are not used because +/// Kyua will not pass any arguments to the plain test program. +int +main(int argc, char** UTILS_UNUSED_PARAM(argv)) +{ + if (argc != 1) { + std::cerr << "No arguments allowed; select the test case with the " + "TEST_CASE variable"; + return EXIT_FAILURE; + } + + const optional< std::string > test_case_env = utils::getenv("TEST_CASE"); + if (!test_case_env) { + std::cerr << "TEST_CASE not defined"; + return EXIT_FAILURE; + } + const std::string& test_case = test_case_env.get(); + + if (test_case == "crash") + test_crash(); + else if (test_case == "fail") + test_fail(); + else if (test_case == "pass") + test_pass(); + else if (test_case == "spawn_blocking_child") + test_spawn_blocking_child(); + else if (test_case == "timeout") + test_timeout(); + else if (test_case == "validate_isolation") + test_validate_isolation(); + else { + std::cerr << "Unknown test case"; + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} diff --git a/external/bsd/kyua-cli/dist/engine/test_case_test.cpp b/external/bsd/kyua-cli/dist/engine/test_case_test.cpp new file mode 100644 index 000000000..300f22867 --- /dev/null +++ b/external/bsd/kyua-cli/dist/engine/test_case_test.cpp @@ -0,0 +1,1104 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "engine/test_case.hpp" + +extern "C" { +#include + +#include +#include +} + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "engine/config.hpp" +#include "engine/exceptions.hpp" +#include "engine/kyuafile.hpp" +#include "engine/test_program.hpp" +#include "engine/test_result.hpp" +#include "utils/config/tree.ipp" +#include "utils/datetime.hpp" +#include "utils/env.hpp" +#include "utils/format/macros.hpp" +#include "utils/fs/operations.hpp" +#include "utils/noncopyable.hpp" +#include "utils/optional.ipp" +#include "utils/passwd.hpp" +#include "utils/process/child.ipp" +#include "utils/sanity.hpp" +#include "utils/stream.hpp" + +namespace config = utils::config; +namespace datetime = utils::datetime; +namespace fs = utils::fs; +namespace passwd = utils::passwd; +namespace process = utils::process; + +using utils::none; +using utils::optional; + + +namespace { + + +/// Test case hooks to capture stdout and stderr in memory. +class capture_hooks : public engine::test_case_hooks { +public: + /// Contents of the stdout of the test case. + std::string stdout_contents; + + /// Contents of the stderr of the test case. + std::string stderr_contents; + + /// Stores the stdout of the test case into stdout_contents. + /// + /// \param file The path to the file containing the stdout. + void + got_stdout(const fs::path& file) + { + atf::utils::cat_file(file.str(), "helper stdout:"); + ATF_REQUIRE(stdout_contents.empty()); + + std::ifstream input(file.c_str()); + ATF_REQUIRE(input); + stdout_contents = utils::read_stream(input); + } + + /// Stores the stderr of the test case into stderr_contents. + /// + /// \param file The path to the file containing the stderr. + void + got_stderr(const fs::path& file) + { + atf::utils::cat_file(file.str(), "helper stderr:"); + ATF_REQUIRE(stderr_contents.empty()); + + std::ifstream input(file.c_str()); + ATF_REQUIRE(input); + stderr_contents = utils::read_stream(input); + } +}; + + +/// Launcher for the helper test cases. +/// +/// This builder class can be used to construct the runtime state of the helper +/// test cases and later run them. The class also provides other helper methods +/// to interact with the helper binary. +class atf_helper : utils::noncopyable { + /// Path to the test program's source directory. + const fs::path _srcdir; + + /// The root of the test suite. + fs::path _root; + + /// Path to the helper test program, relative to _root. + fs::path _binary_path; + + /// Name of the helper test case to run. + const std::string _name; + + /// Metadata of the test case. + engine::metadata_builder _mdbuilder; + + /// Run-time configuration for the test case. + config::tree _user_config; + +public: + /// Constructs a new helper. + /// + /// \param atf_tc A pointer to the calling test case. Needed to obtain + /// run-time configuration variables. + /// \param name The name of the helper to run. + atf_helper(const atf::tests::tc* atf_tc, const char* name) : + _srcdir(atf_tc->get_config_var("srcdir")), + _root(_srcdir), + _binary_path("test_case_atf_helpers"), + _name(name), + _user_config(engine::default_config()) + { + _user_config.set_string("architecture", "mock-architecture"); + _user_config.set_string("platform", "mock-platform"); + } + + /// Provides raw access to the run-time configuration. + /// + /// To override test-suite-specific variables, use set_config() as it + /// abstracts away the name of the fake test suite. + /// + /// \returns A reference to the test case configuration. + config::tree& + config(void) + { + return _user_config; + } + + /// Sets a test-suite-specific configuration variable for the helper. + /// + /// \param variable The name of the environment variable to set. + /// \param value The value of the variable; must be convertible to a string. + template< typename T > + void + set_config(const char* variable, const T& value) + { + _user_config.set_string(F("test_suites.the-suite.%s") % variable, + F("%s") % value); + } + + /// Sets a metadata variable for the helper. + /// + /// \param variable The name of the environment variable to set. + /// \param value The value of the variable; must be convertible to a string. + template< typename T > + void + set_metadata(const char* variable, const T& value) + { + _mdbuilder.set_string(variable, F("%s") % value); + } + + /// Places the helper in a different location. + /// + /// This prepares the helper to be run from a different location than the + /// source directory so that the runtime execution can be validated. + /// + /// \param new_binary_path The new path to the binary, relative to the test + /// suite root. + /// \param new_root The new test suite root. + /// + /// \pre The directory holding the target test program must exist. + /// Otherwise, the relocation of the binary will fail. + void + move(const char* new_binary_path, const char* new_root) + { + _binary_path = fs::path(new_binary_path); + _root = fs::path(new_root); + + const fs::path src_path = fs::path(_srcdir / "test_case_atf_helpers"); + const fs::path new_path = _root / _binary_path; + ATF_REQUIRE( + ::symlink(src_path.c_str(), new_path.c_str()) != -1); + } + + /// Runs the helper. + /// + /// \return The result of the execution. + engine::test_result + run(void) const + { + engine::test_case_hooks dummy_hooks; + return run(dummy_hooks); + } + + /// Runs the helper. + /// + /// \param hooks The hooks to pass to the test case. + /// + /// \return The result of the execution. + engine::test_result + run(engine::test_case_hooks& hooks) const + { + const engine::test_program test_program( + "atf", _binary_path, _root, "the-suite", + engine::metadata_builder().build()); + const engine::test_case test_case("atf", test_program, _name, + _mdbuilder.build()); + + const fs::path workdir("work"); + fs::mkdir(workdir, 0755); + + const engine::test_result result = engine::run_test_case( + &test_case, _user_config, hooks, workdir); + ATF_REQUIRE(::rmdir(workdir.c_str()) != -1); + return result; + } +}; + + +/// Hooks to retrieve stdout and stderr. +class fetch_output_hooks : public engine::test_case_hooks { +public: + /// Copies the stdout of the test case outside of its work directory. + /// + /// \param file The location of the test case's stdout. + void + got_stdout(const fs::path& file) + { + atf::utils::copy_file(file.str(), "helper-stdout.txt"); + atf::utils::cat_file("helper-stdout.txt", "helper stdout: "); + } + + /// Copies the stderr of the test case outside of its work directory. + /// + /// \param file The location of the test case's stderr. + void + got_stderr(const fs::path& file) + { + atf::utils::copy_file(file.str(), "helper-stderr.txt"); + atf::utils::cat_file("helper-stderr.txt", "helper stderr: "); + } +}; + + +/// Simplifies the execution of the helper test cases. +class plain_helper { + /// Path to the test program's source directory. + const fs::path _srcdir; + + /// The root of the test suite. + fs::path _root; + + /// Path to the helper test program, relative to _root. + fs::path _binary_path; + + /// Optional timeout for the test program. + optional< datetime::delta > _timeout; + +public: + /// Constructs a new helper. + /// + /// \param atf_tc A pointer to the calling test case. Needed to obtain + /// run-time configuration variables. + /// \param name The name of the helper to run. + /// \param timeout An optional timeout for the test case. + plain_helper(const atf::tests::tc* atf_tc, const char* name, + const optional< datetime::delta > timeout = none) : + _srcdir(atf_tc->get_config_var("srcdir")), + _root(_srcdir), + _binary_path("test_case_plain_helpers"), + _timeout(timeout) + { + utils::setenv("TEST_CASE", name); + } + + /// Sets an environment variable for the helper. + /// + /// This is simply syntactic sugar for utils::setenv. + /// + /// \param variable The name of the environment variable to set. + /// \param value The value of the variable; must be convertible to a string. + template< typename T > + void + set(const char* variable, const T& value) + { + utils::setenv(variable, F("%s") % value); + } + + /// Places the helper in a different location. + /// + /// This prepares the helper to be run from a different location than the + /// source directory so that the runtime execution can be validated. + /// + /// \param new_binary_path The new path to the binary, relative to the test + /// suite root. + /// \param new_root The new test suite root. + /// + /// \pre The directory holding the target test program must exist. + /// Otherwise, the relocation of the binary will fail. + void + move(const char* new_binary_path, const char* new_root) + { + _binary_path = fs::path(new_binary_path); + _root = fs::path(new_root); + + const fs::path src_path = fs::path(_srcdir) / "test_case_plain_helpers"; + const fs::path new_path = _root / _binary_path; + ATF_REQUIRE( + ::symlink(src_path.c_str(), new_path.c_str()) != -1); + } + + /// Runs the helper. + /// + /// \param user_config The runtime engine configuration, if different to the + /// defaults. + /// + /// \return The result of the execution. + engine::test_result + run(const config::tree& user_config = engine::default_config()) const + { + engine::metadata_builder mdbuilder; + if (_timeout) + mdbuilder.set_timeout(_timeout.get()); + const engine::test_program test_program( + "plain", _binary_path, _root, "unit-tests", mdbuilder.build()); + const engine::test_cases_vector& tcs = test_program.test_cases(); + fetch_output_hooks fetcher; + const engine::test_result result = engine::run_test_case( + tcs[0].get(), user_config, fetcher, fs::path(".")); + std::cerr << "Result is: " << result << '\n'; + return result; + } +}; + + +} // anonymous namespace + + +ATF_TEST_CASE_WITHOUT_HEAD(test_case__ctor_and_getters) +ATF_TEST_CASE_BODY(test_case__ctor_and_getters) +{ + const engine::metadata md = engine::metadata_builder() + .add_custom("first", "value") + .build(); + const engine::test_program test_program( + "mock", fs::path("abc"), fs::path("unused-root"), + "unused-suite-name", engine::metadata_builder().build()); + const engine::test_case test_case("mock", test_program, "foo", md); + ATF_REQUIRE_EQ(&test_program, &test_case.container_test_program()); + ATF_REQUIRE_EQ("foo", test_case.name()); + ATF_REQUIRE(md == test_case.get_metadata()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(test_case__fake_result) +ATF_TEST_CASE_BODY(test_case__fake_result) +{ + const engine::test_result result(engine::test_result::skipped, + "Some reason"); + const engine::test_program test_program( + "mock", fs::path("abc"), fs::path("unused-root"), + "unused-suite-name", engine::metadata_builder().build()); + const engine::test_case test_case("mock", test_program, "__foo__", + "Some description", result); + ATF_REQUIRE_EQ(&test_program, &test_case.container_test_program()); + ATF_REQUIRE_EQ("__foo__", test_case.name()); + ATF_REQUIRE(result == test_case.fake_result().get()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(test_case__operators_eq_and_ne__copy); +ATF_TEST_CASE_BODY(test_case__operators_eq_and_ne__copy) +{ + const engine::test_program tp( + "plain", fs::path("non-existent"), fs::path("."), "suite-name", + engine::metadata_builder().build()); + + const engine::test_case tc1("plain", tp, "name", + engine::metadata_builder().build()); + const engine::test_case tc2 = tc1; + ATF_REQUIRE( tc1 == tc2); + ATF_REQUIRE(!(tc1 != tc2)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(test_case__output); +ATF_TEST_CASE_BODY(test_case__output) +{ + const engine::test_program tp( + "plain", fs::path("non-existent"), fs::path("."), "suite-name", + engine::metadata_builder().build()); + + const engine::test_case tc1( + "plain", tp, "the-name", engine::metadata_builder() + .add_allowed_platform("foo").add_custom("X-bar", "baz").build()); + std::ostringstream str; + str << tc1; + ATF_REQUIRE_EQ( + "test_case{interface='plain', name='the-name', " + "metadata=metadata{allowed_architectures='', allowed_platforms='foo', " + "custom.X-bar='baz', description='', has_cleanup='false', " + "required_configs='', required_files='', required_memory='0', " + "required_programs='', required_user='', timeout='300'}}", + str.str()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(test_case__operators_eq_and_ne__not_copy); +ATF_TEST_CASE_BODY(test_case__operators_eq_and_ne__not_copy) +{ + const std::string base_interface("plain"); + const engine::test_program base_tp( + "plain", fs::path("non-existent"), fs::path("."), "suite-name", + engine::metadata_builder().build()); + const std::string base_name("name"); + const engine::metadata base_metadata = engine::metadata_builder() + .add_custom("X-foo", "bar") + .build(); + + const engine::test_case base_tc(base_interface, base_tp, base_name, + base_metadata); + + // Construct with all same values. + { + const engine::test_case other_tc(base_interface, base_tp, base_name, + base_metadata); + + ATF_REQUIRE( base_tc == other_tc); + ATF_REQUIRE(!(base_tc != other_tc)); + } + + // Different interface. + { + const engine::test_case other_tc("atf", base_tp, base_name, + base_metadata); + + ATF_REQUIRE(!(base_tc == other_tc)); + ATF_REQUIRE( base_tc != other_tc); + } + + // Different test program, different identifier. + { + const engine::test_program other_tp( + "plain", fs::path("another-name"), fs::path("."), "suite2-name", + engine::metadata_builder().build()); + const engine::test_case other_tc(base_interface, other_tp, base_name, + base_metadata); + + ATF_REQUIRE(!(base_tc == other_tc)); + ATF_REQUIRE( base_tc != other_tc); + } + + // Different test program, same identifier. Cannot be detected! + { + const engine::test_program other_tp( + "plain", fs::path("non-existent"), fs::path("."), "suite2-name", + engine::metadata_builder().build()); + const engine::test_case other_tc(base_interface, other_tp, base_name, + base_metadata); + + ATF_REQUIRE( base_tc == other_tc); + ATF_REQUIRE(!(base_tc != other_tc)); + } + + // Different name. + { + const engine::test_case other_tc(base_interface, base_tp, "other", + base_metadata); + + ATF_REQUIRE(!(base_tc == other_tc)); + ATF_REQUIRE( base_tc != other_tc); + } + + // Different metadata. + { + const engine::test_case other_tc(base_interface, base_tp, base_name, + engine::metadata_builder().build()); + + ATF_REQUIRE(!(base_tc == other_tc)); + ATF_REQUIRE( base_tc != other_tc); + } +} + + +ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__atf__current_directory); +ATF_TEST_CASE_BODY(run_test_case__atf__current_directory) +{ + atf_helper helper(this, "pass"); + helper.move("program", "."); + ATF_REQUIRE_EQ(engine::test_result(engine::test_result::passed), + helper.run()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__atf__subdirectory); +ATF_TEST_CASE_BODY(run_test_case__atf__subdirectory) +{ + atf_helper helper(this, "pass"); + ATF_REQUIRE(::mkdir("dir1", 0755) != -1); + ATF_REQUIRE(::mkdir("dir1/dir2", 0755) != -1); + helper.move("dir2/program", "dir1"); + ATF_REQUIRE_EQ(engine::test_result(engine::test_result::passed), + helper.run()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__atf__config_variables); +ATF_TEST_CASE_BODY(run_test_case__atf__config_variables) +{ + atf_helper helper(this, "create_cookie_in_control_dir"); + helper.set_config("control_dir", fs::current_path()); + ATF_REQUIRE_EQ(engine::test_result(engine::test_result::passed), + helper.run()); + + if (!fs::exists(fs::path("cookie"))) + fail("The cookie was not created where we expected; the test program " + "probably received an invalid configuration variable"); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__atf__cleanup_shares_workdir); +ATF_TEST_CASE_BODY(run_test_case__atf__cleanup_shares_workdir) +{ + atf_helper helper(this, "check_cleanup_workdir"); + helper.set_metadata("has_cleanup", "true"); + helper.set_config("control_dir", fs::current_path()); + ATF_REQUIRE_EQ(engine::test_result(engine::test_result::skipped, + "cookie created"), helper.run()); + + if (fs::exists(fs::path("missing_cookie"))) + fail("The cleanup part did not see the cookie; the work directory " + "is probably not shared"); + if (fs::exists(fs::path("invalid_cookie"))) + fail("The cleanup part read an invalid cookie"); + if (!fs::exists(fs::path("cookie_ok"))) + fail("The cleanup part was not executed"); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__atf__has_cleanup__atf__false); +ATF_TEST_CASE_BODY(run_test_case__atf__has_cleanup__atf__false) +{ + atf_helper helper(this, "create_cookie_from_cleanup"); + helper.set_metadata("has_cleanup", "false"); + helper.set_config("control_dir", fs::current_path()); + ATF_REQUIRE_EQ(engine::test_result(engine::test_result::passed), + helper.run()); + + if (fs::exists(fs::path("cookie"))) + fail("The cleanup part was executed even though the test case set " + "has.cleanup to false"); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__atf__has_cleanup__atf__true); +ATF_TEST_CASE_BODY(run_test_case__atf__has_cleanup__atf__true) +{ + atf_helper helper(this, "create_cookie_from_cleanup"); + helper.set_metadata("has_cleanup", "true"); + helper.set_config("control_dir", fs::current_path()); + ATF_REQUIRE_EQ(engine::test_result(engine::test_result::passed), + helper.run()); + + if (!fs::exists(fs::path("cookie"))) + fail("The cleanup part was not executed even though the test case set " + "has.cleanup to true"); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__atf__kill_children); +ATF_TEST_CASE_BODY(run_test_case__atf__kill_children) +{ + atf_helper helper(this, "spawn_blocking_child"); + helper.set_config("control_dir", fs::current_path()); + ATF_REQUIRE_EQ(engine::test_result(engine::test_result::passed), + helper.run()); + + if (!fs::exists(fs::path("pid"))) + fail("The pid file was not created"); + std::ifstream pidfile("pid"); + ATF_REQUIRE(pidfile); + pid_t pid; + pidfile >> pid; + pidfile.close(); + + int attempts = 30; +retry: + if (::kill(pid, SIGCONT) != -1 || errno != ESRCH) { + // Looks like the subchild did not die. + // + // Note that this might be inaccurate for two reasons: + // 1) The system may have spawned a new process with the same pid as + // our subchild... but in practice, this does not happen because + // most systems do not immediately reuse pid numbers. If that + // happens... well, we get a false test failure. + // 2) We ran so fast that even if the process was sent a signal to + // die, it has not had enough time to process it yet. This is why + // we retry this a few times. + if (attempts > 0) { + std::cout << "Subprocess not dead yet; retrying wait\n"; + --attempts; + ::usleep(100000); + goto retry; + } + fail(F("The subprocess %s of our child was not killed") % pid); + } +} + + +ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__atf__isolation); +ATF_TEST_CASE_BODY(run_test_case__atf__isolation) +{ + atf_helper helper(this, "validate_isolation"); + // Simple checks to make sure that the test case has been isolated. + utils::setenv("HOME", "fake-value"); + utils::setenv("LANG", "C"); + ATF_REQUIRE_EQ(engine::test_result(engine::test_result::passed), + helper.run()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__atf__allowed_architectures); +ATF_TEST_CASE_BODY(run_test_case__atf__allowed_architectures) +{ + atf_helper helper(this, "create_cookie_in_control_dir"); + helper.set_metadata("allowed_architectures", "i386 x86_64"); + helper.config().set_string("architecture", "powerpc"); + helper.config().set_string("platform", ""); + ATF_REQUIRE_EQ(engine::test_result(engine::test_result::skipped, "Current " + "architecture 'powerpc' not supported"), + helper.run()); + + if (fs::exists(fs::path("cookie"))) + fail("The test case was not really skipped when the requirements " + "check failed"); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__atf__allowed_platforms); +ATF_TEST_CASE_BODY(run_test_case__atf__allowed_platforms) +{ + atf_helper helper(this, "create_cookie_in_control_dir"); + helper.set_metadata("allowed_platforms", "i386 amd64"); + helper.config().set_string("architecture", ""); + helper.config().set_string("platform", "macppc"); + ATF_REQUIRE_EQ(engine::test_result(engine::test_result::skipped, "Current " + "platform 'macppc' not supported"), + helper.run()); + + if (fs::exists(fs::path("cookie"))) + fail("The test case was not really skipped when the requirements " + "check failed"); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__atf__required_configs); +ATF_TEST_CASE_BODY(run_test_case__atf__required_configs) +{ + atf_helper helper(this, "create_cookie_in_control_dir"); + helper.set_metadata("required_configs", "used-var"); + helper.set_config("control_dir", fs::current_path()); + helper.set_config("unused-var", "value"); + ATF_REQUIRE_EQ(engine::test_result(engine::test_result::skipped, "Required " + "configuration property 'used-var' not " + "defined"), + helper.run()); + + if (fs::exists(fs::path("cookie"))) + fail("The test case was not really skipped when the requirements " + "check failed"); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__atf__required_programs); +ATF_TEST_CASE_BODY(run_test_case__atf__required_programs) +{ + atf_helper helper(this, "create_cookie_in_control_dir"); + helper.set_metadata("required_programs", "/non-existent/program"); + ATF_REQUIRE_EQ(engine::test_result(engine::test_result::skipped, "Required " + "program '/non-existent/program' not " + "found"), + helper.run()); + + if (fs::exists(fs::path("cookie"))) + fail("The test case was not really skipped when the requirements " + "check failed"); +} + + +ATF_TEST_CASE(run_test_case__atf__required_user__atf__root__atf__ok); +ATF_TEST_CASE_HEAD(run_test_case__atf__required_user__atf__root__atf__ok) +{ + set_md_var("require.user", "root"); +} +ATF_TEST_CASE_BODY(run_test_case__atf__required_user__atf__root__atf__ok) +{ + atf_helper helper(this, "create_cookie_in_workdir"); + helper.set_metadata("required_user", "root"); + ATF_REQUIRE(passwd::current_user().is_root()); + ATF_REQUIRE_EQ(engine::test_result(engine::test_result::passed), + helper.run()); +} + + +ATF_TEST_CASE(run_test_case__atf__required_user__atf__root__atf__skip); +ATF_TEST_CASE_HEAD(run_test_case__atf__required_user__atf__root__atf__skip) +{ + set_md_var("require.user", "unprivileged"); +} +ATF_TEST_CASE_BODY(run_test_case__atf__required_user__atf__root__atf__skip) +{ + atf_helper helper(this, "create_cookie_in_workdir"); + helper.set_metadata("required_user", "root"); + ATF_REQUIRE(!passwd::current_user().is_root()); + ATF_REQUIRE_EQ(engine::test_result(engine::test_result::skipped, "Requires " + "root privileges"), + helper.run()); +} + + +ATF_TEST_CASE(run_test_case__atf__required_user__atf__unprivileged__atf__ok); +ATF_TEST_CASE_HEAD(run_test_case__atf__required_user__atf__unprivileged__atf__ok) +{ + set_md_var("require.user", "unprivileged"); +} +ATF_TEST_CASE_BODY(run_test_case__atf__required_user__atf__unprivileged__atf__ok) +{ + atf_helper helper(this, "create_cookie_in_workdir"); + helper.set_metadata("required_user", "unprivileged"); + ATF_REQUIRE(!helper.config().is_set("unprivileged_user")); + ATF_REQUIRE_EQ(engine::test_result(engine::test_result::passed), + helper.run()); +} + + +ATF_TEST_CASE(run_test_case__atf__required_user__atf__unprivileged__atf__skip); +ATF_TEST_CASE_HEAD(run_test_case__atf__required_user__atf__unprivileged__atf__skip) +{ + set_md_var("require.user", "root"); +} +ATF_TEST_CASE_BODY(run_test_case__atf__required_user__atf__unprivileged__atf__skip) +{ + atf_helper helper(this, "create_cookie_in_workdir"); + helper.set_metadata("required_user", "unprivileged"); + ATF_REQUIRE(!helper.config().is_set("unprivileged_user")); + ATF_REQUIRE_EQ(engine::test_result(engine::test_result::skipped, "Requires " + "an unprivileged user but the " + "unprivileged-user configuration " + "variable is not defined"), + helper.run()); +} + + +ATF_TEST_CASE(run_test_case__atf__required_user__atf__unprivileged__atf__drop); +ATF_TEST_CASE_HEAD(run_test_case__atf__required_user__atf__unprivileged__atf__drop) +{ + set_md_var("require.config", "unprivileged-user"); + set_md_var("require.user", "root"); +} +ATF_TEST_CASE_BODY(run_test_case__atf__required_user__atf__unprivileged__atf__drop) +{ + atf_helper helper(this, "check_unprivileged"); + helper.set_metadata("required_user", "unprivileged"); + helper.config().set< engine::user_node >( + "unprivileged_user", + passwd::find_user_by_name(get_config_var("unprivileged-user"))); + ATF_REQUIRE_EQ(engine::test_result(engine::test_result::passed), + helper.run()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__atf__timeout_body); +ATF_TEST_CASE_BODY(run_test_case__atf__timeout_body) +{ + atf_helper helper(this, "timeout_body"); + helper.set_metadata("timeout", "1"); + helper.set_config("control_dir", fs::current_path()); + ATF_REQUIRE_EQ(engine::test_result(engine::test_result::broken, + "Test case body timed out"), + helper.run()); + + if (fs::exists(fs::path("cookie"))) + fail("It seems that the test case was not killed after it timed out"); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__atf__timeout_cleanup); +ATF_TEST_CASE_BODY(run_test_case__atf__timeout_cleanup) +{ + atf_helper helper(this, "timeout_cleanup"); + helper.set_metadata("has_cleanup", "true"); + helper.set_metadata("timeout", "1"); + helper.set_config("control_dir", fs::current_path()); + ATF_REQUIRE_EQ(engine::test_result(engine::test_result::broken, + "Test case cleanup timed out"), + helper.run()); + + if (fs::exists(fs::path("cookie"))) + fail("It seems that the test case was not killed after it timed out"); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__atf__stacktrace__atf__body); +ATF_TEST_CASE_BODY(run_test_case__atf__stacktrace__atf__body) +{ + atf_helper helper(this, "crash"); + capture_hooks hooks; + const engine::test_result result = helper.run(hooks); + ATF_REQUIRE(engine::test_result::broken == result.type()); + ATF_REQUIRE_MATCH("received signal.*core dumped", result.reason()); + + ATF_REQUIRE(!atf::utils::grep_string("attempting to gather stack trace", + hooks.stdout_contents)); + ATF_REQUIRE( atf::utils::grep_string("attempting to gather stack trace", + hooks.stderr_contents)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__atf__stacktrace__atf__cleanup); +ATF_TEST_CASE_BODY(run_test_case__atf__stacktrace__atf__cleanup) +{ + atf_helper helper(this, "crash_cleanup"); + helper.set_metadata("has_cleanup", "true"); + capture_hooks hooks; + const engine::test_result result = helper.run(hooks); + ATF_REQUIRE(engine::test_result::broken == result.type()); + ATF_REQUIRE_MATCH(F("cleanup received signal %s") % SIGABRT, + result.reason()); + + ATF_REQUIRE(!atf::utils::grep_string("attempting to gather stack trace", + hooks.stdout_contents)); + ATF_REQUIRE( atf::utils::grep_string("attempting to gather stack trace", + hooks.stderr_contents)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__atf__missing_results_file); +ATF_TEST_CASE_BODY(run_test_case__atf__missing_results_file) +{ + atf_helper helper(this, "crash"); + const engine::test_result result = helper.run(); + ATF_REQUIRE(engine::test_result::broken == result.type()); + // Need to match instead of doing an explicit comparison because the string + // may include the "core dumped" substring. + ATF_REQUIRE_MATCH(F("test case received signal %s") % SIGABRT, + result.reason()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__atf__missing_test_program); +ATF_TEST_CASE_BODY(run_test_case__atf__missing_test_program) +{ + atf_helper helper(this, "crash"); + ATF_REQUIRE(::mkdir("dir", 0755) != -1); + helper.move("test_case_atf_helpers", "dir"); + ATF_REQUIRE(::unlink("dir/test_case_atf_helpers") != -1); + const engine::test_result result = helper.run(); + ATF_REQUIRE(engine::test_result::broken == result.type()); + ATF_REQUIRE_MATCH("Test program does not exist", result.reason()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__atf__output); +ATF_TEST_CASE_BODY(run_test_case__atf__output) +{ + atf_helper helper(this, "output"); + helper.set_metadata("has_cleanup", "true"); + + capture_hooks hooks; + ATF_REQUIRE_EQ(engine::test_result(engine::test_result::passed), + helper.run(hooks)); + + ATF_REQUIRE_EQ("Body message to stdout\nCleanup message to stdout\n", + hooks.stdout_contents); + ATF_REQUIRE_EQ("Body message to stderr\nCleanup message to stderr\n", + hooks.stderr_contents); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__plain__result_pass); +ATF_TEST_CASE_BODY(run_test_case__plain__result_pass) +{ + ATF_REQUIRE_EQ(engine::test_result(engine::test_result::passed), + plain_helper(this, "pass").run()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__plain__result_fail); +ATF_TEST_CASE_BODY(run_test_case__plain__result_fail) +{ + ATF_REQUIRE_EQ(engine::test_result(engine::test_result::failed, + "Returned non-success exit status 8"), + plain_helper(this, "fail").run()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__plain__result_crash); +ATF_TEST_CASE_BODY(run_test_case__plain__result_crash) +{ + const engine::test_result result = plain_helper(this, "crash").run(); + ATF_REQUIRE(engine::test_result::broken == result.type()); + ATF_REQUIRE_MATCH(F("Received signal %s") % SIGABRT, result.reason()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__plain__current_directory); +ATF_TEST_CASE_BODY(run_test_case__plain__current_directory) +{ + plain_helper helper(this, "pass"); + helper.move("program", "."); + ATF_REQUIRE_EQ(engine::test_result(engine::test_result::passed), + helper.run()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__plain__subdirectory); +ATF_TEST_CASE_BODY(run_test_case__plain__subdirectory) +{ + plain_helper helper(this, "pass"); + ATF_REQUIRE(::mkdir("dir1", 0755) != -1); + ATF_REQUIRE(::mkdir("dir1/dir2", 0755) != -1); + helper.move("dir2/program", "dir1"); + ATF_REQUIRE_EQ(engine::test_result(engine::test_result::passed), + helper.run()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__plain__kill_children); +ATF_TEST_CASE_BODY(run_test_case__plain__kill_children) +{ + plain_helper helper(this, "spawn_blocking_child"); + helper.set("CONTROL_DIR", fs::current_path()); + ATF_REQUIRE_EQ(engine::test_result(engine::test_result::passed), + helper.run()); + + if (!fs::exists(fs::path("pid"))) + fail("The pid file was not created"); + std::ifstream pidfile("pid"); + ATF_REQUIRE(pidfile); + pid_t pid; + pidfile >> pid; + pidfile.close(); + + int attempts = 30; +retry: + if (::kill(pid, SIGCONT) != -1 || errno != ESRCH) { + // Looks like the subchild did not die. + // + // Note that this might be inaccurate for two reasons: + // 1) The system may have spawned a new process with the same pid as + // our subchild... but in practice, this does not happen because + // most systems do not immediately reuse pid numbers. If that + // happens... well, we get a false test failure. + // 2) We ran so fast that even if the process was sent a signal to + // die, it has not had enough time to process it yet. This is why + // we retry this a few times. + if (attempts > 0) { + std::cout << "Subprocess not dead yet; retrying wait\n"; + --attempts; + ::usleep(100000); + goto retry; + } + fail(F("The subprocess %s of our child was not killed") % pid); + } +} + + +ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__plain__isolation); +ATF_TEST_CASE_BODY(run_test_case__plain__isolation) +{ + const plain_helper helper(this, "validate_isolation"); + utils::setenv("TEST_CASE", "validate_isolation"); + // Simple checks to make sure that the test case has been isolated. + utils::setenv("HOME", "fake-value"); + utils::setenv("LANG", "C"); + ATF_REQUIRE_EQ(engine::test_result(engine::test_result::passed), + helper.run()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__plain__timeout); +ATF_TEST_CASE_BODY(run_test_case__plain__timeout) +{ + plain_helper helper(this, "timeout", + utils::make_optional(datetime::delta(1, 0))); + helper.set("CONTROL_DIR", fs::current_path()); + ATF_REQUIRE_EQ(engine::test_result(engine::test_result::broken, + "Test case timed out"), + helper.run()); + + if (fs::exists(fs::path("cookie"))) + fail("It seems that the test case was not killed after it timed out"); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__plain__stacktrace); +ATF_TEST_CASE_BODY(run_test_case__plain__stacktrace) +{ + plain_helper helper(this, "crash"); + helper.set("CONTROL_DIR", fs::current_path()); + + const engine::test_result result = plain_helper(this, "crash").run(); + ATF_REQUIRE(engine::test_result::broken == result.type()); + ATF_REQUIRE_MATCH(F("Received signal %s") % SIGABRT, result.reason()); + + ATF_REQUIRE(!atf::utils::grep_file("attempting to gather stack trace", + "helper-stdout.txt")); + ATF_REQUIRE( atf::utils::grep_file("attempting to gather stack trace", + "helper-stderr.txt")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(run_test_case__plain__missing_test_program); +ATF_TEST_CASE_BODY(run_test_case__plain__missing_test_program) +{ + plain_helper helper(this, "pass"); + ATF_REQUIRE(::mkdir("dir", 0755) != -1); + helper.move("test_case_helpers", "dir"); + ATF_REQUIRE(::unlink("dir/test_case_helpers") != -1); + const engine::test_result result = helper.run(); + ATF_REQUIRE(engine::test_result::broken == result.type()); + ATF_REQUIRE_MATCH("Test program does not exist", result.reason()); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, test_case__ctor_and_getters); + ATF_ADD_TEST_CASE(tcs, test_case__fake_result); + + ATF_ADD_TEST_CASE(tcs, test_case__operators_eq_and_ne__copy); + ATF_ADD_TEST_CASE(tcs, test_case__operators_eq_and_ne__not_copy); + + ATF_ADD_TEST_CASE(tcs, test_case__output); + + ATF_ADD_TEST_CASE(tcs, run_test_case__atf__current_directory); + ATF_ADD_TEST_CASE(tcs, run_test_case__atf__subdirectory); + ATF_ADD_TEST_CASE(tcs, run_test_case__atf__config_variables); + ATF_ADD_TEST_CASE(tcs, run_test_case__atf__cleanup_shares_workdir); + ATF_ADD_TEST_CASE(tcs, run_test_case__atf__has_cleanup__atf__false); + ATF_ADD_TEST_CASE(tcs, run_test_case__atf__has_cleanup__atf__true); + ATF_ADD_TEST_CASE(tcs, run_test_case__atf__kill_children); + ATF_ADD_TEST_CASE(tcs, run_test_case__atf__isolation); + ATF_ADD_TEST_CASE(tcs, run_test_case__atf__allowed_architectures); + ATF_ADD_TEST_CASE(tcs, run_test_case__atf__allowed_platforms); + ATF_ADD_TEST_CASE(tcs, run_test_case__atf__required_configs); + ATF_ADD_TEST_CASE(tcs, run_test_case__atf__required_programs); + ATF_ADD_TEST_CASE(tcs, run_test_case__atf__required_user__atf__root__atf__ok); + ATF_ADD_TEST_CASE(tcs, run_test_case__atf__required_user__atf__root__atf__skip); + ATF_ADD_TEST_CASE(tcs, run_test_case__atf__required_user__atf__unprivileged__atf__ok); + ATF_ADD_TEST_CASE(tcs, run_test_case__atf__required_user__atf__unprivileged__atf__skip); + ATF_ADD_TEST_CASE(tcs, run_test_case__atf__required_user__atf__unprivileged__atf__drop); + ATF_ADD_TEST_CASE(tcs, run_test_case__atf__timeout_body); + ATF_ADD_TEST_CASE(tcs, run_test_case__atf__timeout_cleanup); + ATF_ADD_TEST_CASE(tcs, run_test_case__atf__stacktrace__atf__body); + ATF_ADD_TEST_CASE(tcs, run_test_case__atf__stacktrace__atf__cleanup); + ATF_ADD_TEST_CASE(tcs, run_test_case__atf__missing_results_file); + ATF_ADD_TEST_CASE(tcs, run_test_case__atf__missing_test_program); + ATF_ADD_TEST_CASE(tcs, run_test_case__atf__output); + + ATF_ADD_TEST_CASE(tcs, run_test_case__plain__result_pass); + ATF_ADD_TEST_CASE(tcs, run_test_case__plain__result_fail); + ATF_ADD_TEST_CASE(tcs, run_test_case__plain__result_crash); + ATF_ADD_TEST_CASE(tcs, run_test_case__plain__current_directory); + ATF_ADD_TEST_CASE(tcs, run_test_case__plain__subdirectory); + ATF_ADD_TEST_CASE(tcs, run_test_case__plain__kill_children); + ATF_ADD_TEST_CASE(tcs, run_test_case__plain__isolation); + ATF_ADD_TEST_CASE(tcs, run_test_case__plain__timeout); + ATF_ADD_TEST_CASE(tcs, run_test_case__plain__stacktrace); + ATF_ADD_TEST_CASE(tcs, run_test_case__plain__missing_test_program); + + // TODO(jmmv): Add test cases for debug. +} diff --git a/external/bsd/kyua-cli/dist/engine/test_program.cpp b/external/bsd/kyua-cli/dist/engine/test_program.cpp new file mode 100644 index 000000000..9cec29e9d --- /dev/null +++ b/external/bsd/kyua-cli/dist/engine/test_program.cpp @@ -0,0 +1,486 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "engine/test_program.hpp" + +#include +#include +#include +#include + +#include +#include + +#include "engine/exceptions.hpp" +#include "engine/test_result.hpp" +#include "engine/testers.hpp" +#include "utils/format/macros.hpp" +#include "utils/logging/macros.hpp" +#include "utils/logging/operations.hpp" +#include "utils/optional.ipp" +#include "utils/sanity.hpp" +#include "utils/text/operations.ipp" + +namespace fs = utils::fs; +namespace logging = utils::logging; +namespace text = utils::text; + +using utils::none; +using utils::optional; + + +namespace { + + +/// Lua hook for the test_case function. +/// +/// \pre state(-1) contains the arguments to the function. +/// +/// \param state The Lua state in which we are running. +/// +/// \return The number of return values, which is always 0. +static int +lua_test_case(lutok::state& state) +{ + if (!state.is_table()) + throw std::runtime_error("Oh noes"); // XXX + + state.get_global("_test_cases"); + engine::test_cases_vector* test_cases = + *state.to_userdata< engine::test_cases_vector* >(); + state.pop(1); + + state.get_global("_test_program"); + const engine::test_program* test_program = + *state.to_userdata< engine::test_program* >(); + state.pop(1); + + state.push_string("name"); + state.get_table(-2); + const std::string name = state.to_string(); + state.pop(1); + + engine::metadata_builder mdbuilder(test_program->get_metadata()); + + state.push_nil(); + while (state.next(-2)) { + if (!state.is_string(-2)) + throw std::runtime_error("Oh oh"); // XXX + const std::string property = state.to_string(-2); + + if (!state.is_string(-1)) + throw std::runtime_error("Oh oh"); // XXX + const std::string value = state.to_string(-1); + + if (property != "name") + mdbuilder.set_string(property, value); + + state.pop(1); + } + state.pop(1); + + engine::test_case_ptr test_case( + new engine::test_case(test_program->interface_name(), *test_program, + name, mdbuilder.build())); + test_cases->push_back(test_case); + + return 0; +} + + +/// Sets up the Lua state to process the output of a test case list. +/// +/// \param [in,out] state The Lua state to configure. +/// \param test_program Pointer to the test program being loaded. +/// \param [out] test_cases Vector that will contain the list of test cases. +static void +setup_lua_state(lutok::state& state, const engine::test_program* test_program, + engine::test_cases_vector* test_cases) +{ + *state.new_userdata< engine::test_cases_vector* >() = test_cases; + state.set_global("_test_cases"); + + *state.new_userdata< const engine::test_program* >() = test_program; + state.set_global("_test_program"); + + state.push_cxx_function(lua_test_case); + state.set_global("test_case"); +} + + +/// Loads the list of test cases from a test program. +/// +/// \param test_program Representation of the test program to load. +/// +/// \return A list of test cases. +static engine::test_cases_vector +load_test_cases(const engine::test_program& test_program) +{ + const engine::tester tester(test_program.interface_name(), none, none); + const std::string output = tester.list(test_program.absolute_path()); + + engine::test_cases_vector test_cases; + lutok::state state; + setup_lua_state(state, &test_program, &test_cases); + lutok::do_string(state, output, 0); + return test_cases; +} + + +/// Predicate to compare two test cases via pointers to them. +/// +/// \param tc1 Entry in a map of test case names to test case pointers. +/// \param tc2 Entry in a map of test case names to test case pointers. +/// +/// \return True if the test case in tc1 is the same as in tc2. Note that the +/// container test programs are NOT compared. +static bool +compare_test_case(const std::pair< std::string, engine::test_case_ptr >& tc1, + const std::pair< std::string, engine::test_case_ptr >& tc2) +{ + return tc1.first == tc2.first && *tc1.second == *tc2.second; +} + + +/// Compares if two sets of test cases hold the same values. +/// +/// \param tests1 First collection of test cases. +/// \param tests2 Second collection of test cases. +/// +/// \return True if both collections hold the same test cases (value-wise, not +/// pointer-wise); false otherwise. +static bool +compare_test_cases(const optional< engine::test_cases_vector >& tests1, + const optional< engine::test_cases_vector >& tests2) +{ + if (!tests1 && !tests2) + return true; + else if ((tests1 && !tests2) || (!tests1 && tests2)) + return false; + INV(tests1 && tests2); + + // This is very inefficient, but because it should only be used in our own + // tests, it doesn't matter. + std::map< std::string, engine::test_case_ptr > map1, map2; + for (engine::test_cases_vector::const_iterator iter = tests1.get().begin(); + iter != tests1.get().end(); ++iter) + map1.insert(make_pair((*iter)->name(), *iter)); + for (engine::test_cases_vector::const_iterator iter = tests2.get().begin(); + iter != tests2.get().end(); ++iter) + map2.insert(make_pair((*iter)->name(), *iter)); + return std::equal(map1.begin(), map1.end(), map2.begin(), + compare_test_case); +} + + +} // anonymous namespace + + +/// Internal implementation of a test_program. +struct engine::test_program::impl { + /// Name of the test program interface. + std::string interface_name; + + /// Name of the test program binary relative to root. + fs::path binary; + + /// Root of the test suite containing the test program. + fs::path root; + + /// Name of the test suite this program belongs to. + std::string test_suite_name; + + /// Metadata of the test program. + metadata md; + + /// List of test cases in the test program; lazily initialized. + optional< test_cases_vector > test_cases; + + /// Constructor. + /// + /// \param interface_name_ Name of the test program interface. + /// \param binary_ The name of the test program binary relative to root_. + /// \param root_ The root of the test suite containing the test program. + /// \param test_suite_name_ The name of the test suite this program + /// belongs to. + /// \param md_ Metadata of the test program. + impl(const std::string& interface_name_, const fs::path& binary_, + const fs::path& root_, const std::string& test_suite_name_, + const metadata& md_) : + interface_name(interface_name_), + binary(binary_), + root(root_), + test_suite_name(test_suite_name_), + md(md_) + { + PRE_MSG(!binary.is_absolute(), + F("The program '%s' must be relative to the root of the test " + "suite '%s'") % binary % root); + } + + /// Equality comparator. + /// + /// \param other The other object to compare this one to. + /// + /// \return True if this object and other are equal; false otherwise. + bool + operator==(const impl& other) const + { + return (interface_name == other.interface_name && + binary == other.binary && + root == other.root && + test_suite_name == other.test_suite_name && + md == other.md && + compare_test_cases(test_cases, other.test_cases)); + } +}; + + +/// Constructs a new test program. +/// +/// \param interface_name_ Name of the test program interface. +/// \param binary_ The name of the test program binary relative to root_. +/// \param root_ The root of the test suite containing the test program. +/// \param test_suite_name_ The name of the test suite this program belongs to. +/// \param md_ Metadata of the test program. +engine::test_program::test_program(const std::string& interface_name_, + const fs::path& binary_, + const fs::path& root_, + const std::string& test_suite_name_, + const metadata& md_) : + _pimpl(new impl(interface_name_, binary_, root_, test_suite_name_, md_)) +{ +} + + +/// Destroys a test program. +engine::test_program::~test_program(void) +{ +} + + +/// Gets the name of the test program interface. +/// +/// \return An interface name. +const std::string& +engine::test_program::interface_name(void) const +{ + return _pimpl->interface_name; +} + + +/// Gets the path to the test program relative to the root of the test suite. +/// +/// \return The relative path to the test program binary. +const fs::path& +engine::test_program::relative_path(void) const +{ + return _pimpl->binary; +} + + +/// Gets the absolute path to the test program. +/// +/// \return The absolute path to the test program binary. +const fs::path +engine::test_program::absolute_path(void) const +{ + const fs::path full_path = _pimpl->root / _pimpl->binary; + return full_path.is_absolute() ? full_path : full_path.to_absolute(); +} + + +/// Gets the root of the test suite containing this test program. +/// +/// \return The path to the root of the test suite. +const fs::path& +engine::test_program::root(void) const +{ + return _pimpl->root; +} + + +/// Gets the name of the test suite containing this test program. +/// +/// \return The name of the test suite. +const std::string& +engine::test_program::test_suite_name(void) const +{ + return _pimpl->test_suite_name; +} + + +/// Gets the metadata of the test program. +/// +/// \return The metadata. +const engine::metadata& +engine::test_program::get_metadata(void) const +{ + return _pimpl->md; +} + + +/// Gets a test case by its name. +/// +/// \param name The name of the test case to locate. +/// +/// \return The requested test case. +/// +/// \throw not_found_error If the specified test case is not in the test +/// program. +const engine::test_case_ptr& +engine::test_program::find(const std::string& name) const +{ + // TODO(jmmv): Should use a test_cases_map instead of a vector to optimize + // lookups. + const test_cases_vector& tcs = test_cases(); + for (test_cases_vector::const_iterator iter = tcs.begin(); + iter != tcs.end(); iter++) { + if ((*iter)->name() == name) + return *iter; + } + throw not_found_error(F("Unknown test case %s in test program %s") % name % + relative_path()); +} + + +/// Gets the list of test cases from the test program. +/// +/// Note that this operation may be expensive because it may lazily load the +/// test cases list from the test program. Errors during the processing of the +/// test case list are represented as a single test case describing the failure. +/// +/// \return The list of test cases provided by the test program. +const engine::test_cases_vector& +engine::test_program::test_cases(void) const +{ + if (!_pimpl->test_cases) { + try { + _pimpl->test_cases = load_test_cases(*this); + } catch (const std::runtime_error& e) { + // TODO(jmmv): This is a very ugly workaround for the fact that we + // cannot report failures at the test-program level. We should + // either address this, or move this reporting to the testers + // themselves. + LW(F("Failed to load test cases list: %s") % e.what()); + engine::test_cases_vector fake_test_cases; + fake_test_cases.push_back(test_case_ptr(new test_case( + _pimpl->interface_name, *this, "__test_cases_list__", + "Represents the correct processing of the test cases list", + test_result(engine::test_result::broken, e.what())))); + _pimpl->test_cases = fake_test_cases; + } + } + return _pimpl->test_cases.get(); +} + + +/// Sets the collection of test cases included in this test program. +/// +/// This function is provided so that when we load test programs from the +/// database we can populate them with the test cases they include. We don't +/// want such test programs to be executed to gather this information. +/// +/// We cannot provide this collection of tests in the constructor of the test +/// program because the test cases have to point to their test programs. +/// +/// \pre The test program must not have attempted to load its test cases yet. +/// I.e. test_cases() has not been called. +/// +/// \param test_cases_ The test cases to add to this test program. +void +engine::test_program::set_test_cases(const test_cases_vector& test_cases_) +{ + PRE(!_pimpl->test_cases); + _pimpl->test_cases = test_cases_; +} + + +/// Equality comparator. +/// +/// \param other The other object to compare this one to. +/// +/// \return True if this object and other are equal; false otherwise. +bool +engine::test_program::operator==(const test_program& other) const +{ + return _pimpl == other._pimpl || *_pimpl == *other._pimpl; +} + + +/// Inequality comparator. +/// +/// \param other The other object to compare this one to. +/// +/// \return True if this object and other are different; false otherwise. +bool +engine::test_program::operator!=(const test_program& other) const +{ + return !(*this == other); +} + + +/// Injects the object into a stream. +/// +/// \param output The stream into which to inject the object. +/// \param object The object to format. +/// +/// \return The output stream. +std::ostream& +engine::operator<<(std::ostream& output, const test_cases_vector& object) +{ + output << "["; + for (test_cases_vector::size_type i = 0; i < object.size(); ++i) { + if (i != 0) + output << ", "; + output << *object[i]; + } + output << "]"; + return output; +} + + +/// Injects the object into a stream. +/// +/// \param output The stream into which to inject the object. +/// \param object The object to format. +/// +/// \return The output stream. +std::ostream& +engine::operator<<(std::ostream& output, const test_program& object) +{ + output << F("test_program{interface=%s, binary=%s, root=%s, test_suite=%s, " + "metadata=%s, test_cases=%s}") + % text::quote(object.interface_name(), '\'') + % text::quote(object.relative_path().str(), '\'') + % text::quote(object.root().str(), '\'') + % text::quote(object.test_suite_name(), '\'') + % object.get_metadata() + % object.test_cases(); + return output; +} diff --git a/external/bsd/kyua-cli/dist/engine/test_program.hpp b/external/bsd/kyua-cli/dist/engine/test_program.hpp new file mode 100644 index 000000000..f2a71b31e --- /dev/null +++ b/external/bsd/kyua-cli/dist/engine/test_program.hpp @@ -0,0 +1,101 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file engine/test_program.hpp +/// Interface to interact with test programs. +/// +/// A test program is purely a collection of test cases. The test program has +/// no identity by itself: it only exists to provide a consistent entry point +/// for all the test cases it contains and to group such test cases +/// semantically. Therefore, this module provides no data type to represent the +/// test program. + +#if !defined(ENGINE_TEST_PROGRAM_HPP) +#define ENGINE_TEST_PROGRAM_HPP + +#include +#include +#include +#include + +#include "engine/test_case.hpp" +#include "utils/fs/path.hpp" + +namespace engine { + + +/// Collection of test cases. +typedef std::vector< test_case_ptr > test_cases_vector; + + +std::ostream& operator<<(std::ostream&, const test_cases_vector&); + + +/// Representation of a test program. +class test_program { + struct impl; + + /// Pointer to the shared internal implementation. + std::tr1::shared_ptr< impl > _pimpl; + +public: + test_program(const std::string&, const utils::fs::path&, + const utils::fs::path&, const std::string&, + const metadata&); + ~test_program(void); + + const std::string& interface_name(void) const; + const utils::fs::path& root(void) const; + const utils::fs::path& relative_path(void) const; + const utils::fs::path absolute_path(void) const; + const std::string& test_suite_name(void) const; + const metadata& get_metadata(void) const; + + const test_case_ptr& find(const std::string&) const; + const test_cases_vector& test_cases(void) const; + void set_test_cases(const test_cases_vector&); + + bool operator==(const test_program&) const; + bool operator!=(const test_program&) const; +}; + + +std::ostream& operator<<(std::ostream&, const test_program&); + + +/// Pointer to a test program. +typedef std::tr1::shared_ptr< test_program > test_program_ptr; + + +/// Collection of test programs. +typedef std::vector< test_program_ptr > test_programs_vector; + + +} // namespace engine + +#endif // !defined(ENGINE_TEST_PROGRAM_HPP) diff --git a/external/bsd/kyua-cli/dist/engine/test_program_test.cpp b/external/bsd/kyua-cli/dist/engine/test_program_test.cpp new file mode 100644 index 000000000..c8765e309 --- /dev/null +++ b/external/bsd/kyua-cli/dist/engine/test_program_test.cpp @@ -0,0 +1,327 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "engine/test_program.hpp" + +#include + +#include + +#include "engine/exceptions.hpp" +#include "utils/fs/operations.hpp" +#include "utils/fs/path.hpp" + +namespace fs = utils::fs; + + +ATF_TEST_CASE_WITHOUT_HEAD(ctor_and_getters); +ATF_TEST_CASE_BODY(ctor_and_getters) +{ + const engine::metadata md = engine::metadata_builder() + .add_custom("foo", "bar") + .build(); + const engine::test_program test_program( + "mock", fs::path("binary"), fs::path("root"), "suite-name", md); + ATF_REQUIRE_EQ("mock", test_program.interface_name()); + ATF_REQUIRE_EQ(fs::path("binary"), test_program.relative_path()); + ATF_REQUIRE_EQ(fs::current_path() / "root/binary", + test_program.absolute_path()); + ATF_REQUIRE_EQ(fs::path("root"), test_program.root()); + ATF_REQUIRE_EQ("suite-name", test_program.test_suite_name()); + ATF_REQUIRE_EQ(md, test_program.get_metadata()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(find__ok); +ATF_TEST_CASE_BODY(find__ok) +{ + const engine::test_program test_program( + "plain", fs::path("non-existent"), fs::path("."), "suite-name", + engine::metadata_builder().build()); + const engine::test_case_ptr test_case = test_program.find("main"); + ATF_REQUIRE_EQ(fs::path("non-existent"), + test_case->container_test_program().relative_path()); + ATF_REQUIRE_EQ("main", test_case->name()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(find__missing); +ATF_TEST_CASE_BODY(find__missing) +{ + const engine::test_program test_program( + "plain", fs::path("non-existent"), fs::path("."), "suite-name", + engine::metadata_builder().build()); + ATF_REQUIRE_THROW_RE(engine::not_found_error, + "case.*abc.*program.*non-existent", + test_program.find("abc")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(test_cases__get); +ATF_TEST_CASE_BODY(test_cases__get) +{ + const engine::test_program test_program( + "plain", fs::path("non-existent"), fs::path("."), "suite-name", + engine::metadata_builder().build()); + const engine::test_cases_vector& test_cases = test_program.test_cases(); + ATF_REQUIRE_EQ(1, test_cases.size()); + ATF_REQUIRE_EQ(fs::path("non-existent"), + test_cases[0]->container_test_program().relative_path()); + ATF_REQUIRE_EQ("main", test_cases[0]->name()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(test_cases__some); +ATF_TEST_CASE_BODY(test_cases__some) +{ + engine::test_program test_program( + "plain", fs::path("non-existent"), fs::path("."), "suite-name", + engine::metadata_builder().build()); + + engine::test_cases_vector exp_test_cases; + const engine::test_case test_case("plain", test_program, "main", + engine::metadata_builder().build()); + exp_test_cases.push_back(engine::test_case_ptr( + new engine::test_case(test_case))); + test_program.set_test_cases(exp_test_cases); + + ATF_REQUIRE_EQ(exp_test_cases, test_program.test_cases()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(operators_eq_and_ne__copy); +ATF_TEST_CASE_BODY(operators_eq_and_ne__copy) +{ + const engine::test_program tp1( + "plain", fs::path("non-existent"), fs::path("."), "suite-name", + engine::metadata_builder().build()); + const engine::test_program tp2 = tp1; + ATF_REQUIRE( tp1 == tp2); + ATF_REQUIRE(!(tp1 != tp2)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(operators_eq_and_ne__not_copy); +ATF_TEST_CASE_BODY(operators_eq_and_ne__not_copy) +{ + const std::string base_interface("plain"); + const fs::path base_relative_path("the/test/program"); + const fs::path base_root("/the/root"); + const std::string base_test_suite("suite-name"); + const engine::metadata base_metadata = engine::metadata_builder() + .add_custom("X-foo", "bar") + .build(); + + engine::test_program base_tp( + base_interface, base_relative_path, base_root, base_test_suite, + base_metadata); + + engine::test_cases_vector base_tcs; + { + const engine::test_case tc1("plain", base_tp, "main", + engine::metadata_builder().build()); + base_tcs.push_back(engine::test_case_ptr(new engine::test_case(tc1))); + } + base_tp.set_test_cases(base_tcs); + + // Construct with all same values. + { + engine::test_program other_tp( + base_interface, base_relative_path, base_root, base_test_suite, + base_metadata); + + engine::test_cases_vector other_tcs; + { + const engine::test_case tc1("plain", other_tp, "main", + engine::metadata_builder().build()); + other_tcs.push_back(engine::test_case_ptr( + new engine::test_case(tc1))); + } + other_tp.set_test_cases(other_tcs); + + ATF_REQUIRE( base_tp == other_tp); + ATF_REQUIRE(!(base_tp != other_tp)); + } + + // Different interface. + { + engine::test_program other_tp( + "atf", base_relative_path, base_root, base_test_suite, + base_metadata); + other_tp.set_test_cases(base_tcs); + + ATF_REQUIRE(!(base_tp == other_tp)); + ATF_REQUIRE( base_tp != other_tp); + } + + // Different relative path. + { + engine::test_program other_tp( + base_interface, fs::path("a/b/c"), base_root, base_test_suite, + base_metadata); + other_tp.set_test_cases(base_tcs); + + ATF_REQUIRE(!(base_tp == other_tp)); + ATF_REQUIRE( base_tp != other_tp); + } + + // Different root. + { + engine::test_program other_tp( + base_interface, base_relative_path, fs::path("."), base_test_suite, + base_metadata); + other_tp.set_test_cases(base_tcs); + + ATF_REQUIRE(!(base_tp == other_tp)); + ATF_REQUIRE( base_tp != other_tp); + } + + // Different test suite. + { + engine::test_program other_tp( + base_interface, base_relative_path, base_root, "different-suite", + base_metadata); + other_tp.set_test_cases(base_tcs); + + ATF_REQUIRE(!(base_tp == other_tp)); + ATF_REQUIRE( base_tp != other_tp); + } + + // Different metadata. + { + engine::test_program other_tp( + base_interface, base_relative_path, base_root, base_test_suite, + engine::metadata_builder().build()); + other_tp.set_test_cases(base_tcs); + + ATF_REQUIRE(!(base_tp == other_tp)); + ATF_REQUIRE( base_tp != other_tp); + } + + // Different test cases. + { + engine::test_program other_tp( + base_interface, base_relative_path, base_root, base_test_suite, + base_metadata); + + engine::test_cases_vector other_tcs; + { + const engine::test_case tc1("atf", base_tp, "foo", + engine::metadata_builder().build()); + other_tcs.push_back(engine::test_case_ptr( + new engine::test_case(tc1))); + } + other_tp.set_test_cases(other_tcs); + + ATF_REQUIRE(!(base_tp == other_tp)); + ATF_REQUIRE( base_tp != other_tp); + } +} + + +ATF_TEST_CASE_WITHOUT_HEAD(output__no_test_cases); +ATF_TEST_CASE_BODY(output__no_test_cases) +{ + engine::test_program tp( + "plain", fs::path("binary/path"), fs::path("/the/root"), "suite-name", + engine::metadata_builder().add_allowed_architecture("a").build()); + tp.set_test_cases(engine::test_cases_vector()); + + std::ostringstream str; + str << tp; + ATF_REQUIRE_EQ( + "test_program{interface='plain', binary='binary/path', " + "root='/the/root', test_suite='suite-name', " + "metadata=metadata{allowed_architectures='a', allowed_platforms='', " + "description='', has_cleanup='false', " + "required_configs='', required_files='', required_memory='0', " + "required_programs='', required_user='', timeout='300'}, " + "test_cases=[]}", + str.str()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(output__some_test_cases); +ATF_TEST_CASE_BODY(output__some_test_cases) +{ + engine::test_program tp( + "plain", fs::path("binary/path"), fs::path("/the/root"), "suite-name", + engine::metadata_builder().add_allowed_architecture("a").build()); + + const engine::test_case_ptr tc1(new engine::test_case( + "plain", tp, "the-name", engine::metadata_builder() + .add_allowed_platform("foo").add_custom("X-bar", "baz").build())); + const engine::test_case_ptr tc2(new engine::test_case( + "plain", tp, "another-name", engine::metadata_builder().build())); + engine::test_cases_vector tcs; + tcs.push_back(tc1); + tcs.push_back(tc2); + tp.set_test_cases(tcs); + + std::ostringstream str; + str << tp; + ATF_REQUIRE_EQ( + "test_program{interface='plain', binary='binary/path', " + "root='/the/root', test_suite='suite-name', " + "metadata=metadata{allowed_architectures='a', allowed_platforms='', " + "description='', has_cleanup='false', " + "required_configs='', required_files='', required_memory='0', " + "required_programs='', required_user='', timeout='300'}, " + "test_cases=[" + "test_case{interface='plain', name='the-name', " + "metadata=metadata{allowed_architectures='', allowed_platforms='foo', " + "custom.X-bar='baz', description='', has_cleanup='false', " + "required_configs='', required_files='', required_memory='0', " + "required_programs='', required_user='', timeout='300'}}, " + "test_case{interface='plain', name='another-name', " + "metadata=metadata{allowed_architectures='', allowed_platforms='', " + "description='', has_cleanup='false', " + "required_configs='', required_files='', required_memory='0', " + "required_programs='', required_user='', timeout='300'}}]}", + str.str()); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + // TODO(jmmv): These tests have ceased to be realistic with the move to + // TestersDesign. We probably should have some (few!) integration tests for + // the various known testers... or, alternatively, provide a mock tester to + // run our tests with. + ATF_ADD_TEST_CASE(tcs, ctor_and_getters); + ATF_ADD_TEST_CASE(tcs, find__ok); + ATF_ADD_TEST_CASE(tcs, find__missing); + ATF_ADD_TEST_CASE(tcs, test_cases__get); + ATF_ADD_TEST_CASE(tcs, test_cases__some); + + ATF_ADD_TEST_CASE(tcs, operators_eq_and_ne__copy); + ATF_ADD_TEST_CASE(tcs, operators_eq_and_ne__not_copy); + + ATF_ADD_TEST_CASE(tcs, output__no_test_cases); + ATF_ADD_TEST_CASE(tcs, output__some_test_cases); +} diff --git a/external/bsd/kyua-cli/dist/engine/test_result.cpp b/external/bsd/kyua-cli/dist/engine/test_result.cpp new file mode 100644 index 000000000..342eff86e --- /dev/null +++ b/external/bsd/kyua-cli/dist/engine/test_result.cpp @@ -0,0 +1,202 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "engine/test_result.hpp" + +#include "engine/exceptions.hpp" +#include "utils/format/macros.hpp" +#include "utils/sanity.hpp" +#include "utils/text/operations.ipp" + +namespace text = utils::text; + + +/// Constructs a base result. +/// +/// \param type_ The type of the result. +/// \param reason_ The reason explaining the result, if any. It is OK for this +/// to be empty, which is actually the default. +engine::test_result::test_result(const result_type type_, + const std::string& reason_) : + _type(type_), + _reason(reason_) +{ +} + + +/// Parses a result from an input stream. +/// +/// The parsing of a results file is quite permissive in terms of file syntax +/// validation. We accept result files with or without trailing new lines, and +/// with descriptions that may span multiple lines. This is to avoid getting in +/// trouble when the result is generated from user code, in which case it is +/// hard to predict how newlines look like. Just swallow them; it's better for +/// the consumer. +/// +/// \param input The stream from which to read the result. +/// +/// \return The parsed result. If there is any problem during parsing, the +/// failure is encoded as a broken result. +engine::test_result +engine::test_result::parse(std::istream& input) +{ + std::string line; + if (!std::getline(input, line).good() && line.empty()) + return test_result(broken, "Empty result file"); + + // Fast-path for the most common case. + if (line == "passed") + return test_result(passed); + + std::string type, reason; + const std::string::size_type pos = line.find(": "); + if (pos == std::string::npos) { + type = line; + reason = ""; + } else { + type = line.substr(0, pos); + reason = line.substr(pos + 2); + } + + if (input.good()) { + line.clear(); + while (std::getline(input, line).good() && !line.empty()) { + reason += "<>" + line; + line.clear(); + } + if (!line.empty()) + reason += "<>" + line; + } + + if (type == "broken") { + return test_result(broken, reason); + } else if (type == "expected_failure") { + return test_result(expected_failure, reason); + } else if (type == "failed") { + return test_result(failed, reason); + } else if (type == "passed") { + return test_result(passed, reason); + } else if (type == "skipped") { + return test_result(skipped, reason); + } else { + return test_result(broken, F("Unknown result type '%s'") % type); + } +} + + +/// Returns the type of the result. +/// +/// \return A result type. +engine::test_result::result_type +engine::test_result::type(void) const +{ + return _type; +} + + +/// Returns the reason explaining the result. +/// +/// \return A textual reason, possibly empty. +const std::string& +engine::test_result::reason(void) const +{ + return _reason; +} + + +/// True if the test case result has a positive connotation. +/// +/// \return Whether the test case is good or not. +bool +engine::test_result::good(void) const +{ + switch (_type) { + case expected_failure: + case passed: + case skipped: + return true; + + case broken: + case failed: + return false; + } + UNREACHABLE; +} + + +/// Equality comparator. +/// +/// \param other The test result to compare to. +/// +/// \return True if the other object is equal to this one, false otherwise. +bool +engine::test_result::operator==(const test_result& other) const +{ + return _type == other._type && _reason == other._reason; +} + + +/// Inequality comparator. +/// +/// \param other The test result to compare to. +/// +/// \return True if the other object is different from this one, false +/// otherwise. +bool +engine::test_result::operator!=(const test_result& other) const +{ + return !(*this == other); +} + + +/// Injects the object into a stream. +/// +/// \param output The stream into which to inject the object. +/// \param object The object to format. +/// +/// \return The output stream. +std::ostream& +engine::operator<<(std::ostream& output, const test_result& object) +{ + std::string result_name; + switch (object.type()) { + case test_result::broken: result_name = "broken"; break; + case test_result::expected_failure: result_name = "expected_failure"; break; + case test_result::failed: result_name = "failed"; break; + case test_result::passed: result_name = "passed"; break; + case test_result::skipped: result_name = "skipped"; break; + } + const std::string& reason = object.reason(); + if (reason.empty()) { + output << F("test_result{type=%s}") % text::quote(result_name, '\''); + } else { + output << F("test_result{type=%s, reason=%s}") + % text::quote(result_name, '\'') % text::quote(reason, '\''); + } + return output; +} diff --git a/external/bsd/kyua-cli/dist/engine/test_result.hpp b/external/bsd/kyua-cli/dist/engine/test_result.hpp new file mode 100644 index 000000000..29399180e --- /dev/null +++ b/external/bsd/kyua-cli/dist/engine/test_result.hpp @@ -0,0 +1,91 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file engine/test_result.hpp +/// Representation of test case results. + +#if !defined(ENGINE_TEST_RESULT_HPP) +#define ENGINE_TEST_RESULT_HPP + +#include +#include +#include + +namespace engine { + + +/// Representation of a single test result. +/// +/// A test result is a simple pair of (type, reason). The type indicates the +/// semantics of the results, and the optional reason provides an extra +/// description of the result type. +/// +/// In general, a 'passed' result will not have a reason attached, because a +/// successful test case does not deserve any kind of explanation. We used to +/// special-case this with a very complex class hierarchy, but it proved to +/// result in an extremely-complex to maintain code base that provided no +/// benefits. As a result, we allow any test type to carry a reason. +class test_result { +public: + /// Type definitions for all possible test case results. + enum result_type { + broken, + expected_failure, + failed, + passed, + skipped, + }; + +private: + /// The type of the result. + result_type _type; + + /// A description of the result; may be empty. + std::string _reason; + +public: + test_result(const result_type, const std::string& = ""); + static test_result parse(std::istream&); + + result_type type(void) const; + const std::string& reason(void) const; + + bool good(void) const; + + bool operator==(const test_result&) const; + bool operator!=(const test_result&) const; +}; + + +std::ostream& operator<<(std::ostream&, const test_result&); + + +} // namespace engine + + +#endif // !defined(ENGINE_TEST_RESULT_HPP) diff --git a/external/bsd/kyua-cli/dist/engine/test_result_test.cpp b/external/bsd/kyua-cli/dist/engine/test_result_test.cpp new file mode 100644 index 000000000..bda57751e --- /dev/null +++ b/external/bsd/kyua-cli/dist/engine/test_result_test.cpp @@ -0,0 +1,262 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "engine/test_result.hpp" + +#include + +#include + +#include "engine/exceptions.hpp" + +using engine::test_result; + + +namespace { + + +/// Creates a test case to validate the getters. +/// +/// \param name The name of the test case; "__getters" will be appended. +/// \param expected_type The expected type of the result. +/// \param expected_reason The expected reason for the result. +/// \param result The result to query. +#define GETTERS_TEST(name, expected_type, expected_reason, result) \ + ATF_TEST_CASE_WITHOUT_HEAD(name ## __getters); \ + ATF_TEST_CASE_BODY(name ## __getters) \ + { \ + ATF_REQUIRE(expected_type == result.type()); \ + ATF_REQUIRE_EQ(expected_reason, result.reason()); \ + } + + +/// Creates a test case to validate the good() method. +/// +/// \param name The name of the test case; "__good" will be appended. +/// \param expected The expected result of good(). +/// \param result_type The result type to check. +#define GOOD_TEST(name, expected, result_type) \ + ATF_TEST_CASE_WITHOUT_HEAD(name ## __good); \ + ATF_TEST_CASE_BODY(name ## __good) \ + { \ + ATF_REQUIRE_EQ(expected, test_result(result_type).good()); \ + } + + +/// Creates a test case to validate the operator<< method. +/// +/// \param name The name of the test case; "__output" will be appended. +/// \param expected The expected string in the output. +/// \param result The result to format. +#define OUTPUT_TEST(name, expected, result) \ + ATF_TEST_CASE_WITHOUT_HEAD(name ## __output); \ + ATF_TEST_CASE_BODY(name ## __output) \ + { \ + std::ostringstream output; \ + output << "prefix" << result << "suffix"; \ + ATF_REQUIRE_EQ("prefix" + std::string(expected) + "suffix", \ + output.str()); \ + } + + +/// Validates the parse() method on a particular test result type. +/// +/// \param result_name Textual representation of the type, to be written to the +/// input data. +/// \param result_type Expected result type. +static void +parse_test(const std::string& result_name, + const test_result::result_type result_type) +{ + std::istringstream input(result_name); + ATF_REQUIRE(test_result(result_type) == test_result::parse(input)); + + input.clear(); + input.str(result_name + ": Some message"); + ATF_REQUIRE(test_result(result_type, "Some message") == + test_result::parse(input)); + + input.clear(); + input.str(result_name + ": Some message\n"); + ATF_REQUIRE(test_result(result_type, "Some message") == + test_result::parse(input)); + + input.clear(); + input.str(result_name + ": foo\nbar"); + ATF_REQUIRE(test_result(result_type, "foo<>bar") == + test_result::parse(input)); + + input.clear(); + input.str(result_name + ": foo\nbar\n"); + ATF_REQUIRE(test_result(result_type, "foo<>bar") == + test_result::parse(input)); +} + + +/// Creates a test case to validate the parse() method for a given type. +/// +/// \param name The name of the test case; "parse__" will be prepended. +#define PARSE_TEST(name) \ + ATF_TEST_CASE_WITHOUT_HEAD(parse__ ## name); \ + ATF_TEST_CASE_BODY(parse__ ## name) \ + { \ + parse_test(#name, test_result:: name); \ + } + + +} // anonymous namespace + + +PARSE_TEST(broken); +PARSE_TEST(expected_failure); +PARSE_TEST(failed); +PARSE_TEST(passed); +PARSE_TEST(skipped); + + +ATF_TEST_CASE_WITHOUT_HEAD(parse__empty); +ATF_TEST_CASE_BODY(parse__empty) +{ + std::istringstream input(""); + ATF_REQUIRE(test_result(test_result::broken, "Empty result file") == + test_result::parse(input)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(parse__unknown_type); +ATF_TEST_CASE_BODY(parse__unknown_type) +{ + std::istringstream input("passed "); + ATF_REQUIRE( + test_result(test_result::broken, "Unknown result type 'passed '") == + test_result::parse(input)); + + input.clear(); + input.str("fail"); + ATF_REQUIRE( + test_result(test_result::broken, "Unknown result type 'fail'") == + test_result::parse(input)); + + input.clear(); + input.str("a b"); + ATF_REQUIRE( + test_result(test_result::broken, "Unknown result type 'a b'") == + test_result::parse(input)); +} + + +GETTERS_TEST(broken, test_result::broken, "The reason", + test_result(test_result::broken, "The reason")); +GETTERS_TEST(expected_failure, test_result::expected_failure, "The reason", + test_result(test_result::expected_failure, "The reason")); +GETTERS_TEST(failed, test_result::failed, "The reason", + test_result(test_result::failed, "The reason")); +GETTERS_TEST(passed, test_result::passed, "", + test_result(test_result::passed)); +GETTERS_TEST(skipped, test_result::skipped, "The reason", + test_result(test_result::skipped, "The reason")); + + +GOOD_TEST(broken, false, test_result::broken); +GOOD_TEST(expected_failure, true, test_result::expected_failure); +GOOD_TEST(failed, false, test_result::failed); +GOOD_TEST(passed, true, test_result::passed); +GOOD_TEST(skipped, true, test_result::skipped); + + +OUTPUT_TEST(broken, "test_result{type='broken', reason='foo'}", + test_result(test_result::broken, "foo")); +OUTPUT_TEST(expected_failure, + "test_result{type='expected_failure', reason='abc def'}", + test_result(test_result::expected_failure, "abc def")); +OUTPUT_TEST(failed, "test_result{type='failed', reason='some \\'string'}", + test_result(test_result::failed, "some 'string")); +OUTPUT_TEST(passed, "test_result{type='passed'}", + test_result(test_result::passed, "")); +OUTPUT_TEST(skipped, "test_result{type='skipped', reason='last message'}", + test_result(test_result::skipped, "last message")); + + +ATF_TEST_CASE_WITHOUT_HEAD(operator_eq); +ATF_TEST_CASE_BODY(operator_eq) +{ + const test_result result1(test_result::broken, "Foo"); + const test_result result2(test_result::broken, "Foo"); + const test_result result3(test_result::broken, "Bar"); + const test_result result4(test_result::failed, "Foo"); + + ATF_REQUIRE( result1 == result1); + ATF_REQUIRE( result1 == result2); + ATF_REQUIRE(!(result1 == result3)); + ATF_REQUIRE(!(result1 == result4)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(operator_ne); +ATF_TEST_CASE_BODY(operator_ne) +{ + const test_result result1(test_result::broken, "Foo"); + const test_result result2(test_result::broken, "Foo"); + const test_result result3(test_result::broken, "Bar"); + const test_result result4(test_result::failed, "Foo"); + + ATF_REQUIRE(!(result1 != result1)); + ATF_REQUIRE(!(result1 != result2)); + ATF_REQUIRE( result1 != result3); + ATF_REQUIRE( result1 != result4); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, parse__broken); + ATF_ADD_TEST_CASE(tcs, parse__expected_failure); + ATF_ADD_TEST_CASE(tcs, parse__failed); + ATF_ADD_TEST_CASE(tcs, parse__passed); + ATF_ADD_TEST_CASE(tcs, parse__skipped); + ATF_ADD_TEST_CASE(tcs, parse__empty); + ATF_ADD_TEST_CASE(tcs, parse__unknown_type); + + ATF_ADD_TEST_CASE(tcs, broken__getters); + ATF_ADD_TEST_CASE(tcs, broken__good); + ATF_ADD_TEST_CASE(tcs, broken__output); + ATF_ADD_TEST_CASE(tcs, expected_failure__getters); + ATF_ADD_TEST_CASE(tcs, expected_failure__good); + ATF_ADD_TEST_CASE(tcs, expected_failure__output); + ATF_ADD_TEST_CASE(tcs, failed__getters); + ATF_ADD_TEST_CASE(tcs, failed__good); + ATF_ADD_TEST_CASE(tcs, failed__output); + ATF_ADD_TEST_CASE(tcs, passed__getters); + ATF_ADD_TEST_CASE(tcs, passed__good); + ATF_ADD_TEST_CASE(tcs, passed__output); + ATF_ADD_TEST_CASE(tcs, skipped__getters); + ATF_ADD_TEST_CASE(tcs, skipped__good); + ATF_ADD_TEST_CASE(tcs, skipped__output); + ATF_ADD_TEST_CASE(tcs, operator_eq); + ATF_ADD_TEST_CASE(tcs, operator_ne); +} diff --git a/external/bsd/kyua-cli/dist/engine/testers.cpp b/external/bsd/kyua-cli/dist/engine/testers.cpp new file mode 100644 index 000000000..68fb04854 --- /dev/null +++ b/external/bsd/kyua-cli/dist/engine/testers.cpp @@ -0,0 +1,309 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "engine/testers.hpp" + +extern "C" { +#include +#include +} + +#include +#include +#include +#include +#include + +#include "engine/exceptions.hpp" +#include "utils/env.hpp" +#include "utils/format/macros.hpp" +#include "utils/fs/operations.hpp" +#include "utils/fs/path.hpp" +#include "utils/logging/macros.hpp" +#include "utils/optional.ipp" +#include "utils/passwd.hpp" +#include "utils/process/child.ipp" +#include "utils/process/status.hpp" +#include "utils/stream.hpp" + +namespace datetime = utils::datetime; +namespace fs = utils::fs; +namespace logging = utils::logging; +namespace passwd = utils::passwd; +namespace process = utils::process; + +using utils::none; +using utils::optional; + + +namespace { + + +/// Mapping of interface names to tester binaries. +typedef std::map< std::string, std::string > testers_map; + + +/// Collection of known-good interface to tester mappings. +static testers_map interfaces_to_testers; + + +/// Drops the trailing newline in a string and replaces others with a literal. +/// +/// \param input The string in which to perform the replacements. +/// +/// \return The modified string. +static std::string +replace_newlines(const std::string input) +{ + std::string output = input; + + while (output.length() > 0 && output[output.length() - 1] == '\n') { + output.erase(output.end() - 1); + } + + std::string::size_type newline = output.find('\n', 0); + while (newline != std::string::npos) { + output.replace(newline, 1, "<>"); + newline = output.find('\n', newline + 1); + } + + return output; +} + + +/// RAII pattern to invoke a release method on destruction. +/// +/// \todo The existence of this class here is a hack. We should either +/// generalize the class and use it wherever we need release on destruction +/// semantics, or we should have proper abstractions for the objects below that +/// use this class. +/// +/// \tparam Object The type of the object to be released. Not a pointer. +/// \tparam ReturnType The return type of the release method. +template< typename Object, typename ReturnType > +class object_releaser { + /// Pointer to the object being managed. + Object* _object; + + /// Release hook. + ReturnType (*_free_hook)(Object*); + +public: + /// Constructor. + /// + /// \param object Pointer to the object being managed. + /// \param free_hook Release hook. + object_releaser(Object* object, ReturnType (*free_hook)(Object*)) : + _object(object), _free_hook(free_hook) + { + } + + /// Destructor. + ~object_releaser(void) + { + _free_hook(_object); + } +}; + + +/// Finds all available testers and caches their data. +/// +/// \param [out] testers Map into which to store the list of available testers. +static void +load_testers(testers_map& testers) +{ + PRE(testers.empty()); + + const fs::path raw_testersdir(utils::getenv_with_default( + "KYUA_TESTERSDIR", KYUA_TESTERSDIR)); + const fs::path testersdir = raw_testersdir.is_absolute() ? + raw_testersdir : raw_testersdir.to_absolute(); + + ::DIR* dir = ::opendir(testersdir.c_str()); + if (dir == NULL) { + const int original_errno = errno; + LW(F("Failed to open testers dir %s: %s") % testersdir % + strerror(original_errno)); + return; // No testers available in the given location. + } + const object_releaser< ::DIR, int > dir_releaser(dir, ::closedir); + + ::regex_t preg; + if (::regcomp(&preg, "^kyua-(.+)-tester$", REG_EXTENDED) != 0) + throw engine::error("Failed to compile regular expression"); + const object_releaser< ::regex_t, void > preg_releaser(&preg, ::regfree); + + ::dirent* de; + while ((de = readdir(dir)) != NULL) { + ::regmatch_t matches[2]; + const int ret = ::regexec(&preg, de->d_name, 2, matches, 0); + if (ret == 0) { + const std::string interface(de->d_name + matches[1].rm_so, + matches[1].rm_eo - matches[1].rm_so); + const fs::path path = testersdir / de->d_name; + LI(F("Found tester for interface %s in %s") % interface % path); + INV(path.is_absolute()); + testers[interface] = path.str(); + } else if (ret == REG_NOMATCH) { + // Not a tester; skip. + } else { + throw engine::error("Failed to match regular expression"); + } + } +} + + +} // anonymous namespace + + +/// Returns the path to a tester binary. +/// +/// \param interface Name of the interface of the tester being looked for. +/// +/// \return Absolute path to the tester. +fs::path +engine::tester_path(const std::string& interface) +{ + if (interfaces_to_testers.empty()) + load_testers(interfaces_to_testers); + + const testers_map::const_iterator iter = interfaces_to_testers.find( + interface); + if (iter == interfaces_to_testers.end()) + throw engine::error("Unknown interface " + interface); + + const fs::path path((*iter).second); + INV(path.is_absolute()); + return path; +} + + +/// Constructs a tester. +/// +/// \param interface Name of the interface to use. +/// \param unprivileged_user If not none, the user to switch to when running +/// the tester. +/// \param timeout If not none, the timeout to pass to the tester. +engine::tester::tester(const std::string& interface, + const optional< passwd::user >& unprivileged_user, + const optional< datetime::delta >& timeout) : + _interface(interface) +{ + if (unprivileged_user) { + _common_args.push_back(F("-u%s") % unprivileged_user.get().uid); + _common_args.push_back(F("-g%s") % unprivileged_user.get().gid); + } + if (timeout) { + PRE(timeout.get().useconds == 0); + _common_args.push_back(F("-t%s") % timeout.get().seconds); + } +} + + +/// Destructor. +engine::tester::~tester(void) +{ +} + + +/// Executes a list operation on a test program. +/// +/// \param program Path to the test program. +/// +/// \return The output of the tester, which represents a valid list of test +/// cases. +/// +/// \throw error If the tester returns with an unsuccessful exit code. +std::string +engine::tester::list(const fs::path& program) const +{ + std::vector< std::string > args = _common_args; + args.push_back("list"); + args.push_back(program.str()); + + const fs::path tester_path = engine::tester_path(_interface); + std::auto_ptr< process::child > child = process::child::spawn_capture( + tester_path, args); + + const std::string output = utils::read_stream(child->output()); + + const process::status status = child->wait(); + if (!status.exited() || status.exitstatus() != EXIT_SUCCESS) + throw engine::error("Tester did not exit cleanly: " + + replace_newlines(output)); + return output; +} + + +/// Executes a test operation on a test case. +/// +/// \param program Path to the test program. +/// \param test_case_name Name of the test case to execute. +/// \param result_file Path to the file in which to leave the result of the +/// tester invocation. +/// \param stdout_file Path to the file in which to store the stdout. +/// \param stderr_file Path to the file in which to store the stderr. +/// \param vars Collection of configuration variables. +/// +/// \throw error If the tester returns with an unsuccessful exit code. +void +engine::tester::test(const fs::path& program, const std::string& test_case_name, + const fs::path& result_file, const fs::path& stdout_file, + const fs::path& stderr_file, + const std::map< std::string, std::string >& vars) const +{ + std::vector< std::string > args = _common_args; + args.push_back("test"); + for (std::map< std::string, std::string >::const_iterator i = vars.begin(); + i != vars.end(); ++i) { + args.push_back(F("-v%s=%s") % (*i).first % (*i).second); + } + args.push_back(program.str()); + args.push_back(test_case_name); + args.push_back(result_file.str()); + + const fs::path tester_path = engine::tester_path(_interface); + std::auto_ptr< process::child > child = process::child::spawn_files( + tester_path, args, stdout_file, stderr_file); + const process::status status = child->wait(); + + if (status.exited()) { + if (status.exitstatus() == EXIT_SUCCESS) { + // OK; the tester exited cleanly. + } else if (status.exitstatus() == EXIT_FAILURE) { + // OK; the tester reported that the test itself failed and we have + // the result file to indicate this. + } else { + throw engine::error(F("Tester failed with code %s; this is a bug") % + status.exitstatus()); + } + } else { + INV(status.signaled()); + throw engine::error("Tester received a signal; this is a bug"); + } +} diff --git a/external/bsd/kyua-cli/dist/engine/testers.hpp b/external/bsd/kyua-cli/dist/engine/testers.hpp new file mode 100644 index 000000000..7f59a5cf1 --- /dev/null +++ b/external/bsd/kyua-cli/dist/engine/testers.hpp @@ -0,0 +1,85 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file engine/testers.hpp +/// Invocation of external tester binaries. + +#if !defined(ENGINE_TESTERS_HPP) +#define ENGINE_TESTERS_HPP + +#include +#include +#include + +#include "utils/datetime.hpp" +#include "utils/optional.hpp" +#include "utils/passwd.hpp" + +namespace utils { +namespace config { +class tree; +} // namespace config +namespace fs { +class path; +} // namespace fs +} // namespace utils + +namespace engine { + + +/// Abstraction to invoke an external tester. +/// +/// This class provides the primitives to construct an invocation of an external +/// tester. In other words: this is the place where the knowledge of what +/// arguments a tester receives and the output it returns. +class tester { + /// Name of the tester interface to use. + std::string _interface; + + /// Common arguments to the tester, to be passed before the subcommand. + std::vector< std::string > _common_args; + +public: + tester(const std::string&, const utils::optional< utils::passwd::user >&, + const utils::optional< utils::datetime::delta >&); + ~tester(void); + + std::string list(const utils::fs::path&) const; + void test(const utils::fs::path&, const std::string&, + const utils::fs::path&, const utils::fs::path&, + const utils::fs::path&, + const std::map< std::string, std::string >&) const; +}; + + +utils::fs::path tester_path(const std::string&); + + +} // namespace engine + +#endif // !defined(ENGINE_TESTERS_HPP) diff --git a/external/bsd/kyua-cli/dist/engine/testers_test.cpp b/external/bsd/kyua-cli/dist/engine/testers_test.cpp new file mode 100644 index 000000000..a9e3c3d3f --- /dev/null +++ b/external/bsd/kyua-cli/dist/engine/testers_test.cpp @@ -0,0 +1,316 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "engine/testers.hpp" + +extern "C" { +#include +} + +#include + +#include + +#include "engine/exceptions.hpp" +#include "utils/datetime.hpp" +#include "utils/env.hpp" +#include "utils/format/macros.hpp" +#include "utils/fs/path.hpp" +#include "utils/fs/operations.hpp" +#include "utils/optional.ipp" +#include "utils/passwd.hpp" + +namespace datetime = utils::datetime; +namespace fs = utils::fs; +namespace passwd = utils::passwd; + +using utils::none; +using utils::optional; + + +namespace { + + +/// Creates a mock tester. +/// +/// The interface accepted by the tester is 'mock'. This tester outputs the +/// arguments passed to it and then prints a message to both the stdout and the +/// stderr. +/// +/// \param exit_status Code to exit with. +static void +create_mock_tester(const int exit_status) +{ + atf::utils::create_file( + "kyua-mock-tester", + F("#! /bin/sh\n" + "while [ ${#} -gt 0 ]; do\n" + " echo \"Arg: ${1}\"\n" + " shift\n" + "done\n" + "echo 'tester output'\n" + "echo 'tester error' 1>&2\n" + "exit %s\n") % exit_status); + ATF_REQUIRE(::chmod("kyua-mock-tester", 0755) != -1); + + utils::setenv("KYUA_TESTERSDIR", fs::current_path().str()); +} + + +} // anonymous namespace + + +ATF_TEST_CASE_WITHOUT_HEAD(tester__list__defaults); +ATF_TEST_CASE_BODY(tester__list__defaults) +{ + create_mock_tester(EXIT_SUCCESS); + engine::tester tester("mock", none, none); + const std::string output = tester.list(fs::path("/foo/bar")); + + const std::string exp_output = + "Arg: list\n" + "Arg: /foo/bar\n" + "tester output\n" + "tester error\n"; + ATF_REQUIRE_EQ(exp_output, output); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(tester__list__explicit_common_args); +ATF_TEST_CASE_BODY(tester__list__explicit_common_args) +{ + const passwd::user user("fake", 123, 456); + const datetime::delta timeout(15, 0); + + create_mock_tester(EXIT_SUCCESS); + engine::tester tester("mock", utils::make_optional(user), + utils::make_optional(timeout)); + const std::string output = tester.list(fs::path("/another/program/1")); + + const std::string exp_output = + "Arg: -u123\n" + "Arg: -g456\n" + "Arg: -t15\n" + "Arg: list\n" + "Arg: /another/program/1\n" + "tester output\n" + "tester error\n"; + ATF_REQUIRE_EQ(exp_output, output); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(tester__list__unknown_interface); +ATF_TEST_CASE_BODY(tester__list__unknown_interface) +{ + utils::setenv("KYUA_TESTERSDIR", "."); + engine::tester tester("non-existent", none, none); + ATF_REQUIRE_THROW_RE(engine::error, "Unknown interface non-existent", + tester.list(fs::path("does-not-matter"))); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(tester__list__tester_fails); +ATF_TEST_CASE_BODY(tester__list__tester_fails) +{ + create_mock_tester(EXIT_FAILURE); + engine::tester tester("mock", none, none); + ATF_REQUIRE_THROW_RE( + engine::error, + "Tester did not exit cleanly:.*tester output.*tester error", + tester.list(fs::path("does-not-matter"))); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(tester__test__defaults); +ATF_TEST_CASE_BODY(tester__test__defaults) +{ + std::map< std::string, std::string > vars; + + create_mock_tester(EXIT_FAILURE); + engine::tester tester("mock", none, none); + tester.test(fs::path("/foo/bar"), "test-case", fs::path("/the/result/file"), + fs::path("tester.out"), fs::path("tester.err"), vars); + + const std::string exp_output = + "Arg: test\n" + "Arg: /foo/bar\n" + "Arg: test-case\n" + "Arg: /the/result/file\n" + "tester output\n"; + const std::string exp_error = + "tester error\n"; + ATF_REQUIRE(atf::utils::compare_file("tester.out", exp_output)); + ATF_REQUIRE(atf::utils::compare_file("tester.err", exp_error)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(tester__test__explicit_common_args_and_vars); +ATF_TEST_CASE_BODY(tester__test__explicit_common_args_and_vars) +{ + const passwd::user user("fake", 123, 456); + const datetime::delta timeout(15, 0); + + std::map< std::string, std::string > vars; + vars["var1"] = "value1"; + vars["variable-2"] = "value with spaces"; + + create_mock_tester(EXIT_SUCCESS); + engine::tester tester("mock", utils::make_optional(user), + utils::make_optional(timeout)); + tester.test(fs::path("/foo/bar"), "test-case", fs::path("/the/result/file"), + fs::path("tester.out"), fs::path("tester.err"), vars); + + const std::string exp_output = + "Arg: -u123\n" + "Arg: -g456\n" + "Arg: -t15\n" + "Arg: test\n" + "Arg: -vvar1=value1\n" + "Arg: -vvariable-2=value with spaces\n" + "Arg: /foo/bar\n" + "Arg: test-case\n" + "Arg: /the/result/file\n" + "tester output\n"; + const std::string exp_error = + "tester error\n"; + ATF_REQUIRE(atf::utils::compare_file("tester.out", exp_output)); + ATF_REQUIRE(atf::utils::compare_file("tester.err", exp_error)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(tester__test__unknown_interface); +ATF_TEST_CASE_BODY(tester__test__unknown_interface) +{ + const std::map< std::string, std::string > vars; + + utils::setenv("KYUA_TESTERSDIR", "."); + engine::tester tester("non-existent", none, none); + ATF_REQUIRE_THROW_RE(engine::error, "Unknown interface non-existent", + tester.test(fs::path("foo"), "bar", fs::path("baz"), + fs::path("out"), fs::path("err"), vars)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(tester__test__tester_fails); +ATF_TEST_CASE_BODY(tester__test__tester_fails) +{ + const std::map< std::string, std::string > vars; + + create_mock_tester(2); + engine::tester tester("mock", none, none); + ATF_REQUIRE_THROW_RE( + engine::error, + "Tester failed with code 2; this is a bug", + tester.test(fs::path("foo"), "bar", fs::path("baz"), + fs::path("out"), fs::path("err"), vars)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(tester_path__default); +ATF_TEST_CASE_BODY(tester_path__default) +{ + ATF_REQUIRE(atf::utils::file_exists(engine::tester_path("atf").str())); + ATF_REQUIRE(atf::utils::file_exists(engine::tester_path("plain").str())); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(tester_path__custom); +ATF_TEST_CASE_BODY(tester_path__custom) +{ + fs::mkdir(fs::path("testers"), 0755); + atf::utils::create_file("testers/kyua-mock-1-tester", "Not a binary"); + atf::utils::create_file("testers/kyua-mock-2-tester", "Not a binary"); + utils::setenv("KYUA_TESTERSDIR", (fs::current_path() / "testers").str()); + + const fs::path mock1 = engine::tester_path("mock-1"); + ATF_REQUIRE(mock1.is_absolute()); + ATF_REQUIRE(atf::utils::file_exists(mock1.str())); + + const fs::path mock2 = engine::tester_path("mock-2"); + ATF_REQUIRE(mock2.is_absolute()); + ATF_REQUIRE(atf::utils::file_exists(mock2.str())); + + ATF_REQUIRE_THROW_RE(engine::error, "Unknown interface mock-3", + engine::tester_path("mock-3")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(tester_path__cached); +ATF_TEST_CASE_BODY(tester_path__cached) +{ + fs::mkdir(fs::path("testers"), 0755); + atf::utils::create_file("testers/kyua-mock-tester", "Not a binary"); + utils::setenv("KYUA_TESTERSDIR", (fs::current_path() / "testers").str()); + + const fs::path mock = engine::tester_path("mock"); + ATF_REQUIRE(atf::utils::file_exists(mock.str())); + ATF_REQUIRE(::unlink(mock.c_str()) != -1); + ATF_REQUIRE(!atf::utils::file_exists(mock.str())); + ATF_REQUIRE_EQ(mock, engine::tester_path("mock")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(tester_path__empty); +ATF_TEST_CASE_BODY(tester_path__empty) +{ + fs::mkdir(fs::path("testers"), 0755); + atf::utils::create_file("testers/kyua--tester", "Not a binary"); + utils::setenv("KYUA_TESTERSDIR", (fs::current_path() / "testers").str()); + + ATF_REQUIRE_THROW_RE(engine::error, "Unknown interface ", + engine::tester_path("")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(tester_path__missing); +ATF_TEST_CASE_BODY(tester_path__missing) +{ + utils::setenv("KYUA_TESTERSDIR", fs::current_path().str()); + ATF_REQUIRE_THROW_RE(engine::error, "Unknown interface plain", + engine::tester_path("plain")); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, tester__list__defaults); + ATF_ADD_TEST_CASE(tcs, tester__list__explicit_common_args); + ATF_ADD_TEST_CASE(tcs, tester__list__unknown_interface); + ATF_ADD_TEST_CASE(tcs, tester__list__tester_fails); + + ATF_ADD_TEST_CASE(tcs, tester__test__defaults); + ATF_ADD_TEST_CASE(tcs, tester__test__explicit_common_args_and_vars); + ATF_ADD_TEST_CASE(tcs, tester__test__unknown_interface); + ATF_ADD_TEST_CASE(tcs, tester__test__tester_fails); + + ATF_ADD_TEST_CASE(tcs, tester_path__default); + ATF_ADD_TEST_CASE(tcs, tester_path__custom); + ATF_ADD_TEST_CASE(tcs, tester_path__cached); + ATF_ADD_TEST_CASE(tcs, tester_path__empty); + ATF_ADD_TEST_CASE(tcs, tester_path__missing); +} diff --git a/external/bsd/kyua-cli/dist/examples/Kyuafile b/external/bsd/kyua-cli/dist/examples/Kyuafile new file mode 100644 index 000000000..2c8f39baa --- /dev/null +++ b/external/bsd/kyua-cli/dist/examples/Kyuafile @@ -0,0 +1,5 @@ +syntax(2) + +test_suite("kyua") + +atf_test_program{name="syntax_test"} diff --git a/external/bsd/kyua-cli/dist/examples/Kyuafile.top b/external/bsd/kyua-cli/dist/examples/Kyuafile.top new file mode 100644 index 000000000..d8c95116e --- /dev/null +++ b/external/bsd/kyua-cli/dist/examples/Kyuafile.top @@ -0,0 +1,54 @@ +-- Copyright 2011 Google Inc. +-- All rights reserved. +-- +-- Redistribution and use in source and binary forms, with or without +-- modification, are permitted provided that the following conditions are +-- met: +-- +-- * Redistributions of source code must retain the above copyright +-- notice, this list of conditions and the following disclaimer. +-- * Redistributions in binary form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- * Neither the name of Google Inc. nor the names of its contributors +-- may be used to endorse or promote products derived from this software +-- without specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +-- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +-- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +-- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +-- OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +-- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +-- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +-- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +-- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +-- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +-- Example top-level Kyuafile. +-- +-- This sample top-level Kyuafile looks for any */Kyuafile files and includes +-- them in order to process all the test cases within a test suite. +-- +-- This file is supposed to be installed in the root directory of the tests +-- hierarchy; typically, this is /usr/tests/Kyuafile (note that the .top +-- extension has been dropped). Third-party packages install tests as +-- subdirectories of /usr/tests. When doing so, they should not have to update +-- the contents of the top-level Kyuafile; in other words, Kyua needs to +-- discover tests in such subdirectories automatically. + +syntax(2) + +local directory = fs.dirname(current_kyuafile()) +for file in fs.files(directory) do + if file == "." or file == ".." then + -- Skip these special entries. + else + local kyuafile_relative = fs.join(file, "Kyuafile") + local kyuafile_absolute = fs.join(directory, kyuafile_relative) + if fs.exists(kyuafile_absolute) then + include(kyuafile_relative) + end + end +end diff --git a/external/bsd/kyua-cli/dist/examples/kyua.conf b/external/bsd/kyua-cli/dist/examples/kyua.conf new file mode 100644 index 000000000..e1cd873f2 --- /dev/null +++ b/external/bsd/kyua-cli/dist/examples/kyua.conf @@ -0,0 +1,63 @@ +-- Copyright 2011 Google Inc. +-- All rights reserved. +-- +-- Redistribution and use in source and binary forms, with or without +-- modification, are permitted provided that the following conditions are +-- met: +-- +-- * Redistributions of source code must retain the above copyright +-- notice, this list of conditions and the following disclaimer. +-- * Redistributions in binary form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- * Neither the name of Google Inc. nor the names of its contributors +-- may be used to endorse or promote products derived from this software +-- without specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +-- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +-- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +-- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +-- OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +-- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +-- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +-- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +-- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +-- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +-- Example file for the configuration of Kyua. +-- +-- All the values shown here do not reflect the default values that Kyua +-- is using on this installation: these are just fictitious settings that +-- may or may not work. +-- +-- To write your own configuration file, it is recommended that you start +-- from a blank file and then define only those settings that you want to +-- override. If you want to use this file as a template, you will have +-- to comment out all the settings first to prevent any side-effects. + +-- The file must start by declaring the name and version of its format. +syntax(2) + +-- Name of the system architecture (aka processor type). +architecture = "x86_64" + +-- Name of the system platform (aka machine type). +platform = "amd64" + +-- The name or UID of the unprivileged user. +-- +-- If set, this user must exist in the system and his privileges will be +-- used to run test cases that need regular privileges when Kyua is +-- executed as root. +unprivileged_user = "nobody" + +-- Set fictitious configuration properties for the test suite named 'FreeBSD'. +test_suites.FreeBSD.iterations = "1000" +test_suites.FreeBSD.run_old_tests = "false" + +-- Set fictitious configuration properties for the test suite named 'NetBSD'. +test_suites.NetBSD.file_systems = "ffs lfs ext2fs" +test_suites.NetBSD.iterations = "100" +test_suites.NetBSD.run_broken_tests = "true" diff --git a/external/bsd/kyua-cli/dist/examples/syntax_test.cpp b/external/bsd/kyua-cli/dist/examples/syntax_test.cpp new file mode 100644 index 000000000..79dfe364e --- /dev/null +++ b/external/bsd/kyua-cli/dist/examples/syntax_test.cpp @@ -0,0 +1,186 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +extern "C" { +#include +} + +#include + +#include "engine/config.hpp" +#include "engine/kyuafile.hpp" +#include "utils/config/tree.ipp" +#include "utils/fs/operations.hpp" +#include "utils/fs/path.hpp" +#include "utils/optional.ipp" +#include "utils/passwd.hpp" + +namespace config = utils::config; +namespace fs = utils::fs; +namespace passwd = utils::passwd; + +using utils::none; + + +namespace { + + +/// Gets the path to an example file. +/// +/// \param tc The caller test case. Needed to obtain its 'examplesdir' +/// property, if any. +/// \param name The name of the example file. +/// +/// \return A path to the desired example file. This can either be inside the +/// source tree before installing Kyua or in the target installation directory +/// after installation. +static fs::path +example_file(const atf::tests::tc* tc, const char* name) +{ + const fs::path examplesdir = + tc->has_config_var("examplesdir") ? + fs::path(tc->get_config_var("examplesdir")) : + fs::path(KYUA_EXAMPLESDIR); + return examplesdir / name; +} + + +} // anonymous namespace + + +ATF_TEST_CASE(kyua_conf); +ATF_TEST_CASE_HEAD(kyua_conf) +{ + set_md_var("require.files", example_file(this, "kyua.conf").str()); +} +ATF_TEST_CASE_BODY(kyua_conf) +{ + std::vector< passwd::user > users; + users.push_back(passwd::user("nobody", 1, 2)); + passwd::set_mock_users_for_testing(users); + + const config::tree user_config = engine::load_config( + example_file(this, "kyua.conf")); + + ATF_REQUIRE_EQ( + "x86_64", + user_config.lookup< config::string_node >("architecture")); + ATF_REQUIRE_EQ( + "amd64", + user_config.lookup< config::string_node >("platform")); + + ATF_REQUIRE_EQ( + "nobody", + user_config.lookup< engine::user_node >("unprivileged_user").name); + + config::properties_map exp_test_suites; + exp_test_suites["test_suites.FreeBSD.iterations"] = "1000"; + exp_test_suites["test_suites.FreeBSD.run_old_tests"] = "false"; + exp_test_suites["test_suites.NetBSD.file_systems"] = "ffs lfs ext2fs"; + exp_test_suites["test_suites.NetBSD.iterations"] = "100"; + exp_test_suites["test_suites.NetBSD.run_broken_tests"] = "true"; + ATF_REQUIRE(exp_test_suites == user_config.all_properties("test_suites")); +} + + +ATF_TEST_CASE(kyuafile_top__no_matches); +ATF_TEST_CASE_HEAD(kyuafile_top__no_matches) +{ + set_md_var("require.files", example_file(this, "Kyuafile.top").str()); +} +ATF_TEST_CASE_BODY(kyuafile_top__no_matches) +{ + fs::mkdir(fs::path("root"), 0755); + const fs::path source_path = example_file(this, "Kyuafile.top"); + ATF_REQUIRE(::symlink(source_path.c_str(), "root/Kyuafile") != -1); + + atf::utils::create_file("root/file", ""); + fs::mkdir(fs::path("root/subdir"), 0755); + + const engine::kyuafile kyuafile = engine::kyuafile::load( + fs::path("root/Kyuafile"), none); + ATF_REQUIRE_EQ(fs::path("root"), kyuafile.source_root()); + ATF_REQUIRE_EQ(fs::path("root"), kyuafile.build_root()); + ATF_REQUIRE(kyuafile.test_programs().empty()); +} + + +ATF_TEST_CASE(kyuafile_top__some_matches); +ATF_TEST_CASE_HEAD(kyuafile_top__some_matches) +{ + set_md_var("require.files", example_file(this, "Kyuafile.top").str()); +} +ATF_TEST_CASE_BODY(kyuafile_top__some_matches) +{ + fs::mkdir(fs::path("root"), 0755); + const fs::path source_path = example_file(this, "Kyuafile.top"); + ATF_REQUIRE(::symlink(source_path.c_str(), "root/Kyuafile") != -1); + + atf::utils::create_file("root/file", ""); + + fs::mkdir(fs::path("root/subdir1"), 0755); + atf::utils::create_file("root/subdir1/Kyuafile", + "syntax(2)\n" + "atf_test_program{name='a', test_suite='b'}\n"); + atf::utils::create_file("root/subdir1/a", ""); + + fs::mkdir(fs::path("root/subdir2"), 0755); + atf::utils::create_file("root/subdir2/Kyuafile", + "syntax(2)\n" + "atf_test_program{name='c', test_suite='d'}\n"); + atf::utils::create_file("root/subdir2/c", ""); + atf::utils::create_file("root/subdir2/Kyuafile.etc", "invalid"); + + const engine::kyuafile kyuafile = engine::kyuafile::load( + fs::path("root/Kyuafile"), none); + ATF_REQUIRE_EQ(fs::path("root"), kyuafile.source_root()); + ATF_REQUIRE_EQ(fs::path("root"), kyuafile.build_root()); + + engine::test_program exp_test_program_a( + "atf", fs::path("subdir1/a"), fs::path("root"), "b", + engine::metadata_builder().build()); + engine::test_program exp_test_program_c( + "atf", fs::path("subdir2/c"), fs::path("root"), "d", + engine::metadata_builder().build()); + + ATF_REQUIRE_EQ(2, kyuafile.test_programs().size()); + ATF_REQUIRE((exp_test_program_a == *kyuafile.test_programs()[0] && + exp_test_program_c == *kyuafile.test_programs()[1]) + || + (exp_test_program_a == *kyuafile.test_programs()[1] && + exp_test_program_c == *kyuafile.test_programs()[0])); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, kyua_conf); + + ATF_ADD_TEST_CASE(tcs, kyuafile_top__no_matches); + ATF_ADD_TEST_CASE(tcs, kyuafile_top__some_matches); +} diff --git a/external/bsd/kyua-cli/dist/integration/Kyuafile b/external/bsd/kyua-cli/dist/integration/Kyuafile new file mode 100644 index 000000000..0c3c594ef --- /dev/null +++ b/external/bsd/kyua-cli/dist/integration/Kyuafile @@ -0,0 +1,15 @@ +syntax(2) + +test_suite("kyua") + +atf_test_program{name="cmd_about_test"} +atf_test_program{name="cmd_config_test"} +atf_test_program{name="cmd_db_exec_test"} +atf_test_program{name="cmd_db_migrate_test"} +atf_test_program{name="cmd_debug_test"} +atf_test_program{name="cmd_help_test"} +atf_test_program{name="cmd_list_test"} +atf_test_program{name="cmd_report_html_test"} +atf_test_program{name="cmd_report_test"} +atf_test_program{name="cmd_test_test"} +atf_test_program{name="global_test"} diff --git a/external/bsd/kyua-cli/dist/integration/cmd_about_test.sh b/external/bsd/kyua-cli/dist/integration/cmd_about_test.sh new file mode 100644 index 000000000..736aba280 --- /dev/null +++ b/external/bsd/kyua-cli/dist/integration/cmd_about_test.sh @@ -0,0 +1,151 @@ +# Copyright 2011 Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Google Inc. nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +# Location of installed documents. Used to validate the output of the about +# messages against the golden files. +KYUA_DOCDIR='__KYUA_DOCDIR__' + + +# Common code to validate the output of all about information. +# +# \param file The name of the file with the output. +check_all() { + local file="${1}"; shift + + grep -E 'kyua-cli.*[0-9]+\.[0-9]+' "${file}" || \ + atf_fail 'No version reported' + grep 'Copyright' "${file}" || atf_fail 'No license reported' + grep '<.*@.*>' "${file}" || atf_fail 'No authors reported' + grep 'Homepage' "${file}" || atf_fail 'No homepage reported' +} + + +utils_test_case all_topics__installed +all_topics__installed_head() { + atf_set "require.files" "${KYUA_DOCDIR}/AUTHORS ${KYUA_DOCDIR}/COPYING" +} +all_topics__installed_body() { + atf_check -s exit:0 -o save:stdout -e empty kyua about + check_all stdout +} + + +utils_test_case all_topics__override +all_topics__override_body() { + mkdir docs + echo "Author " >docs/AUTHORS + echo "Copyright text" >docs/COPYING + export KYUA_DOCDIR=docs + atf_check -s exit:0 -o save:stdout -e empty kyua about + check_all stdout +} + + +utils_test_case topic__authors__installed +topic__authors__installed_head() { + atf_set "require.files" "${KYUA_DOCDIR}/AUTHORS" +} +topic__authors__installed_body() { + atf_check -s exit:0 -o file:"${KYUA_DOCDIR}/AUTHORS" -e empty \ + kyua about authors +} + + +utils_test_case topic__authors__override +topic__authors__override_body() { + mkdir docs + echo "Author " >docs/AUTHORS + export KYUA_DOCDIR=docs + atf_check -s exit:0 -o file:docs/AUTHORS -e empty kyua about authors +} + + +utils_test_case topic__license__installed +topic__license__installed_head() { + atf_set "require.files" "${KYUA_DOCDIR}/COPYING" +} +topic__license__installed_body() { + atf_check -s exit:0 -o file:"${KYUA_DOCDIR}/COPYING" -e empty \ + kyua about license +} + + +utils_test_case topic__license__override +topic__license__override_body() { + mkdir docs + echo "Copyright text" >docs/COPYING + export KYUA_DOCDIR=docs + atf_check -s exit:0 -o file:docs/COPYING -e empty kyua about license +} + + +utils_test_case topic__version +topic__version_body() { + atf_check -s exit:0 -o save:stdout -e empty kyua about version + + local lines="$(wc -l stdout | awk '{ print $1 }')" + [ "${lines}" -eq 1 ] || atf_fail "Version query returned more than one line" + + grep '^kyua-cli (.*) [0-9]\.[0-9]$' stdout || \ + atf_fail "Invalid version message" +} + + +utils_test_case topic__invalid +topic__invalid_body() { + cat >experr <stderr <"${HOME}/.kyua/kyua.conf" <expout <"${HOME}/.kyua/kyua.conf" <expout <experr <kyua.conf <kyua.conf <.kyua/kyua.conf <kyua.conf <kyua.conf <experr <"${HOME}/.kyua/kyua.conf" <config <experr <experr <expout <expout2 + atf_check -s exit:0 -o file:expout2 -e empty \ + kyua db-exec --no-headers "SELECT * FROM data ORDER BY a" +} + + +atf_init_test_cases() { + atf_add_test_case one_arg + atf_add_test_case many_args + atf_add_test_case no_args + atf_add_test_case invalid_statement + + atf_add_test_case store_flag__default_home + atf_add_test_case store_flag__explicit__ok + atf_add_test_case store_flag__explicit__fail + + atf_add_test_case no_headers_flag +} diff --git a/external/bsd/kyua-cli/dist/integration/cmd_db_migrate_test.sh b/external/bsd/kyua-cli/dist/integration/cmd_db_migrate_test.sh new file mode 100644 index 000000000..e12df3824 --- /dev/null +++ b/external/bsd/kyua-cli/dist/integration/cmd_db_migrate_test.sh @@ -0,0 +1,107 @@ +# Copyright 2013 Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Google Inc. nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +utils_test_case upgrade +upgrade_head() { + data=$(atf_get_srcdir)/../store + + atf_set require.files "${data}/schema_v1.sql ${data}/testdata_v1.sql" + atf_set require.progs "sqlite3" +} +upgrade_body() { + data=$(atf_get_srcdir)/../store + + mkdir .kyua + cat "${data}/schema_v1.sql" "${data}/testdata_v1.sql" \ + | sqlite3 .kyua/store.db + atf_check -s exit:0 -o empty -e empty kyua db-migrate +} + + +utils_test_case already_up_to_date +already_up_to_date_body() { + atf_check -s exit:0 -o ignore -e empty \ + kyua db-exec "SELECT * FROM metadata" # Create database. + atf_check -s exit:1 -o empty -e match:"already at schema version" \ + kyua db-migrate +} + + +utils_test_case need_upgrade +need_upgrade_head() { + data=$(atf_get_srcdir)/../store + + atf_set require.files "${data}/schema_v1.sql" + atf_set require.progs "sqlite3" +} +need_upgrade_body() { + data=$(atf_get_srcdir)/../store + + mkdir .kyua + sqlite3 .kyua/store.db <"${data}/schema_v1.sql" + atf_check -s exit:2 -o empty \ + -e match:"database has schema version 1.*use db-migrate" kyua report +} + + +utils_test_case store_flag__ok +store_flag__ok_body() { + echo "This is not a valid database" >test.db + atf_check -s exit:1 -o empty -e match:"Migration failed" \ + kyua db-migrate --store ./test.db +} + + +utils_test_case store_flag__fail +store_flag__fail_body() { + atf_check -s exit:1 -o empty -e match:"Cannot open.*test.db" \ + kyua db-migrate --store ./test.db +} + + +utils_test_case too_many_arguments +too_many_arguments_body() { + cat >stderr <Kyuafile <experr <Kyuafile <experr <Kyuafile <expout < passed +EOF +cat >experr <Kyuafile <expout < failed: This fails on purpose +EOF + cat >experr <Kyuafile <experr <experr <experr <Kyuafile <expout < passed +EOF + atf_check -s exit:0 -o file:expout -e empty kyua debug \ + --stdout=saved.out --stderr=saved.err single:with_cleanup + + cat >expout <experr <Kyuafile <expout < passed +EOF + atf_check -s exit:0 -o file:expout -e empty kyua debug \ + --stdout=saved.out --stderr=saved.err second:pass + + cat >expout <experr <root/Kyuafile <root/subdir/Kyuafile <expout < failed: This fails on purpose +EOF + cat >experr <Kyuafile <expout < passed +EOF + cat >experr <"my-config" <Kyuafile <Kyuafile <expout < passed +EOF +cat >experr <Kyuafile <myfile <experr <Kyuafile <experr <' expected near ''. +EOF + atf_check -s exit:2 -o empty -e file:experr kyua debug foo:bar +} + + +utils_test_case bogus_test_program +bogus_test_program_body() { + cat >Kyuafile <non_executable + + cat >experr <experr <expout < broken: Tester did not exit cleanly: kyua-atf-tester: Invalid test cases list header 'This is not a valid test program!' +EOF + atf_check -s exit:1 -o file:expout -e empty kyua debug crash_on_list:__test_cases_list__ + + cat >expout < broken: Tester did not exit cleanly: kyua-atf-tester: execvp failed: Permission denied +EOF + atf_check -s exit:1 -o file:expout -e empty kyua debug non_executable:__test_cases_list__ +} + + +atf_init_test_cases() { + atf_add_test_case no_args + atf_add_test_case many_args + atf_add_test_case one_arg__ok_pass + atf_add_test_case one_arg__ok_fail + atf_add_test_case one_arg__no_match + atf_add_test_case one_arg__no_test_case + atf_add_test_case one_arg__bad_filter + + atf_add_test_case body_and_cleanup + + atf_add_test_case stdout_stderr_flags + + atf_add_test_case args_are_relative + + atf_add_test_case only_load_used_test_programs + + atf_add_test_case config_behavior + + atf_add_test_case build_root_flag + atf_add_test_case kyuafile_flag__ok + atf_add_test_case missing_kyuafile + atf_add_test_case bogus_kyuafile + atf_add_test_case bogus_test_program +} diff --git a/external/bsd/kyua-cli/dist/integration/cmd_help_test.sh b/external/bsd/kyua-cli/dist/integration/cmd_help_test.sh new file mode 100644 index 000000000..00f205a05 --- /dev/null +++ b/external/bsd/kyua-cli/dist/integration/cmd_help_test.sh @@ -0,0 +1,91 @@ +# Copyright 2011 Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Google Inc. nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +utils_test_case global +global_body() { + atf_check -s exit:0 -o save:stdout -e empty kyua help + grep '^Usage: kyua' stdout || atf_fail 'No usage line printed' + grep -- '--loglevel' stdout || atf_fail 'Generic options not printed' + if grep -- '--show' stdout; then + atf_fail 'One option of the about subcommand appeared in the output' + fi + grep 'about *Shows general' stdout || atf_fail 'Commands not printed' +} + + +utils_test_case one_command +one_command_body() { + atf_check -s exit:0 -o save:stdout -e empty kyua help test + grep '^Usage: kyua' stdout || atf_fail 'No usage line printed' + grep '^Run tests' stdout || atf_fail 'No description printed' + grep -- '--loglevel' stdout || atf_fail 'Generic options not printed' + grep -- '--kyuafile' stdout || atf_fail 'Command options not printed' + if grep 'about: Shows general' stdout; then + atf_fail 'Printed table of commands, but should not have done so' + fi +} + + +utils_test_case ignore_bad_config +ignore_bad_config_body() { + echo 'this is an invalid configuration file' >bad-config + atf_check -s exit:0 -o save:stdout -e empty kyua -c bad-config help + grep '^Usage: kyua' stdout || atf_fail 'No usage line printed' + grep -- '--loglevel' stdout || atf_fail 'Generic options not printed' +} + + +utils_test_case unknown_command +unknown_command_body() { + cat >stderr <stderr <Kyuafile <subdir/Kyuafile <expout <Kyuafile <subdir/Kyuafile <expout <Kyuafile <expout <Kyuafile <expout <experr <experr <Kyuafile <subdir/Kyuafile <expout <experr <experr <Kyuafile <experr <Kyuafile <expout <experr <root/Kyuafile <root/subdir/Kyuafile <expout <Kyuafile <expout <Kyuafile <first + utils_cp_helper simple_all_pass build/first + + cat >subdir/Kyuafile <subdir/second + utils_cp_helper simple_some_fail build/subdir/second + + cat >expout <Kyuafile <myfile <expout <Kyuafile <myfile <expout <Kyuafile <subdir/Kyuafile <expout <Kyuafile <experr <Kyuafile <experr <experr <subdir/Kyuafile <experr <subdir/Kyuafile <experr <Kyuafile <experr <' expected near ''. +EOF + atf_check -s exit:2 -o empty -e file:experr kyua list +} + + +utils_test_case bogus_test_program +bogus_test_program_body() { + cat >Kyuafile <non_executable + + cat >expout <Kyuafile <subdir/Kyuafile <subdir/ok + + cat >experr <Kyuafile </dev/null; then + : + else + atf_fail "Test case output not found in HTML page" + fi + shift + done +} + + +# Ensure a file does not have a set of strings. +# +# \param file The name of the file to check. +# \param ... List of strings to check. +check_not_in_file() { + local file="${1}"; shift + + while [ ${#} -gt 0 ]; do + echo "Checking for lack of '${1}' in ${file}" + if grep "${1}" "${file}" >/dev/null; then + atf_fail "Spurious test case output found in HTML page" + fi + shift + done +} + + +utils_test_case default_behavior__ok +default_behavior__ok_body() { + utils_install_timestamp_wrapper + + run_tests "mock1" + + atf_check -s exit:0 -o ignore -e empty kyua report-html + for f in \ + html/index.html \ + html/context.html \ + html/simple_all_pass_pass.html \ + html/simple_all_pass_skip.html \ + html/simple_some_fail_fail.html \ + html/simple_some_fail_pass.html \ + html/metadata_no_properties.html \ + html/metadata_one_property.html \ + html/metadata_many_properties.html \ + html/metadata_with_cleanup.html + do + test -f "${f}" || atf_fail "Missing ${f}" + done + + atf_check -o match:"2 TESTS FAILING" cat html/index.html + + check_in_file html/simple_all_pass_pass.html \ + "This is the stdout of pass" "This is the stderr of pass" + check_not_in_file html/simple_all_pass_pass.html \ + "This is the stdout of skip" "This is the stderr of skip" \ + "This is the stdout of fail" "This is the stderr of fail" \ + "Test case did not write anything to" + + check_in_file html/simple_all_pass_skip.html \ + "This is the stdout of skip" "This is the stderr of skip" + check_not_in_file html/simple_all_pass_skip.html \ + "This is the stdout of pass" "This is the stderr of pass" \ + "This is the stdout of fail" "This is the stderr of fail" \ + "Test case did not write anything to" + + check_in_file html/simple_some_fail_fail.html \ + "This is the stdout of fail" "This is the stderr of fail" + check_not_in_file html/simple_some_fail_fail.html \ + "This is the stdout of pass" "This is the stderr of pass" \ + "This is the stdout of skip" "This is the stderr of skip" \ + "Test case did not write anything to" + + check_in_file html/simple_some_fail_pass.html \ + "Test case did not write anything to stdout" \ + "Test case did not write anything to stderr" + check_not_in_file html/simple_some_fail_pass.html \ + "This is the stdout of pass" "This is the stderr of pass" \ + "This is the stdout of skip" "This is the stderr of skip" \ + "This is the stdout of fail" "This is the stderr of fail" + + check_in_file html/metadata_one_property.html \ + "description = Does nothing but has one metadata property" + check_not_in_file html/metadata_one_property.html \ + "allowed_architectures = some-architecture" + + check_in_file html/metadata_many_properties.html \ + "allowed_architectures = some-architecture" + check_not_in_file html/metadata_many_properties.html \ + "description = Does nothing but has one metadata property" +} + + +utils_test_case default_behavior__no_actions +default_behavior__no_actions_body() { + kyua db-exec "SELECT * FROM actions" + + echo 'kyua: E: No actions in the database.' >experr + atf_check -s exit:2 -o empty -e file:experr kyua report-html +} + + +utils_test_case default_behavior__no_store +default_behavior__no_store_body() { + atf_check -s exit:2 -o empty \ + -e match:"kyua: E: Cannot open '.*/.kyua/store.db': " kyua report-html +} + + +utils_test_case action__explicit +action__explicit_body() { + run_tests "mock1"; action1=$? + run_tests "mock2"; action2=$? + + atf_check -s exit:0 -o ignore -e empty kyua report-html \ + --action="${action1}" + grep "action 1" html/index.html || atf_fail "Invalid action in report" + grep "MOCK.*mock1" html/context.html || atf_fail "Invalid context in report" + + rm -rf html + atf_check -s exit:0 -o ignore -e empty kyua report-html \ + --action="${action2}" + grep "action 2" html/index.html || atf_fail "Invalid action in report" + grep "MOCK.*mock2" html/context.html || atf_fail "Invalid context in report" +} + + +utils_test_case action__not_found +action__not_found_body() { + kyua db-exec "SELECT * FROM actions" + + echo 'kyua: E: Error loading action 514: does not exist.' >experr + atf_check -s exit:2 -o empty -e file:experr kyua report-html --action=514 +} + + +utils_test_case force__yes +force__yes_body() { + run_tests "mock1" + + atf_check -s exit:0 -o ignore -e empty kyua report-html + test -f html/index.html || atf_fail "Expected file not created" + rm html/index.html + atf_check -s exit:0 -o ignore -e empty kyua report-html --force + test -f html/index.html || atf_fail "Expected file not created" +} + + +utils_test_case force__no +force__no_body() { + run_tests "mock1" + + atf_check -s exit:0 -o ignore -e empty kyua report-html + test -f html/index.html || atf_fail "Expected file not created" + rm html/index.html + +cat >experr <Kyuafile <expout < Skipped tests +simple_all_pass:skip -> skipped: The reason for skipping is this [S.UUUs] +===> Summary +Action: 1 +Test cases: 2 total, 1 skipped, 0 expected failures, 0 broken, 0 failed +Total time: S.UUUs +EOF + atf_check -s exit:0 -o file:expout -e empty kyua report + + run_tests "mock2" + + cat >expout < Skipped tests +simple_all_pass:skip -> skipped: The reason for skipping is this [S.UUUs] +===> Summary +Action: 2 +Test cases: 2 total, 1 skipped, 0 expected failures, 0 broken, 0 failed +Total time: S.UUUs +EOF + atf_check -s exit:0 -o file:expout -e empty kyua report +} + + +utils_test_case default_behavior__no_actions +default_behavior__no_actions_body() { + kyua db-exec "SELECT * FROM actions" + + echo 'kyua: E: No actions in the database.' >experr + atf_check -s exit:2 -o empty -e file:experr kyua report +} + + +utils_test_case default_behavior__no_store +default_behavior__no_store_body() { + atf_check -s exit:2 -o empty \ + -e match:"kyua: E: Cannot open '.*/.kyua/store.db': " kyua report +} + + +utils_test_case action__explicit +action__explicit_body() { + run_tests "mock1"; action1=$? + run_tests "mock2"; action2=$? + + atf_check -s exit:0 -o match:"MOCK=mock1" -o not-match:"MOCK=mock2" \ + -o match:"Action: 1" -o not-match:"Action: 2" \ + -e empty kyua report --action="${action1}" --show-context + atf_check -s exit:0 -o not-match:"MOCK=mock1" -o match:"MOCK=mock2" \ + -o match:"Action: 2" -o not-match:"Action: 1" \ + -e empty kyua report --action="${action2}" --show-context +} + + +utils_test_case action__not_found +action__not_found_body() { + kyua db-exec "SELECT * FROM actions" + + echo 'kyua: E: Error loading action 514: does not exist.' >experr + atf_check -s exit:2 -o empty -e file:experr kyua report --action=514 +} + + +utils_test_case show_context +show_context_body() { + run_tests "mock1" + + cat >expout < Execution context +Current directory: $(pwd)/testsuite +Environment variables: +EOF + mkdir testsuite + ( cd testsuite && HOME=$(pwd)/home MOCK=mock1 env ) \ + | sort | sed -e 's,^, ,' | grep -v '^ _.*=.*' >>expout + rmdir testsuite + cat >>expout < Skipped tests +simple_all_pass:skip -> skipped: The reason for skipping is this [S.UUUs] +===> Summary +Action: 1 +Test cases: 2 total, 1 skipped, 0 expected failures, 0 broken, 0 failed +Total time: S.UUUs +EOF + atf_check -s exit:0 -o file:expout -e empty -x kyua report --show-context \ + "| ${utils_strip_timestamp} | grep -v '^ _.*=.*'" +} + + +utils_test_case output__change_file +output__change_file_body() { + run_tests + + cat >report < Skipped tests +simple_all_pass:skip -> skipped: The reason for skipping is this [S.UUUs] +===> Summary +Action: 1 +Test cases: 2 total, 1 skipped, 0 expected failures, 0 broken, 0 failed +Total time: S.UUUs +EOF + + atf_check -s exit:0 -o file:report -e empty -x kyua report \ + --output=/dev/stdout "| ${utils_strip_timestamp}" + atf_check -s exit:0 -o empty -e save:stderr kyua report \ + --output=/dev/stderr + atf_check -s exit:0 -o file:report -x cat stderr \ + "| ${utils_strip_timestamp}" + + atf_check -s exit:0 -o empty -e empty kyua report \ + --output=my-file + atf_check -s exit:0 -o file:report -x cat my-file \ + "| ${utils_strip_timestamp}" +} + + +utils_test_case results_filter__empty +results_filter__empty_body() { + utils_install_timestamp_wrapper + + run_tests "mock1" + + cat >expout < Passed tests +simple_all_pass:pass -> passed [S.UUUs] +===> Skipped tests +simple_all_pass:skip -> skipped: The reason for skipping is this [S.UUUs] +===> Summary +Action: 1 +Test cases: 2 total, 1 skipped, 0 expected failures, 0 broken, 0 failed +Total time: S.UUUs +EOF + atf_check -s exit:0 -o file:expout -e empty kyua report --results-filter= +} + + +utils_test_case results_filter__one +results_filter__one_body() { + utils_install_timestamp_wrapper + + run_tests "mock1" + + cat >expout < Passed tests +simple_all_pass:pass -> passed [S.UUUs] +===> Summary +Action: 1 +Test cases: 2 total, 1 skipped, 0 expected failures, 0 broken, 0 failed +Total time: S.UUUs +EOF + atf_check -s exit:0 -o file:expout -e empty kyua report \ + --results-filter=passed +} + + +utils_test_case results_filter__multiple_all_match +results_filter__multiple_all_match_body() { + utils_install_timestamp_wrapper + + run_tests "mock1" + + cat >expout < Skipped tests +simple_all_pass:skip -> skipped: The reason for skipping is this [S.UUUs] +===> Passed tests +simple_all_pass:pass -> passed [S.UUUs] +===> Summary +Action: 1 +Test cases: 2 total, 1 skipped, 0 expected failures, 0 broken, 0 failed +Total time: S.UUUs +EOF + atf_check -s exit:0 -o file:expout -e empty kyua report \ + --results-filter=skipped,passed +} + + +utils_test_case results_filter__multiple_some_match +results_filter__multiple_some_match_body() { + utils_install_timestamp_wrapper + + run_tests "mock1" + + cat >expout < Skipped tests +simple_all_pass:skip -> skipped: The reason for skipping is this [S.UUUs] +===> Summary +Action: 1 +Test cases: 2 total, 1 skipped, 0 expected failures, 0 broken, 0 failed +Total time: S.UUUs +EOF + atf_check -s exit:0 -o file:expout -e empty kyua report \ + --results-filter=skipped,xfail,broken,failed +} + + +atf_init_test_cases() { + atf_add_test_case default_behavior__ok + atf_add_test_case default_behavior__no_actions + atf_add_test_case default_behavior__no_store + + atf_add_test_case action__explicit + atf_add_test_case action__not_found + + atf_add_test_case show_context + + atf_add_test_case output__change_file + + atf_add_test_case results_filter__empty + atf_add_test_case results_filter__one + atf_add_test_case results_filter__multiple_all_match + atf_add_test_case results_filter__multiple_some_match +} diff --git a/external/bsd/kyua-cli/dist/integration/cmd_test_test.sh b/external/bsd/kyua-cli/dist/integration/cmd_test_test.sh new file mode 100644 index 000000000..3b2d412f6 --- /dev/null +++ b/external/bsd/kyua-cli/dist/integration/cmd_test_test.sh @@ -0,0 +1,993 @@ +# Copyright 2011 Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Google Inc. nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +utils_test_case one_test_program__all_pass +one_test_program__all_pass_body() { + utils_install_timestamp_wrapper + + cat >Kyuafile <expout < passed [S.UUUs] +simple_all_pass:skip -> skipped: The reason for skipping is this [S.UUUs] + +2/2 passed (0 failed) +Committed action 1 +EOF + + utils_cp_helper simple_all_pass . + atf_check -s exit:0 -o file:expout -e empty kyua test +} + + +utils_test_case one_test_program__some_fail +one_test_program__some_fail_body() { + utils_install_timestamp_wrapper + + cat >Kyuafile <expout < failed: This fails on purpose [S.UUUs] +simple_some_fail:pass -> passed [S.UUUs] + +1/2 passed (1 failed) +Committed action 1 +EOF + + utils_cp_helper simple_some_fail . + atf_check -s exit:1 -o file:expout -e empty kyua test +} + + +utils_test_case many_test_programs__all_pass +many_test_programs__all_pass_body() { + utils_install_timestamp_wrapper + + cat >Kyuafile <expout < passed [S.UUUs] +first:skip -> skipped: The reason for skipping is this [S.UUUs] +second:pass -> passed [S.UUUs] +second:skip -> skipped: The reason for skipping is this [S.UUUs] +third:pass -> passed [S.UUUs] +third:skip -> skipped: The reason for skipping is this [S.UUUs] +fourth:main -> skipped: Required file '/non-existent/foo' not found [S.UUUs] + +7/7 passed (0 failed) +Committed action 1 +EOF + + utils_cp_helper simple_all_pass first + utils_cp_helper simple_all_pass second + utils_cp_helper simple_all_pass third + echo "not executed" >fourth; chmod +x fourth + atf_check -s exit:0 -o file:expout -e empty kyua test +} + + +utils_test_case many_test_programs__some_fail +many_test_programs__some_fail_body() { + utils_install_timestamp_wrapper + + cat >Kyuafile <expout < failed: This fails on purpose [S.UUUs] +first:pass -> passed [S.UUUs] +second:fail -> failed: This fails on purpose [S.UUUs] +second:pass -> passed [S.UUUs] +third:pass -> passed [S.UUUs] +third:skip -> skipped: The reason for skipping is this [S.UUUs] +fourth:main -> failed: Returned non-success exit status 76 [S.UUUs] + +4/7 passed (3 failed) +Committed action 1 +EOF + + utils_cp_helper simple_some_fail first + utils_cp_helper simple_some_fail second + utils_cp_helper simple_all_pass third + echo '#! /bin/sh' >fourth + echo 'exit 76' >>fourth + chmod +x fourth + atf_check -s exit:1 -o file:expout -e empty kyua test +} + + +utils_test_case expect__all_pass +expect__all_pass_body() { + utils_install_timestamp_wrapper + + cat >Kyuafile <expout < expected_failure: This is the reason for death [S.UUUs] +expect_all_pass:exit -> expected_failure: Exiting with correct code [S.UUUs] +expect_all_pass:failure -> expected_failure: Oh no: Forced failure [S.UUUs] +expect_all_pass:signal -> expected_failure: Exiting with correct signal [S.UUUs] +expect_all_pass:timeout -> expected_failure: This times out [S.UUUs] + +5/5 passed (0 failed) +Committed action 1 +EOF + + utils_cp_helper expect_all_pass . + atf_check -s exit:0 -o file:expout -e empty kyua test +} + + +utils_test_case expect__some_fail +expect__some_fail_body() { + utils_install_timestamp_wrapper + + cat >Kyuafile <expout < failed: Test case was expected to terminate abruptly but it continued execution [S.UUUs] +expect_some_fail:exit -> failed: Test case expected to exit with code 12 but got code 34 [S.UUUs] +expect_some_fail:failure -> failed: Test case was expecting a failure but none were raised [S.UUUs] +expect_some_fail:pass -> passed [S.UUUs] +expect_some_fail:signal -> failed: Test case expected to receive signal 15 but got 9 [S.UUUs] +expect_some_fail:timeout -> failed: Test case was expected to hang but it continued execution [S.UUUs] + +1/6 passed (5 failed) +Committed action 1 +EOF + + utils_cp_helper expect_some_fail . + atf_check -s exit:1 -o file:expout -e empty kyua test +} + + +utils_test_case premature_exit +premature_exit_body() { + utils_install_timestamp_wrapper + + cat >Kyuafile <expout < broken: Premature exit; test case received signal 9 [S.UUUs] +bogus_test_cases:exit -> broken: Premature exit; test case exited with code 0 [S.UUUs] +bogus_test_cases:pass -> passed [S.UUUs] + +1/3 passed (2 failed) +Committed action 1 +EOF + + utils_cp_helper bogus_test_cases . + atf_check -s exit:1 -o file:expout -e empty kyua test +} + + +utils_test_case no_args +no_args_body() { + utils_install_timestamp_wrapper + + cat >Kyuafile <subdir/Kyuafile <expout < passed [S.UUUs] +simple_all_pass:skip -> skipped: The reason for skipping is this [S.UUUs] +subdir/simple_some_fail:fail -> failed: This fails on purpose [S.UUUs] +subdir/simple_some_fail:pass -> passed [S.UUUs] + +3/4 passed (1 failed) +Committed action 1 +EOF + atf_check -s exit:1 -o file:expout -e empty kyua test +} + + +utils_test_case one_arg__subdir +one_arg__subdir_body() { + utils_install_timestamp_wrapper + + cat >Kyuafile <subdir/Kyuafile <expout < passed [S.UUUs] +subdir/simple_all_pass:skip -> skipped: The reason for skipping is this [S.UUUs] + +2/2 passed (0 failed) +Committed action 1 +EOF + atf_check -s exit:0 -o file:expout -e empty kyua test subdir +} + + +utils_test_case one_arg__test_case +one_arg__test_case_body() { + utils_install_timestamp_wrapper + + cat >Kyuafile <expout < skipped: The reason for skipping is this [S.UUUs] + +1/1 passed (0 failed) +Committed action 1 +EOF + atf_check -s exit:0 -o file:expout -e empty kyua test first:skip +} + + +utils_test_case one_arg__test_program +one_arg__test_program_body() { + utils_install_timestamp_wrapper + + cat >Kyuafile <expout < failed: This fails on purpose [S.UUUs] +second:pass -> passed [S.UUUs] + +1/2 passed (1 failed) +Committed action 1 +EOF + atf_check -s exit:1 -o file:expout -e empty kyua test second +} + + +utils_test_case one_arg__invalid +one_arg__invalid_body() { +cat >experr <experr <Kyuafile <subdir/Kyuafile <expout < failed: This fails on purpose [S.UUUs] +subdir/second:pass -> passed [S.UUUs] +first:pass -> passed [S.UUUs] + +2/3 passed (1 failed) +Committed action 1 +EOF + atf_check -s exit:1 -o file:expout -e empty kyua test subdir first:pass +} + + +utils_test_case many_args__invalid +many_args__invalid_body() { +cat >experr <experr <Kyuafile <expout <experr <Kyuafile <expout < passed [S.UUUs] +first:skip -> skipped: The reason for skipping is this [S.UUUs] +third:fail -> failed: This fails on purpose [S.UUUs] +third:pass -> passed [S.UUUs] + +3/4 passed (1 failed) +Committed action 1 +EOF + + cat >experr <root/Kyuafile <root/subdir/Kyuafile <expout < passed [S.UUUs] +first:skip -> skipped: The reason for skipping is this [S.UUUs] +subdir/fourth:fail -> failed: This fails on purpose [S.UUUs] + +2/3 passed (1 failed) +Committed action 1 +EOF + atf_check -s exit:1 -o file:expout -e empty kyua test \ + -k "$(pwd)/root/Kyuafile" first subdir/fourth:fail +} + + +utils_test_case only_load_used_test_programs +only_load_used_test_programs_body() { + utils_install_timestamp_wrapper + + cat >Kyuafile <expout < passed [S.UUUs] +first:skip -> skipped: The reason for skipping is this [S.UUUs] + +2/2 passed (0 failed) +Committed action 1 +EOF + CREATE_COOKIE="$(pwd)/cookie"; export CREATE_COOKIE + atf_check -s exit:0 -o file:expout -e empty kyua test first + if test -f "${CREATE_COOKIE}"; then + atf_fail "An unmatched test case has been executed, which harms" \ + "performance" + fi +} + + +utils_test_case config_behavior +config_behavior_body() { + cat >"my-config" <Kyuafile <Kyuafile <expout < passed [S.UUUs] +some-program:skip -> skipped: The reason for skipping is this [S.UUUs] + +2/2 passed (0 failed) +Committed action 1 +EOF + + # TODO(jmmv): The tests below should not care about the specific contents of + # the database, but we cannot do better yet. Instead, we should bundle + # these tests with the tests of the future "report" tests so that we can + # actually validate the integration of testing plus reporting. + + atf_check -s exit:0 -o file:expout -e empty kyua test + atf_check -s exit:0 -o inline:'1\n' -e empty \ + kyua db-exec --no-headers "SELECT COUNT(action_id) FROM ACTIONS" + atf_check -s exit:0 -o inline:'1\n' -e empty \ + kyua db-exec --no-headers "SELECT COUNT(context_id) FROM CONTEXTS" + + rm -f some-program + utils_cp_helper simple_some_fail some-program + cat >expout < failed: This fails on purpose [S.UUUs] +some-program:pass -> passed [S.UUUs] + +1/2 passed (1 failed) +Committed action 2 +EOF + + atf_check -s exit:1 -o file:expout -e empty kyua test + atf_check -s exit:0 -o inline:'2\n' -e empty \ + kyua db-exec --no-headers "SELECT COUNT(action_id) FROM ACTIONS" + atf_check -s exit:0 -o inline:'2\n' -e empty \ + kyua db-exec --no-headers "SELECT COUNT(context_id) FROM CONTEXTS" + +cat >expout <Kyuafile <Kyuafile <Kyuafile <subdir/Kyuafile <expout < passed [S.UUUs] +first:skip -> skipped: The reason for skipping is this [S.UUUs] +subdir/second:pass -> passed [S.UUUs] +subdir/second:skip -> skipped: The reason for skipping is this [S.UUUs] +subdir/third:pass -> passed [S.UUUs] +subdir/third:skip -> skipped: The reason for skipping is this [S.UUUs] + +6/6 passed (0 failed) +Committed action 1 +EOF + + mkdir build + mkdir build/subdir + utils_cp_helper simple_all_pass build/first + utils_cp_helper simple_all_pass build/subdir/second + utils_cp_helper simple_all_pass build/subdir/third + + atf_check -s exit:0 -o file:expout -e empty kyua test --build-root=build +} + + +utils_test_case kyuafile_flag__no_args +kyuafile_flag__no_args_body() { + utils_install_timestamp_wrapper + + cat >Kyuafile <myfile <expout < passed [S.UUUs] +sometest:skip -> skipped: The reason for skipping is this [S.UUUs] + +2/2 passed (0 failed) +Committed action 1 +EOF + atf_check -s exit:0 -o file:expout -e empty kyua test -k myfile + cat >expout < passed [S.UUUs] +sometest:skip -> skipped: The reason for skipping is this [S.UUUs] + +2/2 passed (0 failed) +Committed action 2 +EOF + atf_check -s exit:0 -o file:expout -e empty kyua test --kyuafile=myfile +} + + +utils_test_case kyuafile_flag__some_args +kyuafile_flag__some_args_body() { + utils_install_timestamp_wrapper + + cat >Kyuafile <myfile <expout < passed [S.UUUs] +sometest:skip -> skipped: The reason for skipping is this [S.UUUs] + +2/2 passed (0 failed) +Committed action 1 +EOF + atf_check -s exit:0 -o file:expout -e empty kyua test -k myfile sometest + cat >expout < passed [S.UUUs] +sometest:skip -> skipped: The reason for skipping is this [S.UUUs] + +2/2 passed (0 failed) +Committed action 2 +EOF + atf_check -s exit:0 -o file:expout -e empty kyua test --kyuafile=myfile \ + sometest +} + + +utils_test_case interrupt +interrupt_body() { + cat >Kyuafile <stdout 2>stderr & + pid=${!} + echo "Kyua subprocess is PID ${pid}" + + while [ ! -f body ]; do + echo "Waiting for body to start" + sleep 1 + done + echo "Body started" + sleep 1 + + echo "Sending INT signal to ${pid}" + kill -INT ${pid} + echo "Waiting for process ${pid} to exit" + wait ${pid} + ret=${?} + sed -e 's,^,kyua stdout:,' stdout + sed -e 's,^,kyua stderr:,' stderr + echo "Process ${pid} exited" + [ ${ret} -ne 0 ] || atf_fail 'No error code reported' + + [ -f cleanup ] || atf_fail 'Cleanup part not executed after signal' + + atf_check -s exit:0 -o ignore -e empty grep 'Signal caught' stderr + atf_check -s exit:0 -o ignore -e empty \ + grep 'kyua: E: Interrupted by signal' stderr +} + + +utils_test_case no_test_program_match +no_test_program_match_body() { + cat >Kyuafile <expout <experr <Kyuafile <expout <experr <experr <subdir/Kyuafile <experr <subdir/Kyuafile <experr <"${HOME}/.kyua/kyua.conf" <Kyuafile <experr <' expected near ''. +EOF + atf_check -s exit:2 -o empty -e file:experr kyua test +} + + +utils_test_case bogus_test_program +bogus_test_program_body() { + utils_install_timestamp_wrapper + + cat >Kyuafile <non_executable + + cat >expout < broken: Tester did not exit cleanly: kyua-atf-tester: Invalid test cases list header 'This is not a valid test program!' [S.UUUs] +non_executable:__test_cases_list__ -> broken: Tester did not exit cleanly: kyua-atf-tester: execvp failed: Permission denied [S.UUUs] + +0/2 passed (2 failed) +Committed action 1 +EOF + atf_check -s exit:1 -o file:expout -e empty kyua test +} + + +utils_test_case missing_test_program +missing_test_program_body() { + cat >Kyuafile <subdir/Kyuafile <subdir/ok + + cat >experr <experr <experr <experr < +#include +#include +#include + + +int +main(void) +{ + std::cerr << "This is not a valid test program!\n"; + + const char* cookie = std::getenv("CREATE_COOKIE"); + if (cookie != NULL && std::strlen(cookie) > 0) { + std::ofstream file(cookie); + if (!file) + std::abort(); + file << "Cookie file\n"; + file.close(); + } + + return EXIT_SUCCESS; +} diff --git a/external/bsd/kyua-cli/dist/integration/helpers/bogus_test_cases.cpp b/external/bsd/kyua-cli/dist/integration/helpers/bogus_test_cases.cpp new file mode 100644 index 000000000..41a0e5136 --- /dev/null +++ b/external/bsd/kyua-cli/dist/integration/helpers/bogus_test_cases.cpp @@ -0,0 +1,64 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +extern "C" { +#include +#include +} + +#include + +#include + + +ATF_TEST_CASE_WITHOUT_HEAD(die); +ATF_TEST_CASE_BODY(die) +{ + ::kill(::getpid(), SIGKILL); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(exit); +ATF_TEST_CASE_BODY(exit) +{ + std::exit(EXIT_SUCCESS); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(pass); +ATF_TEST_CASE_BODY(pass) +{ +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, die); + ATF_ADD_TEST_CASE(tcs, exit); + ATF_ADD_TEST_CASE(tcs, pass); +} diff --git a/external/bsd/kyua-cli/dist/integration/helpers/config.cpp b/external/bsd/kyua-cli/dist/integration/helpers/config.cpp new file mode 100644 index 000000000..6d09324c2 --- /dev/null +++ b/external/bsd/kyua-cli/dist/integration/helpers/config.cpp @@ -0,0 +1,46 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include + + +ATF_TEST_CASE(get_variable); +ATF_TEST_CASE_HEAD(get_variable) +{ + set_md_var("require.config", "X-the-variable"); +} +ATF_TEST_CASE_BODY(get_variable) +{ + ATF_REQUIRE_EQ("value2", get_config_var("X-the-variable")); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, get_variable); +} diff --git a/external/bsd/kyua-cli/dist/integration/helpers/expect_all_pass.cpp b/external/bsd/kyua-cli/dist/integration/helpers/expect_all_pass.cpp new file mode 100644 index 000000000..0faf4d83a --- /dev/null +++ b/external/bsd/kyua-cli/dist/integration/helpers/expect_all_pass.cpp @@ -0,0 +1,90 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +extern "C" { +#include +#include +} + +#include + +#include + + +ATF_TEST_CASE_WITHOUT_HEAD(die); +ATF_TEST_CASE_BODY(die) +{ + expect_death("This is the reason for death"); + std::abort(); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(exit); +ATF_TEST_CASE_BODY(exit) +{ + expect_exit(12, "Exiting with correct code"); + std::exit(12); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(failure); +ATF_TEST_CASE_BODY(failure) +{ + expect_fail("Oh no"); + fail("Forced failure"); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(signal); +ATF_TEST_CASE_BODY(signal) +{ + expect_signal(SIGTERM, "Exiting with correct signal"); + ::kill(::getpid(), SIGTERM); +} + + +ATF_TEST_CASE(timeout); +ATF_TEST_CASE_HEAD(timeout) +{ + set_md_var("timeout", "1"); +} +ATF_TEST_CASE_BODY(timeout) +{ + expect_timeout("This times out"); + ::sleep(10); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, die); + ATF_ADD_TEST_CASE(tcs, exit); + ATF_ADD_TEST_CASE(tcs, failure); + ATF_ADD_TEST_CASE(tcs, signal); + ATF_ADD_TEST_CASE(tcs, timeout); +} diff --git a/external/bsd/kyua-cli/dist/integration/helpers/expect_some_fail.cpp b/external/bsd/kyua-cli/dist/integration/helpers/expect_some_fail.cpp new file mode 100644 index 000000000..a1960c4e6 --- /dev/null +++ b/external/bsd/kyua-cli/dist/integration/helpers/expect_some_fail.cpp @@ -0,0 +1,94 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +extern "C" { +#include +#include +} + +#include + +#include + + +ATF_TEST_CASE_WITHOUT_HEAD(die); +ATF_TEST_CASE_BODY(die) +{ + expect_death("Won't die"); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(exit); +ATF_TEST_CASE_BODY(exit) +{ + expect_exit(12, "Invalid exit code"); + std::exit(34); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(failure); +ATF_TEST_CASE_BODY(failure) +{ + expect_fail("Does not fail"); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(pass); +ATF_TEST_CASE_BODY(pass) +{ +} + + +ATF_TEST_CASE_WITHOUT_HEAD(signal); +ATF_TEST_CASE_BODY(signal) +{ + expect_signal(SIGTERM, "Invalid signal"); + ::kill(::getpid(), SIGKILL); +} + + +ATF_TEST_CASE(timeout); +ATF_TEST_CASE_HEAD(timeout) +{ + set_md_var("timeout", "1"); +} +ATF_TEST_CASE_BODY(timeout) +{ + expect_timeout("Does not time out"); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, die); + ATF_ADD_TEST_CASE(tcs, exit); + ATF_ADD_TEST_CASE(tcs, failure); + ATF_ADD_TEST_CASE(tcs, pass); + ATF_ADD_TEST_CASE(tcs, signal); + ATF_ADD_TEST_CASE(tcs, timeout); +} diff --git a/external/bsd/kyua-cli/dist/integration/helpers/interrupts.cpp b/external/bsd/kyua-cli/dist/integration/helpers/interrupts.cpp new file mode 100644 index 000000000..49fecc13a --- /dev/null +++ b/external/bsd/kyua-cli/dist/integration/helpers/interrupts.cpp @@ -0,0 +1,62 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +extern "C" { +#include +} + +#include + +#include + + +ATF_TEST_CASE_WITH_CLEANUP(block_body); +ATF_TEST_CASE_HEAD(block_body) +{ + set_md_var("require.config", "X-body-cookie X-cleanup-cookie"); +} +ATF_TEST_CASE_BODY(block_body) +{ + const std::string cookie(get_config_var("X-body-cookie")); + std::ofstream output(cookie.c_str()); + output.close(); + for (;;) + ::pause(); +} +ATF_TEST_CASE_CLEANUP(block_body) +{ + const std::string cookie(get_config_var("X-cleanup-cookie")); + std::ofstream output(cookie.c_str()); + output.close(); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, block_body); +} diff --git a/external/bsd/kyua-cli/dist/integration/helpers/metadata.cpp b/external/bsd/kyua-cli/dist/integration/helpers/metadata.cpp new file mode 100644 index 000000000..3e37d4173 --- /dev/null +++ b/external/bsd/kyua-cli/dist/integration/helpers/metadata.cpp @@ -0,0 +1,93 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include +#include + +#include + + +ATF_TEST_CASE_WITHOUT_HEAD(no_properties); +ATF_TEST_CASE_BODY(no_properties) +{ +} + + +ATF_TEST_CASE(one_property); +ATF_TEST_CASE_HEAD(one_property) +{ + set_md_var("descr", "Does nothing but has one metadata property"); +} +ATF_TEST_CASE_BODY(one_property) +{ + std::abort(); +} + + +ATF_TEST_CASE(many_properties); +ATF_TEST_CASE_HEAD(many_properties) +{ + set_md_var("descr", " A description with some padding"); + set_md_var("require.arch", "some-architecture"); + set_md_var("require.config", "var1 var2 var3"); + set_md_var("require.files", "/my/file1 /some/other/file"); + set_md_var("require.machine", "some-platform"); + set_md_var("require.progs", "bin1 bin2 /nonexistent/bin3"); + set_md_var("require.user", "root"); + set_md_var("X-no-meaning", "I am a custom variable"); +} +ATF_TEST_CASE_BODY(many_properties) +{ + std::abort(); +} + + +ATF_TEST_CASE_WITH_CLEANUP(with_cleanup); +ATF_TEST_CASE_HEAD(with_cleanup) +{ + set_md_var("timeout", "250"); +} +ATF_TEST_CASE_BODY(with_cleanup) +{ + std::cout << "Body message to stdout\n"; + std::cerr << "Body message to stderr\n"; +} +ATF_TEST_CASE_CLEANUP(with_cleanup) +{ + std::cout << "Cleanup message to stdout\n"; + std::cerr << "Cleanup message to stderr\n"; +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, no_properties); + ATF_ADD_TEST_CASE(tcs, one_property); + ATF_ADD_TEST_CASE(tcs, many_properties); + ATF_ADD_TEST_CASE(tcs, with_cleanup); +} diff --git a/external/bsd/kyua-cli/dist/integration/helpers/simple_all_pass.cpp b/external/bsd/kyua-cli/dist/integration/helpers/simple_all_pass.cpp new file mode 100644 index 000000000..85a27f7b1 --- /dev/null +++ b/external/bsd/kyua-cli/dist/integration/helpers/simple_all_pass.cpp @@ -0,0 +1,55 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include + +#include + + +ATF_TEST_CASE_WITHOUT_HEAD(pass); +ATF_TEST_CASE_BODY(pass) +{ + std::cout << "This is the stdout of pass\n"; + std::cerr << "This is the stderr of pass\n"; +} + + +ATF_TEST_CASE_WITHOUT_HEAD(skip); +ATF_TEST_CASE_BODY(skip) +{ + std::cout << "This is the stdout of skip\n"; + std::cerr << "This is the stderr of skip\n"; + skip("The reason for skipping is this"); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, pass); + ATF_ADD_TEST_CASE(tcs, skip); +} diff --git a/external/bsd/kyua-cli/dist/integration/helpers/simple_some_fail.cpp b/external/bsd/kyua-cli/dist/integration/helpers/simple_some_fail.cpp new file mode 100644 index 000000000..fe450faed --- /dev/null +++ b/external/bsd/kyua-cli/dist/integration/helpers/simple_some_fail.cpp @@ -0,0 +1,53 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include + +#include + + +ATF_TEST_CASE_WITHOUT_HEAD(fail); +ATF_TEST_CASE_BODY(fail) +{ + std::cout << "This is the stdout of fail\n"; + std::cerr << "This is the stderr of fail\n"; + fail("This fails on purpose"); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(pass); +ATF_TEST_CASE_BODY(pass) +{ +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, fail); + ATF_ADD_TEST_CASE(tcs, pass); +} diff --git a/external/bsd/kyua-cli/dist/integration/utils.sh b/external/bsd/kyua-cli/dist/integration/utils.sh new file mode 100644 index 000000000..95f6ecd22 --- /dev/null +++ b/external/bsd/kyua-cli/dist/integration/utils.sh @@ -0,0 +1,85 @@ +# Copyright 2011 Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Google Inc. nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +# Subcommand to strip the timestamps of a report. +# +# This is to make the reports deterministic and thus easily testable. The +# timestamps are replaced by the fixed string S.UUUs. +# +# This variable should be used as shown here: +# +# atf_check ... -x kyua report "| ${uilts_strip_timestamp}" +utils_strip_timestamp='sed -e "s,[0-9][0-9]*.[0-9][0-9][0-9]s,S.UUUs,g"' + + +# Copies a helper binary from the source directory to the work directory. +# +# \param name The name of the binary to copy. +# \param destination The target location for the binary; can be either +# a directory name or a file name. +utils_cp_helper() { + local name="${1}"; shift + local destination="${1}"; shift + + ln -s "$(atf_get_srcdir)"/helpers/"${name}" "${destination}" +} + + +# Creates a 'kyua' binary in the path that strips timestamps off the output. +# +# Call this on test cases that wish to replace timestamps in the *stdout* of +# Kyua with the S.UUUs deterministic string. This is usable for tests that +# validate the 'test' subcommand, but also by a few specific tests for the +# 'report' subcommand. +utils_install_timestamp_wrapper() { + [ ! -x kyua ] || return + cat >kyua <kyua.tmpout +result=\${?} +cat kyua.tmpout | ${utils_strip_timestamp} +exit \${result} +EOF + chmod +x kyua + PATH="$(pwd):${PATH}" +} + + +# Defines a test case with a default head. +utils_test_case() { + local name="${1}"; shift + + atf_test_case "${name}" + eval "${name}_head() { + atf_set require.progs kyua + }" +} diff --git a/external/bsd/kyua-cli/dist/main.cpp b/external/bsd/kyua-cli/dist/main.cpp new file mode 100644 index 000000000..cb3ca0bad --- /dev/null +++ b/external/bsd/kyua-cli/dist/main.cpp @@ -0,0 +1,50 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "cli/main.hpp" + + +/// Program entry point. +/// +/// The whole purpose of this extremely-simple function is to delegate execution +/// to an internal module that does not contain a proper ::main() function. +/// This is to allow unit-testing of the internal code. +/// +/// \param argc The number of arguments passed on the command line. +/// \param argv NULL-terminated array containing the command line arguments. +/// +/// \return 0 on success, some other integer on error. +/// +/// \throw std::exception This throws any uncaught exception. Such exceptions +/// are bugs, but we let them propagate so that the runtime will abort and +/// dump core. +int +main(const int argc, const char* const* const argv) +{ + return cli::main(argc, argv); +} diff --git a/external/bsd/kyua-cli/dist/misc/context.html b/external/bsd/kyua-cli/dist/misc/context.html new file mode 100644 index 000000000..8b3589230 --- /dev/null +++ b/external/bsd/kyua-cli/dist/misc/context.html @@ -0,0 +1,55 @@ + + + + + Execution context for action %%action_id%% + + + + + +

    Execution context for action %%action_id%%

    + +
      +
    • Work directory: %%cwd%%
    • +
    + +

    Environment variables

    + +
      +%loop env_var iter +
    • %%env_var(iter)%%: %%env_var_value(iter)%%
    • +%endloop +
    + + + diff --git a/external/bsd/kyua-cli/dist/misc/index.html b/external/bsd/kyua-cli/dist/misc/index.html new file mode 100644 index 000000000..5e590a5af --- /dev/null +++ b/external/bsd/kyua-cli/dist/misc/index.html @@ -0,0 +1,179 @@ + + + + + + Tests summary + + + + + + +

    Summary for test action %%action_id%%

    + +

    Overall result: +%if bad_tests_count + %%bad_tests_count%% TESTS FAILING +%else + ALL TESTS PASSING +%endif +

    + + + + + + + + + + +%if length(broken_test_cases) + + + + +%else + + + + +%endif +%if length(failed_test_cases) + + + + +%else + + + + +%endif + +%if length(xfail_test_cases) + +%else + +%endif + + + +%if length(skipped_test_cases) + +%else + +%endif + + + +%if length(passed_test_cases) + +%else + +%endif + + + +
    Test case resultCount
    Broken%%length(broken_test_cases)%%
    Broken%%length(broken_test_cases)%%
    Failed%%length(failed_test_cases)%%
    Failed%%length(failed_test_cases)%%
    Expected failuresExpected failures%%length(xfail_test_cases)%%
    SkippedSkipped%%length(skipped_test_cases)%%
    PassedPassed%%length(passed_test_cases)%%
    + +

    Execution context

    + + +%if length(broken_test_cases) +

    Broken test cases

    + + +%endif + + +%if length(failed_test_cases) +

    Failed test cases

    + + +%endif + + +%if length(xfail_test_cases) +

    Expected failures

    + + +%endif + + +%if length(skipped_test_cases) +

    Skipped test cases

    + + +%endif + + +%if length(passed_test_cases) +

    Passed test cases

    + + +%endif + + + + diff --git a/external/bsd/kyua-cli/dist/misc/report.css b/external/bsd/kyua-cli/dist/misc/report.css new file mode 100644 index 000000000..55a39e847 --- /dev/null +++ b/external/bsd/kyua-cli/dist/misc/report.css @@ -0,0 +1,78 @@ +/* Copyright 2012 Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Google Inc. nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +body { + background: white; + text-color: black; +} + +h1 { + color: #00d000; +} + +h2 { + color: #00a000; +} + +p.overall font.good { + color: #00ff00; +} + +p.overall font.bad { + color: #ff0000; +} + +pre { + background-color: #e0f0e0; + margin-left: 20px; + margin-right: 20px; + padding: 5px; +} + +table.tests-count { + border-width: 1; + border-style: solid; + border-color: #b0e0b0; + padding: 0; +} + +table.tests-count td { + padding: 3px; +} + +table.tests-count td.numeric { + text-align: right; +} + +table.tests-count tr.bad { + background: #e0b0b0; +} + +table.tests-count thead tr { + background: #b0e0b0; +} diff --git a/external/bsd/kyua-cli/dist/misc/test_result.html b/external/bsd/kyua-cli/dist/misc/test_result.html new file mode 100644 index 000000000..a44f3d970 --- /dev/null +++ b/external/bsd/kyua-cli/dist/misc/test_result.html @@ -0,0 +1,74 @@ + + + + + Test case: %%test_case%% + + + + + +

    Test case: %%test_case%%

    + +
      +
    • Test program: %%test_program%%
    • +
    • Result: %%result%%
    • +
    • Duration: %%duration%%
    • +
    • Execution context
    • +
    + +

    Metadata

    + +
      +%loop metadata_var iter +
    • %%metadata_var(iter)%% = %%metadata_value(iter)%%
    • +%endloop +
    + +

    Standard output

    + +%if defined(stdout) +
    %%stdout%%
    +%else +Test case did not write anything to stdout. +%endif + +

    Standard error

    + +%if defined(stderr) +
    %%stderr%%
    +%else +Test case did not write anything to stderr. +%endif + + + diff --git a/external/bsd/kyua-cli/dist/store/Kyuafile b/external/bsd/kyua-cli/dist/store/Kyuafile new file mode 100644 index 000000000..689ce7b1b --- /dev/null +++ b/external/bsd/kyua-cli/dist/store/Kyuafile @@ -0,0 +1,10 @@ +syntax(2) + +test_suite("kyua") + +atf_test_program{name="backend_test"} +atf_test_program{name="dbtypes_test"} +atf_test_program{name="exceptions_test"} +atf_test_program{name="metadata_test"} +atf_test_program{name="schema_inttest"} +atf_test_program{name="transaction_test"} diff --git a/external/bsd/kyua-cli/dist/store/backend.cpp b/external/bsd/kyua-cli/dist/store/backend.cpp new file mode 100644 index 000000000..48f8e293b --- /dev/null +++ b/external/bsd/kyua-cli/dist/store/backend.cpp @@ -0,0 +1,374 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "store/backend.hpp" + +#include + +#include "store/exceptions.hpp" +#include "store/metadata.hpp" +#include "store/transaction.hpp" +#include "utils/env.hpp" +#include "utils/format/macros.hpp" +#include "utils/logging/macros.hpp" +#include "utils/sanity.hpp" +#include "utils/stream.hpp" +#include "utils/sqlite/database.hpp" +#include "utils/sqlite/exceptions.hpp" +#include "utils/sqlite/statement.ipp" + +namespace fs = utils::fs; +namespace sqlite = utils::sqlite; + + +/// The current schema version. +/// +/// Any new database gets this schema version. Existing databases with an older +/// schema version must be first migrated to the current schema with +/// migrate_schema() before they can be used. +/// +/// This must be kept in sync with the value in the corresponding schema_vX.sql +/// file, where X matches this version number. +/// +/// This variable is not const to allow tests to modify it. No other code +/// should change its value. +int store::detail::current_schema_version = 2; + + +namespace { + + +/// Opens a database and defines session pragmas. +/// +/// This auxiliary function ensures that, every time we open a SQLite database, +/// we define the same set of pragmas for it. +/// +/// \param file The database file to be opened. +/// \param flags The flags for the open; see sqlite::database::open. +/// +/// \return The opened database. +/// +/// \throw store::error If there is a problem opening or creating the database. +static sqlite::database +do_open(const fs::path& file, const int flags) +{ + try { + sqlite::database database = sqlite::database::open(file, flags); + database.exec("PRAGMA foreign_keys = ON"); + return database; + } catch (const sqlite::error& e) { + throw store::error(F("Cannot open '%s': %s") % file % e.what()); + } +} + + +/// Checks if a database is empty (i.e. if it is new). +/// +/// \param db The database to check. +/// +/// \return True if the database is empty. +static bool +empty_database(sqlite::database& db) +{ + sqlite::statement stmt = db.create_statement("SELECT * FROM sqlite_master"); + return !stmt.step(); +} + + +/// Performs a single migration step. +/// +/// \param db Open database to which to apply the migration step. +/// \param version_from Current schema version in the database. +/// \param version_to Schema version to migrate to. +/// +/// \throw error If there is a problem applying the migration. +static void +migrate_schema_step(sqlite::database& db, const int version_from, + const int version_to) +{ + PRE(version_to == version_from + 1); + + const fs::path migration = store::detail::migration_file(version_from, + version_to); + + std::ifstream input(migration.c_str()); + if (!input) + throw store::error(F("Cannot open migration file '%s'") % migration); + + const std::string migration_string = utils::read_stream(input); + try { + db.exec(migration_string); + } catch (const sqlite::error& e) { + throw store::error(F("Schema migration failed: %s") % e.what()); + } +} + + +} // anonymous namespace + + +/// Calculates the path to a schema migration file. +/// +/// \param version_from The version from which the database is being upgraded. +/// \param version_to The version to which the database is being upgraded. +/// +/// \return The path to the installed migrate_vX_vY.sql file. +fs::path +store::detail::migration_file(const int version_from, const int version_to) +{ + return fs::path(utils::getenv_with_default("KYUA_STOREDIR", KYUA_STOREDIR)) + / (F("migrate_v%s_v%s.sql") % version_from % version_to); +} + + +/// Calculates the path to the schema file for the database. +/// +/// \return The path to the installed schema_vX.sql file that matches the +/// current_schema_version. +fs::path +store::detail::schema_file(void) +{ + return fs::path(utils::getenv_with_default("KYUA_STOREDIR", KYUA_STOREDIR)) + / (F("schema_v%s.sql") % current_schema_version); +} + + +/// Initializes an empty database. +/// +/// \param db The database to initialize. +/// +/// \return The metadata record written into the new database. +/// +/// \throw store::error If there is a problem initializing the database. +store::metadata +store::detail::initialize(sqlite::database& db) +{ + PRE(empty_database(db)); + + const fs::path schema = schema_file(); + + std::ifstream input(schema.c_str()); + if (!input) + throw error(F("Cannot open database schema '%s'") % schema); + + LI(F("Populating new database with schema from %s") % schema); + const std::string schema_string = utils::read_stream(input); + try { + db.exec(schema_string); + + const metadata metadata = metadata::fetch_latest(db); + LI(F("New metadata entry %s") % metadata.timestamp()); + if (metadata.schema_version() != detail::current_schema_version) { + UNREACHABLE_MSG(F("current_schema_version is out of sync with " + "%s") % schema); + } + return metadata; + } catch (const store::integrity_error& e) { + // Could be raised by metadata::fetch_latest. + UNREACHABLE_MSG("Inconsistent code while creating a database"); + } catch (const sqlite::error& e) { + throw error(F("Failed to initialize database: %s") % e.what()); + } +} + + +/// Backs up a database for schema migration purposes. +/// +/// \todo We should probably use the SQLite backup API instead of doing a raw +/// file copy. We issue our backup call with the database already open, but +/// because it is quiescent, it's OK to do so. +/// +/// \param source Location of the database to be backed up. +/// \param old_version Version of the database's CURRENT schema, used to +/// determine the name of the backup file. +/// +/// \throw error If there is a problem during the backup. +void +store::detail::backup_database(const fs::path& source, const int old_version) +{ + const fs::path target(F("%s.v%s.backup") % source.str() % old_version); + + LI(F("Backing up database %s to %s") % source % target); + + std::ifstream input(source.c_str()); + if (!input) + throw error(F("Cannot open database file %s") % source); + + std::ofstream output(target.c_str()); + if (!output) + throw error(F("Cannot create database backup file %s") % target); + + char buffer[1024]; + while (input.good()) { + input.read(buffer, sizeof(buffer)); + if (input.good() || input.eof()) + output.write(buffer, input.gcount()); + } + if (!input.good() && !input.eof()) + throw error(F("Error while reading input file %s") % source); +} + + +/// Internal implementation for the backend. +struct store::backend::impl { + /// The SQLite database this backend talks to. + sqlite::database database; + + /// Constructor. + /// + /// \param database_ The SQLite database instance. + /// \param metadata_ The metadata for the loaded database. This must match + /// the schema version we implement in this module; otherwise, a + /// migration is necessary. + /// + /// \throw integrity_error If the schema in the database is too modern, + /// which might indicate some form of corruption or an old binary. + /// \throw old_schema_error If the schema in the database is older than our + /// currently-implemented version and needs an upgrade. The caller can + /// use migrate_schema() to fix this problem. + impl(sqlite::database& database_, const metadata& metadata_) : + database(database_) + { + const int database_version = metadata_.schema_version(); + + if (database_version == detail::current_schema_version) { + // OK. + } else if (database_version < detail::current_schema_version) { + throw old_schema_error(database_version); + } else if (database_version > detail::current_schema_version) { + throw integrity_error( + F("Database at schema version %s, which is newer than the " + "supported version %s") + % database_version % detail::current_schema_version); + } + } +}; + + +/// Constructs a new backend. +/// +/// \param pimpl_ The internal data. +store::backend::backend(impl* pimpl_) : + _pimpl(pimpl_) +{ +} + + +/// Destructor. +store::backend::~backend(void) +{ +} + + +/// Opens a database in read-only mode. +/// +/// \param file The database file to be opened. +/// +/// \return The backend representation. +/// +/// \throw store::error If there is any problem opening the database. +store::backend +store::backend::open_ro(const fs::path& file) +{ + sqlite::database db = do_open(file, sqlite::open_readonly); + return backend(new impl(db, metadata::fetch_latest(db))); +} + + +/// Opens a database in read-write mode and creates it if necessary. +/// +/// \param file The database file to be opened. +/// +/// \return The backend representation. +/// +/// \throw store::error If there is any problem opening or creating +/// the database. +store::backend +store::backend::open_rw(const fs::path& file) +{ + sqlite::database db = do_open(file, sqlite::open_readwrite | + sqlite::open_create); + if (empty_database(db)) + return backend(new impl(db, detail::initialize(db))); + else + return backend(new impl(db, metadata::fetch_latest(db))); +} + + +/// Gets the connection to the SQLite database. +/// +/// \return A database connection. +sqlite::database& +store::backend::database(void) +{ + return _pimpl->database; +} + + +/// Opens a transaction. +/// +/// \return A new transaction. +store::transaction +store::backend::start(void) +{ + return transaction(*this); +} + + +/// Migrates the schema of a database to the current version. +/// +/// The algorithm implemented here performs a migration step for every +/// intermediate version between the schema version in the database to the +/// version implemented in this file. This should permit upgrades from +/// arbitrary old databases. +/// +/// \param file The database whose schema to upgrade. +/// +/// \throw error If there is a problem with the migration. +void +store::migrate_schema(const utils::fs::path& file) +{ + sqlite::database db = do_open(file, sqlite::open_readwrite); + + const int version_from = metadata::fetch_latest(db).schema_version(); + const int version_to = detail::current_schema_version; + if (version_from == version_to) { + throw error(F("Database already at schema version %s; migration not " + "needed") % version_from); + } else if (version_from > version_to) { + throw error(F("Database at schema version %s, which is newer than the " + "supported version %s") % version_from % version_to); + } + + detail::backup_database(file, version_from); + + for (int i = version_from; i < version_to; ++i) { + LI(F("Migrating schema from version %s to %s") % i % (i + 1)); + migrate_schema_step(db, i, i + 1); + } +} diff --git a/external/bsd/kyua-cli/dist/store/backend.hpp b/external/bsd/kyua-cli/dist/store/backend.hpp new file mode 100644 index 000000000..e5da4de0a --- /dev/null +++ b/external/bsd/kyua-cli/dist/store/backend.hpp @@ -0,0 +1,97 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file store/backend.hpp +/// Interface to the backend database. + +#if !defined(STORE_BACKEND_HPP) +#define STORE_BACKEND_HPP + +#include + +namespace utils { +namespace fs { +class path; +} // namespace fs +namespace sqlite { +class database; +} // namespace sqlite +} // namespace utils + +namespace store { + + +class metadata; + + +namespace detail { + + +extern int current_schema_version; + + +utils::fs::path migration_file(const int, const int); +utils::fs::path schema_file(void); +metadata initialize(utils::sqlite::database&); +void backup_database(const utils::fs::path&, const int); + + +} // anonymous namespace + + +class transaction; + + +/// Public interface to the database store. +class backend { + struct impl; + + /// Pointer to the shared internal implementation. + std::tr1::shared_ptr< impl > _pimpl; + + friend class metadata; + + backend(impl*); + +public: + ~backend(void); + + static backend open_ro(const utils::fs::path&); + static backend open_rw(const utils::fs::path&); + + utils::sqlite::database& database(void); + transaction start(void); +}; + + +void migrate_schema(const utils::fs::path&); + + +} // namespace store + +#endif // !defined(STORE_BACKEND_HPP) diff --git a/external/bsd/kyua-cli/dist/store/backend_test.cpp b/external/bsd/kyua-cli/dist/store/backend_test.cpp new file mode 100644 index 000000000..61a9d48c1 --- /dev/null +++ b/external/bsd/kyua-cli/dist/store/backend_test.cpp @@ -0,0 +1,317 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "store/backend.hpp" + +extern "C" { +#include +} + +#include + +#include "store/exceptions.hpp" +#include "store/metadata.hpp" +#include "utils/datetime.hpp" +#include "utils/env.hpp" +#include "utils/fs/operations.hpp" +#include "utils/fs/path.hpp" +#include "utils/logging/operations.hpp" +#include "utils/sqlite/database.hpp" +#include "utils/sqlite/statement.ipp" + +namespace datetime = utils::datetime; +namespace fs = utils::fs; +namespace logging = utils::logging; +namespace sqlite = utils::sqlite; + + +ATF_TEST_CASE_WITHOUT_HEAD(detail__backup_database__ok); +ATF_TEST_CASE_BODY(detail__backup_database__ok) +{ + atf::utils::create_file("test.db", "The DB\n"); + store::detail::backup_database(fs::path("test.db"), 13); + ATF_REQUIRE(fs::exists(fs::path("test.db"))); + ATF_REQUIRE(fs::exists(fs::path("test.db.v13.backup"))); + ATF_REQUIRE(atf::utils::compare_file("test.db.v13.backup", "The DB\n")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(detail__backup_database__ok_overwrite); +ATF_TEST_CASE_BODY(detail__backup_database__ok_overwrite) +{ + atf::utils::create_file("test.db", "Original contents"); + atf::utils::create_file("test.db.v1.backup", "Overwrite me"); + store::detail::backup_database(fs::path("test.db"), 1); + ATF_REQUIRE(fs::exists(fs::path("test.db"))); + ATF_REQUIRE(fs::exists(fs::path("test.db.v1.backup"))); + ATF_REQUIRE(atf::utils::compare_file("test.db.v1.backup", + "Original contents")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(detail__backup_database__fail_open); +ATF_TEST_CASE_BODY(detail__backup_database__fail_open) +{ + ATF_REQUIRE_THROW_RE(store::error, "Cannot open.*foo.db", + store::detail::backup_database(fs::path("foo.db"), 5)); +} + + +ATF_TEST_CASE(detail__backup_database__fail_create); +ATF_TEST_CASE_HEAD(detail__backup_database__fail_create) +{ + set_md_var("require.user", "unprivileged"); +} +ATF_TEST_CASE_BODY(detail__backup_database__fail_create) +{ + ATF_REQUIRE(::mkdir("dir", 0755) != -1); + atf::utils::create_file("dir/test.db", "Does not need to be valid"); + ATF_REQUIRE(::chmod("dir", 0111) != -1); + ATF_REQUIRE_THROW_RE( + store::error, "Cannot create.*dir/test.db.v13.backup", + store::detail::backup_database(fs::path("dir/test.db"), 13)); +} + + +ATF_TEST_CASE(detail__initialize__ok); +ATF_TEST_CASE_HEAD(detail__initialize__ok) +{ + logging::set_inmemory(); + set_md_var("require.files", store::detail::schema_file().c_str()); +} +ATF_TEST_CASE_BODY(detail__initialize__ok) +{ + sqlite::database db = sqlite::database::in_memory(); + const datetime::timestamp before = datetime::timestamp::now(); + const store::metadata md = store::detail::initialize(db); + const datetime::timestamp after = datetime::timestamp::now(); + + ATF_REQUIRE(md.timestamp() >= before.to_seconds()); + ATF_REQUIRE(md.timestamp() <= after.to_microseconds()); + ATF_REQUIRE_EQ(store::detail::current_schema_version, md.schema_version()); + + // Query some known tables to ensure they were created. + db.exec("SELECT * FROM metadata"); + + // And now query some know values. + sqlite::statement stmt = db.create_statement( + "SELECT COUNT(*) FROM metadata"); + ATF_REQUIRE(stmt.step()); + ATF_REQUIRE_EQ(1, stmt.column_int(0)); + ATF_REQUIRE(!stmt.step()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(detail__initialize__missing_schema); +ATF_TEST_CASE_BODY(detail__initialize__missing_schema) +{ + utils::setenv("KYUA_STOREDIR", "/non-existent"); + store::detail::current_schema_version = 712; + + sqlite::database db = sqlite::database::in_memory(); + ATF_REQUIRE_THROW_RE(store::error, + "Cannot open.*'/non-existent/schema_v712.sql'", + store::detail::initialize(db)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(detail__initialize__sqlite_error); +ATF_TEST_CASE_BODY(detail__initialize__sqlite_error) +{ + utils::setenv("KYUA_STOREDIR", "."); + store::detail::current_schema_version = 712; + + atf::utils::create_file("schema_v712.sql", "foo_bar_baz;\n"); + + sqlite::database db = sqlite::database::in_memory(); + ATF_REQUIRE_THROW_RE(store::error, "Failed to initialize.*:.*foo_bar_baz", + store::detail::initialize(db)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(detail__migration_file__builtin); +ATF_TEST_CASE_BODY(detail__migration_file__builtin) +{ + utils::unsetenv("KYUA_STOREDIR"); + ATF_REQUIRE_EQ(fs::path(KYUA_STOREDIR) / "migrate_v5_v9.sql", + store::detail::migration_file(5, 9)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(detail__migration_file__overriden); +ATF_TEST_CASE_BODY(detail__migration_file__overriden) +{ + utils::setenv("KYUA_STOREDIR", "/tmp/test"); + ATF_REQUIRE_EQ(fs::path("/tmp/test/migrate_v5_v9.sql"), + store::detail::migration_file(5, 9)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(detail__schema_file__builtin); +ATF_TEST_CASE_BODY(detail__schema_file__builtin) +{ + utils::unsetenv("KYUA_STOREDIR"); + ATF_REQUIRE_EQ(fs::path(KYUA_STOREDIR) / "schema_v2.sql", + store::detail::schema_file()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(detail__schema_file__overriden); +ATF_TEST_CASE_BODY(detail__schema_file__overriden) +{ + utils::setenv("KYUA_STOREDIR", "/tmp/test"); + store::detail::current_schema_version = 123; + ATF_REQUIRE_EQ(fs::path("/tmp/test/schema_v123.sql"), + store::detail::schema_file()); +} + + +ATF_TEST_CASE(backend__open_ro__ok); +ATF_TEST_CASE_HEAD(backend__open_ro__ok) +{ + logging::set_inmemory(); + set_md_var("require.files", store::detail::schema_file().c_str()); +} +ATF_TEST_CASE_BODY(backend__open_ro__ok) +{ + { + sqlite::database db = sqlite::database::open( + fs::path("test.db"), sqlite::open_readwrite | sqlite::open_create); + store::detail::initialize(db); + } + store::backend backend = store::backend::open_ro(fs::path("test.db")); + backend.database().exec("SELECT * FROM metadata"); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(backend__open_ro__missing_file); +ATF_TEST_CASE_BODY(backend__open_ro__missing_file) +{ + ATF_REQUIRE_THROW_RE(store::error, "Cannot open 'missing.db': ", + store::backend::open_ro(fs::path("missing.db"))); + ATF_REQUIRE(!fs::exists(fs::path("missing.db"))); +} + + +ATF_TEST_CASE(backend__open_ro__integrity_error); +ATF_TEST_CASE_HEAD(backend__open_ro__integrity_error) +{ + logging::set_inmemory(); + set_md_var("require.files", store::detail::schema_file().c_str()); +} +ATF_TEST_CASE_BODY(backend__open_ro__integrity_error) +{ + { + sqlite::database db = sqlite::database::open( + fs::path("test.db"), sqlite::open_readwrite | sqlite::open_create); + store::detail::initialize(db); + db.exec("DELETE FROM metadata"); + } + ATF_REQUIRE_THROW_RE(store::integrity_error, "metadata.*empty", + store::backend::open_ro(fs::path("test.db"))); +} + + +ATF_TEST_CASE(backend__open_rw__ok); +ATF_TEST_CASE_HEAD(backend__open_rw__ok) +{ + logging::set_inmemory(); + set_md_var("require.files", store::detail::schema_file().c_str()); +} +ATF_TEST_CASE_BODY(backend__open_rw__ok) +{ + { + sqlite::database db = sqlite::database::open( + fs::path("test.db"), sqlite::open_readwrite | sqlite::open_create); + store::detail::initialize(db); + } + store::backend backend = store::backend::open_rw(fs::path("test.db")); + backend.database().exec("SELECT * FROM metadata"); +} + + +ATF_TEST_CASE(backend__open_rw__create_missing); +ATF_TEST_CASE_HEAD(backend__open_rw__create_missing) +{ + logging::set_inmemory(); + set_md_var("require.files", store::detail::schema_file().c_str()); +} +ATF_TEST_CASE_BODY(backend__open_rw__create_missing) +{ + store::backend backend = store::backend::open_rw(fs::path("test.db")); + backend.database().exec("SELECT * FROM metadata"); +} + + +ATF_TEST_CASE(backend__open_rw__integrity_error); +ATF_TEST_CASE_HEAD(backend__open_rw__integrity_error) +{ + logging::set_inmemory(); + set_md_var("require.files", store::detail::schema_file().c_str()); +} +ATF_TEST_CASE_BODY(backend__open_rw__integrity_error) +{ + { + sqlite::database db = sqlite::database::open( + fs::path("test.db"), sqlite::open_readwrite | sqlite::open_create); + store::detail::initialize(db); + db.exec("DELETE FROM metadata"); + } + ATF_REQUIRE_THROW_RE(store::integrity_error, "metadata.*empty", + store::backend::open_rw(fs::path("test.db"))); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, detail__backup_database__ok); + ATF_ADD_TEST_CASE(tcs, detail__backup_database__ok_overwrite); + ATF_ADD_TEST_CASE(tcs, detail__backup_database__fail_open); + ATF_ADD_TEST_CASE(tcs, detail__backup_database__fail_create); + + ATF_ADD_TEST_CASE(tcs, detail__initialize__ok); + ATF_ADD_TEST_CASE(tcs, detail__initialize__missing_schema); + ATF_ADD_TEST_CASE(tcs, detail__initialize__sqlite_error); + + ATF_ADD_TEST_CASE(tcs, detail__migration_file__builtin); + ATF_ADD_TEST_CASE(tcs, detail__migration_file__overriden); + + ATF_ADD_TEST_CASE(tcs, detail__schema_file__builtin); + ATF_ADD_TEST_CASE(tcs, detail__schema_file__overriden); + + ATF_ADD_TEST_CASE(tcs, backend__open_ro__ok); + ATF_ADD_TEST_CASE(tcs, backend__open_ro__missing_file); + ATF_ADD_TEST_CASE(tcs, backend__open_ro__integrity_error); + ATF_ADD_TEST_CASE(tcs, backend__open_rw__ok); + ATF_ADD_TEST_CASE(tcs, backend__open_rw__create_missing); + ATF_ADD_TEST_CASE(tcs, backend__open_rw__integrity_error); + + // Tests for migrate_schema are in schema_inttest. This is because, for + // such tests to be meaningful, they need to be integration tests and don't + // really fit the goal of this unit-test module. +} diff --git a/external/bsd/kyua-cli/dist/store/dbtypes.cpp b/external/bsd/kyua-cli/dist/store/dbtypes.cpp new file mode 100644 index 000000000..b82e1e0af --- /dev/null +++ b/external/bsd/kyua-cli/dist/store/dbtypes.cpp @@ -0,0 +1,186 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "store/dbtypes.hpp" + +#include "engine/test_program.hpp" +#include "store/exceptions.hpp" +#include "utils/format/macros.hpp" +#include "utils/sanity.hpp" +#include "utils/sqlite/statement.ipp" + +namespace datetime = utils::datetime; +namespace sqlite = utils::sqlite; + + +/// Binds a boolean value to a statement parameter. +/// +/// \param stmt The statement to which to bind the parameter. +/// \param field The name of the parameter; must exist. +/// \param value The value to bind. +void +store::bind_bool(sqlite::statement& stmt, const char* field, const bool value) +{ + stmt.bind(field, value ? "true" : "false"); +} + + +/// Binds a time delta to a statement parameter. +/// +/// \param stmt The statement to which to bind the parameter. +/// \param field The name of the parameter; must exist. +/// \param delta The value to bind. +void +store::bind_delta(sqlite::statement& stmt, const char* field, + const datetime::delta& delta) +{ + stmt.bind(field, static_cast< int64_t >(delta.to_microseconds())); +} + + +/// Binds a string to a statement parameter. +/// +/// If the string is not empty, this binds the string itself. Otherwise, it +/// binds a NULL value. +/// +/// \param stmt The statement to which to bind the parameter. +/// \param stmt The statement to which to bind the field. +/// \param field The name of the parameter; must exist. +/// \param str The string to bind. +void +store::bind_optional_string(sqlite::statement& stmt, const char* field, + const std::string& str) +{ + if (str.empty()) + stmt.bind(field, sqlite::null()); + else + stmt.bind(field, str); +} + + +/// Binds a timestamp to a statement parameter. +/// +/// \param stmt The statement to which to bind the parameter. +/// \param field The name of the parameter; must exist. +/// \param timestamp The value to bind. +void +store::bind_timestamp(sqlite::statement& stmt, const char* field, + const datetime::timestamp& timestamp) +{ + stmt.bind(field, timestamp.to_microseconds()); +} + + +/// Queries a boolean value from a statement. +/// +/// \param stmt The statement from which to get the column. +/// \param column The name of the column holding the value. +/// +/// \return The parsed value if all goes well. +/// +/// \throw integrity_error If the value in the specified column is invalid. +bool +store::column_bool(sqlite::statement& stmt, const char* column) +{ + const int id = stmt.column_id(column); + if (stmt.column_type(id) != sqlite::type_text) + throw store::integrity_error(F("Boolean value in column %s is not a " + "string") % column); + const std::string value = stmt.column_text(id); + if (value == "true") + return true; + else if (value == "false") + return false; + else + throw store::integrity_error(F("Unknown boolean value '%s'") % value); +} + + +/// Queries a time delta from a statement. +/// +/// \param stmt The statement from which to get the column. +/// \param column The name of the column holding the value. +/// +/// \return The parsed value if all goes well. +/// +/// \throw integrity_error If the value in the specified column is invalid. +datetime::delta +store::column_delta(sqlite::statement& stmt, const char* column) +{ + const int id = stmt.column_id(column); + if (stmt.column_type(id) != sqlite::type_integer) + throw store::integrity_error(F("Time delta in column %s is not an " + "integer") % column); + return datetime::delta::from_microseconds(stmt.column_int64(id)); +} + + +/// Queries an optional string from a statement. +/// +/// \param stmt The statement from which to get the column. +/// \param column The name of the column holding the value. +/// +/// \return The parsed value if all goes well. +/// +/// \throw integrity_error If the value in the specified column is invalid. +std::string +store::column_optional_string(sqlite::statement& stmt, const char* column) +{ + const int id = stmt.column_id(column); + switch (stmt.column_type(id)) { + case sqlite::type_text: + return stmt.column_text(id); + case sqlite::type_null: + return ""; + default: + throw integrity_error(F("Invalid string type in column %s") % column); + } +} + + +/// Queries a timestamp from a statement. +/// +/// \param stmt The statement from which to get the column. +/// \param column The name of the column holding the value. +/// +/// \return The parsed value if all goes well. +/// +/// \throw integrity_error If the value in the specified column is invalid. +datetime::timestamp +store::column_timestamp(sqlite::statement& stmt, const char* column) +{ + const int id = stmt.column_id(column); + if (stmt.column_type(id) != sqlite::type_integer) + throw store::integrity_error(F("Timestamp in column %s is not an " + "integer") % column); + const int64_t value = stmt.column_int64(id); + if (value < 0) + throw store::integrity_error(F("Timestamp in column %s must be " + "positive") % column); + return datetime::timestamp::from_microseconds(value); +} diff --git a/external/bsd/kyua-cli/dist/store/dbtypes.hpp b/external/bsd/kyua-cli/dist/store/dbtypes.hpp new file mode 100644 index 000000000..2fd7ed9ae --- /dev/null +++ b/external/bsd/kyua-cli/dist/store/dbtypes.hpp @@ -0,0 +1,66 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file store/dbtypes.hpp +/// Functions to internalize/externalize various types. +/// +/// These helper functions are only provided to help in the implementation of +/// other modules. Therefore, this header file should never be included from +/// other header files. + +#if defined(STORE_DBTYPES_HPP) +# error "Do not include dbtypes.hpp multiple times" +#endif // !defined(STORE_DBTYPES_HPP) +#define STORE_DBTYPES_HPP + +#include "store/transaction.hpp" +#include "utils/datetime.hpp" +#include "utils/sqlite/statement.hpp" + +namespace engine { +class test_program; +} // namespace engine + +namespace store { + + +void bind_bool(utils::sqlite::statement&, const char*, const bool); +void bind_delta(utils::sqlite::statement&, const char*, + const utils::datetime::delta&); +void bind_optional_string(utils::sqlite::statement&, const char*, + const std::string&); +void bind_timestamp(utils::sqlite::statement&, const char*, + const utils::datetime::timestamp&); +bool column_bool(utils::sqlite::statement&, const char*); +utils::datetime::delta column_delta(utils::sqlite::statement&, const char*); +std::string column_optional_string(utils::sqlite::statement&, const char*); +utils::datetime::timestamp column_timestamp(utils::sqlite::statement&, + const char*); + + +} // namespace store diff --git a/external/bsd/kyua-cli/dist/store/dbtypes_test.cpp b/external/bsd/kyua-cli/dist/store/dbtypes_test.cpp new file mode 100644 index 000000000..073708734 --- /dev/null +++ b/external/bsd/kyua-cli/dist/store/dbtypes_test.cpp @@ -0,0 +1,205 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "store/dbtypes.hpp" + +#include + +#include "engine/test_program.hpp" +#include "store/exceptions.hpp" +#include "utils/datetime.hpp" +#include "utils/optional.ipp" +#include "utils/sqlite/database.hpp" +#include "utils/sqlite/statement.ipp" + +namespace datetime = utils::datetime; +namespace fs = utils::fs; +namespace sqlite = utils::sqlite; + +using utils::none; + + +namespace { + + +/// Validates that a particular bind_x/column_x sequence works. +/// +/// \param bind The store::bind_* function to put the value. +/// \param value The value to store and validate. +/// \param column The store::column_* function to get the value. +template< typename Type1, typename Type2, typename Type3 > +static void +do_ok_test(void (*bind)(sqlite::statement&, const char*, Type1), + Type2 value, + Type3 (*column)(sqlite::statement&, const char*)) +{ + sqlite::database db = sqlite::database::in_memory(); + db.exec("CREATE TABLE test (column DONTCARE)"); + + sqlite::statement insert = db.create_statement("INSERT INTO test " + "VALUES (:v)"); + bind(insert, ":v", value); + insert.step_without_results(); + + sqlite::statement query = db.create_statement("SELECT * FROM test"); + ATF_REQUIRE(query.step()); + ATF_REQUIRE(column(query, "column") == value); + ATF_REQUIRE(!query.step()); +} + + +/// Validates an error condition of column_*. +/// +/// \param value The invalid value to insert into the database. +/// \param column The store::column_* function to get the value. +/// \param error_regexp The expected message in the raised integrity_error. +template< typename Type1, typename Type2 > +static void +do_invalid_test(Type1 value, + Type2 (*column)(sqlite::statement&, const char*), + const std::string& error_regexp) +{ + sqlite::database db = sqlite::database::in_memory(); + db.exec("CREATE TABLE test (column DONTCARE)"); + + sqlite::statement insert = db.create_statement("INSERT INTO test " + "VALUES (:v)"); + insert.bind(":v", value); + insert.step_without_results(); + + sqlite::statement query = db.create_statement("SELECT * FROM test"); + ATF_REQUIRE(query.step()); + ATF_REQUIRE_THROW_RE(store::integrity_error, error_regexp, + column(query, "column")); + ATF_REQUIRE(!query.step()); +} + + +} // anonymous namespace + + +ATF_TEST_CASE_WITHOUT_HEAD(bool__ok); +ATF_TEST_CASE_BODY(bool__ok) +{ + do_ok_test(store::bind_bool, true, store::column_bool); + do_ok_test(store::bind_bool, false, store::column_bool); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(bool__get_invalid_type); +ATF_TEST_CASE_BODY(bool__get_invalid_type) +{ + do_invalid_test(123, store::column_bool, "not a string"); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(bool__get_invalid_value); +ATF_TEST_CASE_BODY(bool__get_invalid_value) +{ + do_invalid_test("foo", store::column_bool, "Unknown boolean.*foo"); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(delta__ok); +ATF_TEST_CASE_BODY(delta__ok) +{ + do_ok_test(store::bind_delta, datetime::delta(15, 34), store::column_delta); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(delta__get_invalid_type); +ATF_TEST_CASE_BODY(delta__get_invalid_type) +{ + do_invalid_test(15.6, store::column_delta, "not an integer"); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(optional_string__ok); +ATF_TEST_CASE_BODY(optional_string__ok) +{ + do_ok_test(store::bind_optional_string, "", store::column_optional_string); + do_ok_test(store::bind_optional_string, "a", store::column_optional_string); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(optional_string__get_invalid_type); +ATF_TEST_CASE_BODY(optional_string__get_invalid_type) +{ + do_invalid_test(35, store::column_optional_string, "Invalid string"); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(timestamp__ok); +ATF_TEST_CASE_BODY(timestamp__ok) +{ + do_ok_test(store::bind_timestamp, + datetime::timestamp::from_microseconds(0), + store::column_timestamp); + do_ok_test(store::bind_timestamp, + datetime::timestamp::from_microseconds(123), + store::column_timestamp); + + do_ok_test(store::bind_timestamp, + datetime::timestamp::from_values(2012, 2, 9, 23, 15, 51, 987654), + store::column_timestamp); + do_ok_test(store::bind_timestamp, + datetime::timestamp::from_values(1980, 1, 2, 3, 4, 5, 0), + store::column_timestamp); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(timestamp__get_invalid_type); +ATF_TEST_CASE_BODY(timestamp__get_invalid_type) +{ + do_invalid_test(35.6, store::column_timestamp, "not an integer"); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(timestamp__get_invalid_value); +ATF_TEST_CASE_BODY(timestamp__get_invalid_value) +{ + do_invalid_test(-1234, store::column_timestamp, "must be positive"); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, bool__ok); + ATF_ADD_TEST_CASE(tcs, bool__get_invalid_type); + ATF_ADD_TEST_CASE(tcs, bool__get_invalid_value); + + ATF_ADD_TEST_CASE(tcs, delta__ok); + ATF_ADD_TEST_CASE(tcs, delta__get_invalid_type); + + ATF_ADD_TEST_CASE(tcs, optional_string__ok); + ATF_ADD_TEST_CASE(tcs, optional_string__get_invalid_type); + + ATF_ADD_TEST_CASE(tcs, timestamp__ok); + ATF_ADD_TEST_CASE(tcs, timestamp__get_invalid_type); + ATF_ADD_TEST_CASE(tcs, timestamp__get_invalid_value); +} diff --git a/external/bsd/kyua-cli/dist/store/exceptions.cpp b/external/bsd/kyua-cli/dist/store/exceptions.cpp new file mode 100644 index 000000000..6385438a9 --- /dev/null +++ b/external/bsd/kyua-cli/dist/store/exceptions.cpp @@ -0,0 +1,88 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "store/exceptions.hpp" + +#include "utils/format/macros.hpp" + + +/// Constructs a new error with a plain-text message. +/// +/// \param message The plain-text error message. +store::error::error(const std::string& message) : + std::runtime_error(message) +{ +} + + +/// Destructor for the error. +store::error::~error(void) throw() +{ +} + + +/// Constructs a new error with a plain-text message. +/// +/// \param message The plain-text error message. +store::integrity_error::integrity_error(const std::string& message) : + error(message) +{ +} + + +/// Destructor for the error. +store::integrity_error::~integrity_error(void) throw() +{ +} + + +/// Constructs a new error with a plain-text message. +/// +/// \param version Version of the current schema. +store::old_schema_error::old_schema_error(const int version) : + error(F("The database contains version %s of the schema, which is " + "stale and needs to be upgraded") % version), + _old_version(version) +{ +} + + +/// Destructor for the error. +store::old_schema_error::~old_schema_error(void) throw() +{ +} + + +/// Returns the current schema version in the database. +/// +/// \return A version number. +int +store::old_schema_error::old_version(void) const +{ + return _old_version; +} diff --git a/external/bsd/kyua-cli/dist/store/exceptions.hpp b/external/bsd/kyua-cli/dist/store/exceptions.hpp new file mode 100644 index 000000000..92771a5b1 --- /dev/null +++ b/external/bsd/kyua-cli/dist/store/exceptions.hpp @@ -0,0 +1,72 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file store/exceptions.hpp +/// Exception types raised by the store module. + +#if !defined(STORE_EXCEPTIONS_HPP) +#define STORE_EXCEPTIONS_HPP + +#include + +namespace store { + + +/// Base exception for store errors. +class error : public std::runtime_error { +public: + explicit error(const std::string&); + virtual ~error(void) throw(); +}; + + +/// The data in the database is inconsistent. +class integrity_error : public error { +public: + explicit integrity_error(const std::string&); + virtual ~integrity_error(void) throw(); +}; + + +/// The database schema is old and needs a migration. +class old_schema_error : public error { + /// Version in the database that caused this error. + int _old_version; + +public: + explicit old_schema_error(const int); + virtual ~old_schema_error(void) throw(); + + int old_version(void) const; +}; + + +} // namespace store + + +#endif // !defined(STORE_EXCEPTIONS_HPP) diff --git a/external/bsd/kyua-cli/dist/store/exceptions_test.cpp b/external/bsd/kyua-cli/dist/store/exceptions_test.cpp new file mode 100644 index 000000000..1ad75e741 --- /dev/null +++ b/external/bsd/kyua-cli/dist/store/exceptions_test.cpp @@ -0,0 +1,65 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "store/exceptions.hpp" + +#include + +#include + + +ATF_TEST_CASE_WITHOUT_HEAD(error); +ATF_TEST_CASE_BODY(error) +{ + const store::error e("Some text"); + ATF_REQUIRE(std::strcmp("Some text", e.what()) == 0); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(integrity_error); +ATF_TEST_CASE_BODY(integrity_error) +{ + const store::integrity_error e("Some text"); + ATF_REQUIRE(std::strcmp("Some text", e.what()) == 0); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(old_schema_error); +ATF_TEST_CASE_BODY(old_schema_error) +{ + const store::old_schema_error e(15); + ATF_REQUIRE_MATCH("version 15 .*upgraded", e.what()); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, error); + ATF_ADD_TEST_CASE(tcs, integrity_error); + ATF_ADD_TEST_CASE(tcs, old_schema_error); +} diff --git a/external/bsd/kyua-cli/dist/store/metadata.cpp b/external/bsd/kyua-cli/dist/store/metadata.cpp new file mode 100644 index 000000000..7c3658364 --- /dev/null +++ b/external/bsd/kyua-cli/dist/store/metadata.cpp @@ -0,0 +1,137 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "store/metadata.hpp" + +#include "store/exceptions.hpp" +#include "utils/format/macros.hpp" +#include "utils/sanity.hpp" +#include "utils/sqlite/database.hpp" +#include "utils/sqlite/exceptions.hpp" +#include "utils/sqlite/statement.ipp" + +namespace sqlite = utils::sqlite; + + +namespace { + + +/// Fetches an integer column from a statement of the 'metadata' table. +/// +/// \param stmt The statement from which to get the column value. +/// \param column The name of the column to retrieve. +/// +/// \return The value of the column. +/// +/// \throw store::integrity_error If there is a problem fetching the value +/// caused by an invalid schema or data. +static int64_t +int64_column(sqlite::statement& stmt, const char* column) +{ + int index; + try { + index = stmt.column_id(column); + } catch (const sqlite::invalid_column_error& e) { + UNREACHABLE_MSG("Invalid column specification; the SELECT statement " + "should have caught this"); + } + if (stmt.column_type(index) != sqlite::type_integer) + throw store::integrity_error(F("The '%s' column in 'metadata' table " + "has an invalid type") % column); + return stmt.column_int64(index); +} + + +} // anonymous namespace + + +/// Constructs a new metadata object. +/// +/// \param schema_version_ The schema version. +/// \param timestamp_ The time at which this version was created. +store::metadata::metadata(const int schema_version_, const int64_t timestamp_) : + _schema_version(schema_version_), + _timestamp(timestamp_) +{ +} + + +/// Returns the timestamp of this entry. +/// +/// \return The timestamp in this metadata entry. +int64_t +store::metadata::timestamp(void) const +{ + return _timestamp; +} + + +/// Returns the schema version. +/// +/// \return The schema version in this metadata entry. +int +store::metadata::schema_version(void) const +{ + return _schema_version; +} + + +/// Reads the latest metadata entry from the database. +/// +/// \param db The database from which to read the metadata from. +/// +/// \return The current metadata of the database. It is not OK for the metadata +/// table to be empty, so this is guaranteed to return a value unless there is +/// an error. +/// +/// \throw store::integrity_error If the metadata in the database is empty, +/// has an invalid schema or its contents are bogus. +store::metadata +store::metadata::fetch_latest(sqlite::database& db) +{ + try { + sqlite::statement stmt = db.create_statement( + "SELECT schema_version, timestamp FROM metadata " + "ORDER BY schema_version DESC LIMIT 1"); + if (!stmt.step()) + throw store::integrity_error("The 'metadata' table is empty"); + + const int schema_version_ = + static_cast< int >(int64_column(stmt, "schema_version")); + const int64_t timestamp_ = int64_column(stmt, "timestamp"); + + if (stmt.step()) + UNREACHABLE_MSG("Got more than one result from a query that " + "does not permit this; any pragmas defined?"); + + return metadata(schema_version_, timestamp_); + } catch (const sqlite::error& e) { + throw store::integrity_error(F("Invalid metadata schema: %s") % + e.what()); + } +} diff --git a/external/bsd/kyua-cli/dist/store/metadata.hpp b/external/bsd/kyua-cli/dist/store/metadata.hpp new file mode 100644 index 000000000..6dbb1ab5a --- /dev/null +++ b/external/bsd/kyua-cli/dist/store/metadata.hpp @@ -0,0 +1,62 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file store/metadata.hpp +/// Representation of the database metadata. + +#if !defined(STORE_METADATA_HPP) +#define STORE_METADATA_HPP + +#include + +#include "utils/sqlite/database.hpp" + +namespace store { + + +/// Representation of the database metadata. +class metadata { + /// Current version of the database schema. + int _schema_version; + + /// Timestamp of the last metadata entry in the database. + int64_t _timestamp; + + metadata(const int, const int64_t); + +public: + int64_t timestamp(void) const; + int schema_version(void) const; + + static metadata fetch_latest(utils::sqlite::database&); +}; + + +} // namespace store + +#endif // !defined(STORE_METADATA_HPP) diff --git a/external/bsd/kyua-cli/dist/store/metadata_test.cpp b/external/bsd/kyua-cli/dist/store/metadata_test.cpp new file mode 100644 index 000000000..5f2e6d52a --- /dev/null +++ b/external/bsd/kyua-cli/dist/store/metadata_test.cpp @@ -0,0 +1,153 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "store/metadata.hpp" + +#include + +#include "store/backend.hpp" +#include "store/exceptions.hpp" +#include "utils/logging/operations.hpp" +#include "utils/sqlite/database.hpp" + +namespace logging = utils::logging; +namespace sqlite = utils::sqlite; + + +namespace { + + +/// Creates a test in-memory database. +/// +/// When using this function, you must define a 'require.files' property in this +/// case pointing to store::detail::schema_file(). +/// +/// The database created by this function mimics a real complete database, but +/// without any predefined values. I.e. for our particular case, the metadata +/// table is empty. +/// +/// \return A SQLite database instance. +static sqlite::database +create_database(void) +{ + sqlite::database db = sqlite::database::in_memory(); + store::detail::initialize(db); + db.exec("DELETE FROM metadata"); + return db; +} + + +} // anonymous namespace + + +ATF_TEST_CASE(fetch_latest__ok); +ATF_TEST_CASE_HEAD(fetch_latest__ok) +{ + logging::set_inmemory(); + set_md_var("require.files", store::detail::schema_file().c_str()); +} +ATF_TEST_CASE_BODY(fetch_latest__ok) +{ + sqlite::database db = create_database(); + db.exec("INSERT INTO metadata (schema_version, timestamp) " + "VALUES (512, 5678)"); + db.exec("INSERT INTO metadata (schema_version, timestamp) " + "VALUES (256, 1234)"); + + const store::metadata metadata = store::metadata::fetch_latest(db); + ATF_REQUIRE_EQ(5678L, metadata.timestamp()); + ATF_REQUIRE_EQ(512, metadata.schema_version()); +} + + +ATF_TEST_CASE(fetch_latest__empty_metadata); +ATF_TEST_CASE_HEAD(fetch_latest__empty_metadata) +{ + logging::set_inmemory(); + set_md_var("require.files", store::detail::schema_file().c_str()); +} +ATF_TEST_CASE_BODY(fetch_latest__empty_metadata) +{ + sqlite::database db = create_database(); + ATF_REQUIRE_THROW_RE(store::integrity_error, "metadata.*empty", + store::metadata::fetch_latest(db)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(fetch_latest__no_timestamp); +ATF_TEST_CASE_BODY(fetch_latest__no_timestamp) +{ + sqlite::database db = sqlite::database::in_memory(); + db.exec("CREATE TABLE metadata (schema_version INTEGER)"); + db.exec("INSERT INTO metadata VALUES (3)"); + + ATF_REQUIRE_THROW_RE(store::integrity_error, + "Invalid metadata.*timestamp", + store::metadata::fetch_latest(db)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(fetch_latest__no_schema_version); +ATF_TEST_CASE_BODY(fetch_latest__no_schema_version) +{ + sqlite::database db = sqlite::database::in_memory(); + db.exec("CREATE TABLE metadata (timestamp INTEGER)"); + db.exec("INSERT INTO metadata VALUES (3)"); + + ATF_REQUIRE_THROW_RE(store::integrity_error, + "Invalid metadata.*schema_version", + store::metadata::fetch_latest(db)); +} + + +ATF_TEST_CASE(fetch_latest__invalid_timestamp); +ATF_TEST_CASE_HEAD(fetch_latest__invalid_timestamp) +{ + logging::set_inmemory(); + set_md_var("require.files", store::detail::schema_file().c_str()); +} +ATF_TEST_CASE_BODY(fetch_latest__invalid_timestamp) +{ + sqlite::database db = create_database(); + db.exec("INSERT INTO metadata (schema_version, timestamp) " + "VALUES (3, 'foo')"); + + ATF_REQUIRE_THROW_RE(store::integrity_error, + "timestamp.*invalid type", + store::metadata::fetch_latest(db)); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, fetch_latest__ok); + ATF_ADD_TEST_CASE(tcs, fetch_latest__empty_metadata); + ATF_ADD_TEST_CASE(tcs, fetch_latest__no_timestamp); + ATF_ADD_TEST_CASE(tcs, fetch_latest__no_schema_version); + ATF_ADD_TEST_CASE(tcs, fetch_latest__invalid_timestamp); +} diff --git a/external/bsd/kyua-cli/dist/store/migrate_v1_v2.sql b/external/bsd/kyua-cli/dist/store/migrate_v1_v2.sql new file mode 100644 index 000000000..fdbc79d89 --- /dev/null +++ b/external/bsd/kyua-cli/dist/store/migrate_v1_v2.sql @@ -0,0 +1,352 @@ +-- Copyright 2013 Google Inc. +-- All rights reserved. +-- +-- Redistribution and use in source and binary forms, with or without +-- modification, are permitted provided that the following conditions are +-- met: +-- +-- * Redistributions of source code must retain the above copyright +-- notice, this list of conditions and the following disclaimer. +-- * Redistributions in binary form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- * Neither the name of Google Inc. nor the names of its contributors +-- may be used to endorse or promote products derived from this software +-- without specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +-- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +-- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +-- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +-- OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +-- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +-- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +-- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +-- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +-- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +-- \file store/v1-to-v2.sql +-- Migration of a database with version 1 of the schema to version 2. +-- +-- Version 2 appeared in revision 9a73561a1e3975bba4cbfd19aee6b2365a39519e +-- and its changes were: +-- +-- * Changed the primary key of the metadata table to be the +-- schema_version, not the timestamp. Because timestamps only have +-- second resolution, the old schema made testing of schema migrations +-- difficult. +-- +-- * Introduced the metadatas table, which holds the metadata of all test +-- programs and test cases in an abstract manner regardless of their +-- interface. +-- +-- * Added the metadata_id field to the test_programs and test_cases +-- tables, referencing the new metadatas table. +-- +-- * Changed the precision of the timeout metadata field to be in seconds +-- rather than in microseconds. There is no data loss, and the code that +-- writes the metadata is simplified. +-- +-- * Removed the atf_* and plain_* tables. +-- +-- * Added missing indexes to improve the performance of reports. +-- +-- * Added missing column affinities to the absolute_path and relative_path +-- columns of the test_programs table. + + +-- TODO(jmmv): Implement addition of missing affinities. + + +-- +-- Change primary key of the metadata table. +-- + + +CREATE TABLE new_metadata ( + schema_version INTEGER PRIMARY KEY CHECK (schema_version >= 1), + timestamp TIMESTAMP NOT NULL CHECK (timestamp >= 0) +); + +INSERT INTO new_metadata (schema_version, timestamp) + SELECT schema_version, timestamp FROM metadata; + +DROP TABLE metadata; +ALTER TABLE new_metadata RENAME TO metadata; + + +-- +-- Add the new tables, columns and indexes. +-- + + +CREATE TABLE metadatas ( + metadata_id INTEGER NOT NULL, + property_name TEXT NOT NULL, + property_value TEXT, + + PRIMARY KEY (metadata_id, property_name) +); + + +-- Upgrade the test_programs table by adding missing column affinities and +-- the new metadata_id column. +CREATE TABLE new_test_programs ( + test_program_id INTEGER PRIMARY KEY AUTOINCREMENT, + action_id INTEGER REFERENCES actions, + + absolute_path TEXT NOT NULL, + root TEXT NOT NULL, + relative_path TEXT NOT NULL, + test_suite_name TEXT NOT NULL, + metadata_id INTEGER, + interface TEXT NOT NULL +); +PRAGMA foreign_keys = OFF; +INSERT INTO new_test_programs (test_program_id, action_id, absolute_path, + root, relative_path, test_suite_name, + interface) + SELECT test_program_id, action_id, absolute_path, root, relative_path, + test_suite_name, interface FROM test_programs; +DROP TABLE test_programs; +ALTER TABLE new_test_programs RENAME TO test_programs; +PRAGMA foreign_keys = ON; + + +ALTER TABLE test_cases ADD COLUMN metadata_id INTEGER; + + +CREATE INDEX index_metadatas_by_id + ON metadatas (metadata_id); +CREATE INDEX index_test_programs_by_action_id + ON test_programs (action_id); +CREATE INDEX index_test_cases_by_test_programs_id + ON test_cases (test_program_id); + + +-- +-- Data migration +-- +-- This is, by far, the trickiest part of the migration. +-- TODO(jmmv): Describe the trickiness in here. +-- + + +-- Auxiliary table to construct the final contents of the metadatas table. +-- +-- We construct the contents by writing a row for every metadata property of +-- every test program and test case. Entries corresponding to a test program +-- will have the test_program_id field set to not NULL and entries corresponding +-- to test cases will have the test_case_id set to not NULL. +-- +-- The tricky part, however, is to create the individual identifiers for every +-- metadata entry. We do this by picking the minimum ROWID of a particular set +-- of properties that map to a single test_program_id or test_case_id. +CREATE TABLE tmp_metadatas ( + test_program_id INTEGER DEFAULT NULL, + test_case_id INTEGER DEFAULT NULL, + interface TEXT NOT NULL, + property_name TEXT NOT NULL, + property_value TEXT NOT NULL, + + UNIQUE (test_program_id, test_case_id, property_name) +); +CREATE INDEX index_tmp_metadatas_by_test_case_id + ON tmp_metadatas (test_case_id); +CREATE INDEX index_tmp_metadatas_by_test_program_id + ON tmp_metadatas (test_program_id); + + +-- Populate default metadata values for all test programs and test cases. +-- +-- We do this first to ensure that all test programs and test cases have +-- explicit values for their metadata. Because we want to keep historical data +-- for the tests, we must record these values unconditionally instead of relying +-- on the built-in values in the code. +-- +-- Once this is done, we override any values explicity set by the tests. +CREATE TABLE tmp_default_metadata ( + default_name TEXT PRIMARY KEY, + default_value TEXT NOT NULL +); +INSERT INTO tmp_default_metadata VALUES ('allowed_architectures', ''); +INSERT INTO tmp_default_metadata VALUES ('allowed_platforms', ''); +INSERT INTO tmp_default_metadata VALUES ('description', ''); +INSERT INTO tmp_default_metadata VALUES ('has_cleanup', 'false'); +INSERT INTO tmp_default_metadata VALUES ('required_configs', ''); +INSERT INTO tmp_default_metadata VALUES ('required_files', ''); +INSERT INTO tmp_default_metadata VALUES ('required_memory', '0'); +INSERT INTO tmp_default_metadata VALUES ('required_programs', ''); +INSERT INTO tmp_default_metadata VALUES ('required_user', ''); +INSERT INTO tmp_default_metadata VALUES ('timeout', '300'); +INSERT INTO tmp_metadatas + SELECT test_program_id, NULL, interface, default_name, default_value + FROM test_programs JOIN tmp_default_metadata; +INSERT INTO tmp_metadatas + SELECT NULL, test_case_id, interface, default_name, default_value + FROM test_programs JOIN test_cases + ON test_cases.test_program_id = test_programs.test_program_id + JOIN tmp_default_metadata; +DROP TABLE tmp_default_metadata; + + +-- Populate metadata overrides from plain test programs. +UPDATE tmp_metadatas + SET property_value = ( + SELECT CAST(timeout / 1000000 AS TEXT) FROM plain_test_programs AS aux + WHERE aux.test_program_id = tmp_metadatas.test_program_id) + WHERE test_program_id IS NOT NULL AND property_name = 'timeout' + AND interface = 'plain'; +UPDATE tmp_metadatas + SET property_value = ( + SELECT DISTINCT CAST(timeout / 1000000 AS TEXT) + FROM test_cases AS aux JOIN plain_test_programs + ON aux.test_program_id == plain_test_programs.test_program_id + WHERE aux.test_case_id = tmp_metadatas.test_case_id) + WHERE test_case_id IS NOT NULL AND property_name = 'timeout' + AND interface = 'plain'; + + +-- Populate metadata overrides from ATF test cases. +UPDATE atf_test_cases SET description = '' WHERE description IS NULL; +UPDATE atf_test_cases SET required_user = '' WHERE required_user IS NULL; + +UPDATE tmp_metadatas + SET property_value = ( + SELECT description FROM atf_test_cases AS aux + WHERE aux.test_case_id = tmp_metadatas.test_case_id) + WHERE test_case_id IS NOT NULL AND property_name = 'description' + AND interface = 'atf'; +UPDATE tmp_metadatas + SET property_value = ( + SELECT has_cleanup FROM atf_test_cases AS aux + WHERE aux.test_case_id = tmp_metadatas.test_case_id) + WHERE test_case_id IS NOT NULL AND property_name = 'has_cleanup' + AND interface = 'atf'; +UPDATE tmp_metadatas + SET property_value = ( + SELECT CAST(timeout / 1000000 AS TEXT) FROM atf_test_cases AS aux + WHERE aux.test_case_id = tmp_metadatas.test_case_id) + WHERE test_case_id IS NOT NULL AND property_name = 'timeout' + AND interface = 'atf'; +UPDATE tmp_metadatas + SET property_value = ( + SELECT CAST(required_memory AS TEXT) FROM atf_test_cases AS aux + WHERE aux.test_case_id = tmp_metadatas.test_case_id) + WHERE test_case_id IS NOT NULL AND property_name = 'required_memory' + AND interface = 'atf'; +UPDATE tmp_metadatas + SET property_value = ( + SELECT required_user FROM atf_test_cases AS aux + WHERE aux.test_case_id = tmp_metadatas.test_case_id) + WHERE test_case_id IS NOT NULL AND property_name = 'required_user' + AND interface = 'atf'; +UPDATE tmp_metadatas + SET property_value = ( + SELECT GROUP_CONCAT(aux.property_value, ' ') + FROM atf_test_cases_multivalues AS aux + WHERE aux.test_case_id = tmp_metadatas.test_case_id AND + aux.property_name = 'require.arch') + WHERE test_case_id IS NOT NULL AND property_name = 'allowed_architectures' + AND interface = 'atf' + AND EXISTS(SELECT 1 FROM atf_test_cases_multivalues AS aux + WHERE aux.test_case_id = tmp_metadatas.test_case_id + AND property_name = 'require.arch'); +UPDATE tmp_metadatas + SET property_value = ( + SELECT GROUP_CONCAT(aux.property_value, ' ') + FROM atf_test_cases_multivalues AS aux + WHERE aux.test_case_id = tmp_metadatas.test_case_id AND + aux.property_name = 'require.machine') + WHERE test_case_id IS NOT NULL AND property_name = 'allowed_platforms' + AND interface = 'atf' + AND EXISTS(SELECT 1 FROM atf_test_cases_multivalues AS aux + WHERE aux.test_case_id = tmp_metadatas.test_case_id + AND property_name = 'require.machine'); +UPDATE tmp_metadatas + SET property_value = ( + SELECT GROUP_CONCAT(aux.property_value, ' ') + FROM atf_test_cases_multivalues AS aux + WHERE aux.test_case_id = tmp_metadatas.test_case_id AND + aux.property_name = 'require.config') + WHERE test_case_id IS NOT NULL AND property_name = 'required_configs' + AND interface = 'atf' + AND EXISTS(SELECT 1 FROM atf_test_cases_multivalues AS aux + WHERE aux.test_case_id = tmp_metadatas.test_case_id + AND property_name = 'require.config'); +UPDATE tmp_metadatas + SET property_value = ( + SELECT GROUP_CONCAT(aux.property_value, ' ') + FROM atf_test_cases_multivalues AS aux + WHERE aux.test_case_id = tmp_metadatas.test_case_id AND + aux.property_name = 'require.files') + WHERE test_case_id IS NOT NULL AND property_name = 'required_files' + AND interface = 'atf' + AND EXISTS(SELECT 1 FROM atf_test_cases_multivalues AS aux + WHERE aux.test_case_id = tmp_metadatas.test_case_id + AND property_name = 'require.files'); +UPDATE tmp_metadatas + SET property_value = ( + SELECT GROUP_CONCAT(aux.property_value, ' ') + FROM atf_test_cases_multivalues AS aux + WHERE aux.test_case_id = tmp_metadatas.test_case_id AND + aux.property_name = 'require.progs') + WHERE test_case_id IS NOT NULL AND property_name = 'required_programs' + AND interface = 'atf' + AND EXISTS(SELECT 1 FROM atf_test_cases_multivalues AS aux + WHERE aux.test_case_id = tmp_metadatas.test_case_id + AND property_name = 'require.progs'); + + +-- Fill metadata_id pointers in the test_programs and test_cases tables. +UPDATE test_programs + SET metadata_id = ( + SELECT MIN(ROWID) FROM tmp_metadatas + WHERE tmp_metadatas.test_program_id = test_programs.test_program_id + ); +UPDATE test_cases + SET metadata_id = ( + SELECT MIN(ROWID) FROM tmp_metadatas + WHERE tmp_metadatas.test_case_id = test_cases.test_case_id + ); + + +-- Populate the metadatas table based on tmp_metadatas. +INSERT INTO metadatas (metadata_id, property_name, property_value) + SELECT ( + SELECT MIN(ROWID) FROM tmp_metadatas AS s + WHERE s.test_program_id = tmp_metadatas.test_program_id + ), property_name, property_value + FROM tmp_metadatas WHERE test_program_id IS NOT NULL; +INSERT INTO metadatas (metadata_id, property_name, property_value) + SELECT ( + SELECT MIN(ROWID) FROM tmp_metadatas AS s + WHERE s.test_case_id = tmp_metadatas.test_case_id + ), property_name, property_value + FROM tmp_metadatas WHERE test_case_id IS NOT NULL; + + +-- Drop temporary entities used during the migration. +DROP INDEX index_tmp_metadatas_by_test_program_id; +DROP INDEX index_tmp_metadatas_by_test_case_id; +DROP TABLE tmp_metadatas; + + +-- +-- Drop obsolete tables. +-- + + +DROP TABLE atf_test_cases; +DROP TABLE atf_test_cases_multivalues; +DROP TABLE plain_test_programs; + + +-- +-- Update the metadata version. +-- + + +INSERT INTO metadata (timestamp, schema_version) + VALUES (strftime('%s', 'now'), 2); diff --git a/external/bsd/kyua-cli/dist/store/schema_inttest.cpp b/external/bsd/kyua-cli/dist/store/schema_inttest.cpp new file mode 100644 index 000000000..12e0e42ec --- /dev/null +++ b/external/bsd/kyua-cli/dist/store/schema_inttest.cpp @@ -0,0 +1,502 @@ +// Copyright 2013 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "store/backend.hpp" + +#include +#include + +#include + +#include "engine/action.hpp" +#include "engine/context.hpp" +#include "engine/test_case.hpp" +#include "engine/test_program.hpp" +#include "engine/test_result.hpp" +#include "store/backend.hpp" +#include "store/transaction.hpp" +#include "utils/format/macros.hpp" +#include "utils/fs/path.hpp" +#include "utils/logging/operations.hpp" +#include "utils/sqlite/database.hpp" +#include "utils/stream.hpp" +#include "utils/units.hpp" + +namespace datetime = utils::datetime; +namespace fs = utils::fs; +namespace logging = utils::logging; +namespace sqlite = utils::sqlite; +namespace units = utils::units; + + +/// Executes an SQL script within a database. +/// +/// \param db Database in which to run the script. +/// \param path Path to the data file. +static void +exec_db_file(sqlite::database& db, const fs::path& path) +{ + std::ifstream input(path.c_str()); + if (!input) + ATF_FAIL(F("Failed to open %s") % path); + db.exec(utils::read_stream(input)); +} + + +/// Validates the contents of the action with identifier 1. +/// +/// \param transaction An open read transaction in the backend. +static void +check_action_1(store::transaction& transaction) +{ + const fs::path root("/some/root"); + std::map< std::string, std::string > environment; + const engine::context context_1(root, environment); + + const engine::action action_1(context_1); + + ATF_REQUIRE_EQ(action_1, transaction.get_action(1)); + + store::results_iterator iter = transaction.get_action_results(1); + ATF_REQUIRE(!iter); +} + + +/// Validates the contents of the action with identifier 2. +/// +/// \param transaction An open read transaction in the backend. +static void +check_action_2(store::transaction& transaction) +{ + const fs::path root("/test/suite/root"); + std::map< std::string, std::string > environment; + environment["HOME"] = "/home/test"; + environment["PATH"] = "/bin:/usr/bin"; + const engine::context context_2(root, environment); + + const engine::action action_2(context_2); + + ATF_REQUIRE_EQ(action_2, transaction.get_action(2)); + + engine::test_program test_program_1( + "plain", fs::path("foo_test"), fs::path("/test/suite/root"), + "suite-name", engine::metadata_builder().build()); + { + const engine::test_case_ptr test_case_1(new engine::test_case( + "plain", test_program_1, "main", + engine::metadata_builder().build())); + engine::test_cases_vector test_cases; + test_cases.push_back(test_case_1); + test_program_1.set_test_cases(test_cases); + } + const engine::test_result result_1(engine::test_result::passed); + + engine::test_program test_program_2( + "plain", fs::path("subdir/another_test"), fs::path("/test/suite/root"), + "subsuite-name", engine::metadata_builder() + .set_timeout(datetime::delta(10, 0)).build()); + { + const engine::test_case_ptr test_case_2(new engine::test_case( + "plain", test_program_2, "main", engine::metadata_builder() + .set_timeout(datetime::delta(10, 0)).build())); + engine::test_cases_vector test_cases; + test_cases.push_back(test_case_2); + test_program_2.set_test_cases(test_cases); + } + const engine::test_result result_2(engine::test_result::failed, + "Exited with code 1"); + + engine::test_program test_program_3( + "plain", fs::path("subdir/bar_test"), fs::path("/test/suite/root"), + "subsuite-name", engine::metadata_builder().build()); + { + const engine::test_case_ptr test_case_3(new engine::test_case( + "plain", test_program_3, "main", + engine::metadata_builder().build())); + engine::test_cases_vector test_cases; + test_cases.push_back(test_case_3); + test_program_3.set_test_cases(test_cases); + } + const engine::test_result result_3(engine::test_result::broken, + "Received signal 1"); + + engine::test_program test_program_4( + "plain", fs::path("top_test"), fs::path("/test/suite/root"), + "suite-name", engine::metadata_builder().build()); + { + const engine::test_case_ptr test_case_4(new engine::test_case( + "plain", test_program_4, "main", + engine::metadata_builder().build())); + engine::test_cases_vector test_cases; + test_cases.push_back(test_case_4); + test_program_4.set_test_cases(test_cases); + } + const engine::test_result result_4(engine::test_result::expected_failure, + "Known bug"); + + engine::test_program test_program_5( + "plain", fs::path("last_test"), fs::path("/test/suite/root"), + "suite-name", engine::metadata_builder().build()); + { + const engine::test_case_ptr test_case_5(new engine::test_case( + "plain", test_program_5, "main", + engine::metadata_builder().build())); + engine::test_cases_vector test_cases; + test_cases.push_back(test_case_5); + test_program_5.set_test_cases(test_cases); + } + const engine::test_result result_5(engine::test_result::skipped, + "Does not apply"); + + store::results_iterator iter = transaction.get_action_results(2); + ATF_REQUIRE(iter); + ATF_REQUIRE_EQ(test_program_1, *iter.test_program()); + ATF_REQUIRE_EQ("main", iter.test_case_name()); + ATF_REQUIRE_EQ(result_1, iter.result()); + ATF_REQUIRE(iter.stdout_contents().empty()); + ATF_REQUIRE(iter.stderr_contents().empty()); + ATF_REQUIRE_EQ(datetime::delta(10, 500), iter.duration()); + + ++iter; + ATF_REQUIRE(iter); + ATF_REQUIRE_EQ(test_program_5, *iter.test_program()); + ATF_REQUIRE_EQ("main", iter.test_case_name()); + ATF_REQUIRE_EQ(result_5, iter.result()); + ATF_REQUIRE(iter.stdout_contents().empty()); + ATF_REQUIRE(iter.stderr_contents().empty()); + ATF_REQUIRE_EQ(datetime::delta(6, 0), iter.duration()); + + ++iter; + ATF_REQUIRE(iter); + ATF_REQUIRE_EQ(test_program_2, *iter.test_program()); + ATF_REQUIRE_EQ("main", iter.test_case_name()); + ATF_REQUIRE_EQ(result_2, iter.result()); + ATF_REQUIRE_EQ("Test stdout", iter.stdout_contents()); + ATF_REQUIRE_EQ("Test stderr", iter.stderr_contents()); + ATF_REQUIRE_EQ(datetime::delta(0, 898821), iter.duration()); + + ++iter; + ATF_REQUIRE(iter); + ATF_REQUIRE_EQ(test_program_3, *iter.test_program()); + ATF_REQUIRE_EQ("main", iter.test_case_name()); + ATF_REQUIRE_EQ(result_3, iter.result()); + ATF_REQUIRE(iter.stdout_contents().empty()); + ATF_REQUIRE(iter.stderr_contents().empty()); + ATF_REQUIRE_EQ(datetime::delta(7, 481932), iter.duration()); + + ++iter; + ATF_REQUIRE(iter); + ATF_REQUIRE_EQ(test_program_4, *iter.test_program()); + ATF_REQUIRE_EQ("main", iter.test_case_name()); + ATF_REQUIRE_EQ(result_4, iter.result()); + ATF_REQUIRE(iter.stdout_contents().empty()); + ATF_REQUIRE(iter.stderr_contents().empty()); + ATF_REQUIRE_EQ(datetime::delta(0, 20000), iter.duration()); + + ++iter; + ATF_REQUIRE(!iter); +} + + +/// Validates the contents of the action with identifier 3. +/// +/// \param transaction An open read transaction in the backend. +static void +check_action_3(store::transaction& transaction) +{ + const fs::path root("/usr/tests"); + std::map< std::string, std::string > environment; + environment["PATH"] = "/bin:/usr/bin"; + const engine::context context_3(root, environment); + + const engine::action action_3(context_3); + + ATF_REQUIRE_EQ(action_3, transaction.get_action(3)); + + engine::test_program test_program_6( + "atf", fs::path("complex_test"), fs::path("/usr/tests"), + "suite-name", engine::metadata_builder().build()); + { + const engine::test_case_ptr test_case_6(new engine::test_case( + "atf", test_program_6, "this_passes", + engine::metadata_builder().build())); + const engine::test_case_ptr test_case_7(new engine::test_case( + "atf", test_program_6, "this_fails", + engine::metadata_builder() + .set_description("Test description") + .set_has_cleanup(true) + .set_required_memory(units::bytes(128)) + .set_required_user("root").build())); + const engine::test_case_ptr test_case_8(new engine::test_case( + "atf", test_program_6, "this_skips", + engine::metadata_builder() + .add_allowed_architecture("powerpc") + .add_allowed_architecture("x86_64") + .add_allowed_platform("amd64") + .add_allowed_platform("macppc") + .add_required_config("X-foo") + .add_required_config("unprivileged_user") + .add_required_file(fs::path("/the/data/file")) + .add_required_program(fs::path("/bin/ls")) + .add_required_program(fs::path("cp")) + .set_description("Test explanation") + .set_has_cleanup(true) + .set_required_memory(units::bytes(512)) + .set_required_user("unprivileged") + .set_timeout(datetime::delta(600, 0)) + .build())); + engine::test_cases_vector test_cases; + test_cases.push_back(test_case_6); + test_cases.push_back(test_case_7); + test_cases.push_back(test_case_8); + test_program_6.set_test_cases(test_cases); + } + const engine::test_result result_6(engine::test_result::passed); + const engine::test_result result_7(engine::test_result::failed, + "Some reason"); + const engine::test_result result_8(engine::test_result::skipped, + "Another reason"); + + engine::test_program test_program_7( + "atf", fs::path("simple_test"), fs::path("/usr/tests"), + "subsuite-name", engine::metadata_builder().build()); + { + const engine::test_case_ptr test_case_9(new engine::test_case( + "atf", test_program_7, "main", + engine::metadata_builder() + .set_description("More text") + .set_has_cleanup(true) + .set_required_memory(units::bytes(128)) + .set_required_user("unprivileged") + .build())); + engine::test_cases_vector test_cases; + test_cases.push_back(test_case_9); + test_program_7.set_test_cases(test_cases); + } + const engine::test_result result_9(engine::test_result::failed, + "Exited with code 1"); + + store::results_iterator iter = transaction.get_action_results(3); + ATF_REQUIRE(iter); + ATF_REQUIRE_EQ(test_program_6, *iter.test_program()); + ATF_REQUIRE_EQ("this_fails", iter.test_case_name()); + ATF_REQUIRE_EQ(result_7, iter.result()); + ATF_REQUIRE(iter.stdout_contents().empty()); + ATF_REQUIRE(iter.stderr_contents().empty()); + ATF_REQUIRE_EQ(datetime::delta(1, 897182), iter.duration()); + + ++iter; + ATF_REQUIRE(iter); + ATF_REQUIRE_EQ(test_program_6, *iter.test_program()); + ATF_REQUIRE_EQ("this_passes", iter.test_case_name()); + ATF_REQUIRE_EQ(result_6, iter.result()); + ATF_REQUIRE(iter.stdout_contents().empty()); + ATF_REQUIRE(iter.stderr_contents().empty()); + ATF_REQUIRE_EQ(datetime::delta(6, 0), iter.duration()); + + ++iter; + ATF_REQUIRE(iter); + ATF_REQUIRE_EQ(test_program_6, *iter.test_program()); + ATF_REQUIRE_EQ("this_skips", iter.test_case_name()); + ATF_REQUIRE_EQ(result_8, iter.result()); + ATF_REQUIRE_EQ("Another stdout", iter.stdout_contents()); + ATF_REQUIRE(iter.stderr_contents().empty()); + ATF_REQUIRE_EQ(datetime::delta(0, 817987), iter.duration()); + + ++iter; + ATF_REQUIRE(iter); + ATF_REQUIRE_EQ(test_program_7, *iter.test_program()); + ATF_REQUIRE_EQ("main", iter.test_case_name()); + ATF_REQUIRE_EQ(result_9, iter.result()); + ATF_REQUIRE(iter.stdout_contents().empty()); + ATF_REQUIRE_EQ("Another stderr", iter.stderr_contents()); + ATF_REQUIRE_EQ(datetime::delta(9, 961700), iter.duration()); + + ++iter; + ATF_REQUIRE(!iter); +} + + +/// Validates the contents of the action with identifier 4. +/// +/// \param transaction An open read transaction in the backend. +static void +check_action_4(store::transaction& transaction) +{ + const fs::path root("/usr/tests"); + std::map< std::string, std::string > environment; + environment["LANG"] = "C"; + environment["PATH"] = "/bin:/usr/bin"; + environment["TERM"] = "xterm"; + const engine::context context_4(root, environment); + + const engine::action action_4(context_4); + + ATF_REQUIRE_EQ(action_4, transaction.get_action(4)); + + engine::test_program test_program_8( + "plain", fs::path("subdir/another_test"), fs::path("/usr/tests"), + "subsuite-name", engine::metadata_builder() + .set_timeout(datetime::delta(10, 0)).build()); + { + const engine::test_case_ptr test_case_10(new engine::test_case( + "plain", test_program_8, "main", + engine::metadata_builder() + .set_timeout(datetime::delta(10, 0)).build())); + engine::test_cases_vector test_cases; + test_cases.push_back(test_case_10); + test_program_8.set_test_cases(test_cases); + } + const engine::test_result result_10(engine::test_result::failed, + "Exit failure"); + + engine::test_program test_program_9( + "atf", fs::path("complex_test"), fs::path("/usr/tests"), + "suite-name", engine::metadata_builder().build()); + { + const engine::test_case_ptr test_case_11(new engine::test_case( + "atf", test_program_9, "this_passes", + engine::metadata_builder().build())); + const engine::test_case_ptr test_case_12(new engine::test_case( + "atf", test_program_9, "this_fails", + engine::metadata_builder() + .set_description("Test description") + .set_required_user("root") + .build())); + engine::test_cases_vector test_cases; + test_cases.push_back(test_case_11); + test_cases.push_back(test_case_12); + test_program_9.set_test_cases(test_cases); + } + const engine::test_result result_11(engine::test_result::passed); + const engine::test_result result_12(engine::test_result::failed, + "Some reason"); + + store::results_iterator iter = transaction.get_action_results(4); + ATF_REQUIRE(iter); + ATF_REQUIRE_EQ(test_program_9, *iter.test_program()); + ATF_REQUIRE_EQ("this_fails", iter.test_case_name()); + ATF_REQUIRE_EQ(result_12, iter.result()); + ATF_REQUIRE(iter.stdout_contents().empty()); + ATF_REQUIRE(iter.stderr_contents().empty()); + ATF_REQUIRE_EQ(datetime::delta(1, 905000), iter.duration()); + + ++iter; + ATF_REQUIRE(iter); + ATF_REQUIRE_EQ(test_program_9, *iter.test_program()); + ATF_REQUIRE_EQ("this_passes", iter.test_case_name()); + ATF_REQUIRE_EQ(result_11, iter.result()); + ATF_REQUIRE(iter.stdout_contents().empty()); + ATF_REQUIRE(iter.stderr_contents().empty()); + ATF_REQUIRE_EQ(datetime::delta(0, 500000), iter.duration()); + + ++iter; + ATF_REQUIRE(iter); + ATF_REQUIRE_EQ(test_program_8, *iter.test_program()); + ATF_REQUIRE_EQ("main", iter.test_case_name()); + ATF_REQUIRE_EQ(result_10, iter.result()); + ATF_REQUIRE_EQ("Test stdout", iter.stdout_contents()); + ATF_REQUIRE_EQ("Test stderr", iter.stderr_contents()); + ATF_REQUIRE_EQ(datetime::delta(1, 0), iter.duration()); + + ++iter; + ATF_REQUIRE(!iter); +} + + +/// Validates the contents of an open database agains good known values. +/// +/// \param transaction An open read-only backend. +static void +check_data(store::backend& backend) +{ + store::transaction transaction = backend.start(); + check_action_1(transaction); + check_action_2(transaction); + check_action_3(transaction); + check_action_4(transaction); +} + + +ATF_TEST_CASE(current_schema); +ATF_TEST_CASE_HEAD(current_schema) +{ + logging::set_inmemory(); + const std::string required_files = + store::detail::schema_file().str() + + " " + (fs::path(get_config_var("srcdir")) / "testdata_v2.sql").str(); + set_md_var("require.files", required_files); +} +ATF_TEST_CASE_BODY(current_schema) +{ + const fs::path testpath("test.db"); + + sqlite::database db = sqlite::database::open( + testpath, sqlite::open_readwrite | sqlite::open_create); + exec_db_file(db, store::detail::schema_file()); + exec_db_file(db, fs::path(get_config_var("srcdir")) / "testdata_v2.sql"); + db.close(); + + store::backend backend = store::backend::open_ro(testpath); + check_data(backend); +} + + +ATF_TEST_CASE(migrate_schema__v1_to_v2); +ATF_TEST_CASE_HEAD(migrate_schema__v1_to_v2) +{ + logging::set_inmemory(); + const std::string required_files = + store::detail::migration_file(1, 2).str() + + " " + (fs::path(get_config_var("srcdir")) / "schema_v1.sql").str() + + " " + (fs::path(get_config_var("srcdir")) / "testdata_v1.sql").str(); + set_md_var("require.files", required_files); +} +ATF_TEST_CASE_BODY(migrate_schema__v1_to_v2) +{ + const fs::path testpath("test.db"); + + sqlite::database db = sqlite::database::open( + testpath, sqlite::open_readwrite | sqlite::open_create); + exec_db_file(db, fs::path(get_config_var("srcdir")) / "schema_v1.sql"); + exec_db_file(db, fs::path(get_config_var("srcdir")) / "testdata_v1.sql"); + db.close(); + + store::migrate_schema(fs::path("test.db")); + + store::backend backend = store::backend::open_ro(testpath); + check_data(backend); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, current_schema); + + ATF_ADD_TEST_CASE(tcs, migrate_schema__v1_to_v2); +} diff --git a/external/bsd/kyua-cli/dist/store/schema_v1.sql b/external/bsd/kyua-cli/dist/store/schema_v1.sql new file mode 100644 index 000000000..33f1b6cbd --- /dev/null +++ b/external/bsd/kyua-cli/dist/store/schema_v1.sql @@ -0,0 +1,314 @@ +-- Copyright 2011 Google Inc. +-- All rights reserved. +-- +-- Redistribution and use in source and binary forms, with or without +-- modification, are permitted provided that the following conditions are +-- met: +-- +-- * Redistributions of source code must retain the above copyright +-- notice, this list of conditions and the following disclaimer. +-- * Redistributions in binary form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- * Neither the name of Google Inc. nor the names of its contributors +-- may be used to endorse or promote products derived from this software +-- without specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +-- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +-- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +-- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +-- OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +-- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +-- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +-- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +-- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +-- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +-- \file store/schema_v1.sql +-- Definition of the database schema. +-- +-- The whole contents of this file are wrapped in a transaction. We want +-- to ensure that the initial contents of the database (the table layout as +-- well as any predefined values) are written atomically to simplify error +-- handling in our code. + + +BEGIN TRANSACTION; + + +-- ------------------------------------------------------------------------- +-- Metadata. +-- ------------------------------------------------------------------------- + + +-- Database-wide properties. +-- +-- Rows in this table are immutable: modifying the metadata implies writing +-- a new record with a larger timestamp value, and never updating previous +-- records. When extracting data from this table, the only "valid" row is +-- the one with the highest timestamp. All the other rows are meaningless. +-- +-- In other words, this table keeps the history of the database metadata. +-- The only reason for doing this is for debugging purposes. It may come +-- in handy to know when a particular database-wide operation happened if +-- it turns out that the database got corrupted. +CREATE TABLE metadata ( + timestamp TIMESTAMP PRIMARY KEY CHECK (timestamp >= 0), + schema_version INTEGER NOT NULL CHECK (schema_version >= 1) +); + + +-- ------------------------------------------------------------------------- +-- Contexts. +-- ------------------------------------------------------------------------- + + +-- Execution contexts. +-- +-- A context represents the execution environment of a particular action. +-- Because every action is invoked by the user, the context may have +-- changed. We record such information for information and debugging +-- purposes. +CREATE TABLE contexts ( + context_id INTEGER PRIMARY KEY AUTOINCREMENT, + cwd TEXT NOT NULL + + -- TODO(jmmv): Record the run-time configuration. +); + + +-- Environment variables of a context. +CREATE TABLE env_vars ( + context_id INTEGER REFERENCES contexts, + var_name TEXT NOT NULL, + var_value TEXT NOT NULL, + + PRIMARY KEY (context_id, var_name) +); + + +-- ------------------------------------------------------------------------- +-- Actions. +-- ------------------------------------------------------------------------- + + +-- Representation of user-initiated actions. +-- +-- An action is an operation initiated by the user. At the moment, the +-- only operation Kyua supports is the "test" operation (in the future we +-- should be able to store, e.g. build logs). To keep things simple the +-- database schema is restricted to represent one single action. +CREATE TABLE actions ( + action_id INTEGER PRIMARY KEY AUTOINCREMENT, + context_id INTEGER REFERENCES contexts +); + + +-- ------------------------------------------------------------------------- +-- Test suites. +-- +-- The tables in this section represent all the components that form a test +-- suite. This includes data about the test suite itself (test programs +-- and test cases), and also the data about particular runs (test results). +-- +-- As you will notice, every object belongs to a particular action, has a +-- unique identifier and there is no attempt to deduplicate data. This +-- comes from the fact that a test suite is not "stable" over time: i.e. on +-- each execution of the test suite, test programs and test cases may have +-- come and gone. This has the interesting result of making the +-- distinction of a test case and a test result a pure syntactic +-- difference, because there is always a 1:1 relation. +-- +-- The code that performs the processing of the actions is the component in +-- charge of finding correlations between test programs and test cases +-- across different actions. +-- ------------------------------------------------------------------------- + + +-- Representation of a test program. +-- +-- At the moment, there are no substantial differences between the +-- different interfaces, so we can simplify the design by with having a +-- single table representing all test caes. We may need to revisit this in +-- the future. +CREATE TABLE test_programs ( + test_program_id INTEGER PRIMARY KEY AUTOINCREMENT, + action_id INTEGER REFERENCES actions, + + -- The absolute path to the test program. This should not be necessary + -- because it is basically the concatenation of root and relative_path. + -- However, this allows us to very easily search for test programs + -- regardless of where they were executed from. (I.e. different + -- combinations of root + relative_path can map to the same absolute path). + absolute_path NOT NULL, + + -- The path to the root of the test suite (where the Kyuafile lives). + root TEXT NOT NULL, + + -- The path to the test program, relative to the root. + relative_path NOT NULL, + + -- Name of the test suite the test program belongs to. + test_suite_name TEXT NOT NULL, + + -- The name of the test program interface. + -- + -- Note that this indicates both the interface for the test program and + -- its test cases. See below for the corresponding detail tables. + interface TEXT NOT NULL +); + + +-- Representation of a test case. +-- +-- At the moment, there are no substantial differences between the +-- different interfaces, so we can simplify the design by with having a +-- single table representing all test caes. We may need to revisit this in +-- the future. +CREATE TABLE test_cases ( + test_case_id INTEGER PRIMARY KEY AUTOINCREMENT, + test_program_id INTEGER REFERENCES test_programs, + name TEXT NOT NULL +); + + +-- Representation of test case results. +-- +-- Note that there is a 1:1 relation between test cases and their results. +-- This is a result of storing the information of a test case on every +-- single action. +CREATE TABLE test_results ( + test_case_id INTEGER PRIMARY KEY REFERENCES test_cases, + result_type TEXT NOT NULL, + result_reason TEXT, + + start_time TIMESTAMP NOT NULL, + end_time TIMESTAMP NOT NULL +); + + +-- Collection of output files of the test case. +CREATE TABLE test_case_files ( + test_case_id INTEGER NOT NULL REFERENCES test_cases, + + -- The raw name of the file. + -- + -- The special names '__STDOUT__' and '__STDERR__' are reserved to hold + -- the stdout and stderr of the test case, respectively. If any of + -- these are empty, there will be no corresponding entry in this table + -- (hence why we do not allow NULLs in these fields). + file_name TEXT NOT NULL, + + -- Pointer to the file itself. + file_id INTEGER NOT NULL REFERENCES files, + + PRIMARY KEY (test_case_id, file_name) +); + + +-- ------------------------------------------------------------------------- +-- Detail tables for the 'atf' test interface. +-- ------------------------------------------------------------------------- + + +-- Properties specific to 'atf' test cases. +-- +-- This table contains the representation of singly-valued properties such +-- as 'timeout'. Properties that can have more than one (textual) value +-- are stored in the atf_test_cases_multivalues table. +-- +-- Note that all properties can be NULL because test cases are not required +-- to define them. +CREATE TABLE atf_test_cases ( + test_case_id INTEGER PRIMARY KEY REFERENCES test_cases, + + -- Free-form description of the text case. + description TEXT, + + -- Either 'true' or 'false', indicating whether the test case has a + -- cleanup routine or not. + has_cleanup TEXT, + + -- The timeout for the test case in microseconds. + timeout INTEGER, + + -- The amount of physical memory required by the test case. + required_memory INTEGER, + + -- Either 'root' or 'unprivileged', indicating the privileges required by + -- the test case. + required_user TEXT +); + + +-- Representation of test case properties that have more than one value. +-- +-- While we could store the flattened values of the properties as provided +-- by the test case itself, we choose to store the processed, split +-- representation. This allows us to perform queries about the test cases +-- directly on the database without doing text processing; for example, +-- "get all test cases that require /bin/ls". +CREATE TABLE atf_test_cases_multivalues ( + test_case_id INTEGER REFERENCES test_cases, + + -- The name of the property; for example, 'require.progs'. + property_name TEXT NOT NULL, + + -- One of the values of the property. + property_value TEXT NOT NULL +); + + +-- ------------------------------------------------------------------------- +-- Detail tables for the 'plain' test interface. +-- ------------------------------------------------------------------------- + + +-- Properties specific to 'plain' test programs. +CREATE TABLE plain_test_programs ( + test_program_id INTEGER PRIMARY KEY REFERENCES test_programs, + + -- The timeout for the test cases in this test program. While this + -- setting has a default value for test programs, we explicitly record + -- the information here. The "default value" used when the test + -- program was run might change over time, so we want to know what it + -- was exactly when this was run. + timeout INTEGER NOT NULL +); + + +-- ------------------------------------------------------------------------- +-- Verbatim files. +-- ------------------------------------------------------------------------- + + +-- Copies of files or logs generated during testing. +-- +-- TODO(jmmv): This will probably grow to unmanageable sizes. We should add a +-- hash to the file contents and use that as the primary key instead. +CREATE TABLE files ( + file_id INTEGER PRIMARY KEY, + + contents BLOB NOT NULL +); + + +-- ------------------------------------------------------------------------- +-- Initialization of values. +-- ------------------------------------------------------------------------- + + +-- Create a new metadata record. +-- +-- For every new database, we want to ensure that the metadata is valid if +-- the database creation (i.e. the whole transaction) succeeded. +-- +-- If you modify the value of the schema version in this statement, you +-- will also have to modify the version encoded in the backend module. +INSERT INTO metadata (timestamp, schema_version) + VALUES (strftime('%s', 'now'), 1); + + +COMMIT TRANSACTION; diff --git a/external/bsd/kyua-cli/dist/store/schema_v2.sql b/external/bsd/kyua-cli/dist/store/schema_v2.sql new file mode 100644 index 000000000..d0d4780aa --- /dev/null +++ b/external/bsd/kyua-cli/dist/store/schema_v2.sql @@ -0,0 +1,293 @@ +-- Copyright 2012 Google Inc. +-- All rights reserved. +-- +-- Redistribution and use in source and binary forms, with or without +-- modification, are permitted provided that the following conditions are +-- met: +-- +-- * Redistributions of source code must retain the above copyright +-- notice, this list of conditions and the following disclaimer. +-- * Redistributions in binary form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- * Neither the name of Google Inc. nor the names of its contributors +-- may be used to endorse or promote products derived from this software +-- without specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +-- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +-- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +-- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +-- OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +-- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +-- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +-- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +-- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +-- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +-- \file store/schema_v2.sql +-- Definition of the database schema. +-- +-- The whole contents of this file are wrapped in a transaction. We want +-- to ensure that the initial contents of the database (the table layout as +-- well as any predefined values) are written atomically to simplify error +-- handling in our code. + + +BEGIN TRANSACTION; + + +-- ------------------------------------------------------------------------- +-- Metadata. +-- ------------------------------------------------------------------------- + + +-- Database-wide properties. +-- +-- Rows in this table are immutable: modifying the metadata implies writing +-- a new record with a new schema_version greater than all existing +-- records, and never updating previous records. When extracting data from +-- this table, the only "valid" row is the one with the highest +-- scheam_version. All the other rows are meaningless and only exist for +-- historical purposes. +-- +-- In other words, this table keeps the history of the database metadata. +-- The only reason for doing this is for debugging purposes. It may come +-- in handy to know when a particular database-wide operation happened if +-- it turns out that the database got corrupted. +CREATE TABLE metadata ( + schema_version INTEGER PRIMARY KEY CHECK (schema_version >= 1), + timestamp TIMESTAMP NOT NULL CHECK (timestamp >= 0) +); + + +-- ------------------------------------------------------------------------- +-- Contexts. +-- ------------------------------------------------------------------------- + + +-- Execution contexts. +-- +-- A context represents the execution environment of a particular action. +-- Because every action is invoked by the user, the context may have +-- changed. We record such information for information and debugging +-- purposes. +CREATE TABLE contexts ( + context_id INTEGER PRIMARY KEY AUTOINCREMENT, + cwd TEXT NOT NULL + + -- TODO(jmmv): Record the run-time configuration. +); + + +-- Environment variables of a context. +CREATE TABLE env_vars ( + context_id INTEGER REFERENCES contexts, + var_name TEXT NOT NULL, + var_value TEXT NOT NULL, + + PRIMARY KEY (context_id, var_name) +); + + +-- ------------------------------------------------------------------------- +-- Actions. +-- ------------------------------------------------------------------------- + + +-- Representation of user-initiated actions. +-- +-- An action is an operation initiated by the user. At the moment, the +-- only operation Kyua supports is the "test" operation (in the future we +-- should be able to store, e.g. build logs). To keep things simple the +-- database schema is restricted to represent one single action. +CREATE TABLE actions ( + action_id INTEGER PRIMARY KEY AUTOINCREMENT, + context_id INTEGER REFERENCES contexts +); + + +-- ------------------------------------------------------------------------- +-- Test suites. +-- +-- The tables in this section represent all the components that form a test +-- suite. This includes data about the test suite itself (test programs +-- and test cases), and also the data about particular runs (test results). +-- +-- As you will notice, every object belongs to a particular action, has a +-- unique identifier and there is no attempt to deduplicate data. This +-- comes from the fact that a test suite is not "stable" over time: i.e. on +-- each execution of the test suite, test programs and test cases may have +-- come and gone. This has the interesting result of making the +-- distinction of a test case and a test result a pure syntactic +-- difference, because there is always a 1:1 relation. +-- +-- The code that performs the processing of the actions is the component in +-- charge of finding correlations between test programs and test cases +-- across different actions. +-- ------------------------------------------------------------------------- + + +-- Representation of the metadata objects. +-- +-- The way this table works is like this: every time we record a metadata +-- object, we calculate what its identifier should be as the last rowid of +-- the table. All properties of that metadata object thus receive the same +-- identifier. +CREATE TABLE metadatas ( + metadata_id INTEGER NOT NULL, + + -- The name of the property. + property_name TEXT NOT NULL, + + -- One of the values of the property. + property_value TEXT, + + PRIMARY KEY (metadata_id, property_name) +); + + +-- Optimize the loading of the metadata of any single entity. +-- +-- The metadata_id column of the metadatas table is not enough to act as a +-- primary key, yet we need to locate entries in the metadatas table solely by +-- their identifier. +-- +-- TODO(jmmv): I think this index is useless given that the primary key in the +-- metadatas table includes the metadata_id as the first component. Need to +-- verify this and drop the index or this comment appropriately. +CREATE INDEX index_metadatas_by_id + ON metadatas (metadata_id); + + +-- Representation of a test program. +-- +-- At the moment, there are no substantial differences between the +-- different interfaces, so we can simplify the design by with having a +-- single table representing all test caes. We may need to revisit this in +-- the future. +CREATE TABLE test_programs ( + test_program_id INTEGER PRIMARY KEY AUTOINCREMENT, + action_id INTEGER REFERENCES actions, + + -- The absolute path to the test program. This should not be necessary + -- because it is basically the concatenation of root and relative_path. + -- However, this allows us to very easily search for test programs + -- regardless of where they were executed from. (I.e. different + -- combinations of root + relative_path can map to the same absolute path). + absolute_path TEXT NOT NULL, + + -- The path to the root of the test suite (where the Kyuafile lives). + root TEXT NOT NULL, + + -- The path to the test program, relative to the root. + relative_path TEXT NOT NULL, + + -- Name of the test suite the test program belongs to. + test_suite_name TEXT NOT NULL, + + -- Reference to the various rows of metadatas. + metadata_id INTEGER, + + -- The name of the test program interface. + -- + -- Note that this indicates both the interface for the test program and + -- its test cases. See below for the corresponding detail tables. + interface TEXT NOT NULL +); + + +-- Optimize the lookup of test programs by the action they belong to. +CREATE INDEX index_test_programs_by_action_id + ON test_programs (action_id); + + +-- Representation of a test case. +-- +-- At the moment, there are no substantial differences between the +-- different interfaces, so we can simplify the design by with having a +-- single table representing all test caes. We may need to revisit this in +-- the future. +CREATE TABLE test_cases ( + test_case_id INTEGER PRIMARY KEY AUTOINCREMENT, + test_program_id INTEGER REFERENCES test_programs, + name TEXT NOT NULL, + + -- Reference to the various rows of metadatas. + metadata_id INTEGER +); + + +-- Optimize the loading of all test cases that are part of a test program. +CREATE INDEX index_test_cases_by_test_programs_id + ON test_cases (test_program_id); + + +-- Representation of test case results. +-- +-- Note that there is a 1:1 relation between test cases and their results. +-- This is a result of storing the information of a test case on every +-- single action. +CREATE TABLE test_results ( + test_case_id INTEGER PRIMARY KEY REFERENCES test_cases, + result_type TEXT NOT NULL, + result_reason TEXT, + + start_time TIMESTAMP NOT NULL, + end_time TIMESTAMP NOT NULL +); + + +-- Collection of output files of the test case. +CREATE TABLE test_case_files ( + test_case_id INTEGER NOT NULL REFERENCES test_cases, + + -- The raw name of the file. + -- + -- The special names '__STDOUT__' and '__STDERR__' are reserved to hold + -- the stdout and stderr of the test case, respectively. If any of + -- these are empty, there will be no corresponding entry in this table + -- (hence why we do not allow NULLs in these fields). + file_name TEXT NOT NULL, + + -- Pointer to the file itself. + file_id INTEGER NOT NULL REFERENCES files, + + PRIMARY KEY (test_case_id, file_name) +); + + +-- ------------------------------------------------------------------------- +-- Verbatim files. +-- ------------------------------------------------------------------------- + + +-- Copies of files or logs generated during testing. +-- +-- TODO(jmmv): This will probably grow to unmanageable sizes. We should add a +-- hash to the file contents and use that as the primary key instead. +CREATE TABLE files ( + file_id INTEGER PRIMARY KEY, + + contents BLOB NOT NULL +); + + +-- ------------------------------------------------------------------------- +-- Initialization of values. +-- ------------------------------------------------------------------------- + + +-- Create a new metadata record. +-- +-- For every new database, we want to ensure that the metadata is valid if +-- the database creation (i.e. the whole transaction) succeeded. +-- +-- If you modify the value of the schema version in this statement, you +-- will also have to modify the version encoded in the backend module. +INSERT INTO metadata (timestamp, schema_version) + VALUES (strftime('%s', 'now'), 2); + + +COMMIT TRANSACTION; diff --git a/external/bsd/kyua-cli/dist/store/testdata_v1.sql b/external/bsd/kyua-cli/dist/store/testdata_v1.sql new file mode 100644 index 000000000..d2d9a5ba0 --- /dev/null +++ b/external/bsd/kyua-cli/dist/store/testdata_v1.sql @@ -0,0 +1,330 @@ +-- Copyright 2013 Google Inc. +-- All rights reserved. +-- +-- Redistribution and use in source and binary forms, with or without +-- modification, are permitted provided that the following conditions are +-- met: +-- +-- * Redistributions of source code must retain the above copyright +-- notice, this list of conditions and the following disclaimer. +-- * Redistributions in binary form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- * Neither the name of Google Inc. nor the names of its contributors +-- may be used to endorse or promote products derived from this software +-- without specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +-- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +-- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +-- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +-- OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +-- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +-- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +-- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +-- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +-- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +-- \file store/testdata_v1.sql +-- Populates a v1 database with some test data. + + +BEGIN TRANSACTION; + + +-- +-- Action 1: Empty context and no test programs nor test cases. +-- + + +-- context_id 1 +INSERT INTO contexts (context_id, cwd) VALUES (1, '/some/root'); + +-- action_id 1 +INSERT INTO actions (action_id, context_id) VALUES (1, 1); + + +-- +-- Action 2: Plain test programs only. +-- +-- This action contains 5 test programs, each with one test case, and each +-- reporting one of all possible result types. +-- + + +-- context_id 2 +INSERT INTO contexts (context_id, cwd) VALUES (2, '/test/suite/root'); +INSERT INTO env_vars (context_id, var_name, var_value) + VALUES (2, 'HOME', '/home/test'); +INSERT INTO env_vars (context_id, var_name, var_value) + VALUES (2, 'PATH', '/bin:/usr/bin'); + +-- action_id 2 +INSERT INTO actions (action_id, context_id) VALUES (2, 2); + +-- test_program_id 1 +INSERT INTO test_programs (test_program_id, action_id, absolute_path, root, + relative_path, test_suite_name, interface) + VALUES (1, 2, '/test/suite/root/foo_test', '/test/suite/root', + 'foo_test', 'suite-name', 'plain'); +INSERT INTO plain_test_programs (test_program_id, timeout) + VALUES (1, 300000000); + +-- test_case_id 1 +INSERT INTO test_cases (test_case_id, test_program_id, name) + VALUES (1, 1, 'main'); +INSERT INTO test_results (test_case_id, result_type, result_reason, start_time, + end_time) + VALUES (1, 'passed', NULL, 1357643611000000, 1357643621000500); + +-- test_program_id 2 +INSERT INTO test_programs (test_program_id, action_id, absolute_path, root, + relative_path, test_suite_name, interface) + VALUES (2, 2, '/test/suite/root/subdir/another_test', '/test/suite/root', + 'subdir/another_test', 'subsuite-name', 'plain'); +INSERT INTO plain_test_programs (test_program_id, timeout) + VALUES (2, 10000000); + +-- test_case_id 2 +INSERT INTO test_cases (test_case_id, test_program_id, name) + VALUES (2, 2, 'main'); +INSERT INTO test_results (test_case_id, result_type, result_reason, start_time, + end_time) + VALUES (2, 'failed', 'Exited with code 1', + 1357643622001200, 1357643622900021); + +-- file_id 1 +INSERT INTO files (file_id, contents) VALUES (1, x'54657374207374646f7574'); +INSERT INTO test_case_files (test_case_id, file_name, file_id) + VALUES (2, '__STDOUT__', 1); + +-- file_id 2 +INSERT INTO files (file_id, contents) VALUES (2, x'5465737420737464657272'); +INSERT INTO test_case_files (test_case_id, file_name, file_id) + VALUES (2, '__STDERR__', 2); + +-- test_program_id 3 +INSERT INTO test_programs (test_program_id, action_id, absolute_path, root, + relative_path, test_suite_name, interface) + VALUES (3, 2, '/test/suite/root/subdir/bar_test', '/test/suite/root', + 'subdir/bar_test', 'subsuite-name', 'plain'); +INSERT INTO plain_test_programs (test_program_id, timeout) + VALUES (3, 300000000); + +-- test_case_id 3 +INSERT INTO test_cases (test_case_id, test_program_id, name) + VALUES (3, 3, 'main'); +INSERT INTO test_results (test_case_id, result_type, result_reason, start_time, + end_time) + VALUES (3, 'broken', 'Received signal 1', + 1357643623500000, 1357643630981932); + +-- test_program_id 4 +INSERT INTO test_programs (test_program_id, action_id, absolute_path, root, + relative_path, test_suite_name, interface) + VALUES (4, 2, '/test/suite/root/top_test', '/test/suite/root', + 'top_test', 'suite-name', 'plain'); +INSERT INTO plain_test_programs (test_program_id, timeout) + VALUES (4, 300000000); + +-- test_case_id 4 +INSERT INTO test_cases (test_case_id, test_program_id, name) + VALUES (4, 4, 'main'); +INSERT INTO test_results (test_case_id, result_type, result_reason, start_time, + end_time) + VALUES (4, 'expected_failure', 'Known bug', + 1357643631000000, 1357643631020000); + +-- test_program_id 5 +INSERT INTO test_programs (test_program_id, action_id, absolute_path, root, + relative_path, test_suite_name, interface) + VALUES (5, 2, '/test/suite/root/last_test', '/test/suite/root', + 'last_test', 'suite-name', 'plain'); +INSERT INTO plain_test_programs (test_program_id, timeout) + VALUES (5, 300000000); + +-- test_case_id 5 +INSERT INTO test_cases (test_case_id, test_program_id, name) + VALUES (5, 5, 'main'); +INSERT INTO test_results (test_case_id, result_type, result_reason, start_time, + end_time) + VALUES (5, 'skipped', 'Does not apply', 1357643632000000, 1357643638000000); + + +-- +-- Action 3: ATF test programs only. +-- + + +-- context_id 3 +INSERT INTO contexts (context_id, cwd) VALUES (3, '/usr/tests'); +INSERT INTO env_vars (context_id, var_name, var_value) + VALUES (3, 'PATH', '/bin:/usr/bin'); + +-- action_id 3 +INSERT INTO actions (action_id, context_id) VALUES (3, 3); + +-- test_program_id 6 +INSERT INTO test_programs (test_program_id, action_id, absolute_path, root, + relative_path, test_suite_name, interface) + VALUES (6, 3, '/usr/tests/complex_test', '/usr/tests', + 'complex_test', 'suite-name', 'atf'); + +-- test_case_id 6, passed, no optional metadata. +INSERT INTO test_cases (test_case_id, test_program_id, name) + VALUES (6, 6, 'this_passes'); +INSERT INTO test_results (test_case_id, result_type, result_reason, start_time, + end_time) + VALUES (6, 'passed', NULL, 1357648712000000, 1357648718000000); +INSERT INTO atf_test_cases (test_case_id, description, has_cleanup, timeout, + required_memory, required_user) + VALUES (6, NULL, 'false', 300000000, 0, NULL); + +-- test_case_id 7, failed, optional non-multivalue metadata. +INSERT INTO test_cases (test_case_id, test_program_id, name) + VALUES (7, 6, 'this_fails'); +INSERT INTO test_results (test_case_id, result_type, result_reason, start_time, + end_time) + VALUES (7, 'failed', 'Some reason', 1357648719000000, 1357648720897182); +INSERT INTO atf_test_cases (test_case_id, description, has_cleanup, timeout, + required_memory, required_user) + VALUES (7, 'Test description', 'true', 300000000, 128, 'root'); + +-- test_case_id 8, skipped, all optional metadata. +INSERT INTO test_cases (test_case_id, test_program_id, name) + VALUES (8, 6, 'this_skips'); +INSERT INTO test_results (test_case_id, result_type, result_reason, start_time, + end_time) + VALUES (8, 'skipped', 'Another reason', 1357648729182013, 1357648730000000); +INSERT INTO atf_test_cases (test_case_id, description, has_cleanup, timeout, + required_memory, required_user) + VALUES (8, 'Test explanation', 'true', 600000000, 512, 'unprivileged'); +INSERT INTO atf_test_cases_multivalues (test_case_id, property_name, + property_value) + VALUES (8, 'require.arch', 'x86_64'); +INSERT INTO atf_test_cases_multivalues (test_case_id, property_name, + property_value) + VALUES (8, 'require.arch', 'powerpc'); +INSERT INTO atf_test_cases_multivalues (test_case_id, property_name, + property_value) + VALUES (8, 'require.machine', 'amd64'); +INSERT INTO atf_test_cases_multivalues (test_case_id, property_name, + property_value) + VALUES (8, 'require.machine', 'macppc'); +INSERT INTO atf_test_cases_multivalues (test_case_id, property_name, + property_value) + VALUES (8, 'require.config', 'unprivileged_user'); +INSERT INTO atf_test_cases_multivalues (test_case_id, property_name, + property_value) + VALUES (8, 'require.config', 'X-foo'); +INSERT INTO atf_test_cases_multivalues (test_case_id, property_name, + property_value) + VALUES (8, 'require.files', '/the/data/file'); +INSERT INTO atf_test_cases_multivalues (test_case_id, property_name, + property_value) + VALUES (8, 'require.progs', 'cp'); +INSERT INTO atf_test_cases_multivalues (test_case_id, property_name, + property_value) + VALUES (8, 'require.progs', '/bin/ls'); + +-- file_id 3 +INSERT INTO files (file_id, contents) + VALUES (3, x'416e6f74686572207374646f7574'); +INSERT INTO test_case_files (test_case_id, file_name, file_id) + VALUES (8, '__STDOUT__', 3); + +-- test_program_id 7 +INSERT INTO test_programs (test_program_id, action_id, absolute_path, root, + relative_path, test_suite_name, interface) + VALUES (7, 3, '/usr/tests/simple_test', '/usr/tests', + 'simple_test', 'subsuite-name', 'atf'); + +-- test_case_id 9 +INSERT INTO test_cases (test_case_id, test_program_id, name) + VALUES (9, 7, 'main'); +INSERT INTO test_results (test_case_id, result_type, result_reason, start_time, + end_time) + VALUES (9, 'failed', 'Exited with code 1', + 1357648740120000, 1357648750081700); +INSERT INTO atf_test_cases (test_case_id, description, has_cleanup, timeout, + required_memory, required_user) + VALUES (9, 'More text', 'true', 300000000, 128, 'unprivileged'); + +-- file_id 4 +INSERT INTO files (file_id, contents) + VALUES (4, x'416e6f7468657220737464657272'); +INSERT INTO test_case_files (test_case_id, file_name, file_id) + VALUES (9, '__STDERR__', 4); + + +-- +-- Action 4: Mixture of test programs. +-- + + +-- context_id 4 +INSERT INTO contexts (context_id, cwd) VALUES (4, '/usr/tests'); +INSERT INTO env_vars (context_id, var_name, var_value) + VALUES (4, 'LANG', 'C'); +INSERT INTO env_vars (context_id, var_name, var_value) + VALUES (4, 'PATH', '/bin:/usr/bin'); +INSERT INTO env_vars (context_id, var_name, var_value) + VALUES (4, 'TERM', 'xterm'); + +-- action_id 4 +INSERT INTO actions (action_id, context_id) VALUES (4, 4); + +-- test_program_id 8 +INSERT INTO test_programs (test_program_id, action_id, absolute_path, root, + relative_path, test_suite_name, interface) + VALUES (8, 4, '/usr/tests/subdir/another_test', '/usr/tests', + 'subdir/another_test', 'subsuite-name', 'plain'); +INSERT INTO plain_test_programs (test_program_id, timeout) + VALUES (8, 10000000); + +-- test_case_id 10 +INSERT INTO test_cases (test_case_id, test_program_id, name) + VALUES (10, 8, 'main'); +INSERT INTO test_results (test_case_id, result_type, result_reason, start_time, + end_time) + VALUES (10, 'failed', 'Exit failure', 1357644395000000, 1357644396000000); + +-- file_id 5 +INSERT INTO files (file_id, contents) VALUES (5, x'54657374207374646f7574'); +INSERT INTO test_case_files (test_case_id, file_name, file_id) + VALUES (10, '__STDOUT__', 5); + +-- file_id 6 +INSERT INTO files (file_id, contents) VALUES (6, x'5465737420737464657272'); +INSERT INTO test_case_files (test_case_id, file_name, file_id) + VALUES (10, '__STDERR__', 6); + +-- test_program_id 9 +INSERT INTO test_programs (test_program_id, action_id, absolute_path, root, + relative_path, test_suite_name, interface) + VALUES (9, 4, '/usr/tests/complex_test', '/usr/tests', + 'complex_test', 'suite-name', 'atf'); + +-- test_case_id 11 +INSERT INTO test_cases (test_case_id, test_program_id, name) + VALUES (11, 9, 'this_passes'); +INSERT INTO test_results (test_case_id, result_type, result_reason, start_time, + end_time) + VALUES (11, 'passed', NULL, 1357644396500000, 1357644397000000); +INSERT INTO atf_test_cases (test_case_id, description, has_cleanup, timeout, + required_memory, required_user) + VALUES (11, NULL, 'false', 300000000, 0, NULL); + +-- test_case_id 12 +INSERT INTO test_cases (test_case_id, test_program_id, name) + VALUES (12, 9, 'this_fails'); +INSERT INTO test_results (test_case_id, result_type, result_reason, start_time, + end_time) + VALUES (12, 'failed', 'Some reason', 1357644397100000, 1357644399005000); +INSERT INTO atf_test_cases (test_case_id, description, has_cleanup, timeout, + required_memory, required_user) + VALUES (12, 'Test description', 'false', 300000000, 0, 'root'); + + +COMMIT TRANSACTION; diff --git a/external/bsd/kyua-cli/dist/store/testdata_v2.sql b/external/bsd/kyua-cli/dist/store/testdata_v2.sql new file mode 100644 index 000000000..214595f22 --- /dev/null +++ b/external/bsd/kyua-cli/dist/store/testdata_v2.sql @@ -0,0 +1,462 @@ +-- Copyright 2013 Google Inc. +-- All rights reserved. +-- +-- Redistribution and use in source and binary forms, with or without +-- modification, are permitted provided that the following conditions are +-- met: +-- +-- * Redistributions of source code must retain the above copyright +-- notice, this list of conditions and the following disclaimer. +-- * Redistributions in binary form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- * Neither the name of Google Inc. nor the names of its contributors +-- may be used to endorse or promote products derived from this software +-- without specific prior written permission. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +-- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +-- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +-- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +-- OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +-- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +-- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +-- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +-- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +-- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +-- \file store/testdata_v2.sql +-- Populates a v2 database with some test data. + + +BEGIN TRANSACTION; + + +-- +-- Action 1: Empty context and no test programs nor test cases. +-- + + +-- context_id 1 +INSERT INTO contexts (context_id, cwd) VALUES (1, '/some/root'); + +-- action_id 1 +INSERT INTO actions (action_id, context_id) VALUES (1, 1); + + +-- +-- Action 2: Plain test programs only. +-- +-- This action contains 5 test programs, each with one test case, and each +-- reporting one of all possible result types. +-- + + +-- context_id 2 +INSERT INTO contexts (context_id, cwd) VALUES (2, '/test/suite/root'); +INSERT INTO env_vars (context_id, var_name, var_value) + VALUES (2, 'HOME', '/home/test'); +INSERT INTO env_vars (context_id, var_name, var_value) + VALUES (2, 'PATH', '/bin:/usr/bin'); + +-- action_id 2 +INSERT INTO actions (action_id, context_id) VALUES (2, 2); + +-- metadata_id 1 +INSERT INTO metadatas VALUES (1, 'allowed_architectures', ''); +INSERT INTO metadatas VALUES (1, 'allowed_platforms', ''); +INSERT INTO metadatas VALUES (1, 'description', ''); +INSERT INTO metadatas VALUES (1, 'has_cleanup', 'false'); +INSERT INTO metadatas VALUES (1, 'required_configs', ''); +INSERT INTO metadatas VALUES (1, 'required_files', ''); +INSERT INTO metadatas VALUES (1, 'required_memory', '0'); +INSERT INTO metadatas VALUES (1, 'required_programs', ''); +INSERT INTO metadatas VALUES (1, 'required_user', ''); +INSERT INTO metadatas VALUES (1, 'timeout', '300'); + +-- test_program_id 1 +INSERT INTO test_programs (test_program_id, action_id, absolute_path, root, + relative_path, test_suite_name, metadata_id, + interface) + VALUES (1, 2, '/test/suite/root/foo_test', '/test/suite/root', + 'foo_test', 'suite-name', 1, 'plain'); + +-- test_case_id 1 +INSERT INTO test_cases (test_case_id, test_program_id, name, metadata_id) + VALUES (1, 1, 'main', 1); +INSERT INTO test_results (test_case_id, result_type, result_reason, start_time, + end_time) + VALUES (1, 'passed', NULL, 1357643611000000, 1357643621000500); + +-- metadata_id 2 +INSERT INTO metadatas VALUES (2, 'allowed_architectures', ''); +INSERT INTO metadatas VALUES (2, 'allowed_platforms', ''); +INSERT INTO metadatas VALUES (2, 'description', ''); +INSERT INTO metadatas VALUES (2, 'has_cleanup', 'false'); +INSERT INTO metadatas VALUES (2, 'required_configs', ''); +INSERT INTO metadatas VALUES (2, 'required_files', ''); +INSERT INTO metadatas VALUES (2, 'required_memory', '0'); +INSERT INTO metadatas VALUES (2, 'required_programs', ''); +INSERT INTO metadatas VALUES (2, 'required_user', ''); +INSERT INTO metadatas VALUES (2, 'timeout', '10'); + +-- test_program_id 2 +INSERT INTO test_programs (test_program_id, action_id, absolute_path, root, + relative_path, test_suite_name, metadata_id, + interface) + VALUES (2, 2, '/test/suite/root/subdir/another_test', '/test/suite/root', + 'subdir/another_test', 'subsuite-name', 2, 'plain'); + +-- test_case_id 2 +INSERT INTO test_cases (test_case_id, test_program_id, name, metadata_id) + VALUES (2, 2, 'main', 2); +INSERT INTO test_results (test_case_id, result_type, result_reason, start_time, + end_time) + VALUES (2, 'failed', 'Exited with code 1', + 1357643622001200, 1357643622900021); + +-- file_id 1 +INSERT INTO files (file_id, contents) VALUES (1, x'54657374207374646f7574'); +INSERT INTO test_case_files (test_case_id, file_name, file_id) + VALUES (2, '__STDOUT__', 1); + +-- file_id 2 +INSERT INTO files (file_id, contents) VALUES (2, x'5465737420737464657272'); +INSERT INTO test_case_files (test_case_id, file_name, file_id) + VALUES (2, '__STDERR__', 2); + +-- metadata_id 3 +INSERT INTO metadatas VALUES (3, 'allowed_architectures', ''); +INSERT INTO metadatas VALUES (3, 'allowed_platforms', ''); +INSERT INTO metadatas VALUES (3, 'description', ''); +INSERT INTO metadatas VALUES (3, 'has_cleanup', 'false'); +INSERT INTO metadatas VALUES (3, 'required_configs', ''); +INSERT INTO metadatas VALUES (3, 'required_files', ''); +INSERT INTO metadatas VALUES (3, 'required_memory', '0'); +INSERT INTO metadatas VALUES (3, 'required_programs', ''); +INSERT INTO metadatas VALUES (3, 'required_user', ''); +INSERT INTO metadatas VALUES (3, 'timeout', '300'); + +-- test_program_id 3 +INSERT INTO test_programs (test_program_id, action_id, absolute_path, root, + relative_path, test_suite_name, metadata_id, + interface) + VALUES (3, 2, '/test/suite/root/subdir/bar_test', '/test/suite/root', + 'subdir/bar_test', 'subsuite-name', 3, 'plain'); + +-- test_case_id 3 +INSERT INTO test_cases (test_case_id, test_program_id, name, metadata_id) + VALUES (3, 3, 'main', 3); +INSERT INTO test_results (test_case_id, result_type, result_reason, start_time, + end_time) + VALUES (3, 'broken', 'Received signal 1', + 1357643623500000, 1357643630981932); + +-- metadata_id 4 +INSERT INTO metadatas VALUES (4, 'allowed_architectures', ''); +INSERT INTO metadatas VALUES (4, 'allowed_platforms', ''); +INSERT INTO metadatas VALUES (4, 'description', ''); +INSERT INTO metadatas VALUES (4, 'has_cleanup', 'false'); +INSERT INTO metadatas VALUES (4, 'required_configs', ''); +INSERT INTO metadatas VALUES (4, 'required_files', ''); +INSERT INTO metadatas VALUES (4, 'required_memory', '0'); +INSERT INTO metadatas VALUES (4, 'required_programs', ''); +INSERT INTO metadatas VALUES (4, 'required_user', ''); +INSERT INTO metadatas VALUES (4, 'timeout', '300'); + +-- test_program_id 4 +INSERT INTO test_programs (test_program_id, action_id, absolute_path, root, + relative_path, test_suite_name, metadata_id, + interface) + VALUES (4, 2, '/test/suite/root/top_test', '/test/suite/root', + 'top_test', 'suite-name', 4, 'plain'); + +-- test_case_id 4 +INSERT INTO test_cases (test_case_id, test_program_id, name, metadata_id) + VALUES (4, 4, 'main', 4); +INSERT INTO test_results (test_case_id, result_type, result_reason, start_time, + end_time) + VALUES (4, 'expected_failure', 'Known bug', + 1357643631000000, 1357643631020000); + +-- metadata_id 5 +INSERT INTO metadatas VALUES (5, 'allowed_architectures', ''); +INSERT INTO metadatas VALUES (5, 'allowed_platforms', ''); +INSERT INTO metadatas VALUES (5, 'description', ''); +INSERT INTO metadatas VALUES (5, 'has_cleanup', 'false'); +INSERT INTO metadatas VALUES (5, 'required_configs', ''); +INSERT INTO metadatas VALUES (5, 'required_files', ''); +INSERT INTO metadatas VALUES (5, 'required_memory', '0'); +INSERT INTO metadatas VALUES (5, 'required_programs', ''); +INSERT INTO metadatas VALUES (5, 'required_user', ''); +INSERT INTO metadatas VALUES (5, 'timeout', '300'); + +-- test_program_id 5 +INSERT INTO test_programs (test_program_id, action_id, absolute_path, root, + relative_path, test_suite_name, metadata_id, + interface) + VALUES (5, 2, '/test/suite/root/last_test', '/test/suite/root', + 'last_test', 'suite-name', 5, 'plain'); + +-- test_case_id 5 +INSERT INTO test_cases (test_case_id, test_program_id, name, metadata_id) + VALUES (5, 5, 'main', 5); +INSERT INTO test_results (test_case_id, result_type, result_reason, start_time, + end_time) + VALUES (5, 'skipped', 'Does not apply', 1357643632000000, 1357643638000000); + + +-- +-- Action 3: ATF test programs only. +-- + + +-- context_id 3 +INSERT INTO contexts (context_id, cwd) VALUES (3, '/usr/tests'); +INSERT INTO env_vars (context_id, var_name, var_value) + VALUES (3, 'PATH', '/bin:/usr/bin'); + +-- action_id 3 +INSERT INTO actions (action_id, context_id) VALUES (3, 3); + +-- metadata_id 6 +INSERT INTO metadatas VALUES (6, 'allowed_architectures', ''); +INSERT INTO metadatas VALUES (6, 'allowed_platforms', ''); +INSERT INTO metadatas VALUES (6, 'description', ''); +INSERT INTO metadatas VALUES (6, 'has_cleanup', 'false'); +INSERT INTO metadatas VALUES (6, 'required_configs', ''); +INSERT INTO metadatas VALUES (6, 'required_files', ''); +INSERT INTO metadatas VALUES (6, 'required_memory', '0'); +INSERT INTO metadatas VALUES (6, 'required_programs', ''); +INSERT INTO metadatas VALUES (6, 'required_user', ''); +INSERT INTO metadatas VALUES (6, 'timeout', '300'); + +-- test_program_id 6 +INSERT INTO test_programs (test_program_id, action_id, absolute_path, root, + relative_path, test_suite_name, metadata_id, + interface) + VALUES (6, 3, '/usr/tests/complex_test', '/usr/tests', + 'complex_test', 'suite-name', 6, 'atf'); + +-- metadata_id 7 +INSERT INTO metadatas VALUES (7, 'allowed_architectures', ''); +INSERT INTO metadatas VALUES (7, 'allowed_platforms', ''); +INSERT INTO metadatas VALUES (7, 'description', ''); +INSERT INTO metadatas VALUES (7, 'has_cleanup', 'false'); +INSERT INTO metadatas VALUES (7, 'required_configs', ''); +INSERT INTO metadatas VALUES (7, 'required_files', ''); +INSERT INTO metadatas VALUES (7, 'required_memory', '0'); +INSERT INTO metadatas VALUES (7, 'required_programs', ''); +INSERT INTO metadatas VALUES (7, 'required_user', ''); +INSERT INTO metadatas VALUES (7, 'timeout', '300'); + +-- test_case_id 6, passed, no optional metadata. +INSERT INTO test_cases (test_case_id, test_program_id, name, metadata_id) + VALUES (6, 6, 'this_passes', 7); +INSERT INTO test_results (test_case_id, result_type, result_reason, start_time, + end_time) + VALUES (6, 'passed', NULL, 1357648712000000, 1357648718000000); + +-- metadata_id 8 +INSERT INTO metadatas VALUES (8, 'allowed_architectures', ''); +INSERT INTO metadatas VALUES (8, 'allowed_platforms', ''); +INSERT INTO metadatas VALUES (8, 'description', 'Test description'); +INSERT INTO metadatas VALUES (8, 'has_cleanup', 'true'); +INSERT INTO metadatas VALUES (8, 'required_configs', ''); +INSERT INTO metadatas VALUES (8, 'required_files', ''); +INSERT INTO metadatas VALUES (8, 'required_memory', '128'); +INSERT INTO metadatas VALUES (8, 'required_programs', ''); +INSERT INTO metadatas VALUES (8, 'required_user', 'root'); +INSERT INTO metadatas VALUES (8, 'timeout', '300'); + +-- test_case_id 7, failed, optional non-multivalue metadata. +INSERT INTO test_cases (test_case_id, test_program_id, name, metadata_id) + VALUES (7, 6, 'this_fails', 8); +INSERT INTO test_results (test_case_id, result_type, result_reason, start_time, + end_time) + VALUES (7, 'failed', 'Some reason', 1357648719000000, 1357648720897182); + +-- metadata_id 9 +INSERT INTO metadatas VALUES (9, 'allowed_architectures', 'powerpc x86_64'); +INSERT INTO metadatas VALUES (9, 'allowed_platforms', 'amd64 macppc'); +INSERT INTO metadatas VALUES (9, 'description', 'Test explanation'); +INSERT INTO metadatas VALUES (9, 'has_cleanup', 'true'); +INSERT INTO metadatas VALUES (9, 'required_configs', 'unprivileged_user X-foo'); +INSERT INTO metadatas VALUES (9, 'required_files', '/the/data/file'); +INSERT INTO metadatas VALUES (9, 'required_memory', '512'); +INSERT INTO metadatas VALUES (9, 'required_programs', 'cp /bin/ls'); +INSERT INTO metadatas VALUES (9, 'required_user', 'unprivileged'); +INSERT INTO metadatas VALUES (9, 'timeout', '600'); + +-- test_case_id 8, skipped, all optional metadata. +INSERT INTO test_cases (test_case_id, test_program_id, name, metadata_id) + VALUES (8, 6, 'this_skips', 9); +INSERT INTO test_results (test_case_id, result_type, result_reason, start_time, + end_time) + VALUES (8, 'skipped', 'Another reason', 1357648729182013, 1357648730000000); + +-- file_id 3 +INSERT INTO files (file_id, contents) + VALUES (3, x'416e6f74686572207374646f7574'); +INSERT INTO test_case_files (test_case_id, file_name, file_id) + VALUES (8, '__STDOUT__', 3); + +-- metadata_id 10 +INSERT INTO metadatas VALUES (10, 'allowed_architectures', ''); +INSERT INTO metadatas VALUES (10, 'allowed_platforms', ''); +INSERT INTO metadatas VALUES (10, 'description', ''); +INSERT INTO metadatas VALUES (10, 'has_cleanup', 'false'); +INSERT INTO metadatas VALUES (10, 'required_configs', ''); +INSERT INTO metadatas VALUES (10, 'required_files', ''); +INSERT INTO metadatas VALUES (10, 'required_memory', '0'); +INSERT INTO metadatas VALUES (10, 'required_programs', ''); +INSERT INTO metadatas VALUES (10, 'required_user', ''); +INSERT INTO metadatas VALUES (10, 'timeout', '300'); + +-- test_program_id 7 +INSERT INTO test_programs (test_program_id, action_id, absolute_path, root, + relative_path, test_suite_name, metadata_id, + interface) + VALUES (7, 3, '/usr/tests/simple_test', '/usr/tests', + 'simple_test', 'subsuite-name', 10, 'atf'); + +-- metadata_id 11 +INSERT INTO metadatas VALUES (11, 'allowed_architectures', ''); +INSERT INTO metadatas VALUES (11, 'allowed_platforms', ''); +INSERT INTO metadatas VALUES (11, 'description', 'More text'); +INSERT INTO metadatas VALUES (11, 'has_cleanup', 'true'); +INSERT INTO metadatas VALUES (11, 'required_configs', ''); +INSERT INTO metadatas VALUES (11, 'required_files', ''); +INSERT INTO metadatas VALUES (11, 'required_memory', '128'); +INSERT INTO metadatas VALUES (11, 'required_programs', ''); +INSERT INTO metadatas VALUES (11, 'required_user', 'unprivileged'); +INSERT INTO metadatas VALUES (11, 'timeout', '300'); + +-- test_case_id 9 +INSERT INTO test_cases (test_case_id, test_program_id, name, metadata_id) + VALUES (9, 7, 'main', 11); +INSERT INTO test_results (test_case_id, result_type, result_reason, start_time, + end_time) + VALUES (9, 'failed', 'Exited with code 1', + 1357648740120000, 1357648750081700); + +-- file_id 4 +INSERT INTO files (file_id, contents) + VALUES (4, x'416e6f7468657220737464657272'); +INSERT INTO test_case_files (test_case_id, file_name, file_id) + VALUES (9, '__STDERR__', 4); + + +-- +-- Action 4: Mixture of test programs. +-- + + +-- context_id 4 +INSERT INTO contexts (context_id, cwd) VALUES (4, '/usr/tests'); +INSERT INTO env_vars (context_id, var_name, var_value) + VALUES (4, 'LANG', 'C'); +INSERT INTO env_vars (context_id, var_name, var_value) + VALUES (4, 'PATH', '/bin:/usr/bin'); +INSERT INTO env_vars (context_id, var_name, var_value) + VALUES (4, 'TERM', 'xterm'); + +-- action_id 4 +INSERT INTO actions (action_id, context_id) VALUES (4, 4); + +-- metadata_id 12 +INSERT INTO metadatas VALUES (12, 'allowed_architectures', ''); +INSERT INTO metadatas VALUES (12, 'allowed_platforms', ''); +INSERT INTO metadatas VALUES (12, 'description', ''); +INSERT INTO metadatas VALUES (12, 'has_cleanup', 'false'); +INSERT INTO metadatas VALUES (12, 'required_configs', ''); +INSERT INTO metadatas VALUES (12, 'required_files', ''); +INSERT INTO metadatas VALUES (12, 'required_memory', '0'); +INSERT INTO metadatas VALUES (12, 'required_programs', ''); +INSERT INTO metadatas VALUES (12, 'required_user', ''); +INSERT INTO metadatas VALUES (12, 'timeout', '10'); + +-- test_program_id 8 +INSERT INTO test_programs (test_program_id, action_id, absolute_path, root, + relative_path, test_suite_name, metadata_id, + interface) + VALUES (8, 4, '/usr/tests/subdir/another_test', '/usr/tests', + 'subdir/another_test', 'subsuite-name', 12, 'plain'); + +-- test_case_id 10 +INSERT INTO test_cases (test_case_id, test_program_id, name, metadata_id) + VALUES (10, 8, 'main', 12); +INSERT INTO test_results (test_case_id, result_type, result_reason, start_time, + end_time) + VALUES (10, 'failed', 'Exit failure', 1357644395000000, 1357644396000000); + +-- file_id 5 +INSERT INTO files (file_id, contents) VALUES (5, x'54657374207374646f7574'); +INSERT INTO test_case_files (test_case_id, file_name, file_id) + VALUES (10, '__STDOUT__', 5); + +-- file_id 6 +INSERT INTO files (file_id, contents) VALUES (6, x'5465737420737464657272'); +INSERT INTO test_case_files (test_case_id, file_name, file_id) + VALUES (10, '__STDERR__', 6); + +-- metadata_id 13 +INSERT INTO metadatas VALUES (13, 'allowed_architectures', ''); +INSERT INTO metadatas VALUES (13, 'allowed_platforms', ''); +INSERT INTO metadatas VALUES (13, 'description', ''); +INSERT INTO metadatas VALUES (13, 'has_cleanup', 'false'); +INSERT INTO metadatas VALUES (13, 'required_configs', ''); +INSERT INTO metadatas VALUES (13, 'required_files', ''); +INSERT INTO metadatas VALUES (13, 'required_memory', '0'); +INSERT INTO metadatas VALUES (13, 'required_programs', ''); +INSERT INTO metadatas VALUES (13, 'required_user', ''); +INSERT INTO metadatas VALUES (13, 'timeout', '300'); + +-- test_program_id 9 +INSERT INTO test_programs (test_program_id, action_id, absolute_path, root, + relative_path, test_suite_name, metadata_id, + interface) + VALUES (9, 4, '/usr/tests/complex_test', '/usr/tests', + 'complex_test', 'suite-name', 14, 'atf'); + +-- metadata_id 15 +INSERT INTO metadatas VALUES (15, 'allowed_architectures', ''); +INSERT INTO metadatas VALUES (15, 'allowed_platforms', ''); +INSERT INTO metadatas VALUES (15, 'description', ''); +INSERT INTO metadatas VALUES (15, 'has_cleanup', 'false'); +INSERT INTO metadatas VALUES (15, 'required_configs', ''); +INSERT INTO metadatas VALUES (15, 'required_files', ''); +INSERT INTO metadatas VALUES (15, 'required_memory', '0'); +INSERT INTO metadatas VALUES (15, 'required_programs', ''); +INSERT INTO metadatas VALUES (15, 'required_user', ''); +INSERT INTO metadatas VALUES (15, 'timeout', '300'); + +-- test_case_id 11 +INSERT INTO test_cases (test_case_id, test_program_id, name, metadata_id) + VALUES (11, 9, 'this_passes', 15); +INSERT INTO test_results (test_case_id, result_type, result_reason, start_time, + end_time) + VALUES (11, 'passed', NULL, 1357644396500000, 1357644397000000); + +-- metadata_id 16 +INSERT INTO metadatas VALUES (16, 'allowed_architectures', ''); +INSERT INTO metadatas VALUES (16, 'allowed_platforms', ''); +INSERT INTO metadatas VALUES (16, 'description', 'Test description'); +INSERT INTO metadatas VALUES (16, 'has_cleanup', 'false'); +INSERT INTO metadatas VALUES (16, 'required_configs', ''); +INSERT INTO metadatas VALUES (16, 'required_files', ''); +INSERT INTO metadatas VALUES (16, 'required_memory', '0'); +INSERT INTO metadatas VALUES (16, 'required_programs', ''); +INSERT INTO metadatas VALUES (16, 'required_user', 'root'); +INSERT INTO metadatas VALUES (16, 'timeout', '300'); + +-- test_case_id 12 +INSERT INTO test_cases (test_case_id, test_program_id, name, metadata_id) + VALUES (12, 9, 'this_fails', 16); +INSERT INTO test_results (test_case_id, result_type, result_reason, start_time, + end_time) + VALUES (12, 'failed', 'Some reason', 1357644397100000, 1357644399005000); + + +COMMIT TRANSACTION; diff --git a/external/bsd/kyua-cli/dist/store/transaction.cpp b/external/bsd/kyua-cli/dist/store/transaction.cpp new file mode 100644 index 000000000..b6773b25c --- /dev/null +++ b/external/bsd/kyua-cli/dist/store/transaction.cpp @@ -0,0 +1,987 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "store/transaction.hpp" + +extern "C" { +#include +} + +#include +#include +#include + +#include "engine/action.hpp" +#include "engine/context.hpp" +#include "engine/test_result.hpp" +#include "store/backend.hpp" +#include "store/dbtypes.hpp" +#include "store/exceptions.hpp" +#include "utils/datetime.hpp" +#include "utils/defs.hpp" +#include "utils/format/macros.hpp" +#include "utils/logging/macros.hpp" +#include "utils/optional.ipp" +#include "utils/sanity.hpp" +#include "utils/stream.hpp" +#include "utils/sqlite/database.hpp" +#include "utils/sqlite/exceptions.hpp" +#include "utils/sqlite/statement.ipp" +#include "utils/sqlite/transaction.hpp" +#include "utils/units.hpp" + +namespace datetime = utils::datetime; +namespace fs = utils::fs; +namespace sqlite = utils::sqlite; +namespace units = utils::units; + +using utils::none; +using utils::optional; + + +namespace { + + +/// Retrieves the environment variables of a context. +/// +/// \param db The SQLite database. +/// \param context_id The identifier of the context. +/// +/// \return The environment variables of the specified context. +/// +/// \throw sqlite::error If there is a problem storing the variables. +static std::map< std::string, std::string > +get_env_vars(sqlite::database& db, const int64_t context_id) +{ + std::map< std::string, std::string > env; + + sqlite::statement stmt = db.create_statement( + "SELECT var_name, var_value FROM env_vars " + "WHERE context_id == :context_id"); + stmt.bind(":context_id", context_id); + + while (stmt.step()) { + const std::string name = stmt.safe_column_text("var_name"); + const std::string value = stmt.safe_column_text("var_value"); + env[name] = value; + } + + return env; +} + + +/// Retrieves a metadata object. +/// +/// \param db The SQLite database. +/// \param metadata_id The identifier of the metadata. +/// +/// \return A new metadata object. +static engine::metadata +get_metadata(sqlite::database& db, const int64_t metadata_id) +{ + engine::metadata_builder builder; + + sqlite::statement stmt = db.create_statement( + "SELECT * FROM metadatas WHERE metadata_id == :metadata_id"); + stmt.bind(":metadata_id", metadata_id); + while (stmt.step()) { + const std::string name = stmt.safe_column_text("property_name"); + const std::string value = stmt.safe_column_text("property_value"); + builder.set_string(name, value); + } + + return builder.build(); +} + + +/// Gets a file from the database. +/// +/// \param db The database to query the file from. +/// \param file_id The identifier of the file to be queried. +/// +/// \return A textual representation of the file contents. +/// +/// \throw integrity_error If there is any problem in the loaded data or if the +/// file cannot be found. +static std::string +get_file(sqlite::database& db, const int64_t file_id) +{ + sqlite::statement stmt = db.create_statement( + "SELECT contents FROM files WHERE file_id == :file_id"); + stmt.bind(":file_id", file_id); + if (!stmt.step()) + throw store::integrity_error(F("Cannot find referenced file %s") % + file_id); + + try { + const sqlite::blob raw_contents = stmt.safe_column_blob("contents"); + const std::string contents( + static_cast< const char *>(raw_contents.memory), raw_contents.size); + + const bool more = stmt.step(); + INV(!more); + + return contents; + } catch (const sqlite::error& e) { + throw store::integrity_error(e.what()); + } +} + + +/// Gets all the test cases within a particular test program. +/// +/// \param db The database to query the information from. +/// \param test_program_id The identifier of the test program whose test cases +/// to query. +/// \param test_program The test program itself, needed to establish a binding +/// between the loaded test cases and the test program. +/// \param interface The interface type of the test cases to be loaded. This +/// assumes that all test cases within a test program share the same +/// interface, which is a pretty reasonable assumption. +/// +/// \return The collection of loaded test cases. +/// +/// \throw integrity_error If there is any problem in the loaded data. +static engine::test_cases_vector +get_test_cases(sqlite::database& db, const int64_t test_program_id, + const engine::test_program& test_program, + const std::string& interface) +{ + engine::test_cases_vector test_cases; + + sqlite::statement stmt = db.create_statement( + "SELECT name, metadata_id " + "FROM test_cases WHERE test_program_id == :test_program_id"); + stmt.bind(":test_program_id", test_program_id); + while (stmt.step()) { + const std::string name = stmt.safe_column_text("name"); + const int64_t metadata_id = stmt.safe_column_int64("metadata_id"); + + const engine::metadata metadata = get_metadata(db, metadata_id); + engine::test_case_ptr test_case( + new engine::test_case(interface, test_program, name, metadata)); + LD(F("Loaded test case '%s'") % test_case->name()); + test_cases.push_back(test_case); + } + + return test_cases; +} + + +/// Retrieves a result from the database. +/// +/// \param stmt The statement with the data for the result to load. +/// \param type_column The name of the column containing the type of the result. +/// \param reason_column The name of the column containing the reason for the +/// result, if any. +/// +/// \return The loaded result. +/// +/// \throw integrity_error If the data in the database is invalid. +static engine::test_result +parse_result(sqlite::statement& stmt, const char* type_column, + const char* reason_column) +{ + using engine::test_result; + + try { + const std::string type = stmt.safe_column_text(type_column); + if (type == "passed") { + if (stmt.column_type(stmt.column_id(reason_column)) != + sqlite::type_null) + throw store::integrity_error("Result of type 'passed' has a " + "non-NULL reason"); + return test_result(test_result::passed); + } else if (type == "broken") { + return test_result(test_result::broken, + stmt.safe_column_text(reason_column)); + } else if (type == "expected_failure") { + return test_result(test_result::expected_failure, + stmt.safe_column_text(reason_column)); + } else if (type == "failed") { + return test_result(test_result::failed, + stmt.safe_column_text(reason_column)); + } else if (type == "skipped") { + return test_result(test_result::skipped, + stmt.safe_column_text(reason_column)); + } else { + throw store::integrity_error(F("Unknown test result type %s") % + type); + } + } catch (const sqlite::error& e) { + throw store::integrity_error(e.what()); + } +} + + +/// Stores the environment variables of a context. +/// +/// \param db The SQLite database. +/// \param context_id The identifier of the context. +/// \param env The environment variables to store. +/// +/// \throw sqlite::error If there is a problem storing the variables. +static void +put_env_vars(sqlite::database& db, const int64_t context_id, + const std::map< std::string, std::string >& env) +{ + sqlite::statement stmt = db.create_statement( + "INSERT INTO env_vars (context_id, var_name, var_value) " + "VALUES (:context_id, :var_name, :var_value)"); + stmt.bind(":context_id", context_id); + for (std::map< std::string, std::string >::const_iterator iter = + env.begin(); iter != env.end(); iter++) { + stmt.bind(":var_name", (*iter).first); + stmt.bind(":var_value", (*iter).second); + stmt.step_without_results(); + stmt.reset(); + } +} + + +/// Calculates the last rowid of a table. +/// +/// \param db The SQLite database. +/// \param table Name of the table. +/// +/// \return The last rowid; 0 if the table is empty. +static int64_t +last_rowid(sqlite::database& db, const std::string& table) +{ + sqlite::statement stmt = db.create_statement( + F("SELECT MAX(ROWID) AS max_rowid FROM %s") % table); + stmt.step(); + if (stmt.column_type(0) == sqlite::type_null) { + return 0; + } else { + INV(stmt.column_type(0) == sqlite::type_integer); + return stmt.column_int64(0); + } +} + + +/// Stores a metadata object. +/// +/// \param db The database into which to store the information. +/// \param md The metadata to store. +/// +/// \return The identifier of the new metadata object. +static int64_t +put_metadata(sqlite::database& db, const engine::metadata& md) +{ + const engine::properties_map props = md.to_properties(); + + const int64_t metadata_id = last_rowid(db, "metadatas"); + + sqlite::statement stmt = db.create_statement( + "INSERT INTO metadatas (metadata_id, property_name, property_value) " + "VALUES (:metadata_id, :property_name, :property_value)"); + stmt.bind(":metadata_id", metadata_id); + + for (engine::properties_map::const_iterator iter = props.begin(); + iter != props.end(); ++iter) { + stmt.bind(":property_name", (*iter).first); + stmt.bind(":property_value", (*iter).second); + stmt.step_without_results(); + stmt.reset(); + } + + return metadata_id; +} + + +/// Stores an arbitrary file into the database as a BLOB. +/// +/// \param db The database into which to store the file. +/// \param path Path to the file to be stored. +/// +/// \return The identifier of the stored file, or none if the file was empty. +/// +/// \throw sqlite::error If there are problems writing to the database. +static optional< int64_t > +put_file(sqlite::database& db, const fs::path& path) +{ + std::ifstream input(path.c_str()); + if (!input) + throw store::error(F("Cannot open file %s") % path); + + try { + if (utils::stream_length(input) == 0) + return none; + } catch (const std::runtime_error& e) { + // Skipping empty files is an optimization. If we fail to calculate the + // size of the file, just ignore the problem. If there are real issues + // with the file, the read below will fail anyway. + LD(F("Cannot determine if file is empty: %s") % e.what()); + } + + // TODO(jmmv): This will probably cause an unreasonable amount of memory + // consumption if we decide to store arbitrary files in the database (other + // than stdout or stderr). Should this happen, we need to investigate a + // better way to feel blobs into SQLite. + const std::string contents = utils::read_stream(input); + + sqlite::statement stmt = db.create_statement( + "INSERT INTO files (contents) VALUES (:contents)"); + stmt.bind(":contents", sqlite::blob(contents.c_str(), contents.length())); + stmt.step_without_results(); + + return optional< int64_t >(db.last_insert_rowid()); +} + + +} // anonymous namespace + + +/// Loads a specific test program from the database. +/// +/// \param backend_ The store backend we are dealing with. +/// \param id The identifier of the test program to load. +/// +/// \return The instantiated test program. +/// +/// \throw integrity_error If the data read from the database cannot be properly +/// interpreted. +engine::test_program_ptr +store::detail::get_test_program(backend& backend_, const int64_t id) +{ + sqlite::database& db = backend_.database(); + + engine::test_program_ptr test_program; + sqlite::statement stmt = db.create_statement( + "SELECT * FROM test_programs WHERE test_program_id == :id"); + stmt.bind(":id", id); + stmt.step(); + const std::string interface = stmt.safe_column_text("interface"); + test_program.reset(new engine::test_program( + interface, + fs::path(stmt.safe_column_text("relative_path")), + fs::path(stmt.safe_column_text("root")), + stmt.safe_column_text("test_suite_name"), + get_metadata(db, stmt.safe_column_int64("metadata_id")))); + const bool more = stmt.step(); + INV(!more); + + LD(F("Loaded test program '%s'; getting test cases") % + test_program->relative_path()); + test_program->set_test_cases(get_test_cases(db, id, *test_program, + interface)); + return test_program; +} + + +/// Internal implementation for a results iterator. +struct store::results_iterator::impl { + /// The store backend we are dealing with. + store::backend _backend; + + /// The statement to iterate on. + sqlite::statement _stmt; + + /// A cache for the last loaded test program. + optional< std::pair< int64_t, engine::test_program_ptr > > + _last_test_program; + + /// Whether the iterator is still valid or not. + bool _valid; + + /// Constructor. + impl(store::backend& backend_, const int64_t action_id_) : + _backend(backend_), + _stmt(backend_.database().create_statement( + "SELECT test_programs.test_program_id, " + " test_programs.interface, " + " test_cases.test_case_id, test_cases.name, " + " test_results.result_type, test_results.result_reason, " + " test_results.start_time, test_results.end_time " + "FROM test_programs " + " JOIN test_cases " + " ON test_programs.test_program_id = test_cases.test_program_id " + " JOIN test_results " + " ON test_cases.test_case_id = test_results.test_case_id " + "WHERE test_programs.action_id == :action_id " + "ORDER BY test_programs.absolute_path, test_cases.name")) + { + _stmt.bind(":action_id", action_id_); + _valid = _stmt.step(); + } +}; + + +/// Constructor. +/// +/// \param pimpl_ The internal implementation details of the iterator. +store::results_iterator::results_iterator( + std::tr1::shared_ptr< impl > pimpl_) : + _pimpl(pimpl_) +{ +} + + +/// Destructor. +store::results_iterator::~results_iterator(void) +{ +} + + +/// Moves the iterator forward by one result. +/// +/// \return The iterator itself. +store::results_iterator& +store::results_iterator::operator++(void) +{ + _pimpl->_valid = _pimpl->_stmt.step(); + return *this; +} + + +/// Checks whether the iterator is still valid. +/// +/// \return True if there is more elements to iterate on, false otherwise. +store::results_iterator::operator bool(void) const +{ + return _pimpl->_valid; +} + + +/// Gets the test program this result belongs to. +/// +/// \return The representation of a test program. +const engine::test_program_ptr +store::results_iterator::test_program(void) const +{ + const int64_t id = _pimpl->_stmt.safe_column_int64("test_program_id"); + if (!_pimpl->_last_test_program || + _pimpl->_last_test_program.get().first != id) + { + const engine::test_program_ptr tp = detail::get_test_program( + _pimpl->_backend, id); + _pimpl->_last_test_program = std::make_pair(id, tp); + } + return _pimpl->_last_test_program.get().second; +} + + +/// Gets the name of the test case pointed by the iterator. +/// +/// The caller can look up the test case data by using the find() method on the +/// test program returned by test_program(). +/// +/// \return A test case name, unique within the test program. +std::string +store::results_iterator::test_case_name(void) const +{ + return _pimpl->_stmt.safe_column_text("name"); +} + + +/// Gets the result of the test case pointed by the iterator. +/// +/// \return A test case result. +engine::test_result +store::results_iterator::result(void) const +{ + return parse_result(_pimpl->_stmt, "result_type", "result_reason"); +} + + +/// Gets the duration of the test case execution. +/// +/// \return A time delta representing the run time of the test case. +datetime::delta +store::results_iterator::duration(void) const +{ + const datetime::timestamp start_time = column_timestamp( + _pimpl->_stmt, "start_time"); + const datetime::timestamp end_time = column_timestamp( + _pimpl->_stmt, "end_time"); + return end_time - start_time; +} + + +/// Gets a file from a test case. +/// +/// \param db The database to query the file from. +/// \param test_case_id The identifier of the test case. +/// \param filename The name of the file to be retrieved. +/// +/// \return A textual representation of the file contents. +/// +/// \throw integrity_error If there is any problem in the loaded data or if the +/// file cannot be found. +static std::string +get_test_case_file(sqlite::database& db, const int64_t test_case_id, + const char* filename) +{ + sqlite::statement stmt = db.create_statement( + "SELECT file_id FROM test_case_files " + "WHERE test_case_id == :test_case_id AND file_name == :file_name"); + stmt.bind(":test_case_id", test_case_id); + stmt.bind(":file_name", filename); + if (stmt.step()) + return get_file(db, stmt.safe_column_int64("file_id")); + else + return ""; +} + + +/// Gets the contents of stdout of a test case. +/// +/// \return A textual representation of the stdout contents of the test case. +/// This may of course be empty if the test case didn't print anything. +std::string +store::results_iterator::stdout_contents(void) const +{ + return get_test_case_file(_pimpl->_backend.database(), + _pimpl->_stmt.safe_column_int64("test_case_id"), + "__STDOUT__"); +} + + +/// Gets the contents of stderr of a test case. +/// +/// \return A textual representation of the stderr contents of the test case. +/// This may of course be empty if the test case didn't print anything. +std::string +store::results_iterator::stderr_contents(void) const +{ + return get_test_case_file(_pimpl->_backend.database(), + _pimpl->_stmt.safe_column_int64("test_case_id"), + "__STDERR__"); +} + + +/// Internal implementation for a store transaction. +struct store::transaction::impl { + /// The backend instance. + store::backend& _backend; + + + /// The SQLite database this transaction deals with. + sqlite::database _db; + + /// The backing SQLite transaction. + sqlite::transaction _tx; + + /// Opens a transaction. + /// + /// \param backend_ The backend this transaction is connected to. + impl(backend& backend_) : + _backend(backend_), + _db(backend_.database()), + _tx(backend_.database().begin_transaction()) + { + } +}; + + +/// Creates a new transaction. +/// +/// \param backend_ The backend this transaction belongs to. +store::transaction::transaction(backend& backend_) : + _pimpl(new impl(backend_)) +{ +} + + +/// Destructor. +store::transaction::~transaction(void) +{ +} + + +/// Commits the transaction. +/// +/// \throw error If there is any problem when talking to the database. +void +store::transaction::commit(void) +{ + try { + _pimpl->_tx.commit(); + } catch (const sqlite::error& e) { + throw error(e.what()); + } +} + + +/// Rolls the transaction back. +/// +/// \throw error If there is any problem when talking to the database. +void +store::transaction::rollback(void) +{ + try { + _pimpl->_tx.rollback(); + } catch (const sqlite::error& e) { + throw error(e.what()); + } +} + + +/// Retrieves an action from the database. +/// +/// \param action_id The identifier of the action to retrieve. +/// +/// \return The retrieved action. +/// +/// \throw error If there is a problem loading the action. +engine::action +store::transaction::get_action(const int64_t action_id) +{ + try { + sqlite::statement stmt = _pimpl->_db.create_statement( + "SELECT context_id FROM actions WHERE action_id == :action_id"); + stmt.bind(":action_id", action_id); + if (!stmt.step()) + throw error(F("Error loading action %s: does not exist") % + action_id); + + return engine::action( + get_context(stmt.safe_column_int64("context_id"))); + } catch (const sqlite::error& e) { + throw error(F("Error loading action %s: %s") % action_id % e.what()); + } +} + + +/// Creates a new iterator to scan the test results of an action. +/// +/// \param action_id The identifier of the action for which to get the results. +/// +/// \return The constructed iterator. +/// +/// \throw error If there is any problem constructing the iterator. +store::results_iterator +store::transaction::get_action_results(const int64_t action_id) +{ + try { + return results_iterator(std::tr1::shared_ptr< results_iterator::impl >( + new results_iterator::impl(_pimpl->_backend, action_id))); + } catch (const sqlite::error& e) { + throw error(e.what()); + } +} + + +/// Retrieves the latest action from the database. +/// +/// \return The retrieved action. +/// +/// \throw error If there is a problem loading the action. +std::pair< int64_t, engine::action > +store::transaction::get_latest_action(void) +{ + try { + sqlite::statement stmt = _pimpl->_db.create_statement( + "SELECT action_id, context_id FROM actions WHERE " + "action_id == (SELECT max(action_id) FROM actions)"); + if (!stmt.step()) + throw error("No actions in the database"); + + const int64_t action_id = stmt.safe_column_int64("action_id"); + const engine::context context = get_context( + stmt.safe_column_int64("context_id")); + + return std::pair< int64_t, engine::action >( + action_id, engine::action(context)); + } catch (const sqlite::error& e) { + throw error(F("Error loading latest action: %s") % e.what()); + } +} + + +/// Retrieves an context from the database. +/// +/// \param context_id The identifier of the context to retrieve. +/// +/// \return The retrieved context. +/// +/// \throw error If there is a problem loading the context. +engine::context +store::transaction::get_context(const int64_t context_id) +{ + try { + sqlite::statement stmt = _pimpl->_db.create_statement( + "SELECT cwd FROM contexts WHERE context_id == :context_id"); + stmt.bind(":context_id", context_id); + if (!stmt.step()) + throw error(F("Error loading context %s: does not exist") % + context_id); + + return engine::context(fs::path(stmt.safe_column_text("cwd")), + get_env_vars(_pimpl->_db, context_id)); + } catch (const sqlite::error& e) { + throw error(F("Error loading context %s: %s") % context_id % e.what()); + } +} + + +/// Puts an action into the database. +/// +/// \pre The action has not been put yet. +/// \pre The dependent objects have already been put. +/// \post The action is stored into the database with a new identifier. +/// +/// \param unused_action The action to put. +/// \param context_id The identifier for the action's context. +/// +/// \return The identifier of the inserted action. +/// +/// \throw error If there is any problem when talking to the database. +int64_t +store::transaction::put_action(const engine::action& UTILS_UNUSED_PARAM(action), + const int64_t context_id) +{ + try { + sqlite::statement stmt = _pimpl->_db.create_statement( + "INSERT INTO actions (context_id) VALUES (:context_id)"); + stmt.bind(":context_id", context_id); + stmt.step_without_results(); + const int64_t action_id = _pimpl->_db.last_insert_rowid(); + + return action_id; + } catch (const sqlite::error& e) { + throw error(e.what()); + } +} + + +/// Puts a context into the database. +/// +/// \pre The context has not been put yet. +/// \post The context is stored into the database with a new identifier. +/// +/// \param context The context to put. +/// +/// \return The identifier of the inserted context. +/// +/// \throw error If there is any problem when talking to the database. +int64_t +store::transaction::put_context(const engine::context& context) +{ + try { + sqlite::statement stmt = _pimpl->_db.create_statement( + "INSERT INTO contexts (cwd) VALUES (:cwd)"); + stmt.bind(":cwd", context.cwd().str()); + stmt.step_without_results(); + const int64_t context_id = _pimpl->_db.last_insert_rowid(); + + put_env_vars(_pimpl->_db, context_id, context.env()); + + return context_id; + } catch (const sqlite::error& e) { + throw error(e.what()); + } +} + + +/// Puts a test program into the database. +/// +/// \pre The test program has not been put yet. +/// \post The test program is stored into the database with a new identifier. +/// +/// \param test_program The test program to put. +/// \param action_id The action this test program belongs to. +/// +/// \return The identifier of the inserted test program. +/// +/// \throw error If there is any problem when talking to the database. +int64_t +store::transaction::put_test_program(const engine::test_program& test_program, + const int64_t action_id) +{ + try { + const int64_t metadata_id = put_metadata( + _pimpl->_db, test_program.get_metadata()); + + sqlite::statement stmt = _pimpl->_db.create_statement( + "INSERT INTO test_programs (action_id, absolute_path, " + " root, relative_path, test_suite_name, " + " metadata_id, interface) " + "VALUES (:action_id, :absolute_path, :root, :relative_path, " + " :test_suite_name, :metadata_id, :interface)"); + stmt.bind(":action_id", action_id); + stmt.bind(":absolute_path", test_program.absolute_path().str()); + // TODO(jmmv): The root is not necessarily absolute. We need to ensure + // that we can recover the absolute path of the test program. Maybe we + // need to change the test_program to always ensure root is absolute? + stmt.bind(":root", test_program.root().str()); + stmt.bind(":relative_path", test_program.relative_path().str()); + stmt.bind(":test_suite_name", test_program.test_suite_name()); + stmt.bind(":metadata_id", metadata_id); + stmt.bind(":interface", test_program.interface_name()); + stmt.step_without_results(); + return _pimpl->_db.last_insert_rowid(); + } catch (const sqlite::error& e) { + throw error(e.what()); + } +} + + +/// Puts a test case into the database. +/// +/// \pre The test case has not been put yet. +/// \post The test case is stored into the database with a new identifier. +/// +/// \param test_case The test case to put. +/// \param test_program_id The test program this test case belongs to. +/// +/// \return The identifier of the inserted test case. +/// +/// \throw error If there is any problem when talking to the database. +int64_t +store::transaction::put_test_case(const engine::test_case& test_case, + const int64_t test_program_id) +{ + try { + const int64_t metadata_id = put_metadata( + _pimpl->_db, test_case.get_metadata()); + + sqlite::statement stmt = _pimpl->_db.create_statement( + "INSERT INTO test_cases (test_program_id, name, metadata_id) " + "VALUES (:test_program_id, :name, :metadata_id)"); + stmt.bind(":test_program_id", test_program_id); + stmt.bind(":name", test_case.name()); + stmt.bind(":metadata_id", metadata_id); + stmt.step_without_results(); + return _pimpl->_db.last_insert_rowid(); + } catch (const sqlite::error& e) { + throw error(e.what()); + } +} + + +/// Stores a file generated by a test case into the database as a BLOB. +/// +/// \param name The name of the file to store in the database. This needs to be +/// unique per test case. The caller is free to decide what names to use +/// for which files. For example, it might make sense to always call +/// __STDOUT__ the stdout of the test case so that it is easy to locate. +/// \param path The path to the file to be stored. +/// \param test_case_id The identifier of the test case this file belongs to. +/// +/// \return The identifier of the stored file, or none if the file was empty. +/// +/// \throw store::error If there are problems writing to the database. +optional< int64_t > +store::transaction::put_test_case_file(const std::string& name, + const fs::path& path, + const int64_t test_case_id) +{ + LD(F("Storing %s (%s) of test case %s") % name % path % test_case_id); + try { + const optional< int64_t > file_id = put_file(_pimpl->_db, path); + if (!file_id) { + LD("Not storing empty file"); + return none; + } + + sqlite::statement stmt = _pimpl->_db.create_statement( + "INSERT INTO test_case_files (test_case_id, file_name, file_id) " + "VALUES (:test_case_id, :file_name, :file_id)"); + stmt.bind(":test_case_id", test_case_id); + stmt.bind(":file_name", name); + stmt.bind(":file_id", file_id.get()); + stmt.step_without_results(); + + return optional< int64_t >(_pimpl->_db.last_insert_rowid()); + } catch (const sqlite::error& e) { + throw error(e.what()); + } +} + + +/// Puts a result into the database. +/// +/// \pre The result has not been put yet. +/// \post The result is stored into the database with a new identifier. +/// +/// \param result The result to put. +/// \param test_case_id The test case this result corresponds to. +/// \param start_time The time when the test started to run. +/// \param end_time The time when the test finished running. +/// +/// \return The identifier of the inserted result. +/// +/// \throw error If there is any problem when talking to the database. +int64_t +store::transaction::put_result(const engine::test_result& result, + const int64_t test_case_id, + const datetime::timestamp& start_time, + const datetime::timestamp& end_time) +{ + try { + sqlite::statement stmt = _pimpl->_db.create_statement( + "INSERT INTO test_results (test_case_id, result_type, " + " result_reason, start_time, " + " end_time) " + "VALUES (:test_case_id, :result_type, :result_reason, " + " :start_time, :end_time)"); + stmt.bind(":test_case_id", test_case_id); + + switch (result.type()) { + case engine::test_result::broken: + stmt.bind(":result_type", "broken"); + break; + + case engine::test_result::expected_failure: + stmt.bind(":result_type", "expected_failure"); + break; + + case engine::test_result::failed: + stmt.bind(":result_type", "failed"); + break; + + case engine::test_result::passed: + stmt.bind(":result_type", "passed"); + break; + + case engine::test_result::skipped: + stmt.bind(":result_type", "skipped"); + break; + + default: + UNREACHABLE; + } + + if (result.reason().empty()) + stmt.bind(":result_reason", sqlite::null()); + else + stmt.bind(":result_reason", result.reason()); + + store::bind_timestamp(stmt, ":start_time", start_time); + store::bind_timestamp(stmt, ":end_time", end_time); + + stmt.step_without_results(); + const int64_t result_id = _pimpl->_db.last_insert_rowid(); + + return result_id; + } catch (const sqlite::error& e) { + throw error(e.what()); + } +} diff --git a/external/bsd/kyua-cli/dist/store/transaction.hpp b/external/bsd/kyua-cli/dist/store/transaction.hpp new file mode 100644 index 000000000..0cf4f9831 --- /dev/null +++ b/external/bsd/kyua-cli/dist/store/transaction.hpp @@ -0,0 +1,140 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file store/transaction.hpp +/// Implementation of transactions on the backend. + +#if !defined(STORE_TRANSACTION_HPP) +#define STORE_TRANSACTION_HPP + +extern "C" { +#include +} + +#include +#include +#include + +#include "engine/test_program.hpp" +#include "utils/datetime.hpp" +#include "utils/fs/path.hpp" +#include "utils/optional.hpp" + +namespace engine { +class action; +class context; +class test_result; +} // namespace engine + +namespace store { + + +class backend; +class transaction; + + +namespace detail { + + +engine::test_program_ptr get_test_program(backend&, const int64_t); + + +} // namespace detail + + +/// Iterator for the set of test case results that are part of an action. +/// +/// \todo Note that this is not a "standard" C++ iterator. I have chosen to +/// implement a different interface because it makes things easier to represent +/// an SQL statement state. Rewrite as a proper C++ iterator, inheriting from +/// std::iterator. +class results_iterator { + struct impl; + + /// Pointer to the shared internal implementation. + std::tr1::shared_ptr< impl > _pimpl; + + friend class transaction; + results_iterator(std::tr1::shared_ptr< impl >); + +public: + ~results_iterator(void); + + results_iterator& operator++(void); + operator bool(void) const; + + const engine::test_program_ptr test_program(void) const; + std::string test_case_name(void) const; + engine::test_result result(void) const; + utils::datetime::delta duration(void) const; + + std::string stdout_contents(void) const; + std::string stderr_contents(void) const; +}; + + +/// Representation of a transaction. +/// +/// Transactions are the entry place for high-level calls that access the +/// database. +class transaction { + struct impl; + + /// Pointer to the shared internal implementation. + std::tr1::shared_ptr< impl > _pimpl; + + friend class backend; + transaction(backend&); + +public: + ~transaction(void); + + void commit(void); + void rollback(void); + + engine::action get_action(const int64_t); + results_iterator get_action_results(const int64_t); + std::pair< int64_t, engine::action > get_latest_action(void); + engine::context get_context(const int64_t); + + int64_t put_action(const engine::action&, const int64_t); + int64_t put_context(const engine::context&); + int64_t put_test_program(const engine::test_program&, const int64_t); + int64_t put_test_case(const engine::test_case&, const int64_t); + utils::optional< int64_t > put_test_case_file(const std::string&, + const utils::fs::path&, + const int64_t); + int64_t put_result(const engine::test_result&, const int64_t, + const utils::datetime::timestamp&, + const utils::datetime::timestamp&); +}; + + +} // namespace store + +#endif // !defined(STORE_TRANSACTION_HPP) diff --git a/external/bsd/kyua-cli/dist/store/transaction_test.cpp b/external/bsd/kyua-cli/dist/store/transaction_test.cpp new file mode 100644 index 000000000..fe42b1116 --- /dev/null +++ b/external/bsd/kyua-cli/dist/store/transaction_test.cpp @@ -0,0 +1,926 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "store/transaction.hpp" + +#include +#include +#include +#include + +#include + +#include "engine/action.hpp" +#include "engine/context.hpp" +#include "engine/test_result.hpp" +#include "store/backend.hpp" +#include "store/exceptions.hpp" +#include "utils/datetime.hpp" +#include "utils/fs/path.hpp" +#include "utils/logging/operations.hpp" +#include "utils/optional.ipp" +#include "utils/sqlite/database.hpp" +#include "utils/sqlite/exceptions.hpp" +#include "utils/sqlite/statement.ipp" +#include "utils/units.hpp" + +namespace datetime = utils::datetime; +namespace fs = utils::fs; +namespace logging = utils::logging; +namespace sqlite = utils::sqlite; +namespace units = utils::units; + +using utils::none; +using utils::optional; + + +namespace { + + +/// Performs a test for a working put_result +/// +/// \param result The result object to put. +/// \param result_type The textual name of the result to expect in the +/// database. +/// \param exp_reason The reason to expect in the database. This is separate +/// from the result parameter so that we can handle passed() here as well. +/// Just provide NULL in this case. +static void +do_put_result_ok_test(const engine::test_result& result, + const char* result_type, const char* exp_reason) +{ + store::backend backend = store::backend::open_rw(fs::path("test.db")); + backend.database().exec("PRAGMA foreign_keys = OFF"); + store::transaction tx = backend.start(); + const datetime::timestamp start_time = datetime::timestamp::from_values( + 2012, 01, 30, 22, 10, 00, 0); + const datetime::timestamp end_time = datetime::timestamp::from_values( + 2012, 01, 30, 22, 15, 30, 123456); + tx.put_result(result, 312, start_time, end_time); + tx.commit(); + + sqlite::statement stmt = backend.database().create_statement( + "SELECT test_case_id, result_type, result_reason " + "FROM test_results"); + + ATF_REQUIRE(stmt.step()); + ATF_REQUIRE_EQ(312, stmt.column_int64(0)); + ATF_REQUIRE_EQ(result_type, stmt.column_text(1)); + if (exp_reason != NULL) + ATF_REQUIRE_EQ(exp_reason, stmt.column_text(2)); + else + ATF_REQUIRE(stmt.column_type(2) == sqlite::type_null); + ATF_REQUIRE(!stmt.step()); +} + + +} // anonymous namespace + + +ATF_TEST_CASE(commit__ok); +ATF_TEST_CASE_HEAD(commit__ok) +{ + logging::set_inmemory(); + set_md_var("require.files", store::detail::schema_file().c_str()); +} +ATF_TEST_CASE_BODY(commit__ok) +{ + store::backend backend = store::backend::open_rw(fs::path("test.db")); + store::transaction tx = backend.start(); + backend.database().exec("CREATE TABLE a (b INTEGER PRIMARY KEY)"); + backend.database().exec("SELECT * FROM a"); + tx.commit(); + backend.database().exec("SELECT * FROM a"); +} + + +ATF_TEST_CASE(commit__fail); +ATF_TEST_CASE_HEAD(commit__fail) +{ + logging::set_inmemory(); + set_md_var("require.files", store::detail::schema_file().c_str()); +} +ATF_TEST_CASE_BODY(commit__fail) +{ + store::backend backend = store::backend::open_rw(fs::path("test.db")); + const engine::context context(fs::path("/foo/bar"), + std::map< std::string, std::string >()); + { + store::transaction tx = backend.start(); + tx.put_context(context); + backend.database().exec( + "CREATE TABLE foo (" + "a REFERENCES contexts(context_id) DEFERRABLE INITIALLY DEFERRED)"); + backend.database().exec("INSERT INTO foo VALUES (912378472)"); + ATF_REQUIRE_THROW(store::error, tx.commit()); + } + // If the code attempts to maintain any state regarding the already-put + // objects and the commit does not clean up correctly, this would fail in + // some manner. + store::transaction tx = backend.start(); + tx.put_context(context); + tx.commit(); +} + + +ATF_TEST_CASE(rollback__ok); +ATF_TEST_CASE_HEAD(rollback__ok) +{ + logging::set_inmemory(); + set_md_var("require.files", store::detail::schema_file().c_str()); +} +ATF_TEST_CASE_BODY(rollback__ok) +{ + store::backend backend = store::backend::open_rw(fs::path("test.db")); + store::transaction tx = backend.start(); + backend.database().exec("CREATE TABLE a_table (b INTEGER PRIMARY KEY)"); + backend.database().exec("SELECT * FROM a_table"); + tx.rollback(); + ATF_REQUIRE_THROW_RE(sqlite::error, "a_table", + backend.database().exec("SELECT * FROM a_table")); +} + + +ATF_TEST_CASE(get_put_action__ok); +ATF_TEST_CASE_HEAD(get_put_action__ok) +{ + logging::set_inmemory(); + set_md_var("require.files", store::detail::schema_file().c_str()); +} +ATF_TEST_CASE_BODY(get_put_action__ok) +{ + store::backend backend = store::backend::open_rw(fs::path("test.db")); + const engine::context context1(fs::path("/foo/bar"), + std::map< std::string, std::string >()); + const engine::context context2(fs::path("/foo/baz"), + std::map< std::string, std::string >()); + const engine::action exp_action1(context1); + const engine::action exp_action2(context2); + const engine::action exp_action3(context1); + + int64_t id1, id2, id3; + { + store::transaction tx = backend.start(); + const int64_t context1_id = tx.put_context(context1); + const int64_t context2_id = tx.put_context(context2); + id1 = tx.put_action(exp_action1, context1_id); + id3 = tx.put_action(exp_action3, context1_id); + id2 = tx.put_action(exp_action2, context2_id); + tx.commit(); + } + { + store::transaction tx = backend.start(); + const engine::action action1 = tx.get_action(id1); + const engine::action action2 = tx.get_action(id2); + const engine::action action3 = tx.get_action(id3); + tx.rollback(); + + ATF_REQUIRE(exp_action1 == action1); + ATF_REQUIRE(exp_action2 == action2); + ATF_REQUIRE(exp_action3 == action3); + } +} + + +ATF_TEST_CASE(get_put_action__get_fail__missing); +ATF_TEST_CASE_HEAD(get_put_action__get_fail__missing) +{ + logging::set_inmemory(); + set_md_var("require.files", store::detail::schema_file().c_str()); +} +ATF_TEST_CASE_BODY(get_put_action__get_fail__missing) +{ + store::backend backend = store::backend::open_rw(fs::path("test.db")); + + store::transaction tx = backend.start(); + ATF_REQUIRE_THROW_RE(store::error, "action 523: does not exist", + tx.get_action(523)); +} + + +ATF_TEST_CASE(get_put_action__get_fail__invalid_context); +ATF_TEST_CASE_HEAD(get_put_action__get_fail__invalid_context) +{ + logging::set_inmemory(); + set_md_var("require.files", store::detail::schema_file().c_str()); +} +ATF_TEST_CASE_BODY(get_put_action__get_fail__invalid_context) +{ + store::backend backend = store::backend::open_rw(fs::path("test.db")); + backend.database().exec("PRAGMA foreign_keys = OFF"); + backend.database().exec("INSERT INTO actions (action_id, context_id) " + "VALUES (123, 456)"); + + store::transaction tx = backend.start(); + ATF_REQUIRE_THROW_RE(store::error, "context 456: does not exist", + tx.get_action(123)); +} + + +ATF_TEST_CASE(get_put_action__put_fail); +ATF_TEST_CASE_HEAD(get_put_action__put_fail) +{ + logging::set_inmemory(); + set_md_var("require.files", store::detail::schema_file().c_str()); +} +ATF_TEST_CASE_BODY(get_put_action__put_fail) +{ + store::backend backend = store::backend::open_rw(fs::path("test.db")); + store::transaction tx = backend.start(); + const engine::context context(fs::path("/foo/bar"), + std::map< std::string, std::string >()); + const int64_t context_id = tx.put_context(context); + const engine::action action(context); + backend.database().exec("DROP TABLE actions"); + ATF_REQUIRE_THROW(store::error, tx.put_action(action, context_id)); + tx.commit(); +} + + +ATF_TEST_CASE(get_action_results__none); +ATF_TEST_CASE_HEAD(get_action_results__none) +{ + logging::set_inmemory(); + set_md_var("require.files", store::detail::schema_file().c_str()); +} +ATF_TEST_CASE_BODY(get_action_results__none) +{ + store::backend backend = store::backend::open_rw(fs::path("test.db")); + store::transaction tx = backend.start(); + store::results_iterator iter = tx.get_action_results(1); + ATF_REQUIRE(!iter); +} + + +ATF_TEST_CASE(get_action_results__many); +ATF_TEST_CASE_HEAD(get_action_results__many) +{ + logging::set_inmemory(); + set_md_var("require.files", store::detail::schema_file().c_str()); +} +ATF_TEST_CASE_BODY(get_action_results__many) +{ + store::backend backend = store::backend::open_rw(fs::path("test.db")); + + store::transaction tx = backend.start(); + + const engine::context context(fs::path("/foo/bar"), + std::map< std::string, std::string >()); + const engine::action action(context); + const int64_t context_id = tx.put_context(context); + const int64_t action_id = tx.put_action(action, context_id); + const int64_t action2_id = tx.put_action(action, context_id); + + const datetime::timestamp start_time1 = datetime::timestamp::from_values( + 2012, 01, 30, 22, 10, 00, 0); + const datetime::timestamp end_time1 = datetime::timestamp::from_values( + 2012, 01, 30, 22, 15, 30, 1234); + const datetime::timestamp start_time2 = datetime::timestamp::from_values( + 2012, 01, 30, 22, 15, 40, 987); + const datetime::timestamp end_time2 = datetime::timestamp::from_values( + 2012, 01, 30, 22, 16, 0, 0); + + atf::utils::create_file("unused.txt", "unused file\n"); + + engine::test_program test_program_1( + "plain", fs::path("a/prog1"), fs::path("/the/root"), "suite1", + engine::metadata_builder().build()); + engine::test_case_ptr test_case_1(new engine::test_case( + "plain", test_program_1, "main", engine::metadata_builder().build())); + engine::test_cases_vector test_cases_1; + test_cases_1.push_back(test_case_1); + test_program_1.set_test_cases(test_cases_1); + const engine::test_result result_1(engine::test_result::passed); + { + const int64_t tp_id = tx.put_test_program(test_program_1, action_id); + const int64_t tc_id = tx.put_test_case(*test_case_1, tp_id); + atf::utils::create_file("prog1.out", "stdout of prog1\n"); + tx.put_test_case_file("__STDOUT__", fs::path("prog1.out"), tc_id); + tx.put_test_case_file("unused.txt", fs::path("unused.txt"), tc_id); + tx.put_result(result_1, tc_id, start_time1, end_time1); + + const int64_t tp2_id = tx.put_test_program(test_program_1, action2_id); + const int64_t tc2_id = tx.put_test_case(*test_case_1, tp2_id); + tx.put_test_case_file("__STDOUT__", fs::path("unused.txt"), tc2_id); + tx.put_test_case_file("__STDERR__", fs::path("unused.txt"), tc2_id); + tx.put_result(result_1, tc2_id, start_time1, end_time1); + } + + engine::test_program test_program_2( + "plain", fs::path("b/prog2"), fs::path("/the/root"), "suite2", + engine::metadata_builder().build()); + engine::test_case_ptr test_case_2(new engine::test_case( + "plain", test_program_2, "main", engine::metadata_builder().build())); + engine::test_cases_vector test_cases_2; + test_cases_2.push_back(test_case_2); + test_program_2.set_test_cases(test_cases_2); + const engine::test_result result_2(engine::test_result::failed, + "Some text"); + { + const int64_t tp_id = tx.put_test_program(test_program_2, action_id); + const int64_t tc_id = tx.put_test_case(*test_case_2, tp_id); + atf::utils::create_file("prog2.err", "stderr of prog2\n"); + tx.put_test_case_file("__STDERR__", fs::path("prog2.err"), tc_id); + tx.put_test_case_file("unused.txt", fs::path("unused.txt"), tc_id); + tx.put_result(result_2, tc_id, start_time2, end_time2); + } + + tx.commit(); + + store::transaction tx2 = backend.start(); + store::results_iterator iter = tx2.get_action_results(action_id); + ATF_REQUIRE(iter); + ATF_REQUIRE(test_program_1 == *iter.test_program()); + ATF_REQUIRE_EQ("main", iter.test_case_name()); + ATF_REQUIRE_EQ("stdout of prog1\n", iter.stdout_contents()); + ATF_REQUIRE(iter.stderr_contents().empty()); + ATF_REQUIRE(result_1 == iter.result()); + ATF_REQUIRE(end_time1 - start_time1 == iter.duration()); + ATF_REQUIRE(++iter); + ATF_REQUIRE(test_program_2 == *iter.test_program()); + ATF_REQUIRE_EQ("main", iter.test_case_name()); + ATF_REQUIRE(iter.stdout_contents().empty()); + ATF_REQUIRE_EQ("stderr of prog2\n", iter.stderr_contents()); + ATF_REQUIRE(result_2 == iter.result()); + ATF_REQUIRE(end_time2 - start_time2 == iter.duration()); + ATF_REQUIRE(!++iter); +} + + +ATF_TEST_CASE(get_latest_action__ok); +ATF_TEST_CASE_HEAD(get_latest_action__ok) +{ + logging::set_inmemory(); + set_md_var("require.files", store::detail::schema_file().c_str()); +} +ATF_TEST_CASE_BODY(get_latest_action__ok) +{ + store::backend backend = store::backend::open_rw(fs::path("test.db")); + const engine::context context1(fs::path("/foo/bar"), + std::map< std::string, std::string >()); + const engine::context context2(fs::path("/foo/baz"), + std::map< std::string, std::string >()); + const engine::action exp_action1(context1); + const engine::action exp_action2(context2); + + int64_t id2; + { + store::transaction tx = backend.start(); + const int64_t context1_id = tx.put_context(context1); + const int64_t context2_id = tx.put_context(context2); + (void)tx.put_action(exp_action1, context1_id); + id2 = tx.put_action(exp_action2, context2_id); + tx.commit(); + } + { + store::transaction tx = backend.start(); + const std::pair< int64_t, engine::action > latest_action = + tx.get_latest_action(); + tx.rollback(); + + ATF_REQUIRE(id2 == latest_action.first); + ATF_REQUIRE(exp_action2 == latest_action.second); + } +} + + +ATF_TEST_CASE(get_latest_action__none); +ATF_TEST_CASE_HEAD(get_latest_action__none) +{ + logging::set_inmemory(); + set_md_var("require.files", store::detail::schema_file().c_str()); +} +ATF_TEST_CASE_BODY(get_latest_action__none) +{ + store::backend backend = store::backend::open_rw(fs::path("test.db")); + store::transaction tx = backend.start(); + ATF_REQUIRE_THROW_RE(store::error, "No actions", tx.get_latest_action()); +} + + +ATF_TEST_CASE(get_latest_action__invalid_context); +ATF_TEST_CASE_HEAD(get_latest_action__invalid_context) +{ + logging::set_inmemory(); + set_md_var("require.files", store::detail::schema_file().c_str()); +} +ATF_TEST_CASE_BODY(get_latest_action__invalid_context) +{ + store::backend backend = store::backend::open_rw(fs::path("test.db")); + backend.database().exec("PRAGMA foreign_keys = OFF"); + backend.database().exec("INSERT INTO actions (action_id, context_id) " + "VALUES (123, 456)"); + + store::transaction tx = backend.start(); + ATF_REQUIRE_THROW_RE(store::error, "context 456: does not exist", + tx.get_latest_action()); +} + + +ATF_TEST_CASE(get_put_context__ok); +ATF_TEST_CASE_HEAD(get_put_context__ok) +{ + logging::set_inmemory(); + set_md_var("require.files", store::detail::schema_file().c_str()); +} +ATF_TEST_CASE_BODY(get_put_context__ok) +{ + store::backend backend = store::backend::open_rw(fs::path("test.db")); + + std::map< std::string, std::string > env1; + env1["A1"] = "foo"; + env1["A2"] = "bar"; + std::map< std::string, std::string > env2; + const engine::context exp_context1(fs::path("/foo/bar"), env1); + const engine::context exp_context2(fs::path("/foo/bar"), env1); + const engine::context exp_context3(fs::path("/foo/baz"), env2); + + int64_t id1, id2, id3; + { + store::transaction tx = backend.start(); + id1 = tx.put_context(exp_context1); + id3 = tx.put_context(exp_context3); + id2 = tx.put_context(exp_context2); + tx.commit(); + } + { + store::transaction tx = backend.start(); + const engine::context context1 = tx.get_context(id1); + const engine::context context2 = tx.get_context(id2); + const engine::context context3 = tx.get_context(id3); + tx.rollback(); + + ATF_REQUIRE(exp_context1 == context1); + ATF_REQUIRE(exp_context2 == context2); + ATF_REQUIRE(exp_context3 == context3); + } +} + + +ATF_TEST_CASE(get_put_context__get_fail__missing); +ATF_TEST_CASE_HEAD(get_put_context__get_fail__missing) +{ + logging::set_inmemory(); + set_md_var("require.files", store::detail::schema_file().c_str()); +} +ATF_TEST_CASE_BODY(get_put_context__get_fail__missing) +{ + store::backend backend = store::backend::open_rw(fs::path("test.db")); + + store::transaction tx = backend.start(); + ATF_REQUIRE_THROW_RE(store::error, "context 456: does not exist", + tx.get_context(456)); +} + + +ATF_TEST_CASE(get_put_context__get_fail__invalid_cwd); +ATF_TEST_CASE_HEAD(get_put_context__get_fail__invalid_cwd) +{ + logging::set_inmemory(); + set_md_var("require.files", store::detail::schema_file().c_str()); +} +ATF_TEST_CASE_BODY(get_put_context__get_fail__invalid_cwd) +{ + store::backend backend = store::backend::open_rw(fs::path("test.db")); + + sqlite::statement stmt = backend.database().create_statement( + "INSERT INTO contexts (context_id, cwd) VALUES (78, :cwd)"); + const char buffer[10] = "foo bar"; + stmt.bind(":cwd", sqlite::blob(buffer, sizeof(buffer))); + stmt.step_without_results(); + + store::transaction tx = backend.start(); + ATF_REQUIRE_THROW_RE(store::error, "context 78: .*cwd.*not a string", + tx.get_context(78)); +} + + +ATF_TEST_CASE(get_put_context__get_fail__invalid_env_vars); +ATF_TEST_CASE_HEAD(get_put_context__get_fail__invalid_env_vars) +{ + logging::set_inmemory(); + set_md_var("require.files", store::detail::schema_file().c_str()); +} +ATF_TEST_CASE_BODY(get_put_context__get_fail__invalid_env_vars) +{ + store::backend backend = store::backend::open_rw(fs::path("test.db")); + + backend.database().exec("INSERT INTO contexts (context_id, cwd) " + "VALUES (10, '/foo/bar')"); + backend.database().exec("INSERT INTO contexts (context_id, cwd) " + "VALUES (20, '/foo/bar')"); + + const char buffer[10] = "foo bar"; + + { + sqlite::statement stmt = backend.database().create_statement( + "INSERT INTO env_vars (context_id, var_name, var_value) " + "VALUES (10, :var_name, 'abc')"); + stmt.bind(":var_name", sqlite::blob(buffer, sizeof(buffer))); + stmt.step_without_results(); + } + + { + sqlite::statement stmt = backend.database().create_statement( + "INSERT INTO env_vars (context_id, var_name, var_value) " + "VALUES (20, 'abc', :var_value)"); + stmt.bind(":var_value", sqlite::blob(buffer, sizeof(buffer))); + stmt.step_without_results(); + } + + store::transaction tx = backend.start(); + ATF_REQUIRE_THROW_RE(store::error, "context 10: .*var_name.*not a string", + tx.get_context(10)); + ATF_REQUIRE_THROW_RE(store::error, "context 20: .*var_value.*not a string", + tx.get_context(20)); +} + + +ATF_TEST_CASE(get_put_context__put_fail); +ATF_TEST_CASE_HEAD(get_put_context__put_fail) +{ + logging::set_inmemory(); + set_md_var("require.files", store::detail::schema_file().c_str()); +} +ATF_TEST_CASE_BODY(get_put_context__put_fail) +{ + (void)store::backend::open_rw(fs::path("test.db")); + store::backend backend = store::backend::open_ro(fs::path("test.db")); + store::transaction tx = backend.start(); + const engine::context context(fs::path("/foo/bar"), + std::map< std::string, std::string >()); + ATF_REQUIRE_THROW(store::error, tx.put_context(context)); + tx.commit(); +} + + +ATF_TEST_CASE(put_test_program__ok); +ATF_TEST_CASE_HEAD(put_test_program__ok) +{ + logging::set_inmemory(); + set_md_var("require.files", store::detail::schema_file().c_str()); +} +ATF_TEST_CASE_BODY(put_test_program__ok) +{ + const engine::metadata md = engine::metadata_builder() + .add_custom("var1", "value1") + .add_custom("var2", "value2") + .build(); + const engine::test_program test_program( + "mock", fs::path("the/binary"), fs::path("/some//root"), + "the-suite", md); + + store::backend backend = store::backend::open_rw(fs::path("test.db")); + backend.database().exec("PRAGMA foreign_keys = OFF"); + store::transaction tx = backend.start(); + const int64_t test_program_id = tx.put_test_program(test_program, 15); + tx.commit(); + + { + sqlite::statement stmt = backend.database().create_statement( + "SELECT * FROM test_programs"); + + ATF_REQUIRE(stmt.step()); + ATF_REQUIRE_EQ(test_program_id, + stmt.safe_column_int64("test_program_id")); + ATF_REQUIRE_EQ(15, stmt.safe_column_int64("action_id")); + ATF_REQUIRE_EQ("/some/root/the/binary", + stmt.safe_column_text("absolute_path")); + ATF_REQUIRE_EQ("/some/root", stmt.safe_column_text("root")); + ATF_REQUIRE_EQ("the/binary", stmt.safe_column_text("relative_path")); + ATF_REQUIRE_EQ("the-suite", stmt.safe_column_text("test_suite_name")); + ATF_REQUIRE(!stmt.step()); + } +} + + +ATF_TEST_CASE(put_test_program__fail); +ATF_TEST_CASE_HEAD(put_test_program__fail) +{ + logging::set_inmemory(); + set_md_var("require.files", store::detail::schema_file().c_str()); +} +ATF_TEST_CASE_BODY(put_test_program__fail) +{ + const engine::test_program test_program( + "mock", fs::path("the/binary"), fs::path("/some/root"), "the-suite", + engine::metadata_builder().build()); + + store::backend backend = store::backend::open_rw(fs::path("test.db")); + store::transaction tx = backend.start(); + ATF_REQUIRE_THROW(store::error, tx.put_test_program(test_program, -1)); + tx.commit(); +} + + +ATF_TEST_CASE(put_test_case__ok); +ATF_TEST_CASE_HEAD(put_test_case__ok) +{ + logging::set_inmemory(); + set_md_var("require.files", store::detail::schema_file().c_str()); +} +ATF_TEST_CASE_BODY(put_test_case__ok) +{ + engine::test_program test_program( + "atf", fs::path("the/binary"), fs::path("/some/root"), "the-suite", + engine::metadata_builder().build()); + + const engine::test_case_ptr test_case1(new engine::test_case( + "atf", test_program, "tc1", engine::metadata_builder().build())); + + const engine::metadata md2 = engine::metadata_builder() + .add_allowed_architecture("powerpc") + .add_allowed_architecture("x86_64") + .add_allowed_platform("amd64") + .add_allowed_platform("macppc") + .add_custom("X-user1", "value1") + .add_custom("X-user2", "value2") + .add_required_config("var1") + .add_required_config("var2") + .add_required_config("var3") + .add_required_file(fs::path("/file1/yes")) + .add_required_file(fs::path("/file2/foo")) + .add_required_program(fs::path("/bin/ls")) + .add_required_program(fs::path("cp")) + .set_description("The description") + .set_has_cleanup(true) + .set_required_memory(units::bytes::parse("1k")) + .set_required_user("root") + .set_timeout(datetime::delta(520, 0)) + .build(); + const engine::test_case_ptr test_case2(new engine::test_case( + "atf", test_program, "tc2", md2)); + + { + engine::test_cases_vector test_cases; + test_cases.push_back(test_case1); + test_cases.push_back(test_case2); + test_program.set_test_cases(test_cases); + } + + store::backend backend = store::backend::open_rw(fs::path("test.db")); + backend.database().exec("PRAGMA foreign_keys = OFF"); + int64_t test_program_id; + { + store::transaction tx = backend.start(); + test_program_id = tx.put_test_program(test_program, 15); + tx.put_test_case(*test_case1, test_program_id); + tx.put_test_case(*test_case2, test_program_id); + tx.commit(); + } + + store::transaction tx = backend.start(); + const engine::test_program_ptr loaded_test_program = + store::detail::get_test_program(backend, test_program_id); + ATF_REQUIRE(test_program == *loaded_test_program); +} + + +ATF_TEST_CASE(put_test_case__fail); +ATF_TEST_CASE_HEAD(put_test_case__fail) +{ + logging::set_inmemory(); + set_md_var("require.files", store::detail::schema_file().c_str()); +} +ATF_TEST_CASE_BODY(put_test_case__fail) +{ + // TODO(jmmv): Use a mock test program and test case. + const engine::test_program test_program( + "plain", fs::path("the/binary"), fs::path("/some/root"), "the-suite", + engine::metadata_builder().build()); + const engine::test_case test_case("plain", test_program, "main", + engine::metadata_builder().build()); + + store::backend backend = store::backend::open_rw(fs::path("test.db")); + store::transaction tx = backend.start(); + ATF_REQUIRE_THROW(store::error, tx.put_test_case(test_case, -1)); + tx.commit(); +} + + +ATF_TEST_CASE(put_test_case_file__empty); +ATF_TEST_CASE_HEAD(put_test_case_file__empty) +{ + logging::set_inmemory(); + set_md_var("require.files", store::detail::schema_file().c_str()); +} +ATF_TEST_CASE_BODY(put_test_case_file__empty) +{ + atf::utils::create_file("input.txt", ""); + + store::backend backend = store::backend::open_rw(fs::path("test.db")); + backend.database().exec("PRAGMA foreign_keys = OFF"); + store::transaction tx = backend.start(); + const optional< int64_t > file_id = tx.put_test_case_file( + "my-file", fs::path("input.txt"), 123L); + tx.commit(); + ATF_REQUIRE(!file_id); + + sqlite::statement stmt = backend.database().create_statement( + "SELECT * FROM test_case_files NATURAL JOIN files"); + ATF_REQUIRE(!stmt.step()); +} + + +ATF_TEST_CASE(put_test_case_file__some); +ATF_TEST_CASE_HEAD(put_test_case_file__some) +{ + logging::set_inmemory(); + set_md_var("require.files", store::detail::schema_file().c_str()); +} +ATF_TEST_CASE_BODY(put_test_case_file__some) +{ + const char contents[] = "This is a test!"; + + atf::utils::create_file("input.txt", contents); + + store::backend backend = store::backend::open_rw(fs::path("test.db")); + backend.database().exec("PRAGMA foreign_keys = OFF"); + store::transaction tx = backend.start(); + const optional< int64_t > file_id = tx.put_test_case_file( + "my-file", fs::path("input.txt"), 123L); + tx.commit(); + ATF_REQUIRE(file_id); + + sqlite::statement stmt = backend.database().create_statement( + "SELECT * FROM test_case_files NATURAL JOIN files"); + + ATF_REQUIRE(stmt.step()); + ATF_REQUIRE_EQ(123L, stmt.safe_column_int64("test_case_id")); + ATF_REQUIRE_EQ("my-file", stmt.safe_column_text("file_name")); + const sqlite::blob blob = stmt.safe_column_blob("contents"); + ATF_REQUIRE(std::strlen(contents) == static_cast< std::size_t >(blob.size)); + ATF_REQUIRE(std::memcmp(contents, blob.memory, blob.size) == 0); + ATF_REQUIRE(!stmt.step()); +} + + +ATF_TEST_CASE(put_test_case_file__fail); +ATF_TEST_CASE_HEAD(put_test_case_file__fail) +{ + logging::set_inmemory(); + set_md_var("require.files", store::detail::schema_file().c_str()); +} +ATF_TEST_CASE_BODY(put_test_case_file__fail) +{ + store::backend backend = store::backend::open_rw(fs::path("test.db")); + backend.database().exec("PRAGMA foreign_keys = OFF"); + store::transaction tx = backend.start(); + ATF_REQUIRE_THROW(store::error, + tx.put_test_case_file("foo", fs::path("missing"), 1L)); + tx.commit(); + + sqlite::statement stmt = backend.database().create_statement( + "SELECT * FROM test_case_files NATURAL JOIN files"); + ATF_REQUIRE(!stmt.step()); +} + + +ATF_TEST_CASE(put_result__ok__broken); +ATF_TEST_CASE_HEAD(put_result__ok__broken) +{ + logging::set_inmemory(); + set_md_var("require.files", store::detail::schema_file().c_str()); +} +ATF_TEST_CASE_BODY(put_result__ok__broken) +{ + const engine::test_result result(engine::test_result::broken, "a b cd"); + do_put_result_ok_test(result, "broken", "a b cd"); +} + + +ATF_TEST_CASE(put_result__ok__expected_failure); +ATF_TEST_CASE_HEAD(put_result__ok__expected_failure) +{ + logging::set_inmemory(); + set_md_var("require.files", store::detail::schema_file().c_str()); +} +ATF_TEST_CASE_BODY(put_result__ok__expected_failure) +{ + const engine::test_result result(engine::test_result::expected_failure, + "a b cd"); + do_put_result_ok_test(result, "expected_failure", "a b cd"); +} + + +ATF_TEST_CASE(put_result__ok__failed); +ATF_TEST_CASE_HEAD(put_result__ok__failed) +{ + logging::set_inmemory(); + set_md_var("require.files", store::detail::schema_file().c_str()); +} +ATF_TEST_CASE_BODY(put_result__ok__failed) +{ + const engine::test_result result(engine::test_result::failed, "a b cd"); + do_put_result_ok_test(result, "failed", "a b cd"); +} + + +ATF_TEST_CASE(put_result__ok__passed); +ATF_TEST_CASE_HEAD(put_result__ok__passed) +{ + logging::set_inmemory(); + set_md_var("require.files", store::detail::schema_file().c_str()); +} +ATF_TEST_CASE_BODY(put_result__ok__passed) +{ + const engine::test_result result(engine::test_result::passed); + do_put_result_ok_test(result, "passed", NULL); +} + + +ATF_TEST_CASE(put_result__ok__skipped); +ATF_TEST_CASE_HEAD(put_result__ok__skipped) +{ + logging::set_inmemory(); + set_md_var("require.files", store::detail::schema_file().c_str()); +} +ATF_TEST_CASE_BODY(put_result__ok__skipped) +{ + const engine::test_result result(engine::test_result::skipped, "a b cd"); + do_put_result_ok_test(result, "skipped", "a b cd"); +} + + +ATF_TEST_CASE(put_result__fail); +ATF_TEST_CASE_HEAD(put_result__fail) +{ + logging::set_inmemory(); + set_md_var("require.files", store::detail::schema_file().c_str()); +} +ATF_TEST_CASE_BODY(put_result__fail) +{ + const engine::test_result result(engine::test_result::broken, "foo"); + + store::backend backend = store::backend::open_rw(fs::path("test.db")); + store::transaction tx = backend.start(); + const datetime::timestamp zero = datetime::timestamp::from_microseconds(0); + ATF_REQUIRE_THROW(store::error, tx.put_result(result, -1, zero, zero)); + tx.commit(); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, commit__ok); + ATF_ADD_TEST_CASE(tcs, commit__fail); + ATF_ADD_TEST_CASE(tcs, rollback__ok); + + ATF_ADD_TEST_CASE(tcs, get_put_action__ok); + ATF_ADD_TEST_CASE(tcs, get_put_action__get_fail__missing); + ATF_ADD_TEST_CASE(tcs, get_put_action__get_fail__invalid_context); + ATF_ADD_TEST_CASE(tcs, get_put_action__put_fail); + + ATF_ADD_TEST_CASE(tcs, get_action_results__none); + ATF_ADD_TEST_CASE(tcs, get_action_results__many); + + ATF_ADD_TEST_CASE(tcs, get_latest_action__ok); + ATF_ADD_TEST_CASE(tcs, get_latest_action__none); + ATF_ADD_TEST_CASE(tcs, get_latest_action__invalid_context); + + ATF_ADD_TEST_CASE(tcs, get_put_context__ok); + ATF_ADD_TEST_CASE(tcs, get_put_context__get_fail__missing); + ATF_ADD_TEST_CASE(tcs, get_put_context__get_fail__invalid_cwd); + ATF_ADD_TEST_CASE(tcs, get_put_context__get_fail__invalid_env_vars); + ATF_ADD_TEST_CASE(tcs, get_put_context__put_fail); + + ATF_ADD_TEST_CASE(tcs, put_test_program__ok); + ATF_ADD_TEST_CASE(tcs, put_test_program__fail); + ATF_ADD_TEST_CASE(tcs, put_test_case__ok); + ATF_ADD_TEST_CASE(tcs, put_test_case__fail); + ATF_ADD_TEST_CASE(tcs, put_test_case_file__empty); + ATF_ADD_TEST_CASE(tcs, put_test_case_file__some); + ATF_ADD_TEST_CASE(tcs, put_test_case_file__fail); + + ATF_ADD_TEST_CASE(tcs, put_result__ok__broken); + ATF_ADD_TEST_CASE(tcs, put_result__ok__expected_failure); + ATF_ADD_TEST_CASE(tcs, put_result__ok__failed); + ATF_ADD_TEST_CASE(tcs, put_result__ok__passed); + ATF_ADD_TEST_CASE(tcs, put_result__ok__skipped); + ATF_ADD_TEST_CASE(tcs, put_result__fail); +} diff --git a/external/bsd/kyua-cli/dist/utils/Kyuafile b/external/bsd/kyua-cli/dist/utils/Kyuafile new file mode 100644 index 000000000..b529a3fb8 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/Kyuafile @@ -0,0 +1,23 @@ +syntax(2) + +test_suite("kyua") + +atf_test_program{name="auto_array_test"} +atf_test_program{name="datetime_test"} +atf_test_program{name="env_test"} +atf_test_program{name="memory_test"} +atf_test_program{name="optional_test"} +atf_test_program{name="passwd_test"} +atf_test_program{name="sanity_test"} +atf_test_program{name="stream_test"} +atf_test_program{name="units_test"} + +include("cmdline/Kyuafile") +include("config/Kyuafile") +include("format/Kyuafile") +include("fs/Kyuafile") +include("logging/Kyuafile") +include("process/Kyuafile") +include("signals/Kyuafile") +include("sqlite/Kyuafile") +include("text/Kyuafile") diff --git a/external/bsd/kyua-cli/dist/utils/auto_array.hpp b/external/bsd/kyua-cli/dist/utils/auto_array.hpp new file mode 100644 index 000000000..21dfe97d8 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/auto_array.hpp @@ -0,0 +1,103 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file utils/auto_array.hpp +/// Provides the utils::auto_array class. +/// +/// The class is provided as a separate module on its own to minimize +/// header-inclusion side-effects. + +#if !defined(UTILS_AUTO_ARRAY_HPP) +#define UTILS_AUTO_ARRAY_HPP + +#include + +namespace utils { + + +template< class > class auto_array; + + +namespace detail { + + +/// Wrapper class to provide reference semantics for utils::auto_array. +/// +/// This class is internally used, for example, to allow returning a +/// utils::auto_array from a function. +template< class T > +class auto_array_ref { + /// Internal pointer to the dynamically-allocated array. + T* _ptr; + + template< class > friend class utils::auto_array; + +public: + explicit auto_array_ref(T*); +}; + + +} // namespace detail + + +/// A simple smart pointer for arrays providing strict ownership semantics. +/// +/// This class is the counterpart of std::auto_ptr for arrays. The semantics of +/// the API of this class are the same as those of std::auto_ptr. +/// +/// The wrapped pointer must be NULL or must have been allocated using operator +/// new[]. +template< class T > +class auto_array { + /// Internal pointer to the dynamically-allocated array. + T* _ptr; + +public: + auto_array(T* = NULL) throw(); + auto_array(auto_array< T >&) throw(); + auto_array(detail::auto_array_ref< T >) throw(); + ~auto_array(void) throw(); + + T* get(void) throw(); + const T* get(void) const throw(); + + T* release(void) throw(); + void reset(T* = NULL) throw(); + + auto_array< T >& operator=(auto_array< T >&) throw(); + auto_array< T >& operator=(detail::auto_array_ref< T >) throw(); + T& operator[](int) throw(); + const T& operator[](int) const throw(); + operator detail::auto_array_ref< T >(void) throw(); +}; + + +} // namespace utils + + +#endif // !defined(UTILS_AUTO_ARRAY_HPP) diff --git a/external/bsd/kyua-cli/dist/utils/auto_array.ipp b/external/bsd/kyua-cli/dist/utils/auto_array.ipp new file mode 100644 index 000000000..d23153caf --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/auto_array.ipp @@ -0,0 +1,227 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#if !defined(UTILS_AUTO_ARRAY_IPP) +#define UTILS_AUTO_ARRAY_IPP + +#include "utils/auto_array.hpp" + +namespace utils { + + +namespace detail { + + +/// Constructs a new auto_array_ref from a pointer. +/// +/// \param ptr The pointer to wrap. +template< class T > inline +auto_array_ref< T >::auto_array_ref(T* ptr) : + _ptr(ptr) +{ +} + + +} // namespace detail + + +/// Constructs a new auto_array from a given pointer. +/// +/// This grabs ownership of the pointer unless it is NULL. +/// +/// \param ptr The pointer to wrap. If not NULL, the memory pointed to must +/// have been allocated with operator new[]. +template< class T > inline +auto_array< T >::auto_array(T* ptr) throw() : + _ptr(ptr) +{ +} + + +/// Constructs a copy of an auto_array. +/// +/// \param ptr The pointer to copy from. This pointer is invalidated and the +/// new copy grabs ownership of the object pointed to. +template< class T > inline +auto_array< T >::auto_array(auto_array< T >& ptr) throw() : + _ptr(ptr.release()) +{ +} + + +/// Constructs a new auto_array form a reference. +/// +/// Internal function used to construct a new auto_array from an object +/// returned, for example, from a function. +/// +/// \param ref The reference. +template< class T > inline +auto_array< T >::auto_array(detail::auto_array_ref< T > ref) throw() : + _ptr(ref._ptr) +{ +} + + +/// Destructor for auto_array objects. +template< class T > inline +auto_array< T >::~auto_array(void) throw() +{ + if (_ptr != NULL) + delete [] _ptr; +} + + +/// Gets the value of the wrapped pointer without releasing ownership. +/// +/// \return The raw mutable pointer. +template< class T > inline +T* +auto_array< T >::get(void) throw() +{ + return _ptr; +} + + +/// Gets the value of the wrapped pointer without releasing ownership. +/// +/// \return The raw immutable pointer. +template< class T > inline +const T* +auto_array< T >::get(void) const throw() +{ + return _ptr; +} + + +/// Gets the value of the wrapped pointer and releases ownership. +/// +/// \return The raw mutable pointer. +template< class T > inline +T* +auto_array< T >::release(void) throw() +{ + T* ptr = _ptr; + _ptr = NULL; + return ptr; +} + + +/// Changes the value of the wrapped pointer. +/// +/// If the auto_array was pointing to an array, such array is released and the +/// wrapped pointer is replaced with the new pointer provided. +/// +/// \param ptr The pointer to use as a replacement; may be NULL. +template< class T > inline +void +auto_array< T >::reset(T* ptr) throw() +{ + if (_ptr != NULL) + delete [] _ptr; + _ptr = ptr; +} + + +/// Assignment operator. +/// +/// \param ptr The object to copy from. This is invalidated after the copy. +/// \return A reference to the auto_array object itself. +template< class T > inline +auto_array< T >& +auto_array< T >::operator=(auto_array< T >& ptr) throw() +{ + reset(ptr.release()); + return *this; +} + + +/// Internal assignment operator for function returns. +/// +/// \param ref The reference object to copy from. +/// \return A reference to the auto_array object itself. +template< class T > inline +auto_array< T >& +auto_array< T >::operator=(detail::auto_array_ref< T > ref) throw() +{ + if (_ptr != ref._ptr) { + delete [] _ptr; + _ptr = ref._ptr; + } + return *this; +} + + +/// Subscript operator to access the array by position. +/// +/// This does not perform any bounds checking, in particular because auto_array +/// does not know the size of the arrays pointed to by it. +/// +/// \param pos The position to access, indexed from zero. +/// +/// \return A mutable reference to the element at the specified position. +template< class T > inline +T& +auto_array< T >::operator[](int pos) throw() +{ + return _ptr[pos]; +} + + +/// Subscript operator to access the array by position. +/// +/// This does not perform any bounds checking, in particular because auto_array +/// does not know the size of the arrays pointed to by it. +/// +/// \param pos The position to access, indexed from zero. +/// +/// \return An immutable reference to the element at the specified position. +template< class T > inline +const T& +auto_array< T >::operator[](int pos) const throw() +{ + return _ptr[pos]; +} + + +/// Internal conversion to a reference wrapper. +/// +/// This is used internally to support returning auto_array objects from +/// functions. The auto_array is invalidated when used. +/// +/// \return A new detail::auto_array_ref object holding the pointer. +template< class T > inline +auto_array< T >::operator detail::auto_array_ref< T >(void) throw() +{ + return detail::auto_array_ref< T >(release()); +} + + +} // namespace utils + + +#endif // !defined(UTILS_AUTO_ARRAY_IPP) diff --git a/external/bsd/kyua-cli/dist/utils/auto_array_test.cpp b/external/bsd/kyua-cli/dist/utils/auto_array_test.cpp new file mode 100644 index 000000000..ade8c5e7b --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/auto_array_test.cpp @@ -0,0 +1,316 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/auto_array.ipp" + +extern "C" { +#include +} + +#include + +#include + +#include "utils/defs.hpp" + +using utils::auto_array; + + +namespace { + + +/// Mock class to capture calls to the new and delete operators. +class test_array { +public: + /// User-settable cookie to disambiguate instances of this class. + int m_value; + + /// The current balance of existing test_array instances. + static ssize_t m_nblocks; + + /// Captures invalid calls to new on an array. + /// + /// \param unused_size The amount of memory to allocate, in bytes. + /// + /// \return Nothing; this always fails the test case. + void* + operator new(const size_t UTILS_UNUSED_PARAM(size)) + { + ATF_FAIL("New called but should have been new[]"); + return new int(5); + } + + /// Obtains memory for a new instance and increments m_nblocks. + /// + /// \param size The amount of memory to allocate, in bytes. + /// + /// \return A pointer to the allocated memory. + /// + /// \throw std::bad_alloc If the memory cannot be allocated. + void* + operator new[](const size_t size) + { + void* mem = ::operator new(size); + m_nblocks++; + std::cout << "Allocated 'test_array' object " << mem << "\n"; + return mem; + } + + /// Captures invalid calls to delete on an array. + /// + /// \param unused_mem The pointer to the memory to be deleted. + /// + /// \return Nothing; this always fails the test case. + void + operator delete(void* UTILS_UNUSED_PARAM(mem)) + { + ATF_FAIL("Delete called but should have been delete[]"); + } + + /// Deletes a previously allocated array and decrements m_nblocks. + /// + /// \param mem The pointer to the memory to be deleted. + void + operator delete[](void* mem) + { + std::cout << "Releasing 'test_array' object " << mem << "\n"; + if (m_nblocks == 0) + ATF_FAIL("Unbalanced delete[]"); + m_nblocks--; + ::operator delete(mem); + } +}; + + +ssize_t test_array::m_nblocks = 0; + + +} // anonymous namespace + + +ATF_TEST_CASE(scope); +ATF_TEST_CASE_HEAD(scope) +{ + set_md_var("descr", "Tests the automatic scope handling in the " + "auto_array smart pointer class"); +} +ATF_TEST_CASE_BODY(scope) +{ + ATF_REQUIRE_EQ(test_array::m_nblocks, 0); + { + auto_array< test_array > t(new test_array[10]); + ATF_REQUIRE_EQ(test_array::m_nblocks, 1); + } + ATF_REQUIRE_EQ(test_array::m_nblocks, 0); +} + + +ATF_TEST_CASE(copy); +ATF_TEST_CASE_HEAD(copy) +{ + set_md_var("descr", "Tests the auto_array smart pointer class' copy " + "constructor"); +} +ATF_TEST_CASE_BODY(copy) +{ + ATF_REQUIRE_EQ(test_array::m_nblocks, 0); + { + auto_array< test_array > t1(new test_array[10]); + ATF_REQUIRE_EQ(test_array::m_nblocks, 1); + + { + auto_array< test_array > t2(t1); + ATF_REQUIRE_EQ(test_array::m_nblocks, 1); + } + ATF_REQUIRE_EQ(test_array::m_nblocks, 0); + } + ATF_REQUIRE_EQ(test_array::m_nblocks, 0); +} + + +ATF_TEST_CASE(copy_ref); +ATF_TEST_CASE_HEAD(copy_ref) +{ + set_md_var("descr", "Tests the auto_array smart pointer class' copy " + "constructor through the auxiliary ref object"); +} +ATF_TEST_CASE_BODY(copy_ref) +{ + ATF_REQUIRE_EQ(test_array::m_nblocks, 0); + { + auto_array< test_array > t1(new test_array[10]); + ATF_REQUIRE_EQ(test_array::m_nblocks, 1); + + { + auto_array< test_array > t2 = t1; + ATF_REQUIRE_EQ(test_array::m_nblocks, 1); + } + ATF_REQUIRE_EQ(test_array::m_nblocks, 0); + } + ATF_REQUIRE_EQ(test_array::m_nblocks, 0); +} + + +ATF_TEST_CASE(get); +ATF_TEST_CASE_HEAD(get) +{ + set_md_var("descr", "Tests the auto_array smart pointer class' get " + "method"); +} +ATF_TEST_CASE_BODY(get) +{ + test_array* ta = new test_array[10]; + auto_array< test_array > t(ta); + ATF_REQUIRE_EQ(t.get(), ta); +} + + +ATF_TEST_CASE(release); +ATF_TEST_CASE_HEAD(release) +{ + set_md_var("descr", "Tests the auto_array smart pointer class' release " + "method"); +} +ATF_TEST_CASE_BODY(release) +{ + test_array* ta1 = new test_array[10]; + { + auto_array< test_array > t(ta1); + ATF_REQUIRE_EQ(test_array::m_nblocks, 1); + test_array* ta2 = t.release(); + ATF_REQUIRE_EQ(ta2, ta1); + ATF_REQUIRE_EQ(test_array::m_nblocks, 1); + } + ATF_REQUIRE_EQ(test_array::m_nblocks, 1); + delete [] ta1; +} + + +ATF_TEST_CASE(reset); +ATF_TEST_CASE_HEAD(reset) +{ + set_md_var("descr", "Tests the auto_array smart pointer class' reset " + "method"); +} +ATF_TEST_CASE_BODY(reset) +{ + test_array* ta1 = new test_array[10]; + test_array* ta2 = new test_array[10]; + ATF_REQUIRE_EQ(test_array::m_nblocks, 2); + + { + auto_array< test_array > t(ta1); + ATF_REQUIRE_EQ(test_array::m_nblocks, 2); + t.reset(ta2); + ATF_REQUIRE_EQ(test_array::m_nblocks, 1); + t.reset(); + ATF_REQUIRE_EQ(test_array::m_nblocks, 0); + } + ATF_REQUIRE_EQ(test_array::m_nblocks, 0); +} + + +ATF_TEST_CASE(assign); +ATF_TEST_CASE_HEAD(assign) +{ + set_md_var("descr", "Tests the auto_array smart pointer class' " + "assignment operator"); +} +ATF_TEST_CASE_BODY(assign) +{ + ATF_REQUIRE_EQ(test_array::m_nblocks, 0); + { + auto_array< test_array > t1(new test_array[10]); + ATF_REQUIRE_EQ(test_array::m_nblocks, 1); + + { + auto_array< test_array > t2; + t2 = t1; + ATF_REQUIRE_EQ(test_array::m_nblocks, 1); + } + ATF_REQUIRE_EQ(test_array::m_nblocks, 0); + } + ATF_REQUIRE_EQ(test_array::m_nblocks, 0); +} + + +ATF_TEST_CASE(assign_ref); +ATF_TEST_CASE_HEAD(assign_ref) +{ + set_md_var("descr", "Tests the auto_array smart pointer class' " + "assignment operator through the auxiliary ref " + "object"); +} +ATF_TEST_CASE_BODY(assign_ref) +{ + ATF_REQUIRE_EQ(test_array::m_nblocks, 0); + { + auto_array< test_array > t1(new test_array[10]); + ATF_REQUIRE_EQ(test_array::m_nblocks, 1); + + { + auto_array< test_array > t2; + t2 = t1; + ATF_REQUIRE_EQ(test_array::m_nblocks, 1); + } + ATF_REQUIRE_EQ(test_array::m_nblocks, 0); + } + ATF_REQUIRE_EQ(test_array::m_nblocks, 0); +} + + +ATF_TEST_CASE(access); +ATF_TEST_CASE_HEAD(access) +{ + set_md_var("descr", "Tests the auto_array smart pointer class' access " + "operator"); +} +ATF_TEST_CASE_BODY(access) +{ + auto_array< test_array > t(new test_array[10]); + + for (int i = 0; i < 10; i++) + t[i].m_value = i * 2; + + for (int i = 0; i < 10; i++) + ATF_REQUIRE_EQ(t[i].m_value, i * 2); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, scope); + ATF_ADD_TEST_CASE(tcs, copy); + ATF_ADD_TEST_CASE(tcs, copy_ref); + ATF_ADD_TEST_CASE(tcs, get); + ATF_ADD_TEST_CASE(tcs, release); + ATF_ADD_TEST_CASE(tcs, reset); + ATF_ADD_TEST_CASE(tcs, assign); + ATF_ADD_TEST_CASE(tcs, assign_ref); + ATF_ADD_TEST_CASE(tcs, access); +} diff --git a/external/bsd/kyua-cli/dist/utils/cmdline/Kyuafile b/external/bsd/kyua-cli/dist/utils/cmdline/Kyuafile new file mode 100644 index 000000000..d5e6f7122 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/cmdline/Kyuafile @@ -0,0 +1,11 @@ +syntax(2) + +test_suite("kyua") + +atf_test_program{name="base_command_test"} +atf_test_program{name="commands_map_test"} +atf_test_program{name="exceptions_test"} +atf_test_program{name="globals_test"} +atf_test_program{name="options_test"} +atf_test_program{name="parser_test"} +atf_test_program{name="ui_test"} diff --git a/external/bsd/kyua-cli/dist/utils/cmdline/base_command.cpp b/external/bsd/kyua-cli/dist/utils/cmdline/base_command.cpp new file mode 100644 index 000000000..73e832ab2 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/cmdline/base_command.cpp @@ -0,0 +1,200 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/cmdline/base_command.hpp" + +#include "utils/cmdline/exceptions.hpp" +#include "utils/cmdline/options.hpp" +#include "utils/sanity.hpp" + +namespace cmdline = utils::cmdline; + + +/// Creates a new command. +/// +/// \param name_ The name of the command. Must be unique within the context of +/// a program and have no spaces. +/// \param arg_list_ A textual description of the arguments received by the +/// command. May be empty. +/// \param min_args_ The minimum number of arguments required by the command. +/// \param max_args_ The maximum number of arguments required by the command. +/// -1 means infinity. +/// \param short_description_ A description of the purpose of the command. +cmdline::command_proto::command_proto(const std::string& name_, + const std::string& arg_list_, + const int min_args_, + const int max_args_, + const std::string& short_description_) : + _name(name_), + _arg_list(arg_list_), + _min_args(min_args_), + _max_args(max_args_), + _short_description(short_description_) +{ + PRE(name_.find(' ') == std::string::npos); + PRE(max_args_ == -1 || min_args_ <= max_args_); +} + + +/// Destructor for a command. +cmdline::command_proto::~command_proto(void) +{ + for (options_vector::const_iterator iter = _options.begin(); + iter != _options.end(); iter++) + delete *iter; +} + + +/// Internal method to register a dynamically-allocated option. +/// +/// Always use add_option() from subclasses to add options. +/// +/// \param option_ The option to add. Must have been dynamically allocated. +/// This grabs ownership of the pointer, which is released when the command +/// is destroyed. +void +cmdline::command_proto::add_option_ptr(const cmdline::base_option* option_) +{ + try { + _options.push_back(option_); + } catch (...) { + delete option_; + throw; + } +} + + +/// Processes the command line based on the command description. +/// +/// \param args The raw command line to be processed. +/// +/// \return An object containing the list of options and free arguments found in +/// args. +/// +/// \throw cmdline::usage_error If there is a problem processing the command +/// line. This error is caused by invalid input from the user. +cmdline::parsed_cmdline +cmdline::command_proto::parse_cmdline(const cmdline::args_vector& args) const +{ + PRE(name() == args[0]); + const parsed_cmdline cmdline = cmdline::parse(args, options()); + + const int argc = cmdline.arguments().size(); + if (argc < _min_args) + throw usage_error("Not enough arguments"); + if (_max_args != -1 && argc > _max_args) + throw usage_error("Too many arguments"); + + return cmdline; +} + + +/// Gets the name of the command. +/// +/// \return The command name. +const std::string& +cmdline::command_proto::name(void) const +{ + return _name; +} + + +/// Gets the textual representation of the arguments list. +/// +/// \return The description of the arguments list. +const std::string& +cmdline::command_proto::arg_list(void) const +{ + return _arg_list; +} + + +/// Gets the description of the purpose of the command. +/// +/// \return The description of the command. +const std::string& +cmdline::command_proto::short_description(void) const +{ + return _short_description; +} + + +/// Gets the definition of the options accepted by the command. +/// +/// \return The list of options. +const cmdline::options_vector& +cmdline::command_proto::options(void) const +{ + return _options; +} + + +/// Creates a new command. +/// +/// \param name_ The name of the command. Must be unique within the context of +/// a program and have no spaces. +/// \param arg_list_ A textual description of the arguments received by the +/// command. May be empty. +/// \param min_args_ The minimum number of arguments required by the command. +/// \param max_args_ The maximum number of arguments required by the command. +/// -1 means infinity. +/// \param short_description_ A description of the purpose of the command. +cmdline::base_command_no_data::base_command_no_data( + const std::string& name_, + const std::string& arg_list_, + const int min_args_, + const int max_args_, + const std::string& short_description_) : + command_proto(name_, arg_list_, min_args_, max_args_, short_description_) +{ +} + + +/// Entry point for the command. +/// +/// This delegates execution to the run() abstract function after the command +/// line provided in args has been parsed. +/// +/// If this function returns, the command is assumed to have been executed +/// successfully. Any error must be reported by means of exceptions. +/// +/// \param ui Object to interact with the I/O of the command. The command must +/// always use this object to write to stdout and stderr. +/// \param args The command line passed to the command broken by word, which +/// includes options and arguments. +/// +/// \return The exit code that the program has to return. 0 on success, some +/// other value on error. +/// \throw usage_error If args is invalid (i.e. if the options are mispecified +/// or if the arguments are invalid). +int +cmdline::base_command_no_data::main(cmdline::ui* ui, + const cmdline::args_vector& args) +{ + return run(ui, parse_cmdline(args)); +} diff --git a/external/bsd/kyua-cli/dist/utils/cmdline/base_command.hpp b/external/bsd/kyua-cli/dist/utils/cmdline/base_command.hpp new file mode 100644 index 000000000..073225ca4 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/cmdline/base_command.hpp @@ -0,0 +1,162 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file utils/cmdline/base_command.hpp +/// Provides the utils::cmdline::base_command class. + +#if !defined(UTILS_CMDLINE_BASE_COMMAND_HPP) +#define UTILS_CMDLINE_BASE_COMMAND_HPP + +#include + +#include "utils/cmdline/options.hpp" +#include "utils/cmdline/parser.hpp" +#include "utils/noncopyable.hpp" + +namespace utils { +namespace cmdline { + + +class ui; + + +/// Prototype class for the implementation of subcommands of a program. +/// +/// Use the subclasses of command_proto defined in this module instead of +/// command_proto itself as base classes for your application-specific +/// commands. +class command_proto : noncopyable { + /// The user-visible name of the command. + const std::string _name; + + /// Textual description of the command arguments. + const std::string _arg_list; + + /// The minimum number of required arguments. + const int _min_args; + + /// The maximum number of allowed arguments; -1 for infinity. + const int _max_args; + + /// A textual description of the command. + const std::string _short_description; + + /// Collection of command-specific options. + options_vector _options; + + void add_option_ptr(const base_option*); + +protected: + template< typename Option > void add_option(const Option&); + parsed_cmdline parse_cmdline(const args_vector&) const; + +public: + command_proto(const std::string&, const std::string&, const int, const int, + const std::string&); + virtual ~command_proto(void); + + const std::string& name(void) const; + const std::string& arg_list(void) const; + const std::string& short_description(void) const; + const options_vector& options(void) const; +}; + + +/// Unparametrized base subcommand for a program. +/// +/// Use this class to define subcommands for your program that do not need any +/// information passed in from the main command-line dispatcher other than the +/// command-line arguments. +class base_command_no_data : public command_proto { + /// Main code of the command. + /// + /// This is called from main() after the command line has been processed and + /// validated. + /// + /// \param ui Object to interact with the I/O of the command. The command + /// must always use this object to write to stdout and stderr. + /// \param cmdline The parsed command line, containing the values of any + /// given options and arguments. + /// + /// \return The exit code that the program has to return. 0 on success, + /// some other value on error. + /// + /// \throw std::runtime_error Any errors detected during the execution of + /// the command are reported by means of exceptions. + virtual int run(ui* ui, const parsed_cmdline& cmdline) = 0; + +public: + base_command_no_data(const std::string&, const std::string&, const int, + const int, const std::string&); + + int main(ui*, const args_vector&); +}; + + +/// Parametrized base subcommand for a program. +/// +/// Use this class to define subcommands for your program that need some kind of +/// runtime information passed in from the main command-line dispatcher. +/// +/// \param Data The type of the object passed to the subcommand at runtime. +/// This is useful, for example, to pass around the runtime configuration of the +/// program. +template< typename Data > +class base_command : public command_proto { + /// Main code of the command. + /// + /// This is called from main() after the command line has been processed and + /// validated. + /// + /// \param ui Object to interact with the I/O of the command. The command + /// must always use this object to write to stdout and stderr. + /// \param cmdline The parsed command line, containing the values of any + /// given options and arguments. + /// \param data An instance of the runtime data passed from main(). + /// + /// \return The exit code that the program has to return. 0 on success, + /// some other value on error. + /// + /// \throw std::runtime_error Any errors detected during the execution of + /// the command are reported by means of exceptions. + virtual int run(ui* ui, const parsed_cmdline& cmdline, + const Data& data) = 0; + +public: + base_command(const std::string&, const std::string&, const int, const int, + const std::string&); + + int main(ui*, const args_vector&, const Data&); +}; + + +} // namespace cmdline +} // namespace utils + + +#endif // !defined(UTILS_CMDLINE_BASE_COMMAND_HPP) diff --git a/external/bsd/kyua-cli/dist/utils/cmdline/base_command.ipp b/external/bsd/kyua-cli/dist/utils/cmdline/base_command.ipp new file mode 100644 index 000000000..803855d47 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/cmdline/base_command.ipp @@ -0,0 +1,104 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#if !defined(UTILS_CMDLINE_BASE_COMMAND_IPP) +#define UTILS_CMDLINE_BASE_COMMAND_IPP + +#include "utils/cmdline/base_command.hpp" + + +namespace utils { +namespace cmdline { + + +/// Adds an option to the command. +/// +/// This is to be called from the constructor of the subclass that implements +/// the command. +/// +/// \param option_ The option to add. +template< typename Option > +void +command_proto::add_option(const Option& option_) +{ + add_option_ptr(new Option(option_)); +} + + +/// Creates a new command. +/// +/// \param name_ The name of the command. Must be unique within the context of +/// a program and have no spaces. +/// \param arg_list_ A textual description of the arguments received by the +/// command. May be empty. +/// \param min_args_ The minimum number of arguments required by the command. +/// \param max_args_ The maximum number of arguments required by the command. +/// -1 means infinity. +/// \param short_description_ A description of the purpose of the command. +template< typename Data > +base_command< Data >::base_command(const std::string& name_, + const std::string& arg_list_, + const int min_args_, + const int max_args_, + const std::string& short_description_) : + command_proto(name_, arg_list_, min_args_, max_args_, short_description_) +{ +} + + +/// Entry point for the command. +/// +/// This delegates execution to the run() abstract function after the command +/// line provided in args has been parsed. +/// +/// If this function returns, the command is assumed to have been executed +/// successfully. Any error must be reported by means of exceptions. +/// +/// \param ui Object to interact with the I/O of the command. The command must +/// always use this object to write to stdout and stderr. +/// \param args The command line passed to the command broken by word, which +/// includes options and arguments. +/// \param data An opaque data structure to pass to the run method. +/// +/// \return The exit code that the program has to return. 0 on success, some +/// other value on error. +/// \throw usage_error If args is invalid (i.e. if the options are mispecified +/// or if the arguments are invalid). +template< typename Data > +int +base_command< Data >::main(ui* ui, const args_vector& args, const Data& data) +{ + return run(ui, parse_cmdline(args), data); +} + + +} // namespace cli +} // namespace utils + + +#endif // !defined(UTILS_CMDLINE_BASE_COMMAND_IPP) diff --git a/external/bsd/kyua-cli/dist/utils/cmdline/base_command_test.cpp b/external/bsd/kyua-cli/dist/utils/cmdline/base_command_test.cpp new file mode 100644 index 000000000..0ecf19bb9 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/cmdline/base_command_test.cpp @@ -0,0 +1,297 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/cmdline/base_command.ipp" + +#include + +#include "utils/cmdline/exceptions.hpp" +#include "utils/cmdline/options.hpp" +#include "utils/cmdline/parser.ipp" +#include "utils/cmdline/ui_mock.hpp" +#include "utils/defs.hpp" + +namespace cmdline = utils::cmdline; + + +namespace { + + +/// Mock command to test the cmdline::base_command base class. +/// +/// \param Data The type of the opaque data object passed to main(). +/// \param ExpectedData The value run() will expect to find in the Data object +/// passed to main(). +template< typename Data, Data ExpectedData > +class mock_cmd : public cmdline::base_command< Data > { +public: + /// Indicates if run() has been called already and executed correctly. + bool executed; + + /// Contains the argument of --the_string after run() is executed. + std::string optvalue; + + /// Constructs a new mock command. + mock_cmd(void) : + cmdline::base_command< Data >("mock", "arg1 [arg2 [arg3]]", 1, 3, + "Command for testing."), + executed(false) + { + this->add_option(cmdline::string_option("the_string", "Test option", + "arg")); + } + + /// Executes the command. + /// + /// \param unused_ui Object to interact with the I/O of the program. + /// \param cmdline Representation of the command line to the subcommand. + /// \param data Arbitrary data cookie passed to the command. + /// + /// \return A hardcoded number for testing purposes. + int + run(cmdline::ui* UTILS_UNUSED_PARAM(ui), + const cmdline::parsed_cmdline& cmdline, const Data& data) + { + if (cmdline.has_option("the_string")) + optvalue = cmdline.get_option< cmdline::string_option >( + "the_string"); + ATF_REQUIRE_EQ(ExpectedData, data); + executed = true; + return 1234; + } +}; + + +/// Mock command to test the cmdline::base_command_no_data base class. +class mock_cmd_no_data : public cmdline::base_command_no_data { +public: + /// Indicates if run() has been called already and executed correctly. + bool executed; + + /// Contains the argument of --the_string after run() is executed. + std::string optvalue; + + /// Constructs a new mock command. + mock_cmd_no_data(void) : + cmdline::base_command_no_data("mock", "arg1 [arg2 [arg3]]", 1, 3, + "Command for testing."), + executed(false) + { + add_option(cmdline::string_option("the_string", "Test option", "arg")); + } + + /// Executes the command. + /// + /// \param unused_ui Object to interact with the I/O of the program. + /// \param cmdline Representation of the command line to the subcommand. + /// + /// \return A hardcoded number for testing purposes. + int + run(cmdline::ui* UTILS_UNUSED_PARAM(ui), + const cmdline::parsed_cmdline& cmdline) + { + if (cmdline.has_option("the_string")) + optvalue = cmdline.get_option< cmdline::string_option >( + "the_string"); + executed = true; + return 1234; + } +}; + + +/// Implementation of a command to get access to parse_cmdline(). +class parse_cmdline_portal : public cmdline::command_proto { +public: + /// Constructs a new mock command. + parse_cmdline_portal(void) : + cmdline::command_proto("portal", "arg1 [arg2 [arg3]]", 1, 3, + "Command for testing.") + { + this->add_option(cmdline::string_option("the_string", "Test option", + "arg")); + } + + /// Delegator for the internal parse_cmdline() method. + /// + /// \param args The input arguments to be parsed. + /// + /// \return The parsed command line, split in options and arguments. + cmdline::parsed_cmdline + operator()(const cmdline::args_vector& args) const + { + return parse_cmdline(args); + } +}; + + +} // anonymous namespace + + +ATF_TEST_CASE_WITHOUT_HEAD(command_proto__parse_cmdline__ok); +ATF_TEST_CASE_BODY(command_proto__parse_cmdline__ok) +{ + cmdline::args_vector args; + args.push_back("portal"); + args.push_back("--the_string=foo bar"); + args.push_back("one arg"); + args.push_back("another arg"); + (void)parse_cmdline_portal()(args); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(command_proto__parse_cmdline__parse_fail); +ATF_TEST_CASE_BODY(command_proto__parse_cmdline__parse_fail) +{ + cmdline::args_vector args; + args.push_back("portal"); + args.push_back("--foo-bar"); + ATF_REQUIRE_THROW_RE(cmdline::usage_error, "Unknown.*foo-bar", + (void)parse_cmdline_portal()(args)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(command_proto__parse_cmdline__args_invalid); +ATF_TEST_CASE_BODY(command_proto__parse_cmdline__args_invalid) +{ + cmdline::args_vector args; + args.push_back("portal"); + + ATF_REQUIRE_THROW_RE(cmdline::usage_error, "Not enough arguments", + (void)parse_cmdline_portal()(args)); + + args.push_back("1"); + args.push_back("2"); + args.push_back("3"); + args.push_back("4"); + ATF_REQUIRE_THROW_RE(cmdline::usage_error, "Too many arguments", + (void)parse_cmdline_portal()(args)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(base_command__getters); +ATF_TEST_CASE_BODY(base_command__getters) +{ + mock_cmd< int, 584 > cmd; + ATF_REQUIRE_EQ("mock", cmd.name()); + ATF_REQUIRE_EQ("arg1 [arg2 [arg3]]", cmd.arg_list()); + ATF_REQUIRE_EQ("Command for testing.", cmd.short_description()); + ATF_REQUIRE_EQ(1, cmd.options().size()); + ATF_REQUIRE_EQ("the_string", cmd.options()[0]->long_name()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(base_command__main__ok) +ATF_TEST_CASE_BODY(base_command__main__ok) +{ + mock_cmd< int, 584 > cmd; + + cmdline::ui_mock ui; + cmdline::args_vector args; + args.push_back("mock"); + args.push_back("--the_string=foo bar"); + args.push_back("one arg"); + args.push_back("another arg"); + ATF_REQUIRE_EQ(1234, cmd.main(&ui, args, 584)); + ATF_REQUIRE(cmd.executed); + ATF_REQUIRE_EQ("foo bar", cmd.optvalue); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(base_command__main__parse_cmdline_fail) +ATF_TEST_CASE_BODY(base_command__main__parse_cmdline_fail) +{ + mock_cmd< int, 584 > cmd; + + cmdline::ui_mock ui; + cmdline::args_vector args; + args.push_back("mock"); + args.push_back("--foo-bar"); + ATF_REQUIRE_THROW_RE(cmdline::usage_error, "Unknown.*foo-bar", + cmd.main(&ui, args, 584)); + ATF_REQUIRE(!cmd.executed); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(base_command_no_data__getters); +ATF_TEST_CASE_BODY(base_command_no_data__getters) +{ + mock_cmd_no_data cmd; + ATF_REQUIRE_EQ("mock", cmd.name()); + ATF_REQUIRE_EQ("arg1 [arg2 [arg3]]", cmd.arg_list()); + ATF_REQUIRE_EQ("Command for testing.", cmd.short_description()); + ATF_REQUIRE_EQ(1, cmd.options().size()); + ATF_REQUIRE_EQ("the_string", cmd.options()[0]->long_name()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(base_command_no_data__main__ok) +ATF_TEST_CASE_BODY(base_command_no_data__main__ok) +{ + mock_cmd_no_data cmd; + + cmdline::ui_mock ui; + cmdline::args_vector args; + args.push_back("mock"); + args.push_back("--the_string=foo bar"); + args.push_back("one arg"); + args.push_back("another arg"); + ATF_REQUIRE_EQ(1234, cmd.main(&ui, args)); + ATF_REQUIRE(cmd.executed); + ATF_REQUIRE_EQ("foo bar", cmd.optvalue); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(base_command_no_data__main__parse_cmdline_fail) +ATF_TEST_CASE_BODY(base_command_no_data__main__parse_cmdline_fail) +{ + mock_cmd_no_data cmd; + + cmdline::ui_mock ui; + cmdline::args_vector args; + args.push_back("mock"); + args.push_back("--foo-bar"); + ATF_REQUIRE_THROW_RE(cmdline::usage_error, "Unknown.*foo-bar", + cmd.main(&ui, args)); + ATF_REQUIRE(!cmd.executed); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, command_proto__parse_cmdline__ok); + ATF_ADD_TEST_CASE(tcs, command_proto__parse_cmdline__parse_fail); + ATF_ADD_TEST_CASE(tcs, command_proto__parse_cmdline__args_invalid); + + ATF_ADD_TEST_CASE(tcs, base_command__getters); + ATF_ADD_TEST_CASE(tcs, base_command__main__ok); + ATF_ADD_TEST_CASE(tcs, base_command__main__parse_cmdline_fail); + + ATF_ADD_TEST_CASE(tcs, base_command_no_data__getters); + ATF_ADD_TEST_CASE(tcs, base_command_no_data__main__ok); + ATF_ADD_TEST_CASE(tcs, base_command_no_data__main__parse_cmdline_fail); +} diff --git a/external/bsd/kyua-cli/dist/utils/cmdline/commands_map.hpp b/external/bsd/kyua-cli/dist/utils/cmdline/commands_map.hpp new file mode 100644 index 000000000..4e82db1d6 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/cmdline/commands_map.hpp @@ -0,0 +1,94 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file utils/cmdline/commands_map.hpp +/// Maintains a collection of dynamically-instantiated commands. +/// +/// Commands need to be dynamically-instantiated because they are often +/// complex data structures. Instantiating them as static variables causes +/// problems with the order of construction of globals. The commands_map class +/// provided by this module provides a mechanism to maintain these instantiated +/// objects. + +#if !defined(UTILS_CMDLINE_COMMANDS_MAP_HPP) +#define UTILS_CMDLINE_COMMANDS_MAP_HPP + +#include +#include +#include +#include + +#include "utils/noncopyable.hpp" + + +namespace utils { +namespace cmdline { + + +/// Collection of dynamically-instantiated commands. +template< typename BaseCommand > +class commands_map : noncopyable { + /// Map of command names to their implementations. + typedef std::map< std::string, BaseCommand* > impl_map; + + /// Map of category names to the command names they contain. + typedef std::map< std::string, std::set< std::string > > categories_map; + + /// Collection of all available commands. + impl_map _commands; + + /// Collection of defined categories and their commands. + categories_map _categories; + +public: + commands_map(void); + ~commands_map(void); + + /// Scoped, strictly-owned pointer to a command from this map. + typedef typename std::auto_ptr< BaseCommand > command_ptr; + void insert(command_ptr, const std::string& = ""); + void insert(BaseCommand*, const std::string& = ""); + + /// Type for a constant iterator. + typedef typename categories_map::const_iterator const_iterator; + + bool empty(void) const; + + const_iterator begin(void) const; + const_iterator end(void) const; + + BaseCommand* find(const std::string&); + const BaseCommand* find(const std::string&) const; +}; + + +} // namespace cmdline +} // namespace utils + + +#endif // !defined(UTILS_CMDLINE_BASE_COMMAND_HPP) diff --git a/external/bsd/kyua-cli/dist/utils/cmdline/commands_map.ipp b/external/bsd/kyua-cli/dist/utils/cmdline/commands_map.ipp new file mode 100644 index 000000000..569e8ea83 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/cmdline/commands_map.ipp @@ -0,0 +1,161 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/cmdline/commands_map.hpp" +#include "utils/sanity.hpp" + + +namespace utils { + + +/// Constructs an empty set of commands. +template< typename BaseCommand > +cmdline::commands_map< BaseCommand >::commands_map(void) +{ +} + + +/// Destroys a set of commands. +/// +/// This releases the dynamically-instantiated objects. +template< typename BaseCommand > +cmdline::commands_map< BaseCommand >::~commands_map(void) +{ + for (typename impl_map::iterator iter = _commands.begin(); + iter != _commands.end(); iter++) + delete (*iter).second; +} + + +/// Inserts a new command into the map. +/// +/// \param command The command to insert. This must have been dynamically +/// allocated with new. The call grabs ownership of the command, or the +/// command is freed if the call fails. +/// \param category The category this command belongs to. Defaults to the empty +/// string, which indicates that the command has not be categorized. +template< typename BaseCommand > +void +cmdline::commands_map< BaseCommand >::insert(command_ptr command, + const std::string& category) +{ + INV(_commands.find(command->name()) == _commands.end()); + BaseCommand* ptr = command.release(); + INV(ptr != NULL); + _commands[ptr->name()] = ptr; + _categories[category].insert(ptr->name()); +} + + +/// Inserts a new command into the map. +/// +/// This grabs ownership of the pointer, so it is ONLY safe to use with the +/// following idiom: insert(new foo()). +/// +/// \param command The command to insert. This must have been dynamically +/// allocated with new. The call grabs ownership of the command, or the +/// command is freed if the call fails. +/// \param category The category this command belongs to. Defaults to the empty +/// string, which indicates that the command has not be categorized. +template< typename BaseCommand > +void +cmdline::commands_map< BaseCommand >::insert(BaseCommand* command, + const std::string& category) +{ + insert(command_ptr(command), category); +} + + +/// Checks whether the list of commands is empty. +/// +/// \return True if there are no commands in this map. +template< typename BaseCommand > +bool +cmdline::commands_map< BaseCommand >::empty(void) const +{ + return _commands.empty(); +} + + +/// Returns a constant iterator to the beginning of the categories mapping. +/// +/// \return A map (string -> BaseCommand*) iterator. +template< typename BaseCommand > +typename cmdline::commands_map< BaseCommand >::const_iterator +cmdline::commands_map< BaseCommand >::begin(void) const +{ + return _categories.begin(); +} + + +/// Returns a constant iterator to the end of the categories mapping. +/// +/// \return A map (string -> BaseCommand*) iterator. +template< typename BaseCommand > +typename cmdline::commands_map< BaseCommand >::const_iterator +cmdline::commands_map< BaseCommand >::end(void) const +{ + return _categories.end(); +} + + +/// Finds a command by name; mutable version. +/// +/// \param name The name of the command to locate. +/// +/// \return The command itself or NULL if it does not exist. +template< typename BaseCommand > +BaseCommand* +cmdline::commands_map< BaseCommand >::find(const std::string& name) +{ + typename impl_map::iterator iter = _commands.find(name); + if (iter == _commands.end()) + return NULL; + else + return (*iter).second; +} + + +/// Finds a command by name; constant version. +/// +/// \param name The name of the command to locate. +/// +/// \return The command itself or NULL if it does not exist. +template< typename BaseCommand > +const BaseCommand* +cmdline::commands_map< BaseCommand >::find(const std::string& name) const +{ + typename impl_map::const_iterator iter = _commands.find(name); + if (iter == _commands.end()) + return NULL; + else + return (*iter).second; +} + + +} // namespace utils diff --git a/external/bsd/kyua-cli/dist/utils/cmdline/commands_map_test.cpp b/external/bsd/kyua-cli/dist/utils/cmdline/commands_map_test.cpp new file mode 100644 index 000000000..4f05e0e35 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/cmdline/commands_map_test.cpp @@ -0,0 +1,144 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/cmdline/commands_map.ipp" + +#include + +#include "utils/cmdline/base_command.hpp" +#include "utils/defs.hpp" +#include "utils/sanity.hpp" + +namespace cmdline = utils::cmdline; + + +namespace { + + +/// Fake command to validate the behavior of commands_map. +/// +/// Note that this command does not do anything. It is only intended to provide +/// a specific class that can be inserted into commands_map instances and check +/// that it can be located properly. +class mock_cmd : public cmdline::base_command_no_data { +public: + /// Constructor for the mock command. + /// + /// \param mock_name The name of the command. All other settings are set to + /// irrelevant values. + mock_cmd(const char* mock_name) : + cmdline::base_command_no_data(mock_name, "", 0, 0, + "Command for testing.") + { + } + + /// Runs the mock command. + /// + /// \param unused_ui Object to interact with the I/O of the program. + /// \param unused_cmdline Representation of the command line to the + /// subcommand. + /// + /// \return Nothing because this function is never called. + int + run(cmdline::ui* UTILS_UNUSED_PARAM(ui), + const cmdline::parsed_cmdline& UTILS_UNUSED_PARAM(cmdline)) + { + UNREACHABLE; + } +}; + + +} // anonymous namespace + + +ATF_TEST_CASE_WITHOUT_HEAD(empty); +ATF_TEST_CASE_BODY(empty) +{ + cmdline::commands_map< cmdline::base_command_no_data > commands; + ATF_REQUIRE(commands.empty()); + ATF_REQUIRE(commands.begin() == commands.end()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(some); +ATF_TEST_CASE_BODY(some) +{ + cmdline::commands_map< cmdline::base_command_no_data > commands; + cmdline::base_command_no_data* cmd1 = new mock_cmd("cmd1"); + commands.insert(cmd1); + cmdline::base_command_no_data* cmd2 = new mock_cmd("cmd2"); + commands.insert(cmd2, "foo"); + + ATF_REQUIRE(!commands.empty()); + + cmdline::commands_map< cmdline::base_command_no_data >::const_iterator + iter = commands.begin(); + ATF_REQUIRE_EQ("", (*iter).first); + ATF_REQUIRE_EQ(1, (*iter).second.size()); + ATF_REQUIRE_EQ("cmd1", *(*iter).second.begin()); + + ++iter; + ATF_REQUIRE_EQ("foo", (*iter).first); + ATF_REQUIRE_EQ(1, (*iter).second.size()); + ATF_REQUIRE_EQ("cmd2", *(*iter).second.begin()); + + ATF_REQUIRE(++iter == commands.end()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(find__match); +ATF_TEST_CASE_BODY(find__match) +{ + cmdline::commands_map< cmdline::base_command_no_data > commands; + cmdline::base_command_no_data* cmd1 = new mock_cmd("cmd1"); + commands.insert(cmd1); + cmdline::base_command_no_data* cmd2 = new mock_cmd("cmd2"); + commands.insert(cmd2); + + ATF_REQUIRE(cmd1 == commands.find("cmd1")); + ATF_REQUIRE(cmd2 == commands.find("cmd2")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(find__nomatch); +ATF_TEST_CASE_BODY(find__nomatch) +{ + cmdline::commands_map< cmdline::base_command_no_data > commands; + commands.insert(new mock_cmd("cmd1")); + + ATF_REQUIRE(NULL == commands.find("cmd2")); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, empty); + ATF_ADD_TEST_CASE(tcs, some); + ATF_ADD_TEST_CASE(tcs, find__match); + ATF_ADD_TEST_CASE(tcs, find__nomatch); +} diff --git a/external/bsd/kyua-cli/dist/utils/cmdline/exceptions.cpp b/external/bsd/kyua-cli/dist/utils/cmdline/exceptions.cpp new file mode 100644 index 000000000..d2fbe1906 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/cmdline/exceptions.cpp @@ -0,0 +1,175 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/cmdline/exceptions.hpp" + +#include "utils/format/macros.hpp" +#include "utils/sanity.hpp" + +namespace cmdline = utils::cmdline; + + +#define VALIDATE_OPTION_NAME(option) PRE_MSG( \ + (option.length() == 2 && (option[0] == '-' && option[1] != '-')) || \ + (option.length() > 2 && (option[0] == '-' && option[1] == '-')), \ + F("The option name %s must be fully specified") % option); + + +/// Constructs a new error with a plain-text message. +/// +/// \param message The plain-text error message. +cmdline::error::error(const std::string& message) : + std::runtime_error(message) +{ +} + + +/// Destructor for the error. +cmdline::error::~error(void) throw() +{ +} + + +/// Constructs a new usage_error. +/// +/// \param message The reason behind the usage error. +cmdline::usage_error::usage_error(const std::string& message) : + error(message) +{ +} + + +/// Destructor for the error. +cmdline::usage_error::~usage_error(void) throw() +{ +} + + +/// Constructs a new missing_option_argument_error. +/// +/// \param option_ The option for which no argument was provided. The option +/// name must be fully specified (with - or -- in front). +cmdline::missing_option_argument_error::missing_option_argument_error( + const std::string& option_) : + usage_error(F("Missing required argument for option %s") % option_), + _option(option_) +{ + VALIDATE_OPTION_NAME(option_); +} + + +/// Destructor for the error. +cmdline::missing_option_argument_error::~missing_option_argument_error(void) + throw() +{ +} + + +/// Returns the option name for which no argument was provided. +/// +/// \return The option name. +const std::string& +cmdline::missing_option_argument_error::option(void) const +{ + return _option; +} + + +/// Constructs a new option_argument_value_error. +/// +/// \param option_ The option to which an invalid argument was passed. The +/// option name must be fully specified (with - or -- in front). +/// \param argument_ The invalid argument. +/// \param reason_ The reason describing why the argument is invalid. +cmdline::option_argument_value_error::option_argument_value_error( + const std::string& option_, const std::string& argument_, + const std::string& reason_) : + usage_error(F("Invalid argument '%s' for option %s: %s") % argument_ % + option_ % reason_), + _option(option_), + _argument(argument_), + _reason(reason_) +{ + VALIDATE_OPTION_NAME(option_); +} + + +/// Destructor for the error. +cmdline::option_argument_value_error::~option_argument_value_error(void) + throw() +{ +} + + +/// Returns the option to which the invalid argument was passed. +/// +/// \return The option name. +const std::string& +cmdline::option_argument_value_error::option(void) const +{ + return _option; +} + + +/// Returns the invalid argument value. +/// +/// \return The invalid argument. +const std::string& +cmdline::option_argument_value_error::argument(void) const +{ + return _argument; +} + + +/// Constructs a new unknown_option_error. +/// +/// \param option_ The unknown option. The option name must be fully specified +/// (with - or -- in front). +cmdline::unknown_option_error::unknown_option_error( + const std::string& option_) : + usage_error(F("Unknown option %s") % option_), + _option(option_) +{ + VALIDATE_OPTION_NAME(option_); +} + + +/// Destructor for the error. +cmdline::unknown_option_error::~unknown_option_error(void) throw() +{ +} + + +/// Returns the unknown option name. +/// +/// \return The unknown option. +const std::string& +cmdline::unknown_option_error::option(void) const +{ + return _option; +} diff --git a/external/bsd/kyua-cli/dist/utils/cmdline/exceptions.hpp b/external/bsd/kyua-cli/dist/utils/cmdline/exceptions.hpp new file mode 100644 index 000000000..0c5ed7a22 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/cmdline/exceptions.hpp @@ -0,0 +1,108 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file utils/cmdline/exceptions.hpp +/// Exception types raised by the cmdline module. + +#if !defined(UTILS_CMDLINE_EXCEPTIONS_HPP) +#define UTILS_CMDLINE_EXCEPTIONS_HPP + +#include + +namespace utils { +namespace cmdline { + + +/// Base exception for cmdline errors. +class error : public std::runtime_error { +public: + explicit error(const std::string&); + ~error(void) throw(); +}; + + +/// Generic error to describe problems caused by the user. +class usage_error : public error { +public: + explicit usage_error(const std::string&); + ~usage_error(void) throw(); +}; + + +/// Error denoting that no argument was provided to an option that required one. +class missing_option_argument_error : public usage_error { + /// Name of the option for which no required argument was specified. + std::string _option; + +public: + explicit missing_option_argument_error(const std::string&); + ~missing_option_argument_error(void) throw(); + + const std::string& option(void) const; +}; + + +/// Error denoting that the argument provided to an option is invalid. +class option_argument_value_error : public usage_error { + /// Name of the option for which the argument was invalid. + std::string _option; + + /// Raw value of the invalid user-provided argument. + std::string _argument; + + /// Reason describing why the argument is invalid. + std::string _reason; + +public: + explicit option_argument_value_error(const std::string&, const std::string&, + const std::string&); + ~option_argument_value_error(void) throw(); + + const std::string& option(void) const; + const std::string& argument(void) const; +}; + + +/// Error denoting that the user specified an unknown option. +class unknown_option_error : public usage_error { + /// Name of the option that was not known. + std::string _option; + +public: + explicit unknown_option_error(const std::string&); + ~unknown_option_error(void) throw(); + + const std::string& option(void) const; +}; + + +} // namespace cmdline +} // namespace utils + + +#endif // !defined(UTILS_CMDLINE_EXCEPTIONS_HPP) diff --git a/external/bsd/kyua-cli/dist/utils/cmdline/exceptions_test.cpp b/external/bsd/kyua-cli/dist/utils/cmdline/exceptions_test.cpp new file mode 100644 index 000000000..9fdf12454 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/cmdline/exceptions_test.cpp @@ -0,0 +1,83 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/cmdline/exceptions.hpp" + +#include + +#include + +namespace cmdline = utils::cmdline; + + +ATF_TEST_CASE_WITHOUT_HEAD(error); +ATF_TEST_CASE_BODY(error) +{ + const cmdline::error e("Some text"); + ATF_REQUIRE(std::strcmp("Some text", e.what()) == 0); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(missing_option_argument_error); +ATF_TEST_CASE_BODY(missing_option_argument_error) +{ + const cmdline::missing_option_argument_error e("-o"); + ATF_REQUIRE(std::strcmp("Missing required argument for option -o", + e.what()) == 0); + ATF_REQUIRE_EQ("-o", e.option()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(option_argument_value_error); +ATF_TEST_CASE_BODY(option_argument_value_error) +{ + const cmdline::option_argument_value_error e("--the_option", "the value", + "the reason"); + ATF_REQUIRE(std::strcmp("Invalid argument 'the value' for option " + "--the_option: the reason", e.what()) == 0); + ATF_REQUIRE_EQ("--the_option", e.option()); + ATF_REQUIRE_EQ("the value", e.argument()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(unknown_option_error); +ATF_TEST_CASE_BODY(unknown_option_error) +{ + const cmdline::unknown_option_error e("--foo"); + ATF_REQUIRE(std::strcmp("Unknown option --foo", e.what()) == 0); + ATF_REQUIRE_EQ("--foo", e.option()); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, error); + ATF_ADD_TEST_CASE(tcs, missing_option_argument_error); + ATF_ADD_TEST_CASE(tcs, option_argument_value_error); + ATF_ADD_TEST_CASE(tcs, unknown_option_error); +} diff --git a/external/bsd/kyua-cli/dist/utils/cmdline/globals.cpp b/external/bsd/kyua-cli/dist/utils/cmdline/globals.cpp new file mode 100644 index 000000000..1bbd08d08 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/cmdline/globals.cpp @@ -0,0 +1,78 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/cmdline/globals.hpp" + +#include "utils/format/macros.hpp" +#include "utils/logging/macros.hpp" +#include "utils/fs/path.hpp" +#include "utils/sanity.hpp" + +namespace cmdline = utils::cmdline; + +namespace { + + +/// The name of the binary used to execute the program. +static std::string Progname; + + +} // anonymous namespace + + +/// Initializes the global state of the CLI. +/// +/// This function can only be called once during the execution of a program, +/// unless override_for_testing is set to true. +/// +/// \param argv0 The value of argv[0]; i.e. the program name. +/// \param override_for_testing Should always be set to false unless for tests +/// of this functionality, which may set this to true to redefine internal +/// state. +void +cmdline::init(const char* argv0, const bool override_for_testing) +{ + if (!override_for_testing) + PRE_MSG(Progname.empty(), "cmdline::init called more than once"); + Progname = utils::fs::path(argv0).leaf_name(); + LD(F("Program name: %s") % Progname); + POST(!Progname.empty()); +} + + +/// Gets the program name. +/// +/// \pre init() must have been called in advance. +/// +/// \return The program name. +const std::string& +cmdline::progname(void) +{ + PRE_MSG(!Progname.empty(), "cmdline::init not called yet"); + return Progname; +} diff --git a/external/bsd/kyua-cli/dist/utils/cmdline/globals.hpp b/external/bsd/kyua-cli/dist/utils/cmdline/globals.hpp new file mode 100644 index 000000000..47b6d14f5 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/cmdline/globals.hpp @@ -0,0 +1,48 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file utils/cmdline/globals.hpp +/// Representation of global, immutable state for a CLI. + +#if !defined(UTILS_CMDLINE_GLOBALS_HPP) +#define UTILS_CMDLINE_GLOBALS_HPP + +#include + +namespace utils { +namespace cmdline { + + +void init(const char*, const bool = false); +const std::string& progname(void); + + +} // namespace cmdline +} // namespace utils + +#endif // !defined(UTILS_CMDLINE_GLOBALS_HPP) diff --git a/external/bsd/kyua-cli/dist/utils/cmdline/globals_test.cpp b/external/bsd/kyua-cli/dist/utils/cmdline/globals_test.cpp new file mode 100644 index 000000000..6bb32fc54 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/cmdline/globals_test.cpp @@ -0,0 +1,77 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/cmdline/globals.hpp" + +#include + +namespace cmdline = utils::cmdline; + + +ATF_TEST_CASE_WITHOUT_HEAD(progname__absolute); +ATF_TEST_CASE_BODY(progname__absolute) +{ + cmdline::init("/path/to/foobar"); + ATF_REQUIRE_EQ("foobar", cmdline::progname()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(progname__relative); +ATF_TEST_CASE_BODY(progname__relative) +{ + cmdline::init("to/barbaz"); + ATF_REQUIRE_EQ("barbaz", cmdline::progname()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(progname__plain); +ATF_TEST_CASE_BODY(progname__plain) +{ + cmdline::init("program"); + ATF_REQUIRE_EQ("program", cmdline::progname()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(progname__override_for_testing); +ATF_TEST_CASE_BODY(progname__override_for_testing) +{ + cmdline::init("program"); + ATF_REQUIRE_EQ("program", cmdline::progname()); + + cmdline::init("foo", true); + ATF_REQUIRE_EQ("foo", cmdline::progname()); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, progname__absolute); + ATF_ADD_TEST_CASE(tcs, progname__relative); + ATF_ADD_TEST_CASE(tcs, progname__plain); + ATF_ADD_TEST_CASE(tcs, progname__override_for_testing); +} diff --git a/external/bsd/kyua-cli/dist/utils/cmdline/options.cpp b/external/bsd/kyua-cli/dist/utils/cmdline/options.cpp new file mode 100644 index 000000000..a086f8477 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/cmdline/options.cpp @@ -0,0 +1,612 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/cmdline/options.hpp" + +#include +#include + +#include "utils/cmdline/exceptions.hpp" +#include "utils/defs.hpp" +#include "utils/format/macros.hpp" +#include "utils/fs/exceptions.hpp" +#include "utils/sanity.hpp" +#include "utils/text/operations.ipp" + +namespace cmdline = utils::cmdline; +namespace text = utils::text; + + +/// Constructs a generic option with both a short and a long name. +/// +/// \param short_name_ The short name for the option. +/// \param long_name_ The long name for the option. +/// \param description_ A user-friendly description for the option. +/// \param arg_name_ If not NULL, specifies that the option must receive an +/// argument and specifies the name of such argument for documentation +/// purposes. +/// \param default_value_ If not NULL, specifies that the option has a default +/// value for the mandatory argument. +cmdline::base_option::base_option(const char short_name_, + const char* long_name_, + const char* description_, + const char* arg_name_, + const char* default_value_) : + _short_name(short_name_), + _long_name(long_name_), + _description(description_), + _arg_name(arg_name_ == NULL ? "" : arg_name_), + _has_default_value(default_value_ != NULL), + _default_value(default_value_ == NULL ? "" : default_value_) +{ + INV(short_name_ != '\0'); +} + + +/// Constructs a generic option with a long name only. +/// +/// \param long_name_ The long name for the option. +/// \param description_ A user-friendly description for the option. +/// \param arg_name_ If not NULL, specifies that the option must receive an +/// argument and specifies the name of such argument for documentation +/// purposes. +/// \param default_value_ If not NULL, specifies that the option has a default +/// value for the mandatory argument. +cmdline::base_option::base_option(const char* long_name_, + const char* description_, + const char* arg_name_, + const char* default_value_) : + _short_name('\0'), + _long_name(long_name_), + _description(description_), + _arg_name(arg_name_ == NULL ? "" : arg_name_), + _has_default_value(default_value_ != NULL), + _default_value(default_value_ == NULL ? "" : default_value_) +{ +} + + +/// Destructor for the option. +cmdline::base_option::~base_option(void) +{ +} + + +/// Checks whether the option has a short name or not. +/// +/// \return True if the option has a short name, false otherwise. +bool +cmdline::base_option::has_short_name(void) const +{ + return _short_name != '\0'; +} + + +/// Returns the short name of the option. +/// +/// \pre has_short_name() must be true. +/// +/// \return The short name. +char +cmdline::base_option::short_name(void) const +{ + PRE(has_short_name()); + return _short_name; +} + + +/// Returns the long name of the option. +/// +/// \return The long name. +const std::string& +cmdline::base_option::long_name(void) const +{ + return _long_name; +} + + +/// Returns the description of the option. +/// +/// \return The description. +const std::string& +cmdline::base_option::description(void) const +{ + return _description; +} + + +/// Checks whether the option needs an argument or not. +/// +/// \return True if the option needs an argument, false otherwise. +bool +cmdline::base_option::needs_arg(void) const +{ + return !_arg_name.empty(); +} + + +/// Returns the argument name of the option for documentation purposes. +/// +/// \pre needs_arg() must be true. +/// +/// \return The argument name. +const std::string& +cmdline::base_option::arg_name(void) const +{ + INV(needs_arg()); + return _arg_name; +} + + +/// Checks whether the option has a default value for its argument. +/// +/// \pre needs_arg() must be true. +/// +/// \return True if the option has a default value, false otherwise. +bool +cmdline::base_option::has_default_value(void) const +{ + PRE(needs_arg()); + return _has_default_value; +} + + +/// Returns the default value for the argument to the option. +/// +/// \pre has_default_value() must be true. +/// +/// \return The default value. +const std::string& +cmdline::base_option::default_value(void) const +{ + INV(has_default_value()); + return _default_value;; +} + + +/// Formats the short name of the option for documentation purposes. +/// +/// \return A string describing the option's short name. +std::string +cmdline::base_option::format_short_name(void) const +{ + PRE(has_short_name()); + + if (needs_arg()) { + return F("-%s %s") % short_name() % arg_name(); + } else { + return F("-%s") % short_name(); + } +} + + +/// Formats the long name of the option for documentation purposes. +/// +/// \return A string describing the option's long name. +std::string +cmdline::base_option::format_long_name(void) const +{ + if (needs_arg()) { + return F("--%s=%s") % long_name() % arg_name(); + } else { + return F("--%s") % long_name(); + } +} + + + +/// Ensures that an argument passed to the option is valid. +/// +/// This must be reimplemented by subclasses that describe options with +/// arguments. +/// +/// \param unused_str The argument to validate as provided by the user in the +/// command line. +/// +/// \throw cmdline::option_argument_value_error Subclasses must raise this +/// exception to indicate the cases in which str is invalid. +void +cmdline::base_option::validate(const std::string& UTILS_UNUSED_PARAM(str)) const +{ + UNREACHABLE_MSG("Option does not support an argument"); +} + + +/// Constructs a boolean option with both a short and a long name. +/// +/// \param short_name_ The short name for the option. +/// \param long_name_ The long name for the option. +/// \param description_ A user-friendly description for the option. +cmdline::bool_option::bool_option(const char short_name_, + const char* long_name_, + const char* description_) : + base_option(short_name_, long_name_, description_) +{ +} + + +/// Constructs a boolean option with a long name only. +/// +/// \param long_name_ The long name for the option. +/// \param description_ A user-friendly description for the option. +cmdline::bool_option::bool_option(const char* long_name_, + const char* description_) : + base_option(long_name_, description_) +{ +} + + +/// Constructs an integer option with both a short and a long name. +/// +/// \param short_name_ The short name for the option. +/// \param long_name_ The long name for the option. +/// \param description_ A user-friendly description for the option. +/// \param arg_name_ The name of the mandatory argument, for documentation +/// purposes. +/// \param default_value_ If not NULL, the default value for the mandatory +/// argument. +cmdline::int_option::int_option(const char short_name_, + const char* long_name_, + const char* description_, + const char* arg_name_, + const char* default_value_) : + base_option(short_name_, long_name_, description_, arg_name_, + default_value_) +{ +} + + +/// Constructs an integer option with a long name only. +/// +/// \param long_name_ The long name for the option. +/// \param description_ A user-friendly description for the option. +/// \param arg_name_ The name of the mandatory argument, for documentation +/// purposes. +/// \param default_value_ If not NULL, the default value for the mandatory +/// argument. +cmdline::int_option::int_option(const char* long_name_, + const char* description_, + const char* arg_name_, + const char* default_value_) : + base_option(long_name_, description_, arg_name_, default_value_) +{ +} + + +/// Ensures that an integer argument passed to the int_option is valid. +/// +/// \param raw_value The argument representing an integer as provided by the +/// user. +/// +/// \throw cmdline::option_argument_value_error If the integer provided in +/// raw_value is invalid. +void +cmdline::int_option::validate(const std::string& raw_value) const +{ + try { + (void)text::to_type< int >(raw_value); + } catch (const std::runtime_error& e) { + throw cmdline::option_argument_value_error( + F("--%s") % long_name(), raw_value, "Not a valid integer"); + } +} + + +/// Converts an integer argument to a native integer. +/// +/// \param raw_value The argument representing an integer as provided by the +/// user. +/// +/// \return The integer. +/// +/// \pre validate(raw_value) must be true. +int +cmdline::int_option::convert(const std::string& raw_value) +{ + try { + return text::to_type< int >(raw_value); + } catch (const std::runtime_error& e) { + PRE_MSG(false, F("Raw value '%s' for int option not properly " + "validated: %s") % raw_value % e.what()); + } +} + + +/// Constructs a list option with both a short and a long name. +/// +/// \param short_name_ The short name for the option. +/// \param long_name_ The long name for the option. +/// \param description_ A user-friendly description for the option. +/// \param arg_name_ The name of the mandatory argument, for documentation +/// purposes. +/// \param default_value_ If not NULL, the default value for the mandatory +/// argument. +cmdline::list_option::list_option(const char short_name_, + const char* long_name_, + const char* description_, + const char* arg_name_, + const char* default_value_) : + base_option(short_name_, long_name_, description_, arg_name_, + default_value_) +{ +} + + +/// Constructs a list option with a long name only. +/// +/// \param long_name_ The long name for the option. +/// \param description_ A user-friendly description for the option. +/// \param arg_name_ The name of the mandatory argument, for documentation +/// purposes. +/// \param default_value_ If not NULL, the default value for the mandatory +/// argument. +cmdline::list_option::list_option(const char* long_name_, + const char* description_, + const char* arg_name_, + const char* default_value_) : + base_option(long_name_, description_, arg_name_, default_value_) +{ +} + + +/// Ensures that a lisstring argument passed to the list_option is valid. +/// +/// \param unused_raw_value The argument representing a list as provided by the +/// user. +void +cmdline::list_option::validate( + const std::string& UTILS_UNUSED_PARAM(raw_value)) const +{ + // Any list is potentially valid; the caller must check for semantics. +} + + +/// Converts a string argument to a vector. +/// +/// \param raw_value The argument representing a list as provided by the user. +/// +/// \return The list. +/// +/// \pre validate(raw_value) must be true. +cmdline::list_option::option_type +cmdline::list_option::convert(const std::string& raw_value) +{ + try { + return text::split(raw_value, ','); + } catch (const std::runtime_error& e) { + PRE_MSG(false, F("Raw value '%s' for list option not properly " + "validated: %s") % raw_value % e.what()); + } +} + + +/// Constructs a path option with both a short and a long name. +/// +/// \param short_name_ The short name for the option. +/// \param long_name_ The long name for the option. +/// \param description_ A user-friendly description for the option. +/// \param arg_name_ The name of the mandatory argument, for documentation +/// purposes. +/// \param default_value_ If not NULL, the default value for the mandatory +/// argument. +cmdline::path_option::path_option(const char short_name_, + const char* long_name_, + const char* description_, + const char* arg_name_, + const char* default_value_) : + base_option(short_name_, long_name_, description_, arg_name_, + default_value_) +{ +} + + +/// Constructs a path option with a long name only. +/// +/// \param long_name_ The long name for the option. +/// \param description_ A user-friendly description for the option. +/// \param arg_name_ The name of the mandatory argument, for documentation +/// purposes. +/// \param default_value_ If not NULL, the default value for the mandatory +/// argument. +cmdline::path_option::path_option(const char* long_name_, + const char* description_, + const char* arg_name_, + const char* default_value_) : + base_option(long_name_, description_, arg_name_, default_value_) +{ +} + + +/// Ensures that a path argument passed to the path_option is valid. +/// +/// \param raw_value The argument representing a path as provided by the user. +/// +/// \throw cmdline::option_argument_value_error If the path provided in +/// raw_value is invalid. +void +cmdline::path_option::validate(const std::string& raw_value) const +{ + try { + (void)utils::fs::path(raw_value); + } catch (const utils::fs::error& e) { + throw cmdline::option_argument_value_error(F("--%s") % long_name(), + raw_value, e.what()); + } +} + + +/// Converts a path argument to a utils::fs::path. +/// +/// \param raw_value The argument representing a path as provided by the user. +/// +/// \return The path. +/// +/// \pre validate(raw_value) must be true. +utils::fs::path +cmdline::path_option::convert(const std::string& raw_value) +{ + try { + return utils::fs::path(raw_value); + } catch (const std::runtime_error& e) { + PRE_MSG(false, F("Raw value '%s' for path option not properly " + "validated: %s") % raw_value % e.what()); + } +} + + +/// Constructs a property option with both a short and a long name. +/// +/// \param short_name_ The short name for the option. +/// \param long_name_ The long name for the option. +/// \param description_ A user-friendly description for the option. +/// \param arg_name_ The name of the mandatory argument, for documentation +/// purposes. Must include the '=' delimiter. +cmdline::property_option::property_option(const char short_name_, + const char* long_name_, + const char* description_, + const char* arg_name_) : + base_option(short_name_, long_name_, description_, arg_name_) +{ + PRE(arg_name().find('=') != std::string::npos); +} + + +/// Constructs a property option with a long name only. +/// +/// \param long_name_ The long name for the option. +/// \param description_ A user-friendly description for the option. +/// \param arg_name_ The name of the mandatory argument, for documentation +/// purposes. Must include the '=' delimiter. +cmdline::property_option::property_option(const char* long_name_, + const char* description_, + const char* arg_name_) : + base_option(long_name_, description_, arg_name_) +{ + PRE(arg_name().find('=') != std::string::npos); +} + + +/// Validates the argument to a property option. +/// +/// \param raw_value The argument provided by the user. +void +cmdline::property_option::validate(const std::string& raw_value) const +{ + const std::string::size_type pos = raw_value.find('='); + if (pos == std::string::npos) + throw cmdline::option_argument_value_error( + F("--%s") % long_name(), raw_value, + F("Argument does not have the form '%s'") % arg_name()); + + const std::string key = raw_value.substr(0, pos); + if (key.empty()) + throw cmdline::option_argument_value_error( + F("--%s") % long_name(), raw_value, "Empty property name"); + + const std::string value = raw_value.substr(pos + 1); + if (value.empty()) + throw cmdline::option_argument_value_error( + F("--%s") % long_name(), raw_value, "Empty value"); +} + + +/// Returns the property option in a key/value pair form. +/// +/// \param raw_value The argument provided by the user. +/// +/// \return raw_value The key/value pair representation of the property. +/// +/// \pre validate(raw_value) must be true. +cmdline::property_option::option_type +cmdline::property_option::convert(const std::string& raw_value) +{ + const std::string::size_type pos = raw_value.find('='); + return std::make_pair(raw_value.substr(0, pos), raw_value.substr(pos + 1)); +} + + +/// Constructs a string option with both a short and a long name. +/// +/// \param short_name_ The short name for the option. +/// \param long_name_ The long name for the option. +/// \param description_ A user-friendly description for the option. +/// \param arg_name_ The name of the mandatory argument, for documentation +/// purposes. +/// \param default_value_ If not NULL, the default value for the mandatory +/// argument. +cmdline::string_option::string_option(const char short_name_, + const char* long_name_, + const char* description_, + const char* arg_name_, + const char* default_value_) : + base_option(short_name_, long_name_, description_, arg_name_, + default_value_) +{ +} + + +/// Constructs a string option with a long name only. +/// +/// \param long_name_ The long name for the option. +/// \param description_ A user-friendly description for the option. +/// \param arg_name_ The name of the mandatory argument, for documentation +/// purposes. +/// \param default_value_ If not NULL, the default value for the mandatory +/// argument. +cmdline::string_option::string_option(const char* long_name_, + const char* description_, + const char* arg_name_, + const char* default_value_) : + base_option(long_name_, description_, arg_name_, default_value_) +{ +} + + +/// Does nothing; all string values are valid arguments to a string_option. +/// +/// \param unused_raw_value The argument provided by the user. +void +cmdline::string_option::validate( + const std::string& UTILS_UNUSED_PARAM(raw_value)) const +{ + // Nothing to do. +} + + +/// Returns the string unmodified. +/// +/// \param raw_value The argument provided by the user. +/// +/// \return raw_value +/// +/// \pre validate(raw_value) must be true. +std::string +cmdline::string_option::convert(const std::string& raw_value) +{ + return raw_value; +} diff --git a/external/bsd/kyua-cli/dist/utils/cmdline/options.hpp b/external/bsd/kyua-cli/dist/utils/cmdline/options.hpp new file mode 100644 index 000000000..7a609da5a --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/cmdline/options.hpp @@ -0,0 +1,235 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file utils/cmdline/options.hpp +/// Definitions of command-line options. + +#if !defined(UTILS_CMDLINE_OPTIONS_HPP) +#define UTILS_CMDLINE_OPTIONS_HPP + +#include +#include +#include + +#include "utils/fs/path.hpp" + +namespace utils { +namespace cmdline { + + +/// Type-less base option class. +/// +/// This abstract class provides the most generic representation of options. It +/// allows defining options with both short and long names, with and without +/// arguments and with and without optional values. These are all the possible +/// combinations supported by the getopt_long(3) function, on which this is +/// built. +/// +/// The internal values (e.g. the default value) of a generic option are all +/// represented as strings. However, from the caller's perspective, this is +/// suboptimal. Hence why this class must be specialized: the subclasses +/// provide type-specific accessors and provide automatic validation of the +/// types (e.g. a string '3foo' is not passed to an integer option). +/// +/// Given that subclasses are used through templatized code, they must provide: +/// +///
      +///
    • A public option_type typedef that defines the type of the +/// option.
    • +/// +///
    • A convert() method that takes a string and converts it to +/// option_type. The string can be assumed to be convertible to the +/// destination type. Should not raise exceptions.
    • +/// +///
    • A validate() method that matches the implementation of convert(). +/// This method can throw option_argument_value_error if the string cannot +/// be converted appropriately. If validate() does not throw, then +/// convert() must execute successfully.
    • +///
    +/// +/// TODO(jmmv): Many methods in this class are split into two parts: has_foo() +/// and foo(), the former to query if the foo is available and the latter to get +/// the foo. It'd be very nice if we'd use something similar Boost.Optional to +/// simplify this interface altogether. +class base_option { + /// Short name of the option; 0 to indicate that none is available. + char _short_name; + + /// Long name of the option. + std::string _long_name; + + /// Textual description of the purpose of the option. + std::string _description; + + /// Descriptive name of the required argument; empty if not allowed. + std::string _arg_name; + + /// Whether the option has a default value or not. + /// + /// \todo We should probably be using the optional class here. + bool _has_default_value; + + /// If _has_default_value is true, the default value. + std::string _default_value; + +public: + base_option(const char, const char*, const char*, const char* = NULL, + const char* = NULL); + base_option(const char*, const char*, const char* = NULL, + const char* = NULL); + virtual ~base_option(void); + + bool has_short_name(void) const; + char short_name(void) const; + const std::string& long_name(void) const; + const std::string& description(void) const; + + bool needs_arg(void) const; + const std::string& arg_name(void) const; + + bool has_default_value(void) const; + const std::string& default_value(void) const; + + std::string format_short_name(void) const; + std::string format_long_name(void) const; + + virtual void validate(const std::string&) const; +}; + + +/// Definition of a boolean option. +/// +/// A boolean option can be specified once in the command line, at which point +/// is set to true. Such an option cannot carry optional arguments. +class bool_option : public base_option { +public: + bool_option(const char, const char*, const char*); + bool_option(const char*, const char*); + virtual ~bool_option(void) {} + + /// The data type of this option. + typedef bool option_type; +}; + + +/// Definition of an integer option. +class int_option : public base_option { +public: + int_option(const char, const char*, const char*, const char*, + const char* = NULL); + int_option(const char*, const char*, const char*, const char* = NULL); + virtual ~int_option(void) {} + + /// The data type of this option. + typedef int option_type; + + virtual void validate(const std::string& str) const; + static int convert(const std::string& str); +}; + + +/// Definition of a comma-separated list of strings. +class list_option : public base_option { +public: + list_option(const char, const char*, const char*, const char*, + const char* = NULL); + list_option(const char*, const char*, const char*, const char* = NULL); + virtual ~list_option(void) {} + + /// The data type of this option. + typedef std::vector< std::string > option_type; + + virtual void validate(const std::string&) const; + static option_type convert(const std::string&); +}; + + +/// Definition of an option representing a path. +/// +/// The path pointed to by the option may not exist, but it must be +/// syntactically valid. +class path_option : public base_option { +public: + path_option(const char, const char*, const char*, const char*, + const char* = NULL); + path_option(const char*, const char*, const char*, const char* = NULL); + virtual ~path_option(void) {} + + /// The data type of this option. + typedef utils::fs::path option_type; + + virtual void validate(const std::string&) const; + static utils::fs::path convert(const std::string&); +}; + + +/// Definition of a property option. +/// +/// A property option is an option whose required arguments are of the form +/// 'name=value'. Both components of the property are treated as free-form +/// non-empty strings; any other validation must happen on the caller side. +/// +/// \todo Would be nice if the delimiter was parametrizable. With the current +/// parser interface (convert() being a static method), the only way to do +/// this would be to templatize this class. +class property_option : public base_option { +public: + property_option(const char, const char*, const char*, const char*); + property_option(const char*, const char*, const char*); + virtual ~property_option(void) {} + + /// The data type of this option. + typedef std::pair< std::string, std::string > option_type; + + virtual void validate(const std::string& str) const; + static option_type convert(const std::string& str); +}; + + +/// Definition of a free-form string option. +/// +/// This class provides no restrictions on the argument passed to the option. +class string_option : public base_option { +public: + string_option(const char, const char*, const char*, const char*, + const char* = NULL); + string_option(const char*, const char*, const char*, const char* = NULL); + virtual ~string_option(void) {} + + /// The data type of this option. + typedef std::string option_type; + + virtual void validate(const std::string& str) const; + static std::string convert(const std::string& str); +}; + + +} // namespace cmdline +} // namespace utils + +#endif // !defined(UTILS_CMDLINE_OPTIONS_HPP) diff --git a/external/bsd/kyua-cli/dist/utils/cmdline/options_test.cpp b/external/bsd/kyua-cli/dist/utils/cmdline/options_test.cpp new file mode 100644 index 000000000..885cc6f59 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/cmdline/options_test.cpp @@ -0,0 +1,527 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/cmdline/options.hpp" + +#include + +#include "utils/cmdline/exceptions.hpp" +#include "utils/defs.hpp" + +namespace cmdline = utils::cmdline; + +namespace { + + +/// Simple string-based option type for testing purposes. +class mock_option : public cmdline::base_option { +public: + /// Constructs a mock option with a short name and a long name. + /// + /// + /// \param short_name_ The short name for the option. + /// \param long_name_ The long name for the option. + /// \param description_ A user-friendly description for the option. + /// \param arg_name_ If not NULL, specifies that the option must receive an + /// argument and specifies the name of such argument for documentation + /// purposes. + /// \param default_value_ If not NULL, specifies that the option has a + /// default value for the mandatory argument. + mock_option(const char short_name_, const char* long_name_, + const char* description_, const char* arg_name_ = NULL, + const char* default_value_ = NULL) : + base_option(short_name_, long_name_, description_, arg_name_, + default_value_) {} + + /// Constructs a mock option with a long name only. + /// + /// \param long_name_ The long name for the option. + /// \param description_ A user-friendly description for the option. + /// \param arg_name_ If not NULL, specifies that the option must receive an + /// argument and specifies the name of such argument for documentation + /// purposes. + /// \param default_value_ If not NULL, specifies that the option has a + /// default value for the mandatory argument. + mock_option(const char* long_name_, + const char* description_, const char* arg_name_ = NULL, + const char* default_value_ = NULL) : + base_option(long_name_, description_, arg_name_, default_value_) {} + + /// The data type of this option. + typedef std::string option_type; + + /// Ensures that the argument passed to the option is valid. + /// + /// In this particular mock option, this does not perform any validation. + /// + /// \param unused_str The user-provided argument to the option. + void + validate(const std::string& UTILS_UNUSED_PARAM(str)) const + { + // Do nothing. + } + + /// Returns the input parameter without any conversion. + /// + /// \param str The user-provided argument to the option. + /// + /// \return The same value as provided by the user without conversion. + static std::string + convert(const std::string& str) + { + return str; + } +}; + + +} // anonymous namespace + + +ATF_TEST_CASE_WITHOUT_HEAD(base_option__short_name__no_arg); +ATF_TEST_CASE_BODY(base_option__short_name__no_arg) +{ + const mock_option o('f', "force", "Force execution"); + ATF_REQUIRE(o.has_short_name()); + ATF_REQUIRE_EQ('f', o.short_name()); + ATF_REQUIRE_EQ("force", o.long_name()); + ATF_REQUIRE_EQ("Force execution", o.description()); + ATF_REQUIRE(!o.needs_arg()); + ATF_REQUIRE_EQ("-f", o.format_short_name()); + ATF_REQUIRE_EQ("--force", o.format_long_name()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(base_option__short_name__with_arg__no_default); +ATF_TEST_CASE_BODY(base_option__short_name__with_arg__no_default) +{ + const mock_option o('c', "conf_file", "Configuration file", "path"); + ATF_REQUIRE(o.has_short_name()); + ATF_REQUIRE_EQ('c', o.short_name()); + ATF_REQUIRE_EQ("conf_file", o.long_name()); + ATF_REQUIRE_EQ("Configuration file", o.description()); + ATF_REQUIRE(o.needs_arg()); + ATF_REQUIRE_EQ("path", o.arg_name()); + ATF_REQUIRE(!o.has_default_value()); + ATF_REQUIRE_EQ("-c path", o.format_short_name()); + ATF_REQUIRE_EQ("--conf_file=path", o.format_long_name()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(base_option__short_name__with_arg__with_default); +ATF_TEST_CASE_BODY(base_option__short_name__with_arg__with_default) +{ + const mock_option o('c', "conf_file", "Configuration file", "path", + "defpath"); + ATF_REQUIRE(o.has_short_name()); + ATF_REQUIRE_EQ('c', o.short_name()); + ATF_REQUIRE_EQ("conf_file", o.long_name()); + ATF_REQUIRE_EQ("Configuration file", o.description()); + ATF_REQUIRE(o.needs_arg()); + ATF_REQUIRE_EQ("path", o.arg_name()); + ATF_REQUIRE(o.has_default_value()); + ATF_REQUIRE_EQ("defpath", o.default_value()); + ATF_REQUIRE_EQ("-c path", o.format_short_name()); + ATF_REQUIRE_EQ("--conf_file=path", o.format_long_name()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(base_option__long_name__no_arg); +ATF_TEST_CASE_BODY(base_option__long_name__no_arg) +{ + const mock_option o("dryrun", "Dry run mode"); + ATF_REQUIRE(!o.has_short_name()); + ATF_REQUIRE_EQ("dryrun", o.long_name()); + ATF_REQUIRE_EQ("Dry run mode", o.description()); + ATF_REQUIRE(!o.needs_arg()); + ATF_REQUIRE_EQ("--dryrun", o.format_long_name()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(base_option__long_name__with_arg__no_default); +ATF_TEST_CASE_BODY(base_option__long_name__with_arg__no_default) +{ + const mock_option o("helper", "Path to helper", "path"); + ATF_REQUIRE(!o.has_short_name()); + ATF_REQUIRE_EQ("helper", o.long_name()); + ATF_REQUIRE_EQ("Path to helper", o.description()); + ATF_REQUIRE(o.needs_arg()); + ATF_REQUIRE_EQ("path", o.arg_name()); + ATF_REQUIRE(!o.has_default_value()); + ATF_REQUIRE_EQ("--helper=path", o.format_long_name()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(base_option__long_name__with_arg__with_default); +ATF_TEST_CASE_BODY(base_option__long_name__with_arg__with_default) +{ + const mock_option o("executable", "Executable name", "file", "foo"); + ATF_REQUIRE(!o.has_short_name()); + ATF_REQUIRE_EQ("executable", o.long_name()); + ATF_REQUIRE_EQ("Executable name", o.description()); + ATF_REQUIRE(o.needs_arg()); + ATF_REQUIRE_EQ("file", o.arg_name()); + ATF_REQUIRE(o.has_default_value()); + ATF_REQUIRE_EQ("foo", o.default_value()); + ATF_REQUIRE_EQ("--executable=file", o.format_long_name()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(bool_option__short_name); +ATF_TEST_CASE_BODY(bool_option__short_name) +{ + const cmdline::bool_option o('f', "force", "Force execution"); + ATF_REQUIRE(o.has_short_name()); + ATF_REQUIRE_EQ('f', o.short_name()); + ATF_REQUIRE_EQ("force", o.long_name()); + ATF_REQUIRE_EQ("Force execution", o.description()); + ATF_REQUIRE(!o.needs_arg()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(bool_option__long_name); +ATF_TEST_CASE_BODY(bool_option__long_name) +{ + const cmdline::bool_option o("force", "Force execution"); + ATF_REQUIRE(!o.has_short_name()); + ATF_REQUIRE_EQ("force", o.long_name()); + ATF_REQUIRE_EQ("Force execution", o.description()); + ATF_REQUIRE(!o.needs_arg()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(int_option__short_name); +ATF_TEST_CASE_BODY(int_option__short_name) +{ + const cmdline::int_option o('p', "int", "The int", "arg", "value"); + ATF_REQUIRE(o.has_short_name()); + ATF_REQUIRE_EQ('p', o.short_name()); + ATF_REQUIRE_EQ("int", o.long_name()); + ATF_REQUIRE_EQ("The int", o.description()); + ATF_REQUIRE(o.needs_arg()); + ATF_REQUIRE_EQ("arg", o.arg_name()); + ATF_REQUIRE(o.has_default_value()); + ATF_REQUIRE_EQ("value", o.default_value()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(int_option__long_name); +ATF_TEST_CASE_BODY(int_option__long_name) +{ + const cmdline::int_option o("int", "The int", "arg", "value"); + ATF_REQUIRE(!o.has_short_name()); + ATF_REQUIRE_EQ("int", o.long_name()); + ATF_REQUIRE_EQ("The int", o.description()); + ATF_REQUIRE(o.needs_arg()); + ATF_REQUIRE_EQ("arg", o.arg_name()); + ATF_REQUIRE(o.has_default_value()); + ATF_REQUIRE_EQ("value", o.default_value()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(int_option__type); +ATF_TEST_CASE_BODY(int_option__type) +{ + const cmdline::int_option o("int", "The int", "arg"); + + o.validate("123"); + ATF_REQUIRE_EQ(123, cmdline::int_option::convert("123")); + + o.validate("-567"); + ATF_REQUIRE_EQ(-567, cmdline::int_option::convert("-567")); + + ATF_REQUIRE_THROW(cmdline::option_argument_value_error, o.validate("")); + ATF_REQUIRE_THROW(cmdline::option_argument_value_error, o.validate("5a")); + ATF_REQUIRE_THROW(cmdline::option_argument_value_error, o.validate("a5")); + ATF_REQUIRE_THROW(cmdline::option_argument_value_error, o.validate("5 a")); + ATF_REQUIRE_THROW(cmdline::option_argument_value_error, o.validate("5.0")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(list_option__short_name); +ATF_TEST_CASE_BODY(list_option__short_name) +{ + const cmdline::list_option o('p', "list", "The list", "arg", "value"); + ATF_REQUIRE(o.has_short_name()); + ATF_REQUIRE_EQ('p', o.short_name()); + ATF_REQUIRE_EQ("list", o.long_name()); + ATF_REQUIRE_EQ("The list", o.description()); + ATF_REQUIRE(o.needs_arg()); + ATF_REQUIRE_EQ("arg", o.arg_name()); + ATF_REQUIRE(o.has_default_value()); + ATF_REQUIRE_EQ("value", o.default_value()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(list_option__long_name); +ATF_TEST_CASE_BODY(list_option__long_name) +{ + const cmdline::list_option o("list", "The list", "arg", "value"); + ATF_REQUIRE(!o.has_short_name()); + ATF_REQUIRE_EQ("list", o.long_name()); + ATF_REQUIRE_EQ("The list", o.description()); + ATF_REQUIRE(o.needs_arg()); + ATF_REQUIRE_EQ("arg", o.arg_name()); + ATF_REQUIRE(o.has_default_value()); + ATF_REQUIRE_EQ("value", o.default_value()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(list_option__type); +ATF_TEST_CASE_BODY(list_option__type) +{ + const cmdline::list_option o("list", "The list", "arg"); + + o.validate(""); + { + const cmdline::list_option::option_type words = + cmdline::list_option::convert(""); + ATF_REQUIRE(words.empty()); + } + + o.validate("foo"); + { + const cmdline::list_option::option_type words = + cmdline::list_option::convert("foo"); + ATF_REQUIRE_EQ(1, words.size()); + ATF_REQUIRE_EQ("foo", words[0]); + } + + o.validate("foo,bar,baz"); + { + const cmdline::list_option::option_type words = + cmdline::list_option::convert("foo,bar,baz"); + ATF_REQUIRE_EQ(3, words.size()); + ATF_REQUIRE_EQ("foo", words[0]); + ATF_REQUIRE_EQ("bar", words[1]); + ATF_REQUIRE_EQ("baz", words[2]); + } + + o.validate("foo,bar,"); + { + const cmdline::list_option::option_type words = + cmdline::list_option::convert("foo,bar,"); + ATF_REQUIRE_EQ(3, words.size()); + ATF_REQUIRE_EQ("foo", words[0]); + ATF_REQUIRE_EQ("bar", words[1]); + ATF_REQUIRE_EQ("", words[2]); + } + + o.validate(",foo,bar"); + { + const cmdline::list_option::option_type words = + cmdline::list_option::convert(",foo,bar"); + ATF_REQUIRE_EQ(3, words.size()); + ATF_REQUIRE_EQ("", words[0]); + ATF_REQUIRE_EQ("foo", words[1]); + ATF_REQUIRE_EQ("bar", words[2]); + } + + o.validate("foo,,bar"); + { + const cmdline::list_option::option_type words = + cmdline::list_option::convert("foo,,bar"); + ATF_REQUIRE_EQ(3, words.size()); + ATF_REQUIRE_EQ("foo", words[0]); + ATF_REQUIRE_EQ("", words[1]); + ATF_REQUIRE_EQ("bar", words[2]); + } +} + + +ATF_TEST_CASE_WITHOUT_HEAD(path_option__short_name); +ATF_TEST_CASE_BODY(path_option__short_name) +{ + const cmdline::path_option o('p', "path", "The path", "arg", "value"); + ATF_REQUIRE(o.has_short_name()); + ATF_REQUIRE_EQ('p', o.short_name()); + ATF_REQUIRE_EQ("path", o.long_name()); + ATF_REQUIRE_EQ("The path", o.description()); + ATF_REQUIRE(o.needs_arg()); + ATF_REQUIRE_EQ("arg", o.arg_name()); + ATF_REQUIRE(o.has_default_value()); + ATF_REQUIRE_EQ("value", o.default_value()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(path_option__long_name); +ATF_TEST_CASE_BODY(path_option__long_name) +{ + const cmdline::path_option o("path", "The path", "arg", "value"); + ATF_REQUIRE(!o.has_short_name()); + ATF_REQUIRE_EQ("path", o.long_name()); + ATF_REQUIRE_EQ("The path", o.description()); + ATF_REQUIRE(o.needs_arg()); + ATF_REQUIRE_EQ("arg", o.arg_name()); + ATF_REQUIRE(o.has_default_value()); + ATF_REQUIRE_EQ("value", o.default_value()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(path_option__type); +ATF_TEST_CASE_BODY(path_option__type) +{ + const cmdline::path_option o("path", "The path", "arg"); + + o.validate("/some/path"); + + try { + o.validate(""); + fail("option_argument_value_error not raised"); + } catch (const cmdline::option_argument_value_error& e) { + // Expected; ignore. + } + + const cmdline::path_option::option_type path = + cmdline::path_option::convert("/foo/bar"); + ATF_REQUIRE_EQ("bar", path.leaf_name()); // Ensure valid type. +} + + +ATF_TEST_CASE_WITHOUT_HEAD(property_option__short_name); +ATF_TEST_CASE_BODY(property_option__short_name) +{ + const cmdline::property_option o('p', "property", "The property", "a=b"); + ATF_REQUIRE(o.has_short_name()); + ATF_REQUIRE_EQ('p', o.short_name()); + ATF_REQUIRE_EQ("property", o.long_name()); + ATF_REQUIRE_EQ("The property", o.description()); + ATF_REQUIRE(o.needs_arg()); + ATF_REQUIRE_EQ("a=b", o.arg_name()); + ATF_REQUIRE(!o.has_default_value()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(property_option__long_name); +ATF_TEST_CASE_BODY(property_option__long_name) +{ + const cmdline::property_option o("property", "The property", "a=b"); + ATF_REQUIRE(!o.has_short_name()); + ATF_REQUIRE_EQ("property", o.long_name()); + ATF_REQUIRE_EQ("The property", o.description()); + ATF_REQUIRE(o.needs_arg()); + ATF_REQUIRE_EQ("a=b", o.arg_name()); + ATF_REQUIRE(!o.has_default_value()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(property_option__type); +ATF_TEST_CASE_BODY(property_option__type) +{ + typedef std::pair< std::string, std::string > string_pair; + const cmdline::property_option o("property", "The property", "a=b"); + + o.validate("foo=bar"); + ATF_REQUIRE(string_pair("foo", "bar") == + cmdline::property_option::convert("foo=bar")); + + o.validate(" foo = bar baz"); + ATF_REQUIRE(string_pair(" foo ", " bar baz") == + cmdline::property_option::convert(" foo = bar baz")); + + ATF_REQUIRE_THROW(cmdline::option_argument_value_error, o.validate("")); + ATF_REQUIRE_THROW(cmdline::option_argument_value_error, o.validate("=")); + ATF_REQUIRE_THROW(cmdline::option_argument_value_error, o.validate("a=")); + ATF_REQUIRE_THROW(cmdline::option_argument_value_error, o.validate("=b")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(string_option__short_name); +ATF_TEST_CASE_BODY(string_option__short_name) +{ + const cmdline::string_option o('p', "string", "The string", "arg", "value"); + ATF_REQUIRE(o.has_short_name()); + ATF_REQUIRE_EQ('p', o.short_name()); + ATF_REQUIRE_EQ("string", o.long_name()); + ATF_REQUIRE_EQ("The string", o.description()); + ATF_REQUIRE(o.needs_arg()); + ATF_REQUIRE_EQ("arg", o.arg_name()); + ATF_REQUIRE(o.has_default_value()); + ATF_REQUIRE_EQ("value", o.default_value()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(string_option__long_name); +ATF_TEST_CASE_BODY(string_option__long_name) +{ + const cmdline::string_option o("string", "The string", "arg", "value"); + ATF_REQUIRE(!o.has_short_name()); + ATF_REQUIRE_EQ("string", o.long_name()); + ATF_REQUIRE_EQ("The string", o.description()); + ATF_REQUIRE(o.needs_arg()); + ATF_REQUIRE_EQ("arg", o.arg_name()); + ATF_REQUIRE(o.has_default_value()); + ATF_REQUIRE_EQ("value", o.default_value()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(string_option__type); +ATF_TEST_CASE_BODY(string_option__type) +{ + const cmdline::string_option o("string", "The string", "foo"); + + o.validate(""); + o.validate("some string"); + + const cmdline::string_option::option_type string = + cmdline::string_option::convert("foo"); + ATF_REQUIRE_EQ(3, string.length()); // Ensure valid type. +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, base_option__short_name__no_arg); + ATF_ADD_TEST_CASE(tcs, base_option__short_name__with_arg__no_default); + ATF_ADD_TEST_CASE(tcs, base_option__short_name__with_arg__with_default); + ATF_ADD_TEST_CASE(tcs, base_option__long_name__no_arg); + ATF_ADD_TEST_CASE(tcs, base_option__long_name__with_arg__no_default); + ATF_ADD_TEST_CASE(tcs, base_option__long_name__with_arg__with_default); + + ATF_ADD_TEST_CASE(tcs, bool_option__short_name); + ATF_ADD_TEST_CASE(tcs, bool_option__long_name); + + ATF_ADD_TEST_CASE(tcs, int_option__short_name); + ATF_ADD_TEST_CASE(tcs, int_option__long_name); + ATF_ADD_TEST_CASE(tcs, int_option__type); + + ATF_ADD_TEST_CASE(tcs, list_option__short_name); + ATF_ADD_TEST_CASE(tcs, list_option__long_name); + ATF_ADD_TEST_CASE(tcs, list_option__type); + + ATF_ADD_TEST_CASE(tcs, path_option__short_name); + ATF_ADD_TEST_CASE(tcs, path_option__long_name); + ATF_ADD_TEST_CASE(tcs, path_option__type); + + ATF_ADD_TEST_CASE(tcs, property_option__short_name); + ATF_ADD_TEST_CASE(tcs, property_option__long_name); + ATF_ADD_TEST_CASE(tcs, property_option__type); + + ATF_ADD_TEST_CASE(tcs, string_option__short_name); + ATF_ADD_TEST_CASE(tcs, string_option__long_name); + ATF_ADD_TEST_CASE(tcs, string_option__type); +} diff --git a/external/bsd/kyua-cli/dist/utils/cmdline/parser.cpp b/external/bsd/kyua-cli/dist/utils/cmdline/parser.cpp new file mode 100644 index 000000000..b8a6d163c --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/cmdline/parser.cpp @@ -0,0 +1,385 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/cmdline/parser.hpp" + +#if defined(HAVE_CONFIG_H) +# include "config.h" +#endif + +extern "C" { +#include +} + +#include +#include +#include + +#include "utils/auto_array.ipp" +#include "utils/cmdline/exceptions.hpp" +#include "utils/cmdline/options.hpp" +#include "utils/format/macros.hpp" +#include "utils/noncopyable.hpp" +#include "utils/sanity.hpp" + +namespace cmdline = utils::cmdline; + +namespace { + + +/// Auxiliary data to call getopt_long(3). +struct getopt_data : utils::noncopyable { + /// Plain-text representation of the short options. + /// + /// This string follows the syntax expected by getopt_long(3) in the + /// argument to describe the short options. + std::string short_options; + + /// Representation of the long options as expected by getopt_long(3). + utils::auto_array< ::option > long_options; + + /// Auto-generated identifiers to be able to parse long options. + std::map< int, const cmdline::base_option* > ids; +}; + + +/// Converts a cmdline::options_vector to a getopt_data. +/// +/// \param options The high-level definition of the options. +/// \param [out] data An object containing the necessary data to call +/// getopt_long(3) and interpret its results. +static void +options_to_getopt_data(const cmdline::options_vector& options, + getopt_data& data) +{ + data.short_options.clear(); + data.long_options.reset(new ::option[options.size() + 1]); + + int cur_id = 512; + + for (cmdline::options_vector::size_type i = 0; i < options.size(); i++) { + const cmdline::base_option* option = options[i]; + ::option& long_option = data.long_options[i]; + + long_option.name = option->long_name().c_str(); + if (option->needs_arg()) + long_option.has_arg = required_argument; + else + long_option.has_arg = no_argument; + + int id = -1; + if (option->has_short_name()) { + data.short_options += option->short_name(); + if (option->needs_arg()) + data.short_options += ':'; + id = option->short_name(); + } else { + id = cur_id++; + } + long_option.flag = NULL; + long_option.val = id; + data.ids[id] = option; + } + + ::option& last_long_option = data.long_options[options.size()]; + last_long_option.name = NULL; + last_long_option.has_arg = 0; + last_long_option.flag = NULL; + last_long_option.val = 0; +} + + +/// Converts an argc/argv pair to an args_vector. +/// +/// \param argc The value of argc as passed to main(). +/// \param argv The value of argv as passed to main(). +/// +/// \return An args_vector with the same contents of argc/argv. +static cmdline::args_vector +argv_to_vector(int argc, const char* const argv[]) +{ + PRE(argv[argc] == NULL); + cmdline::args_vector args; + for (int i = 0; i < argc; i++) + args.push_back(argv[i]); + return args; +} + + +/// Creates a mutable version of argv. +/// +/// \param argc The value of argc as passed to main(). +/// \param argv The value of argv as passed to main(). +/// +/// \return A new argv, with mutable buffers. The returned array must be +/// released using the free_mutable_argv() function. +static char** +make_mutable_argv(const int argc, const char* const* argv) +{ + char** mutable_argv = new char*[argc + 1]; + for (int i = 0; i < argc; i++) + mutable_argv[i] = ::strdup(argv[i]); + mutable_argv[argc] = NULL; + return mutable_argv; +} + + +/// Releases the object returned by make_mutable_argv(). +/// +/// \param argv A dynamically-allocated argv as returned by make_mutable_argv(). +static void +free_mutable_argv(char** argv) +{ + char** ptr = argv; + while (*ptr != NULL) { + ::free(*ptr); + ptr++; + } + delete [] argv; +} + + +/// Finds the name of the offending option after a getopt_long error. +/// +/// \param data Our internal getopt data used for the call to getopt_long. +/// \param getopt_optopt The value of getopt(3)'s optopt after the error. +/// \param argv The argv passed to getopt_long. +/// \param getopt_optind The value of getopt(3)'s optind after the error. +/// +/// \return A fully-specified option name (i.e. an option name prefixed by +/// either '-' or '--'). +static std::string +find_option_name(const getopt_data& data, const int getopt_optopt, + char** argv, const int getopt_optind) +{ + PRE(getopt_optopt >= 0); + + if (getopt_optopt == 0) { + return argv[getopt_optind - 1]; + } else if (getopt_optopt < std::numeric_limits< char >::max()) { + INV(getopt_optopt > 0); + const char ch = static_cast< char >(getopt_optopt); + return F("-%s") % ch; + } else { + for (const ::option* opt = &data.long_options[0]; opt->name != NULL; + opt++) { + if (opt->val == getopt_optopt) + return F("--%s") % opt->name; + } + UNREACHABLE; + } +} + + +} // anonymous namespace + + +/// Constructs a new parsed_cmdline. +/// +/// Use the cmdline::parse() free functions to construct. +/// +/// \param option_values_ A mapping of long option names to values. This +/// contains a representation of the options provided by the user. Note +/// that each value is actually a collection values: a user may specify a +/// flag multiple times, and depending on the case we want to honor one or +/// the other. For those options that support no argument, the argument +/// value is the empty string. +/// \param arguments_ The list of non-option arguments in the command line. +cmdline::parsed_cmdline::parsed_cmdline( + const std::map< std::string, std::vector< std::string > >& option_values_, + const cmdline::args_vector& arguments_) : + _option_values(option_values_), + _arguments(arguments_) +{ +} + + +/// Checks if the given option has been given in the command line. +/// +/// \param name The long option name to check for presence. +/// +/// \return True if the option has been given; false otherwise. +bool +cmdline::parsed_cmdline::has_option(const std::string& name) const +{ + return _option_values.find(name) != _option_values.end(); +} + + +/// Gets the raw value of an option. +/// +/// The raw value of an option is a collection of strings that represent all the +/// values passed to the option on the command line. It is up to the consumer +/// if he wants to honor only the last value or all of them. +/// +/// The caller has to use get_option() instead; this function is internal. +/// +/// \pre has_option(name) must be true. +/// +/// \param name The option to query. +/// +/// \return The value of the option as a plain string. +const std::vector< std::string >& +cmdline::parsed_cmdline::get_option_raw(const std::string& name) const +{ + std::map< std::string, std::vector< std::string > >::const_iterator iter = + _option_values.find(name); + INV_MSG(iter != _option_values.end(), F("Undefined option --%s") % name); + return (*iter).second; +} + + +/// Returns the non-option arguments found in the command line. +/// +/// \return The arguments, if any. +const cmdline::args_vector& +cmdline::parsed_cmdline::arguments(void) const +{ + return _arguments; +} + + +/// Parses a command line. +/// +/// \param args The command line to parse, broken down by words. +/// \param options The description of the supported options. +/// +/// \return The parsed command line. +/// +/// \pre args[0] must be the program or command name. +/// +/// \throw cmdline::error See the description of parse(argc, argv, options) for +/// more details on the raised errors. +cmdline::parsed_cmdline +cmdline::parse(const cmdline::args_vector& args, + const cmdline::options_vector& options) +{ + PRE_MSG(args.size() >= 1, "No progname or command name found"); + + utils::auto_array< const char* > argv(new const char*[args.size() + 1]); + for (args_vector::size_type i = 0; i < args.size(); i++) + argv[i] = args[i].c_str(); + argv[args.size()] = NULL; + return parse(static_cast< int >(args.size()), argv.get(), options); +} + + +/// Parses a command line. +/// +/// \param argc The number of arguments in argv, without counting the +/// terminating NULL. +/// \param argv The arguments to parse. The array is NULL-terminated. +/// \param options The description of the supported options. +/// +/// \return The parsed command line. +/// +/// \pre args[0] must be the program or command name. +/// +/// \throw cmdline::missing_option_argument_error If the user specified an +/// option that requires an argument, but no argument was provided. +/// \throw cmdline::unknown_option_error If the user specified an unknown +/// option (i.e. an option not defined in options). +/// \throw cmdline::option_argument_value_error If the user passed an invalid +/// argument to a supported option. +cmdline::parsed_cmdline +cmdline::parse(const int argc, const char* const* argv, + const cmdline::options_vector& options) +{ + PRE_MSG(argc >= 1, "No progname or command name found"); + + getopt_data data; + options_to_getopt_data(options, data); + + std::map< std::string, std::vector< std::string > > option_values; + + for (cmdline::options_vector::const_iterator iter = options.begin(); + iter != options.end(); iter++) { + const cmdline::base_option* option = *iter; + if (option->needs_arg() && option->has_default_value()) + option_values[option->long_name()].push_back( + option->default_value()); + } + + args_vector args; + + int mutable_argc = argc; + char** mutable_argv = make_mutable_argv(argc, argv); + const int old_opterr = ::opterr; + try { + int ch; + + ::opterr = 0; + + while ((ch = ::getopt_long(mutable_argc, mutable_argv, + ("+:" + data.short_options).c_str(), + data.long_options.get(), NULL)) != -1) { + if (ch == ':' ) { + const std::string name = find_option_name( + data, ::optopt, mutable_argv, ::optind); + throw cmdline::missing_option_argument_error(name); + } else if (ch == '?') { + const std::string name = find_option_name( + data, ::optopt, mutable_argv, ::optind); + throw cmdline::unknown_option_error(name); + } + + const std::map< int, const cmdline::base_option* >::const_iterator + id = data.ids.find(ch); + INV(id != data.ids.end()); + const cmdline::base_option* option = (*id).second; + + if (option->needs_arg()) { + if (::optarg != NULL) { + option->validate(::optarg); + option_values[option->long_name()].push_back(::optarg); + } else + INV(option->has_default_value()); + } else { + option_values[option->long_name()].push_back(""); + } + } + args = argv_to_vector(mutable_argc - optind, mutable_argv + optind); + + ::opterr = old_opterr; + ::optind = GETOPT_OPTIND_RESET_VALUE; +#if defined(HAVE_GETOPT_WITH_OPTRESET) + ::optreset = 1; +#endif + } catch (...) { + free_mutable_argv(mutable_argv); + ::opterr = old_opterr; + ::optind = GETOPT_OPTIND_RESET_VALUE; +#if defined(HAVE_GETOPT_WITH_OPTRESET) + ::optreset = 1; +#endif + throw; + } + free_mutable_argv(mutable_argv); + + return parsed_cmdline(option_values, args); +} diff --git a/external/bsd/kyua-cli/dist/utils/cmdline/parser.hpp b/external/bsd/kyua-cli/dist/utils/cmdline/parser.hpp new file mode 100644 index 000000000..bedda4b98 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/cmdline/parser.hpp @@ -0,0 +1,100 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file utils/cmdline/parser.hpp +/// Routines and data types to parse command line options and arguments. + +#if !defined(UTILS_CMDLINE_PARSER_HPP) +#define UTILS_CMDLINE_PARSER_HPP + +#include +#include +#include + +namespace utils { +namespace cmdline { + + +class base_option; + + +/// Replacement for argc and argv to represent a command line. +/// +/// TODO(jmmv): This type should be somewhere else. base_command.hpp should not +/// be including this file to just get this type. +typedef std::vector< std::string > args_vector; + + +/// Collection of options to be used during parsing. +/// +/// TODO(jmmv): This type should be somewhere else. base_command.hpp should not +/// be including this file to just get this type. +typedef std::vector< const base_option* > options_vector; + + +/// Representation of a parsed command line. +/// +/// This class is returned by the command line parsing algorithm and provides +/// methods to query the values of the options and the value of the arguments. +/// All the values fed into this class can considered to be sane (i.e. the +/// arguments to the options and the arguments to the command are valid), as all +/// validation happens during parsing (before this class is instantiated). +class parsed_cmdline { + /// Mapping of option names to all the values provided. + std::map< std::string, std::vector< std::string > > _option_values; + + /// Collection of arguments with all options removed. + args_vector _arguments; + + const std::vector< std::string >& get_option_raw(const std::string&) const; + +public: + parsed_cmdline(const std::map< std::string, std::vector< std::string > >&, + const args_vector&); + + bool has_option(const std::string&) const; + + template< typename Option > + typename Option::option_type get_option(const std::string&) const; + + template< typename Option > + std::vector< typename Option::option_type > get_multi_option( + const std::string&) const; + + const args_vector& arguments(void) const; +}; + + +parsed_cmdline parse(const args_vector&, const options_vector&); +parsed_cmdline parse(const int, const char* const*, const options_vector&); + + +} // namespace cmdline +} // namespace utils + +#endif // !defined(UTILS_CMDLINE_PARSER_HPP) diff --git a/external/bsd/kyua-cli/dist/utils/cmdline/parser.ipp b/external/bsd/kyua-cli/dist/utils/cmdline/parser.ipp new file mode 100644 index 000000000..ade4e7eff --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/cmdline/parser.ipp @@ -0,0 +1,83 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#if !defined(UTILS_CMDLINE_PARSER_IPP) +#define UTILS_CMDLINE_PARSER_IPP + +#include "utils/cmdline/parser.hpp" + + +/// Gets the value of an option. +/// +/// If the option has been specified multiple times on the command line, this +/// only returns the last value. This is the traditional behavior. +/// +/// The option must support arguments. Otherwise, a call to this function will +/// not compile because the option type will lack the definition of some fields +/// and/or methods. +/// +/// \param name The option to query. +/// +/// \return The value of the option converted to the appropriate type. +/// +/// \pre has_option(name) must be true. +template< typename Option > typename Option::option_type +utils::cmdline::parsed_cmdline::get_option(const std::string& name) const +{ + const std::vector< std::string >& raw_values = get_option_raw(name); + return Option::convert(raw_values[raw_values.size() - 1]); +} + + +/// Gets the values of an option that supports repetition. +/// +/// The option must support arguments. Otherwise, a call to this function will +/// not compile because the option type will lack the definition of some fields +/// and/or methods. +/// +/// \param name The option to query. +/// +/// \return The values of the option converted to the appropriate type. +/// +/// \pre has_option(name) must be true. +template< typename Option > std::vector< typename Option::option_type > +utils::cmdline::parsed_cmdline::get_multi_option(const std::string& name) const +{ + std::vector< typename Option::option_type > values; + + const std::vector< std::string >& raw_values = get_option_raw(name); + for (std::vector< std::string >::const_iterator iter = raw_values.begin(); + iter != raw_values.end(); iter++) { + values.push_back(Option::convert(*iter)); + } + + return values; +} + + +#endif // !defined(UTILS_CMDLINE_PARSER_IPP) diff --git a/external/bsd/kyua-cli/dist/utils/cmdline/parser_test.cpp b/external/bsd/kyua-cli/dist/utils/cmdline/parser_test.cpp new file mode 100644 index 000000000..ee5415594 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/cmdline/parser_test.cpp @@ -0,0 +1,688 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/cmdline/parser.ipp" + +#if defined(HAVE_CONFIG_H) +#include "config.h" +#endif + +extern "C" { +#include +#include +#include +} + +#include +#include +#include +#include +#include +#include + +#include + +#include "utils/cmdline/exceptions.hpp" +#include "utils/cmdline/options.hpp" +#include "utils/format/macros.hpp" +#include "utils/sanity.hpp" + +namespace cmdline = utils::cmdline; + +using cmdline::base_option; +using cmdline::bool_option; +using cmdline::int_option; +using cmdline::parse; +using cmdline::parsed_cmdline; +using cmdline::string_option; + + +namespace { + + +/// Mock option type to check the validate and convert methods sequence. +/// +/// Instances of this option accept a string argument that must be either "zero" +/// or "one". These are validated and converted to integers. +class mock_option : public base_option { +public: + /// Constructs the new option. + /// + /// \param long_name_ The long name for the option. All other option + /// properties are irrelevant for the tests using this, so they are set + /// to arbitrary values. + mock_option(const char* long_name_) : + base_option(long_name_, "Irrelevant description", "arg") + { + } + + /// The type of the argument of this option. + typedef int option_type; + + /// Checks that the user-provided option is valid. + /// + /// \param str The user argument; must be "zero" or "one". + /// + /// \throw cmdline::option_argument_value_error If str is not valid. + void + validate(const std::string& str) const + { + if (str != "zero" && str != "one") + throw cmdline::option_argument_value_error(F("--%s") % long_name(), + str, "Unknown value"); + } + + /// Converts the user-provided argument to our native integer type. + /// + /// \param str The user argument; must be "zero" or "one". + /// + /// \return 0 if the input is "zero", or 1 if the input is "one". + /// + /// \throw std::runtime_error If str is not valid. In real life, this + /// should be a precondition because validate() has already ensured that + /// the values passed to convert() are correct. However, we raise an + /// exception here because we are actually validating that this code + /// sequence holds true. + static int + convert(const std::string& str) + { + if (str == "zero") + return 0; + else if (str == "one") + return 1; + else { + // This would generally be an assertion but, given that this is + // test code, we want to catch any errors regardless of how the + // binary is built. + throw std::runtime_error("Value not validated properly."); + } + } +}; + + +/// Redirects stdout and stderr to a file. +/// +/// This fails the test case in case of any error. +/// +/// \param file The name of the file to redirect stdout and stderr to. +/// +/// \return A copy of the old stdout and stderr file descriptors. +static std::pair< int, int > +mock_stdfds(const char* file) +{ + std::cout.flush(); + std::cerr.flush(); + + const int oldout = ::dup(STDOUT_FILENO); + ATF_REQUIRE(oldout != -1); + const int olderr = ::dup(STDERR_FILENO); + ATF_REQUIRE(olderr != -1); + + const int fd = ::open(file, O_WRONLY | O_CREAT | O_TRUNC, 0644); + ATF_REQUIRE(fd != -1); + ATF_REQUIRE(::dup2(fd, STDOUT_FILENO) != -1); + ATF_REQUIRE(::dup2(fd, STDERR_FILENO) != -1); + ::close(fd); + + return std::make_pair(oldout, olderr); +} + + +/// Restores stdout and stderr after a call to mock_stdfds. +/// +/// \param oldfds The copy of the previous stdout and stderr as returned by the +/// call to mock_fds(). +static void +restore_stdfds(const std::pair< int, int >& oldfds) +{ + ATF_REQUIRE(::dup2(oldfds.first, STDOUT_FILENO) != -1); + ::close(oldfds.first); + ATF_REQUIRE(::dup2(oldfds.second, STDERR_FILENO) != -1); + ::close(oldfds.second); +} + + +/// Checks whether a '+:' prefix to the short options of getopt_long works. +/// +/// It turns out that the getopt_long(3) implementation of Ubuntu 10.04.1 (and +/// very likely other distributions) does not properly report a missing argument +/// to a second long option as such. Instead of returning ':' when the second +/// long option provided on the command line does not carry a required argument, +/// it will mistakenly return '?' which translates to "unknown option". +/// +/// As a result of this bug, we cannot properly detect that 'flag2' requires an +/// argument in a command line like: 'progname --flag1=foo --flag2'. +/// +/// I am not sure if we could fully workaround the issue in the implementation +/// of our library. For the time being I am just using this bug detection in +/// the test cases to prevent failures that are not really our fault. +/// +/// \return bool True if getopt_long is broken and does not interpret '+:' +/// correctly; False otherwise. +static bool +is_getopt_long_pluscolon_broken(void) +{ + struct ::option long_options[] = { + { "flag1", 1, NULL, '1' }, + { "flag2", 1, NULL, '2' }, + { NULL, 0, NULL, 0 } + }; + + const int argc = 3; + char* argv[4]; + argv[0] = ::strdup("progname"); + argv[1] = ::strdup("--flag1=a"); + argv[2] = ::strdup("--flag2"); + argv[3] = NULL; + + const int old_opterr = ::opterr; + ::opterr = 0; + + bool got_colon = false; + + int opt; + while ((opt = ::getopt_long(argc, argv, "+:", long_options, NULL)) != -1) { + switch (opt) { + case '1': break; + case '2': break; + case ':': got_colon = true; break; + case '?': break; + default: UNREACHABLE; break; + } + } + + ::opterr = old_opterr; + ::optind = 1; +#if defined(HAVE_GETOPT_WITH_OPTRESET) + ::optreset = 1; +#endif + + for (char** arg = &argv[0]; *arg != NULL; arg++) + std::free(*arg); + + return !got_colon; +} + + +} // anonymous namespace + + +ATF_TEST_CASE_WITHOUT_HEAD(progname__no_options); +ATF_TEST_CASE_BODY(progname__no_options) +{ + const int argc = 1; + const char* const argv[] = {"progname", NULL}; + std::vector< const base_option* > options; + const parsed_cmdline cmdline = parse(argc, argv, options); + + ATF_REQUIRE(cmdline.arguments().empty()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(progname__some_options); +ATF_TEST_CASE_BODY(progname__some_options) +{ + const int argc = 1; + const char* const argv[] = {"progname", NULL}; + const string_option a('a', "a_option", "Foo", NULL); + const string_option b('b', "b_option", "Bar", "arg", "foo"); + const string_option c("c_option", "Baz", NULL); + const string_option d("d_option", "Wohoo", "arg", "bar"); + std::vector< const base_option* > options; + options.push_back(&a); + options.push_back(&b); + options.push_back(&c); + options.push_back(&d); + const parsed_cmdline cmdline = parse(argc, argv, options); + + ATF_REQUIRE_EQ("foo", cmdline.get_option< string_option >("b_option")); + ATF_REQUIRE_EQ("bar", cmdline.get_option< string_option >("d_option")); + ATF_REQUIRE(cmdline.arguments().empty()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(some_args__no_options); +ATF_TEST_CASE_BODY(some_args__no_options) +{ + const int argc = 5; + const char* const argv[] = {"progname", "foo", "-c", "--opt", "bar", NULL}; + std::vector< const base_option* > options; + const parsed_cmdline cmdline = parse(argc, argv, options); + + ATF_REQUIRE(!cmdline.has_option("c")); + ATF_REQUIRE(!cmdline.has_option("opt")); + ATF_REQUIRE_EQ(4, cmdline.arguments().size()); + ATF_REQUIRE_EQ("foo", cmdline.arguments()[0]); + ATF_REQUIRE_EQ("-c", cmdline.arguments()[1]); + ATF_REQUIRE_EQ("--opt", cmdline.arguments()[2]); + ATF_REQUIRE_EQ("bar", cmdline.arguments()[3]); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(some_args__some_options); +ATF_TEST_CASE_BODY(some_args__some_options) +{ + const int argc = 5; + const char* const argv[] = {"progname", "foo", "-c", "--opt", "bar", NULL}; + const string_option c('c', "opt", "Description", NULL); + std::vector< const base_option* > options; + options.push_back(&c); + const parsed_cmdline cmdline = parse(argc, argv, options); + + ATF_REQUIRE(!cmdline.has_option("c")); + ATF_REQUIRE(!cmdline.has_option("opt")); + ATF_REQUIRE_EQ(4, cmdline.arguments().size()); + ATF_REQUIRE_EQ("foo", cmdline.arguments()[0]); + ATF_REQUIRE_EQ("-c", cmdline.arguments()[1]); + ATF_REQUIRE_EQ("--opt", cmdline.arguments()[2]); + ATF_REQUIRE_EQ("bar", cmdline.arguments()[3]); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(some_options__all_known); +ATF_TEST_CASE_BODY(some_options__all_known) +{ + const int argc = 14; + const char* const argv[] = { + "progname", + "-a", + "-bvalue_b", + "-c", "value_c", + //"-d", // Options with default optional values are unsupported. + "-evalue_e", // Has default; overriden. + "--f_long", + "--g_long=value_g", + "--h_long", "value_h", + //"--i_long", // Options with default optional values are unsupported. + "--j_long", "value_j", // Has default; overriden as separate argument. + "arg1", "arg2", NULL, + }; + const bool_option a('a', "a_long", ""); + const string_option b('b', "b_long", "Description", "arg"); + const string_option c('c', "c_long", "ABCD", "foo"); + const string_option d('d', "d_long", "Description", "bar", "default_d"); + const string_option e('e', "e_long", "Description", "baz", "default_e"); + const bool_option f("f_long", "Description"); + const string_option g("g_long", "Description", "arg"); + const string_option h("h_long", "Description", "foo"); + const string_option i("i_long", "EFGH", "bar", "default_i"); + const string_option j("j_long", "Description", "baz", "default_j"); + std::vector< const base_option* > options; + options.push_back(&a); + options.push_back(&b); + options.push_back(&c); + options.push_back(&d); + options.push_back(&e); + options.push_back(&f); + options.push_back(&g); + options.push_back(&h); + options.push_back(&i); + options.push_back(&j); + const parsed_cmdline cmdline = parse(argc, argv, options); + + ATF_REQUIRE(cmdline.has_option("a_long")); + ATF_REQUIRE_EQ("value_b", cmdline.get_option< string_option >("b_long")); + ATF_REQUIRE_EQ("value_c", cmdline.get_option< string_option >("c_long")); + ATF_REQUIRE_EQ("default_d", cmdline.get_option< string_option >("d_long")); + ATF_REQUIRE_EQ("value_e", cmdline.get_option< string_option >("e_long")); + ATF_REQUIRE(cmdline.has_option("f_long")); + ATF_REQUIRE_EQ("value_g", cmdline.get_option< string_option >("g_long")); + ATF_REQUIRE_EQ("value_h", cmdline.get_option< string_option >("h_long")); + ATF_REQUIRE_EQ("default_i", cmdline.get_option< string_option >("i_long")); + ATF_REQUIRE_EQ("value_j", cmdline.get_option< string_option >("j_long")); + ATF_REQUIRE_EQ(2, cmdline.arguments().size()); + ATF_REQUIRE_EQ("arg1", cmdline.arguments()[0]); + ATF_REQUIRE_EQ("arg2", cmdline.arguments()[1]); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(some_options__multi); +ATF_TEST_CASE_BODY(some_options__multi) +{ + const int argc = 9; + const char* const argv[] = { + "progname", + "-a1", + "-bvalue1", + "-a2", + "--a_long=3", + "-bvalue2", + "--b_long=value3", + "arg1", "arg2", NULL, + }; + const int_option a('a', "a_long", "Description", "arg"); + const string_option b('b', "b_long", "Description", "arg"); + std::vector< const base_option* > options; + options.push_back(&a); + options.push_back(&b); + const parsed_cmdline cmdline = parse(argc, argv, options); + + { + ATF_REQUIRE_EQ(3, cmdline.get_option< int_option >("a_long")); + const std::vector< int > multi = + cmdline.get_multi_option< int_option >("a_long"); + ATF_REQUIRE_EQ(3, multi.size()); + ATF_REQUIRE_EQ(1, multi[0]); + ATF_REQUIRE_EQ(2, multi[1]); + ATF_REQUIRE_EQ(3, multi[2]); + } + + { + ATF_REQUIRE_EQ("value3", cmdline.get_option< string_option >("b_long")); + const std::vector< std::string > multi = + cmdline.get_multi_option< string_option >("b_long"); + ATF_REQUIRE_EQ(3, multi.size()); + ATF_REQUIRE_EQ("value1", multi[0]); + ATF_REQUIRE_EQ("value2", multi[1]); + ATF_REQUIRE_EQ("value3", multi[2]); + } +} + + +ATF_TEST_CASE_WITHOUT_HEAD(subcommands); +ATF_TEST_CASE_BODY(subcommands) +{ + const int argc = 5; + const char* const argv[] = {"progname", "--flag1", "subcommand", + "--flag2", "arg", NULL}; + const bool_option flag1("flag1", ""); + std::vector< const base_option* > options; + options.push_back(&flag1); + const parsed_cmdline cmdline = parse(argc, argv, options); + + ATF_REQUIRE( cmdline.has_option("flag1")); + ATF_REQUIRE(!cmdline.has_option("flag2")); + ATF_REQUIRE_EQ(3, cmdline.arguments().size()); + ATF_REQUIRE_EQ("subcommand", cmdline.arguments()[0]); + ATF_REQUIRE_EQ("--flag2", cmdline.arguments()[1]); + ATF_REQUIRE_EQ("arg", cmdline.arguments()[2]); + + const bool_option flag2("flag2", ""); + std::vector< const base_option* > options2; + options2.push_back(&flag2); + const parsed_cmdline cmdline2 = parse(cmdline.arguments(), options2); + + ATF_REQUIRE(!cmdline2.has_option("flag1")); + ATF_REQUIRE( cmdline2.has_option("flag2")); + ATF_REQUIRE_EQ(1, cmdline2.arguments().size()); + ATF_REQUIRE_EQ("arg", cmdline2.arguments()[0]); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(missing_option_argument_error__short); +ATF_TEST_CASE_BODY(missing_option_argument_error__short) +{ + const int argc = 3; + const char* const argv[] = {"progname", "-a3", "-b", NULL}; + const string_option flag1('a', "flag1", "Description", "arg"); + const string_option flag2('b', "flag2", "Description", "arg"); + std::vector< const base_option* > options; + options.push_back(&flag1); + options.push_back(&flag2); + + try { + parse(argc, argv, options); + fail("missing_option_argument_error not raised"); + } catch (const cmdline::missing_option_argument_error& e) { + ATF_REQUIRE_EQ("-b", e.option()); + } catch (const cmdline::unknown_option_error& e) { + if (is_getopt_long_pluscolon_broken()) + expect_fail("Your getopt_long is broken"); + fail("Got unknown_option_error instead of " + "missing_option_argument_error"); + } +} + + +ATF_TEST_CASE_WITHOUT_HEAD(missing_option_argument_error__shortblock); +ATF_TEST_CASE_BODY(missing_option_argument_error__shortblock) +{ + const int argc = 3; + const char* const argv[] = {"progname", "-ab3", "-ac", NULL}; + const bool_option flag1('a', "flag1", "Description"); + const string_option flag2('b', "flag2", "Description", "arg"); + const string_option flag3('c', "flag2", "Description", "arg"); + std::vector< const base_option* > options; + options.push_back(&flag1); + options.push_back(&flag2); + options.push_back(&flag3); + + try { + parse(argc, argv, options); + fail("missing_option_argument_error not raised"); + } catch (const cmdline::missing_option_argument_error& e) { + ATF_REQUIRE_EQ("-c", e.option()); + } catch (const cmdline::unknown_option_error& e) { + if (is_getopt_long_pluscolon_broken()) + expect_fail("Your getopt_long is broken"); + fail("Got unknown_option_error instead of " + "missing_option_argument_error"); + } +} + + +ATF_TEST_CASE_WITHOUT_HEAD(missing_option_argument_error__long); +ATF_TEST_CASE_BODY(missing_option_argument_error__long) +{ + const int argc = 3; + const char* const argv[] = {"progname", "--flag1=a", "--flag2", NULL}; + const string_option flag1("flag1", "Description", "arg"); + const string_option flag2("flag2", "Description", "arg"); + std::vector< const base_option* > options; + options.push_back(&flag1); + options.push_back(&flag2); + + try { + parse(argc, argv, options); + fail("missing_option_argument_error not raised"); + } catch (const cmdline::missing_option_argument_error& e) { + ATF_REQUIRE_EQ("--flag2", e.option()); + } catch (const cmdline::unknown_option_error& e) { + if (is_getopt_long_pluscolon_broken()) + expect_fail("Your getopt_long is broken"); + fail("Got unknown_option_error instead of " + "missing_option_argument_error"); + } +} + + +ATF_TEST_CASE_WITHOUT_HEAD(unknown_option_error__short); +ATF_TEST_CASE_BODY(unknown_option_error__short) +{ + const int argc = 3; + const char* const argv[] = {"progname", "-a", "-b", NULL}; + const bool_option flag1('a', "flag1", "Description"); + std::vector< const base_option* > options; + options.push_back(&flag1); + + try { + parse(argc, argv, options); + fail("unknown_option_error not raised"); + } catch (const cmdline::unknown_option_error& e) { + ATF_REQUIRE_EQ("-b", e.option()); + } +} + + +ATF_TEST_CASE_WITHOUT_HEAD(unknown_option_error__shortblock); +ATF_TEST_CASE_BODY(unknown_option_error__shortblock) +{ + const int argc = 3; + const char* const argv[] = {"progname", "-a", "-bdc", NULL}; + const bool_option flag1('a', "flag1", "Description"); + const bool_option flag2('b', "flag2", "Description"); + const bool_option flag3('c', "flag3", "Description"); + std::vector< const base_option* > options; + options.push_back(&flag1); + options.push_back(&flag2); + options.push_back(&flag3); + + try { + parse(argc, argv, options); + fail("unknown_option_error not raised"); + } catch (const cmdline::unknown_option_error& e) { + ATF_REQUIRE_EQ("-d", e.option()); + } +} + + +ATF_TEST_CASE_WITHOUT_HEAD(unknown_option_error__long); +ATF_TEST_CASE_BODY(unknown_option_error__long) +{ + const int argc = 3; + const char* const argv[] = {"progname", "--flag1=a", "--flag2", NULL}; + const string_option flag1("flag1", "Description", "arg"); + std::vector< const base_option* > options; + options.push_back(&flag1); + + try { + parse(argc, argv, options); + fail("unknown_option_error not raised"); + } catch (const cmdline::unknown_option_error& e) { + ATF_REQUIRE_EQ("--flag2", e.option()); + } +} + + +ATF_TEST_CASE_WITHOUT_HEAD(unknown_plus_option_error); +ATF_TEST_CASE_BODY(unknown_plus_option_error) +{ + const int argc = 2; + const char* const argv[] = {"progname", "-+", NULL}; + const cmdline::options_vector options; + + try { + parse(argc, argv, options); + fail("unknown_option_error not raised"); + } catch (const cmdline::unknown_option_error& e) { + ATF_REQUIRE_EQ("-+", e.option()); + } catch (const cmdline::missing_option_argument_error& e) { + fail("Looks like getopt_long thinks a + option is defined and it " + "even requires an argument"); + } +} + + +ATF_TEST_CASE_WITHOUT_HEAD(option_types); +ATF_TEST_CASE_BODY(option_types) +{ + const int argc = 3; + const char* const argv[] = {"progname", "--flag1=a", "--flag2=one", NULL}; + const string_option flag1("flag1", "The flag1", "arg"); + const mock_option flag2("flag2"); + std::vector< const base_option* > options; + options.push_back(&flag1); + options.push_back(&flag2); + + const parsed_cmdline cmdline = parse(argc, argv, options); + + ATF_REQUIRE(cmdline.has_option("flag1")); + ATF_REQUIRE(cmdline.has_option("flag2")); + ATF_REQUIRE_EQ("a", cmdline.get_option< string_option >("flag1")); + ATF_REQUIRE_EQ(1, cmdline.get_option< mock_option >("flag2")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(option_validation_error); +ATF_TEST_CASE_BODY(option_validation_error) +{ + const int argc = 3; + const char* const argv[] = {"progname", "--flag1=zero", "--flag2=foo", + NULL}; + const mock_option flag1("flag1"); + const mock_option flag2("flag2"); + std::vector< const base_option* > options; + options.push_back(&flag1); + options.push_back(&flag2); + + try { + parse(argc, argv, options); + fail("option_argument_value_error not raised"); + } catch (const cmdline::option_argument_value_error& e) { + ATF_REQUIRE_EQ("--flag2", e.option()); + ATF_REQUIRE_EQ("foo", e.argument()); + } +} + + +ATF_TEST_CASE_WITHOUT_HEAD(silent_errors); +ATF_TEST_CASE_BODY(silent_errors) +{ + const int argc = 2; + const char* const argv[] = {"progname", "-h", NULL}; + cmdline::options_vector options; + + try { + std::pair< int, int > oldfds = mock_stdfds("output.txt"); + try { + parse(argc, argv, options); + } catch (...) { + restore_stdfds(oldfds); + throw; + } + restore_stdfds(oldfds); + fail("unknown_option_error not raised"); + } catch (const cmdline::unknown_option_error& e) { + ATF_REQUIRE_EQ("-h", e.option()); + } + + std::ifstream input("output.txt"); + ATF_REQUIRE(input); + + bool has_output = false; + std::string line; + while (std::getline(input, line).good()) { + std::cout << line << '\n'; + has_output = true; + } + + if (has_output) + fail("getopt_long printed messages on stdout/stderr by itself"); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, progname__no_options); + ATF_ADD_TEST_CASE(tcs, progname__some_options); + ATF_ADD_TEST_CASE(tcs, some_args__no_options); + ATF_ADD_TEST_CASE(tcs, some_args__some_options); + ATF_ADD_TEST_CASE(tcs, some_options__all_known); + ATF_ADD_TEST_CASE(tcs, some_options__multi); + ATF_ADD_TEST_CASE(tcs, subcommands); + ATF_ADD_TEST_CASE(tcs, missing_option_argument_error__short); + ATF_ADD_TEST_CASE(tcs, missing_option_argument_error__shortblock); + ATF_ADD_TEST_CASE(tcs, missing_option_argument_error__long); + ATF_ADD_TEST_CASE(tcs, unknown_option_error__short); + ATF_ADD_TEST_CASE(tcs, unknown_option_error__shortblock); + ATF_ADD_TEST_CASE(tcs, unknown_option_error__long); + ATF_ADD_TEST_CASE(tcs, unknown_plus_option_error); + ATF_ADD_TEST_CASE(tcs, option_types); + ATF_ADD_TEST_CASE(tcs, option_validation_error); + ATF_ADD_TEST_CASE(tcs, silent_errors); +} diff --git a/external/bsd/kyua-cli/dist/utils/cmdline/ui.cpp b/external/bsd/kyua-cli/dist/utils/cmdline/ui.cpp new file mode 100644 index 000000000..a8e1c7e1e --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/cmdline/ui.cpp @@ -0,0 +1,270 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/cmdline/ui.hpp" + +extern "C" { +#include + +#include +} + +#include + +#include "utils/cmdline/globals.hpp" +#include "utils/env.hpp" +#include "utils/format/macros.hpp" +#include "utils/fs/path.hpp" +#include "utils/logging/macros.hpp" +#include "utils/optional.ipp" +#include "utils/text/operations.ipp" +#include "utils/sanity.hpp" +#include "utils/text/table.hpp" + +namespace cmdline = utils::cmdline; +namespace text = utils::text; + +using utils::none; +using utils::optional; + + +/// Destructor for the class. +cmdline::ui::~ui(void) +{ +} + + +/// Writes a line to stderr. +/// +/// The written line is printed as is, without being wrapped to fit within the +/// screen width. +/// +/// \param message The line to print, without the trailing newline character. +/// \param newline Whether to append a newline to the message or not. +void +cmdline::ui::err(const std::string& message, const bool newline) +{ + PRE(message.empty() || message[message.length() - 1] != '\n'); + LI(F("stderr: %s") % message); + if (newline) + std::cerr << message << "\n"; + else { + std::cerr << message; + std::cerr.flush(); + } +} + + +/// Writes a line to stdout. +/// +/// The written line is printed as is, without being wrapped to fit within the +/// screen width. +/// +/// \param message The line to print, without the trailing newline character. +/// \param newline Whether to append a newline to the message or not. +void +cmdline::ui::out(const std::string& message, const bool newline) +{ + PRE(message.empty() || message[message.length() - 1] != '\n'); + LI(F("stdout: %s") % message); + if (newline) + std::cout << message << "\n"; + else { + std::cout << message; + std::cout.flush(); + } +} + + +/// Queries the width of the screen. +/// +/// This information comes first from the COLUMNS environment variable. If not +/// present or invalid, and if the stdout of the current process is connected to +/// a terminal the width is deduced from the terminal itself. Ultimately, if +/// all fails, none is returned. This function shall not raise any errors. +/// +/// Be aware that the results of this query are cached during execution. +/// Subsequent calls to this function will always return the same value even if +/// the terminal size has actually changed. +/// +/// \todo Install a signal handler for SIGWINCH so that we can readjust our +/// knowledge of the terminal width when the user resizes the window. +/// +/// \return The width of the screen if it was possible to determine it, or none +/// otherwise. +optional< std::size_t > +cmdline::ui::screen_width(void) const +{ + static bool done = false; + static optional< std::size_t > width = none; + + if (!done) { + const optional< std::string > columns = utils::getenv("COLUMNS"); + if (columns) { + if (columns.get().length() > 0) { + try { + width = utils::make_optional( + utils::text::to_type< std::size_t >(columns.get())); + } catch (const utils::text::value_error& e) { + LD(F("Ignoring invalid value in COLUMNS variable: %s") % + e.what()); + } + } + } + if (!width) { + struct ::winsize ws; + if (::ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) != -1) + width = optional< std::size_t >(ws.ws_col); + } + + if (width && width.get() >= 80) + width.get() -= 5; + + done = true; + } + + return width; +} + + +/// Writes a line to stdout. +/// +/// The line is wrapped to fit on screen. +/// +/// \param message The line to print, without the trailing newline character. +void +cmdline::ui::out_wrap(const std::string& message) +{ + const optional< std::size_t > max_width = screen_width(); + if (max_width) { + const std::vector< std::string > lines = text::refill( + message, max_width.get()); + for (std::vector< std::string >::const_iterator iter = lines.begin(); + iter != lines.end(); iter++) + out(*iter); + } else + out(message); +} + + +/// Writes a line to stdout with a leading tag. +/// +/// If the line does not fit on the current screen width, the line is broken +/// into pieces and the tag is repeated on every line. +/// +/// \param tag The leading line tag. +/// \param message The message to be printed, without the trailing newline +/// character. +/// \param repeat If true, print the tag on every line; otherwise, indent the +/// text of all lines to match the width of the tag on the first line. +void +cmdline::ui::out_tag_wrap(const std::string& tag, const std::string& message, + const bool repeat) +{ + const optional< std::size_t > max_width = screen_width(); + if (max_width && max_width.get() > tag.length()) { + const std::vector< std::string > lines = text::refill( + message, max_width.get() - tag.length()); + for (std::vector< std::string >::const_iterator iter = lines.begin(); + iter != lines.end(); iter++) { + if (repeat || iter == lines.begin()) + out(F("%s%s") % tag % *iter); + else + out(F("%s%s") % std::string(tag.length(), ' ') % *iter); + } + } else { + out(F("%s%s") % tag % message); + } +} + + +/// Writes a table to stdout. +/// +/// \param table The table to write. +/// \param formatter The table formatter to use to convert the table to a +/// console representation. +/// \param prefix Text to prepend to all the lines of the output table. +void +cmdline::ui::out_table(const text::table& table, + text::table_formatter formatter, + const std::string& prefix) +{ + if (table.empty()) + return; + + const optional< std::size_t > max_width = screen_width(); + if (max_width) + formatter.set_table_width(max_width.get() - prefix.length()); + + const std::vector< std::string > lines = formatter.format(table); + for (std::vector< std::string >::const_iterator iter = lines.begin(); + iter != lines.end(); ++iter) + out(prefix + *iter); +} + + +/// Formats and prints an error message. +/// +/// \param ui_ The user interface object used to print the message. +/// \param message The message to print. Must not end with a dot nor with a +/// newline character. +void +cmdline::print_error(ui* ui_, const std::string& message) +{ + PRE(!message.empty() && message[message.length() - 1] != '.'); + LE(message); + ui_->err(F("%s: E: %s.") % cmdline::progname() % message); +} + + +/// Formats and prints an informational message. +/// +/// \param ui_ The user interface object used to print the message. +/// \param message The message to print. Must not end with a dot nor with a +/// newline character. +void +cmdline::print_info(ui* ui_, const std::string& message) +{ + PRE(!message.empty() && message[message.length() - 1] != '.'); + LI(message); + ui_->err(F("%s: I: %s.") % cmdline::progname() % message); +} + + +/// Formats and prints a warning message. +/// +/// \param ui_ The user interface object used to print the message. +/// \param message The message to print. Must not end with a dot nor with a +/// newline character. +void +cmdline::print_warning(ui* ui_, const std::string& message) +{ + PRE(!message.empty() && message[message.length() - 1] != '.'); + LW(message); + ui_->err(F("%s: W: %s.") % cmdline::progname() % message); +} diff --git a/external/bsd/kyua-cli/dist/utils/cmdline/ui.hpp b/external/bsd/kyua-cli/dist/utils/cmdline/ui.hpp new file mode 100644 index 000000000..6849dfcb7 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/cmdline/ui.hpp @@ -0,0 +1,87 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file utils/cmdline/ui.hpp +/// Abstractions and utilities to write formatted messages to the console. + +#if !defined(UTILS_CMDLINE_UI_HPP) +#define UTILS_CMDLINE_UI_HPP + +#include +#include + +#if defined(__minix) +#include +#endif /* defined(__minix) */ + +#include "utils/optional.hpp" + +namespace utils { + +namespace text { +class table; +class table_formatter; +} // namespace text + +namespace cmdline { + + +/// Interface to interact with the CLI. +/// +/// The main purpose of this class is to substitute direct usages of stdout and +/// stderr. An instance of this class is passed to every command of a CLI, +/// which allows unit testing and validation of the interaction with the user. +/// +/// This class writes directly to stdout and stderr. For testing purposes, see +/// the utils::cmdline::ui_mock class. +class ui { +public: + virtual ~ui(void); + + virtual void err(const std::string&, const bool = true); + virtual void out(const std::string&, const bool = true); + virtual optional< std::size_t > screen_width(void) const; + + void out_wrap(const std::string&); + void out_tag_wrap(const std::string&, const std::string&, + const bool = true); + void out_table(const utils::text::table&, utils::text::table_formatter, + const std::string&); +}; + + +void print_error(ui*, const std::string&); +void print_info(ui*, const std::string&); +void print_warning(ui*, const std::string&); + + +} // namespace cmdline +} // namespace utils + + +#endif // !defined(UTILS_CMDLINE_UI_HPP) diff --git a/external/bsd/kyua-cli/dist/utils/cmdline/ui_mock.cpp b/external/bsd/kyua-cli/dist/utils/cmdline/ui_mock.cpp new file mode 100644 index 000000000..5efd81f86 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/cmdline/ui_mock.cpp @@ -0,0 +1,114 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/cmdline/ui_mock.hpp" + +#include + +#include "utils/optional.ipp" + +using utils::cmdline::ui_mock; +using utils::none; +using utils::optional; + + +/// Constructs a new mock UI. +/// +/// \param screen_width_ The width of the screen to use for testing purposes. +/// Defaults to 0 to prevent uncontrolled wrapping on our tests. +ui_mock::ui_mock(const std::size_t screen_width_) : + _screen_width(screen_width_) +{ +} + + +/// Writes a line to stderr and records it for further inspection. +/// +/// \param message The line to print and record, without the trailing newline +/// character. +/// \param newline Whether to append a newline to the message or not. +void +ui_mock::err(const std::string& message, const bool newline) +{ + if (newline) + std::cerr << message << "\n"; + else { + std::cerr << message << "\n"; + std::cerr.flush(); + } + _err_log.push_back(message); +} + + +/// Writes a line to stdout and records it for further inspection. +/// +/// \param message The line to print and record, without the trailing newline +/// character. +/// \param newline Whether to append a newline to the message or not. +void +ui_mock::out(const std::string& message, const bool newline) +{ + if (newline) + std::cout << message << "\n"; + else { + std::cout << message << "\n"; + std::cout.flush(); + } + _out_log.push_back(message); +} + + +/// Queries the width of the screen. +/// +/// \return Always none, as we do not want to depend on line wrapping in our +/// tests. +optional< std::size_t > +ui_mock::screen_width(void) const +{ + return _screen_width > 0 ? optional< std::size_t >(_screen_width) : none; +} + + +/// Gets all the lines written to stderr. +/// +/// \return The printed lines. +const std::vector< std::string >& +ui_mock::err_log(void) const +{ + return _err_log; +} + + +/// Gets all the lines written to stdout. +/// +/// \return The printed lines. +const std::vector< std::string >& +ui_mock::out_log(void) const +{ + return _out_log; +} diff --git a/external/bsd/kyua-cli/dist/utils/cmdline/ui_mock.hpp b/external/bsd/kyua-cli/dist/utils/cmdline/ui_mock.hpp new file mode 100644 index 000000000..ef62e7670 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/cmdline/ui_mock.hpp @@ -0,0 +1,78 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file utils/cmdline/ui_mock.hpp +/// Provides the utils::cmdline::ui_mock class. +/// +/// This file is only supposed to be included from test program, never from +/// production code. + +#if !defined(UTILS_CMDLINE_UI_MOCK_HPP) +#define UTILS_CMDLINE_UI_MOCK_HPP + +#include +#include +#include + +#include "utils/cmdline/ui.hpp" + +namespace utils { +namespace cmdline { + + +/// Testable interface to interact with the CLI. +/// +/// This class records all writes to stdout and stderr to allow further +/// inspection for testing purposes. +class ui_mock : public ui { + /// Fake width of the screen; if 0, represents none. + std::size_t _screen_width; + + /// Messages sent to stderr. + std::vector< std::string > _err_log; + + /// Messages sent to stdout. + std::vector< std::string > _out_log; + +public: + ui_mock(const std::size_t = 0); + + void err(const std::string&, const bool = true); + void out(const std::string&, const bool = true); + optional< std::size_t > screen_width(void) const; + + const std::vector< std::string >& err_log(void) const; + const std::vector< std::string >& out_log(void) const; +}; + + +} // namespace cmdline +} // namespace utils + + +#endif // !defined(UTILS_CMDLINE_UI_MOCK_HPP) diff --git a/external/bsd/kyua-cli/dist/utils/cmdline/ui_test.cpp b/external/bsd/kyua-cli/dist/utils/cmdline/ui_test.cpp new file mode 100644 index 000000000..3c50ce277 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/cmdline/ui_test.cpp @@ -0,0 +1,392 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/cmdline/ui.hpp" + +extern "C" { +#include + +#include +#include +} + +#include +#include + +#include + +#include "utils/cmdline/globals.hpp" +#include "utils/cmdline/ui_mock.hpp" +#include "utils/env.hpp" +#include "utils/format/macros.hpp" +#include "utils/optional.ipp" +#include "utils/text/table.hpp" + +namespace cmdline = utils::cmdline; +namespace text = utils::text; + +using utils::none; +using utils::optional; + + +namespace { + + +/// Reopens stdout as a tty and returns its width. +/// +/// \return The width of the tty in columns. If the width is wider than 80, the +/// result is 5 columns narrower to match the screen_width() algorithm. +static std::size_t +reopen_stdout(void) +{ + const int fd = ::open("/dev/tty", O_WRONLY); + if (fd == -1) + ATF_SKIP(F("Cannot open tty for test: %s") % ::strerror(errno)); + struct ::winsize ws; + if (::ioctl(fd, TIOCGWINSZ, &ws) == -1) + ATF_SKIP(F("Cannot determine size of tty: %s") % ::strerror(errno)); + + if (fd != STDOUT_FILENO) { + if (::dup2(fd, STDOUT_FILENO) == -1) + ATF_SKIP(F("Failed to redirect stdout: %s") % ::strerror(errno)); + ::close(fd); + } + + return ws.ws_col >= 80 ? ws.ws_col - 5 : ws.ws_col; +} + + +} // anonymous namespace + + +ATF_TEST_CASE_WITHOUT_HEAD(ui__screen_width__columns_set__no_tty); +ATF_TEST_CASE_BODY(ui__screen_width__columns_set__no_tty) +{ + utils::setenv("COLUMNS", "4321"); + ::close(STDOUT_FILENO); + + cmdline::ui ui; + ATF_REQUIRE_EQ(4321 - 5, ui.screen_width().get()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(ui__screen_width__columns_set__tty); +ATF_TEST_CASE_BODY(ui__screen_width__columns_set__tty) +{ + utils::setenv("COLUMNS", "4321"); + (void)reopen_stdout(); + + cmdline::ui ui; + ATF_REQUIRE_EQ(4321 - 5, ui.screen_width().get()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(ui__screen_width__columns_empty__no_tty); +ATF_TEST_CASE_BODY(ui__screen_width__columns_empty__no_tty) +{ + utils::setenv("COLUMNS", ""); + ::close(STDOUT_FILENO); + + cmdline::ui ui; + ATF_REQUIRE(!ui.screen_width()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(ui__screen_width__columns_empty__tty); +ATF_TEST_CASE_BODY(ui__screen_width__columns_empty__tty) +{ + utils::setenv("COLUMNS", ""); + const std::size_t columns = reopen_stdout(); + + cmdline::ui ui; + ATF_REQUIRE_EQ(columns, ui.screen_width().get()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(ui__screen_width__columns_invalid__no_tty); +ATF_TEST_CASE_BODY(ui__screen_width__columns_invalid__no_tty) +{ + utils::setenv("COLUMNS", "foo bar"); + ::close(STDOUT_FILENO); + + cmdline::ui ui; + ATF_REQUIRE(!ui.screen_width()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(ui__screen_width__columns_invalid__tty); +ATF_TEST_CASE_BODY(ui__screen_width__columns_invalid__tty) +{ + utils::setenv("COLUMNS", "foo bar"); + const std::size_t columns = reopen_stdout(); + + cmdline::ui ui; + ATF_REQUIRE_EQ(columns, ui.screen_width().get()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(ui__screen_width__tty_is_file); +ATF_TEST_CASE_BODY(ui__screen_width__tty_is_file) +{ + utils::unsetenv("COLUMNS"); + const int fd = ::open("test.txt", O_WRONLY | O_CREAT | O_TRUNC, 0755); + ATF_REQUIRE(fd != -1); + if (fd != STDOUT_FILENO) { + ATF_REQUIRE(::dup2(fd, STDOUT_FILENO) != -1); + ::close(fd); + } + + cmdline::ui ui; + ATF_REQUIRE(!ui.screen_width()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(ui__screen_width__cached); +ATF_TEST_CASE_BODY(ui__screen_width__cached) +{ + cmdline::ui ui; + + utils::setenv("COLUMNS", "100"); + ATF_REQUIRE_EQ(100 - 5, ui.screen_width().get()); + + utils::setenv("COLUMNS", "80"); + ATF_REQUIRE_EQ(100 - 5, ui.screen_width().get()); + + utils::unsetenv("COLUMNS"); + ATF_REQUIRE_EQ(100 - 5, ui.screen_width().get()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(ui__err); +ATF_TEST_CASE_BODY(ui__err) +{ + cmdline::ui_mock ui(10); // Keep shorter than message. + ui.err("This is a short message"); + ATF_REQUIRE_EQ(1, ui.err_log().size()); + ATF_REQUIRE_EQ("This is a short message", ui.err_log()[0]); + ATF_REQUIRE(ui.out_log().empty()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(ui__out); +ATF_TEST_CASE_BODY(ui__out) +{ + cmdline::ui_mock ui(10); // Keep shorter than message. + ui.out("This is a short message"); + ATF_REQUIRE(ui.err_log().empty()); + ATF_REQUIRE_EQ(1, ui.out_log().size()); + ATF_REQUIRE_EQ("This is a short message", ui.out_log()[0]); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(ui__out_wrap__no_refill); +ATF_TEST_CASE_BODY(ui__out_wrap__no_refill) +{ + cmdline::ui_mock ui(100); + ui.out_wrap("This is a short message"); + ATF_REQUIRE(ui.err_log().empty()); + ATF_REQUIRE_EQ(1, ui.out_log().size()); + ATF_REQUIRE_EQ("This is a short message", ui.out_log()[0]); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(ui__out_wrap__refill); +ATF_TEST_CASE_BODY(ui__out_wrap__refill) +{ + cmdline::ui_mock ui(16); + ui.out_wrap("This is a short message"); + ATF_REQUIRE(ui.err_log().empty()); + ATF_REQUIRE_EQ(2, ui.out_log().size()); + ATF_REQUIRE_EQ("This is a short", ui.out_log()[0]); + ATF_REQUIRE_EQ("message", ui.out_log()[1]); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(ui__out_tag_wrap__no_refill); +ATF_TEST_CASE_BODY(ui__out_tag_wrap__no_refill) +{ + cmdline::ui_mock ui(100); + ui.out_tag_wrap("Some long tag: ", "This is a short message"); + ATF_REQUIRE(ui.err_log().empty()); + ATF_REQUIRE_EQ(1, ui.out_log().size()); + ATF_REQUIRE_EQ("Some long tag: This is a short message", ui.out_log()[0]); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(ui__out_tag_wrap__refill__repeat); +ATF_TEST_CASE_BODY(ui__out_tag_wrap__refill__repeat) +{ + cmdline::ui_mock ui(32); + ui.out_tag_wrap("Some long tag: ", "This is a short message"); + ATF_REQUIRE(ui.err_log().empty()); + ATF_REQUIRE_EQ(2, ui.out_log().size()); + ATF_REQUIRE_EQ("Some long tag: This is a short", ui.out_log()[0]); + ATF_REQUIRE_EQ("Some long tag: message", ui.out_log()[1]); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(ui__out_tag_wrap__refill__no_repeat); +ATF_TEST_CASE_BODY(ui__out_tag_wrap__refill__no_repeat) +{ + cmdline::ui_mock ui(32); + ui.out_tag_wrap("Some long tag: ", "This is a short message", false); + ATF_REQUIRE(ui.err_log().empty()); + ATF_REQUIRE_EQ(2, ui.out_log().size()); + ATF_REQUIRE_EQ("Some long tag: This is a short", ui.out_log()[0]); + ATF_REQUIRE_EQ(" message", ui.out_log()[1]); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(ui__out_tag_wrap__tag_too_long); +ATF_TEST_CASE_BODY(ui__out_tag_wrap__tag_too_long) +{ + cmdline::ui_mock ui(5); + ui.out_tag_wrap("Some long tag: ", "This is a short message"); + ATF_REQUIRE(ui.err_log().empty()); + ATF_REQUIRE_EQ(1, ui.out_log().size()); + ATF_REQUIRE_EQ("Some long tag: This is a short message", ui.out_log()[0]); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(ui__out_table__empty); +ATF_TEST_CASE_BODY(ui__out_table__empty) +{ + const text::table table(3); + + text::table_formatter formatter; + formatter.set_separator(" | "); + formatter.set_column_width(0, 23); + formatter.set_column_width(1, text::table_formatter::width_refill); + + cmdline::ui_mock ui(52); + ui.out_table(table, formatter, " "); + ATF_REQUIRE(ui.out_log().empty()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(ui__out_table__not_empty); +ATF_TEST_CASE_BODY(ui__out_table__not_empty) +{ + text::table table(3); + { + text::table_row row; + row.push_back("First"); + row.push_back("Second"); + row.push_back("Third"); + table.add_row(row); + } + { + text::table_row row; + row.push_back("Fourth with some text"); + row.push_back("Fifth with some more text"); + row.push_back("Sixth foo"); + table.add_row(row); + } + + text::table_formatter formatter; + formatter.set_separator(" | "); + formatter.set_column_width(0, 23); + formatter.set_column_width(1, text::table_formatter::width_refill); + + cmdline::ui_mock ui(52); + ui.out_table(table, formatter, " "); + ATF_REQUIRE_EQ(4, ui.out_log().size()); + ATF_REQUIRE_EQ(" First | Second | Third", + ui.out_log()[0]); + ATF_REQUIRE_EQ(" Fourth with some text | Fifth with | Sixth foo", + ui.out_log()[1]); + ATF_REQUIRE_EQ(" | some more | ", + ui.out_log()[2]); + ATF_REQUIRE_EQ(" | text | ", + ui.out_log()[3]); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(print_error); +ATF_TEST_CASE_BODY(print_error) +{ + cmdline::init("error-program"); + cmdline::ui_mock ui; + cmdline::print_error(&ui, "The error"); + ATF_REQUIRE(ui.out_log().empty()); + ATF_REQUIRE_EQ(1, ui.err_log().size()); + ATF_REQUIRE_EQ("error-program: E: The error.", ui.err_log()[0]); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(print_info); +ATF_TEST_CASE_BODY(print_info) +{ + cmdline::init("info-program"); + cmdline::ui_mock ui; + cmdline::print_info(&ui, "The info"); + ATF_REQUIRE(ui.out_log().empty()); + ATF_REQUIRE_EQ(1, ui.err_log().size()); + ATF_REQUIRE_EQ("info-program: I: The info.", ui.err_log()[0]); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(print_warning); +ATF_TEST_CASE_BODY(print_warning) +{ + cmdline::init("warning-program"); + cmdline::ui_mock ui; + cmdline::print_warning(&ui, "The warning"); + ATF_REQUIRE(ui.out_log().empty()); + ATF_REQUIRE_EQ(1, ui.err_log().size()); + ATF_REQUIRE_EQ("warning-program: W: The warning.", ui.err_log()[0]); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, ui__screen_width__columns_set__no_tty); + ATF_ADD_TEST_CASE(tcs, ui__screen_width__columns_set__tty); + ATF_ADD_TEST_CASE(tcs, ui__screen_width__columns_empty__no_tty); + ATF_ADD_TEST_CASE(tcs, ui__screen_width__columns_empty__tty); + ATF_ADD_TEST_CASE(tcs, ui__screen_width__columns_invalid__no_tty); + ATF_ADD_TEST_CASE(tcs, ui__screen_width__columns_invalid__tty); + ATF_ADD_TEST_CASE(tcs, ui__screen_width__tty_is_file); + ATF_ADD_TEST_CASE(tcs, ui__screen_width__cached); + + ATF_ADD_TEST_CASE(tcs, ui__err); + ATF_ADD_TEST_CASE(tcs, ui__out); + + ATF_ADD_TEST_CASE(tcs, ui__out_wrap__no_refill); + ATF_ADD_TEST_CASE(tcs, ui__out_wrap__refill); + ATF_ADD_TEST_CASE(tcs, ui__out_tag_wrap__no_refill); + ATF_ADD_TEST_CASE(tcs, ui__out_tag_wrap__refill__repeat); + ATF_ADD_TEST_CASE(tcs, ui__out_tag_wrap__refill__no_repeat); + ATF_ADD_TEST_CASE(tcs, ui__out_tag_wrap__tag_too_long); + ATF_ADD_TEST_CASE(tcs, ui__out_table__empty); + ATF_ADD_TEST_CASE(tcs, ui__out_table__not_empty); + + ATF_ADD_TEST_CASE(tcs, print_error); + ATF_ADD_TEST_CASE(tcs, print_info); + ATF_ADD_TEST_CASE(tcs, print_warning); +} diff --git a/external/bsd/kyua-cli/dist/utils/config/Kyuafile b/external/bsd/kyua-cli/dist/utils/config/Kyuafile new file mode 100644 index 000000000..c607a1757 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/config/Kyuafile @@ -0,0 +1,10 @@ +syntax(2) + +test_suite("kyua") + +atf_test_program{name="exceptions_test"} +atf_test_program{name="keys_test"} +atf_test_program{name="lua_module_test"} +atf_test_program{name="nodes_test"} +atf_test_program{name="parser_test"} +atf_test_program{name="tree_test"} diff --git a/external/bsd/kyua-cli/dist/utils/config/exceptions.cpp b/external/bsd/kyua-cli/dist/utils/config/exceptions.cpp new file mode 100644 index 000000000..281966815 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/config/exceptions.cpp @@ -0,0 +1,113 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/config/exceptions.hpp" + +#include "utils/config/tree.ipp" +#include "utils/format/macros.hpp" + +namespace config = utils::config; + + +/// Constructs a new error with a plain-text message. +/// +/// \param message The plain-text error message. +config::error::error(const std::string& message) : + std::runtime_error(message) +{ +} + + +/// Destructor for the error. +config::error::~error(void) throw() +{ +} + + +/// Constructs a new error with a plain-text message. +/// +/// \param message The plain-text error message. +config::invalid_key_error::invalid_key_error(const std::string& message) : + error(message) +{ +} + + +/// Destructor for the error. +config::invalid_key_error::~invalid_key_error(void) throw() +{ +} + + +/// Constructs a new error with a plain-text message. +/// +/// \param message The plain-text error message. +config::syntax_error::syntax_error(const std::string& message) : + error(message) +{ +} + + +/// Destructor for the error. +config::syntax_error::~syntax_error(void) throw() +{ +} + + +/// Constructs a new error with a plain-text message. +/// +/// \param key The unknown key. +/// \param format The message for the error. Must include a single "%s" +/// placedholder, which will be replaced by the key itself. +config::unknown_key_error::unknown_key_error(const detail::tree_key& key, + const std::string& format) : + error(F(format.empty() ? "Unknown configuration property '%s'" : format) % + detail::flatten_key(key)) +{ +} + + +/// Destructor for the error. +config::unknown_key_error::~unknown_key_error(void) throw() +{ +} + + +/// Constructs a new error with a plain-text message. +/// +/// \param message The plain-text error message. +config::value_error::value_error(const std::string& message) : + error(message) +{ +} + + +/// Destructor for the error. +config::value_error::~value_error(void) throw() +{ +} diff --git a/external/bsd/kyua-cli/dist/utils/config/exceptions.hpp b/external/bsd/kyua-cli/dist/utils/config/exceptions.hpp new file mode 100644 index 000000000..25a928153 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/config/exceptions.hpp @@ -0,0 +1,88 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file utils/config/exceptions.hpp +/// Exception types raised by the config module. + +#if !defined(UTILS_CONFIG_EXCEPTIONS_HPP) +#define UTILS_CONFIG_EXCEPTIONS_HPP + +#include + +#include "utils/config/tree.hpp" + +namespace utils { +namespace config { + + +/// Base exceptions for config errors. +class error : public std::runtime_error { +public: + explicit error(const std::string&); + ~error(void) throw(); +}; + + +/// Exception denoting that a key was not found within a tree. +class invalid_key_error : public error { +public: + explicit invalid_key_error(const std::string&); + ~invalid_key_error(void) throw(); +}; + + +/// Exception denoting that a configuration file is invalid. +class syntax_error : public error { +public: + explicit syntax_error(const std::string&); + ~syntax_error(void) throw(); +}; + + +/// Exception denoting that a key was not found within a tree. +class unknown_key_error : public error { +public: + explicit unknown_key_error(const detail::tree_key&, + const std::string& = ""); + ~unknown_key_error(void) throw(); +}; + + +/// Exception denoting that a value was invalid. +class value_error : public error { +public: + explicit value_error(const std::string&); + ~value_error(void) throw(); +}; + + +} // namespace config +} // namespace utils + + +#endif // !defined(UTILS_CONFIG_EXCEPTIONS_HPP) diff --git a/external/bsd/kyua-cli/dist/utils/config/exceptions_test.cpp b/external/bsd/kyua-cli/dist/utils/config/exceptions_test.cpp new file mode 100644 index 000000000..28290b329 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/config/exceptions_test.cpp @@ -0,0 +1,106 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/config/exceptions.hpp" + +#include + +#include + +#include "utils/config/tree.ipp" + +namespace config = utils::config; +namespace detail = utils::config::detail; + + +ATF_TEST_CASE_WITHOUT_HEAD(error); +ATF_TEST_CASE_BODY(error) +{ + const config::error e("Some text"); + ATF_REQUIRE(std::strcmp("Some text", e.what()) == 0); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(invalid_key_error); +ATF_TEST_CASE_BODY(invalid_key_error) +{ + const config::invalid_key_error e("Some text"); + ATF_REQUIRE(std::strcmp("Some text", e.what()) == 0); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(syntax_error); +ATF_TEST_CASE_BODY(syntax_error) +{ + const config::syntax_error e("Some text"); + ATF_REQUIRE(std::strcmp("Some text", e.what()) == 0); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(unknown_key_error__default_message); +ATF_TEST_CASE_BODY(unknown_key_error__default_message) +{ + detail::tree_key key; + key.push_back("1"); + key.push_back("two"); + + const config::unknown_key_error e(key); + ATF_REQUIRE(std::strcmp("Unknown configuration property '1.two'", + e.what()) == 0); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(unknown_key_error__custom_message); +ATF_TEST_CASE_BODY(unknown_key_error__custom_message) +{ + detail::tree_key key; + key.push_back("1"); + key.push_back("two"); + + const config::unknown_key_error e(key, "The test '%s' string"); + ATF_REQUIRE(std::strcmp("The test '1.two' string", e.what()) == 0); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(value_error); +ATF_TEST_CASE_BODY(value_error) +{ + const config::value_error e("Some text"); + ATF_REQUIRE(std::strcmp("Some text", e.what()) == 0); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, error); + ATF_ADD_TEST_CASE(tcs, invalid_key_error); + ATF_ADD_TEST_CASE(tcs, syntax_error); + ATF_ADD_TEST_CASE(tcs, unknown_key_error__default_message); + ATF_ADD_TEST_CASE(tcs, unknown_key_error__custom_message); + ATF_ADD_TEST_CASE(tcs, value_error); +} diff --git a/external/bsd/kyua-cli/dist/utils/config/keys.cpp b/external/bsd/kyua-cli/dist/utils/config/keys.cpp new file mode 100644 index 000000000..592538671 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/config/keys.cpp @@ -0,0 +1,68 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/config/tree.ipp" + +#include "utils/config/exceptions.hpp" +#include "utils/format/macros.hpp" +#include "utils/text/operations.hpp" + +namespace config = utils::config; +namespace text = utils::text; + + +/// Converts a key to its textual representation. +/// +/// \param key The key to convert. +std::string +utils::config::detail::flatten_key(const tree_key& key) +{ + PRE(!key.empty()); + return text::join(key, "."); +} + + +/// Parses and validates a textual key. +/// +/// \param str The key to process in dotted notation. +/// +/// \return The tokenized key if valid. +/// +/// \throw invalid_key_error If the input key is empty or invalid for any other +/// reason. Invalid does NOT mean unknown though. +utils::config::detail::tree_key +utils::config::detail::parse_key(const std::string& str) +{ + const tree_key key = text::split(str, '.'); + if (key.empty()) + throw invalid_key_error("Empty key"); + for (tree_key::const_iterator iter = key.begin(); iter != key.end(); iter++) + if ((*iter).empty()) + throw invalid_key_error(F("Empty component in key '%s'") % str); + return key; +} diff --git a/external/bsd/kyua-cli/dist/utils/config/keys.hpp b/external/bsd/kyua-cli/dist/utils/config/keys.hpp new file mode 100644 index 000000000..50a3b5443 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/config/keys.hpp @@ -0,0 +1,55 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file utils/config/keys.hpp +/// Representation and manipulation of tree keys. + +#if !defined(UTILS_CONFIG_KEYS_HPP) +#define UTILS_CONFIG_KEYS_HPP + +#include +#include + +namespace utils { +namespace config { +namespace detail { + + +/// Representation of a valid, tokenized key. +typedef std::vector< std::string > tree_key; + + +std::string flatten_key(const tree_key&); +tree_key parse_key(const std::string&); + + +} // namespace detail +} // namespace config +} // namespace utils + +#endif // !defined(UTILS_CONFIG_KEYS_HPP) diff --git a/external/bsd/kyua-cli/dist/utils/config/keys_test.cpp b/external/bsd/kyua-cli/dist/utils/config/keys_test.cpp new file mode 100644 index 000000000..a73726546 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/config/keys_test.cpp @@ -0,0 +1,114 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/config/keys.hpp" + +#include + +#include "utils/config/exceptions.hpp" + +namespace config = utils::config; + + +ATF_TEST_CASE_WITHOUT_HEAD(flatten_key__one); +ATF_TEST_CASE_BODY(flatten_key__one) +{ + config::detail::tree_key key; + key.push_back("foo"); + ATF_REQUIRE_EQ("foo", config::detail::flatten_key(key)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(flatten_key__many); +ATF_TEST_CASE_BODY(flatten_key__many) +{ + config::detail::tree_key key; + key.push_back("foo"); + key.push_back("1"); + key.push_back("bar"); + ATF_REQUIRE_EQ("foo.1.bar", config::detail::flatten_key(key)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(parse_key__one); +ATF_TEST_CASE_BODY(parse_key__one) +{ + config::detail::tree_key exp_key; + exp_key.push_back("one"); + ATF_REQUIRE(exp_key == config::detail::parse_key("one")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(parse_key__many); +ATF_TEST_CASE_BODY(parse_key__many) +{ + config::detail::tree_key exp_key; + exp_key.push_back("one"); + exp_key.push_back("2"); + exp_key.push_back("foo"); + ATF_REQUIRE(exp_key == config::detail::parse_key("one.2.foo")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(parse_key__empty_key); +ATF_TEST_CASE_BODY(parse_key__empty_key) +{ + ATF_REQUIRE_THROW_RE(config::invalid_key_error, + "Empty key", + config::detail::parse_key("")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(parse_key__empty_component); +ATF_TEST_CASE_BODY(parse_key__empty_component) +{ + ATF_REQUIRE_THROW_RE(config::invalid_key_error, + "Empty component in key '.'", + config::detail::parse_key(".")); + ATF_REQUIRE_THROW_RE(config::invalid_key_error, + "Empty component in key 'a.'", + config::detail::parse_key("a.")); + ATF_REQUIRE_THROW_RE(config::invalid_key_error, + "Empty component in key '.b'", + config::detail::parse_key(".b")); + ATF_REQUIRE_THROW_RE(config::invalid_key_error, + "Empty component in key 'a..b'", + config::detail::parse_key("a..b")); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, flatten_key__one); + ATF_ADD_TEST_CASE(tcs, flatten_key__many); + + ATF_ADD_TEST_CASE(tcs, parse_key__one); + ATF_ADD_TEST_CASE(tcs, parse_key__many); + ATF_ADD_TEST_CASE(tcs, parse_key__empty_key); + ATF_ADD_TEST_CASE(tcs, parse_key__empty_component); +} diff --git a/external/bsd/kyua-cli/dist/utils/config/lua_module.cpp b/external/bsd/kyua-cli/dist/utils/config/lua_module.cpp new file mode 100644 index 000000000..1a12bdb92 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/config/lua_module.cpp @@ -0,0 +1,273 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/config/lua_module.hpp" + +#include +#include + +#include "utils/config/exceptions.hpp" +#include "utils/config/tree.ipp" + +namespace config = utils::config; + + +namespace { + + +/// Gets the tree singleton stored in the Lua state. +/// +/// \param state The Lua state. The metadata of _G must contain a key named +/// "tree" with a pointer to the singleton. +/// +/// \return A reference to the tree associated with the Lua state. +/// +/// \throw syntax_error If the tree cannot be located. +config::tree& +get_global_tree(lutok::state& state) +{ + lutok::stack_cleaner cleaner(state); + + if (!state.get_metafield(lutok::globals_index, "tree")) + throw config::syntax_error("Cannot find tree singleton; global state " + "corrupted?"); + return **state.to_userdata< config::tree* >(); +} + + +/// Gets a fully-qualified tree key from the state. +/// +/// \param state The Lua state. +/// \param table_index An index to the Lua stack pointing to the table being +/// accessed. If this table contains a tree_key metadata property, this is +/// considered to be the prefix of the tree key. +/// \param field_index An index to the Lua stack pointing to the entry +/// containing the name of the field being indexed. +/// +/// \return A dotted key. +/// +/// \throw invalid_key_error If the name of the key is invalid. +static std::string +get_tree_key(lutok::state& state, const int table_index, const int field_index) +{ + PRE(state.is_string(field_index)); + const std::string field = state.to_string(field_index); + if (!field.empty() && field[0] == '_') + throw config::invalid_key_error( + F("Configuration key cannot have an underscore as a prefix; " + "found %s") % field); + + std::string tree_key; + if (state.get_metafield(table_index, "tree_key")) { + tree_key = state.to_string(-1) + "." + state.to_string(field_index - 1); + state.pop(1); + } else + tree_key = state.to_string(field_index); + return tree_key; +} + + +static int redirect_newindex(lutok::state&); +static int redirect_index(lutok::state&); + + +/// Creates a table for a new configuration inner node. +/// +/// \post state(-1) Contains the new table. +/// +/// \param state The Lua state in which to push the table. +/// \param tree_key The key to which the new table corresponds. +static void +new_table_for_key(lutok::state& state, const std::string& tree_key) +{ + state.new_table(); + { + state.new_table(); + { + state.push_string("__index"); + state.push_cxx_function(redirect_index); + state.set_table(-3); + + state.push_string("__newindex"); + state.push_cxx_function(redirect_newindex); + state.set_table(-3); + + state.push_string("tree_key"); + state.push_string(tree_key); + state.set_table(-3); + } + state.set_metatable(-2); + } +} + + +/// Sets the value of an configuration node. +/// +/// \pre state(-3) The table to index. If this is not _G, then the table +/// metadata must contain a tree_key property describing the path to +/// current level. +/// \pre state(-2) The field to index into the table. Must be a string. +/// \pre state(-1) The value to set the indexed table field to. +/// +/// \param state The Lua state in which to operate. +/// +/// \return The number of result values on the Lua stack; always 0. +/// +/// \throw invalid_key_error If the provided key is invalid. +/// \throw unknown_key_error If the key cannot be located. +/// \throw value_error If the value has an unsupported type or cannot be +/// set on the key, or if the input table or index are invalid. +static int +redirect_newindex(lutok::state& state) +{ + if (!state.is_table(-3)) + throw config::value_error("Indexed object is not a table"); + if (!state.is_string(-2)) + throw config::value_error("Invalid field in configuration object " + "reference; must be a string"); + + const std::string dotted_key = get_tree_key(state, -3, -2); + try { + config::tree& tree = get_global_tree(state); + tree.set_lua(dotted_key, state, -1); + } catch (const config::value_error& e) { + throw config::value_error(F("Invalid value for key '%s' (%s)") % + dotted_key % e.what()); + } + + // Now really set the key in the Lua table, but prevent direct accesses from + // the user by prefixing it. We do this to ensure that re-setting the same + // key of the tree results in a call to __newindex instead of __index. + state.push_string("_" + state.to_string(-2)); + state.push_value(-2); + state.raw_set(-5); + + return 0; +} + + +/// Indexes a configuration node. +/// +/// \pre state(-3) The table to index. If this is not _G, then the table +/// metadata must contain a tree_key property describing the path to +/// current level. If the field does not exist, a new table is created. +/// \pre state(-1) The field to index into the table. Must be a string. +/// +/// \param state The Lua state in which to operate. +/// +/// \return The number of result values on the Lua stack; always 1. +/// +/// \throw value_error If the input table or index are invalid. +static int +redirect_index(lutok::state& state) +{ + if (!state.is_table(-2)) + throw config::value_error("Indexed object is not a table"); + if (!state.is_string(-1)) + throw config::value_error("Invalid field in configuration object " + "reference; must be a string"); + + // Query if the key has already been set by a call to redirect_newindex. + state.push_string("_" + state.to_string(-1)); + state.raw_get(-3); + if (!state.is_nil(-1)) + return 1; + state.pop(1); + + state.push_value(-1); // Duplicate the field name. + state.raw_get(-3); // Get table[field] to see if it's defined. + if (state.is_nil(-1)) { + state.pop(1); + + // The stack is now the same as when we entered the function, but we + // know that the field is undefined and thus have to create a new + // configuration table. + INV(state.is_table(-2)); + INV(state.is_string(-1)); + + const config::tree& tree = get_global_tree(state); + const std::string tree_key = get_tree_key(state, -2, -1); + if (tree.is_set(tree_key)) { + // Publish the pre-recorded value in the tree to the Lua state, + // instead of considering this table key a new inner node. + tree.push_lua(tree_key, state); + } else { + state.push_string("_" + state.to_string(-1)); + state.insert(-2); + state.pop(1); + + new_table_for_key(state, tree_key); + + // Duplicate the newly created table and place it deep in the stack + // so that the raw_set below leaves us with the return value of this + // function at the top of the stack. + state.push_value(-1); + state.insert(-4); + + state.raw_set(-3); + state.pop(1); + } + } + return 1; +} + + +} // anonymous namespace + + +/// Install wrappers for globals to set values in the configuration tree. +/// +/// This function installs wrappers to capture all accesses to global variables. +/// Such wrappers redirect the reads and writes to the out_tree, which is the +/// entity that defines what configuration variables exist. +/// +/// \param state The Lua state into which to install the wrappers. +/// \param out_tree The tree with the layout definition and where the +/// configuration settings will be collected. +void +config::redirect(lutok::state& state, tree& out_tree) +{ + lutok::stack_cleaner cleaner(state); + + state.new_table(); + { + state.push_string("__index"); + state.push_cxx_function(redirect_index); + state.set_table(-3); + + state.push_string("__newindex"); + state.push_cxx_function(redirect_newindex); + state.set_table(-3); + + state.push_string("tree"); + config::tree** tree = state.new_userdata< config::tree* >(); + *tree = &out_tree; + state.set_table(-3); + } + state.set_metatable(lutok::globals_index); +} diff --git a/external/bsd/kyua-cli/dist/utils/config/lua_module.hpp b/external/bsd/kyua-cli/dist/utils/config/lua_module.hpp new file mode 100644 index 000000000..5950e535c --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/config/lua_module.hpp @@ -0,0 +1,52 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file utils/config/lua_module.hpp +/// Bindings to expose a configuration tree to Lua. + +#if !defined(UTILS_CONFIG_LUA_MODULE_HPP) +#define UTILS_CONFIG_LUA_MODULE_HPP + +#include + +#include "lutok/state.hpp" + +namespace utils { +namespace config { + + +class tree; + + +void redirect(lutok::state&, tree&); + + +} // namespace config +} // namespace utils + +#endif // !defined(UTILS_CONFIG_LUA_MODULE_HPP) diff --git a/external/bsd/kyua-cli/dist/utils/config/lua_module_test.cpp b/external/bsd/kyua-cli/dist/utils/config/lua_module_test.cpp new file mode 100644 index 000000000..d56a8bcc6 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/config/lua_module_test.cpp @@ -0,0 +1,441 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/config/lua_module.hpp" + +#include + +#include +#include +#include + +#include "utils/config/tree.ipp" +#include "utils/defs.hpp" + +namespace config = utils::config; + + +namespace { + + +/// Non-native type to use as a leaf node. +struct custom_type { + /// The value recorded in the object. + int value; + + /// Constructs a new object. + /// + /// \param value_ The value to store in the object. + explicit custom_type(const int value_) : + value(value_) + { + } +}; + + +/// Custom implementation of a node type for testing purposes. +class custom_node : public config::typed_leaf_node< custom_type > { +public: + /// Copies the node. + /// + /// \return A dynamically-allocated node. + virtual base_node* + deep_copy(void) const + { + std::auto_ptr< custom_node > new_node(new custom_node()); + new_node->_value = _value; + return new_node.release(); + } + + /// Pushes the node's value onto the Lua stack. + /// + /// \param state The Lua state onto which to push the value. + void + push_lua(lutok::state& state) const + { + state.push_integer(value().value * 5); + } + + /// Sets the value of the node from an entry in the Lua stack. + /// + /// \param state The Lua state from which to get the value. + /// \param value_index The stack index in which the value resides. + void + set_lua(lutok::state& state, const int value_index) + { + ATF_REQUIRE(state.is_number(value_index)); + set(custom_type(state.to_integer(value_index) * 2)); + } + + /// Sets the value of the node from a raw string representation. + /// + /// \post The test case is marked as failed, as this function is not + /// supposed to be invoked by the lua_module code. + /// + /// \param unused_raw_value The value to set the node to. + void + set_string(const std::string& UTILS_UNUSED_PARAM(raw_value)) + { + ATF_FAIL("Should not be used"); + } + + /// Converts the contents of the node to a string. + /// + /// \post The test case is marked as failed, as this function is not + /// supposed to be invoked by the lua_module code. + /// + /// \return Nothing. + std::string + to_string(void) const + { + ATF_FAIL("Should not be used"); + } +}; + + +} // anonymous namespace + + +ATF_TEST_CASE_WITHOUT_HEAD(top__valid_types); +ATF_TEST_CASE_BODY(top__valid_types) +{ + config::tree tree; + tree.define< config::bool_node >("top_boolean"); + tree.define< config::int_node >("top_integer"); + tree.define< config::string_node >("top_string"); + + { + lutok::state state; + config::redirect(state, tree); + lutok::do_string(state, + "top_boolean = true\n" + "top_integer = 12345\n" + "top_string = 'a foo'\n"); + } + + ATF_REQUIRE_EQ(true, tree.lookup< config::bool_node >("top_boolean")); + ATF_REQUIRE_EQ(12345, tree.lookup< config::int_node >("top_integer")); + ATF_REQUIRE_EQ("a foo", tree.lookup< config::string_node >("top_string")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(top__reuse); +ATF_TEST_CASE_BODY(top__reuse) +{ + config::tree tree; + tree.define< config::int_node >("first"); + tree.define< config::int_node >("second"); + + { + lutok::state state; + config::redirect(state, tree); + lutok::do_string(state, "first = 100; second = first * 2"); + } + + ATF_REQUIRE_EQ(100, tree.lookup< config::int_node >("first")); + ATF_REQUIRE_EQ(200, tree.lookup< config::int_node >("second")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(top__reset); +ATF_TEST_CASE_BODY(top__reset) +{ + config::tree tree; + tree.define< config::int_node >("first"); + + { + lutok::state state; + config::redirect(state, tree); + lutok::do_string(state, "first = 100; first = 200"); + } + + ATF_REQUIRE_EQ(200, tree.lookup< config::int_node >("first")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(top__already_set_on_entry); +ATF_TEST_CASE_BODY(top__already_set_on_entry) +{ + config::tree tree; + tree.define< config::int_node >("first"); + tree.set< config::int_node >("first", 100); + + { + lutok::state state; + config::redirect(state, tree); + lutok::do_string(state, "first = first * 15"); + } + + ATF_REQUIRE_EQ(1500, tree.lookup< config::int_node >("first")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(subtree__valid_types); +ATF_TEST_CASE_BODY(subtree__valid_types) +{ + config::tree tree; + tree.define< config::bool_node >("root.boolean"); + tree.define< config::int_node >("root.a.integer"); + tree.define< config::string_node >("root.string"); + + { + lutok::state state; + config::redirect(state, tree); + lutok::do_string(state, + "root.boolean = true\n" + "root.a.integer = 12345\n" + "root.string = 'a foo'\n"); + } + + ATF_REQUIRE_EQ(true, tree.lookup< config::bool_node >("root.boolean")); + ATF_REQUIRE_EQ(12345, tree.lookup< config::int_node >("root.a.integer")); + ATF_REQUIRE_EQ("a foo", tree.lookup< config::string_node >("root.string")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(subtree__reuse); +ATF_TEST_CASE_BODY(subtree__reuse) +{ + config::tree tree; + tree.define< config::int_node >("a.first"); + tree.define< config::int_node >("a.second"); + + { + lutok::state state; + config::redirect(state, tree); + lutok::do_string(state, "a.first = 100; a.second = a.first * 2"); + } + + ATF_REQUIRE_EQ(100, tree.lookup< config::int_node >("a.first")); + ATF_REQUIRE_EQ(200, tree.lookup< config::int_node >("a.second")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(subtree__reset); +ATF_TEST_CASE_BODY(subtree__reset) +{ + config::tree tree; + tree.define< config::int_node >("a.first"); + + { + lutok::state state; + config::redirect(state, tree); + lutok::do_string(state, "a.first = 100; a.first = 200"); + } + + ATF_REQUIRE_EQ(200, tree.lookup< config::int_node >("a.first")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(subtree__already_set_on_entry); +ATF_TEST_CASE_BODY(subtree__already_set_on_entry) +{ + config::tree tree; + tree.define< config::int_node >("a.first"); + tree.set< config::int_node >("a.first", 100); + + { + lutok::state state; + config::redirect(state, tree); + lutok::do_string(state, "a.first = a.first * 15"); + } + + ATF_REQUIRE_EQ(1500, tree.lookup< config::int_node >("a.first")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(subtree__override_inner); +ATF_TEST_CASE_BODY(subtree__override_inner) +{ + config::tree tree; + tree.define_dynamic("root"); + + { + lutok::state state; + config::redirect(state, tree); + lutok::do_string(state, "root.test = 'a'"); + ATF_REQUIRE_THROW_RE(lutok::error, "Invalid value for key 'root'", + lutok::do_string(state, "root = 'b'")); + // Ensure that the previous assignment to 'root' did not cause any + // inconsistencies in the environment that would prevent a new + // assignment from working. + lutok::do_string(state, "root.test2 = 'c'"); + } + + ATF_REQUIRE_EQ("a", tree.lookup< config::string_node >("root.test")); + ATF_REQUIRE_EQ("c", tree.lookup< config::string_node >("root.test2")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(dynamic_subtree__strings); +ATF_TEST_CASE_BODY(dynamic_subtree__strings) +{ + config::tree tree; + tree.define_dynamic("root"); + + lutok::state state; + config::redirect(state, tree); + lutok::do_string(state, + "root.key1 = 1234\n" + "root.a.b.key2 = 'foo bar'\n"); + + ATF_REQUIRE_EQ("1234", tree.lookup< config::string_node >("root.key1")); + ATF_REQUIRE_EQ("foo bar", + tree.lookup< config::string_node >("root.a.b.key2")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(dynamic_subtree__invalid_types); +ATF_TEST_CASE_BODY(dynamic_subtree__invalid_types) +{ + config::tree tree; + tree.define_dynamic("root"); + + lutok::state state; + config::redirect(state, tree); + ATF_REQUIRE_THROW_RE(lutok::error, + "Invalid value for key 'root.boolean' " + "\\(Not a string\\)", + lutok::do_string(state, "root.boolean = true")); + ATF_REQUIRE_THROW_RE(lutok::error, + "Invalid value for key 'root.table' " + "\\(Not a string\\)", + lutok::do_string(state, "root.table = {}")); + ATF_REQUIRE(!tree.is_set("root.boolean")); + ATF_REQUIRE(!tree.is_set("root.table")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(locals); +ATF_TEST_CASE_BODY(locals) +{ + config::tree tree; + tree.define< config::int_node >("the_key"); + + { + lutok::state state; + config::redirect(state, tree); + lutok::do_string(state, + "local function generate()\n" + " return 15\n" + "end\n" + "local test_var = 20\n" + "the_key = generate() + test_var\n"); + } + + ATF_REQUIRE_EQ(35, tree.lookup< config::int_node >("the_key")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(custom_node); +ATF_TEST_CASE_BODY(custom_node) +{ + config::tree tree; + tree.define< custom_node >("key1"); + tree.define< custom_node >("key2"); + tree.set< custom_node >("key2", custom_type(10)); + + { + lutok::state state; + config::redirect(state, tree); + lutok::do_string(state, "key1 = 512\n"); + lutok::do_string(state, "key2 = key2 * 2\n"); + } + + ATF_REQUIRE_EQ(1024, tree.lookup< custom_node >("key1").value); + ATF_REQUIRE_EQ(200, tree.lookup< custom_node >("key2").value); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(invalid_key); +ATF_TEST_CASE_BODY(invalid_key) +{ + config::tree tree; + + lutok::state state; + config::redirect(state, tree); + ATF_REQUIRE_THROW_RE(lutok::error, "Empty component in key 'root.'", + lutok::do_string(state, "root['']['a'] = 12345\n")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(unknown_key); +ATF_TEST_CASE_BODY(unknown_key) +{ + config::tree tree; + tree.define< config::bool_node >("static.bool"); + + lutok::state state; + config::redirect(state, tree); + ATF_REQUIRE_THROW_RE(lutok::error, + "Unknown configuration property 'static.int'", + lutok::do_string(state, + "static.int = 12345\n")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(value_error); +ATF_TEST_CASE_BODY(value_error) +{ + config::tree tree; + tree.define< config::bool_node >("a.b"); + + lutok::state state; + config::redirect(state, tree); + ATF_REQUIRE_THROW_RE(lutok::error, + "Invalid value for key 'a.b' \\(Not a boolean\\)", + lutok::do_string(state, "a.b = 12345\n")); + ATF_REQUIRE_THROW_RE(lutok::error, + "Invalid value for key 'a'", + lutok::do_string(state, "a = 1\n")); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, top__valid_types); + ATF_ADD_TEST_CASE(tcs, top__reuse); + ATF_ADD_TEST_CASE(tcs, top__reset); + ATF_ADD_TEST_CASE(tcs, top__already_set_on_entry); + + ATF_ADD_TEST_CASE(tcs, subtree__valid_types); + ATF_ADD_TEST_CASE(tcs, subtree__reuse); + ATF_ADD_TEST_CASE(tcs, subtree__reset); + ATF_ADD_TEST_CASE(tcs, subtree__already_set_on_entry); + ATF_ADD_TEST_CASE(tcs, subtree__override_inner); + + ATF_ADD_TEST_CASE(tcs, dynamic_subtree__strings); + ATF_ADD_TEST_CASE(tcs, dynamic_subtree__invalid_types); + + ATF_ADD_TEST_CASE(tcs, locals); + ATF_ADD_TEST_CASE(tcs, custom_node); + + ATF_ADD_TEST_CASE(tcs, invalid_key); + ATF_ADD_TEST_CASE(tcs, unknown_key); + ATF_ADD_TEST_CASE(tcs, value_error); +} diff --git a/external/bsd/kyua-cli/dist/utils/config/nodes.cpp b/external/bsd/kyua-cli/dist/utils/config/nodes.cpp new file mode 100644 index 000000000..837405a96 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/config/nodes.cpp @@ -0,0 +1,439 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/config/nodes.ipp" + +#include + +#include + +#include "utils/config/exceptions.hpp" +#include "utils/config/keys.hpp" +#include "utils/format/macros.hpp" + +namespace config = utils::config; + + +/// Destructor. +config::detail::base_node::~base_node(void) +{ +} + + +/// Constructor. +/// +/// \param dynamic_ Whether the node is dynamic or not. +config::detail::inner_node::inner_node(const bool dynamic_) : + _dynamic(dynamic_) +{ +} + + +/// Destructor. +config::detail::inner_node::~inner_node(void) +{ + for (children_map::const_iterator iter = _children.begin(); + iter != _children.end(); ++iter) + delete (*iter).second; +} + + +/// Fills the given node with a copy of this node's data. +/// +/// \param node The node to fill. Should be the fresh return value of a +/// deep_copy() operation. +void +config::detail::inner_node::copy_into(inner_node* node) const +{ + node->_dynamic = _dynamic; + for (children_map::const_iterator iter = _children.begin(); + iter != _children.end(); ++iter) { + base_node* new_node = (*iter).second->deep_copy(); + try { + node->_children[(*iter).first] = new_node; + } catch (...) { + delete new_node; + throw; + } + } +} + + +/// Finds a node without creating it if not found. +/// +/// This recursive algorithm traverses the tree searching for a particular key. +/// The returned node is constant, so this can only be used for querying +/// purposes. For this reason, this algorithm does not create intermediate +/// nodes if they don't exist (as would be necessary to set a new node). +/// +/// \param key The key to be queried. +/// \param key_pos The current level within the key to be examined. +/// +/// \return A reference to the located node, if successful. +/// +/// \throw unknown_key_error If the provided key is unknown. +const config::detail::base_node* +config::detail::inner_node::lookup_ro(const tree_key& key, + const tree_key::size_type key_pos) const +{ + PRE(key_pos < key.size()); + + const children_map::const_iterator child_iter = _children.find( + key[key_pos]); + if (child_iter == _children.end()) + throw unknown_key_error(key); + + if (key_pos == key.size() - 1) { + return (*child_iter).second; + } else { + PRE(key_pos < key.size() - 1); + try { + const inner_node& child = dynamic_cast< const inner_node& >( + *(*child_iter).second); + return child.lookup_ro(key, key_pos + 1); + } catch (const std::bad_cast& e) { + throw unknown_key_error( + key, "Cannot address incomplete configuration property '%s'"); + } + } +} + + +/// Finds a node and creates it if not found. +/// +/// This recursive algorithm traverses the tree searching for a particular key, +/// creating any intermediate nodes if they do not already exist (for the case +/// of dynamic inner nodes). The returned node is non-constant, so this can be +/// used by the algorithms that set key values. +/// +/// \param key The key to be queried. +/// \param key_pos The current level within the key to be examined. +/// \param new_node A function that returns a new leaf node of the desired +/// type. This is only called if the leaf cannot be found, but it has +/// already been defined. +/// +/// \return A reference to the located node, if successful. +/// +/// \throw unknown_key_error If the provided key is unknown. +/// \throw value_error If the resulting node of the search would be an inner +/// node. +config::leaf_node* +config::detail::inner_node::lookup_rw(const tree_key& key, + const tree_key::size_type key_pos, + new_node_hook new_node) +{ + PRE(key_pos < key.size()); + + children_map::const_iterator child_iter = _children.find(key[key_pos]); + if (child_iter == _children.end()) { + if (_dynamic) { + base_node* const child = (key_pos == key.size() - 1) ? + static_cast< base_node* >(new_node()) : + static_cast< base_node* >(new dynamic_inner_node()); + _children.insert(children_map::value_type(key[key_pos], child)); + child_iter = _children.find(key[key_pos]); + } else { + throw unknown_key_error(key); + } + } + + if (key_pos == key.size() - 1) { + try { + leaf_node& child = dynamic_cast< leaf_node& >( + *(*child_iter).second); + return &child; + } catch (const std::bad_cast& unused_error) { + throw value_error(F("Invalid value for key '%s'") % + flatten_key(key)); + } + } else { + PRE(key_pos < key.size() - 1); + try { + inner_node& child = dynamic_cast< inner_node& >( + *(*child_iter).second); + return child.lookup_rw(key, key_pos + 1, new_node); + } catch (const std::bad_cast& e) { + throw unknown_key_error( + key, "Cannot address incomplete configuration property '%s'"); + } + } +} + + +/// Converts the subtree to a collection of key/value string pairs. +/// +/// \param [out] properties The accumulator for the generated properties. The +/// contents of the map are only extended. +/// \param key The path to the current node. +void +config::detail::inner_node::all_properties(properties_map& properties, + const tree_key& key) const +{ + for (children_map::const_iterator iter = _children.begin(); + iter != _children.end(); ++iter) { + tree_key child_key = key; + child_key.push_back((*iter).first); + try { + leaf_node& child = dynamic_cast< leaf_node& >(*(*iter).second); + if (child.is_set()) + properties[flatten_key(child_key)] = child.to_string(); + } catch (const std::bad_cast& unused_error) { + inner_node& child = dynamic_cast< inner_node& >(*(*iter).second); + child.all_properties(properties, child_key); + } + } +} + + +/// Constructor. +config::detail::static_inner_node::static_inner_node(void) : + inner_node(false) +{ +} + + +/// Copies the node. +/// +/// \return A dynamically-allocated node. +config::detail::base_node* +config::detail::static_inner_node::deep_copy(void) const +{ + std::auto_ptr< inner_node > new_node(new static_inner_node()); + copy_into(new_node.get()); + return new_node.release(); +} + + +/// Registers a key as valid and having a specific type. +/// +/// This method does not raise errors on invalid/unknown keys or other +/// tree-related issues. The reasons is that define() is a method that does not +/// depend on user input: it is intended to pre-populate the tree with a +/// specific structure, and that happens once at coding time. +/// +/// \param key The key to be registered. +/// \param key_pos The current level within the key to be examined. +/// \param new_node A function that returns a new leaf node of the desired +/// type. +void +config::detail::static_inner_node::define(const tree_key& key, + const tree_key::size_type key_pos, + new_node_hook new_node) +{ + PRE(key_pos < key.size()); + + if (key_pos == key.size() - 1) { + PRE_MSG(_children.find(key[key_pos]) == _children.end(), + "Key already defined"); + _children.insert(children_map::value_type(key[key_pos], new_node())); + } else { + PRE(key_pos < key.size() - 1); + const children_map::const_iterator child_iter = _children.find( + key[key_pos]); + + if (child_iter == _children.end()) { + static_inner_node* const child_ptr = new static_inner_node(); + _children.insert(children_map::value_type(key[key_pos], child_ptr)); + child_ptr->define(key, key_pos + 1, new_node); + } else { + try { + static_inner_node& child = dynamic_cast< static_inner_node& >( + *(*child_iter).second); + child.define(key, key_pos + 1, new_node); + } catch (const std::bad_cast& e) { + UNREACHABLE; + } + } + } +} + + +/// Constructor. +config::detail::dynamic_inner_node::dynamic_inner_node(void) : + inner_node(true) +{ +} + + +/// Copies the node. +/// +/// \return A dynamically-allocated node. +config::detail::base_node* +config::detail::dynamic_inner_node::deep_copy(void) const +{ + std::auto_ptr< inner_node > new_node(new dynamic_inner_node()); + copy_into(new_node.get()); + return new_node.release(); +} + + +/// Destructor. +config::leaf_node::~leaf_node(void) +{ +} + + +/// Copies the node. +/// +/// \return A dynamically-allocated node. +config::detail::base_node* +config::bool_node::deep_copy(void) const +{ + std::auto_ptr< bool_node > new_node(new bool_node()); + new_node->_value = _value; + return new_node.release(); +} + + +/// Pushes the node's value onto the Lua stack. +/// +/// \param state The Lua state onto which to push the value. +void +config::bool_node::push_lua(lutok::state& state) const +{ + state.push_boolean(value()); +} + + +/// Sets the value of the node from an entry in the Lua stack. +/// +/// \param state The Lua state from which to get the value. +/// \param value_index The stack index in which the value resides. +/// +/// \throw value_error If the value in state(value_index) cannot be +/// processed by this node. +void +config::bool_node::set_lua(lutok::state& state, const int value_index) +{ + if (state.is_boolean(value_index)) + set(state.to_boolean(value_index)); + else + throw value_error("Not a boolean"); +} + + +/// Copies the node. +/// +/// \return A dynamically-allocated node. +config::detail::base_node* +config::int_node::deep_copy(void) const +{ + std::auto_ptr< int_node > new_node(new int_node()); + new_node->_value = _value; + return new_node.release(); +} + + +/// Pushes the node's value onto the Lua stack. +/// +/// \param state The Lua state onto which to push the value. +void +config::int_node::push_lua(lutok::state& state) const +{ + state.push_integer(value()); +} + + +/// Sets the value of the node from an entry in the Lua stack. +/// +/// \param state The Lua state from which to get the value. +/// \param value_index The stack index in which the value resides. +/// +/// \throw value_error If the value in state(value_index) cannot be +/// processed by this node. +void +config::int_node::set_lua(lutok::state& state, const int value_index) +{ + if (state.is_number(value_index)) + set(state.to_integer(value_index)); + else + throw value_error("Not an integer"); +} + + +/// Copies the node. +/// +/// \return A dynamically-allocated node. +config::detail::base_node* +config::string_node::deep_copy(void) const +{ + std::auto_ptr< string_node > new_node(new string_node()); + new_node->_value = _value; + return new_node.release(); +} + + +/// Pushes the node's value onto the Lua stack. +/// +/// \param state The Lua state onto which to push the value. +void +config::string_node::push_lua(lutok::state& state) const +{ + state.push_string(value()); +} + + +/// Sets the value of the node from an entry in the Lua stack. +/// +/// \param state The Lua state from which to get the value. +/// \param value_index The stack index in which the value resides. +/// +/// \throw value_error If the value in state(value_index) cannot be +/// processed by this node. +void +config::string_node::set_lua(lutok::state& state, const int value_index) +{ + if (state.is_string(value_index)) + set(state.to_string(value_index)); + else + throw value_error("Not a string"); +} + + +/// Copies the node. +/// +/// \return A dynamically-allocated node. +config::detail::base_node* +config::strings_set_node::deep_copy(void) const +{ + std::auto_ptr< strings_set_node > new_node(new strings_set_node()); + new_node->_value = _value; + return new_node.release(); +} + + +/// Converts a single word to the native type. +/// +/// \param raw_value The value to parse. +/// +/// \return The parsed value. +std::string +config::strings_set_node::parse_one(const std::string& raw_value) const +{ + return raw_value; +} diff --git a/external/bsd/kyua-cli/dist/utils/config/nodes.hpp b/external/bsd/kyua-cli/dist/utils/config/nodes.hpp new file mode 100644 index 000000000..a94f99dc5 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/config/nodes.hpp @@ -0,0 +1,310 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file utils/config/nodes.hpp +/// Representation of tree nodes. + +#if !defined(UTILS_CONFIG_NODES_HPP) +#define UTILS_CONFIG_NODES_HPP + +#include +#include +#include + +#include + +#include "utils/config/keys.hpp" +#include "utils/noncopyable.hpp" +#include "utils/optional.hpp" + +namespace utils { +namespace config { + + +/// Flat representation of all properties as strings. +typedef std::map< std::string, std::string > properties_map; + + +namespace detail { + + +/// Base representation of a node. +/// +/// This abstract class provides the base type for every node in the tree. Due +/// to the dynamic nature of our trees (each leaf being able to hold arbitrary +/// data types), this base type is a necessity. +class base_node : noncopyable { +public: + virtual ~base_node(void) = 0; + + /// Copies the node. + /// + /// \return A dynamically-allocated node. + virtual base_node* deep_copy(void) const = 0; +}; + + +class static_inner_node; + + +} // namespace detail + + +/// Abstract leaf node without any specified type. +/// +/// This base abstract type is necessary to have a common pointer type to which +/// to cast any leaf. We later provide templated derivates of this class, and +/// those cannot act in this manner. +/// +/// It is important to understand that a leaf can exist without actually holding +/// a value. Our trees are "strictly keyed": keys must have been pre-defined +/// before a value can be set on them. This is to ensure that the end user is +/// using valid key names and not making mistakes due to typos, for example. To +/// represent this condition, we define an "empty" key in the tree to denote +/// that the key is valid, yet it has not been set by the user. Only when an +/// explicit set is performed on the key, it gets a value. +class leaf_node : public detail::base_node { +public: + virtual ~leaf_node(void); + + /// Checks whether the node has been set by the user. + /// + /// Nodes of the tree are predefined by the caller to specify the valid + /// types of the leaves. Such predefinition results in the creation of + /// nodes within the tree, but these nodes have not yet been set. + /// Traversing these nodes is invalid and should result in an "unknown key" + /// error. + /// + /// \return True if a value has been set in the node. + virtual bool is_set(void) const = 0; + + /// Pushes the node's value onto the Lua stack. + /// + /// \param state The Lua state onto which to push the value. + virtual void push_lua(lutok::state& state) const = 0; + + /// Sets the value of the node from an entry in the Lua stack. + /// + /// \param state The Lua state from which to get the value. + /// \param value_index The stack index in which the value resides. + /// + /// \throw value_error If the value in state(value_index) cannot be + /// processed by this node. + virtual void set_lua(lutok::state& state, const int value_index) = 0; + + /// Sets the value of the node from a raw string representation. + /// + /// \param raw_value The value to set the node to. + /// + /// \throw value_error If the value is invalid. + virtual void set_string(const std::string& raw_value) = 0; + + /// Converts the contents of the node to a string. + /// + /// \pre The node must have a value. + /// + /// \return A string representation of the value held by the node. + virtual std::string to_string(void) const = 0; +}; + + +/// Base leaf node for a single arbitrary type. +/// +/// This templated leaf node holds a single object of any type. The conversion +/// to/from string representations is undefined, as that depends on the +/// particular type being processed. You should reimplement this class for any +/// type that needs additional processing/validation during conversion. +template< typename ValueType > +class typed_leaf_node : public leaf_node { +public: + /// The type of the value held by this node. + typedef ValueType value_type; + + typed_leaf_node(void); + + bool is_set(void) const; + + /// Gets the value stored in the node. + /// + /// \todo Figure out why Doxygen is unable to pick up the documentation for + /// this function from the nodes.ipp file. + /// + /// \pre The node must have a value. + /// + /// \return The value in the node. + const value_type& value(void) const; + + /// Gets the read-write value stored in the node. + /// + /// \todo Figure out why Doxygen is unable to pick up the documentation for + /// this function from the nodes.ipp file. + /// + /// \pre The node must have a value. + /// + /// \return The value in the node. + value_type& value(void); + + /// Sets the value of the node. + /// + /// \todo Figure out why Doxygen is unable to pick up the documentation for + /// this function from the nodes.ipp file. + /// + /// \param value_ The new value to set the node to. + void set(const value_type&); + +protected: + /// The value held by this node. + optional< value_type > _value; + +private: + virtual void validate(const value_type&) const; +}; + + +/// Leaf node holding a native type. +/// +/// This templated leaf node holds a native type. The conversion to/from string +/// representations of the value happens by means of iostreams. +template< typename ValueType > +class native_leaf_node : public typed_leaf_node< ValueType > { +public: + void set_string(const std::string&); + std::string to_string(void) const; +}; + + +/// A leaf node that holds a boolean value. +class bool_node : public native_leaf_node< bool > { +public: + virtual base_node* deep_copy(void) const; + + void push_lua(lutok::state&) const; + void set_lua(lutok::state&, const int); +}; + + +/// A leaf node that holds an integer value. +class int_node : public native_leaf_node< int > { +public: + virtual base_node* deep_copy(void) const; + + void push_lua(lutok::state&) const; + void set_lua(lutok::state&, const int); +}; + + +/// A leaf node that holds a string value. +class string_node : public native_leaf_node< std::string > { +public: + virtual base_node* deep_copy(void) const; + + void push_lua(lutok::state&) const; + void set_lua(lutok::state&, const int); +}; + + +/// Base leaf node for a set of native types. +/// +/// This is a base abstract class because there is no generic way to parse a +/// single word in the textual representation of the set to the native value. +template< typename ValueType > +class base_set_node : public leaf_node { +public: + /// The type of the value held by this node. + typedef std::set< ValueType > value_type; + + base_set_node(void); + + bool is_set(void) const; + + /// Gets the value stored in the node. + /// + /// \todo Figure out why Doxygen is unable to pick up the documentation for + /// this function from the nodes.ipp file. + /// + /// \pre The node must have a value. + /// + /// \return The value in the node. + const value_type& value(void) const; + + /// Gets the read-write value stored in the node. + /// + /// \todo Figure out why Doxygen is unable to pick up the documentation for + /// this function from the nodes.ipp file. + /// + /// \pre The node must have a value. + /// + /// \return The value in the node. + value_type& value(void); + + /// Sets the value of the node. + /// + /// \todo Figure out why Doxygen is unable to pick up the documentation for + /// this function from the nodes.ipp file. + /// + /// \param value_ The new value to set the node to. + void set(const value_type&); + + void set_string(const std::string&); + std::string to_string(void) const; + + void push_lua(lutok::state&) const; + void set_lua(lutok::state&, const int); + +protected: + /// The value held by this node. + optional< value_type > _value; + +private: + /// Converts a single word to the native type. + /// + /// \param raw_value The value to parse. + /// + /// \return The parsed value. + /// + /// \throw value_error If the value is invalid. + virtual ValueType parse_one(const std::string& raw_value) const = 0; + + virtual void validate(const value_type&) const; +}; + + +/// A leaf node that holds a set of strings. +class strings_set_node : public base_set_node< std::string > { +public: + virtual base_node* deep_copy(void) const; + +private: + std::string parse_one(const std::string&) const; +}; + + +} // namespace config +} // namespace utils + +#endif // !defined(UTILS_CONFIG_NODES_HPP) diff --git a/external/bsd/kyua-cli/dist/utils/config/nodes.ipp b/external/bsd/kyua-cli/dist/utils/config/nodes.ipp new file mode 100644 index 000000000..7296ed56f --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/config/nodes.ipp @@ -0,0 +1,408 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/config/nodes.hpp" + +#if !defined(UTILS_CONFIG_NODES_IPP) +#define UTILS_CONFIG_NODES_IPP + +#include +#include + +#include "utils/config/exceptions.hpp" +#include "utils/defs.hpp" +#include "utils/format/macros.hpp" +#include "utils/optional.ipp" +#include "utils/text/exceptions.hpp" +#include "utils/text/operations.ipp" +#include "utils/sanity.hpp" + +namespace utils { + + +namespace config { +namespace detail { + + +/// Type of the new_node() family of functions. +typedef base_node* (*new_node_hook)(void); + + +/// Creates a new leaf node of a given type. +/// +/// \tparam NodeType The type of the leaf node to create. +/// +/// \return A pointer to the newly-created node. +template< class NodeType > +base_node* +new_node(void) +{ + return new NodeType(); +} + + +/// Internal node of the tree. +/// +/// This abstract base class provides the mechanism to implement both static and +/// dynamic nodes. Ideally, the implementation would be split in subclasses and +/// this class would not include the knowledge of whether the node is dynamic or +/// not. However, because the static/dynamic difference depends on the leaf +/// types, we need to declare template functions and these cannot be virtual. +class inner_node : public base_node { + /// Whether the node is dynamic or not. + bool _dynamic; + +protected: + /// Type to represent the collection of children of this node. + /// + /// Note that these are one-level keys. They cannot contain dots, and thus + /// is why we use a string rather than a tree_key. + typedef std::map< std::string, base_node* > children_map; + + /// Mapping of keys to values that are descendants of this node. + children_map _children; + + void copy_into(inner_node* new_node) const; + +public: + inner_node(const bool); + virtual ~inner_node(void) = 0; + + const base_node* lookup_ro(const tree_key&, + const tree_key::size_type) const; + leaf_node* lookup_rw(const tree_key&, const tree_key::size_type, + new_node_hook); + + void all_properties(properties_map&, const tree_key&) const; +}; + + +/// Static internal node of the tree. +/// +/// The direct children of this node must be pre-defined by calls to define(). +/// Attempts to traverse this node and resolve a key that is not a pre-defined +/// children will result in an "unknown key" error. +class static_inner_node : public config::detail::inner_node { +public: + static_inner_node(void); + + virtual base_node* deep_copy(void) const; + + void define(const tree_key&, const tree_key::size_type, new_node_hook); +}; + + +/// Dynamic internal node of the tree. +/// +/// The children of this node need not be pre-defined. Attempts to traverse +/// this node and resolve a key will result in such key being created. Any +/// intermediate non-existent nodes of the traversal will be created as dynamic +/// inner nodes as well. +class dynamic_inner_node : public config::detail::inner_node { +public: + virtual base_node* deep_copy(void) const; + + dynamic_inner_node(void); +}; + + +} // namespace detail +} // namespace config + + +/// Constructor for a node with an undefined value. +/// +/// This should only be called by the tree's define() method as a way to +/// register a node as known but undefined. The node will then serve as a +/// placeholder for future values. +template< typename ValueType > +config::typed_leaf_node< ValueType >::typed_leaf_node(void) : + _value(none) +{ +} + + +/// Checks whether the node has been set. +/// +/// Remember that a node can exist before holding a value (i.e. when the node +/// has been defined as "known" but not yet set by the user). This function +/// checks whether the node laready holds a value. +/// +/// \return True if a value has been set in the node. +template< typename ValueType > +bool +config::typed_leaf_node< ValueType >::is_set(void) const +{ + return static_cast< bool >(_value); +} + + +/// Gets the value stored in the node. +/// +/// \pre The node must have a value. +/// +/// \return The value in the node. +template< typename ValueType > +const typename config::typed_leaf_node< ValueType >::value_type& +config::typed_leaf_node< ValueType >::value(void) const +{ + PRE(is_set()); + return _value.get(); +} + + +/// Gets the read-write value stored in the node. +/// +/// \pre The node must have a value. +/// +/// \return The value in the node. +template< typename ValueType > +typename config::typed_leaf_node< ValueType >::value_type& +config::typed_leaf_node< ValueType >::value(void) +{ + PRE(is_set()); + return _value.get(); +} + + +/// Sets the value of the node. +/// +/// \param value_ The new value to set the node to. +/// +/// \throw value_error If the value is invalid, according to validate(). +template< typename ValueType > +void +config::typed_leaf_node< ValueType >::set(const value_type& value_) +{ + validate(value_); + _value = optional< value_type >(value_); +} + + +/// Checks a given value for validity. +/// +/// This is called internally by the node right before updating the recorded +/// value. This method can be redefined by subclasses. +/// +/// \param unused_new_value The value to validate. +/// +/// \throw value_error If the value is not valid. +template< typename ValueType > +void +config::typed_leaf_node< ValueType >::validate( + const value_type& UTILS_UNUSED_PARAM(new_value)) const +{ +} + + +/// Sets the value of the node from a raw string representation. +/// +/// \param raw_value The value to set the node to. +/// +/// \throw value_error If the value is invalid. +template< typename ValueType > +void +config::native_leaf_node< ValueType >::set_string(const std::string& raw_value) +{ + try { + typed_leaf_node< ValueType >::set(text::to_type< ValueType >( + raw_value)); + } catch (const text::value_error& e) { + throw config::value_error(F("Failed to convert string value '%s' to " + "the node's type") % raw_value); + } +} + + +/// Converts the contents of the node to a string. +/// +/// \pre The node must have a value. +/// +/// \return A string representation of the value held by the node. +template< typename ValueType > +std::string +config::native_leaf_node< ValueType >::to_string(void) const +{ + PRE(typed_leaf_node< ValueType >::is_set()); + return F("%s") % typed_leaf_node< ValueType >::value(); +} + + +/// Constructor for a node with an undefined value. +/// +/// This should only be called by the tree's define() method as a way to +/// register a node as known but undefined. The node will then serve as a +/// placeholder for future values. +template< typename ValueType > +config::base_set_node< ValueType >::base_set_node(void) : + _value(none) +{ +} + + +/// Checks whether the node has been set. +/// +/// Remember that a node can exist before holding a value (i.e. when the node +/// has been defined as "known" but not yet set by the user). This function +/// checks whether the node laready holds a value. +/// +/// \return True if a value has been set in the node. +template< typename ValueType > +bool +config::base_set_node< ValueType >::is_set(void) const +{ + return static_cast< bool >(_value); +} + + +/// Gets the value stored in the node. +/// +/// \pre The node must have a value. +/// +/// \return The value in the node. +template< typename ValueType > +const typename config::base_set_node< ValueType >::value_type& +config::base_set_node< ValueType >::value(void) const +{ + PRE(is_set()); + return _value.get(); +} + + +/// Gets the read-write value stored in the node. +/// +/// \pre The node must have a value. +/// +/// \return The value in the node. +template< typename ValueType > +typename config::base_set_node< ValueType >::value_type& +config::base_set_node< ValueType >::value(void) +{ + PRE(is_set()); + return _value.get(); +} + + +/// Sets the value of the node. +/// +/// \param value_ The new value to set the node to. +/// +/// \throw value_error If the value is invalid, according to validate(). +template< typename ValueType > +void +config::base_set_node< ValueType >::set(const value_type& value_) +{ + validate(value_); + _value = optional< value_type >(value_); +} + + +/// Sets the value of the node from a raw string representation. +/// +/// \param raw_value The value to set the node to. +/// +/// \throw value_error If the value is invalid. +template< typename ValueType > +void +config::base_set_node< ValueType >::set_string(const std::string& raw_value) +{ + std::set< ValueType > new_value; + + const std::vector< std::string > words = text::split(raw_value, ' '); + for (std::vector< std::string >::const_iterator iter = words.begin(); + iter != words.end(); ++iter) { + if (!(*iter).empty()) + new_value.insert(parse_one(*iter)); + } + + set(new_value); +} + + +/// Converts the contents of the node to a string. +/// +/// \pre The node must have a value. +/// +/// \return A string representation of the value held by the node. +template< typename ValueType > +std::string +config::base_set_node< ValueType >::to_string(void) const +{ + PRE(is_set()); + return text::join(_value.get(), " "); +} + + +/// Pushes the node's value onto the Lua stack. +/// +/// \param unused_state The Lua state onto which to push the value. +template< typename ValueType > +void +config::base_set_node< ValueType >::push_lua( + lutok::state& UTILS_UNUSED_PARAM(state)) const +{ + UNREACHABLE; +} + + +/// Sets the value of the node from an entry in the Lua stack. +/// +/// \param unused_state The Lua state from which to get the value. +/// \param unused_value_index The stack index in which the value resides. +/// +/// \throw value_error If the value in state(value_index) cannot be +/// processed by this node. +template< typename ValueType > +void +config::base_set_node< ValueType >::set_lua( + lutok::state& UTILS_UNUSED_PARAM(state), + const int UTILS_UNUSED_PARAM(value_index)) +{ + UNREACHABLE; +} + + +/// Checks a given value for validity. +/// +/// This is called internally by the node right before updating the recorded +/// value. This method can be redefined by subclasses. +/// +/// \param unused_new_value The value to validate. +/// +/// \throw value_error If the value is not valid. +template< typename ValueType > +void +config::base_set_node< ValueType >::validate( + const value_type& UTILS_UNUSED_PARAM(new_value)) const +{ +} + + +} // namespace utils + +#endif // !defined(UTILS_CONFIG_NODES_IPP) diff --git a/external/bsd/kyua-cli/dist/utils/config/nodes_test.cpp b/external/bsd/kyua-cli/dist/utils/config/nodes_test.cpp new file mode 100644 index 000000000..ff4e70820 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/config/nodes_test.cpp @@ -0,0 +1,568 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/config/nodes.ipp" + +#include + +#include + +#include "utils/config/exceptions.hpp" +#include "utils/config/keys.hpp" +#include "utils/defs.hpp" + +namespace config = utils::config; + + +namespace { + + +/// Typed leaf node that specializes the validate() method. +class validation_node : public config::int_node { + /// Checks a given value for validity against a fake value. + /// + /// \param new_value The value to validate. + /// + /// \throw value_error If the value is not valid. + void + validate(const value_type& new_value) const + { + if (new_value == 12345) + throw config::value_error("Custom validate method"); + } +}; + + +/// Set node that specializes the validate() method. +class set_validation_node : public config::strings_set_node { + /// Checks a given value for validity against a fake value. + /// + /// \param new_value The value to validate. + /// + /// \throw value_error If the value is not valid. + void + validate(const value_type& new_value) const + { + for (value_type::const_iterator iter = new_value.begin(); + iter != new_value.end(); ++iter) + if (*iter == "throw") + throw config::value_error("Custom validate method"); + } +}; + + +} // anonymous namespace + + +ATF_TEST_CASE_WITHOUT_HEAD(bool_node__deep_copy); +ATF_TEST_CASE_BODY(bool_node__deep_copy) +{ + config::bool_node node; + node.set(true); + config::detail::base_node* raw_copy = node.deep_copy(); + config::bool_node* copy = static_cast< config::bool_node* >(raw_copy); + ATF_REQUIRE(copy->value()); + copy->set(false); + ATF_REQUIRE(node.value()); + ATF_REQUIRE(!copy->value()); + delete copy; +} + + +ATF_TEST_CASE_WITHOUT_HEAD(bool_node__is_set_and_set); +ATF_TEST_CASE_BODY(bool_node__is_set_and_set) +{ + config::bool_node node; + ATF_REQUIRE(!node.is_set()); + node.set(false); + ATF_REQUIRE( node.is_set()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(bool_node__value_and_set); +ATF_TEST_CASE_BODY(bool_node__value_and_set) +{ + config::bool_node node; + node.set(false); + ATF_REQUIRE(!node.value()); + node.set(true); + ATF_REQUIRE( node.value()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(bool_node__push_lua); +ATF_TEST_CASE_BODY(bool_node__push_lua) +{ + lutok::state state; + + config::bool_node node; + node.set(true); + node.push_lua(state); + ATF_REQUIRE(state.is_boolean(-1)); + ATF_REQUIRE(state.to_boolean(-1)); + state.pop(1); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(bool_node__set_lua__ok); +ATF_TEST_CASE_BODY(bool_node__set_lua__ok) +{ + lutok::state state; + + config::bool_node node; + state.push_boolean(false); + node.set_lua(state, -1); + state.pop(1); + ATF_REQUIRE(!node.value()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(bool_node__set_lua__invalid_value); +ATF_TEST_CASE_BODY(bool_node__set_lua__invalid_value) +{ + lutok::state state; + + config::bool_node node; + state.push_string("foo bar"); + ATF_REQUIRE_THROW(config::value_error, node.set_lua(state, -1)); + state.pop(1); + ATF_REQUIRE(!node.is_set()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(bool_node__set_string__ok); +ATF_TEST_CASE_BODY(bool_node__set_string__ok) +{ + config::bool_node node; + node.set_string("false"); + ATF_REQUIRE(!node.value()); + node.set_string("true"); + ATF_REQUIRE( node.value()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(bool_node__set_string__invalid_value); +ATF_TEST_CASE_BODY(bool_node__set_string__invalid_value) +{ + config::bool_node node; + ATF_REQUIRE_THROW(config::value_error, node.set_string("12345")); + ATF_REQUIRE(!node.is_set()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(bool_node__to_string); +ATF_TEST_CASE_BODY(bool_node__to_string) +{ + config::bool_node node; + node.set(false); + ATF_REQUIRE_EQ("false", node.to_string()); + node.set(true); + ATF_REQUIRE_EQ("true", node.to_string()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(int_node__deep_copy); +ATF_TEST_CASE_BODY(int_node__deep_copy) +{ + config::int_node node; + node.set(5); + config::detail::base_node* raw_copy = node.deep_copy(); + config::int_node* copy = static_cast< config::int_node* >(raw_copy); + ATF_REQUIRE_EQ(5, copy->value()); + copy->set(10); + ATF_REQUIRE_EQ(5, node.value()); + ATF_REQUIRE_EQ(10, copy->value()); + delete copy; +} + + +ATF_TEST_CASE_WITHOUT_HEAD(int_node__is_set_and_set); +ATF_TEST_CASE_BODY(int_node__is_set_and_set) +{ + config::int_node node; + ATF_REQUIRE(!node.is_set()); + node.set(20); + ATF_REQUIRE( node.is_set()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(int_node__value_and_set); +ATF_TEST_CASE_BODY(int_node__value_and_set) +{ + config::int_node node; + node.set(20); + ATF_REQUIRE_EQ(20, node.value()); + node.set(0); + ATF_REQUIRE_EQ(0, node.value()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(int_node__push_lua); +ATF_TEST_CASE_BODY(int_node__push_lua) +{ + lutok::state state; + + config::int_node node; + node.set(754); + node.push_lua(state); + ATF_REQUIRE(state.is_number(-1)); + ATF_REQUIRE_EQ(754, state.to_integer(-1)); + state.pop(1); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(int_node__set_lua__ok); +ATF_TEST_CASE_BODY(int_node__set_lua__ok) +{ + lutok::state state; + + config::int_node node; + state.push_integer(123); + state.push_string("456"); + node.set_lua(state, -2); + ATF_REQUIRE_EQ(123, node.value()); + node.set_lua(state, -1); + ATF_REQUIRE_EQ(456, node.value()); + state.pop(2); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(int_node__set_lua__invalid_value); +ATF_TEST_CASE_BODY(int_node__set_lua__invalid_value) +{ + lutok::state state; + + config::int_node node; + state.push_boolean(true); + ATF_REQUIRE_THROW(config::value_error, node.set_lua(state, -1)); + state.pop(1); + ATF_REQUIRE(!node.is_set()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(int_node__set_string__ok); +ATF_TEST_CASE_BODY(int_node__set_string__ok) +{ + config::int_node node; + node.set_string("178"); + ATF_REQUIRE_EQ(178, node.value()); + node.set_string("-123"); + ATF_REQUIRE_EQ(-123, node.value()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(int_node__set_string__invalid_value); +ATF_TEST_CASE_BODY(int_node__set_string__invalid_value) +{ + config::int_node node; + ATF_REQUIRE_THROW(config::value_error, node.set_string(" 23")); + ATF_REQUIRE(!node.is_set()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(int_node__to_string); +ATF_TEST_CASE_BODY(int_node__to_string) +{ + config::int_node node; + node.set(89); + ATF_REQUIRE_EQ("89", node.to_string()); + node.set(-57); + ATF_REQUIRE_EQ("-57", node.to_string()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(string_node__deep_copy); +ATF_TEST_CASE_BODY(string_node__deep_copy) +{ + config::string_node node; + node.set("first"); + config::detail::base_node* raw_copy = node.deep_copy(); + config::string_node* copy = static_cast< config::string_node* >(raw_copy); + ATF_REQUIRE_EQ("first", copy->value()); + copy->set("second"); + ATF_REQUIRE_EQ("first", node.value()); + ATF_REQUIRE_EQ("second", copy->value()); + delete copy; +} + + +ATF_TEST_CASE_WITHOUT_HEAD(string_node__is_set_and_set); +ATF_TEST_CASE_BODY(string_node__is_set_and_set) +{ + config::string_node node; + ATF_REQUIRE(!node.is_set()); + node.set("foo"); + ATF_REQUIRE( node.is_set()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(string_node__value_and_set); +ATF_TEST_CASE_BODY(string_node__value_and_set) +{ + config::string_node node; + node.set("foo"); + ATF_REQUIRE_EQ("foo", node.value()); + node.set(""); + ATF_REQUIRE_EQ("", node.value()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(string_node__push_lua); +ATF_TEST_CASE_BODY(string_node__push_lua) +{ + lutok::state state; + + config::string_node node; + node.set("some message"); + node.push_lua(state); + ATF_REQUIRE(state.is_string(-1)); + ATF_REQUIRE_EQ("some message", state.to_string(-1)); + state.pop(1); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(string_node__set_lua__ok); +ATF_TEST_CASE_BODY(string_node__set_lua__ok) +{ + lutok::state state; + + config::string_node node; + state.push_string("text 1"); + state.push_integer(231); + node.set_lua(state, -2); + ATF_REQUIRE_EQ("text 1", node.value()); + node.set_lua(state, -1); + ATF_REQUIRE_EQ("231", node.value()); + state.pop(2); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(string_node__set_lua__invalid_value); +ATF_TEST_CASE_BODY(string_node__set_lua__invalid_value) +{ + lutok::state state; + + config::bool_node node; + state.new_table(); + ATF_REQUIRE_THROW(config::value_error, node.set_lua(state, -1)); + state.pop(1); + ATF_REQUIRE(!node.is_set()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(string_node__set_string); +ATF_TEST_CASE_BODY(string_node__set_string) +{ + config::string_node node; + node.set_string("abcd efgh"); + ATF_REQUIRE_EQ("abcd efgh", node.value()); + node.set_string(" 1234 "); + ATF_REQUIRE_EQ(" 1234 ", node.value()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(string_node__to_string); +ATF_TEST_CASE_BODY(string_node__to_string) +{ + config::string_node node; + node.set(""); + ATF_REQUIRE_EQ("", node.to_string()); + node.set("aaa"); + ATF_REQUIRE_EQ("aaa", node.to_string()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(strings_set_node__deep_copy); +ATF_TEST_CASE_BODY(strings_set_node__deep_copy) +{ + std::set< std::string > value; + config::strings_set_node node; + value.insert("foo"); + node.set(value); + config::detail::base_node* raw_copy = node.deep_copy(); + config::strings_set_node* copy = + static_cast< config::strings_set_node* >(raw_copy); + value.insert("bar"); + ATF_REQUIRE_EQ(1, copy->value().size()); + copy->set(value); + ATF_REQUIRE_EQ(1, node.value().size()); + ATF_REQUIRE_EQ(2, copy->value().size()); + delete copy; +} + + +ATF_TEST_CASE_WITHOUT_HEAD(strings_set_node__is_set_and_set); +ATF_TEST_CASE_BODY(strings_set_node__is_set_and_set) +{ + std::set< std::string > value; + value.insert("foo"); + + config::strings_set_node node; + ATF_REQUIRE(!node.is_set()); + node.set(value); + ATF_REQUIRE( node.is_set()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(strings_set_node__value_and_set); +ATF_TEST_CASE_BODY(strings_set_node__value_and_set) +{ + std::set< std::string > value; + value.insert("first"); + + config::strings_set_node node; + node.set(value); + ATF_REQUIRE(value == node.value()); + value.clear(); + node.set(value); + value.insert("second"); + ATF_REQUIRE(node.value().empty()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(strings_set_node__set_string); +ATF_TEST_CASE_BODY(strings_set_node__set_string) +{ + config::strings_set_node node; + { + std::set< std::string > expected; + expected.insert("abcd"); + expected.insert("efgh"); + + node.set_string("abcd efgh"); + ATF_REQUIRE(expected == node.value()); + } + { + std::set< std::string > expected; + expected.insert("1234"); + + node.set_string(" 1234 "); + ATF_REQUIRE(expected == node.value()); + } +} + + +ATF_TEST_CASE_WITHOUT_HEAD(strings_set_node__to_string); +ATF_TEST_CASE_BODY(strings_set_node__to_string) +{ + std::set< std::string > value; + config::strings_set_node node; + value.insert("second"); + value.insert("first"); + node.set(value); + ATF_REQUIRE_EQ("first second", node.to_string()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(typed_leaf_node__validate_set); +ATF_TEST_CASE_BODY(typed_leaf_node__validate_set) +{ + validation_node node; + node.set(1234); + ATF_REQUIRE_THROW_RE(config::value_error, "Custom validate method", + node.set(12345)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(typed_leaf_node__validate_set_string); +ATF_TEST_CASE_BODY(typed_leaf_node__validate_set_string) +{ + validation_node node; + node.set_string("1234"); + ATF_REQUIRE_THROW_RE(config::value_error, "Custom validate method", + node.set_string("12345")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(base_set_node__validate_set); +ATF_TEST_CASE_BODY(base_set_node__validate_set) +{ + set_validation_node node; + set_validation_node::value_type values; + values.insert("foo"); + values.insert("bar"); + node.set(values); + values.insert("throw"); + values.insert("baz"); + ATF_REQUIRE_THROW_RE(config::value_error, "Custom validate method", + node.set(values)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(base_set_node__validate_set_string); +ATF_TEST_CASE_BODY(base_set_node__validate_set_string) +{ + set_validation_node node; + node.set_string("foo bar"); + ATF_REQUIRE_THROW_RE(config::value_error, "Custom validate method", + node.set_string("foo bar throw baz")); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, bool_node__deep_copy); + ATF_ADD_TEST_CASE(tcs, bool_node__is_set_and_set); + ATF_ADD_TEST_CASE(tcs, bool_node__value_and_set); + ATF_ADD_TEST_CASE(tcs, bool_node__push_lua); + ATF_ADD_TEST_CASE(tcs, bool_node__set_lua__ok); + ATF_ADD_TEST_CASE(tcs, bool_node__set_lua__invalid_value); + ATF_ADD_TEST_CASE(tcs, bool_node__set_string__ok); + ATF_ADD_TEST_CASE(tcs, bool_node__set_string__invalid_value); + ATF_ADD_TEST_CASE(tcs, bool_node__to_string); + + ATF_ADD_TEST_CASE(tcs, int_node__deep_copy); + ATF_ADD_TEST_CASE(tcs, int_node__is_set_and_set); + ATF_ADD_TEST_CASE(tcs, int_node__value_and_set); + ATF_ADD_TEST_CASE(tcs, int_node__push_lua); + ATF_ADD_TEST_CASE(tcs, int_node__set_lua__ok); + ATF_ADD_TEST_CASE(tcs, int_node__set_lua__invalid_value); + ATF_ADD_TEST_CASE(tcs, int_node__set_string__ok); + ATF_ADD_TEST_CASE(tcs, int_node__set_string__invalid_value); + ATF_ADD_TEST_CASE(tcs, int_node__to_string); + + ATF_ADD_TEST_CASE(tcs, string_node__deep_copy); + ATF_ADD_TEST_CASE(tcs, string_node__is_set_and_set); + ATF_ADD_TEST_CASE(tcs, string_node__value_and_set); + ATF_ADD_TEST_CASE(tcs, string_node__push_lua); + ATF_ADD_TEST_CASE(tcs, string_node__set_lua__ok); + ATF_ADD_TEST_CASE(tcs, string_node__set_lua__invalid_value); + ATF_ADD_TEST_CASE(tcs, string_node__set_string); + ATF_ADD_TEST_CASE(tcs, string_node__to_string); + + ATF_ADD_TEST_CASE(tcs, strings_set_node__deep_copy); + ATF_ADD_TEST_CASE(tcs, strings_set_node__is_set_and_set); + ATF_ADD_TEST_CASE(tcs, strings_set_node__value_and_set); + ATF_ADD_TEST_CASE(tcs, strings_set_node__set_string); + ATF_ADD_TEST_CASE(tcs, strings_set_node__to_string); + + ATF_ADD_TEST_CASE(tcs, typed_leaf_node__validate_set); + ATF_ADD_TEST_CASE(tcs, typed_leaf_node__validate_set_string); + ATF_ADD_TEST_CASE(tcs, base_set_node__validate_set); + ATF_ADD_TEST_CASE(tcs, base_set_node__validate_set_string); +} diff --git a/external/bsd/kyua-cli/dist/utils/config/parser.cpp b/external/bsd/kyua-cli/dist/utils/config/parser.cpp new file mode 100644 index 000000000..3fdaf2c58 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/config/parser.cpp @@ -0,0 +1,192 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/config/parser.hpp" + +#include +#include +#include +#include + +#include "utils/config/exceptions.hpp" +#include "utils/config/lua_module.hpp" +#include "utils/config/tree.ipp" +#include "utils/logging/macros.hpp" +#include "utils/noncopyable.hpp" + +namespace config = utils::config; + + +// History of configuration file versions: +// +// 2 - Changed the syntax() call to take only a version number, instead of the +// word 'config' as the first argument and the version as the second one. +// Files now start with syntax(2) instead of syntax('config', 1). +// +// 1 - Initial version. + + +/// Internal implementation of the parser. +struct utils::config::parser::impl : utils::noncopyable { + /// Pointer to the parent parser. Needed for callbacks. + parser* _parent; + + /// The Lua state used by this parser to process the configuration file. + lutok::state _state; + + /// The tree to be filed in by the configuration parameters, as provided by + /// the caller. + config::tree& _tree; + + /// Whether syntax() has been called or not. + bool _syntax_called; + + /// Constructs a new implementation. + /// + /// \param parent_ Pointer to the class being constructed. + /// \param config_tree_ The configuration tree provided by the user. + impl(parser* const parent_, tree& config_tree_) : + _parent(parent_), _tree(config_tree_), _syntax_called(false) + { + } + + friend void lua_syntax(lutok::state&); + + /// Callback executed by the Lua syntax() function. + /// + /// \param syntax_version The syntax format version as provided by the + /// configuration file in the call to syntax(). + void + syntax_callback(const int syntax_version) + { + if (_syntax_called) + throw syntax_error("syntax() can only be called once"); + _syntax_called = true; + + // Allow the parser caller to populate the tree with its own schema + // depending on the format/version combination. + _parent->setup(_tree, syntax_version); + + // Export the config module to the Lua state so that all global variable + // accesses are redirected to the configuration tree. + config::redirect(_state, _tree); + } +}; + + +namespace { + + +/// Implementation of the Lua syntax() function. +/// +/// The syntax() function has to be called by configuration files as the very +/// first thing they do. Once called, this function populates the configuration +/// tree based on the syntax version and then continues to process the rest of +/// the file. +/// +/// \pre state(-2) The syntax format name, if a v1 file. +/// \pre state(-1) The syntax format version. +/// +/// \param state The Lua state to operate in. +/// +/// \return The number of results pushed onto the stack; always 0. +static int +lua_syntax(lutok::state& state) +{ + if (!state.is_number(-1)) + throw config::value_error("Last argument to syntax must be a number"); + const int syntax_version = state.to_integer(-1); + + if (syntax_version == 1) { + if (state.get_top() != 2) + throw config::value_error("Version 1 files need two arguments to " + "syntax()"); + if (!state.is_string(-2) || state.to_string(-2) != "config") + throw config::value_error("First argument to syntax must be " + "'config' for version 1 files"); + } else { + if (state.get_top() != 1) + throw config::value_error("syntax() only takes one argument"); + } + + state.get_global("_config_parser"); + config::parser::impl* impl = *state.to_userdata< config::parser::impl* >(); + state.pop(1); + + impl->syntax_callback(syntax_version); + + return 0; +} + + +} // anonymous namespace + + +/// Constructs a new parser. +/// +/// \param [in,out] config_tree The configuration tree into which the values set +/// in the configuration file will be stored. +config::parser::parser(tree& config_tree) : + _pimpl(new impl(this, config_tree)) +{ + lutok::stack_cleaner cleaner(_pimpl->_state); + + _pimpl->_state.push_cxx_function(lua_syntax); + _pimpl->_state.set_global("syntax"); + *_pimpl->_state.new_userdata< config::parser::impl* >() = _pimpl.get(); + _pimpl->_state.set_global("_config_parser"); +} + + +/// Destructor. +config::parser::~parser(void) +{ +} + + +/// Parses a configuration file. +/// +/// \post The tree registered during the construction of this class is updated +/// to contain the values read from the configuration file. If the processing +/// fails, the state of the output tree is undefined. +/// +/// \param file The path to the file to process. +/// +/// \throw syntax_error If there is any problem processing the file. +void +config::parser::parse(const fs::path& file) +{ + try { + lutok::do_file(_pimpl->_state, file.str()); + } catch (const lutok::error& e) { + throw syntax_error(e.what()); + } + + if (!_pimpl->_syntax_called) + throw syntax_error("No syntax defined (no call to syntax() found)"); +} diff --git a/external/bsd/kyua-cli/dist/utils/config/parser.hpp b/external/bsd/kyua-cli/dist/utils/config/parser.hpp new file mode 100644 index 000000000..681d1936f --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/config/parser.hpp @@ -0,0 +1,95 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file utils/config/parser.hpp +/// Utilities to read a configuration file into memory. + +#if !defined(UTILS_CONFIG_PARSER_HPP) +#define UTILS_CONFIG_PARSER_HPP + +#include + +#include "utils/fs/path.hpp" +#include "utils/noncopyable.hpp" + +namespace utils { +namespace config { + + +class tree; + + +/// A configuration parser. +/// +/// This parser is a class rather than a function because we need to support +/// callbacks to perform the initialization of the config file schema. The +/// configuration files always start with a call to syntax(), which define the +/// particular version of the schema being used. Depending on such version, the +/// layout of the internal tree representation needs to be different. +/// +/// A parser implementation must provide a setup() method to set up the +/// configuration schema based on the particular combination of syntax format +/// and version specified on the file. +/// +/// Parser objects are not supposed to be reused, and specific trees are not +/// supposed to be passed to multiple parsers (even if sequentially). Doing so +/// will cause all kinds of inconsistencies in the managed tree itself or in the +/// Lua state. +class parser : noncopyable { +public: + struct impl; + +private: + /// Pointer to the internal implementation. + std::auto_ptr< impl > _pimpl; + + /// Hook to initialize the tree keys before reading the file. + /// + /// This hook gets called when the configuration file defines its specific + /// format by calling the syntax() function. We have to delay the tree + /// initialization until this point because, before we know what version of + /// a configuration file we are parsing, we cannot know what keys are valid. + /// + /// \param [in,out] config_tree The tree in which to define the key + /// structure. + /// \param syntax_version The version of the file format as specified in the + /// configuration file. + virtual void setup(tree& config_tree, const int syntax_version) = 0; + +public: + explicit parser(tree&); + virtual ~parser(void); + + void parse(const fs::path&); +}; + + +} // namespace config +} // namespace utils + +#endif // !defined(UTILS_CONFIG_PARSER_HPP) diff --git a/external/bsd/kyua-cli/dist/utils/config/parser_test.cpp b/external/bsd/kyua-cli/dist/utils/config/parser_test.cpp new file mode 100644 index 000000000..f673bc6e9 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/config/parser_test.cpp @@ -0,0 +1,232 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/config/parser.hpp" + +#include + +#include + +#include "utils/config/exceptions.hpp" +#include "utils/config/parser.hpp" +#include "utils/config/tree.ipp" +#include "utils/format/macros.hpp" +#include "utils/fs/path.hpp" + +namespace config = utils::config; +namespace fs = utils::fs; + + +namespace { + + +/// Implementation of a parser for testing purposes. +class mock_parser : public config::parser { + /// Initializes the tree keys before reading the file. + /// + /// \param [in,out] tree The tree in which to define the key structure. + /// \param syntax_version The version of the file format as specified in the + /// configuration file. + void + setup(config::tree& tree, const int syntax_version) + { + if (syntax_version == 1) { + // Do nothing on config_tree. + } else if (syntax_version == 2) { + tree.define< config::string_node >("top_string"); + tree.define< config::int_node >("inner.int"); + tree.define_dynamic("inner.dynamic"); + } else { + throw std::runtime_error(F("Unknown syntax version %s") % + syntax_version); + } + } + +public: + /// Initializes a parser. + mock_parser(config::tree& tree) : + config::parser(tree) + { + } +}; + + +} // anonymous namespace + + +ATF_TEST_CASE_WITHOUT_HEAD(no_keys__ok); +ATF_TEST_CASE_BODY(no_keys__ok) +{ + atf::utils::create_file( + "output.lua", + "syntax(2)\n" + "local foo = 'value'\n"); + + config::tree tree; + mock_parser(tree).parse(fs::path("output.lua")); + ATF_REQUIRE_THROW(config::unknown_key_error, + tree.lookup< config::string_node >("foo")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(no_keys__unknown_key); +ATF_TEST_CASE_BODY(no_keys__unknown_key) +{ + atf::utils::create_file( + "output.lua", + "syntax(2)\n" + "foo = 'value'\n"); + + config::tree tree; + ATF_REQUIRE_THROW_RE(config::syntax_error, "foo", + mock_parser(tree).parse(fs::path("output.lua"))); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(some_keys__ok); +ATF_TEST_CASE_BODY(some_keys__ok) +{ + atf::utils::create_file( + "output.lua", + "syntax(2)\n" + "top_string = 'foo'\n" + "inner.int = 12345\n" + "inner.dynamic.foo = 78\n" + "inner.dynamic.bar = 'some text'\n"); + + config::tree tree; + mock_parser(tree).parse(fs::path("output.lua")); + ATF_REQUIRE_EQ("foo", tree.lookup< config::string_node >("top_string")); + ATF_REQUIRE_EQ(12345, tree.lookup< config::int_node >("inner.int")); + ATF_REQUIRE_EQ("78", + tree.lookup< config::string_node >("inner.dynamic.foo")); + ATF_REQUIRE_EQ("some text", + tree.lookup< config::string_node >("inner.dynamic.bar")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(some_keys__unknown_key); +ATF_TEST_CASE_BODY(some_keys__unknown_key) +{ + atf::utils::create_file( + "output.lua", + "syntax(2)\n" + "top_string2 = 'foo'\n"); + config::tree tree1; + ATF_REQUIRE_THROW_RE(config::syntax_error, + "Unknown configuration property 'top_string2'", + mock_parser(tree1).parse(fs::path("output.lua"))); + + atf::utils::create_file( + "output.lua", + "syntax(2)\n" + "inner.int2 = 12345\n"); + config::tree tree2; + ATF_REQUIRE_THROW_RE(config::syntax_error, + "Unknown configuration property 'inner.int2'", + mock_parser(tree2).parse(fs::path("output.lua"))); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(invalid_syntax); +ATF_TEST_CASE_BODY(invalid_syntax) +{ + config::tree tree; + + atf::utils::create_file("output.lua", "syntax(56)\n"); + ATF_REQUIRE_THROW_RE(config::syntax_error, + "Unknown syntax version 56", + mock_parser(tree).parse(fs::path("output.lua"))); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(syntax_deprecated_format); +ATF_TEST_CASE_BODY(syntax_deprecated_format) +{ + config::tree tree; + + atf::utils::create_file("output.lua", "syntax('config', 1)\n"); + (void)mock_parser(tree).parse(fs::path("output.lua")); + + atf::utils::create_file("output.lua", "syntax('foo', 1)\n"); + ATF_REQUIRE_THROW_RE(config::syntax_error, "must be 'config'", + mock_parser(tree).parse(fs::path("output.lua"))); + + atf::utils::create_file("output.lua", "syntax('config', 2)\n"); + ATF_REQUIRE_THROW_RE(config::syntax_error, "only takes one argument", + mock_parser(tree).parse(fs::path("output.lua"))); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(syntax_not_called); +ATF_TEST_CASE_BODY(syntax_not_called) +{ + config::tree tree; + tree.define< config::int_node >("var"); + + atf::utils::create_file("output.lua", "var = 3\n"); + ATF_REQUIRE_THROW_RE(config::syntax_error, "No syntax defined", + mock_parser(tree).parse(fs::path("output.lua"))); + + ATF_REQUIRE(!tree.is_set("var")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(syntax_called_more_than_once); +ATF_TEST_CASE_BODY(syntax_called_more_than_once) +{ + config::tree tree; + tree.define< config::int_node >("var"); + + atf::utils::create_file( + "output.lua", + "syntax(2)\n" + "var = 3\n" + "syntax(2)\n" + "var = 5\n"); + ATF_REQUIRE_THROW_RE(config::syntax_error, + "syntax\\(\\) can only be called once", + mock_parser(tree).parse(fs::path("output.lua"))); + + ATF_REQUIRE_EQ(3, tree.lookup< config::int_node >("var")); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, no_keys__ok); + ATF_ADD_TEST_CASE(tcs, no_keys__unknown_key); + + ATF_ADD_TEST_CASE(tcs, some_keys__ok); + ATF_ADD_TEST_CASE(tcs, some_keys__unknown_key); + + ATF_ADD_TEST_CASE(tcs, invalid_syntax); + ATF_ADD_TEST_CASE(tcs, syntax_deprecated_format); + ATF_ADD_TEST_CASE(tcs, syntax_not_called); + ATF_ADD_TEST_CASE(tcs, syntax_called_more_than_once); +} diff --git a/external/bsd/kyua-cli/dist/utils/config/tree.cpp b/external/bsd/kyua-cli/dist/utils/config/tree.cpp new file mode 100644 index 000000000..e6a9cdaae --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/config/tree.cpp @@ -0,0 +1,297 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/config/tree.ipp" + +#include "utils/config/exceptions.hpp" +#include "utils/config/keys.hpp" +#include "utils/config/nodes.ipp" +#include "utils/format/macros.hpp" + +namespace config = utils::config; + + +/// Constructor. +config::tree::tree(void) : + _root(new detail::static_inner_node()) +{ +} + + +/// Constructor with a non-empty root. +/// +/// \param root The root to the tree to be owned by this instance. +config::tree::tree(detail::static_inner_node* root) : + _root(root) +{ +} + + +/// Destructor. +config::tree::~tree(void) +{ +} + + +/// Generates a deep copy of the input tree. +/// +/// \return A new tree that is an exact copy of this tree. +config::tree +config::tree::deep_copy(void) const +{ + detail::static_inner_node* new_root = + dynamic_cast< detail::static_inner_node* >(_root->deep_copy()); + return config::tree(new_root); +} + + +/// Registers a node as being dynamic. +/// +/// This operation creates the given key as an inner node. Further set +/// operations that trespass this node will automatically create any missing +/// keys. +/// +/// This method does not raise errors on invalid/unknown keys or other +/// tree-related issues. The reasons is that define() is a method that does not +/// depend on user input: it is intended to pre-populate the tree with a +/// specific structure, and that happens once at coding time. +/// +/// \param dotted_key The key to be registered in dotted representation. +void +config::tree::define_dynamic(const std::string& dotted_key) +{ + try { + const detail::tree_key key = detail::parse_key(dotted_key); + _root->define(key, 0, detail::new_node< detail::dynamic_inner_node >); + } catch (const error& e) { + UNREACHABLE_MSG("define() failing due to key errors is a programming " + "mistake: " + std::string(e.what())); + } +} + + +/// Checks if a given node is set. +/// +/// \param dotted_key The key to be checked. +/// +/// \return True if the key is set to a specific value (not just defined). +/// False if the key is not set or if the key does not exist. +/// +/// \throw invalid_key_error If the provided key has an invalid format. +bool +config::tree::is_set(const std::string& dotted_key) const +{ + const detail::tree_key key = detail::parse_key(dotted_key); + try { + const detail::base_node* raw_node = _root->lookup_ro(key, 0); + try { + const leaf_node& child = dynamic_cast< const leaf_node& >( + *raw_node); + return child.is_set(); + } catch (const std::bad_cast& unused_error) { + return false; + } + } catch (const unknown_key_error& unused_error) { + return false; + } +} + + +/// Pushes a leaf node's value onto the Lua stack. +/// +/// \param dotted_key The key to be pushed. +/// \param state The Lua state into which to push the key's value. +/// +/// \throw invalid_key_error If the provided key has an invalid format. +/// \throw unknown_key_error If the provided key is unknown. +void +config::tree::push_lua(const std::string& dotted_key, lutok::state& state) const +{ + const detail::tree_key key = detail::parse_key(dotted_key); + const detail::base_node* raw_node = _root->lookup_ro(key, 0); + try { + const leaf_node& child = dynamic_cast< const leaf_node& >(*raw_node); + child.push_lua(state); + } catch (const std::bad_cast& unused_error) { + throw unknown_key_error(key); + } +} + + +/// Sets a leaf node's value from a value in the Lua stack. +/// +/// \param dotted_key The key to be set. +/// \param state The Lua state from which to retrieve the value. +/// \param value_index The position in the Lua stack holding the value. +/// +/// \throw invalid_key_error If the provided key has an invalid format. +/// \throw unknown_key_error If the provided key is unknown. +/// \throw value_error If the value mismatches the node type. +void +config::tree::set_lua(const std::string& dotted_key, lutok::state& state, + const int value_index) +{ + const detail::tree_key key = detail::parse_key(dotted_key); + detail::base_node* raw_node = _root->lookup_rw( + key, 0, detail::new_node< string_node >); + try { + leaf_node& child = dynamic_cast< leaf_node& >(*raw_node); + child.set_lua(state, value_index); + } catch (const std::bad_cast& unused_error) { + throw value_error(F("Invalid value for key '%s'") % + detail::flatten_key(key)); + } +} + + +/// Gets the value of a node as a plain string. +/// +/// \param dotted_key The key to be looked up. +/// +/// \return The value of the located node as a string. +/// +/// \throw invalid_key_error If the provided key has an invalid format. +/// \throw unknown_key_error If the provided key is unknown. +std::string +config::tree::lookup_string(const std::string& dotted_key) const +{ + const detail::tree_key key = detail::parse_key(dotted_key); + const detail::base_node* raw_node = _root->lookup_ro(key, 0); + try { + const leaf_node& child = dynamic_cast< const leaf_node& >(*raw_node); + return child.to_string(); + } catch (const std::bad_cast& unused_error) { + throw unknown_key_error(key); + } +} + + +/// Sets the value of a leaf addressed by its key from a string value. +/// +/// This respects the native types of all the nodes that have been predefined. +/// For new nodes under a dynamic subtree, this has no mechanism of determining +/// what type they need to have, so they are created as plain string nodes. +/// +/// \param dotted_key The key to be registered in dotted representation. +/// \param raw_value The string representation of the value to set the node to. +/// +/// \throw invalid_key_error If the provided key has an invalid format. +/// \throw unknown_key_error If the provided key is unknown. +/// \throw value_error If the value mismatches the node type. +void +config::tree::set_string(const std::string& dotted_key, + const std::string& raw_value) +{ + const detail::tree_key key = detail::parse_key(dotted_key); + detail::base_node* raw_node = _root->lookup_rw( + key, 0, detail::new_node< string_node >); + try { + leaf_node& child = dynamic_cast< leaf_node& >(*raw_node); + child.set_string(raw_value); + } catch (const std::bad_cast& unused_error) { + throw value_error(F("Invalid value for key '%s'") % + detail::flatten_key(key)); + } +} + + +/// Converts the tree to a collection of key/value string pairs. +/// +/// \param dotted_key Subtree from which to start the export. +/// \param strip_key If true, remove the dotted_key prefix from the resulting +/// properties. +/// +/// \return A map of keys to values in their textual representation. +/// +/// \throw invalid_key_error If the provided key has an invalid format. +/// \throw unknown_key_error If the provided key is unknown. +/// \throw value_error If the provided key points to a leaf. +config::properties_map +config::tree::all_properties(const std::string& dotted_key, + const bool strip_key) const +{ + PRE(!strip_key || !dotted_key.empty()); + + properties_map properties; + + detail::tree_key key; + const detail::base_node* raw_node; + if (dotted_key.empty()) { + raw_node = _root.get(); + } else { + key = detail::parse_key(dotted_key); + raw_node = _root->lookup_ro(key, 0); + } + try { + const detail::inner_node& child = + dynamic_cast< const detail::inner_node& >(*raw_node); + child.all_properties(properties, key); + } catch (const std::bad_cast& unused_error) { + INV(!dotted_key.empty()); + throw value_error(F("Cannot export properties from a leaf node; " + "'%s' given") % dotted_key); + } + + if (strip_key) { + properties_map stripped; + for (properties_map::const_iterator iter = properties.begin(); + iter != properties.end(); ++iter) { + stripped[(*iter).first.substr(dotted_key.length() + 1)] = + (*iter).second; + } + properties = stripped; + } + + return properties; +} + + +/// Equality comparator. +/// +/// \param other The other object to compare this one to. +/// +/// \return True if this object and other are equal; false otherwise. +bool +config::tree::operator==(const tree& other) const +{ + // TODO(jmmv): Would be nicer to perform the comparison directly on the + // nodes, instead of exporting the values to strings first. + return _root == other._root || all_properties() == other.all_properties(); +} + + +/// Inequality comparator. +/// +/// \param other The other object to compare this one to. +/// +/// \return True if this object and other are different; false otherwise. +bool +config::tree::operator!=(const tree& other) const +{ + return !(*this == other); +} diff --git a/external/bsd/kyua-cli/dist/utils/config/tree.hpp b/external/bsd/kyua-cli/dist/utils/config/tree.hpp new file mode 100644 index 000000000..0075c5765 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/config/tree.hpp @@ -0,0 +1,127 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file utils/config/tree.hpp +/// Data type to represent a tree of arbitrary values with string keys. + +#if !defined(UTILS_CONFIG_TREE_HPP) +#define UTILS_CONFIG_TREE_HPP + +#include +#include +#include + +#include + +#include "utils/config/keys.hpp" +#include "utils/config/nodes.hpp" + +namespace utils { +namespace config { + + +/// Flat representation of all properties as strings. +typedef std::map< std::string, std::string > properties_map; + + +/// Representation of a tree. +/// +/// The string keys of the tree are in dotted notation and actually represent +/// path traversals through the nodes. +/// +/// Our trees are "strictly-keyed": keys must be defined as "existent" before +/// their values can be set. Defining a key is a separate action from setting +/// its value. The rationale is that we want to be able to control what keys +/// get defined: because trees are used to hold configuration, we want to catch +/// typos as early as possible. Also, users cannot set keys unless the types +/// are known in advance because our leaf nodes are strictly typed. +/// +/// However, there is an exception to the strict keys: the inner nodes of the +/// tree can be static or dynamic. Static inner nodes have a known subset of +/// children and attempting to set keys not previously defined will result in an +/// error. Dynamic inner nodes do not have a predefined set of keys and can be +/// used to accept arbitrary user input. +/// +/// For simplicity reasons, we force the root of the tree to be a static inner +/// node. In other words, the root can never contain a value by itself and this +/// is not a problem because the root is not addressable by the key space. +/// Additionally, the root is strict so all of its direct children must be +/// explicitly defined. +/// +/// This is, effectively, a simple wrapper around the node representing the +/// root. Having a separate class aids in clearly representing the concept of a +/// tree and all of its public methods. Also, the tree accepts dotted notations +/// for the keys while the internal structures do not. +/// +/// Note that trees are shallow-copied unless a deep copy is requested with +/// deep_copy(). +class tree { + /// The root of the tree. + std::tr1::shared_ptr< detail::static_inner_node > _root; + + explicit tree(detail::static_inner_node*); + +public: + tree(void); + ~tree(void); + + tree deep_copy(void) const; + + template< class LeafType > + void define(const std::string&); + + void define_dynamic(const std::string&); + + bool is_set(const std::string&) const; + + template< class LeafType > + const typename LeafType::value_type& lookup(const std::string&) const; + template< class LeafType > + typename LeafType::value_type& lookup_rw(const std::string&); + + template< class LeafType > + void set(const std::string&, const typename LeafType::value_type&); + + void push_lua(const std::string&, lutok::state&) const; + void set_lua(const std::string&, lutok::state&, const int); + + std::string lookup_string(const std::string&) const; + void set_string(const std::string&, const std::string&); + + properties_map all_properties(const std::string& = "", + const bool = false) const; + + bool operator==(const tree&) const; + bool operator!=(const tree&) const; +}; + + +} // namespace config +} // namespace utils + +#endif // !defined(UTILS_CONFIG_TREE_HPP) diff --git a/external/bsd/kyua-cli/dist/utils/config/tree.ipp b/external/bsd/kyua-cli/dist/utils/config/tree.ipp new file mode 100644 index 000000000..12b3fc9bf --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/config/tree.ipp @@ -0,0 +1,151 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/config/tree.hpp" + +#if !defined(UTILS_CONFIG_TREE_IPP) +#define UTILS_CONFIG_TREE_IPP + +#include + +#include "utils/config/exceptions.hpp" +#include "utils/config/nodes.ipp" +#include "utils/format/macros.hpp" +#include "utils/sanity.hpp" + +namespace utils { + + +/// Registers a key as valid and having a specific type. +/// +/// This method does not raise errors on invalid/unknown keys or other +/// tree-related issues. The reasons is that define() is a method that does not +/// depend on user input: it is intended to pre-populate the tree with a +/// specific structure, and that happens once at coding time. +/// +/// \tparam LeafType The node type of the leaf we are defining. +/// \param dotted_key The key to be registered in dotted representation. +template< class LeafType > +void +config::tree::define(const std::string& dotted_key) +{ + try { + const detail::tree_key key = detail::parse_key(dotted_key); + _root->define(key, 0, detail::new_node< LeafType >); + } catch (const error& e) { + UNREACHABLE_MSG(F("define() failing due to key errors is a programming " + "mistake: %s") % e.what()); + } +} + + +/// Gets a read-only reference to the value of a leaf addressed by its key. +/// +/// \tparam LeafType The node type of the leaf we are querying. +/// \param dotted_key The key to be registered in dotted representation. +/// +/// \return A reference to the value in the located leaf, if successful. +/// +/// \throw invalid_key_error If the provided key has an invalid format. +/// \throw unknown_key_error If the provided key is unknown. +template< class LeafType > +const typename LeafType::value_type& +config::tree::lookup(const std::string& dotted_key) const +{ + const detail::tree_key key = detail::parse_key(dotted_key); + const detail::base_node* raw_node = _root->lookup_ro(key, 0); + try { + const LeafType& child = dynamic_cast< const LeafType& >(*raw_node); + if (child.is_set()) + return child.value(); + else + throw unknown_key_error(key); + } catch (const std::bad_cast& unused_error) { + throw unknown_key_error(key); + } +} + + +/// Gets a read-write reference to the value of a leaf addressed by its key. +/// +/// \tparam LeafType The node type of the leaf we are querying. +/// \param dotted_key The key to be registered in dotted representation. +/// +/// \return A reference to the value in the located leaf, if successful. +/// +/// \throw invalid_key_error If the provided key has an invalid format. +/// \throw unknown_key_error If the provided key is unknown. +template< class LeafType > +typename LeafType::value_type& +config::tree::lookup_rw(const std::string& dotted_key) +{ + const detail::tree_key key = detail::parse_key(dotted_key); + detail::base_node* raw_node = _root->lookup_rw( + key, 0, detail::new_node< LeafType >); + try { + LeafType& child = dynamic_cast< LeafType& >(*raw_node); + if (child.is_set()) + return child.value(); + else + throw unknown_key_error(key); + } catch (const std::bad_cast& unused_error) { + throw unknown_key_error(key); + } +} + + +/// Sets the value of a leaf addressed by its key. +/// +/// \tparam LeafType The node type of the leaf we are setting. +/// \param dotted_key The key to be registered in dotted representation. +/// \param value The value to set into the node. +/// +/// \throw invalid_key_error If the provided key has an invalid format. +/// \throw unknown_key_error If the provided key is unknown. +/// \throw value_error If the value mismatches the node type. +template< class LeafType > +void +config::tree::set(const std::string& dotted_key, + const typename LeafType::value_type& value) +{ + const detail::tree_key key = detail::parse_key(dotted_key); + leaf_node* raw_node = _root->lookup_rw(key, 0, + detail::new_node< LeafType >); + try { + LeafType& child = dynamic_cast< LeafType& >(*raw_node); + child.set(value); + } catch (const std::bad_cast& unused_error) { + throw value_error(F("Invalid value for key '%s'") % + detail::flatten_key(key)); + } +} + + +} // namespace utils + +#endif // !defined(UTILS_CONFIG_TREE_IPP) diff --git a/external/bsd/kyua-cli/dist/utils/config/tree_test.cpp b/external/bsd/kyua-cli/dist/utils/config/tree_test.cpp new file mode 100644 index 000000000..129d3eaf8 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/config/tree_test.cpp @@ -0,0 +1,846 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/config/tree.ipp" + +#include + +#include "utils/config/nodes.ipp" +#include "utils/format/macros.hpp" +#include "utils/text/operations.ipp" + +namespace config = utils::config; +namespace text = utils::text; + + +namespace { + + +/// Simple wrapper around an integer value without default constructors. +/// +/// The purpose of this type is to have a simple class without default +/// constructors to validate that we can use it as a leaf of a tree. +class int_wrapper { + /// The wrapped integer value. + int _value; + +public: + /// Constructs a new wrapped integer. + /// + /// \param value_ The value to store in the object. + explicit int_wrapper(int value_) : + _value(value_) + { + } + + /// Gets the integer value stored in the object. + int + value(void) const + { + return _value; + } +}; + + +/// Custom tree leaf type for an object without defualt constructors. +class wrapped_int_node : public config::typed_leaf_node< int_wrapper > { +public: + /// Copies the node. + /// + /// \return A dynamically-allocated node. + virtual base_node* + deep_copy(void) const + { + std::auto_ptr< wrapped_int_node > new_node(new wrapped_int_node()); + new_node->_value = _value; + return new_node.release(); + } + + /// Pushes the node's value onto the Lua stack. + /// + /// \param state The Lua state onto which to push the value. + void + push_lua(lutok::state& state) const + { + state.push_integer( + config::typed_leaf_node< int_wrapper >::value().value()); + } + + /// Sets the value of the node from an entry in the Lua stack. + /// + /// \param state The Lua state from which to get the value. + /// \param value_index The stack index in which the value resides. + void + set_lua(lutok::state& state, const int value_index) + { + ATF_REQUIRE(state.is_number(value_index)); + int_wrapper new_value(state.to_integer(value_index)); + config::typed_leaf_node< int_wrapper >::set(new_value); + } + + /// Sets the value of the node from a raw string representation. + /// + /// \param raw_value The value to set the node to. + void + set_string(const std::string& raw_value) + { + int_wrapper new_value(text::to_type< int >(raw_value)); + config::typed_leaf_node< int_wrapper >::set(new_value); + } + + /// Converts the contents of the node to a string. + /// + /// \return A string representation of the value held by the node. + std::string + to_string(void) const + { + return F("%s") % + config::typed_leaf_node< int_wrapper >::value().value(); + } +}; + + +} // anonymous namespace + + +ATF_TEST_CASE_WITHOUT_HEAD(define_set_lookup__one_level); +ATF_TEST_CASE_BODY(define_set_lookup__one_level) +{ + config::tree tree; + + tree.define< config::int_node >("var1"); + tree.define< config::string_node >("var2"); + tree.define< config::bool_node >("var3"); + + tree.set< config::int_node >("var1", 42); + tree.set< config::string_node >("var2", "hello"); + tree.set< config::bool_node >("var3", false); + + ATF_REQUIRE_EQ(42, tree.lookup< config::int_node >("var1")); + ATF_REQUIRE_EQ("hello", tree.lookup< config::string_node >("var2")); + ATF_REQUIRE(!tree.lookup< config::bool_node >("var3")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(define_set_lookup__multiple_levels); +ATF_TEST_CASE_BODY(define_set_lookup__multiple_levels) +{ + config::tree tree; + + tree.define< config::int_node >("foo.bar.1"); + tree.define< config::string_node >("foo.bar.2"); + tree.define< config::bool_node >("foo.3"); + tree.define_dynamic("sub.tree"); + + tree.set< config::int_node >("foo.bar.1", 42); + tree.set< config::string_node >("foo.bar.2", "hello"); + tree.set< config::bool_node >("foo.3", true); + tree.set< config::string_node >("sub.tree.1", "bye"); + tree.set< config::int_node >("sub.tree.2", 4); + tree.set< config::int_node >("sub.tree.3.4", 123); + + ATF_REQUIRE_EQ(42, tree.lookup< config::int_node >("foo.bar.1")); + ATF_REQUIRE_EQ("hello", tree.lookup< config::string_node >("foo.bar.2")); + ATF_REQUIRE(tree.lookup< config::bool_node >("foo.3")); + ATF_REQUIRE_EQ(4, tree.lookup< config::int_node >("sub.tree.2")); + ATF_REQUIRE_EQ(123, tree.lookup< config::int_node >("sub.tree.3.4")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(deep_copy__empty); +ATF_TEST_CASE_BODY(deep_copy__empty) +{ + config::tree tree1; + config::tree tree2 = tree1.deep_copy(); + + tree1.define< config::bool_node >("var1"); + // This would crash if the copy shared the internal data. + tree2.define< config::int_node >("var1"); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(deep_copy__some); +ATF_TEST_CASE_BODY(deep_copy__some) +{ + config::tree tree1; + tree1.define< config::bool_node >("this.is.a.var"); + tree1.set< config::bool_node >("this.is.a.var", true); + tree1.define< config::int_node >("this.is.another.var"); + tree1.set< config::int_node >("this.is.another.var", 34); + tree1.define< config::int_node >("and.another"); + tree1.set< config::int_node >("and.another", 123); + + config::tree tree2 = tree1.deep_copy(); + tree2.set< config::bool_node >("this.is.a.var", false); + tree2.set< config::int_node >("this.is.another.var", 43); + + ATF_REQUIRE( tree1.lookup< config::bool_node >("this.is.a.var")); + ATF_REQUIRE(!tree2.lookup< config::bool_node >("this.is.a.var")); + + ATF_REQUIRE_EQ(34, tree1.lookup< config::int_node >("this.is.another.var")); + ATF_REQUIRE_EQ(43, tree2.lookup< config::int_node >("this.is.another.var")); + + ATF_REQUIRE_EQ(123, tree1.lookup< config::int_node >("and.another")); + ATF_REQUIRE_EQ(123, tree2.lookup< config::int_node >("and.another")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(lookup__invalid_key); +ATF_TEST_CASE_BODY(lookup__invalid_key) +{ + config::tree tree; + + ATF_REQUIRE_THROW(config::invalid_key_error, + tree.lookup< config::int_node >(".")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(lookup__unknown_key); +ATF_TEST_CASE_BODY(lookup__unknown_key) +{ + config::tree tree; + + tree.define< config::int_node >("foo.bar"); + tree.define< config::int_node >("a.b.c"); + tree.define_dynamic("a.d"); + tree.set< config::int_node >("a.b.c", 123); + tree.set< config::int_node >("a.d.100", 0); + + ATF_REQUIRE_THROW(config::unknown_key_error, + tree.lookup< config::int_node >("abc")); + + ATF_REQUIRE_THROW(config::unknown_key_error, + tree.lookup< config::int_node >("foo")); + ATF_REQUIRE_THROW(config::unknown_key_error, + tree.lookup< config::int_node >("foo.bar")); + ATF_REQUIRE_THROW(config::unknown_key_error, + tree.lookup< config::int_node >("foo.bar.baz")); + + ATF_REQUIRE_THROW(config::unknown_key_error, + tree.lookup< config::int_node >("a")); + ATF_REQUIRE_THROW(config::unknown_key_error, + tree.lookup< config::int_node >("a.b")); + ATF_REQUIRE_THROW(config::unknown_key_error, + tree.lookup< config::int_node >("a.c")); + (void)tree.lookup< config::int_node >("a.b.c"); + ATF_REQUIRE_THROW(config::unknown_key_error, + tree.lookup< config::int_node >("a.b.c.d")); + ATF_REQUIRE_THROW(config::unknown_key_error, + tree.lookup< config::int_node >("a.d")); + (void)tree.lookup< config::int_node >("a.d.100"); + ATF_REQUIRE_THROW(config::unknown_key_error, + tree.lookup< config::int_node >("a.d.101")); + ATF_REQUIRE_THROW(config::unknown_key_error, + tree.lookup< config::int_node >("a.d.100.3")); + ATF_REQUIRE_THROW(config::unknown_key_error, + tree.lookup< config::int_node >("a.d.e")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(is_set__one_level); +ATF_TEST_CASE_BODY(is_set__one_level) +{ + config::tree tree; + + tree.define< config::int_node >("var1"); + tree.define< config::string_node >("var2"); + tree.define< config::bool_node >("var3"); + + tree.set< config::int_node >("var1", 42); + tree.set< config::bool_node >("var3", false); + + ATF_REQUIRE( tree.is_set("var1")); + ATF_REQUIRE(!tree.is_set("var2")); + ATF_REQUIRE( tree.is_set("var3")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(is_set__multiple_levels); +ATF_TEST_CASE_BODY(is_set__multiple_levels) +{ + config::tree tree; + + tree.define< config::int_node >("a.b.var1"); + tree.define< config::string_node >("a.b.var2"); + tree.define< config::bool_node >("e.var3"); + + tree.set< config::int_node >("a.b.var1", 42); + tree.set< config::bool_node >("e.var3", false); + + ATF_REQUIRE(!tree.is_set("a")); + ATF_REQUIRE(!tree.is_set("a.b")); + ATF_REQUIRE( tree.is_set("a.b.var1")); + ATF_REQUIRE(!tree.is_set("a.b.var1.trailing")); + + ATF_REQUIRE(!tree.is_set("a")); + ATF_REQUIRE(!tree.is_set("a.b")); + ATF_REQUIRE(!tree.is_set("a.b.var2")); + ATF_REQUIRE(!tree.is_set("a.b.var2.trailing")); + + ATF_REQUIRE(!tree.is_set("e")); + ATF_REQUIRE( tree.is_set("e.var3")); + ATF_REQUIRE(!tree.is_set("e.var3.trailing")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(is_set__invalid_key); +ATF_TEST_CASE_BODY(is_set__invalid_key) +{ + config::tree tree; + + ATF_REQUIRE_THROW(config::invalid_key_error, tree.is_set(".abc")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(set__invalid_key); +ATF_TEST_CASE_BODY(set__invalid_key) +{ + config::tree tree; + + ATF_REQUIRE_THROW(config::invalid_key_error, + tree.set< config::int_node >("foo.", 54)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(set__unknown_key); +ATF_TEST_CASE_BODY(set__unknown_key) +{ + config::tree tree; + + tree.define< config::int_node >("foo.bar"); + tree.define< config::int_node >("a.b.c"); + tree.define_dynamic("a.d"); + tree.set< config::int_node >("a.b.c", 123); + tree.set< config::string_node >("a.d.3", "foo"); + + ATF_REQUIRE_THROW(config::unknown_key_error, + tree.set< config::int_node >("abc", 2)); + + tree.set< config::int_node >("foo.bar", 15); + ATF_REQUIRE_THROW(config::unknown_key_error, + tree.set< config::int_node >("foo.bar.baz", 0)); + + ATF_REQUIRE_THROW(config::unknown_key_error, + tree.set< config::int_node >("a.c", 100)); + tree.set< config::int_node >("a.b.c", -3); + ATF_REQUIRE_THROW(config::unknown_key_error, + tree.set< config::int_node >("a.b.c.d", 82)); + tree.set< config::string_node >("a.d.3", "bar"); + tree.set< config::string_node >("a.d.4", "bar"); + ATF_REQUIRE_THROW(config::unknown_key_error, + tree.set< config::int_node >("a.d.4.5", 82)); + tree.set< config::int_node >("a.d.5.6", 82); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(set__value_error); +ATF_TEST_CASE_BODY(set__value_error) +{ + config::tree tree; + + tree.define< config::int_node >("foo.bar"); + tree.define_dynamic("a.d"); + + ATF_REQUIRE_THROW(config::value_error, + tree.set< config::int_node >("foo", 3)); + ATF_REQUIRE_THROW(config::value_error, + tree.set< config::int_node >("a", -10)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(push_lua__ok); +ATF_TEST_CASE_BODY(push_lua__ok) +{ + config::tree tree; + + tree.define< config::int_node >("top.integer"); + tree.define< wrapped_int_node >("top.custom"); + tree.define_dynamic("dynamic"); + tree.set< config::int_node >("top.integer", 5); + tree.set< wrapped_int_node >("top.custom", int_wrapper(10)); + tree.set_string("dynamic.first", "foo"); + + lutok::state state; + tree.push_lua("top.integer", state); + tree.push_lua("top.custom", state); + tree.push_lua("dynamic.first", state); + ATF_REQUIRE(state.is_number(-3)); + ATF_REQUIRE_EQ(5, state.to_integer(-3)); + ATF_REQUIRE(state.is_number(-2)); + ATF_REQUIRE_EQ(10, state.to_integer(-2)); + ATF_REQUIRE(state.is_string(-1)); + ATF_REQUIRE_EQ("foo", state.to_string(-1)); + state.pop(3); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(set_lua__ok); +ATF_TEST_CASE_BODY(set_lua__ok) +{ + config::tree tree; + + tree.define< config::int_node >("top.integer"); + tree.define< wrapped_int_node >("top.custom"); + tree.define_dynamic("dynamic"); + + { + lutok::state state; + state.push_integer(5); + state.push_integer(10); + state.push_string("foo"); + tree.set_lua("top.integer", state, -3); + tree.set_lua("top.custom", state, -2); + tree.set_lua("dynamic.first", state, -1); + state.pop(3); + } + + ATF_REQUIRE_EQ(5, tree.lookup< config::int_node >("top.integer")); + ATF_REQUIRE_EQ(10, tree.lookup< wrapped_int_node >("top.custom").value()); + ATF_REQUIRE_EQ("foo", tree.lookup< config::string_node >("dynamic.first")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(lookup_rw); +ATF_TEST_CASE_BODY(lookup_rw) +{ + config::tree tree; + + tree.define< config::int_node >("var1"); + tree.define< config::bool_node >("var3"); + + tree.set< config::int_node >("var1", 42); + tree.set< config::bool_node >("var3", false); + + tree.lookup_rw< config::int_node >("var1") += 10; + ATF_REQUIRE_EQ(52, tree.lookup< config::int_node >("var1")); + ATF_REQUIRE(!tree.lookup< config::bool_node >("var3")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(lookup_string__ok); +ATF_TEST_CASE_BODY(lookup_string__ok) +{ + config::tree tree; + + tree.define< config::int_node >("var1"); + tree.define< config::string_node >("b.var2"); + tree.define< config::bool_node >("c.d.var3"); + + tree.set< config::int_node >("var1", 42); + tree.set< config::string_node >("b.var2", "hello"); + tree.set< config::bool_node >("c.d.var3", false); + + ATF_REQUIRE_EQ("42", tree.lookup_string("var1")); + ATF_REQUIRE_EQ("hello", tree.lookup_string("b.var2")); + ATF_REQUIRE_EQ("false", tree.lookup_string("c.d.var3")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(lookup_string__invalid_key); +ATF_TEST_CASE_BODY(lookup_string__invalid_key) +{ + config::tree tree; + + ATF_REQUIRE_THROW(config::invalid_key_error, tree.lookup_string("")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(lookup_string__unknown_key); +ATF_TEST_CASE_BODY(lookup_string__unknown_key) +{ + config::tree tree; + + tree.define< config::int_node >("a.b.c"); + + ATF_REQUIRE_THROW(config::unknown_key_error, tree.lookup_string("a.b")); + ATF_REQUIRE_THROW(config::unknown_key_error, tree.lookup_string("a.b.c.d")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(set_string__ok); +ATF_TEST_CASE_BODY(set_string__ok) +{ + config::tree tree; + + tree.define< config::int_node >("foo.bar.1"); + tree.define< config::string_node >("foo.bar.2"); + tree.define_dynamic("sub.tree"); + + tree.set_string("foo.bar.1", "42"); + tree.set_string("foo.bar.2", "hello"); + tree.set_string("sub.tree.2", "15"); + tree.set_string("sub.tree.3.4", "bye"); + + ATF_REQUIRE_EQ(42, tree.lookup< config::int_node >("foo.bar.1")); + ATF_REQUIRE_EQ("hello", tree.lookup< config::string_node >("foo.bar.2")); + ATF_REQUIRE_EQ("15", tree.lookup< config::string_node >("sub.tree.2")); + ATF_REQUIRE_EQ("bye", tree.lookup< config::string_node >("sub.tree.3.4")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(set_string__invalid_key); +ATF_TEST_CASE_BODY(set_string__invalid_key) +{ + config::tree tree; + + ATF_REQUIRE_THROW(config::invalid_key_error, tree.set_string(".", "foo")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(set_string__unknown_key); +ATF_TEST_CASE_BODY(set_string__unknown_key) +{ + config::tree tree; + + tree.define< config::int_node >("foo.bar"); + tree.define< config::int_node >("a.b.c"); + tree.define_dynamic("a.d"); + tree.set_string("a.b.c", "123"); + tree.set_string("a.d.3", "foo"); + + ATF_REQUIRE_THROW(config::unknown_key_error, tree.set_string("abc", "2")); + + tree.set_string("foo.bar", "15"); + ATF_REQUIRE_THROW(config::unknown_key_error, + tree.set_string("foo.bar.baz", "0")); + + ATF_REQUIRE_THROW(config::unknown_key_error, + tree.set_string("a.c", "100")); + tree.set_string("a.b.c", "-3"); + ATF_REQUIRE_THROW(config::unknown_key_error, + tree.set_string("a.b.c.d", "82")); + tree.set_string("a.d.3", "bar"); + tree.set_string("a.d.4", "bar"); + ATF_REQUIRE_THROW(config::unknown_key_error, + tree.set_string("a.d.4.5", "82")); + tree.set_string("a.d.5.6", "82"); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(set_string__value_error); +ATF_TEST_CASE_BODY(set_string__value_error) +{ + config::tree tree; + + tree.define< config::int_node >("foo.bar"); + + ATF_REQUIRE_THROW(config::value_error, + tree.set_string("foo", "abc")); + ATF_REQUIRE_THROW(config::value_error, + tree.set_string("foo.bar", " -3")); + ATF_REQUIRE_THROW(config::value_error, + tree.set_string("foo.bar", "3 ")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(all_properties__none); +ATF_TEST_CASE_BODY(all_properties__none) +{ + const config::tree tree; + ATF_REQUIRE(tree.all_properties().empty()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(all_properties__all_set); +ATF_TEST_CASE_BODY(all_properties__all_set) +{ + config::tree tree; + + tree.define< config::int_node >("plain"); + tree.set< config::int_node >("plain", 1234); + + tree.define< config::int_node >("static.first"); + tree.set< config::int_node >("static.first", -3); + tree.define< config::string_node >("static.second"); + tree.set< config::string_node >("static.second", "some text"); + + tree.define_dynamic("dynamic"); + tree.set< config::string_node >("dynamic.first", "hello"); + tree.set< config::string_node >("dynamic.second", "bye"); + + config::properties_map exp_properties; + exp_properties["plain"] = "1234"; + exp_properties["static.first"] = "-3"; + exp_properties["static.second"] = "some text"; + exp_properties["dynamic.first"] = "hello"; + exp_properties["dynamic.second"] = "bye"; + + const config::properties_map properties = tree.all_properties(); + ATF_REQUIRE(exp_properties == properties); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(all_properties__some_unset); +ATF_TEST_CASE_BODY(all_properties__some_unset) +{ + config::tree tree; + + tree.define< config::int_node >("static.first"); + tree.set< config::int_node >("static.first", -3); + tree.define< config::string_node >("static.second"); + + tree.define_dynamic("dynamic"); + + config::properties_map exp_properties; + exp_properties["static.first"] = "-3"; + + const config::properties_map properties = tree.all_properties(); + ATF_REQUIRE(exp_properties == properties); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(all_properties__subtree__inner); +ATF_TEST_CASE_BODY(all_properties__subtree__inner) +{ + config::tree tree; + + tree.define< config::int_node >("root.a.b.c.first"); + tree.define< config::int_node >("root.a.b.c.second"); + tree.define< config::int_node >("root.a.d.first"); + + tree.set< config::int_node >("root.a.b.c.first", 1); + tree.set< config::int_node >("root.a.b.c.second", 2); + tree.set< config::int_node >("root.a.d.first", 3); + + { + config::properties_map exp_properties; + exp_properties["root.a.b.c.first"] = "1"; + exp_properties["root.a.b.c.second"] = "2"; + exp_properties["root.a.d.first"] = "3"; + ATF_REQUIRE(exp_properties == tree.all_properties("root")); + ATF_REQUIRE(exp_properties == tree.all_properties("root.a")); + } + + { + config::properties_map exp_properties; + exp_properties["root.a.b.c.first"] = "1"; + exp_properties["root.a.b.c.second"] = "2"; + ATF_REQUIRE(exp_properties == tree.all_properties("root.a.b")); + ATF_REQUIRE(exp_properties == tree.all_properties("root.a.b.c")); + } + + { + config::properties_map exp_properties; + exp_properties["root.a.d.first"] = "3"; + ATF_REQUIRE(exp_properties == tree.all_properties("root.a.d")); + } +} + + +ATF_TEST_CASE_WITHOUT_HEAD(all_properties__subtree__leaf); +ATF_TEST_CASE_BODY(all_properties__subtree__leaf) +{ + config::tree tree; + + tree.define< config::int_node >("root.a.b.c.first"); + tree.set< config::int_node >("root.a.b.c.first", 1); + ATF_REQUIRE_THROW_RE(config::value_error, "Cannot export.*leaf", + tree.all_properties("root.a.b.c.first")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(all_properties__subtree__strip_key); +ATF_TEST_CASE_BODY(all_properties__subtree__strip_key) +{ + config::tree tree; + + tree.define< config::int_node >("root.a.b.c.first"); + tree.define< config::int_node >("root.a.b.c.second"); + tree.define< config::int_node >("root.a.d.first"); + + tree.set< config::int_node >("root.a.b.c.first", 1); + tree.set< config::int_node >("root.a.b.c.second", 2); + tree.set< config::int_node >("root.a.d.first", 3); + + config::properties_map exp_properties; + exp_properties["b.c.first"] = "1"; + exp_properties["b.c.second"] = "2"; + exp_properties["d.first"] = "3"; + ATF_REQUIRE(exp_properties == tree.all_properties("root.a", true)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(all_properties__subtree__invalid_key); +ATF_TEST_CASE_BODY(all_properties__subtree__invalid_key) +{ + config::tree tree; + + ATF_REQUIRE_THROW(config::invalid_key_error, tree.all_properties(".")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(all_properties__subtree__unknown_key); +ATF_TEST_CASE_BODY(all_properties__subtree__unknown_key) +{ + config::tree tree; + + tree.define< config::int_node >("root.a.b.c.first"); + tree.set< config::int_node >("root.a.b.c.first", 1); + tree.define< config::int_node >("root.a.b.c.unset"); + + ATF_REQUIRE_THROW(config::unknown_key_error, + tree.all_properties("root.a.b.c.first.foo")); + ATF_REQUIRE_THROW_RE(config::value_error, "Cannot export.*leaf", + tree.all_properties("root.a.b.c.unset")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(operators_eq_and_ne__empty); +ATF_TEST_CASE_BODY(operators_eq_and_ne__empty) +{ + config::tree t1; + config::tree t2; + ATF_REQUIRE( t1 == t2); + ATF_REQUIRE(!(t1 != t2)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(operators_eq_and_ne__shallow_copy); +ATF_TEST_CASE_BODY(operators_eq_and_ne__shallow_copy) +{ + config::tree t1; + t1.define< config::int_node >("root.a.b.c.first"); + t1.set< config::int_node >("root.a.b.c.first", 1); + config::tree t2 = t1; + ATF_REQUIRE( t1 == t2); + ATF_REQUIRE(!(t1 != t2)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(operators_eq_and_ne__deep_copy); +ATF_TEST_CASE_BODY(operators_eq_and_ne__deep_copy) +{ + config::tree t1; + t1.define< config::int_node >("root.a.b.c.first"); + t1.set< config::int_node >("root.a.b.c.first", 1); + config::tree t2 = t1.deep_copy(); + ATF_REQUIRE( t1 == t2); + ATF_REQUIRE(!(t1 != t2)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(operators_eq_and_ne__some_contents); +ATF_TEST_CASE_BODY(operators_eq_and_ne__some_contents) +{ + config::tree t1, t2; + + t1.define< config::int_node >("root.a.b.c.first"); + t1.set< config::int_node >("root.a.b.c.first", 1); + ATF_REQUIRE(!(t1 == t2)); + ATF_REQUIRE( t1 != t2); + + t2.define< config::int_node >("root.a.b.c.first"); + t2.set< config::int_node >("root.a.b.c.first", 1); + ATF_REQUIRE( t1 == t2); + ATF_REQUIRE(!(t1 != t2)); + + t1.set< config::int_node >("root.a.b.c.first", 2); + ATF_REQUIRE(!(t1 == t2)); + ATF_REQUIRE( t1 != t2); + + t2.set< config::int_node >("root.a.b.c.first", 2); + ATF_REQUIRE( t1 == t2); + ATF_REQUIRE(!(t1 != t2)); + + t1.define< config::string_node >("another.key"); + t1.set< config::string_node >("another.key", "some text"); + ATF_REQUIRE(!(t1 == t2)); + ATF_REQUIRE( t1 != t2); + + t2.define< config::string_node >("another.key"); + t2.set< config::string_node >("another.key", "some text"); + ATF_REQUIRE( t1 == t2); + ATF_REQUIRE(!(t1 != t2)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(custom_leaf__no_default_ctor); +ATF_TEST_CASE_BODY(custom_leaf__no_default_ctor) +{ + config::tree tree; + + tree.define< wrapped_int_node >("test1"); + tree.define< wrapped_int_node >("test2"); + tree.set< wrapped_int_node >("test1", int_wrapper(5)); + tree.set< wrapped_int_node >("test2", int_wrapper(10)); + const int_wrapper& test1 = tree.lookup< wrapped_int_node >("test1"); + ATF_REQUIRE_EQ(5, test1.value()); + const int_wrapper& test2 = tree.lookup< wrapped_int_node >("test2"); + ATF_REQUIRE_EQ(10, test2.value()); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, define_set_lookup__one_level); + ATF_ADD_TEST_CASE(tcs, define_set_lookup__multiple_levels); + + ATF_ADD_TEST_CASE(tcs, deep_copy__empty); + ATF_ADD_TEST_CASE(tcs, deep_copy__some); + + ATF_ADD_TEST_CASE(tcs, lookup__invalid_key); + ATF_ADD_TEST_CASE(tcs, lookup__unknown_key); + + ATF_ADD_TEST_CASE(tcs, is_set__one_level); + ATF_ADD_TEST_CASE(tcs, is_set__multiple_levels); + ATF_ADD_TEST_CASE(tcs, is_set__invalid_key); + + ATF_ADD_TEST_CASE(tcs, set__invalid_key); + ATF_ADD_TEST_CASE(tcs, set__unknown_key); + ATF_ADD_TEST_CASE(tcs, set__value_error); + + ATF_ADD_TEST_CASE(tcs, push_lua__ok); + ATF_ADD_TEST_CASE(tcs, set_lua__ok); + + ATF_ADD_TEST_CASE(tcs, lookup_rw); + + ATF_ADD_TEST_CASE(tcs, lookup_string__ok); + ATF_ADD_TEST_CASE(tcs, lookup_string__invalid_key); + ATF_ADD_TEST_CASE(tcs, lookup_string__unknown_key); + + ATF_ADD_TEST_CASE(tcs, set_string__ok); + ATF_ADD_TEST_CASE(tcs, set_string__invalid_key); + ATF_ADD_TEST_CASE(tcs, set_string__unknown_key); + ATF_ADD_TEST_CASE(tcs, set_string__value_error); + + ATF_ADD_TEST_CASE(tcs, all_properties__none); + ATF_ADD_TEST_CASE(tcs, all_properties__all_set); + ATF_ADD_TEST_CASE(tcs, all_properties__some_unset); + ATF_ADD_TEST_CASE(tcs, all_properties__subtree__inner); + ATF_ADD_TEST_CASE(tcs, all_properties__subtree__leaf); + ATF_ADD_TEST_CASE(tcs, all_properties__subtree__strip_key); + ATF_ADD_TEST_CASE(tcs, all_properties__subtree__invalid_key); + ATF_ADD_TEST_CASE(tcs, all_properties__subtree__unknown_key); + + ATF_ADD_TEST_CASE(tcs, operators_eq_and_ne__empty); + ATF_ADD_TEST_CASE(tcs, operators_eq_and_ne__shallow_copy); + ATF_ADD_TEST_CASE(tcs, operators_eq_and_ne__deep_copy); + ATF_ADD_TEST_CASE(tcs, operators_eq_and_ne__some_contents); + + ATF_ADD_TEST_CASE(tcs, custom_leaf__no_default_ctor); +} diff --git a/external/bsd/kyua-cli/dist/utils/datetime.cpp b/external/bsd/kyua-cli/dist/utils/datetime.cpp new file mode 100644 index 000000000..c59c3d8d5 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/datetime.cpp @@ -0,0 +1,388 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/datetime.hpp" + +extern "C" { +#include + +#include +} + +#include "utils/optional.ipp" +#include "utils/sanity.hpp" + +namespace datetime = utils::datetime; + +using utils::none; +using utils::optional; + + +namespace { + + +/// Fake value for the current time. +static optional< datetime::timestamp > mock_now = none; + + +} // anonymous namespace + + +/// Creates a zero time delta. +datetime::delta::delta(void) : + seconds(0), + useconds(0) +{ +} + + +/// Creates a time delta. +/// +/// \param seconds_ The seconds in the delta. +/// \param useconds_ The microseconds in the delta. +datetime::delta::delta(const int64_t seconds_, + const unsigned long useconds_) : + seconds(seconds_), + useconds(useconds_) +{ +} + + +/// Converts a time expressed in microseconds to a delta. +/// +/// \param useconds The amount of microseconds representing the delta. +/// +/// \return A new delta object. +datetime::delta +datetime::delta::from_microseconds(const int64_t useconds) +{ + return delta(useconds / 1000000, useconds % 1000000); +} + + +/// Convers the delta to a flat representation expressed in microseconds. +/// +/// \return The amount of microseconds that corresponds to this delta. +int64_t +datetime::delta::to_microseconds(void) const +{ + return seconds * 1000000 + useconds; +} + + +/// Checks if two time deltas are equal. +/// +/// \param other The object to compare to. +/// +/// \return True if the two time deltas are equals; false otherwise. +bool +datetime::delta::operator==(const datetime::delta& other) const +{ + return seconds == other.seconds && useconds == other.useconds; +} + + +/// Checks if two time deltas are different. +/// +/// \param other The object to compare to. +/// +/// \return True if the two time deltas are different; false otherwise. +bool +datetime::delta::operator!=(const datetime::delta& other) const +{ + return !(*this == other); +} + + +/// Adds a time delta to this one. +/// +/// \param other The time delta to add. +/// +/// \return The addition of this time delta with the other time delta. +datetime::delta +datetime::delta::operator+(const datetime::delta& other) const +{ + return delta::from_microseconds(to_microseconds() + + other.to_microseconds()); +} + + +/// Adds a time delta to this one and updates this with the result. +/// +/// \param other The time delta to add. +/// +/// \return The addition of this time delta with the other time delta. +datetime::delta +datetime::delta::operator+=(const datetime::delta& other) +{ + *this = *this + other; + return *this; +} + + +/// Injects the object into a stream. +/// +/// \param output The stream into which to inject the object. +/// \param object The object to format. +/// +/// \return The output stream. +std::ostream& +datetime::operator<<(std::ostream& output, const delta& object) +{ + return (output << object.to_microseconds() << "us"); +} + + +namespace utils { +namespace datetime { + + +/// Internal representation for datetime::timestamp. +struct timestamp::impl { + /// The raw timestamp as provided by libc. + ::timeval data; + + /// Constructs an impl object from initialized data. + /// + /// \param data_ The raw timestamp to use. + impl(const ::timeval& data_) : data(data_) + { + } +}; + + +} // namespace datetime +} // namespace utils + + +/// Constructs a new timestamp. +/// +/// \param pimpl_ An existing impl representation. +datetime::timestamp::timestamp(std::tr1::shared_ptr< impl > pimpl_) : + _pimpl(pimpl_) +{ +} + + +/// Constructs a timestamp from the amount of microseconds since the epoch. +/// +/// \param value Microseconds since the epoch in UTC. Must be positive. +/// +/// \return A new timestamp. +datetime::timestamp +datetime::timestamp::from_microseconds(const int64_t value) +{ + PRE(value >= 0); + ::timeval data; + data.tv_sec = static_cast< time_t >(value / 1000000); + data.tv_usec = static_cast< suseconds_t >(value % 1000000); + return timestamp(std::tr1::shared_ptr< impl >(new impl(data))); +} + + +/// Constructs a timestamp based on user-friendly values. +/// +/// \param year The year in the [1900,inf) range. +/// \param month The month in the [1,12] range. +/// \param day The day in the [1,30] range. +/// \param hour The hour in the [0,23] range. +/// \param minute The minute in the [0,59] range. +/// \param second The second in the [0,60] range. Yes, that is 60, which can be +/// the case on leap seconds. +/// \param microsecond The microsecond in the [0,999999] range. +/// +/// \return A new timestamp. +datetime::timestamp +datetime::timestamp::from_values(const int year, const int month, + const int day, const int hour, + const int minute, const int second, + const int microsecond) +{ + PRE(year >= 1900); + PRE(month >= 1 && month <= 12); + PRE(day >= 1 && day <= 30); + PRE(hour >= 0 && hour <= 23); + PRE(minute >= 0 && minute <= 59); + PRE(second >= 0 && second <= 60); + PRE(microsecond >= 0 && microsecond <= 999999); + + // The code below is quite convoluted. The problem is that we can't assume + // that some fields (like tm_zone) of ::tm exist, and thus we can't blindly + // set them from the code. Instead of detecting their presence in the + // configure script, we just query the current time to initialize such + // fields and then we override the ones we are interested in. (There might + // be some better way to do this, but I don't know it and the documentation + // does not shed much light into how to create your own fake date.) + + const time_t current_time = ::time(NULL); + + ::tm timedata; + if (::gmtime_r(¤t_time, &timedata) == NULL) + UNREACHABLE; + + timedata.tm_sec = second; + timedata.tm_min = minute; + timedata.tm_hour = hour; + timedata.tm_mday = day; + timedata.tm_mon = month - 1; + timedata.tm_year = year - 1900; + // Ignored: timedata.tm_wday + // Ignored: timedata.tm_yday + + ::timeval data; + data.tv_sec = ::mktime(&timedata); + data.tv_usec = static_cast< suseconds_t >(microsecond); + return timestamp(std::tr1::shared_ptr< impl >(new impl(data))); +} + + +/// Constructs a new timestamp representing the current time in UTC. +/// +/// \return A new timestamp. +datetime::timestamp +datetime::timestamp::now(void) +{ + if (mock_now) + return mock_now.get(); + + ::timeval data; + { + const int ret = ::gettimeofday(&data, NULL); + INV(ret != -1); + } + + return timestamp(std::tr1::shared_ptr< impl >(new impl(data))); +} + + +/// Formats a timestamp. +/// +/// \param format The format string to use as consumed by strftime(3). +/// +/// \return The formatted time. +std::string +datetime::timestamp::strftime(const std::string& format) const +{ + ::tm timedata; + // This conversion to time_t is necessary because tv_sec is not guaranteed + // to be a time_t. For example, it isn't in NetBSD 5.x + ::time_t epoch_seconds; + epoch_seconds = _pimpl->data.tv_sec; + if (::gmtime_r(&epoch_seconds, &timedata) == NULL) + UNREACHABLE_MSG("gmtime_r(3) did not accept the value returned by " + "gettimeofday(2)"); + + char buf[128]; + if (::strftime(buf, sizeof(buf), format.c_str(), &timedata) == 0) + UNREACHABLE_MSG("Arbitrary-long format strings are unimplemented"); + return buf; +} + + +/// Returns the number of microseconds since the epoch in UTC. +/// +/// \return A number of microseconds. +int64_t +datetime::timestamp::to_microseconds(void) const +{ + return static_cast< int64_t >(_pimpl->data.tv_sec) * 1000000 + + _pimpl->data.tv_usec; +} + + +/// Returns the number of seconds since the epoch in UTC. +/// +/// \return A number of seconds. +int64_t +datetime::timestamp::to_seconds(void) const +{ + return static_cast< int64_t >(_pimpl->data.tv_sec); +} + + +/// Sets the current time for testing purposes. +void +datetime::set_mock_now(const int year, const int month, + const int day, const int hour, + const int minute, const int second, + const int microsecond) +{ + mock_now = timestamp::from_values(year, month, day, hour, minute, second, + microsecond); +} + + +/// Checks if two timestamps are equal. +/// +/// \param other The object to compare to. +/// +/// \return True if the two timestamps are equals; false otherwise. +bool +datetime::timestamp::operator==(const datetime::timestamp& other) const +{ + return _pimpl->data.tv_sec == other._pimpl->data.tv_sec && + _pimpl->data.tv_usec == other._pimpl->data.tv_usec; +} + + +/// Checks if two timestamps are different. +/// +/// \param other The object to compare to. +/// +/// \return True if the two timestamps are different; false otherwise. +bool +datetime::timestamp::operator!=(const datetime::timestamp& other) const +{ + return !(*this == other); +} + + +/// Calculates the delta between two timestamps. +/// +/// \param other The subtrahend. +/// +/// \return The difference between this object and the other object. +datetime::delta +datetime::timestamp::operator-(const datetime::timestamp& other) const +{ + return datetime::delta::from_microseconds(to_microseconds() - + other.to_microseconds()); +} + + +/// Injects the object into a stream. +/// +/// \param output The stream into which to inject the object. +/// \param object The object to format. +/// +/// \return The output stream. +std::ostream& +datetime::operator<<(std::ostream& output, const timestamp& object) +{ + return (output << object.to_microseconds() << "us"); +} diff --git a/external/bsd/kyua-cli/dist/utils/datetime.hpp b/external/bsd/kyua-cli/dist/utils/datetime.hpp new file mode 100644 index 000000000..0e8d50eb2 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/datetime.hpp @@ -0,0 +1,116 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file utils/datetime.hpp +/// Provides date and time-related classes and functions. + +#if !defined(UTILS_DATETIME_HPP) +#define UTILS_DATETIME_HPP + +extern "C" { +#include +} + +#include +#include +#include + +#include + +namespace utils { +namespace datetime { + + +/// Represents a time delta to describe deadlines. +struct delta { + /// The amount of seconds in the time delta. + int64_t seconds; + + /// The amount of microseconds in the time delta. + unsigned long useconds; + + delta(void); + delta(const int64_t, const unsigned long); + + static delta from_microseconds(const int64_t); + int64_t to_microseconds(void) const; + + bool operator==(const delta&) const; + bool operator!=(const delta&) const; + + delta operator+(const delta&) const; + delta operator+=(const delta&); +}; + + +std::ostream& operator<<(std::ostream&, const delta&); + + +/// Represents a fixed date/time. +/// +/// Timestamps are immutable objects and therefore we can simply use a shared +/// pointer to hide the implementation type of the date. By not using an auto +/// pointer, we don't have to worry about providing our own copy constructor and +/// assignment opertor. +class timestamp { + struct impl; + + /// Pointer to the shared internal implementation. + std::tr1::shared_ptr< impl > _pimpl; + + timestamp(std::tr1::shared_ptr< impl >); + +public: + static timestamp from_microseconds(const int64_t); + static timestamp from_values(const int, const int, const int, + const int, const int, const int, + const int); + static timestamp now(void); + + std::string strftime(const std::string&) const; + int64_t to_microseconds(void) const; + int64_t to_seconds(void) const; + + bool operator==(const timestamp&) const; + bool operator!=(const timestamp&) const; + + delta operator-(const timestamp&) const; +}; + + +std::ostream& operator<<(std::ostream&, const timestamp&); + + +void set_mock_now(const int, const int, const int, const int, const int, + const int, const int); + + +} // namespace datetime +} // namespace utils + +#endif // !defined(UTILS_DATETIME_HPP) diff --git a/external/bsd/kyua-cli/dist/utils/datetime_test.cpp b/external/bsd/kyua-cli/dist/utils/datetime_test.cpp new file mode 100644 index 000000000..3c43facbb --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/datetime_test.cpp @@ -0,0 +1,376 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/datetime.hpp" + +extern "C" { +#include +#include +} + +#include + +#include + +namespace datetime = utils::datetime; + + +ATF_TEST_CASE_WITHOUT_HEAD(delta__defaults); +ATF_TEST_CASE_BODY(delta__defaults) +{ + const datetime::delta delta; + ATF_REQUIRE_EQ(0, delta.seconds); + ATF_REQUIRE_EQ(0, delta.useconds); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(delta__overrides); +ATF_TEST_CASE_BODY(delta__overrides) +{ + const datetime::delta delta(1, 2); + ATF_REQUIRE_EQ(1, delta.seconds); + ATF_REQUIRE_EQ(2, delta.useconds); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(delta__from_microseconds); +ATF_TEST_CASE_BODY(delta__from_microseconds) +{ + { + const datetime::delta delta = datetime::delta::from_microseconds(0); + ATF_REQUIRE_EQ(0, delta.seconds); + ATF_REQUIRE_EQ(0, delta.useconds); + } + { + const datetime::delta delta = datetime::delta::from_microseconds( + 999999); + ATF_REQUIRE_EQ(0, delta.seconds); + ATF_REQUIRE_EQ(999999, delta.useconds); + } + { + const datetime::delta delta = datetime::delta::from_microseconds( + 1000000); + ATF_REQUIRE_EQ(1, delta.seconds); + ATF_REQUIRE_EQ(0, delta.useconds); + } + { + const datetime::delta delta = datetime::delta::from_microseconds( + 10576293); + ATF_REQUIRE_EQ(10, delta.seconds); + ATF_REQUIRE_EQ(576293, delta.useconds); + } + { + const datetime::delta delta = datetime::delta::from_microseconds( + 123456789123456); + ATF_REQUIRE_EQ(123456789, delta.seconds); + ATF_REQUIRE_EQ(123456, delta.useconds); + } +} + + +ATF_TEST_CASE_WITHOUT_HEAD(delta__to_microseconds); +ATF_TEST_CASE_BODY(delta__to_microseconds) +{ + ATF_REQUIRE_EQ(0, datetime::delta(0, 0).to_microseconds()); + ATF_REQUIRE_EQ(999999, datetime::delta(0, 999999).to_microseconds()); + ATF_REQUIRE_EQ(1000000, datetime::delta(1, 0).to_microseconds()); + ATF_REQUIRE_EQ(10576293, datetime::delta(10, 576293).to_microseconds()); + ATF_REQUIRE_EQ(11576293, datetime::delta(10, 1576293).to_microseconds()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(delta__equals); +ATF_TEST_CASE_BODY(delta__equals) +{ + ATF_REQUIRE(datetime::delta() == datetime::delta()); + ATF_REQUIRE(datetime::delta() == datetime::delta(0, 0)); + ATF_REQUIRE(datetime::delta(1, 2) == datetime::delta(1, 2)); + + ATF_REQUIRE(!(datetime::delta() == datetime::delta(0, 1))); + ATF_REQUIRE(!(datetime::delta() == datetime::delta(1, 0))); + ATF_REQUIRE(!(datetime::delta(1, 2) == datetime::delta(2, 1))); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(delta__differs); +ATF_TEST_CASE_BODY(delta__differs) +{ + ATF_REQUIRE(!(datetime::delta() != datetime::delta())); + ATF_REQUIRE(!(datetime::delta() != datetime::delta(0, 0))); + ATF_REQUIRE(!(datetime::delta(1, 2) != datetime::delta(1, 2))); + + ATF_REQUIRE(datetime::delta() != datetime::delta(0, 1)); + ATF_REQUIRE(datetime::delta() != datetime::delta(1, 0)); + ATF_REQUIRE(datetime::delta(1, 2) != datetime::delta(2, 1)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(delta__addition); +ATF_TEST_CASE_BODY(delta__addition) +{ + using datetime::delta; + + ATF_REQUIRE(delta() == delta() + delta()); + ATF_REQUIRE(delta(0, 10) == delta() + delta(0, 10)); + ATF_REQUIRE(delta(10, 0) == delta(10, 0) + delta()); + + ATF_REQUIRE(delta(1, 234567) == delta(0, 1234567) + delta()); + ATF_REQUIRE(delta(12, 34) == delta(10, 20) + delta(2, 14)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(delta__addition_and_set); +ATF_TEST_CASE_BODY(delta__addition_and_set) +{ + using datetime::delta; + + { + delta d; + d += delta(3, 5); + ATF_REQUIRE(delta(3, 5) == d); + } + { + delta d(1, 2); + d += delta(3, 5); + ATF_REQUIRE(delta(4, 7) == d); + } + { + delta d(1, 2); + ATF_REQUIRE(delta(4, 7) == (d += delta(3, 5))); + } +} + + +ATF_TEST_CASE_WITHOUT_HEAD(delta__output); +ATF_TEST_CASE_BODY(delta__output) +{ + { + std::ostringstream str; + str << datetime::delta(15, 8791); + ATF_REQUIRE_EQ("15008791us", str.str()); + } + { + std::ostringstream str; + str << datetime::delta(12345678, 0); + ATF_REQUIRE_EQ("12345678000000us", str.str()); + } +} + + +ATF_TEST_CASE_WITHOUT_HEAD(timestamp__copy); +ATF_TEST_CASE_BODY(timestamp__copy) +{ + const datetime::timestamp ts1 = datetime::timestamp::from_values( + 2011, 2, 16, 19, 15, 30, 0); + { + const datetime::timestamp ts2 = ts1; + const datetime::timestamp ts3 = datetime::timestamp::from_values( + 2012, 2, 16, 19, 15, 30, 0); + ATF_REQUIRE_EQ("2011", ts1.strftime("%Y")); + ATF_REQUIRE_EQ("2011", ts2.strftime("%Y")); + ATF_REQUIRE_EQ("2012", ts3.strftime("%Y")); + } + ATF_REQUIRE_EQ("2011", ts1.strftime("%Y")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(timestamp__from_microseconds); +ATF_TEST_CASE_BODY(timestamp__from_microseconds) +{ + const datetime::timestamp ts = datetime::timestamp::from_microseconds( + 1328829351987654LL); + ATF_REQUIRE_EQ("2012-02-09 23:15:51", ts.strftime("%Y-%m-%d %H:%M:%S")); + ATF_REQUIRE_EQ(1328829351987654LL, ts.to_microseconds()); + ATF_REQUIRE_EQ(1328829351, ts.to_seconds()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(timestamp__now__mock); +ATF_TEST_CASE_BODY(timestamp__now__mock) +{ + datetime::set_mock_now(2011, 2, 21, 18, 5, 10, 0); + ATF_REQUIRE_EQ("2011-02-21 18:05:10", + datetime::timestamp::now().strftime("%Y-%m-%d %H:%M:%S")); + + datetime::set_mock_now(2012, 3, 22, 19, 6, 11, 54321); + ATF_REQUIRE_EQ("2012-03-22 19:06:11", + datetime::timestamp::now().strftime("%Y-%m-%d %H:%M:%S")); + ATF_REQUIRE_EQ("2012-03-22 19:06:11", + datetime::timestamp::now().strftime("%Y-%m-%d %H:%M:%S")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(timestamp__now__real); +ATF_TEST_CASE_BODY(timestamp__now__real) +{ + // This test is might fail if we happen to run at the crossing of one + // day to the other and the two measures we pick of the current time + // differ. This is so unlikely that I haven't bothered to do this in any + // other way. + + const time_t just_before = ::time(NULL); + const datetime::timestamp now = datetime::timestamp::now(); + + ::tm data; + char buf[1024]; + ATF_REQUIRE(::gmtime_r(&just_before, &data) != 0); + ATF_REQUIRE(::strftime(buf, sizeof(buf), "%Y-%m-%d", &data) != 0); + ATF_REQUIRE_EQ(buf, now.strftime("%Y-%m-%d")); + + ATF_REQUIRE(now.strftime("%Z") == "GMT" || now.strftime("%Z") == "UTC"); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(timestamp__now__granularity); +ATF_TEST_CASE_BODY(timestamp__now__granularity) +{ + const datetime::timestamp first = datetime::timestamp::now(); + ::usleep(1); + const datetime::timestamp second = datetime::timestamp::now(); + ATF_REQUIRE(first.to_microseconds() != second.to_microseconds()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(timestamp__strftime); +ATF_TEST_CASE_BODY(timestamp__strftime) +{ + const datetime::timestamp ts1 = datetime::timestamp::from_values( + 2010, 12, 10, 8, 45, 50, 0); + ATF_REQUIRE_EQ("2010-12-10", ts1.strftime("%Y-%m-%d")); + ATF_REQUIRE_EQ("08:45:50", ts1.strftime("%H:%M:%S")); + + const datetime::timestamp ts2 = datetime::timestamp::from_values( + 2011, 2, 16, 19, 15, 30, 0); + ATF_REQUIRE_EQ("2011-02-16T19:15:30", ts2.strftime("%Y-%m-%dT%H:%M:%S")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(timestamp__to_microseconds); +ATF_TEST_CASE_BODY(timestamp__to_microseconds) +{ + const datetime::timestamp ts1 = datetime::timestamp::from_values( + 2010, 12, 10, 8, 45, 50, 123456); + ATF_REQUIRE_EQ(1291970750123456LL, ts1.to_microseconds()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(timestamp__to_seconds); +ATF_TEST_CASE_BODY(timestamp__to_seconds) +{ + const datetime::timestamp ts1 = datetime::timestamp::from_values( + 2010, 12, 10, 8, 45, 50, 123456); + ATF_REQUIRE_EQ(1291970750, ts1.to_seconds()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(timestamp__leap_second); +ATF_TEST_CASE_BODY(timestamp__leap_second) +{ + // This is actually a test for from_values(), which is the function that + // includes assertions to validate the input parameters. + const datetime::timestamp ts1 = datetime::timestamp::from_values( + 2012, 6, 30, 23, 59, 60, 543); + ATF_REQUIRE_EQ(1341100800, ts1.to_seconds()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(timestamp__equals); +ATF_TEST_CASE_BODY(timestamp__equals) +{ + ATF_REQUIRE(datetime::timestamp::from_microseconds(1291970750123456LL) == + datetime::timestamp::from_microseconds(1291970750123456LL)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(timestamp__differs); +ATF_TEST_CASE_BODY(timestamp__differs) +{ + ATF_REQUIRE(datetime::timestamp::from_microseconds(1291970750123456LL) != + datetime::timestamp::from_microseconds(1291970750123455LL)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(timestamp__subtraction); +ATF_TEST_CASE_BODY(timestamp__subtraction) +{ + const datetime::timestamp ts1 = datetime::timestamp::from_microseconds( + 1291970750123456LL); + const datetime::timestamp ts2 = datetime::timestamp::from_microseconds( + 1291970750123468LL); + const datetime::timestamp ts3 = datetime::timestamp::from_microseconds( + 1291970850123456LL); + + ATF_REQUIRE(datetime::delta(0, 0) == ts1 - ts1); + ATF_REQUIRE(datetime::delta(0, 12) == ts2 - ts1); + ATF_REQUIRE(datetime::delta(100, 0) == ts3 - ts1); + ATF_REQUIRE(datetime::delta(99, 999988) == ts3 - ts2); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(timestamp__output); +ATF_TEST_CASE_BODY(timestamp__output) +{ + { + std::ostringstream str; + str << datetime::timestamp::from_microseconds(1291970750123456LL); + ATF_REQUIRE_EQ("1291970750123456us", str.str()); + } + { + std::ostringstream str; + str << datetime::timestamp::from_microseconds(1028309798759812LL); + ATF_REQUIRE_EQ("1028309798759812us", str.str()); + } +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, delta__defaults); + ATF_ADD_TEST_CASE(tcs, delta__overrides); + ATF_ADD_TEST_CASE(tcs, delta__from_microseconds); + ATF_ADD_TEST_CASE(tcs, delta__to_microseconds); + ATF_ADD_TEST_CASE(tcs, delta__equals); + ATF_ADD_TEST_CASE(tcs, delta__differs); + ATF_ADD_TEST_CASE(tcs, delta__addition); + ATF_ADD_TEST_CASE(tcs, delta__addition_and_set); + ATF_ADD_TEST_CASE(tcs, delta__output); + + ATF_ADD_TEST_CASE(tcs, timestamp__copy); + ATF_ADD_TEST_CASE(tcs, timestamp__from_microseconds); + ATF_ADD_TEST_CASE(tcs, timestamp__now__mock); + ATF_ADD_TEST_CASE(tcs, timestamp__now__real); + ATF_ADD_TEST_CASE(tcs, timestamp__now__granularity); + ATF_ADD_TEST_CASE(tcs, timestamp__strftime); + ATF_ADD_TEST_CASE(tcs, timestamp__to_microseconds); + ATF_ADD_TEST_CASE(tcs, timestamp__to_seconds); + ATF_ADD_TEST_CASE(tcs, timestamp__leap_second); + ATF_ADD_TEST_CASE(tcs, timestamp__equals); + ATF_ADD_TEST_CASE(tcs, timestamp__differs); + ATF_ADD_TEST_CASE(tcs, timestamp__subtraction); + ATF_ADD_TEST_CASE(tcs, timestamp__output); +} diff --git a/external/bsd/kyua-cli/dist/utils/defs.hpp.in b/external/bsd/kyua-cli/dist/utils/defs.hpp.in new file mode 100644 index 000000000..a52f03f6d --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/defs.hpp.in @@ -0,0 +1,63 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file utils/defs.hpp +/// +/// Definitions for compiler and system features autodetected at configuration +/// time. + +#if !defined(UTILS_DEFS_HPP) +#define UTILS_DEFS_HPP + + +/// Attribute to mark a function as non-returning. +#define UTILS_NORETURN @ATTRIBUTE_NORETURN@ + + +/// Attribute to mark a function as pure. +#define UTILS_PURE @ATTRIBUTE_PURE@ + + +/// Attribute to mark an entity as unused. +#define UTILS_UNUSED @ATTRIBUTE_UNUSED@ + + +/// Macro to mark a parameter as unused. +/// +/// This macro has to be called on the name of a parameter during the +/// definition (not declaration) of a function. When doing so, it declares +/// the parameter as unused to silence compiler warnings and also renames +/// the parameter by prefixing "unused_" to it. This is to ensure that the +/// developer remembers to remove the call to this macro from the parameter +/// when he actually starts using it. +/// +/// \param name The name of the function parameter to mark as unused. +#define UTILS_UNUSED_PARAM(name) unused_ ## name UTILS_UNUSED + + +#endif // !defined(UTILS_DEFS_HPP) diff --git a/external/bsd/kyua-cli/dist/utils/env.cpp b/external/bsd/kyua-cli/dist/utils/env.cpp new file mode 100644 index 000000000..983e803af --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/env.cpp @@ -0,0 +1,174 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/env.hpp" + +#if defined(HAVE_CONFIG_H) +# include "config.h" +#endif + +#include +#include +#include +#include + +#include "utils/format/macros.hpp" +#include "utils/logging/macros.hpp" +#include "utils/optional.ipp" + +using utils::none; +using utils::optional; + + +extern "C" { + extern char** environ; +} + + +/// Gets all environment variables. +/// +/// \return A mapping of (name, value) pairs describing the environment +/// variables. +std::map< std::string, std::string > +utils::getallenv(void) +{ + std::map< std::string, std::string > allenv; + for (char** envp = environ; *envp != NULL; envp++) { + const std::string oneenv = *envp; + const std::string::size_type pos = oneenv.find('='); + const std::string name = oneenv.substr(0, pos); + const std::string value = oneenv.substr(pos + 1); + + PRE(allenv.find(name) == allenv.end()); + allenv[name] = value; + } + return allenv; +} + + +/// Gets the value of an environment variable. +/// +/// \param name The name of the environment variable to query. +/// +/// \return The value of the environment variable if it is defined, or none +/// otherwise. +optional< std::string > +utils::getenv(const std::string& name) +{ + const char* value = std::getenv(name.c_str()); + if (value == NULL) { + LD(F("Environment variable '%s' is not defined") % name); + return none; + } else { + LD(F("Environment variable '%s' is '%s'") % name % value); + return utils::make_optional(std::string(value)); + } +} + + +/// Gets the value of an environment variable with a default fallback. +/// +/// \param name The name of the environment variable to query. +/// \param default_value The value to return if the variable is not defined. +/// +/// \return The value of the environment variable. +std::string +utils::getenv_with_default(const std::string& name, + const std::string& default_value) +{ + const char* value = std::getenv(name.c_str()); + if (value == NULL) { + LD(F("Environment variable '%s' is not defined; using default '%s'") % + name % default_value); + return default_value; + } else { + LD(F("Environment variable '%s' is '%s'") % name % value); + return value; + } +} + + +/// Sets the value of an environment variable. +/// +/// \param name The name of the environment variable to set. +/// \param val The value to set the environment variable to. May be empty. +/// +/// \throw std::runtime_error If there is an error setting the environment +/// variable. +void +utils::setenv(const std::string& name, const std::string& val) +{ + LD(F("Setting environment variable '%s' to '%s'") % name % val); +#if defined(HAVE_SETENV) + if (::setenv(name.c_str(), val.c_str(), 1) == -1) { + const int original_errno = errno; + throw std::runtime_error(F("Failed to set environment variable '%s' to " + "'%s': %s") % + name % val % std::strerror(original_errno)); + } +#elif defined(HAVE_PUTENV) + if (::putenv((F("%s=%s") % name % val).c_str()) == -1) { + const int original_errno = errno; + throw std::runtime_error(F("Failed to set environment variable '%s' to " + "'%s': %s") % + name % val % std::strerror(original_errno)); + } +#else +# error "Don't know how to set an environment variable." +#endif +} + + +/// Unsets an environment variable. +/// +/// \param name The name of the environment variable to unset. +/// +/// \throw std::runtime_error If there is an error unsetting the environment +/// variable. +void +utils::unsetenv(const std::string& name) +{ + LD(F("Unsetting environment variable '%s'") % name); +#if defined(HAVE_UNSETENV) + if (::unsetenv(name.c_str()) == -1) { + const int original_errno = errno; + throw std::runtime_error(F("Failed to unset environment variable " + "'%s'") % + name % std::strerror(original_errno)); + } +#elif defined(HAVE_PUTENV) + if (::putenv((F("%s=") % name).c_str()) == -1) { + const int original_errno = errno; + throw std::runtime_error(F("Failed to unset environment variable " + "'%s'") % + name % std::strerror(original_errno)); + } +#else +# error "Don't know how to unset an environment variable." +#endif +} diff --git a/external/bsd/kyua-cli/dist/utils/env.hpp b/external/bsd/kyua-cli/dist/utils/env.hpp new file mode 100644 index 000000000..ac76bd1b8 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/env.hpp @@ -0,0 +1,56 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file utils/env.hpp +/// Querying and manipulation of environment variables. +/// +/// These utility functions wrap the system functions to manipulate the +/// environment in a portable way and expose their arguments and return values +/// in a C++-friendly manner. + +#if !defined(UTILS_ENV_HPP) +#define UTILS_ENV_HPP + +#include +#include + +#include "utils/optional.hpp" + +namespace utils { + + +std::map< std::string, std::string > getallenv(void); +optional< std::string > getenv(const std::string&); +std::string getenv_with_default(const std::string&, const std::string&); +void setenv(const std::string&, const std::string&); +void unsetenv(const std::string&); + + +} // namespace utils + +#endif // !defined(UTILS_ENV_HPP) diff --git a/external/bsd/kyua-cli/dist/utils/env_test.cpp b/external/bsd/kyua-cli/dist/utils/env_test.cpp new file mode 100644 index 000000000..4fca162ab --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/env_test.cpp @@ -0,0 +1,129 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/env.hpp" + +#include + +#include "utils/optional.ipp" + +using utils::optional; + + +ATF_TEST_CASE_WITHOUT_HEAD(getallenv); +ATF_TEST_CASE_BODY(getallenv) +{ + utils::unsetenv("test-missing"); + utils::setenv("test-empty", ""); + utils::setenv("test-text", "some-value"); + + const std::map< std::string, std::string > allenv = utils::getallenv(); + + { + const std::map< std::string, std::string >::const_iterator iter = + allenv.find("test-missing"); + ATF_REQUIRE(iter == allenv.end()); + } + + { + const std::map< std::string, std::string >::const_iterator iter = + allenv.find("test-empty"); + ATF_REQUIRE(iter != allenv.end()); + ATF_REQUIRE((*iter).second.empty()); + } + + { + const std::map< std::string, std::string >::const_iterator iter = + allenv.find("test-text"); + ATF_REQUIRE(iter != allenv.end()); + ATF_REQUIRE_EQ("some-value", (*iter).second); + } + + if (utils::getenv("PATH")) { + const std::map< std::string, std::string >::const_iterator iter = + allenv.find("PATH"); + ATF_REQUIRE(iter != allenv.end()); + ATF_REQUIRE_EQ(utils::getenv("PATH").get(), (*iter).second); + } +} + + +ATF_TEST_CASE_WITHOUT_HEAD(getenv); +ATF_TEST_CASE_BODY(getenv) +{ + const optional< std::string > path = utils::getenv("PATH"); + ATF_REQUIRE(path); + ATF_REQUIRE(!path.get().empty()); + + ATF_REQUIRE(!utils::getenv("__UNDEFINED_VARIABLE__")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(getenv_with_default); +ATF_TEST_CASE_BODY(getenv_with_default) +{ + ATF_REQUIRE("don't use" != + utils::getenv_with_default("PATH", "don't use")); + + ATF_REQUIRE_EQ("foo", + utils::getenv_with_default("__UNDEFINED_VARIABLE__", "foo")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(setenv); +ATF_TEST_CASE_BODY(setenv) +{ + ATF_REQUIRE(utils::getenv("PATH")); + const std::string oldval = utils::getenv("PATH").get(); + utils::setenv("PATH", "foo-bar"); + ATF_REQUIRE(utils::getenv("PATH").get() != oldval); + ATF_REQUIRE_EQ("foo-bar", utils::getenv("PATH").get()); + + ATF_REQUIRE(!utils::getenv("__UNDEFINED_VARIABLE__")); + utils::setenv("__UNDEFINED_VARIABLE__", "foo2-bar2"); + ATF_REQUIRE_EQ("foo2-bar2", utils::getenv("__UNDEFINED_VARIABLE__").get()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(unsetenv); +ATF_TEST_CASE_BODY(unsetenv) +{ + ATF_REQUIRE(utils::getenv("PATH")); + utils::unsetenv("PATH"); + ATF_REQUIRE(!utils::getenv("PATH")); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, getallenv); + ATF_ADD_TEST_CASE(tcs, getenv); + ATF_ADD_TEST_CASE(tcs, getenv_with_default); + ATF_ADD_TEST_CASE(tcs, setenv); + ATF_ADD_TEST_CASE(tcs, unsetenv); +} diff --git a/external/bsd/kyua-cli/dist/utils/format/Kyuafile b/external/bsd/kyua-cli/dist/utils/format/Kyuafile new file mode 100644 index 000000000..df9b571b6 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/format/Kyuafile @@ -0,0 +1,6 @@ +syntax(2) + +test_suite("kyua") + +atf_test_program{name="exceptions_test"} +atf_test_program{name="formatter_test"} diff --git a/external/bsd/kyua-cli/dist/utils/format/exceptions.cpp b/external/bsd/kyua-cli/dist/utils/format/exceptions.cpp new file mode 100644 index 000000000..2585bb5e1 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/format/exceptions.cpp @@ -0,0 +1,110 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/format/exceptions.hpp" + +using utils::format::bad_format_error; +using utils::format::error; +using utils::format::extra_args_error; + + +/// Constructs a new error with a plain-text message. +/// +/// \param message The plain-text error message. +error::error(const std::string& message) : + std::runtime_error(message) +{ +} + + +/// Destructor for the error. +error::~error(void) throw() +{ +} + + +/// Constructs a new bad_format_error. +/// +/// \param format_ The invalid format string. +/// \param message Description of the error in the format string. +bad_format_error::bad_format_error(const std::string& format_, + const std::string& message) : + error("Invalid formatting string '" + format_ + "': " + message), + _format(format_) +{ +} + + +/// Destructor for the error. +bad_format_error::~bad_format_error(void) throw() +{ +} + + +/// Gets the invalid format string. +const std::string& +bad_format_error::format(void) const +{ + return _format; +} + + +/// Constructs a new extra_args_error. +/// +/// \param format_ The format string. +/// \param arg_ The first extra argument passed to the format string. +extra_args_error::extra_args_error(const std::string& format_, + const std::string& arg_) : + error("Not enough fields in formatting string '" + format_ + "' to place " + "argument '" + arg_ + "'"), + _format(format_), + _arg(arg_) +{ +} + + +/// Destructor for the error. +extra_args_error::~extra_args_error(void) throw() +{ +} + + +/// Gets the format string. +const std::string& +extra_args_error::format(void) const +{ + return _format; +} + + +/// Gets the value of the first extra argument. +const std::string& +extra_args_error::arg(void) const +{ + return _arg; +} diff --git a/external/bsd/kyua-cli/dist/utils/format/exceptions.hpp b/external/bsd/kyua-cli/dist/utils/format/exceptions.hpp new file mode 100644 index 000000000..b55f35531 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/format/exceptions.hpp @@ -0,0 +1,83 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file utils/format/exceptions.hpp +/// Exception types raised by the format module. + +#if !defined(UTILS_FORMAT_EXCEPTIONS_HPP) +#define UTILS_FORMAT_EXCEPTIONS_HPP + +#include + +namespace utils { +namespace format { + + +/// Base exception for format errors. +class error : public std::runtime_error { +public: + explicit error(const std::string&); + virtual ~error(void) throw(); +}; + + +/// Error denoting a bad format string. +class bad_format_error : public error { + /// The format string that caused the error. + std::string _format; + +public: + explicit bad_format_error(const std::string&, const std::string&); + virtual ~bad_format_error(void) throw(); + + const std::string& format(void) const; +}; + + +/// Error denoting too many arguments for the format string. +class extra_args_error : public error { + /// The format string that was passed too many arguments. + std::string _format; + + /// The first argument that caused the error. + std::string _arg; + +public: + explicit extra_args_error(const std::string&, const std::string&); + virtual ~extra_args_error(void) throw(); + + const std::string& format(void) const; + const std::string& arg(void) const; +}; + + +} // namespace format +} // namespace utils + + +#endif // !defined(UTILS_FORMAT_EXCEPTIONS_HPP) diff --git a/external/bsd/kyua-cli/dist/utils/format/exceptions_test.cpp b/external/bsd/kyua-cli/dist/utils/format/exceptions_test.cpp new file mode 100644 index 000000000..9b8e36309 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/format/exceptions_test.cpp @@ -0,0 +1,74 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/format/exceptions.hpp" + +#include + +#include + +using utils::format::bad_format_error; +using utils::format::error; +using utils::format::extra_args_error; + + +ATF_TEST_CASE_WITHOUT_HEAD(error); +ATF_TEST_CASE_BODY(error) +{ + const error e("Some text"); + ATF_REQUIRE(std::strcmp("Some text", e.what()) == 0); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(bad_format_error); +ATF_TEST_CASE_BODY(bad_format_error) +{ + const bad_format_error e("format-string", "the-error"); + ATF_REQUIRE(std::strcmp("Invalid formatting string 'format-string': " + "the-error", e.what()) == 0); + ATF_REQUIRE_EQ("format-string", e.format()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(extra_args_error); +ATF_TEST_CASE_BODY(extra_args_error) +{ + const extra_args_error e("fmt", "extra"); + ATF_REQUIRE(std::strcmp("Not enough fields in formatting string 'fmt' to " + "place argument 'extra'", e.what()) == 0); + ATF_REQUIRE_EQ("fmt", e.format()); + ATF_REQUIRE_EQ("extra", e.arg()); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, error); + ATF_ADD_TEST_CASE(tcs, bad_format_error); + ATF_ADD_TEST_CASE(tcs, extra_args_error); +} diff --git a/external/bsd/kyua-cli/dist/utils/format/formatter.cpp b/external/bsd/kyua-cli/dist/utils/format/formatter.cpp new file mode 100644 index 000000000..ef7afd3b6 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/format/formatter.cpp @@ -0,0 +1,291 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/format/formatter.hpp" + +#include +#include +#include + +#include "utils/format/exceptions.hpp" +#include "utils/sanity.hpp" +#include "utils/text/exceptions.hpp" +#include "utils/text/operations.ipp" + +namespace format = utils::format; +namespace text = utils::text; + + +namespace { + + +/// Finds the next placeholder in a string. +/// +/// \param format The original format string provided by the user; needed for +/// error reporting purposes only. +/// \param expansion The string containing the placeholder to look for. Any +/// '%%' in the string will be skipped, and they must be stripped later by +/// strip_double_percent(). +/// \param begin The position from which to start looking for the next +/// placeholder. +/// +/// \return The position in the string in which the placeholder is located and +/// the placeholder itself. If there are no placeholders left, this returns +/// the length of the string and an empty string. +/// +/// \throw bad_format_error If the input string contains a trailing formatting +/// character. We cannot detect any other kind of invalid formatter because +/// we do not implement a full parser for them. +static std::pair< std::string::size_type, std::string > +find_next_placeholder(const std::string& format, + const std::string& expansion, + std::string::size_type begin) +{ + begin = expansion.find('%', begin); + while (begin != std::string::npos && expansion[begin + 1] == '%') + begin = expansion.find('%', begin + 2); + if (begin == std::string::npos) + return std::make_pair(expansion.length(), ""); + if (begin == expansion.length() - 1) + throw format::bad_format_error(format, "Trailing %"); + + std::string::size_type end = begin + 1; + while (end < expansion.length() && expansion[end] != 's') + end++; + const std::string placeholder = expansion.substr(begin, end - begin + 1); + if (end == expansion.length() || + placeholder.find('%', 1) != std::string::npos) + throw format::bad_format_error(format, "Unterminated placeholder '" + + placeholder + "'"); + return std::make_pair(begin, placeholder); +} + + +/// Converts a string to an integer. +/// +/// \param format The format string; for error reporting purposes only. +/// \param str The string to conver. +/// \param what The name of the field this integer belongs to; for error +/// reporting purposes only. +/// +/// \return An integer representing the input string. +inline int +to_int(const std::string& format, const std::string& str, const char* what) +{ + try { + return text::to_type< int >(str); + } catch (const text::value_error& e) { + throw format::bad_format_error(format, "Invalid " + std::string(what) + + "specifier"); + } +} + + +/// Constructs an std::ostringstream based on a formatting placeholder. +/// +/// \param format The format placeholder; may be empty. +/// +/// \return A new std::ostringstream that is prepared to format a single +/// object in the manner specified by the format placeholder. +/// +/// \throw bad_format_error If the format string is bad. We do minimal +/// validation on this string though. +static std::ostringstream* +new_ostringstream(const std::string& format) +{ + std::auto_ptr< std::ostringstream > output(new std::ostringstream()); + + if (format.length() <= 2) { + // If the format is empty, we create a new stream so that we don't have + // to check for NULLs later on. We rarely should hit this condition + // (and when we do it's a bug in the caller), so this is not a big deal. + // + // Otherwise, if the format is a regular '%s', then we don't have to do + // any processing for additional formatters. So this is just a "fast + // path". + } else { + std::string partial = format.substr(1, format.length() - 2); + if (partial[0] == '0') { + output->fill('0'); + partial.erase(0, 1); + } + if (!partial.empty()) { + const std::string::size_type dot = partial.find('.'); + if (dot != 0) + output->width(to_int(format, partial.substr(0, dot), "width")); + if (dot != std::string::npos) { + output->setf(std::ios::fixed, std::ios::floatfield); + output->precision(to_int(format, partial.substr(dot + 1), + "precision")); + } + } + } + + return output.release(); +} + + +/// Replaces '%%' by '%' in a given string range. +/// +/// \param in The input string to be rewritten. +/// \param begin The position at which to start the replacement. +/// \param end The position at which to end the replacement. +/// +/// \return The modified string and the amount of characters removed. +static std::pair< std::string, int > +strip_double_percent(const std::string& in, const std::string::size_type begin, + std::string::size_type end) +{ + std::string part = in.substr(begin, end - begin); + + int removed = 0; + std::string::size_type pos = part.find("%%"); + while (pos != std::string::npos) { + part.erase(pos, 1); + ++removed; + pos = part.find("%%", pos + 1); + } + + return std::make_pair(in.substr(0, begin) + part + in.substr(end), removed); +} + + +} // anonymous namespace + + +/// Performs internal initialization of the formatter. +/// +/// This is separate from the constructor just because it is shared by different +/// overloaded constructors. +void +format::formatter::init(void) +{ + const std::pair< std::string::size_type, std::string > placeholder = + find_next_placeholder(_format, _expansion, _last_pos); + const std::pair< std::string, int > no_percents = + strip_double_percent(_expansion, _last_pos, placeholder.first); + + _oss = new_ostringstream(placeholder.second); + + _expansion = no_percents.first; + _placeholder_pos = placeholder.first - no_percents.second; + _placeholder = placeholder.second; +} + + +/// Constructs a new formatter object (internal). +/// +/// \param format The format string. +/// \param expansion The format string with any replacements performed so far. +/// \param last_pos The position from which to start looking for formatting +/// placeholders. This must be maintained in case one of the replacements +/// introduced a new placeholder, which must be ignored. Think, for +/// example, replacing a "%s" string with "foo %s". +format::formatter::formatter(const std::string& format, + const std::string& expansion, + const std::string::size_type last_pos) : + _format(format), + _expansion(expansion), + _last_pos(last_pos), + _oss(NULL) +{ + init(); +} + + +/// Constructs a new formatter object. +/// +/// \param format The format string. The formatters in the string are not +/// validated during construction, but will cause errors when used later if +/// they are invalid. +format::formatter::formatter(const std::string& format) : + _format(format), + _expansion(format), + _last_pos(0), + _oss(NULL) +{ + init(); +} + + +format::formatter::~formatter(void) +{ + delete _oss; +} + + +/// Returns the formatted string. +const std::string& +format::formatter::str(void) const +{ + return _expansion; +} + + +/// Automatic conversion of formatter objects to strings. +/// +/// This is provided to allow painless injection of formatter objects into +/// streams, without having to manually call the str() method. +format::formatter::operator const std::string&(void) const +{ + return _expansion; +} + + +/// Specialization of operator% for booleans. +/// +/// \param value The boolean to inject into the format string. +/// +/// \return A new formatter that has one less format placeholder. +format::formatter +format::formatter::operator%(const bool& value) const +{ + (*_oss) << (value ? "true" : "false"); + return replace(_oss->str()); +} + + +/// Replaces the first formatting placeholder with a value. +/// +/// \param arg The replacement string. +/// +/// \return A new formatter in which the first formatting placeholder has been +/// replaced by arg and is ready to replace the next item. +/// +/// \throw utils::format::extra_args_error If there are no more formatting +/// placeholders in the input string, or if the placeholder is invalid. +format::formatter +format::formatter::replace(const std::string& arg) const +{ + if (_placeholder_pos == _expansion.length()) + throw format::extra_args_error(_format, arg); + + const std::string expansion = _expansion.substr(0, _placeholder_pos) + + arg + _expansion.substr(_placeholder_pos + _placeholder.length()); + return formatter(_format, expansion, _placeholder_pos + arg.length()); +} diff --git a/external/bsd/kyua-cli/dist/utils/format/formatter.hpp b/external/bsd/kyua-cli/dist/utils/format/formatter.hpp new file mode 100644 index 000000000..7b9483d12 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/format/formatter.hpp @@ -0,0 +1,121 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file utils/format/formatter.hpp +/// Provides the definition of the utils::format::formatter class. +/// +/// The utils::format::formatter class is a poor man's replacement for the +/// Boost.Format library, as it is much simpler and has less dependencies. +/// +/// Be aware that the formatting supported by this module is NOT compatible +/// with printf(3) nor with Boost.Format. The general syntax for a +/// placeholder in a formatting string is: +/// +/// %[0][width][.precision]s +/// +/// In particular, note that the only valid formatting specifier is %s: the +/// library deduces what to print based on the type of the variable passed +/// in, not based on what the format string says. Also, note that the only +/// valid padding character is 0. + +#if !defined(UTILS_FORMAT_FORMATTER_HPP) +#define UTILS_FORMAT_FORMATTER_HPP + +#include +#include + +namespace utils { +namespace format { + + +/// Mechanism to format strings similar to printf. +/// +/// A formatter always maintains the original format string but also holds a +/// partial expansion. The partial expansion is immutable in the context of a +/// formatter instance, but calls to operator% return new formatter objects with +/// one less formatting placeholder. +/// +/// In general, one can format a string in the following manner: +/// +/// \code +/// const std::string s = (formatter("%s %s") % "foo" % 5).str(); +/// \endcode +/// +/// which, following the explanation above, would correspond to: +/// +/// \code +/// const formatter f1("%s %s"); +/// const formatter f2 = f1 % "foo"; +/// const formatter f3 = f2 % 5; +/// const std::string s = f3.str(); +/// \endcode +class formatter { + /// The original format string provided by the user. + std::string _format; + + /// The current "expansion" of the format string. + /// + /// This field gets updated on every call to operator%() to have one less + /// formatting placeholder. + std::string _expansion; + + /// The position of _expansion from which to scan for placeholders. + std::string::size_type _last_pos; + + /// The position of the first placeholder in the current expansion. + std::string::size_type _placeholder_pos; + + /// The first placeholder in the current expansion. + std::string _placeholder; + + /// Stream used to format any possible argument supplied by operator%(). + std::ostringstream* _oss; + + formatter replace(const std::string&) const; + + void init(void); + formatter(const std::string&, const std::string&, + const std::string::size_type); + +public: + explicit formatter(const std::string&); + ~formatter(void); + + const std::string& str(void) const; + operator const std::string&(void) const; + + template< typename Type > formatter operator%(const Type&) const; + formatter operator%(const bool&) const; +}; + + +} // namespace format +} // namespace utils + + +#endif // !defined(UTILS_FORMAT_FORMATTER_HPP) diff --git a/external/bsd/kyua-cli/dist/utils/format/formatter.ipp b/external/bsd/kyua-cli/dist/utils/format/formatter.ipp new file mode 100644 index 000000000..e1d1e10d6 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/format/formatter.ipp @@ -0,0 +1,76 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#if !defined(UTILS_FORMAT_FORMATTER_IPP) +#define UTILS_FORMAT_FORMATTER_IPP + +#include + +#include "utils/format/formatter.hpp" + +namespace utils { +namespace format { + + +/// Replaces the first format placeholder in a formatter. +/// +/// Constructs a new formatter object that has one less formatting placeholder, +/// as this has been replaced by the provided argument. Calling this operator +/// N times, where N is the number of formatting placeholders, effectively +/// formats the string. +/// +/// \param arg The argument to use as replacement for the format placeholder. +/// +/// \return A new formatter that has one less format placeholder. +template< typename Type > +inline formatter +formatter::operator%(const Type& arg) const +{ + (*_oss) << arg; + return replace(_oss->str()); +} + + +/// Inserts a formatter string into a stream. +/// +/// \param os The output stream. +/// \param f The formatter to process and inject into the stream. +/// +/// \return The output stream os. +inline std::ostream& +operator<<(std::ostream& os, const formatter& f) +{ + return (os << f.str()); +} + + +} // namespace format +} // namespace utils + + +#endif // !defined(UTILS_FORMAT_FORMATTER_IPP) diff --git a/external/bsd/kyua-cli/dist/utils/format/formatter_test.cpp b/external/bsd/kyua-cli/dist/utils/format/formatter_test.cpp new file mode 100644 index 000000000..3226a0a4e --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/format/formatter_test.cpp @@ -0,0 +1,265 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/format/formatter.hpp" + +#include + +#include + +#include "utils/format/exceptions.hpp" +#include "utils/format/macros.hpp" + +namespace format = utils::format; + + +namespace { + + +/// Wraps an integer in a C++ class. +/// +/// This custom type exists to ensure that we can feed arbitrary objects that +/// support operator<< to the formatter; +class int_wrapper { + /// The wrapped integer. + int _value; + +public: + /// Constructs a new wrapper. + /// + /// \param value_ The value to wrap. + int_wrapper(const int value_) : _value(value_) + { + } + + /// Returns the wrapped value. + /// + /// \return An integer. + int + value(void) const + { + return _value; + } +}; + + +/// Writes a wrapped integer into an output stream. +/// +/// \param output The output stream into which to place the integer. +/// \param wrapper The wrapped integer. +/// +/// \return The output stream. +std::ostream& +operator<<(std::ostream& output, const int_wrapper& wrapper) +{ + return (output << wrapper.value()); +} + + +} // anonymous namespace + + +/// Calls ATF_REQUIRE_EQ on an expected string and a formatter. +/// +/// This is pure syntactic sugar to avoid calling the str() method on all the +/// individual tests below, which results in very long lines that require +/// wrapping and clutter readability. +/// +/// \param expected The expected string generated by the formatter. +/// \param formatter The formatter to test. +#define EQ(expected, formatter) ATF_REQUIRE_EQ(expected, (formatter).str()) + + +ATF_TEST_CASE_WITHOUT_HEAD(no_fields); +ATF_TEST_CASE_BODY(no_fields) +{ + EQ("Plain string", F("Plain string")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(one_field); +ATF_TEST_CASE_BODY(one_field) +{ + EQ("foo", F("%sfoo") % ""); + EQ(" foo", F("%sfoo") % " "); + EQ("foo ", F("foo %s") % ""); + EQ("foo bar", F("foo %s") % "bar"); + EQ("foo bar baz", F("foo %s baz") % "bar"); + EQ("foo %s %s", F("foo %s %s") % "%s" % "%s"); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(many_fields); +ATF_TEST_CASE_BODY(many_fields) +{ + EQ("", F("%s%s") % "" % ""); + EQ("foo", F("%s%s%s") % "" % "foo" % ""); + EQ("some 5 text", F("%s %s %s") % "some" % 5 % "text"); + EQ("f%s 5 text", F("%s %s %s") % "f%s" % 5 % "text"); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(escape); +ATF_TEST_CASE_BODY(escape) +{ + EQ("%", F("%%")); + EQ("% %", F("%% %%")); + EQ("%% %%", F("%%%% %%%%")); + + EQ("foo %", F("foo %%")); + EQ("foo bar %", F("foo %s %%") % "bar"); + EQ("foo % bar", F("foo %% %s") % "bar"); + + EQ("foo %%", F("foo %s") % "%%"); + EQ("foo a%%b", F("foo a%sb") % "%%"); + EQ("foo a%%b", F("foo %s") % "a%%b"); + + EQ("foo % bar %%", F("foo %% %s %%%%") % "bar"); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(extra_args_error); +ATF_TEST_CASE_BODY(extra_args_error) +{ + using format::extra_args_error; + + ATF_REQUIRE_THROW(extra_args_error, F("foo") % "bar"); + ATF_REQUIRE_THROW(extra_args_error, F("foo %%") % "bar"); + ATF_REQUIRE_THROW(extra_args_error, F("foo %s") % "bar" % "baz"); + ATF_REQUIRE_THROW(extra_args_error, F("foo %s") % "%s" % "bar"); + ATF_REQUIRE_THROW(extra_args_error, F("%s foo %s") % "bar" % "baz" % "foo"); + + try { + F("foo %s %s") % "bar" % "baz" % "something extra"; + fail("extra_args_error not raised"); + } catch (const extra_args_error& e) { + ATF_REQUIRE_EQ("foo %s %s", e.format()); + ATF_REQUIRE_EQ("something extra", e.arg()); + } +} + + +ATF_TEST_CASE_WITHOUT_HEAD(format__class); +ATF_TEST_CASE_BODY(format__class) +{ + EQ("foo bar", F("%s") % std::string("foo bar")); + EQ("3", F("%s") % int_wrapper(3)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(format__pointer); +ATF_TEST_CASE_BODY(format__pointer) +{ + EQ("0xcafebabe", F("%s") % reinterpret_cast< void* >(0xcafebabe)); + EQ("foo bar", F("%s") % "foo bar"); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(format__bool); +ATF_TEST_CASE_BODY(format__bool) +{ + EQ("true", F("%s") % true); + EQ("false", F("%s") % false); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(format__char); +ATF_TEST_CASE_BODY(format__char) +{ + EQ("Z", F("%s") % 'Z'); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(format__float); +ATF_TEST_CASE_BODY(format__float) +{ + EQ("3", F("%s") % 3.0); + EQ("3.0", F("%.1s") % 3.0); + EQ("3.0", F("%0.1s") % 3.0); + EQ(" 15.600", F("%8.3s") % 15.6); + EQ("01.52", F("%05.2s") % 1.52); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(format__int); +ATF_TEST_CASE_BODY(format__int) +{ + EQ("3", F("%s") % 3); + EQ("3", F("%0s") % 3); + EQ(" -123", F("%5s") % -123); + EQ("00078", F("%05s") % 78); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(format__error); +ATF_TEST_CASE_BODY(format__error) +{ + using format::bad_format_error; + + ATF_REQUIRE_THROW_RE(bad_format_error, "Trailing %", F("%")); + ATF_REQUIRE_THROW_RE(bad_format_error, "Trailing %", F("f%")); + ATF_REQUIRE_THROW_RE(bad_format_error, "Trailing %", F("f%%%")); + ATF_REQUIRE_THROW_RE(bad_format_error, "Trailing %", F("ab %s cd%") % "cd"); + + ATF_REQUIRE_THROW_RE(bad_format_error, "Invalid width", F("%1bs")); + + ATF_REQUIRE_THROW_RE(bad_format_error, "Invalid precision", F("%.s")); + ATF_REQUIRE_THROW_RE(bad_format_error, "Invalid precision", F("%0.s")); + ATF_REQUIRE_THROW_RE(bad_format_error, "Invalid precision", F("%123.s")); + ATF_REQUIRE_THROW_RE(bad_format_error, "Invalid precision", F("%.12bs")); + + ATF_REQUIRE_THROW_RE(bad_format_error, "Unterminated", F("%c") % 'Z'); + ATF_REQUIRE_THROW_RE(bad_format_error, "Unterminated", F("%d") % 5); + ATF_REQUIRE_THROW_RE(bad_format_error, "Unterminated", F("%.1f") % 3); + ATF_REQUIRE_THROW_RE(bad_format_error, "Unterminated", F("%d%s") % 3 % "a"); + + try { + F("foo %s%") % "bar"; + fail("bad_format_error not raised"); + } catch (const bad_format_error& e) { + ATF_REQUIRE_EQ("foo %s%", e.format()); + } +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, no_fields); + ATF_ADD_TEST_CASE(tcs, one_field); + ATF_ADD_TEST_CASE(tcs, many_fields); + ATF_ADD_TEST_CASE(tcs, escape); + ATF_ADD_TEST_CASE(tcs, extra_args_error); + + ATF_ADD_TEST_CASE(tcs, format__class); + ATF_ADD_TEST_CASE(tcs, format__pointer); + ATF_ADD_TEST_CASE(tcs, format__bool); + ATF_ADD_TEST_CASE(tcs, format__char); + ATF_ADD_TEST_CASE(tcs, format__float); + ATF_ADD_TEST_CASE(tcs, format__int); + ATF_ADD_TEST_CASE(tcs, format__error); +} diff --git a/external/bsd/kyua-cli/dist/utils/format/macros.hpp b/external/bsd/kyua-cli/dist/utils/format/macros.hpp new file mode 100644 index 000000000..06f061f64 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/format/macros.hpp @@ -0,0 +1,58 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file utils/format/macros.hpp +/// Convenience macros to simplify usage of the format library. +/// +/// This file must not be included from other header files. + +#if !defined(UTILS_FORMAT_MACROS_HPP) +#define UTILS_FORMAT_MACROS_HPP + +// We include the .ipp file instead of .hpp because, after all, macros.hpp +// is provided purely for convenience and must not be included from other +// header files. Henceforth, we make things easier to the callers. +#include "utils/format/formatter.ipp" + + +/// Constructs a utils::format::formatter object with the given format string. +/// +/// This macro is just a wrapper to make the construction of +/// utils::format::formatter objects shorter, and thus to allow inlining these +/// calls right in where formatted strings are required. A typical usage would +/// look like: +/// +/// \code +/// std::cout << F("%s %d\n") % my_str % my_int; +/// \endcode +/// +/// \param fmt The format string. +#define F(fmt) utils::format::formatter(fmt) + + +#endif // !defined(UTILS_FORMAT_MACROS_HPP) diff --git a/external/bsd/kyua-cli/dist/utils/fs/Kyuafile b/external/bsd/kyua-cli/dist/utils/fs/Kyuafile new file mode 100644 index 000000000..59f14b1c8 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/fs/Kyuafile @@ -0,0 +1,9 @@ +syntax(2) + +test_suite("kyua") + +atf_test_program{name="auto_cleaners_test"} +atf_test_program{name="exceptions_test"} +atf_test_program{name="lua_module_test"} +atf_test_program{name="operations_test"} +atf_test_program{name="path_test"} diff --git a/external/bsd/kyua-cli/dist/utils/fs/auto_cleaners.cpp b/external/bsd/kyua-cli/dist/utils/fs/auto_cleaners.cpp new file mode 100644 index 000000000..c20ff4f11 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/fs/auto_cleaners.cpp @@ -0,0 +1,255 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/fs/auto_cleaners.hpp" + +#include "utils/format/macros.hpp" +#include "utils/fs/exceptions.hpp" +#include "utils/fs/operations.hpp" +#include "utils/logging/macros.hpp" +#include "utils/sanity.hpp" +#include "utils/signals/interrupts.hpp" + +namespace fs = utils::fs; +namespace signals = utils::signals; + + +/// Shared implementation of the auto_directory. +struct utils::fs::auto_directory::impl { + /// The path to the directory being managed. + fs::path _directory; + + /// Whether cleanup() has been already executed or not. + bool _cleaned; + + /// Constructor. + /// + /// \param directory_ The directory to grab the ownership of. + impl(const path& directory_) : + _directory(directory_), + _cleaned(false) + { + } + + /// Destructor. + ~impl(void) + { + try { + this->cleanup(); + } catch (const fs::error& e) { + LW(F("Failed to auto-cleanup directory '%s': %s") % _directory % + e.what()); + } + } + + /// Removes the directory. + /// + /// See the cleanup() method of the auto_directory class for details. + void + cleanup(void) + { + if (!_cleaned) { + // Mark this as cleaned first so that, in case of failure, we don't + // reraise the error from the destructor. + _cleaned = true; + + fs::rmdir(_directory); + } + } +}; + + +/// Constructs a new auto_directory and grabs ownership of a directory. +/// +/// \param directory_ The directory to grab the ownership of. +fs::auto_directory::auto_directory(const path& directory_) : + _pimpl(new impl(directory_)) +{ +} + + +/// Deletes the managed directory; must be empty. +/// +/// This should not be relied on because it cannot provide proper error +/// reporting. Instead, the caller should use the cleanup() method. +fs::auto_directory::~auto_directory(void) +{ +} + + +/// Creates a self-destructing temporary directory. +/// +/// \param path_template The template for the temporary path, which is a +/// basename that is created within the TMPDIR. Must contain the XXXXXX +/// pattern, which is atomically replaced by a random unique string. +/// +/// \return The self-destructing directory. +/// +/// \throw fs::error If the creation fails. +fs::auto_directory +fs::auto_directory::mkdtemp(const std::string& path_template) +{ + signals::interrupts_inhibiter inhibiter; + const fs::path directory_ = fs::mkdtemp(path_template); + try { + return auto_directory(directory_); + } catch (...) { + fs::rmdir(directory_); + throw; + } +} + + +/// Gets the directory managed by this auto_directory. +/// +/// \return The path to the managed directory. +const fs::path& +fs::auto_directory::directory(void) const +{ + return _pimpl->_directory; +} + + +/// Deletes the managed directory; must be empty. +/// +/// This operation is idempotent. +/// +/// \throw fs::error If there is a problem removing any directory or file. +void +fs::auto_directory::cleanup(void) +{ + _pimpl->cleanup(); +} + + +/// Shared implementation of the auto_file. +struct utils::fs::auto_file::impl { + /// The path to the file being managed. + fs::path _file; + + /// Whether removed() has been already executed or not. + bool _removed; + + /// Constructor. + /// + /// \param file_ The file to grab the ownership of. + impl(const path& file_) : + _file(file_), + _removed(false) + { + } + + /// Destructor. + ~impl(void) + { + try { + this->remove(); + } catch (const fs::error& e) { + LW(F("Failed to auto-cleanup file '%s': %s") % _file % + e.what()); + } + } + + /// Removes the file. + /// + /// See the remove() method of the auto_file class for details. + void + remove(void) + { + if (!_removed) { + // Mark this as cleaned first so that, in case of failure, we don't + // reraise the error from the destructor. + _removed = true; + + fs::unlink(_file); + } + } +}; + + +/// Constructs a new auto_file and grabs ownership of a file. +/// +/// \param file_ The file to grab the ownership of. +fs::auto_file::auto_file(const path& file_) : + _pimpl(new impl(file_)) +{ +} + + +/// Deletes the managed file. +/// +/// This should not be relied on because it cannot provide proper error +/// reporting. Instead, the caller should use the remove() method. +fs::auto_file::~auto_file(void) +{ +} + + +/// Creates a self-destructing temporary file. +/// +/// \param path_template The template for the temporary path, which is a +/// basename that is created within the TMPDIR. Must contain the XXXXXX +/// pattern, which is atomically replaced by a random unique string. +/// +/// \return The self-destructing file. +/// +/// \throw fs::error If the creation fails. +fs::auto_file +fs::auto_file::mkstemp(const std::string& path_template) +{ + signals::interrupts_inhibiter inhibiter; + const fs::path file_ = fs::mkstemp(path_template); + try { + return auto_file(file_); + } catch (...) { + fs::unlink(file_); + throw; + } +} + + +/// Gets the file managed by this auto_file. +/// +/// \return The path to the managed file. +const fs::path& +fs::auto_file::file(void) const +{ + return _pimpl->_file; +} + + +/// Deletes the managed file. +/// +/// This operation is idempotent. +/// +/// \throw fs::error If there is a problem removing the file. +void +fs::auto_file::remove(void) +{ + _pimpl->remove(); +} diff --git a/external/bsd/kyua-cli/dist/utils/fs/auto_cleaners.hpp b/external/bsd/kyua-cli/dist/utils/fs/auto_cleaners.hpp new file mode 100644 index 000000000..4d08902aa --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/fs/auto_cleaners.hpp @@ -0,0 +1,87 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file utils/fs/auto_cleaners.hpp +/// RAII wrappers to automatically remove file system entries. + +#if !defined(UTILS_FS_AUTO_CLEANERS_HPP) +#define UTILS_FS_AUTO_CLEANERS_HPP + +#include +#include + +#include "utils/fs/path.hpp" + +namespace utils { +namespace fs { + + +/// Grabs ownership of a directory and removes it upon destruction. +/// +/// This class is reference-counted and therefore only the destruction of the +/// last instance will cause the removal of the directory. +class auto_directory { + struct impl; + /// Reference-counted, shared implementation. + std::tr1::shared_ptr< impl > _pimpl; + +public: + explicit auto_directory(const path&); + ~auto_directory(void); + + static auto_directory mkdtemp(const std::string&); + + const path& directory(void) const; + void cleanup(void); +}; + + +/// Grabs ownership of a file and removes it upon destruction. +/// +/// This class is reference-counted and therefore only the destruction of the +/// last instance will cause the removal of the file. +class auto_file { + struct impl; + /// Reference-counted, shared implementation. + std::tr1::shared_ptr< impl > _pimpl; + +public: + explicit auto_file(const path&); + ~auto_file(void); + + static auto_file mkstemp(const std::string&); + + const path& file(void) const; + void remove(void); +}; + + +} // namespace fs +} // namespace utils + +#endif // !defined(UTILS_FS_AUTO_CLEANERS_HPP) diff --git a/external/bsd/kyua-cli/dist/utils/fs/auto_cleaners_test.cpp b/external/bsd/kyua-cli/dist/utils/fs/auto_cleaners_test.cpp new file mode 100644 index 000000000..bfc01ab75 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/fs/auto_cleaners_test.cpp @@ -0,0 +1,166 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/fs/auto_cleaners.hpp" + +extern "C" { +#include +} + +#include + +#include "utils/env.hpp" +#include "utils/fs/operations.hpp" + +namespace fs = utils::fs; + + +ATF_TEST_CASE_WITHOUT_HEAD(auto_directory__automatic); +ATF_TEST_CASE_BODY(auto_directory__automatic) +{ + const fs::path root("root"); + fs::mkdir(root, 0755); + + { + fs::auto_directory dir(root); + ATF_REQUIRE_EQ(root, dir.directory()); + + ATF_REQUIRE(::access("root", X_OK) == 0); + + { + fs::auto_directory dir_copy(dir); + } + // Should still exist after a copy is destructed. + ATF_REQUIRE(::access("root", X_OK) == 0); + } + ATF_REQUIRE(::access("root", X_OK) == -1); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(auto_directory__explicit); +ATF_TEST_CASE_BODY(auto_directory__explicit) +{ + const fs::path root("root"); + fs::mkdir(root, 0755); + + fs::auto_directory dir(root); + ATF_REQUIRE_EQ(root, dir.directory()); + + ATF_REQUIRE(::access("root", X_OK) == 0); + dir.cleanup(); + dir.cleanup(); + ATF_REQUIRE(::access("root", X_OK) == -1); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(auto_directory__mkdtemp); +ATF_TEST_CASE_BODY(auto_directory__mkdtemp) +{ + utils::setenv("TMPDIR", (fs::current_path() / "tmp").str()); + fs::mkdir(fs::path("tmp"), 0755); + + const std::string path_template("test.XXXXXX"); + { + fs::auto_directory auto_directory = fs::auto_directory::mkdtemp( + path_template); + ATF_REQUIRE(::access((fs::path("tmp") / path_template).c_str(), + X_OK) == -1); + ATF_REQUIRE(::rmdir("tmp") == -1); + + ATF_REQUIRE(::access(auto_directory.directory().c_str(), X_OK) == 0); + } + ATF_REQUIRE(::rmdir("tmp") != -1); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(auto_file__automatic); +ATF_TEST_CASE_BODY(auto_file__automatic) +{ + const fs::path file("foo"); + atf::utils::create_file(file.str(), ""); + { + fs::auto_file auto_file(file); + ATF_REQUIRE_EQ(file, auto_file.file()); + + ATF_REQUIRE(::access(file.c_str(), R_OK) == 0); + + { + fs::auto_file auto_file_copy(auto_file); + } + // Should still exist after a copy is destructed. + ATF_REQUIRE(::access(file.c_str(), R_OK) == 0); + } + ATF_REQUIRE(::access(file.c_str(), R_OK) == -1); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(auto_file__explicit); +ATF_TEST_CASE_BODY(auto_file__explicit) +{ + const fs::path file("bar"); + atf::utils::create_file(file.str(), ""); + + fs::auto_file auto_file(file); + ATF_REQUIRE_EQ(file, auto_file.file()); + + ATF_REQUIRE(::access(file.c_str(), R_OK) == 0); + auto_file.remove(); + auto_file.remove(); + ATF_REQUIRE(::access(file.c_str(), R_OK) == -1); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(auto_file__mkstemp); +ATF_TEST_CASE_BODY(auto_file__mkstemp) +{ + utils::setenv("TMPDIR", (fs::current_path() / "tmp").str()); + fs::mkdir(fs::path("tmp"), 0755); + + const std::string path_template("test.XXXXXX"); + { + fs::auto_file auto_file = fs::auto_file::mkstemp(path_template); + ATF_REQUIRE(::access((fs::path("tmp") / path_template).c_str(), + X_OK) == -1); + ATF_REQUIRE(::rmdir("tmp") == -1); + + ATF_REQUIRE(::access(auto_file.file().c_str(), R_OK) == 0); + } + ATF_REQUIRE(::rmdir("tmp") != -1); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, auto_directory__automatic); + ATF_ADD_TEST_CASE(tcs, auto_directory__explicit); + ATF_ADD_TEST_CASE(tcs, auto_directory__mkdtemp); + + ATF_ADD_TEST_CASE(tcs, auto_file__automatic); + ATF_ADD_TEST_CASE(tcs, auto_file__explicit); + ATF_ADD_TEST_CASE(tcs, auto_file__mkstemp); +} diff --git a/external/bsd/kyua-cli/dist/utils/fs/exceptions.cpp b/external/bsd/kyua-cli/dist/utils/fs/exceptions.cpp new file mode 100644 index 000000000..aabd809eb --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/fs/exceptions.cpp @@ -0,0 +1,146 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/fs/exceptions.hpp" + +#include + +#include "utils/format/macros.hpp" + +namespace fs = utils::fs; + + +/// Constructs a new error with a plain-text message. +/// +/// \param message The plain-text error message. +fs::error::error(const std::string& message) : + std::runtime_error(message) +{ +} + + +/// Destructor for the error. +fs::error::~error(void) throw() +{ +} + + +/// Constructs a new invalid_path_error. +/// +/// \param textual_path Textual representation of the invalid path. +/// \param reason Description of the error in the path. +fs::invalid_path_error::invalid_path_error(const std::string& textual_path, + const std::string& reason) : + error(F("Invalid path '%s': %s") % textual_path % reason), + _textual_path(textual_path) +{ +} + + +/// Destructor for the error. +fs::invalid_path_error::~invalid_path_error(void) throw() +{ +} + + +/// Returns the invalid path related to the exception. +/// +/// \return The textual representation of the invalid path. +const std::string& +fs::invalid_path_error::invalid_path(void) const +{ + return _textual_path; +} + + +/// Constructs a new join_error. +/// +/// \param textual_path1_ Textual representation of the first path. +/// \param textual_path2_ Textual representation of the second path. +/// \param reason Description of the error in the join operation. +fs::join_error::join_error(const std::string& textual_path1_, + const std::string& textual_path2_, + const std::string& reason) : + error(F("Cannot join paths '%s' and '%s': %s") % textual_path1_ % + textual_path2_ % reason), + _textual_path1(textual_path1_), + _textual_path2(textual_path2_) +{ +} + + +/// Destructor for the error. +fs::join_error::~join_error(void) throw() +{ +} + + +/// Gets the first path that caused the error in a join operation. +/// +/// \return The textual representation of the path. +const std::string& +fs::join_error::textual_path1(void) const +{ + return _textual_path1; +} + + +/// Gets the second path that caused the error in a join operation. +/// +/// \return The textual representation of the path. +const std::string& +fs::join_error::textual_path2(void) const +{ + return _textual_path2; +} + + +/// Constructs a new error based on an errno code. +/// +/// \param message_ The message describing what caused the error. +/// \param errno_ The error code. +fs::system_error::system_error(const std::string& message_, const int errno_) : + error(F("%s: %s") % message_ % std::strerror(errno_)), + _original_errno(errno_) +{ +} + + +/// Destructor for the error. +fs::system_error::~system_error(void) throw() +{ +} + + + +/// Gets the original errno code. +int +fs::system_error::original_errno(void) const throw() +{ + return _original_errno; +} diff --git a/external/bsd/kyua-cli/dist/utils/fs/exceptions.hpp b/external/bsd/kyua-cli/dist/utils/fs/exceptions.hpp new file mode 100644 index 000000000..9f7fda1ab --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/fs/exceptions.hpp @@ -0,0 +1,101 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file utils/fs/exceptions.hpp +/// Exception types raised by the fs module. + +#if !defined(UTILS_FS_EXCEPTIONS_HPP) +#define UTILS_FS_EXCEPTIONS_HPP + +#include + +namespace utils { +namespace fs { + + +/// Base exception for fs errors. +class error : public std::runtime_error { +public: + explicit error(const std::string&); + virtual ~error(void) throw(); +}; + + +/// Error denoting an invalid path while constructing a fs::path object. +class invalid_path_error : public error { + /// Raw value of the invalid path. + std::string _textual_path; + +public: + explicit invalid_path_error(const std::string&, const std::string&); + virtual ~invalid_path_error(void) throw(); + + const std::string& invalid_path(void) const; +}; + + +/// Paths cannot be joined. +class join_error : public error { + /// Raw value of the first path in the join operation. + std::string _textual_path1; + + /// Raw value of the second path in the join operation. + std::string _textual_path2; + +public: + explicit join_error(const std::string&, const std::string&, + const std::string&); + virtual ~join_error(void) throw(); + + const std::string& textual_path1(void) const; + const std::string& textual_path2(void) const; +}; + + +/// Exceptions for errno-based errors. +/// +/// TODO(jmmv): This code is duplicated in, at least, utils::process. Figure +/// out a way to reuse this exception while maintaining the correct inheritance +/// (i.e. be able to keep it as a child of fs::error). +class system_error : public error { + /// Error number describing this libc error condition. + int _original_errno; + +public: + explicit system_error(const std::string&, const int); + ~system_error(void) throw(); + + int original_errno(void) const throw(); +}; + + +} // namespace fs +} // namespace utils + + +#endif // !defined(UTILS_FS_EXCEPTIONS_HPP) diff --git a/external/bsd/kyua-cli/dist/utils/fs/exceptions_test.cpp b/external/bsd/kyua-cli/dist/utils/fs/exceptions_test.cpp new file mode 100644 index 000000000..b0c55e27c --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/fs/exceptions_test.cpp @@ -0,0 +1,86 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/fs/exceptions.hpp" + +#include +#include + +#include + +#include "utils/format/macros.hpp" + +namespace fs = utils::fs; + + +ATF_TEST_CASE_WITHOUT_HEAD(error); +ATF_TEST_CASE_BODY(error) +{ + const fs::error e("Some text"); + ATF_REQUIRE(std::strcmp("Some text", e.what()) == 0); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(invalid_path_error); +ATF_TEST_CASE_BODY(invalid_path_error) +{ + const fs::invalid_path_error e("some/invalid/path", "The reason"); + ATF_REQUIRE(std::strcmp("Invalid path 'some/invalid/path': The reason", + e.what()) == 0); + ATF_REQUIRE_EQ("some/invalid/path", e.invalid_path()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(join_error); +ATF_TEST_CASE_BODY(join_error) +{ + const fs::join_error e("dir1/file1", "/dir2/file2", "The reason"); + ATF_REQUIRE(std::strcmp("Cannot join paths 'dir1/file1' and '/dir2/file2': " + "The reason", e.what()) == 0); + ATF_REQUIRE_EQ("dir1/file1", e.textual_path1()); + ATF_REQUIRE_EQ("/dir2/file2", e.textual_path2()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(system_error); +ATF_TEST_CASE_BODY(system_error) +{ + const fs::system_error e("Call failed", ENOENT); + const std::string expected = F("Call failed: %s") % std::strerror(ENOENT); + ATF_REQUIRE_EQ(expected, e.what()); + ATF_REQUIRE_EQ(ENOENT, e.original_errno()); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, error); + ATF_ADD_TEST_CASE(tcs, invalid_path_error); + ATF_ADD_TEST_CASE(tcs, join_error); + ATF_ADD_TEST_CASE(tcs, system_error); +} diff --git a/external/bsd/kyua-cli/dist/utils/fs/lua_module.cpp b/external/bsd/kyua-cli/dist/utils/fs/lua_module.cpp new file mode 100644 index 000000000..916215966 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/fs/lua_module.cpp @@ -0,0 +1,270 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/fs/lua_module.hpp" + +extern "C" { +#include +} + +#include +#include +#include +#include + +#include +#include + +#include "utils/format/macros.hpp" +#include "utils/fs/operations.hpp" +#include "utils/fs/path.hpp" +#include "utils/sanity.hpp" + +namespace fs = utils::fs; + + +namespace { + + +/// Lua binding for fs::path::basename. +/// +/// \pre stack(-1) The input path. +/// \post stack(-1) The basename of the input path. +/// +/// \param state The Lua state. +/// +/// \return The number of result values, i.e. 1. +static int +lua_fs_basename(lutok::state& state) +{ + if (!state.is_string()) + throw std::runtime_error("Need a string parameter"); + const fs::path path(state.to_string()); + + state.push_string(path.leaf_name().c_str()); + return 1; +} + + +/// Lua binding for fs::path::dirname. +/// +/// \pre stack(-1) The input path. +/// \post stack(-1) The directory part of the input path. +/// +/// \param state The Lua state. +/// +/// \return The number of result values, i.e. 1. +static int +lua_fs_dirname(lutok::state& state) +{ + if (!state.is_string()) + throw std::runtime_error("Need a string parameter"); + const fs::path path(state.to_string()); + + state.push_string(path.branch_path().c_str()); + return 1; +} + + +/// Lua binding for fs::path::exists. +/// +/// \pre stack(-1) The input path. +/// \post stack(-1) Whether the input path exists or not. +/// +/// \param state The Lua state. +/// +/// \return The number of result values, i.e. 1. +static int +lua_fs_exists(lutok::state& state) +{ + if (!state.is_string()) + throw std::runtime_error("Need a string parameter"); + const fs::path path(state.to_string()); + + state.push_boolean(fs::exists(path)); + return 1; +} + + +/// Lua binding for the files iterator. +/// +/// This function takes an open directory from the closure of the iterator and +/// returns the next entry. See lua_fs_files() for the iterator generator +/// function. +/// +/// \pre upvalue(1) The userdata containing an open DIR* object. +/// +/// \param state The lua state. +/// +/// \return The number of result values, i.e. 0 if there are no more entries or +/// 1 if an entry has been read. +static int +files_iterator(lutok::state& state) +{ + DIR** dirp = state.to_userdata< DIR* >(state.upvalue_index(1)); + const struct dirent* entry = ::readdir(*dirp); + if (entry == NULL) + return 0; + else { + state.push_string(entry->d_name); + return 1; + } +} + + +/// Lua binding for the destruction of the files iterator. +/// +/// This function takes an open directory and closes it. See lua_fs_files() for +/// the iterator generator function. +/// +/// \pre stack(-1) The userdata containing an open DIR* object. +/// \post The DIR* object is closed. +/// +/// \param state The lua state. +/// +/// \return The number of result values, i.e. 0. +static int +files_gc(lutok::state& state) +{ + PRE(state.is_userdata()); + + DIR** dirp = state.to_userdata< DIR* >(); + // For some reason, this may be called more than once. I don't know why + // this happens, but we must protect against it. + if (*dirp != NULL) { + ::closedir(*dirp); + *dirp = NULL; + } + + return 0; +} + + +/// Lua binding to create an iterator to scan the contents of a directory. +/// +/// \pre stack(-1) The input path. +/// \post stack(-1) The iterator function. +/// +/// \param state The Lua state. +/// +/// \return The number of result values, i.e. 1. +static int +lua_fs_files(lutok::state& state) +{ + if (!state.is_string()) + throw std::runtime_error("Need a string parameter"); + const fs::path path(state.to_string()); + + DIR** dirp = state.new_userdata< DIR* >(); + + state.new_table(); + state.push_string("__gc"); + state.push_cxx_function(files_gc); + state.set_table(); + + state.set_metatable(); + + *dirp = ::opendir(path.c_str()); + if (*dirp == NULL) { + const int original_errno = errno; + throw std::runtime_error(F("Failed to open directory: %s") % + std::strerror(original_errno)); + } + + state.push_cxx_closure(files_iterator, 1); + + return 1; +} + + +/// Lua binding for fs::path::is_absolute. +/// +/// \pre stack(-1) The input path. +/// \post stack(-1) Whether the input path is absolute or not. +/// +/// \param state The Lua state. +/// +/// \return The number of result values, i.e. 1. +static int +lua_fs_is_absolute(lutok::state& state) +{ + if (!state.is_string()) + throw std::runtime_error("Need a string parameter"); + const fs::path path(state.to_string()); + + state.push_boolean(path.is_absolute()); + return 1; +} + + +/// Lua binding for fs::path::operator/. +/// +/// \pre stack(-2) The first input path. +/// \pre stack(-1) The second input path. +/// \post stack(-1) The concatenation of the two paths. +/// +/// \param state The Lua state. +/// +/// \return The number of result values, i.e. 1. +static int +lua_fs_join(lutok::state& state) +{ + if (!state.is_string(-2)) + throw std::runtime_error("Need a string parameter"); + const fs::path path1(state.to_string(-2)); + + if (!state.is_string(-1)) + throw std::runtime_error("Need a string parameter"); + const fs::path path2(state.to_string(-1)); + + state.push_string((path1 / path2).c_str()); + return 1; +} + + +} // anonymous namespace + + +/// Creates a Lua 'fs' module. +/// +/// \post The global 'fs' symbol is set to a table that contains functions to a +/// variety of utilites from the fs C++ module. +/// +/// \param s The Lua state. +void +fs::open_fs(lutok::state& s) +{ + std::map< std::string, lutok::cxx_function > members; + members["basename"] = lua_fs_basename; + members["dirname"] = lua_fs_dirname; + members["exists"] = lua_fs_exists; + members["files"] = lua_fs_files; + members["is_absolute"] = lua_fs_is_absolute; + members["join"] = lua_fs_join; + lutok::create_module(s, "fs", members); +} diff --git a/external/bsd/kyua-cli/dist/utils/fs/lua_module.hpp b/external/bsd/kyua-cli/dist/utils/fs/lua_module.hpp new file mode 100644 index 000000000..08f78c3e7 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/fs/lua_module.hpp @@ -0,0 +1,47 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file utils/fs/lua_module.hpp +/// Lua bindings for the utils::fs module. + +#if !defined(UTILS_FS_LUA_MODULE_HPP) +#define UTILS_FS_LUA_MODULE_HPP + +#include + +namespace utils { +namespace fs { + + +void open_fs(lutok::state&); + + +} // namespace fs +} // namespace utils + +#endif // !defined(UTILS_FS_LUA_MODULE_HPP) diff --git a/external/bsd/kyua-cli/dist/utils/fs/lua_module_test.cpp b/external/bsd/kyua-cli/dist/utils/fs/lua_module_test.cpp new file mode 100644 index 000000000..96ad2bf2e --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/fs/lua_module_test.cpp @@ -0,0 +1,290 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/fs/lua_module.hpp" + +#include +#include +#include +#include + +#include "utils/fs/operations.hpp" +#include "utils/fs/path.hpp" + +namespace fs = utils::fs; + + +ATF_TEST_CASE_WITHOUT_HEAD(open_fs); +ATF_TEST_CASE_BODY(open_fs) +{ + lutok::state state; + stack_balance_checker checker(state); + fs::open_fs(state); + lutok::do_string(state, "return fs.basename", 1); + ATF_REQUIRE(state.is_function()); + lutok::do_string(state, "return fs.dirname", 1); + ATF_REQUIRE(state.is_function()); + lutok::do_string(state, "return fs.join", 1); + ATF_REQUIRE(state.is_function()); + state.pop(3); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(basename__ok); +ATF_TEST_CASE_BODY(basename__ok) +{ + lutok::state state; + fs::open_fs(state); + + lutok::do_string(state, "return fs.basename('/my/test//file_foobar')", 1); + ATF_REQUIRE_EQ("file_foobar", state.to_string()); + state.pop(1); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(basename__fail); +ATF_TEST_CASE_BODY(basename__fail) +{ + lutok::state state; + fs::open_fs(state); + + ATF_REQUIRE_THROW_RE(lutok::error, "Need a string", + lutok::do_string(state, "return fs.basename({})", 1)); + ATF_REQUIRE_THROW_RE(lutok::error, "Invalid path", + lutok::do_string(state, "return fs.basename('')", 1)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(dirname__ok); +ATF_TEST_CASE_BODY(dirname__ok) +{ + lutok::state state; + fs::open_fs(state); + + lutok::do_string(state, "return fs.dirname('/my/test//file_foobar')", 1); + ATF_REQUIRE_EQ("/my/test", state.to_string()); + state.pop(1); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(dirname__fail); +ATF_TEST_CASE_BODY(dirname__fail) +{ + lutok::state state; + fs::open_fs(state); + + ATF_REQUIRE_THROW_RE(lutok::error, "Need a string", + lutok::do_string(state, "return fs.dirname({})", 1)); + ATF_REQUIRE_THROW_RE(lutok::error, "Invalid path", + lutok::do_string(state, "return fs.dirname('')", 1)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(exists__ok); +ATF_TEST_CASE_BODY(exists__ok) +{ + lutok::state state; + fs::open_fs(state); + + atf::utils::create_file("foo", ""); + + lutok::do_string(state, "return fs.exists('foo')", 1); + ATF_REQUIRE(state.to_boolean()); + state.pop(1); + + lutok::do_string(state, "return fs.exists('bar')", 1); + ATF_REQUIRE(!state.to_boolean()); + state.pop(1); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(exists__fail); +ATF_TEST_CASE_BODY(exists__fail) +{ + lutok::state state; + fs::open_fs(state); + + ATF_REQUIRE_THROW_RE(lutok::error, "Need a string", + lutok::do_string(state, "return fs.exists({})", 1)); + ATF_REQUIRE_THROW_RE(lutok::error, "Invalid path", + lutok::do_string(state, "return fs.exists('')", 1)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(files__none); +ATF_TEST_CASE_BODY(files__none) +{ + lutok::state state; + state.open_table(); + fs::open_fs(state); + + fs::mkdir(fs::path("root"), 0755); + + lutok::do_string(state, + "names = {}\n" + "for file in fs.files('root') do\n" + " table.insert(names, file)\n" + "end\n" + "table.sort(names)\n" + "return table.concat(names, ' ')", 1); + ATF_REQUIRE_EQ(". ..", state.to_string()); + state.pop(1); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(files__some); +ATF_TEST_CASE_BODY(files__some) +{ + lutok::state state; + state.open_table(); + fs::open_fs(state); + + fs::mkdir(fs::path("root"), 0755); + atf::utils::create_file("root/file1", ""); + atf::utils::create_file("root/file2", ""); + + lutok::do_string(state, + "names = {}\n" + "for file in fs.files('root') do\n" + " table.insert(names, file)\n" + "end\n" + "table.sort(names)\n" + "return table.concat(names, ' ')", 1); + ATF_REQUIRE_EQ(". .. file1 file2", state.to_string()); + state.pop(1); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(files__fail_arg); +ATF_TEST_CASE_BODY(files__fail_arg) +{ + lutok::state state; + fs::open_fs(state); + + ATF_REQUIRE_THROW_RE(lutok::error, "Need a string parameter", + lutok::do_string(state, "fs.files({})")); + ATF_REQUIRE_THROW_RE(lutok::error, "Invalid path", + lutok::do_string(state, "fs.files('')")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(files__fail_opendir); +ATF_TEST_CASE_BODY(files__fail_opendir) +{ + lutok::state state; + fs::open_fs(state); + + ATF_REQUIRE_THROW_RE(lutok::error, "Failed to open directory", + lutok::do_string(state, "fs.files('root')")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(is_absolute__ok); +ATF_TEST_CASE_BODY(is_absolute__ok) +{ + lutok::state state; + fs::open_fs(state); + + lutok::do_string(state, "return fs.is_absolute('my/test//file_foobar')", 1); + ATF_REQUIRE(!state.to_boolean()); + lutok::do_string(state, "return fs.is_absolute('/my/test//file_foobar')", 1); + ATF_REQUIRE(state.to_boolean()); + state.pop(2); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(is_absolute__fail); +ATF_TEST_CASE_BODY(is_absolute__fail) +{ + lutok::state state; + fs::open_fs(state); + + ATF_REQUIRE_THROW_RE(lutok::error, "Need a string", + lutok::do_string(state, "return fs.is_absolute({})", 1)); + ATF_REQUIRE_THROW_RE(lutok::error, "Invalid path", + lutok::do_string(state, "return fs.is_absolute('')", 1)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(join__ok); +ATF_TEST_CASE_BODY(join__ok) +{ + lutok::state state; + fs::open_fs(state); + + lutok::do_string(state, "return fs.join('/a/b///', 'c/d')", 1); + ATF_REQUIRE_EQ("/a/b/c/d", state.to_string()); + state.pop(1); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(join__fail); +ATF_TEST_CASE_BODY(join__fail) +{ + lutok::state state; + fs::open_fs(state); + + ATF_REQUIRE_THROW_RE(lutok::error, "Need a string", + lutok::do_string(state, "return fs.join({}, 'a')", 1)); + ATF_REQUIRE_THROW_RE(lutok::error, "Need a string", + lutok::do_string(state, "return fs.join('a', {})", 1)); + + ATF_REQUIRE_THROW_RE(lutok::error, "Invalid path", + lutok::do_string(state, "return fs.join('', 'a')", 1)); + ATF_REQUIRE_THROW_RE(lutok::error, "Invalid path", + lutok::do_string(state, "return fs.join('a', '')", 1)); + + ATF_REQUIRE_THROW_RE(lutok::error, "Cannot join.*'a/b'.*'/c'", + lutok::do_string(state, "fs.join('a/b', '/c')")); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, open_fs); + + ATF_ADD_TEST_CASE(tcs, basename__ok); + ATF_ADD_TEST_CASE(tcs, basename__fail); + + ATF_ADD_TEST_CASE(tcs, dirname__ok); + ATF_ADD_TEST_CASE(tcs, dirname__fail); + + ATF_ADD_TEST_CASE(tcs, exists__ok); + ATF_ADD_TEST_CASE(tcs, exists__fail); + + ATF_ADD_TEST_CASE(tcs, files__none); + ATF_ADD_TEST_CASE(tcs, files__some); + ATF_ADD_TEST_CASE(tcs, files__fail_arg); + ATF_ADD_TEST_CASE(tcs, files__fail_opendir); + + ATF_ADD_TEST_CASE(tcs, is_absolute__ok); + ATF_ADD_TEST_CASE(tcs, is_absolute__fail); + + ATF_ADD_TEST_CASE(tcs, join__ok); + ATF_ADD_TEST_CASE(tcs, join__fail); +} diff --git a/external/bsd/kyua-cli/dist/utils/fs/operations.cpp b/external/bsd/kyua-cli/dist/utils/fs/operations.cpp new file mode 100644 index 000000000..f835208f4 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/fs/operations.cpp @@ -0,0 +1,343 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/fs/operations.hpp" + +#if defined(HAVE_CONFIG_H) +# include "config.h" +#endif + +extern "C" { +#include + +#include +#include +} + +#include +#include +#include +#include +#include + +#include "utils/auto_array.ipp" +#include "utils/defs.hpp" +#include "utils/env.hpp" +#include "utils/format/macros.hpp" +#include "utils/fs/exceptions.hpp" +#include "utils/fs/path.hpp" +#include "utils/logging/macros.hpp" +#include "utils/optional.ipp" +#include "utils/sanity.hpp" + +namespace fs = utils::fs; + +using utils::optional; + + +namespace { + + +/// Stats a file, without following links. +/// +/// \param path The file to stat. +/// +/// \return The stat structure on success. +/// +/// \throw system_error An error on failure. +static struct ::stat +safe_stat(const fs::path& path) +{ + struct ::stat sb; + if (::lstat(path.c_str(), &sb) == -1) { + const int original_errno = errno; + throw fs::system_error(F("Cannot get information about %s") % path, + original_errno); + } + return sb; +} + + +} // anonymous namespace + + +/// Queries the path to the current directory. +/// +/// \return The path to the current directory. +/// +/// \throw fs::error If there is a problem querying the current directory. +fs::path +fs::current_path(void) +{ + char* cwd; +#if defined(HAVE_GETCWD_DYN) + cwd = ::getcwd(NULL, 0); +#else + cwd = ::getcwd(NULL, MAXPATHLEN); +#endif + if (cwd == NULL) { + const int original_errno = errno; + throw fs::system_error(F("Failed to get current working directory"), + original_errno); + } + + try { + const fs::path result(cwd); + std::free(cwd); + return result; + } catch (...) { + std::free(cwd); + throw; + } +} + + +/// Checks if a file exists. +/// +/// Be aware that this is racy in the same way as access(2) is. +/// +/// \param path The file to check the existance of. +/// +/// \return True if the file exists; false otherwise. +bool +fs::exists(const fs::path& path) +{ + return ::access(path.c_str(), F_OK) == 0; +} + + +/// Locates a file in the PATH. +/// +/// \param name The file to locate. +/// +/// \return The path to the located file or none if it was not found. The +/// returned path is always absolute. +optional< fs::path > +fs::find_in_path(const char* name) +{ + const optional< std::string > current_path = utils::getenv("PATH"); + if (!current_path || current_path.get().empty()) + return none; + + std::istringstream path_input(current_path.get() + ":"); + std::string path_component; + while (std::getline(path_input, path_component, ':').good()) { + const fs::path candidate = path_component.empty() ? + fs::path(name) : (fs::path(path_component) / name); + if (exists(candidate)) { + if (candidate.is_absolute()) + return utils::make_optional(candidate); + else + return utils::make_optional(candidate.to_absolute()); + } + } + return none; +} + + +/// Creates a directory. +/// +/// \param dir The path to the directory to create. +/// \param mode The permissions for the new directory. +/// +/// \throw system_error If the call to mkdir(2) fails. +void +fs::mkdir(const fs::path& dir, const int mode) +{ + if (::mkdir(dir.c_str(), static_cast< mode_t >(mode)) == -1) { + const int original_errno = errno; + throw fs::system_error(F("Failed to create directory %s") % dir, + original_errno); + } +} + + +/// Creates a directory and any missing parents. +/// +/// This is separate from the fs::mkdir function to clearly differentiate the +/// libc wrapper from the more complex algorithm implemented here. +/// +/// \param dir The path to the directory to create. +/// \param mode The permissions for the new directories. +/// +/// \throw system_error If any call to mkdir(2) fails. +void +fs::mkdir_p(const fs::path& dir, const int mode) +{ + try { + fs::mkdir(dir, mode); + } catch (const fs::system_error& e) { + if (e.original_errno() == ENOENT) { + fs::mkdir_p(dir.branch_path(), mode); + fs::mkdir(dir, mode); + } else if (e.original_errno() != EEXIST) + throw e; + } +} + + +/// Creates a temporary directory. +/// +/// The temporary directory is created using mkdtemp(3) using the provided +/// template. This should be most likely used in conjunction with +/// fs::auto_directory. +/// +/// \param path_template The template for the temporary path, which is a +/// basename that is created within the TMPDIR. Must contain the XXXXXX +/// pattern, which is atomically replaced by a random unique string. +/// +/// \return The generated path for the temporary directory. +/// +/// \throw fs::system_error If the call to mkdtemp(3) fails. +fs::path +fs::mkdtemp(const std::string& path_template) +{ + PRE(path_template.find("XXXXXX") != std::string::npos); + + const fs::path tmpdir(utils::getenv_with_default("TMPDIR", "/tmp")); + const fs::path full_template = tmpdir / path_template; + + utils::auto_array< char > buf(new char[full_template.str().length() + 1]); + std::strcpy(buf.get(), full_template.c_str()); + if (::mkdtemp(buf.get()) == NULL) { + const int original_errno = errno; + throw fs::system_error(F("Cannot create temporary directory using " + "template %s") % full_template, + original_errno); + } + return fs::path(buf.get()); +} + + +/// Creates a temporary file. +/// +/// The temporary file is created using mkstemp(3) using the provided template. +/// This should be most likely used in conjunction with fs::auto_file. +/// +/// \param path_template The template for the temporary path, which is a +/// basename that is created within the TMPDIR. Must contain the XXXXXX +/// pattern, which is atomically replaced by a random unique string. +/// +/// \return The generated path for the temporary directory. +/// +/// \throw fs::system_error If the call to mkstemp(3) fails. +fs::path +fs::mkstemp(const std::string& path_template) +{ + PRE(path_template.find("XXXXXX") != std::string::npos); + + const fs::path tmpdir(utils::getenv_with_default("TMPDIR", "/tmp")); + const fs::path full_template = tmpdir / path_template; + + utils::auto_array< char > buf(new char[full_template.str().length() + 1]); + std::strcpy(buf.get(), full_template.c_str()); + if (::mkstemp(buf.get()) == -1) { + const int original_errno = errno; + throw fs::system_error(F("Cannot create temporary file using template " + "%s") % full_template, original_errno); + } + return fs::path(buf.get()); +} + + +/// Recursively removes a directory. +/// +/// This operation simulates a "rm -r". No effort is made to forcibly delete +/// files and no attention is paid to mount points. +/// +/// \param directory The directory to remove. +/// +/// \throw fs::error If there is a problem removing any directory or file. +void +fs::rm_r(const fs::path& directory) +{ + DIR* dirp = ::opendir(directory.c_str()); + if (dirp == NULL) { + const int original_errno = errno; + throw fs::system_error(F("Failed to open directory %s") % + directory.str(), original_errno); + } + try { + ::dirent* dp; + while ((dp = ::readdir(dirp)) != NULL) { + const std::string name = dp->d_name; + if (name == "." || name == "..") + continue; + + const fs::path entry = directory / dp->d_name; + + const struct ::stat sb = safe_stat(entry); + if (S_ISDIR(sb.st_mode)) { + LD(F("Descending into %s") % entry); + fs::rm_r(entry); + } else { + LD(F("Removing file %s") % entry); + fs::unlink(entry); + } + } + } catch (...) { + ::closedir(dirp); + throw; + } + ::closedir(dirp); + + LD(F("Removing empty directory %s") % directory); + fs::rmdir(directory); +} + + +/// Removes an empty directory. +/// +/// \param file The directory to remove. +/// +/// \throw fs::system_error If the call to rmdir(2) fails. +void +fs::rmdir(const path& file) +{ + if (::rmdir(file.c_str()) == -1) { + const int original_errno = errno; + throw fs::system_error(F("Removal of %s failed") % file, + original_errno); + } +} + + +/// Removes a file. +/// +/// \param file The file to remove. +/// +/// \throw fs::system_error If the call to unlink(2) fails. +void +fs::unlink(const path& file) +{ + if (::unlink(file.c_str()) == -1) { + const int original_errno = errno; + throw fs::system_error(F("Removal of %s failed") % file, + original_errno); + } +} diff --git a/external/bsd/kyua-cli/dist/utils/fs/operations.hpp b/external/bsd/kyua-cli/dist/utils/fs/operations.hpp new file mode 100644 index 000000000..3db9daee8 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/fs/operations.hpp @@ -0,0 +1,64 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file utils/fs/operations.hpp +/// File system algorithms and access functions. +/// +/// The functions in this module are exception-based, type-improved wrappers +/// over the functions provided by libc. + +#if !defined(UTILS_FS_OPERATIONS_HPP) +#define UTILS_FS_OPERATIONS_HPP + +#include + +#include "utils/optional.hpp" + +namespace utils { +namespace fs { + + +class path; + + +path current_path(void); +bool exists(const fs::path&); +utils::optional< path > find_in_path(const char*); +void mkdir(const path&, const int); +void mkdir_p(const path&, const int); +fs::path mkdtemp(const std::string&); +fs::path mkstemp(const std::string&); +void rm_r(const path&); +void rmdir(const path&); +void unlink(const path&); + + +} // namespace fs +} // namespace utils + +#endif // !defined(UTILS_FS_OPERATIONS_HPP) diff --git a/external/bsd/kyua-cli/dist/utils/fs/operations_test.cpp b/external/bsd/kyua-cli/dist/utils/fs/operations_test.cpp new file mode 100644 index 000000000..8043e2e83 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/fs/operations_test.cpp @@ -0,0 +1,410 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/fs/operations.hpp" + +extern "C" { +#include +#include +#include + +#include +#include +#include +} + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "utils/env.hpp" +#include "utils/format/macros.hpp" +#include "utils/fs/exceptions.hpp" +#include "utils/fs/path.hpp" +#include "utils/optional.ipp" + +namespace fs = utils::fs; + +using utils::optional; + + +namespace { + + +/// Checks if a directory entry exists and matches a specific type. +/// +/// \param dir The directory in which to look for the entry. +/// \param name The name of the entry to look up. +/// \param expected_type The expected type of the file as given by dir(5). +/// +/// \return True if the entry exists and matches the given type; false +/// otherwise. +static bool +lookup(const char* dir, const char* name, const int expected_type) +{ + DIR* dirp = ::opendir(dir); + ATF_REQUIRE(dirp != NULL); + + bool found = false; + struct dirent* dp; + while (!found && (dp = readdir(dirp)) != NULL) { + if (std::strcmp(dp->d_name, name) == 0 && + dp->d_type == expected_type) { + found = true; + } + } + ::closedir(dirp); + return found; +} + + +} // anonymous namespace + + +ATF_TEST_CASE_WITHOUT_HEAD(current_path__ok); +ATF_TEST_CASE_BODY(current_path__ok) +{ + const fs::path previous = fs::current_path(); + fs::mkdir(fs::path("root"), 0755); + ATF_REQUIRE(::chdir("root") != -1); + const fs::path cwd = fs::current_path(); + ATF_REQUIRE_EQ(cwd.str().length() - 5, cwd.str().find("/root")); + ATF_REQUIRE_EQ(previous / "root", cwd); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(current_path__enoent); +ATF_TEST_CASE_BODY(current_path__enoent) +{ + const fs::path previous = fs::current_path(); + fs::mkdir(fs::path("root"), 0755); + ATF_REQUIRE(::chdir("root") != -1); + ATF_REQUIRE(::rmdir("../root") != -1); + try { + (void)fs::current_path(); + fail("system_errpr not raised"); + } catch (const fs::system_error& e) { + ATF_REQUIRE_EQ(ENOENT, e.original_errno()); + } +} + + +ATF_TEST_CASE_WITHOUT_HEAD(exists); +ATF_TEST_CASE_BODY(exists) +{ + const fs::path dir("dir"); + ATF_REQUIRE(!fs::exists(dir)); + fs::mkdir(dir, 0755); + ATF_REQUIRE(fs::exists(dir)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(find_in_path__no_path); +ATF_TEST_CASE_BODY(find_in_path__no_path) +{ + utils::unsetenv("PATH"); + ATF_REQUIRE(!fs::find_in_path("ls")); + atf::utils::create_file("ls", ""); + ATF_REQUIRE(!fs::find_in_path("ls")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(find_in_path__empty_path); +ATF_TEST_CASE_BODY(find_in_path__empty_path) +{ + utils::setenv("PATH", ""); + ATF_REQUIRE(!fs::find_in_path("ls")); + atf::utils::create_file("ls", ""); + ATF_REQUIRE(!fs::find_in_path("ls")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(find_in_path__one_component); +ATF_TEST_CASE_BODY(find_in_path__one_component) +{ + const fs::path dir = fs::current_path() / "bin"; + fs::mkdir(dir, 0755); + utils::setenv("PATH", dir.str()); + + ATF_REQUIRE(!fs::find_in_path("ls")); + atf::utils::create_file((dir / "ls").str(), ""); + ATF_REQUIRE_EQ(dir / "ls", fs::find_in_path("ls").get()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(find_in_path__many_components); +ATF_TEST_CASE_BODY(find_in_path__many_components) +{ + const fs::path dir1 = fs::current_path() / "dir1"; + const fs::path dir2 = fs::current_path() / "dir2"; + fs::mkdir(dir1, 0755); + fs::mkdir(dir2, 0755); + utils::setenv("PATH", dir1.str() + ":" + dir2.str()); + + ATF_REQUIRE(!fs::find_in_path("ls")); + atf::utils::create_file((dir2 / "ls").str(), ""); + ATF_REQUIRE_EQ(dir2 / "ls", fs::find_in_path("ls").get()); + atf::utils::create_file((dir1 / "ls").str(), ""); + ATF_REQUIRE_EQ(dir1 / "ls", fs::find_in_path("ls").get()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(find_in_path__current_directory); +ATF_TEST_CASE_BODY(find_in_path__current_directory) +{ + utils::setenv("PATH", "bin:"); + + ATF_REQUIRE(!fs::find_in_path("foo-bar")); + atf::utils::create_file("foo-bar", ""); + ATF_REQUIRE_EQ(fs::path("foo-bar").to_absolute(), + fs::find_in_path("foo-bar").get()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(find_in_path__always_absolute); +ATF_TEST_CASE_BODY(find_in_path__always_absolute) +{ + fs::mkdir(fs::path("my-bin"), 0755); + utils::setenv("PATH", "my-bin"); + + ATF_REQUIRE(!fs::find_in_path("abcd")); + atf::utils::create_file("my-bin/abcd", ""); + ATF_REQUIRE_EQ(fs::path("my-bin/abcd").to_absolute(), + fs::find_in_path("abcd").get()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(mkdir__ok); +ATF_TEST_CASE_BODY(mkdir__ok) +{ + fs::mkdir(fs::path("dir"), 0755); + ATF_REQUIRE(lookup(".", "dir", DT_DIR)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(mkdir__enoent); +ATF_TEST_CASE_BODY(mkdir__enoent) +{ + try { + fs::mkdir(fs::path("dir1/dir2"), 0755); + fail("system_error not raised"); + } catch (const fs::system_error& e) { + ATF_REQUIRE_EQ(ENOENT, e.original_errno()); + } + ATF_REQUIRE(!lookup(".", "dir1", DT_DIR)); + ATF_REQUIRE(!lookup(".", "dir2", DT_DIR)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(mkdir_p__one_component); +ATF_TEST_CASE_BODY(mkdir_p__one_component) +{ + ATF_REQUIRE(!lookup(".", "new-dir", DT_DIR)); + fs::mkdir_p(fs::path("new-dir"), 0755); + ATF_REQUIRE(lookup(".", "new-dir", DT_DIR)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(mkdir_p__many_components); +ATF_TEST_CASE_BODY(mkdir_p__many_components) +{ + ATF_REQUIRE(!lookup(".", "a", DT_DIR)); + fs::mkdir_p(fs::path("a/b/c"), 0755); + ATF_REQUIRE(lookup(".", "a", DT_DIR)); + ATF_REQUIRE(lookup("a", "b", DT_DIR)); + ATF_REQUIRE(lookup("a/b", "c", DT_DIR)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(mkdir_p__already_exists); +ATF_TEST_CASE_BODY(mkdir_p__already_exists) +{ + fs::mkdir(fs::path("a"), 0755); + fs::mkdir(fs::path("a/b"), 0755); + fs::mkdir_p(fs::path("a/b"), 0755); +} + + +ATF_TEST_CASE(mkdir_p__eacces) +ATF_TEST_CASE_HEAD(mkdir_p__eacces) +{ + set_md_var("require.user", "unprivileged"); +} +ATF_TEST_CASE_BODY(mkdir_p__eacces) +{ + fs::mkdir(fs::path("a"), 0755); + fs::mkdir(fs::path("a/b"), 0755); + ATF_REQUIRE(::chmod("a/b", 0555) != -1); + try { + fs::mkdir_p(fs::path("a/b/c/d"), 0755); + fail("system_error not raised"); + } catch (const fs::system_error& e) { + ATF_REQUIRE_EQ(EACCES, e.original_errno()); + } + ATF_REQUIRE(lookup(".", "a", DT_DIR)); + ATF_REQUIRE(lookup("a", "b", DT_DIR)); + ATF_REQUIRE(!lookup(".", "c", DT_DIR)); + ATF_REQUIRE(!lookup("a", "c", DT_DIR)); + ATF_REQUIRE(!lookup("a/b", "c", DT_DIR)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(mkdtemp) +ATF_TEST_CASE_BODY(mkdtemp) +{ + const fs::path tmpdir = fs::current_path() / "tmp"; + utils::setenv("TMPDIR", tmpdir.str()); + fs::mkdir(tmpdir, 0755); + + const std::string dir_template("tempdir.XXXXXX"); + const fs::path tempdir = fs::mkdtemp(dir_template); + ATF_REQUIRE(!lookup("tmp", dir_template.c_str(), DT_DIR)); + ATF_REQUIRE(lookup("tmp", tempdir.leaf_name().c_str(), DT_DIR)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(mkstemp) +ATF_TEST_CASE_BODY(mkstemp) +{ + const fs::path tmpdir = fs::current_path() / "tmp"; + utils::setenv("TMPDIR", tmpdir.str()); + fs::mkdir(tmpdir, 0755); + + const std::string file_template("tempfile.XXXXXX"); + const fs::path tempfile = fs::mkstemp(file_template); + ATF_REQUIRE(!lookup("tmp", file_template.c_str(), DT_REG)); + ATF_REQUIRE(lookup("tmp", tempfile.leaf_name().c_str(), DT_REG)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(rm_r__empty); +ATF_TEST_CASE_BODY(rm_r__empty) +{ + fs::mkdir(fs::path("root"), 0755); + ATF_REQUIRE(lookup(".", "root", DT_DIR)); + fs::rm_r(fs::path("root")); + ATF_REQUIRE(!lookup(".", "root", DT_DIR)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(rm_r__files_and_directories); +ATF_TEST_CASE_BODY(rm_r__files_and_directories) +{ + fs::mkdir(fs::path("root"), 0755); + atf::utils::create_file("root/.hidden_file", ""); + fs::mkdir(fs::path("root/.hidden_dir"), 0755); + atf::utils::create_file("root/.hidden_dir/a", ""); + atf::utils::create_file("root/file", ""); + atf::utils::create_file("root/with spaces", ""); + fs::mkdir(fs::path("root/dir1"), 0755); + fs::mkdir(fs::path("root/dir1/dir2"), 0755); + atf::utils::create_file("root/dir1/dir2/file", ""); + fs::mkdir(fs::path("root/dir1/dir3"), 0755); + ATF_REQUIRE(lookup(".", "root", DT_DIR)); + fs::rm_r(fs::path("root")); + ATF_REQUIRE(!lookup(".", "root", DT_DIR)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(rmdir__ok) +ATF_TEST_CASE_BODY(rmdir__ok) +{ + ATF_REQUIRE(::mkdir("foo", 0755) != -1); + ATF_REQUIRE(::access("foo", X_OK) == 0); + fs::rmdir(fs::path("foo")); + ATF_REQUIRE(::access("foo", X_OK) == -1); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(rmdir__fail) +ATF_TEST_CASE_BODY(rmdir__fail) +{ + ATF_REQUIRE_THROW_RE(fs::system_error, "Removal of foo failed", + fs::rmdir(fs::path("foo"))); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(unlink__ok) +ATF_TEST_CASE_BODY(unlink__ok) +{ + atf::utils::create_file("foo", ""); + ATF_REQUIRE(::access("foo", R_OK) == 0); + fs::unlink(fs::path("foo")); + ATF_REQUIRE(::access("foo", R_OK) == -1); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(unlink__fail) +ATF_TEST_CASE_BODY(unlink__fail) +{ + ATF_REQUIRE_THROW_RE(fs::system_error, "Removal of foo failed", + fs::unlink(fs::path("foo"))); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, current_path__ok); + ATF_ADD_TEST_CASE(tcs, current_path__enoent); + + ATF_ADD_TEST_CASE(tcs, exists); + + ATF_ADD_TEST_CASE(tcs, find_in_path__no_path); + ATF_ADD_TEST_CASE(tcs, find_in_path__empty_path); + ATF_ADD_TEST_CASE(tcs, find_in_path__one_component); + ATF_ADD_TEST_CASE(tcs, find_in_path__many_components); + ATF_ADD_TEST_CASE(tcs, find_in_path__current_directory); + ATF_ADD_TEST_CASE(tcs, find_in_path__always_absolute); + + ATF_ADD_TEST_CASE(tcs, mkdir__ok); + ATF_ADD_TEST_CASE(tcs, mkdir__enoent); + + ATF_ADD_TEST_CASE(tcs, mkdir_p__one_component); + ATF_ADD_TEST_CASE(tcs, mkdir_p__many_components); + ATF_ADD_TEST_CASE(tcs, mkdir_p__already_exists); + ATF_ADD_TEST_CASE(tcs, mkdir_p__eacces); + + ATF_ADD_TEST_CASE(tcs, mkdtemp); + + ATF_ADD_TEST_CASE(tcs, mkstemp); + + ATF_ADD_TEST_CASE(tcs, rm_r__empty); + ATF_ADD_TEST_CASE(tcs, rm_r__files_and_directories); + + ATF_ADD_TEST_CASE(tcs, rmdir__ok); + ATF_ADD_TEST_CASE(tcs, rmdir__fail); + + ATF_ADD_TEST_CASE(tcs, unlink__ok); + ATF_ADD_TEST_CASE(tcs, unlink__fail); +} diff --git a/external/bsd/kyua-cli/dist/utils/fs/path.cpp b/external/bsd/kyua-cli/dist/utils/fs/path.cpp new file mode 100644 index 000000000..ae072b797 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/fs/path.cpp @@ -0,0 +1,299 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/fs/path.hpp" + +#include "utils/fs/exceptions.hpp" +#include "utils/fs/operations.hpp" +#include "utils/sanity.hpp" + +namespace fs = utils::fs; + + +namespace { + + +/// Normalizes an input string to a valid path. +/// +/// A normalized path cannot have empty components; i.e. there can be at most +/// one consecutive separator (/). +/// +/// \param in The string to normalize. +/// +/// \return The normalized string, representing a path. +/// +/// \throw utils::fs::invalid_path_error If the path is empty. +static std::string +normalize(const std::string& in) +{ + if (in.empty()) + throw fs::invalid_path_error(in, "Cannot be empty"); + + std::string out; + + std::string::size_type pos = 0; + do { + const std::string::size_type next_pos = in.find('/', pos); + + const std::string component = in.substr(pos, next_pos - pos); + if (!component.empty()) { + if (pos == 0) + out += component; + else if (component != ".") + out += "/" + component; + } + + if (next_pos == std::string::npos) + pos = next_pos; + else + pos = next_pos + 1; + } while (pos != std::string::npos); + + return out.empty() ? "/" : out; +} + + +} // anonymous namespace + + +/// Creates a new path object from a textual representation of a path. +/// +/// \param text A valid representation of a path in textual form. +/// +/// \throw utils::fs::invalid_path_error If the input text does not represent a +/// valid path. +fs::path::path(const std::string& text) : + _repr(normalize(text)) +{ +} + + +/// Gets a view of the path as an array of characters. +const char* +fs::path::c_str(void) const +{ + return _repr.c_str(); +} + + +/// Gets a view of the path as a std::string. +const std::string& +fs::path::str(void) const +{ + return _repr; +} + + +/// Gets the branch path (directory name) of the path. +/// +/// The branch path of a path with just one component (no separators) is ".". +/// +/// \return A new path representing the branch path. +fs::path +fs::path::branch_path(void) const +{ + const std::string::size_type end_pos = _repr.rfind('/'); + if (end_pos == std::string::npos) + return fs::path("."); + else if (end_pos == 0) + return fs::path("/"); + else + return fs::path(_repr.substr(0, end_pos)); +} + + +/// Gets the leaf name (base name) of the path. +/// +/// \return A new string representing the leaf name. +std::string +fs::path::leaf_name(void) const +{ + const std::string::size_type beg_pos = _repr.rfind('/'); + + if (beg_pos == std::string::npos) + return _repr; + else + return _repr.substr(beg_pos + 1); +} + + +/// Converts a relative path in the current directory to an absolute path. +/// +/// \pre The path is relative. +/// +/// \return The absolute representation of the relative path. +fs::path +fs::path::to_absolute(void) const +{ + PRE(!is_absolute()); + return fs::current_path() / *this; +} + + +/// Checks whether the path is absolute. +bool +fs::path::is_absolute(void) const +{ + return _repr[0] == '/'; +} + + +/// Checks whether the path is a parent of another path. +/// +/// A path is considered to be a parent of itself. +/// +/// \return True if this path is a parent of p. +bool +fs::path::is_parent_of(path p) const +{ + do { + if ((*this) == p) + return true; + p = p.branch_path(); + } while (p != fs::path(".") && p != fs::path("/")); + return false; +} + + +/// Counts the number of components in the path. +/// +/// \return The number of components. +int +fs::path::ncomponents(void) const +{ + int count = 0; + if (_repr == "/") + return 1; + else { + for (std::string::const_iterator iter = _repr.begin(); + iter != _repr.end(); ++iter) { + if (*iter == '/') + count++; + } + return count + 1; + } +} + + +/// Less-than comparator for paths. +/// +/// This is provided to make identifiers useful as map keys. +/// +/// \param p The path to compare to. +/// +/// \return True if this identifier sorts before the other identifier; false +/// otherwise. +bool +fs::path::operator<(const fs::path& p) const +{ + return _repr < p._repr; +} + + +/// Compares two paths for equality. +/// +/// Given that the paths are internally normalized, input paths such as +/// ///foo/bar and /foo///bar are exactly the same. However, this does NOT +/// check for true equality: i.e. this does not access the file system to check +/// if the paths actually point to the same object my means of links. +/// +/// \param p The path to compare to. +/// +/// \returns A boolean indicating whether the paths are equal. +bool +fs::path::operator==(const fs::path& p) const +{ + return _repr == p._repr; +} + + +/// Compares two paths for inequality. +/// +/// See the description of operator==() for more details on the comparison +/// performed. +/// +/// \param p The path to compare to. +/// +/// \returns A boolean indicating whether the paths are different. +bool +fs::path::operator!=(const fs::path& p) const +{ + return _repr != p._repr; +} + + +/// Concatenates this path with one or more components. +/// +/// \param components The new components to concatenate to the path. These are +/// normalized because, in general, they may come from user input. These +/// components cannot represent an absolute path. +/// +/// \return A new path containing the concatenation of this path and the +/// provided components. +/// +/// \throw utils::fs::invalid_path_error If components does not represent a +/// valid path. +/// \throw utils::fs::join_error If the join operation is invalid because the +/// two paths are incompatible. +fs::path +fs::path::operator/(const std::string& components) const +{ + return (*this) / fs::path(components); +} + + +/// Concatenates this path with another path. +/// +/// \param rest The path to concatenate to this one. Cannot be absolute. +/// +/// \return A new path containing the concatenation of this path and the other +/// path. +/// +/// \throw utils::fs::join_error If the join operation is invalid because the +/// two paths are incompatible. +fs::path +fs::path::operator/(const fs::path& rest) const +{ + if (rest.is_absolute()) + throw fs::join_error(_repr, rest._repr, + "Cannot concatenate a path to an absolute path"); + return fs::path(_repr + '/' + rest._repr); +} + + +/// Formats a path for insertion on a stream. +/// +/// \param os The output stream. +/// \param p The path to inject to the stream. +/// +/// \return The output stream os. +std::ostream& +fs::operator<<(std::ostream& os, const fs::path& p) +{ + return (os << p.str()); +} diff --git a/external/bsd/kyua-cli/dist/utils/fs/path.hpp b/external/bsd/kyua-cli/dist/utils/fs/path.hpp new file mode 100644 index 000000000..3db4bdfa9 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/fs/path.hpp @@ -0,0 +1,85 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file utils/fs/path.hpp +/// Provides the utils::fs::path class. +/// +/// This is a poor man's reimplementation of the path class provided by +/// Boost.Filesystem, in the sense that it tries to follow the same API but is +/// much simplified. + +#if !defined(UTILS_FS_PATH_HPP) +#define UTILS_FS_PATH_HPP + +#include +#include + +namespace utils { +namespace fs { + + +/// Representation and manipulation of a file system path. +/// +/// Application code should always use this class to represent a path instead of +/// std::string, because this class is more semantically representative, ensures +/// that the values are valid and provides some useful manipulation functions. +/// +/// Conversions to and from strings are always explicit. +class path { + /// Internal representation of the path. + std::string _repr; + +public: + explicit path(const std::string&); + + const char* c_str(void) const; + const std::string& str(void) const; + + path branch_path(void) const; + std::string leaf_name(void) const; + path to_absolute(void) const; + + bool is_absolute(void) const; + bool is_parent_of(path) const; + int ncomponents(void) const; + + bool operator<(const path&) const; + bool operator==(const path&) const; + bool operator!=(const path&) const; + path operator/(const std::string&) const; + path operator/(const path&) const; +}; + + +std::ostream& operator<<(std::ostream&, const path&); + + +} // namespace fs +} // namespace utils + +#endif // !defined(UTILS_FS_PATH_HPP) diff --git a/external/bsd/kyua-cli/dist/utils/fs/path_test.cpp b/external/bsd/kyua-cli/dist/utils/fs/path_test.cpp new file mode 100644 index 000000000..8593fdddf --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/fs/path_test.cpp @@ -0,0 +1,277 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/fs/path.hpp" + +extern "C" { +#include +} + +#include + +#include + +#include "utils/fs/exceptions.hpp" + +using utils::fs::invalid_path_error; +using utils::fs::join_error; +using utils::fs::path; + + +#define REQUIRE_JOIN_ERROR(path1, path2, expr) \ + try { \ + expr; \ + ATF_FAIL("Expecting join_error but no error raised"); \ + } catch (const join_error& e) { \ + ATF_REQUIRE_EQ(path1, e.textual_path1()); \ + ATF_REQUIRE_EQ(path2, e.textual_path2()); \ + } + + +ATF_TEST_CASE_WITHOUT_HEAD(normalize__ok); +ATF_TEST_CASE_BODY(normalize__ok) +{ + ATF_REQUIRE_EQ(".", path(".").str()); + ATF_REQUIRE_EQ("..", path("..").str()); + ATF_REQUIRE_EQ("/", path("/").str()); + ATF_REQUIRE_EQ("/", path("///").str()); + + ATF_REQUIRE_EQ("foo", path("foo").str()); + ATF_REQUIRE_EQ("foo/bar", path("foo/bar").str()); + ATF_REQUIRE_EQ("foo/bar", path("foo/bar/").str()); + + ATF_REQUIRE_EQ("/foo", path("/foo").str()); + ATF_REQUIRE_EQ("/foo/bar", path("/foo/bar").str()); + ATF_REQUIRE_EQ("/foo/bar", path("/foo/bar/").str()); + + ATF_REQUIRE_EQ("/foo", path("///foo").str()); + ATF_REQUIRE_EQ("/foo/bar", path("///foo///bar").str()); + ATF_REQUIRE_EQ("/foo/bar", path("///foo///bar///").str()); + + ATF_REQUIRE_EQ("./foo/bar", path("./foo/bar").str()); + ATF_REQUIRE_EQ("./foo/bar", path("./foo/./bar").str()); + ATF_REQUIRE_EQ("./foo/bar", path("././foo/./bar").str()); + ATF_REQUIRE_EQ("foo/bar", path("foo/././bar").str()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(normalize__invalid); +ATF_TEST_CASE_BODY(normalize__invalid) +{ + try { + path(""); + fail("invalid_path_error not raised"); + } catch (const invalid_path_error& e) { + ATF_REQUIRE(e.invalid_path().empty()); + } +} + + +ATF_TEST_CASE_WITHOUT_HEAD(is_absolute); +ATF_TEST_CASE_BODY(is_absolute) +{ + ATF_REQUIRE( path("/").is_absolute()); + ATF_REQUIRE( path("////").is_absolute()); + ATF_REQUIRE( path("////a").is_absolute()); + ATF_REQUIRE( path("//a//").is_absolute()); + ATF_REQUIRE(!path("a////").is_absolute()); + ATF_REQUIRE(!path("../foo").is_absolute()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(is_parent_of); +ATF_TEST_CASE_BODY(is_parent_of) +{ + ATF_REQUIRE( path("/").is_parent_of(path("/"))); + ATF_REQUIRE( path(".").is_parent_of(path("."))); + ATF_REQUIRE( path("/a").is_parent_of(path("/a"))); + ATF_REQUIRE( path("/a/b/c").is_parent_of(path("/a/b/c"))); + ATF_REQUIRE( path("a").is_parent_of(path("a"))); + ATF_REQUIRE( path("a/b/c").is_parent_of(path("a/b/c"))); + + ATF_REQUIRE( path("/a/b/c").is_parent_of(path("/a/b/c/d"))); + ATF_REQUIRE( path("/a/b/c").is_parent_of(path("/a/b/c/d/e"))); + ATF_REQUIRE(!path("/a/b/c").is_parent_of(path("a/b/c"))); + ATF_REQUIRE(!path("/a/b/c").is_parent_of(path("a/b/c/d/e"))); + + ATF_REQUIRE( path("a/b/c").is_parent_of(path("a/b/c/d"))); + ATF_REQUIRE( path("a/b/c").is_parent_of(path("a/b/c/d/e"))); + ATF_REQUIRE(!path("a/b/c").is_parent_of(path("/a/b/c"))); + ATF_REQUIRE(!path("a/b/c").is_parent_of(path("/a/b/c/d/e"))); + + ATF_REQUIRE(!path("/a/b/c/d/e").is_parent_of(path("/a/b/c"))); + ATF_REQUIRE(!path("/a/b/c/d/e").is_parent_of(path("a/b/c"))); + ATF_REQUIRE(!path("a/b/c/d/e").is_parent_of(path("/a/b/c"))); + ATF_REQUIRE(!path("a/b/c/d/e").is_parent_of(path("a/b/c"))); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(ncomponents); +ATF_TEST_CASE_BODY(ncomponents) +{ + ATF_REQUIRE_EQ(1, path(".").ncomponents()); + ATF_REQUIRE_EQ(1, path("/").ncomponents()); + + ATF_REQUIRE_EQ(1, path("abc").ncomponents()); + ATF_REQUIRE_EQ(1, path("abc/").ncomponents()); + + ATF_REQUIRE_EQ(2, path("/abc").ncomponents()); + ATF_REQUIRE_EQ(3, path("/abc/def").ncomponents()); + + ATF_REQUIRE_EQ(2, path("abc/def").ncomponents()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(branch_path); +ATF_TEST_CASE_BODY(branch_path) +{ + ATF_REQUIRE_EQ(".", path(".").branch_path().str()); + ATF_REQUIRE_EQ(".", path("foo").branch_path().str()); + ATF_REQUIRE_EQ("foo", path("foo/bar").branch_path().str()); + ATF_REQUIRE_EQ("/", path("/foo").branch_path().str()); + ATF_REQUIRE_EQ("/foo", path("/foo/bar").branch_path().str()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(leaf_name); +ATF_TEST_CASE_BODY(leaf_name) +{ + ATF_REQUIRE_EQ(".", path(".").leaf_name()); + ATF_REQUIRE_EQ("foo", path("foo").leaf_name()); + ATF_REQUIRE_EQ("bar", path("foo/bar").leaf_name()); + ATF_REQUIRE_EQ("foo", path("/foo").leaf_name()); + ATF_REQUIRE_EQ("bar", path("/foo/bar").leaf_name()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(to_absolute); +ATF_TEST_CASE_BODY(to_absolute) +{ + ATF_REQUIRE(::chdir("/bin") != -1); + const std::string absolute = path("ls").to_absolute().str(); + // In some systems (e.g. in Fedora 17), /bin is really a symlink to + // /usr/bin. Doing an explicit match of 'absolute' to /bin/ls fails in such + // case. Instead, attempt doing a search in the generated path just for a + // substring containing '/bin/ls'. Note that this can still fail if /bin is + // linked to something arbitrary like /a/b... but let's just assume this + // does not happen. + ATF_REQUIRE(absolute.find("/bin/ls") != std::string::npos); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(compare_less_than); +ATF_TEST_CASE_BODY(compare_less_than) +{ + ATF_REQUIRE(!(path("/") < path("/"))); + ATF_REQUIRE(!(path("/") < path("///"))); + + ATF_REQUIRE(!(path("/a/b/c") < path("/a/b/c"))); + + ATF_REQUIRE( path("/a") < path("/b")); + ATF_REQUIRE(!(path("/b") < path("/a"))); + + ATF_REQUIRE( path("/a") < path("/aa")); + ATF_REQUIRE(!(path("/aa") < path("/a"))); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(compare_equal); +ATF_TEST_CASE_BODY(compare_equal) +{ + ATF_REQUIRE(path("/") == path("///")); + ATF_REQUIRE(path("/a") == path("///a")); + ATF_REQUIRE(path("/a") == path("///a///")); + + ATF_REQUIRE(path("a/b/c") == path("a//b//c")); + ATF_REQUIRE(path("a/b/c") == path("a//b//c///")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(compare_different); +ATF_TEST_CASE_BODY(compare_different) +{ + ATF_REQUIRE(path("/") != path("//a/")); + ATF_REQUIRE(path("/a") != path("a///")); + + ATF_REQUIRE(path("a/b/c") != path("a/b")); + ATF_REQUIRE(path("a/b/c") != path("a//b")); + ATF_REQUIRE(path("a/b/c") != path("/a/b/c")); + ATF_REQUIRE(path("a/b/c") != path("/a//b//c")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(concat__to_string); +ATF_TEST_CASE_BODY(concat__to_string) +{ + ATF_REQUIRE_EQ("foo/bar", (path("foo") / "bar").str()); + ATF_REQUIRE_EQ("foo/bar", (path("foo/") / "bar").str()); + ATF_REQUIRE_EQ("foo/bar/baz", (path("foo/") / "bar//baz///").str()); + + ATF_REQUIRE_THROW(invalid_path_error, path("foo") / ""); + REQUIRE_JOIN_ERROR("foo", "/a/b", path("foo") / "/a/b"); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(concat__to_path); +ATF_TEST_CASE_BODY(concat__to_path) +{ + ATF_REQUIRE_EQ("foo/bar", (path("foo") / "bar").str()); + ATF_REQUIRE_EQ("foo/bar", (path("foo/") / "bar").str()); + ATF_REQUIRE_EQ("foo/bar/baz", (path("foo/") / "bar//baz///").str()); + + REQUIRE_JOIN_ERROR("foo", "/a/b", path("foo") / path("/a/b")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(use_as_key); +ATF_TEST_CASE_BODY(use_as_key) +{ + std::set< path > paths; + paths.insert(path("/a")); + ATF_REQUIRE(paths.find(path("//a")) != paths.end()); + ATF_REQUIRE(paths.find(path("a")) == paths.end()); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, normalize__ok); + ATF_ADD_TEST_CASE(tcs, normalize__invalid); + ATF_ADD_TEST_CASE(tcs, is_absolute); + ATF_ADD_TEST_CASE(tcs, is_parent_of); + ATF_ADD_TEST_CASE(tcs, ncomponents); + ATF_ADD_TEST_CASE(tcs, branch_path); + ATF_ADD_TEST_CASE(tcs, leaf_name); + ATF_ADD_TEST_CASE(tcs, to_absolute); + ATF_ADD_TEST_CASE(tcs, compare_less_than); + ATF_ADD_TEST_CASE(tcs, compare_equal); + ATF_ADD_TEST_CASE(tcs, compare_different); + ATF_ADD_TEST_CASE(tcs, concat__to_string); + ATF_ADD_TEST_CASE(tcs, concat__to_path); + ATF_ADD_TEST_CASE(tcs, use_as_key); +} diff --git a/external/bsd/kyua-cli/dist/utils/logging/Kyuafile b/external/bsd/kyua-cli/dist/utils/logging/Kyuafile new file mode 100644 index 000000000..0853a335c --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/logging/Kyuafile @@ -0,0 +1,6 @@ +syntax(2) + +test_suite("kyua") + +atf_test_program{name="macros_test"} +atf_test_program{name="operations_test"} diff --git a/external/bsd/kyua-cli/dist/utils/logging/macros.hpp b/external/bsd/kyua-cli/dist/utils/logging/macros.hpp new file mode 100644 index 000000000..675d8f22b --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/logging/macros.hpp @@ -0,0 +1,68 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file utils/logging/macros.hpp +/// Convenience macros to simplify usage of the logging library. +/// +/// This file must not be included from other header files. + +#if !defined(UTILS_LOGGING_MACROS_HPP) +#define UTILS_LOGGING_MACROS_HPP + +#include "utils/logging/operations.hpp" + + +/// Logs a debug message. +/// +/// \param message The message to log. +#define LD(message) utils::logging::log(utils::logging::level_debug, \ + __FILE__, __LINE__, message) + + +/// Logs an error message. +/// +/// \param message The message to log. +#define LE(message) utils::logging::log(utils::logging::level_error, \ + __FILE__, __LINE__, message) + + +/// Logs an informational message. +/// +/// \param message The message to log. +#define LI(message) utils::logging::log(utils::logging::level_info, \ + __FILE__, __LINE__, message) + + +/// Logs a warning message. +/// +/// \param message The message to log. +#define LW(message) utils::logging::log(utils::logging::level_warning, \ + __FILE__, __LINE__, message) + + +#endif // !defined(UTILS_LOGGING_MACROS_HPP) diff --git a/external/bsd/kyua-cli/dist/utils/logging/macros_test.cpp b/external/bsd/kyua-cli/dist/utils/logging/macros_test.cpp new file mode 100644 index 000000000..808d5e184 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/logging/macros_test.cpp @@ -0,0 +1,115 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/logging/macros.hpp" + +#include +#include + +#include + +#include "utils/datetime.hpp" +#include "utils/fs/path.hpp" +#include "utils/logging/operations.hpp" + +namespace datetime = utils::datetime; +namespace fs = utils::fs; +namespace logging = utils::logging; + + +ATF_TEST_CASE_WITHOUT_HEAD(ld); +ATF_TEST_CASE_BODY(ld) +{ + logging::set_persistency("debug", fs::path("test.log")); + datetime::set_mock_now(2011, 2, 21, 18, 30, 0, 0); + LD("Debug message"); + + std::ifstream input("test.log"); + ATF_REQUIRE(input); + + std::string line; + ATF_REQUIRE(std::getline(input, line).good()); + ATF_REQUIRE_MATCH("20110221-183000 D .*: Debug message", line); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(le); +ATF_TEST_CASE_BODY(le) +{ + logging::set_persistency("debug", fs::path("test.log")); + datetime::set_mock_now(2011, 2, 21, 18, 30, 0, 0); + LE("Error message"); + + std::ifstream input("test.log"); + ATF_REQUIRE(input); + + std::string line; + ATF_REQUIRE(std::getline(input, line).good()); + ATF_REQUIRE_MATCH("20110221-183000 E .*: Error message", line); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(li); +ATF_TEST_CASE_BODY(li) +{ + logging::set_persistency("debug", fs::path("test.log")); + datetime::set_mock_now(2011, 2, 21, 18, 30, 0, 0); + LI("Info message"); + + std::ifstream input("test.log"); + ATF_REQUIRE(input); + + std::string line; + ATF_REQUIRE(std::getline(input, line).good()); + ATF_REQUIRE_MATCH("20110221-183000 I .*: Info message", line); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(lw); +ATF_TEST_CASE_BODY(lw) +{ + logging::set_persistency("debug", fs::path("test.log")); + datetime::set_mock_now(2011, 2, 21, 18, 30, 0, 0); + LW("Warning message"); + + std::ifstream input("test.log"); + ATF_REQUIRE(input); + + std::string line; + ATF_REQUIRE(std::getline(input, line).good()); + ATF_REQUIRE_MATCH("20110221-183000 W .*: Warning message", line); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, ld); + ATF_ADD_TEST_CASE(tcs, le); + ATF_ADD_TEST_CASE(tcs, li); + ATF_ADD_TEST_CASE(tcs, lw); +} diff --git a/external/bsd/kyua-cli/dist/utils/logging/operations.cpp b/external/bsd/kyua-cli/dist/utils/logging/operations.cpp new file mode 100644 index 000000000..34443ddb1 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/logging/operations.cpp @@ -0,0 +1,243 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/logging/operations.hpp" + +extern "C" { +#include +} + +#include +#include +#include +#include +#include + +#include "utils/datetime.hpp" +#include "utils/format/macros.hpp" +#include "utils/optional.ipp" +#include "utils/sanity.hpp" + +namespace datetime = utils::datetime; +namespace fs = utils::fs; +namespace logging = utils::logging; + +using utils::none; +using utils::optional; + + +/// The general idea for the application-wide logging goes like this: +/// +/// 1. The application starts. Logging is initialized to capture _all_ log +/// messages into memory regardless of their level by issuing a call to the +/// set_inmemory() function. +/// +/// 2. The application offers the user a way to select the logging level and a +/// file into which to store the log. +/// +/// 3. The application calls set_persistency providing a new log level and a log +/// file. This must be done as early as possible, to minimize the chances of an +/// early crash not capturing any logs. +/// +/// 4. At this point, any log messages stored into memory are flushed to disk +/// respecting the provided log level. +/// +/// 5. The internal state of the logging module is updated to only capture +/// messages that are of the provided log level (or below) and is configured to +/// directly send messages to disk. +/// +/// The call to set_inmemory() should only be performed by the user-facing +/// application. Tests should skip this call so that the logging messages go to +/// stderr by default, thus generating a useful log to debug the tests. + + +namespace { + + +/// Current log level. +static logging::level log_level = logging::level_debug; + + +/// Indicates whether set_persistency() will be called automatically or not. +static bool auto_set_persistency = true; + + +/// First time recorded by the logging module. +static optional< datetime::timestamp > first_timestamp = none; + + +/// In-memory record of log entries before persistency is enabled. +static std::vector< std::pair< logging::level, std::string > > backlog; + + +/// Stream to the currently open log file. +static std::auto_ptr< std::ofstream > logfile; + + +/// Constant string to strftime to format timestamps. +static const char* timestamp_format = "%Y%m%d-%H%M%S"; + + +/// Converts a level to a printable character. +/// +/// \param level The level to convert. +/// +/// \return The printable character, to be used in log messages. +static char +level_to_char(const logging::level level) +{ + switch (level) { + case logging::level_error: return 'E'; + case logging::level_warning: return 'W'; + case logging::level_info: return 'I'; + case logging::level_debug: return 'D'; + default: UNREACHABLE; + } +} + + +} // anonymous namespace + + +/// Generates a standard log name. +/// +/// This always adds the same timestamp to the log name for a particular run. +/// Also, the timestamp added to the file name corresponds to the first +/// timestamp recorded by the module; it does not necessarily contain the +/// current value of "now". +/// +/// \param logdir The path to the directory in which to place the log. +/// \param progname The name of the program that is generating the log. +fs::path +logging::generate_log_name(const fs::path& logdir, const std::string& progname) +{ + if (!first_timestamp) + first_timestamp = datetime::timestamp::now(); + // Update doc/troubleshooting.texi if you change the name format. + return logdir / (F("%s.%s.log") % progname % + first_timestamp.get().strftime(timestamp_format)); +} + + +/// Logs an entry to the log file. +/// +/// If the log is not yet set to persistent mode, the entry is recorded in the +/// in-memory backlog. Otherwise, it is just written to disk. +/// +/// \param message_level The level of the entry. +/// \param file The file from which the log message is generated. +/// \param line The line from which the log message is generated. +/// \param user_message The raw message to store. +void +logging::log(const level message_level, const char* file, const int line, + const std::string& user_message) +{ + const datetime::timestamp now = datetime::timestamp::now(); + if (!first_timestamp) + first_timestamp = now; + + if (auto_set_persistency) { + // These values are hardcoded here for testing purposes. The + // application should call set_inmemory() by itself during + // initialization to avoid this, so that it has explicit control on how + // the call to set_persistency() happens. + set_persistency("debug", fs::path("/dev/stderr")); + auto_set_persistency = false; + } + + if (message_level > log_level) + return; + + // Update doc/troubleshooting.texi if you change the log format. + const std::string message = F("%s %s %s %s:%s: %s") % + now.strftime(timestamp_format) % level_to_char(message_level) % + ::getpid() % file % line % user_message; + if (logfile.get() == NULL) + backlog.push_back(std::make_pair(message_level, message)); + else { + INV(backlog.empty()); + (*logfile) << message << '\n'; + (*logfile).flush(); + } +} + + +/// Sets the logging to record messages in memory for later flushing. +void +logging::set_inmemory(void) +{ + auto_set_persistency = false; +} + + +/// Makes the log persistent. +/// +/// Calling this function flushes the in-memory log, if any, to disk and sets +/// the logging module to send log entries to disk from this point onwards. +/// There is no way back, and the caller program should execute this function as +/// early as possible to ensure that a crash at startup does not discard too +/// many useful log entries. +/// +/// Any log entries above the provided new_level are discarded. +/// +/// \param new_level The new log level. +/// \param path The file to write the logs to. +/// +/// \throw std::range_error If the given log level is invalid. +/// \throw std::runtime_error If the given file cannot be created. +void +logging::set_persistency(const std::string& new_level, const fs::path& path) +{ + auto_set_persistency = false; + + PRE(logfile.get() == NULL); + + // Update doc/troubleshooting.info if you change the log levels. + if (new_level == "debug") + log_level = level_debug; + else if (new_level == "error") + log_level = level_error; + else if (new_level == "info") + log_level = level_info; + else if (new_level == "warning") + log_level = level_warning; + else + throw std::range_error(F("Unrecognized log level '%s'") % new_level); + + logfile.reset(new std::ofstream(path.c_str())); + if (!(*logfile)) + throw std::runtime_error(F("Failed to create log file %s") % path); + + for (std::vector< std::pair< logging::level, std::string > >::const_iterator + iter = backlog.begin(); iter != backlog.end(); iter++) { + if ((*iter).first <= log_level) + (*logfile) << (*iter).second << '\n'; + } + (*logfile).flush(); + backlog.clear(); +} diff --git a/external/bsd/kyua-cli/dist/utils/logging/operations.hpp b/external/bsd/kyua-cli/dist/utils/logging/operations.hpp new file mode 100644 index 000000000..bd4770bed --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/logging/operations.hpp @@ -0,0 +1,64 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file utils/logging/operations.hpp +/// Stateless logging facilities. + +#if !defined(UTILS_LOGGING_OPERATIONS_HPP) +#define UTILS_LOGGING_OPERATIONS_HPP + +#include + +#include "utils/fs/path.hpp" + +namespace utils { +namespace logging { + + +/// Severity levels for log messages. +/// +/// This enumeration must be sorted from the most severe message to the least +/// severe. +enum level { + level_error = 0, + level_warning, + level_info, + level_debug, +}; + + +fs::path generate_log_name(const fs::path&, const std::string&); +void log(const level, const char*, const int, const std::string&); +void set_inmemory(void); +void set_persistency(const std::string&, const fs::path&); + + +} // namespace logging +} // namespace utils + +#endif // !defined(UTILS_LOGGING_OPERATIONS_HPP) diff --git a/external/bsd/kyua-cli/dist/utils/logging/operations_test.cpp b/external/bsd/kyua-cli/dist/utils/logging/operations_test.cpp new file mode 100644 index 000000000..2456ff56a --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/logging/operations_test.cpp @@ -0,0 +1,330 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/logging/operations.hpp" + +extern "C" { +#include +} + +#include +#include + +#include + +#include "utils/datetime.hpp" +#include "utils/format/macros.hpp" +#include "utils/fs/operations.hpp" +#include "utils/fs/path.hpp" + +namespace datetime = utils::datetime; +namespace fs = utils::fs; +namespace logging = utils::logging; + + +ATF_TEST_CASE_WITHOUT_HEAD(generate_log_name__before_log); +ATF_TEST_CASE_BODY(generate_log_name__before_log) +{ + datetime::set_mock_now(2011, 2, 21, 18, 10, 0, 0); + ATF_REQUIRE_EQ(fs::path("/some/dir/foobar.20110221-181000.log"), + logging::generate_log_name(fs::path("/some/dir"), "foobar")); + + datetime::set_mock_now(2011, 2, 21, 18, 10, 1, 987654); + logging::log(logging::level_info, "file", 123, "A message"); + + datetime::set_mock_now(2011, 2, 21, 18, 10, 2, 123); + ATF_REQUIRE_EQ(fs::path("/some/dir/foobar.20110221-181000.log"), + logging::generate_log_name(fs::path("/some/dir"), "foobar")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(generate_log_name__after_log); +ATF_TEST_CASE_BODY(generate_log_name__after_log) +{ + datetime::set_mock_now(2011, 2, 21, 18, 15, 0, 0); + logging::log(logging::level_info, "file", 123, "A message"); + datetime::set_mock_now(2011, 2, 21, 18, 15, 1, 987654); + logging::log(logging::level_info, "file", 123, "A message"); + + datetime::set_mock_now(2011, 2, 21, 18, 15, 2, 123); + ATF_REQUIRE_EQ(fs::path("/some/dir/foobar.20110221-181500.log"), + logging::generate_log_name(fs::path("/some/dir"), "foobar")); + + datetime::set_mock_now(2011, 2, 21, 18, 15, 3, 1); + logging::log(logging::level_info, "file", 123, "A message"); + + datetime::set_mock_now(2011, 2, 21, 18, 15, 4, 91); + ATF_REQUIRE_EQ(fs::path("/some/dir/foobar.20110221-181500.log"), + logging::generate_log_name(fs::path("/some/dir"), "foobar")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(log); +ATF_TEST_CASE_BODY(log) +{ + logging::set_inmemory(); + + datetime::set_mock_now(2011, 2, 21, 18, 10, 0, 0); + logging::log(logging::level_debug, "f1", 1, "Debug message"); + + datetime::set_mock_now(2011, 2, 21, 18, 10, 1, 987654); + logging::log(logging::level_error, "f2", 2, "Error message"); + + logging::set_persistency("debug", fs::path("test.log")); + + datetime::set_mock_now(2011, 2, 21, 18, 10, 2, 123); + logging::log(logging::level_info, "f3", 3, "Info message"); + + datetime::set_mock_now(2011, 2, 21, 18, 10, 3, 456); + logging::log(logging::level_warning, "f4", 4, "Warning message"); + + std::ifstream input("test.log"); + ATF_REQUIRE(input); + + const pid_t pid = ::getpid(); + + std::string line; + ATF_REQUIRE(std::getline(input, line).good()); + ATF_REQUIRE_EQ( + (F("20110221-181000 D %s f1:1: Debug message") % pid).str(), line); + ATF_REQUIRE(std::getline(input, line).good()); + ATF_REQUIRE_EQ( + (F("20110221-181001 E %s f2:2: Error message") % pid).str(), line); + ATF_REQUIRE(std::getline(input, line).good()); + ATF_REQUIRE_EQ( + (F("20110221-181002 I %s f3:3: Info message") % pid).str(), line); + ATF_REQUIRE(std::getline(input, line).good()); + ATF_REQUIRE_EQ( + (F("20110221-181003 W %s f4:4: Warning message") % pid).str(), line); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(set_persistency__no_backlog); +ATF_TEST_CASE_BODY(set_persistency__no_backlog) +{ + logging::set_persistency("debug", fs::path("test.log")); + + datetime::set_mock_now(2011, 2, 21, 18, 20, 0, 654321); + logging::log(logging::level_debug, "file", 123, "Debug message"); + + std::ifstream input("test.log"); + ATF_REQUIRE(input); + + const pid_t pid = ::getpid(); + + std::string line; + ATF_REQUIRE(std::getline(input, line).good()); + ATF_REQUIRE_EQ( + (F("20110221-182000 D %s file:123: Debug message") % pid).str(), line); +} + + +/// Creates a log for testing purposes, buffering messages on start. +/// +/// \param level The level of the desired log. +/// \param path The output file. +static void +create_log(const std::string& level, const std::string& path) +{ + logging::set_inmemory(); + + datetime::set_mock_now(2011, 3, 19, 11, 40, 0, 100); + logging::log(logging::level_debug, "file1", 11, "Debug 1"); + + datetime::set_mock_now(2011, 3, 19, 11, 40, 1, 200); + logging::log(logging::level_error, "file2", 22, "Error 1"); + + datetime::set_mock_now(2011, 3, 19, 11, 40, 2, 300); + logging::log(logging::level_info, "file3", 33, "Info 1"); + + datetime::set_mock_now(2011, 3, 19, 11, 40, 3, 400); + logging::log(logging::level_warning, "file4", 44, "Warning 1"); + + logging::set_persistency(level, fs::path(path)); + + datetime::set_mock_now(2011, 3, 19, 11, 40, 4, 500); + logging::log(logging::level_debug, "file1", 11, "Debug 2"); + + datetime::set_mock_now(2011, 3, 19, 11, 40, 5, 600); + logging::log(logging::level_error, "file2", 22, "Error 2"); + + datetime::set_mock_now(2011, 3, 19, 11, 40, 6, 700); + logging::log(logging::level_info, "file3", 33, "Info 2"); + + datetime::set_mock_now(2011, 3, 19, 11, 40, 7, 800); + logging::log(logging::level_warning, "file4", 44, "Warning 2"); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(set_persistency__some_backlog__debug); +ATF_TEST_CASE_BODY(set_persistency__some_backlog__debug) +{ + create_log("debug", "test.log"); + + std::ifstream input("test.log"); + ATF_REQUIRE(input); + + const pid_t pid = ::getpid(); + + std::string line; + ATF_REQUIRE(std::getline(input, line).good()); + ATF_REQUIRE_EQ( + (F("20110319-114000 D %s file1:11: Debug 1") % pid).str(), line); + ATF_REQUIRE(std::getline(input, line).good()); + ATF_REQUIRE_EQ( + (F("20110319-114001 E %s file2:22: Error 1") % pid).str(), line); + ATF_REQUIRE(std::getline(input, line).good()); + ATF_REQUIRE_EQ( + (F("20110319-114002 I %s file3:33: Info 1") % pid).str(), line); + ATF_REQUIRE(std::getline(input, line).good()); + ATF_REQUIRE_EQ( + (F("20110319-114003 W %s file4:44: Warning 1") % pid).str(), line); + ATF_REQUIRE(std::getline(input, line).good()); + ATF_REQUIRE_EQ( + (F("20110319-114004 D %s file1:11: Debug 2") % pid).str(), line); + ATF_REQUIRE(std::getline(input, line).good()); + ATF_REQUIRE_EQ( + (F("20110319-114005 E %s file2:22: Error 2") % pid).str(), line); + ATF_REQUIRE(std::getline(input, line).good()); + ATF_REQUIRE_EQ( + (F("20110319-114006 I %s file3:33: Info 2") % pid).str(), line); + ATF_REQUIRE(std::getline(input, line).good()); + ATF_REQUIRE_EQ( + (F("20110319-114007 W %s file4:44: Warning 2") % pid).str(), line); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(set_persistency__some_backlog__error); +ATF_TEST_CASE_BODY(set_persistency__some_backlog__error) +{ + create_log("error", "test.log"); + + std::ifstream input("test.log"); + ATF_REQUIRE(input); + + const pid_t pid = ::getpid(); + + std::string line; + ATF_REQUIRE(std::getline(input, line).good()); + ATF_REQUIRE_EQ( + (F("20110319-114001 E %s file2:22: Error 1") % pid).str(), line); + ATF_REQUIRE(std::getline(input, line).good()); + ATF_REQUIRE_EQ( + (F("20110319-114005 E %s file2:22: Error 2") % pid).str(), line); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(set_persistency__some_backlog__info); +ATF_TEST_CASE_BODY(set_persistency__some_backlog__info) +{ + create_log("info", "test.log"); + + std::ifstream input("test.log"); + ATF_REQUIRE(input); + + const pid_t pid = ::getpid(); + + std::string line; + ATF_REQUIRE(std::getline(input, line).good()); + ATF_REQUIRE_EQ( + (F("20110319-114001 E %s file2:22: Error 1") % pid).str(), line); + ATF_REQUIRE(std::getline(input, line).good()); + ATF_REQUIRE_EQ( + (F("20110319-114002 I %s file3:33: Info 1") % pid).str(), line); + ATF_REQUIRE(std::getline(input, line).good()); + ATF_REQUIRE_EQ( + (F("20110319-114003 W %s file4:44: Warning 1") % pid).str(), line); + ATF_REQUIRE(std::getline(input, line).good()); + ATF_REQUIRE_EQ( + (F("20110319-114005 E %s file2:22: Error 2") % pid).str(), line); + ATF_REQUIRE(std::getline(input, line).good()); + ATF_REQUIRE_EQ( + (F("20110319-114006 I %s file3:33: Info 2") % pid).str(), line); + ATF_REQUIRE(std::getline(input, line).good()); + ATF_REQUIRE_EQ( + (F("20110319-114007 W %s file4:44: Warning 2") % pid).str(), line); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(set_persistency__some_backlog__warning); +ATF_TEST_CASE_BODY(set_persistency__some_backlog__warning) +{ + create_log("warning", "test.log"); + + std::ifstream input("test.log"); + ATF_REQUIRE(input); + + const pid_t pid = ::getpid(); + + std::string line; + ATF_REQUIRE(std::getline(input, line).good()); + ATF_REQUIRE_EQ( + (F("20110319-114001 E %s file2:22: Error 1") % pid).str(), line); + ATF_REQUIRE(std::getline(input, line).good()); + ATF_REQUIRE_EQ( + (F("20110319-114003 W %s file4:44: Warning 1") % pid).str(), line); + ATF_REQUIRE(std::getline(input, line).good()); + ATF_REQUIRE_EQ( + (F("20110319-114005 E %s file2:22: Error 2") % pid).str(), line); + ATF_REQUIRE(std::getline(input, line).good()); + ATF_REQUIRE_EQ( + (F("20110319-114007 W %s file4:44: Warning 2") % pid).str(), line); +} + + +ATF_TEST_CASE(set_persistency__fail); +ATF_TEST_CASE_HEAD(set_persistency__fail) +{ + set_md_var("require.user", "unprivileged"); +} +ATF_TEST_CASE_BODY(set_persistency__fail) +{ + ATF_REQUIRE_THROW_RE(std::range_error, "'foobar'", + logging::set_persistency("foobar", fs::path("log"))); + + fs::mkdir(fs::path("dir"), 0644); + ATF_REQUIRE_THROW_RE(std::runtime_error, "dir/fail.log", + logging::set_persistency("debug", + fs::path("dir/fail.log"))); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, generate_log_name__before_log); + ATF_ADD_TEST_CASE(tcs, generate_log_name__after_log); + + ATF_ADD_TEST_CASE(tcs, log); + + ATF_ADD_TEST_CASE(tcs, set_persistency__no_backlog); + ATF_ADD_TEST_CASE(tcs, set_persistency__some_backlog__debug); + ATF_ADD_TEST_CASE(tcs, set_persistency__some_backlog__error); + ATF_ADD_TEST_CASE(tcs, set_persistency__some_backlog__info); + ATF_ADD_TEST_CASE(tcs, set_persistency__some_backlog__warning); + ATF_ADD_TEST_CASE(tcs, set_persistency__fail); +} diff --git a/external/bsd/kyua-cli/dist/utils/memory.cpp b/external/bsd/kyua-cli/dist/utils/memory.cpp new file mode 100644 index 000000000..d580384b1 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/memory.cpp @@ -0,0 +1,164 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/memory.hpp" + +#if defined(HAVE_CONFIG_H) +# include "config.h" +#endif + +extern "C" { +#if defined(HAVE_SYS_TYPES_H) +# include +#endif +#if defined(HAVE_SYS_PARAM_H) +# include +#endif +#if defined(HAVE_SYS_SYSCTL_H) +# include +#endif +} + +#include +#include +#include +#include + +#include "utils/defs.hpp" +#include "utils/format/macros.hpp" +#include "utils/logging/macros.hpp" +#include "utils/units.hpp" +#include "utils/sanity.hpp" + +namespace units = utils::units; + + +namespace { + + +/// Name of the method to query the available memory as detected by configure. +static const char* query_type = MEMORY_QUERY_TYPE; + + +/// Value of query_type when we do not know how to query the memory. +static const char* query_type_unknown = "unknown"; + + +/// Value of query_type when we have to use sysctlbyname(3). +static const char* query_type_sysctlbyname = "sysctlbyname"; + + +/// Name of the sysctl MIB with the physical memory as detected by configure. +/// +/// This should only be used if memory_query_type is 'sysctl'. +static const char* query_sysctl_mib = MEMORY_QUERY_SYSCTL_MIB; + + +#if !defined(HAVE_SYSCTLBYNAME) +/// Stub for sysctlbyname(3) for systems that don't have it. +/// +/// The whole purpose of this fake function is to allow the caller code to be +/// compiled on any machine regardless of the presence of sysctlbyname(3). This +/// will prevent the code from breaking when it is compiled on a machine without +/// this function. It also prevents "unused variable" warnings in the caller +/// code. +/// +/// \param unused_name Unused. +/// \param unused_oldp Unused. +/// \param unused_oldlenp Unused. +/// \param unused_newp Unused. +/// \param unused_newlen Unused. +/// +/// \return Nothing; this always crashes. +static int +sysctlbyname(const char* UTILS_UNUSED_PARAM(name), + void* UTILS_UNUSED_PARAM(oldp), + std::size_t* UTILS_UNUSED_PARAM(oldlenp), + const void* UTILS_UNUSED_PARAM(newp), + std::size_t UTILS_UNUSED_PARAM(newlen)) +{ + UNREACHABLE; +} +#endif + + +} // anonymous namespace + + +/// Gets the value of an integral sysctl MIB. +/// +/// \pre The system supports the sysctlbyname(3) function. +/// +/// \param mib The name of the sysctl MIB to query. +/// +/// \return The value of the MIB, if found. +/// +/// \throw std::runtime_error If the sysctlbyname(3) call fails. This might be +/// a bit drastic. If it turns out that this causes problems, we could just +/// change the code to log the error instead of raising an exception. +static int64_t +query_sysctl(const char* mib) +{ + // This must be explicitly initialized to 0. If the sysctl query returned a + // value smaller in size than value_length, we would get garbage otherwise. + int64_t value = 0; + std::size_t value_length = sizeof(value); + if (::sysctlbyname(mib, &value, &value_length, NULL, 0) == -1) { + const int original_errno = errno; + throw std::runtime_error(F("Failed to get sysctl(%s) value: %s") % + mib % std::strerror(original_errno)); + } + return value; +} + + +/// Queries the total amount of physical memory. +/// +/// The real query is run only once and the result is cached. Further calls to +/// this function will always return the same value. +/// +/// \return The amount of physical memory, in bytes. If the code does not know +/// how to query the memory, this logs a warning and returns 0. +units::bytes +utils::physical_memory(void) +{ + static int64_t amount = -1; + if (amount == -1) { + if (std::strcmp(query_type, query_type_unknown) == 0) { + LW("Don't know how to query the physical memory"); + amount = 0; + } else if (std::strcmp(query_type, query_type_sysctlbyname) == 0) { + amount = query_sysctl(query_sysctl_mib); + } else + UNREACHABLE_MSG("Unimplemented memory query type"); + LI(F("Physical memory as returned by query type '%s': %s") % + query_type % amount); + } + POST(amount > -1); + return units::bytes(amount); +} diff --git a/external/bsd/kyua-cli/dist/utils/memory.hpp b/external/bsd/kyua-cli/dist/utils/memory.hpp new file mode 100644 index 000000000..289735e69 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/memory.hpp @@ -0,0 +1,45 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file utils/memory.hpp +/// Utilities to query details of the system memory. + +#if !defined(UTILS_MEMORY_HPP) +#define UTILS_MEMORY_HPP + +#include "utils/units.hpp" + +namespace utils { + + +units::bytes physical_memory(void); + + +} // namespace utils + +#endif // !defined(UTILS_MEMORY_HPP) diff --git a/external/bsd/kyua-cli/dist/utils/memory_test.cpp b/external/bsd/kyua-cli/dist/utils/memory_test.cpp new file mode 100644 index 000000000..c5a718f61 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/memory_test.cpp @@ -0,0 +1,63 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#if defined(HAVE_CONFIG_H) +# include "config.h" +#endif + +#include "utils/memory.hpp" + +#include + +#include + +#include "utils/units.hpp" + +namespace units = utils::units; + + +ATF_TEST_CASE_WITHOUT_HEAD(physical_memory); +ATF_TEST_CASE_BODY(physical_memory) +{ + const units::bytes memory = utils::physical_memory(); + + if (std::strcmp(MEMORY_QUERY_TYPE, "unknown") == 0) { + ATF_REQUIRE(memory == 0); + } else if (std::strcmp(MEMORY_QUERY_TYPE, "sysctlbyname") == 0) { + ATF_REQUIRE(memory > 0); + ATF_REQUIRE(memory < 100 * units::TB); // Large enough for now... + } else { + fail("Unimplemented memory query type"); + } +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, physical_memory); +} diff --git a/external/bsd/kyua-cli/dist/utils/noncopyable.hpp b/external/bsd/kyua-cli/dist/utils/noncopyable.hpp new file mode 100644 index 000000000..7a934d220 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/noncopyable.hpp @@ -0,0 +1,73 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file utils/noncopyable.hpp +/// Provides the utils::noncopyable class. +/// +/// The class is provided as a separate module on its own to minimize +/// header-inclusion side-effects. + +#if !defined(UTILS_NONCOPYABLE_HPP) +#define UTILS_NONCOPYABLE_HPP + + +namespace utils { + + +/// Forbids copying a class at compile-time. +/// +/// Inheriting from this class delivers a private copy constructor and an +/// assignment operator that effectively forbid copying the class during +/// compilation. +/// +/// Always use private inheritance. +class noncopyable { + /// Data placeholder. + /// + /// The class cannot be empty; otherwise we get ABI-stability warnings + /// during the build, which will break it due to strict checking. + int _noncopyable_dummy; + + /// Private copy constructor to deny copying of subclasses. + noncopyable(const noncopyable&); + + /// Private assignment constructor to deny copying of subclasses. + noncopyable& operator=(const noncopyable&); + +protected: + // Explicitly needed to provide some non-private functions. Otherwise + // we also get some warnings during the build. + noncopyable(void) {} + ~noncopyable(void) {} +}; + + +} // namespace utils + + +#endif // !defined(UTILS_NONCOPYABLE_HPP) diff --git a/external/bsd/kyua-cli/dist/utils/optional.hpp b/external/bsd/kyua-cli/dist/utils/optional.hpp new file mode 100644 index 000000000..34bcad6ab --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/optional.hpp @@ -0,0 +1,108 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file utils/optional.hpp +/// Provides the utils::optional class. +/// +/// The class is provided as a separate module on its own to minimize +/// header-inclusion side-effects. + +#if !defined(UTILS_OPTIONAL_HPP) +#define UTILS_OPTIONAL_HPP + +#include + + +namespace utils { + + +namespace detail { + + +/// Internal type-safe representation for the none type. +struct none_t {}; + + +} // namespace detail + + +/// The none value. +/// +/// This has internal linkage so it is OK to define it in the header file. +/// However, pointers to none from different translation units will be +/// different. Just don't do that. +const detail::none_t none = {}; + + +/// Holds a data value or none. +/// +/// This class allows users to represent values that may be uninitialized. +/// Instead of having to keep separate variables to track whether a variable is +/// supposed to have a value or not, this class allows multiplexing the +/// behaviors. +/// +/// This class is a simplified version of Boost.Optional. +template< class T > +class optional { + /// Internal representation of the optional data value. + T* _data; + +public: + optional(void); + optional(utils::detail::none_t); + optional(const optional< T >&); + explicit optional(const T&); + ~optional(void); + + optional& operator=(utils::detail::none_t); + optional& operator=(const T&); + optional& operator=(const optional< T >&); + + bool operator==(const optional< T >&) const; + bool operator!=(const optional< T >&) const; + + operator bool(void) const; + + const T& get(void) const; + const T& get_default(const T&) const; + T& get(void); +}; + + +template< class T > +std::ostream& operator<<(std::ostream&, const optional< T >&); + + +template< class T > +optional< T > make_optional(const T&); + + +} // namespace utils + + +#endif // !defined(UTILS_OPTIONAL_HPP) diff --git a/external/bsd/kyua-cli/dist/utils/optional.ipp b/external/bsd/kyua-cli/dist/utils/optional.ipp new file mode 100644 index 000000000..50a45ac32 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/optional.ipp @@ -0,0 +1,257 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#if !defined(UTILS_OPTIONAL_IPP) +#define UTILS_OPTIONAL_IPP + +#include + +#include "utils/defs.hpp" +#include "utils/optional.hpp" +#include "utils/sanity.hpp" + + +/// Initializes an optional object to the none value. +template< class T > +utils::optional< T >::optional(void) : + _data(NULL) +{ +} + + +/// Explicitly initializes an optional object to the none value. +/// +/// \param unused_none A copy of the utils::none instance. +template< class T > +utils::optional< T >::optional( + utils::detail::none_t UTILS_UNUSED_PARAM(none)) : + _data(NULL) +{ +} + + +/// Initializes an optional object to a non-none value. +/// +/// \param data The initial value for the object. +template< class T > +utils::optional< T >::optional(const T& data) : + _data(new T(data)) +{ +} + + +/// Copy constructor. +/// +/// \param other The optional object to copy from. +template< class T > +utils::optional< T >::optional(const optional< T >& other) : + _data(other._data == NULL ? NULL : new T(*(other._data))) +{ +} + + +/// Destructor. +template< class T > +utils::optional< T >::~optional(void) +{ + if (_data != NULL) + delete _data; + _data = NULL; // Prevent accidental reuse. +} + + +/// Explicitly assigns an optional object to the none value. +/// +/// \param unused_none A copy of the utils::none instance. +/// +/// \return A reference to this. +template< class T > +utils::optional< T >& +utils::optional< T >::operator=(utils::detail::none_t UTILS_UNUSED_PARAM(none)) +{ + if (_data != NULL) + delete _data; + _data = NULL; + return *this; +} + + +/// Assigns a new value to the optional object. +/// +/// \param data The initial value for the object. +/// +/// \return A reference to this. +template< class T > +utils::optional< T >& +utils::optional< T >::operator=(const T& data) +{ + T* new_data = new T(data); + if (_data != NULL) + delete _data; + _data = new_data; + return *this; +} + + +/// Copies an optional value. +/// +/// \param other The optional object to copy from. +/// +/// \return A reference to this. +template< class T > +utils::optional< T >& +utils::optional< T >::operator=(const optional< T >& other) +{ + T* new_data = other._data == NULL ? NULL : new T(*(other._data)); + if (_data != NULL) + delete _data; + _data = new_data; + return *this; +} + + +/// Equality comparator. +/// +/// \param other The other object to compare this one to. +/// +/// \return True if this object and other are equal; false otherwise. +template< class T > +bool +utils::optional< T >::operator==(const optional< T >& other) const +{ + if (_data == NULL && other._data == NULL) { + return true; + } else if (_data == NULL || other._data == NULL) { + return false; + } else { + INV(_data != NULL && other._data != NULL); + return *_data == *other._data; + } +} + + +/// Inequality comparator. +/// +/// \param other The other object to compare this one to. +/// +/// \return True if this object and other are different; false otherwise. +template< class T > +bool +utils::optional< T >::operator!=(const optional< T >& other) const +{ + return !(*this == other); +} + + +/// Gets the value hold by the optional object. +/// +/// \pre The optional object must not be none. +/// +/// \return A reference to the data. +template< class T > +const T& +utils::optional< T >::get(void) const +{ + PRE(_data != NULL); + return *_data; +} + + +/// Gets the value of this object with a default fallback. +/// +/// \param default_value The value to return if this object holds no value. +/// +/// \return A reference to the data in the optional object, or the reference +/// passed in as a parameter. +template< class T > +const T& +utils::optional< T >::get_default(const T& default_value) const +{ + if (_data != NULL) + return *_data; + else + return default_value; +} + + +/// Tests whether the optional object contains data or not. +/// +/// \return True if the object is not none; false otherwise. +template< class T > +utils::optional< T >::operator bool(void) const +{ + return _data != NULL; +} + + +/// Tests whether the optional object contains data or not. +/// +/// \return True if the object is not none; false otherwise. +template< class T > +T& +utils::optional< T >::get(void) +{ + PRE(_data != NULL); + return *_data; +} + + +/// Injects the object into a stream. +/// +/// \param output The stream into which to inject the object. +/// \param object The object to format. +/// +/// \return The output stream. +template< class T > +std::ostream& utils::operator<<(std::ostream& output, + const optional< T >& object) +{ + if (!object) { + output << "none"; + } else { + output << object.get(); + } + return output; +} + + +/// Helper function to instantiate optional objects. +/// +/// \param value The value for the optional object. Shouldn't be none, as +/// optional objects can be constructed from none right away. +/// +/// \return A new optional object. +template< class T > +utils::optional< T > +utils::make_optional(const T& value) +{ + return optional< T >(value); +} + + +#endif // !defined(UTILS_OPTIONAL_IPP) diff --git a/external/bsd/kyua-cli/dist/utils/optional_test.cpp b/external/bsd/kyua-cli/dist/utils/optional_test.cpp new file mode 100644 index 000000000..216ad09be --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/optional_test.cpp @@ -0,0 +1,285 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/optional.ipp" + +#include +#include + +#include + +using utils::none; +using utils::optional; + + +namespace { + + +/// Fake class to capture calls to the new and delete operators. +class test_alloc { +public: + /// Value to disambiguate objects after construction. + int value; + + /// Balance of alive instances of this class in dynamic memory. + static size_t instances; + + /// Constructs a new optional object. + /// + /// \param value_ The value to store in this object for disambiguation. + test_alloc(int value_) : value(value_) + { + } + + /// Allocates a new object and records its existence. + /// + /// \param size The amount of memory to allocate. + /// + /// \return A pointer to the allocated memory. + /// + /// \throw std::bad_alloc If the memory allocation fails. + void* + operator new(size_t size) + { + instances++; + std::cout << "test_alloc::operator new called\n"; + return ::operator new(size); + } + + /// Deallocates an existing object and unrecords its existence. + /// + /// \param mem The pointer to the memory to deallocate. + void + operator delete(void* mem) + { + instances--; + std::cout << "test_alloc::operator delete called\n"; + ::operator delete(mem); + } +}; + + +size_t test_alloc::instances = 0; + + +/// Constructs and returns an optional object. +/// +/// This is used by tests to validate that returning an object from within a +/// function works (i.e. the necessary constructors are available). +/// +/// \tparam Type The type of the object included in the optional wrapper. +/// \param value The value to put inside the optional wrapper. +/// +/// \return The constructed optional object. +template< typename Type > +optional< Type > +return_optional(const Type& value) +{ + return optional< Type >(value); +} + + +} // anonymous namespace + + +ATF_TEST_CASE_WITHOUT_HEAD(ctors__native_type); +ATF_TEST_CASE_BODY(ctors__native_type) +{ + const optional< int > no_args; + ATF_REQUIRE(!no_args); + + const optional< int > with_none(none); + ATF_REQUIRE(!with_none); + + const optional< int > with_arg(3); + ATF_REQUIRE(with_arg); + ATF_REQUIRE_EQ(3, with_arg.get()); + + const optional< int > copy_none(with_none); + ATF_REQUIRE(!copy_none); + + const optional< int > copy_arg(with_arg); + ATF_REQUIRE(copy_arg); + ATF_REQUIRE_EQ(3, copy_arg.get()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(ctors__complex_type); +ATF_TEST_CASE_BODY(ctors__complex_type) +{ + const optional< std::string > no_args; + ATF_REQUIRE(!no_args); + + const optional< std::string > with_none(none); + ATF_REQUIRE(!with_none); + + const optional< std::string > with_arg("foo"); + ATF_REQUIRE(with_arg); + ATF_REQUIRE_EQ("foo", with_arg.get()); + + const optional< std::string > copy_none(with_none); + ATF_REQUIRE(!copy_none); + + const optional< std::string > copy_arg(with_arg); + ATF_REQUIRE(copy_arg); + ATF_REQUIRE_EQ("foo", copy_arg.get()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(assign); +ATF_TEST_CASE_BODY(assign) +{ + optional< int > from_default; + from_default = optional< int >(); + ATF_REQUIRE(!from_default); + + optional< int > from_none(3); + from_none = none; + ATF_REQUIRE(!from_none); + + optional< int > from_int; + from_int = 6; + ATF_REQUIRE_EQ(6, from_int.get()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(return); +ATF_TEST_CASE_BODY(return) +{ + optional< long > from_return(return_optional< long >(123)); + ATF_REQUIRE(from_return); + ATF_REQUIRE_EQ(123, from_return.get()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(memory); +ATF_TEST_CASE_BODY(memory) +{ + ATF_REQUIRE_EQ(0, test_alloc::instances); + { + optional< test_alloc > optional1(test_alloc(3)); + ATF_REQUIRE_EQ(1, test_alloc::instances); + ATF_REQUIRE_EQ(3, optional1.get().value); + + { + optional< test_alloc > optional2(optional1); + ATF_REQUIRE_EQ(2, test_alloc::instances); + ATF_REQUIRE_EQ(3, optional2.get().value); + + optional2 = 5; + ATF_REQUIRE_EQ(2, test_alloc::instances); + ATF_REQUIRE_EQ(5, optional2.get().value); + ATF_REQUIRE_EQ(3, optional1.get().value); + } + ATF_REQUIRE_EQ(1, test_alloc::instances); + ATF_REQUIRE_EQ(3, optional1.get().value); + } + ATF_REQUIRE_EQ(0, test_alloc::instances); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(get_default); +ATF_TEST_CASE_BODY(get_default) +{ + const std::string def_value = "hello"; + optional< std::string > optional; + ATF_REQUIRE(&def_value == &optional.get_default(def_value)); + optional = "bye"; + ATF_REQUIRE_EQ("bye", optional.get_default(def_value)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(make_optional); +ATF_TEST_CASE_BODY(make_optional) +{ + optional< int > opt = utils::make_optional(576); + ATF_REQUIRE(opt); + ATF_REQUIRE_EQ(576, opt.get()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(operators_eq_and_ne); +ATF_TEST_CASE_BODY(operators_eq_and_ne) +{ + optional< int > opt1, opt2; + + opt1 = none; opt2 = none; + ATF_REQUIRE( opt1 == opt2); + ATF_REQUIRE(!(opt1 != opt2)); + + opt1 = utils::make_optional(5); opt2 = none; + ATF_REQUIRE(!(opt1 == opt2)); + ATF_REQUIRE( opt1 != opt2); + + opt1 = none; opt2 = utils::make_optional(5); + ATF_REQUIRE(!(opt1 == opt2)); + ATF_REQUIRE( opt1 != opt2); + + opt1 = utils::make_optional(5); opt2 = utils::make_optional(5); + ATF_REQUIRE( opt1 == opt2); + ATF_REQUIRE(!(opt1 != opt2)); + + opt1 = utils::make_optional(6); opt2 = utils::make_optional(5); + ATF_REQUIRE(!(opt1 == opt2)); + ATF_REQUIRE( opt1 != opt2); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(output); +ATF_TEST_CASE_BODY(output) +{ + { + std::ostringstream str; + str << optional< int >(none); + ATF_REQUIRE_EQ("none", str.str()); + } + { + std::ostringstream str; + str << optional< int >(5); + ATF_REQUIRE_EQ("5", str.str()); + } + { + std::ostringstream str; + str << optional< std::string >("this is a text"); + ATF_REQUIRE_EQ("this is a text", str.str()); + } +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, ctors__native_type); + ATF_ADD_TEST_CASE(tcs, ctors__complex_type); + ATF_ADD_TEST_CASE(tcs, assign); + ATF_ADD_TEST_CASE(tcs, return); + ATF_ADD_TEST_CASE(tcs, memory); + ATF_ADD_TEST_CASE(tcs, get_default); + ATF_ADD_TEST_CASE(tcs, make_optional); + ATF_ADD_TEST_CASE(tcs, operators_eq_and_ne); + ATF_ADD_TEST_CASE(tcs, output); +} diff --git a/external/bsd/kyua-cli/dist/utils/passwd.cpp b/external/bsd/kyua-cli/dist/utils/passwd.cpp new file mode 100644 index 000000000..b884f7e7e --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/passwd.cpp @@ -0,0 +1,194 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/passwd.hpp" + +extern "C" { +#include + +#include +#include +} + +#include + +#include "utils/format/macros.hpp" +#include "utils/logging/macros.hpp" +#include "utils/optional.ipp" +#include "utils/sanity.hpp" + +namespace passwd_ns = utils::passwd; + + +namespace { + + +/// If defined, replaces the value returned by current_user(). +static utils::optional< passwd_ns::user > fake_current_user; + + +/// If not empty, defines the current set of mock users. +static std::vector< passwd_ns::user > mock_users; + + +/// Formats a user for logging purposes. +/// +/// \param user The user to format. +/// +/// \return The user as a string. +static std::string +format_user(const passwd_ns::user& user) +{ + return F("name=%s, uid=%s, gid=%s") % user.name % user.uid % user.gid; +} + + +} // anonymous namespace + + +/// Constructs a new user. +/// +/// \param name_ The name of the user. +/// \param uid_ The user identifier. +/// \param gid_ The login group identifier. +passwd_ns::user::user(const std::string& name_, const unsigned int uid_, + const unsigned int gid_) : + name(name_), + uid(uid_), + gid(gid_) +{ +} + + +/// Checks if the user has superpowers or not. +/// +/// \return True if the user is root, false otherwise. +bool +passwd_ns::user::is_root(void) const +{ + return uid == 0; +} + + +/// Gets the current user. +/// +/// \return The current user. +passwd_ns::user +passwd_ns::current_user(void) +{ + if (fake_current_user) { + const user u = fake_current_user.get(); + LD(F("Current user is fake: %s") % format_user(u)); + return u; + } else { + const user u = find_user_by_uid(::getuid()); + LD(F("Current user is: %s") % format_user(u)); + return u; + } +} + + +/// Gets information about a user by its name. +/// +/// \param name The name of the user to query. +/// +/// \return The information about the user. +/// +/// \throw std::runtime_error If the user does not exist. +passwd_ns::user +passwd_ns::find_user_by_name(const std::string& name) +{ + if (mock_users.empty()) { + const struct ::passwd* pw = ::getpwnam(name.c_str()); + if (pw == NULL) + throw std::runtime_error(F("Failed to get information about the " + "user '%s'") % name); + INV(pw->pw_name == name); + return user(pw->pw_name, pw->pw_uid, pw->pw_gid); + } else { + for (std::vector< user >::const_iterator iter = mock_users.begin(); + iter != mock_users.end(); iter++) { + if ((*iter).name == name) + return *iter; + } + throw std::runtime_error(F("Failed to get information about the " + "user '%s'") % name); + } +} + + +/// Gets information about a user by its identifier. +/// +/// \param uid The identifier of the user to query. +/// +/// \return The information about the user. +/// +/// \throw std::runtime_error If the user does not exist. +passwd_ns::user +passwd_ns::find_user_by_uid(const unsigned int uid) +{ + if (mock_users.empty()) { + const struct ::passwd* pw = ::getpwuid(uid); + if (pw == NULL) + throw std::runtime_error(F("Failed to get information about the " + "user with UID %s") % uid); + INV(pw->pw_uid == uid); + return user(pw->pw_name, pw->pw_uid, pw->pw_gid); + } else { + for (std::vector< user >::const_iterator iter = mock_users.begin(); + iter != mock_users.end(); iter++) { + if ((*iter).uid == uid) + return *iter; + } + throw std::runtime_error(F("Failed to get information about the " + "user with UID %s") % uid); + } +} + + +/// Overrides the current user for testing purposes. +/// +/// This DOES NOT change the current privileges! +/// +/// \param new_current_user The new current user. +void +passwd_ns::set_current_user_for_testing(const user& new_current_user) +{ + fake_current_user = new_current_user; +} + + +/// Overrides the current set of users for testing purposes. +/// +/// \param users The new users set. Cannot be empty. +void +passwd_ns::set_mock_users_for_testing(const std::vector< user >& users) +{ + PRE(!users.empty()); + mock_users = users; +} diff --git a/external/bsd/kyua-cli/dist/utils/passwd.hpp b/external/bsd/kyua-cli/dist/utils/passwd.hpp new file mode 100644 index 000000000..dfab90a19 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/passwd.hpp @@ -0,0 +1,69 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file utils/passwd.hpp +/// Querying and manipulation of users and groups. + +#if !defined(UTILS_PASSWD_HPP) +#define UTILS_PASSWD_HPP + +#include +#include + +namespace utils { +namespace passwd { + + +/// Represents a system user. +struct user { + /// The name of the user. + std::string name; + + /// The system-wide identifier of the user. + unsigned int uid; + + /// The login group identifier for the user. + unsigned int gid; + + user(const std::string&, const unsigned int, const unsigned int); + + bool is_root(void) const; +}; + + +user current_user(void); +user find_user_by_name(const std::string&); +user find_user_by_uid(const unsigned int); +void set_current_user_for_testing(const user&); +void set_mock_users_for_testing(const std::vector< user >&); + + +} // namespace passwd +} // namespace utils + +#endif // !defined(UTILS_PASSWD_HPP) diff --git a/external/bsd/kyua-cli/dist/utils/passwd_test.cpp b/external/bsd/kyua-cli/dist/utils/passwd_test.cpp new file mode 100644 index 000000000..7d97c65ca --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/passwd_test.cpp @@ -0,0 +1,179 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/passwd.hpp" + +extern "C" { +#include + +#include +#include +} + +#include +#include + +#include + +namespace passwd_ns = utils::passwd; + + +ATF_TEST_CASE_WITHOUT_HEAD(user__public_fields); +ATF_TEST_CASE_BODY(user__public_fields) +{ + const passwd_ns::user user("the-name", 1, 2); + ATF_REQUIRE_EQ("the-name", user.name); + ATF_REQUIRE_EQ(1, user.uid); + ATF_REQUIRE_EQ(2, user.gid); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(user__is_root__true); +ATF_TEST_CASE_BODY(user__is_root__true) +{ + const passwd_ns::user user("i-am-root", 0, 10); + ATF_REQUIRE(user.is_root()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(user__is_root__false); +ATF_TEST_CASE_BODY(user__is_root__false) +{ + const passwd_ns::user user("i-am-not-root", 123, 10); + ATF_REQUIRE(!user.is_root()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(current_user); +ATF_TEST_CASE_BODY(current_user) +{ + const passwd_ns::user user = passwd_ns::current_user(); + ATF_REQUIRE_EQ(::getuid(), user.uid); + ATF_REQUIRE_EQ(::getgid(), user.gid); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(current_user__fake); +ATF_TEST_CASE_BODY(current_user__fake) +{ + const passwd_ns::user new_user("someone-else", ::getuid() + 1, 0); + passwd_ns::set_current_user_for_testing(new_user); + + const passwd_ns::user user = passwd_ns::current_user(); + ATF_REQUIRE(::getuid() != user.uid); + ATF_REQUIRE_EQ(new_user.uid, user.uid); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(find_user_by_name__ok); +ATF_TEST_CASE_BODY(find_user_by_name__ok) +{ + const struct ::passwd* pw = ::getpwuid(::getuid()); + ATF_REQUIRE(pw != NULL); + + const passwd_ns::user user = passwd_ns::find_user_by_name(pw->pw_name); + ATF_REQUIRE_EQ(::getuid(), user.uid); + ATF_REQUIRE_EQ(::getgid(), user.gid); + ATF_REQUIRE_EQ(pw->pw_name, user.name); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(find_user_by_name__fail); +ATF_TEST_CASE_BODY(find_user_by_name__fail) +{ + ATF_REQUIRE_THROW_RE(std::runtime_error, "Failed.*user 'i-do-not-exist'", + passwd_ns::find_user_by_name("i-do-not-exist")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(find_user_by_name__fake); +ATF_TEST_CASE_BODY(find_user_by_name__fake) +{ + std::vector< passwd_ns::user > users; + users.push_back(passwd_ns::user("myself2", 20, 40)); + users.push_back(passwd_ns::user("myself1", 10, 15)); + users.push_back(passwd_ns::user("myself3", 30, 60)); + passwd_ns::set_mock_users_for_testing(users); + + const passwd_ns::user user = passwd_ns::find_user_by_name("myself1"); + ATF_REQUIRE_EQ(10, user.uid); + ATF_REQUIRE_EQ(15, user.gid); + ATF_REQUIRE_EQ("myself1", user.name); + + ATF_REQUIRE_THROW_RE(std::runtime_error, "Failed.*user 'root'", + passwd_ns::find_user_by_name("root")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(find_user_by_uid__ok); +ATF_TEST_CASE_BODY(find_user_by_uid__ok) +{ + const passwd_ns::user user = passwd_ns::find_user_by_uid(::getuid()); + ATF_REQUIRE_EQ(::getuid(), user.uid); + ATF_REQUIRE_EQ(::getgid(), user.gid); + + const struct ::passwd* pw = ::getpwuid(::getuid()); + ATF_REQUIRE(pw != NULL); + ATF_REQUIRE_EQ(pw->pw_name, user.name); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(find_user_by_uid__fake); +ATF_TEST_CASE_BODY(find_user_by_uid__fake) +{ + std::vector< passwd_ns::user > users; + users.push_back(passwd_ns::user("myself2", 20, 40)); + users.push_back(passwd_ns::user("myself1", 10, 15)); + users.push_back(passwd_ns::user("myself3", 30, 60)); + passwd_ns::set_mock_users_for_testing(users); + + const passwd_ns::user user = passwd_ns::find_user_by_uid(10); + ATF_REQUIRE_EQ(10, user.uid); + ATF_REQUIRE_EQ(15, user.gid); + ATF_REQUIRE_EQ("myself1", user.name); + + ATF_REQUIRE_THROW_RE(std::runtime_error, "Failed.*user.*UID 0", + passwd_ns::find_user_by_uid(0)); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, user__public_fields); + ATF_ADD_TEST_CASE(tcs, user__is_root__true); + ATF_ADD_TEST_CASE(tcs, user__is_root__false); + + ATF_ADD_TEST_CASE(tcs, current_user); + ATF_ADD_TEST_CASE(tcs, current_user__fake); + + ATF_ADD_TEST_CASE(tcs, find_user_by_name__ok); + ATF_ADD_TEST_CASE(tcs, find_user_by_name__fail); + ATF_ADD_TEST_CASE(tcs, find_user_by_name__fake); + ATF_ADD_TEST_CASE(tcs, find_user_by_uid__ok); + ATF_ADD_TEST_CASE(tcs, find_user_by_uid__fake); +} diff --git a/external/bsd/kyua-cli/dist/utils/process/Kyuafile b/external/bsd/kyua-cli/dist/utils/process/Kyuafile new file mode 100644 index 000000000..fa225d30c --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/process/Kyuafile @@ -0,0 +1,9 @@ +syntax(2) + +test_suite("kyua") + +atf_test_program{name="child_test"} +atf_test_program{name="exceptions_test"} +atf_test_program{name="fdstream_test"} +atf_test_program{name="status_test"} +atf_test_program{name="systembuf_test"} diff --git a/external/bsd/kyua-cli/dist/utils/process/child.cpp b/external/bsd/kyua-cli/dist/utils/process/child.cpp new file mode 100644 index 000000000..9191f12f1 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/process/child.cpp @@ -0,0 +1,453 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/process/child.ipp" + +extern "C" { +#include +#include + +#include +#include +#include +} + +#include +#include +#include +#include +#include +#include + +#include "utils/defs.hpp" +#include "utils/format/macros.hpp" +#include "utils/logging/macros.hpp" +#include "utils/process/exceptions.hpp" +#include "utils/process/fdstream.hpp" +#include "utils/process/system.hpp" +#include "utils/process/status.hpp" +#include "utils/sanity.hpp" +#include "utils/signals/interrupts.hpp" + + +namespace utils { +namespace process { + + +/// Private implementation fields for child objects. +struct child::impl { + /// The process identifier. + pid_t _pid; + + /// The input stream for the process' stdout and stderr. May be NULL. + std::auto_ptr< process::ifdstream > _output; + + /// Initializes private implementation data. + /// + /// \param pid The process identifier. + /// \param output The input stream. Grabs ownership of the pointer. + impl(const pid_t pid, process::ifdstream* output) : + _pid(pid), _output(output) {} +}; + + +} // namespace process +} // namespace utils + + +namespace fs = utils::fs; +namespace process = utils::process; +namespace signals = utils::signals; + + +namespace { + + +/// Exception-based version of dup(2). +/// +/// \param old_fd The file descriptor to duplicate. +/// \param new_fd The file descriptor to use as the duplicate. This is +/// closed if it was open before the copy happens. +/// +/// \throw process::system_error If the call to dup2(2) fails. +static void +safe_dup(const int old_fd, const int new_fd) +{ + if (process::detail::syscall_dup2(old_fd, new_fd) == -1) { + const int original_errno = errno; + throw process::system_error(F("dup2(%s, %s) failed") % old_fd % new_fd, + original_errno); + } +} + + +/// Exception-based version of open(2) to open (or create) a file for append. +/// +/// \param filename The file to open in append mode. +/// +/// \return The file descriptor for the opened or created file. +/// +/// \throw process::system_error If the call to open(2) fails. +static int +open_for_append(const fs::path& filename) +{ + const int fd = process::detail::syscall_open( + filename.c_str(), O_CREAT | O_WRONLY | O_APPEND, + S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + if (fd == -1) { + const int original_errno = errno; + throw process::system_error(F("Failed to create %s because open(2) " + "failed") % filename, original_errno); + } + return fd; +} + + +/// Exception-based, type-improved version of wait(2). +/// +/// Because we are waiting for the termination of a process, and because this is +/// the canonical way to call wait(2) for this module, we ensure from here that +/// any subprocess of the process we are killing is terminated. +/// +/// \param pid The identifier of the process to wait for. +/// +/// \return The termination status of the process. +/// +/// \throw process::system_error If the call to waitpid(2) fails. +static process::status +safe_wait(const pid_t pid) +{ + LD(F("Waiting for pid=%s") % pid); + int stat_loc; + if (process::detail::syscall_waitpid(pid, &stat_loc, 0) == -1) { + const int original_errno = errno; + throw process::system_error(F("Failed to wait for PID %s") % pid, + original_errno); + } + return process::status(pid, stat_loc); +} + + +/// Logs the execution of another program. +/// +/// \param program The binary to execute. +/// \param args The arguments to pass to the binary, without the program name. +static void +log_exec(const fs::path& program, const process::args_vector& args) +{ + std::string plain_command = program.str(); + for (process::args_vector::const_iterator iter = args.begin(); + iter != args.end(); ++iter) + plain_command += F(" %s") % *iter; + LD(F("Executing%s") % plain_command); +} + + +/// Maximum number of arguments supported by cxx_exec. +/// +/// We need this limit to avoid having to allocate dynamic memory in the child +/// process to construct the arguments list, which would have side-effects in +/// the parent's memory if we use vfork(). +#define MAX_ARGS 128 + + +static void cxx_exec(const fs::path& program, const process::args_vector& args) + throw() UTILS_NORETURN; + + +/// Executes an external binary and replaces the current process. +/// +/// This function must not use any of the logging features, so that the output +/// of the subprocess is not "polluted" by our own messages. +/// +/// This function must also not affect the global state of the current process +/// as otherwise we would not be able to use vfork(). Only state stored in the +/// stack can be touched. +/// +/// \param program The binary to execute. +/// \param args The arguments to pass to the binary, without the program name. +static void +cxx_exec(const fs::path& program, const process::args_vector& args) throw() +{ + assert(args.size() < MAX_ARGS); + try { + const char* argv[MAX_ARGS + 1]; + + argv[0] = program.c_str(); + for (process::args_vector::size_type i = 0; i < args.size(); i++) + argv[1 + i] = args[i].c_str(); + argv[1 + args.size()] = NULL; + + const int ret = ::execv(program.c_str(), + (char* const*)(unsigned long)(const void*)argv); + const int original_errno = errno; + assert(ret == -1); + + std::cerr << "Failed to execute " << program << ": " + << std::strerror(original_errno) << "\n"; + std::abort(); + } catch (const std::runtime_error& error) { + std::cerr << "Failed to execute " << program << ": " + << error.what() << "\n"; + std::abort(); + } catch (...) { + std::cerr << "Failed to execute " << program << "; got unexpected " + "exception during exec\n"; + std::abort(); + } +} + + +} // anonymous namespace + + +/// Creates a new child. +/// +/// \param implptr A dynamically-allocated impl object with the contents of the +/// new child. +process::child::child(impl *implptr) : + _pimpl(implptr) +{ +} + + +/// Destructor for child. +process::child::~child(void) +{ +} + + +/// Helper function for fork(). +/// +/// Please note: if you update this function to change the return type or to +/// raise different errors, do not forget to update fork() accordingly. +/// +/// \return In the case of the parent, a new child object returned as a +/// dynamically-allocated object because children classes are unique and thus +/// noncopyable. In the case of the child, a NULL pointer. +/// +/// \throw process::system_error If the calls to pipe(2) or fork(2) fail. +std::auto_ptr< process::child > +process::child::fork_capture_aux(void) +{ + std::cout.flush(); + std::cerr.flush(); + + int fds[2]; + if (detail::syscall_pipe(fds) == -1) + throw process::system_error("pipe(2) failed", errno); + + std::auto_ptr< signals::interrupts_inhibiter > inhibiter( + new signals::interrupts_inhibiter); + pid_t pid = detail::syscall_fork(); + if (pid == -1) { + inhibiter.reset(NULL); // Unblock signals. + ::close(fds[0]); + ::close(fds[1]); + throw process::system_error("fork(2) failed", errno); + } else if (pid == 0) { + inhibiter.reset(NULL); // Unblock signals. +#if !defined(__minix) + ::setpgid(::getpid(), ::getpid()); +#endif /* !defined(__minix) */ + try { + ::close(fds[0]); + safe_dup(fds[1], STDOUT_FILENO); + safe_dup(fds[1], STDERR_FILENO); + ::close(fds[1]); + } catch (const system_error& e) { + std::cerr << F("Failed to set up subprocess: %s\n") % e.what(); + std::abort(); + } + return std::auto_ptr< process::child >(NULL); + } else { + ::close(fds[1]); + LD(F("Spawned process %s: stdout and stderr inherited") % pid); + signals::add_pid_to_kill(pid); + inhibiter.reset(NULL); // Unblock signals. + return std::auto_ptr< process::child >( + new process::child(new impl(pid, new process::ifdstream(fds[0])))); + } +} + + +/// Helper function for fork(). +/// +/// Please note: if you update this function to change the return type or to +/// raise different errors, do not forget to update fork() accordingly. +/// +/// \param stdout_file The name of the file in which to store the stdout. +/// If this has the magic value /dev/stdout, then the parent's stdout is +/// reused without applying any redirection. +/// \param stderr_file The name of the file in which to store the stderr. +/// If this has the magic value /dev/stderr, then the parent's stderr is +/// reused without applying any redirection. +/// +/// \return In the case of the parent, a new child object returned as a +/// dynamically-allocated object because children classes are unique and thus +/// noncopyable. In the case of the child, a NULL pointer. +/// +/// \throw process::system_error If the call to fork(2) fails. +std::auto_ptr< process::child > +process::child::fork_files_aux(const fs::path& stdout_file, + const fs::path& stderr_file) +{ + std::cout.flush(); + std::cerr.flush(); + + std::auto_ptr< signals::interrupts_inhibiter > inhibiter( + new signals::interrupts_inhibiter); + pid_t pid = detail::syscall_fork(); + if (pid == -1) { + inhibiter.reset(NULL); // Unblock signals. + throw process::system_error("fork(2) failed", errno); + } else if (pid == 0) { + inhibiter.reset(NULL); // Unblock signals. +#if !defined(__minix) + ::setpgid(::getpid(), ::getpid()); +#endif /* !defined(__minix) */ + + try { + if (stdout_file != fs::path("/dev/stdout")) { + const int stdout_fd = open_for_append(stdout_file); + safe_dup(stdout_fd, STDOUT_FILENO); + ::close(stdout_fd); + } + if (stderr_file != fs::path("/dev/stderr")) { + const int stderr_fd = open_for_append(stderr_file); + safe_dup(stderr_fd, STDERR_FILENO); + ::close(stderr_fd); + } + } catch (const system_error& e) { + std::cerr << F("Failed to set up subprocess: %s\n") % e.what(); + std::abort(); + } + return std::auto_ptr< process::child >(NULL); + } else { + LD(F("Spawned process %s: stdout=%s, stderr=%s") % pid % stdout_file % + stderr_file); + signals::add_pid_to_kill(pid); + inhibiter.reset(NULL); // Unblock signals. + return std::auto_ptr< process::child >( + new process::child(new impl(pid, NULL))); + } +} + + +/// Spawns a new binary and multiplexes and captures its stdout and stderr. +/// +/// If the subprocess cannot be completely set up for any reason, it attempts to +/// dump an error message to its stderr channel and it then calls std::abort(). +/// +/// \param program The binary to execute. +/// \param args The arguments to pass to the binary, without the program name. +/// +/// \return A new child object, returned as a dynamically-allocated object +/// because children classes are unique and thus noncopyable. +/// +/// \throw process::system_error If the process cannot be spawned due to a +/// system call error. +std::auto_ptr< process::child > +process::child::spawn_capture(const fs::path& program, const args_vector& args) +{ + std::auto_ptr< child > child = fork_capture_aux(); + if (child.get() == NULL) + cxx_exec(program, args); + log_exec(program, args); + return child; +} + + +/// Spawns a new binary and redirects its stdout and stderr to files. +/// +/// If the subprocess cannot be completely set up for any reason, it attempts to +/// dump an error message to its stderr channel and it then calls std::abort(). +/// +/// \param program The binary to execute. +/// \param args The arguments to pass to the binary, without the program name. +/// \param stdout_file The name of the file in which to store the stdout. +/// \param stderr_file The name of the file in which to store the stderr. +/// +/// \return A new child object, returned as a dynamically-allocated object +/// because children classes are unique and thus noncopyable. +/// +/// \throw process::system_error If the process cannot be spawned due to a +/// system call error. +std::auto_ptr< process::child > +process::child::spawn_files(const fs::path& program, + const args_vector& args, + const fs::path& stdout_file, + const fs::path& stderr_file) +{ + std::auto_ptr< child > child = fork_files_aux(stdout_file, stderr_file); + if (child.get() == NULL) + cxx_exec(program, args); + log_exec(program, args); + return child; +} + + +/// Returns the process identifier of this child. +/// +/// \return A process identifier. +int +process::child::pid(void) const +{ + return _pimpl->_pid; +} + + +/// Gets the input stream corresponding to the stdout and stderr of the child. +/// +/// \pre The child must have been started by fork_capture(). +/// +/// \return A reference to the input stream connected to the output of the test +/// case. +std::istream& +process::child::output(void) +{ + PRE(_pimpl->_output.get() != NULL); + return *_pimpl->_output; +} + + +/// Blocks to wait for completion. +/// +/// \return The termination status of the child process. +/// +/// \throw process::system_error If the call to waitpid(2) fails. +process::status +process::child::wait(void) +{ + const process::status status = safe_wait(_pimpl->_pid); + { + signals::interrupts_inhibiter inhibiter; + signals::remove_pid_to_kill(_pimpl->_pid); + } + return status; +} diff --git a/external/bsd/kyua-cli/dist/utils/process/child.hpp b/external/bsd/kyua-cli/dist/utils/process/child.hpp new file mode 100644 index 000000000..aa6b6e207 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/process/child.hpp @@ -0,0 +1,105 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file utils/process/child.hpp +/// Spawning and manipulation of children processes. +/// +/// The child module provides a set of functions to spawn subprocesses with +/// different settings, and the corresponding set of classes to interact with +/// said subprocesses. The interfaces to fork subprocesses are very simplified +/// and only provide the minimum functionality required by the rest of the +/// project. +/// +/// Be aware that the semantics of the fork and wait methods exposed by this +/// module are slightly different from that of the native calls. Any process +/// spawned by fork here will be isolated in its own process group; once any of +/// such children processes is awaited for, its whole process group will be +/// terminated. This is the semantics we want in the above layers to ensure +/// that test programs (and, for that matter, external utilities) do not leak +/// subprocesses on the system. + +#if !defined(UTILS_PROCESS_CHILD_HPP) +#define UTILS_PROCESS_CHILD_HPP + +#include +#include +#include +#include + +#include "utils/fs/path.hpp" +#include "utils/noncopyable.hpp" +#include "utils/process/status.hpp" + +namespace utils { +namespace process { + + +/// Arguments to a program, without the program name. +typedef std::vector< std::string > args_vector; + + +/// Child process spawner and controller. +class child : noncopyable { + struct impl; + + /// Pointer to the shared internal implementation. + std::auto_ptr< impl > _pimpl; + + static std::auto_ptr< child > fork_capture_aux(void); + + static std::auto_ptr< child > fork_files_aux(const fs::path&, + const fs::path&); + + explicit child(impl *); + +public: + ~child(void); + + template< typename Hook > + static std::auto_ptr< child > fork_capture(Hook); + std::istream& output(void); + + template< typename Hook > + static std::auto_ptr< child > fork_files(Hook, const fs::path&, + const fs::path&); + + static std::auto_ptr< child > spawn_capture( + const fs::path&, const args_vector&); + static std::auto_ptr< child > spawn_files( + const fs::path&, const args_vector&, const fs::path&, const fs::path&); + + int pid(void) const; + + status wait(void); +}; + + +} // namespace process +} // namespace utils + +#endif // !defined(UTILS_PROCESS_CHILD_HPP) diff --git a/external/bsd/kyua-cli/dist/utils/process/child.ipp b/external/bsd/kyua-cli/dist/utils/process/child.ipp new file mode 100644 index 000000000..7a1383004 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/process/child.ipp @@ -0,0 +1,106 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#if !defined(UTILS_PROCESS_CHILD_IPP) +#define UTILS_PROCESS_CHILD_IPP + +#include + +#include "utils/process/child.hpp" + +namespace utils { +namespace process { + + +/// Spawns a new subprocess and redirects its stdout and stderr to files. +/// +/// If the subprocess cannot be completely set up for any reason, it attempts to +/// dump an error message to its stderr channel and it then calls std::abort(). +/// +/// \param hook The function to execute in the subprocess. Must not return. +/// \param stdout_file The name of the file in which to store the stdout. +/// \param stderr_file The name of the file in which to store the stderr. +/// +/// \return A new child object, returned as a dynamically-allocated object +/// because children classes are unique and thus noncopyable. +/// +/// \throw process::system_error If the process cannot be spawned due to a +/// system call error. +template< typename Hook > +std::auto_ptr< child > +child::fork_files(Hook hook, const fs::path& stdout_file, + const fs::path& stderr_file) +{ + std::auto_ptr< child > child = fork_files_aux(stdout_file, stderr_file); + if (child.get() == NULL) { + try { + hook(); + std::abort(); + } catch (...) { + std::abort(); + } + } + + return child; +} + + +/// Spawns a new subprocess and multiplexes and captures its stdout and stderr. +/// +/// If the subprocess cannot be completely set up for any reason, it attempts to +/// dump an error message to its stderr channel and it then calls std::abort(). +/// +/// \param hook The function to execute in the subprocess. Must not return. +/// +/// \return A new child object, returned as a dynamically-allocated object +/// because children classes are unique and thus noncopyable. +/// +/// \throw process::system_error If the process cannot be spawned due to a +/// system call error. +template< typename Hook > +std::auto_ptr< child > +child::fork_capture(Hook hook) +{ + std::auto_ptr< child > child = fork_capture_aux(); + if (child.get() == NULL) { + try { + hook(); + std::abort(); + } catch (...) { + std::abort(); + } + } + + return child; +} + + +} // namespace process +} // namespace utils + +#endif // !defined(UTILS_PROCESS_CHILD_IPP) diff --git a/external/bsd/kyua-cli/dist/utils/process/child_test.cpp b/external/bsd/kyua-cli/dist/utils/process/child_test.cpp new file mode 100644 index 000000000..22895c1cd --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/process/child_test.cpp @@ -0,0 +1,764 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/process/child.ipp" + +extern "C" { +#include +#include + +#include +#include +#include +} + +#include +#include +#include +#include +#include +#include + +#include + +#include "utils/defs.hpp" +#include "utils/env.hpp" +#include "utils/format/macros.hpp" +#include "utils/fs/operations.hpp" +#include "utils/logging/macros.hpp" +#include "utils/process/exceptions.hpp" +#include "utils/process/system.hpp" +#include "utils/sanity.hpp" + +namespace fs = utils::fs; +namespace logging = utils::logging; +namespace process = utils::process; + + +namespace { + + +/// Body for a process that prints a simple message and exits. +/// +/// \tparam ExitStatus The exit status for the subprocess. +/// \tparam Message A single character that will be prepended to the printed +/// messages. This would ideally be a string, but we cannot templatize a +/// function with an object nor a pointer. +template< int ExitStatus, char Message > +static void +child_simple_function(void) +{ + std::cout << "To stdout: " << Message << "\n"; + std::cerr << "To stderr: " << Message << "\n"; + std::exit(ExitStatus); +} + + +/// Functor for the body of a process that prints a simple message and exits. +class child_simple_functor { + /// The exit status that the subprocess will yield. + int _exitstatus; + + /// The message to print on stdout and stderr. + std::string _message; + +public: + /// Constructs a new functor. + /// + /// \param exitstatus The exit status that the subprocess will yield. + /// \param message The message to print on stdout and stderr. + child_simple_functor(const int exitstatus, const std::string& message) : + _exitstatus(exitstatus), + _message(message) + { + } + + /// Body for the subprocess. + void + operator()(void) + { + std::cout << "To stdout: " << _message << "\n"; + std::cerr << "To stderr: " << _message << "\n"; + std::exit(_exitstatus); + } +}; + + +/// Body for a process that prints many messages to stdout and exits. +/// +/// The goal of this body is to validate that any buffering performed on the +/// parent process to read the output of the subprocess works correctly. +static void +child_printer_function(void) +{ + for (std::size_t i = 0; i < 100; i++) + std::cout << "This is a message to stdout, sequence " << i << "\n"; + std::cout.flush(); + std::cerr << "Exiting\n"; + std::exit(EXIT_SUCCESS); +} + + +/// Functor for the body of a process that runs child_printer_function. +class child_printer_functor { +public: + /// Body for the subprocess. + void + operator()(void) + { + child_printer_function(); + } +}; + + +/// Body for a child process that creates a pidfile. +static void +child_write_pid(void) +{ + std::ofstream output("pidfile"); + output << ::getpid() << "\n"; + output.close(); + std::exit(EXIT_SUCCESS); +} + + +/// A child process that returns. +/// +/// The fork() wrappers are supposed to capture this condition and terminate the +/// child before the code returns to the fork() call point. +static void +child_return(void) +{ +} + + +/// A child process that raises an exception. +/// +/// The fork() wrappers are supposed to capture this condition and terminate the +/// child before the code returns to the fork() call point. +/// +/// \tparam Type The type of the exception to raise. +/// \tparam Value The value passed to the constructor of the exception type. In +/// general, this only makes sense if Type is a primitive type so that, in +/// the end, the code becomes "throw int(123)". +/// +/// \throw Type An exception of the provided type. +template< class Type, Type Value > +void +child_raise_exception(void) +{ + throw Type(Value); +} + + +/// Calculates the path to the test helpers binary. +/// +/// \param tc A pointer to the caller test case, needed to extract the value of +/// the "srcdir" property. +/// +/// \return The path to the helpers binary. +static fs::path +get_helpers(const atf::tests::tc* tc) +{ + return fs::path(tc->get_config_var("srcdir")) / "helpers"; +} + + +/// Mock fork(2) that just returns an error. +/// +/// \tparam Errno The value to set as the errno of the failed call. +/// +/// \return Always -1. +template< int Errno > +static pid_t +fork_fail(void) throw() +{ + errno = Errno; + return -1; +} + + +/// Mock open(2) that fails if the 'raise-error' file is opened. +/// +/// \tparam Errno The value to set as the errno if the known failure triggers. +/// \param path The path to the file to be opened. +/// \param flags The open flags. +/// \param ... The file mode creation, if flags contains O_CREAT. +/// +/// \return The opened file handle or -1 on error. +template< int Errno > +static int +open_fail(const char* path, const int flags, ...) throw() +{ + if (std::strcmp(path, "raise-error") == 0) { + errno = Errno; + return -1; + } else { + va_list ap; + va_start(ap, flags); + const int mode = va_arg(ap, int); + va_end(ap); + return ::open(path, flags, mode); + } +} + + +/// Mock pipe(2) that just returns an error. +/// +/// \tparam Errno The value to set as the errno of the failed call. +/// \param [out] unused_fildes A pointer to a 2-integer array. +/// +/// \return Always -1. +template< int Errno > +static pid_t +pipe_fail(int* UTILS_UNUSED_PARAM(fildes)) throw() +{ + errno = Errno; + return -1; +} + + +/// Helper for child tests to validate inheritance of stdout/stderr. +/// +/// This function ensures that passing one of /dev/stdout or /dev/stderr to +/// the child__fork_files fork method does the right thing. The idea is that we +/// call fork with the given parameters and then make our child redirect one of +/// its file descriptors to a specific file without going through the process +/// library. We then validate if this redirection worked and got the expected +/// output. +/// +/// \param fork_stdout The path to pass to the fork call as the stdout file. +/// \param fork_stderr The path to pass to the fork call as the stderr file. +/// \param child_file The file to explicitly in the subchild. +/// \param child_fd The file descriptor to which to attach child_file. +static void +do_inherit_test(const char* fork_stdout, const char* fork_stderr, + const char* child_file, const int child_fd) +{ + const pid_t pid = ::fork(); + ATF_REQUIRE(pid != -1); + if (pid == 0) { + logging::set_inmemory(); + + const int fd = ::open(child_file, O_CREAT | O_WRONLY | O_TRUNC, 0644); + if (fd != child_fd) { + if (::dup2(fd, child_fd) == -1) + std::abort(); + ::close(fd); + } + + std::auto_ptr< process::child > child = process::child::fork_files( + child_simple_function< 123, 'Z' >, + fs::path(fork_stdout), fs::path(fork_stderr)); + const process::status status = child->wait(); + if (!status.exited() || status.exitstatus() != 123) + std::abort(); + std::exit(EXIT_SUCCESS); + } else { + int status; + ATF_REQUIRE(::waitpid(pid, &status, 0) != -1); + ATF_REQUIRE(WIFEXITED(status)); + ATF_REQUIRE_EQ(EXIT_SUCCESS, WEXITSTATUS(status)); + ATF_REQUIRE(atf::utils::grep_file("stdout: Z", "stdout.txt")); + ATF_REQUIRE(atf::utils::grep_file("stderr: Z", "stderr.txt")); + } +} + + +/// Performs a "child__fork_capture__ok_*" test. +/// +/// This test basically ensures that the child__fork_capture class spawns a +/// process whose output is captured in an input stream. +/// +/// \tparam Hook The type of the fork hook to use. +/// \param hook The hook to the fork call. +template< class Hook > +static void +child__fork_capture__ok(Hook hook) +{ + std::cout << "This unflushed message should not propagate to the child"; + std::cerr << "This unflushed message should not propagate to the child"; + std::auto_ptr< process::child > child = process::child::fork_capture(hook); + std::cout << std::endl; + std::cerr << std::endl; + + std::istream& output = child->output(); + for (std::size_t i = 0; i < 100; i++) { + std::string line; + ATF_REQUIRE(std::getline(output, line).good()); + ATF_REQUIRE_EQ((F("This is a message to stdout, " + "sequence %s") % i).str(), line); + } + + std::string line; + ATF_REQUIRE(std::getline(output, line).good()); + ATF_REQUIRE_EQ("Exiting", line); + + process::status status = child->wait(); + ATF_REQUIRE(status.exited()); + ATF_REQUIRE_EQ(EXIT_SUCCESS, status.exitstatus()); +} + + +} // anonymous namespace + + +ATF_TEST_CASE_WITHOUT_HEAD(child__fork_capture__ok_function); +ATF_TEST_CASE_BODY(child__fork_capture__ok_function) +{ + child__fork_capture__ok(child_printer_function); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(child__fork_capture__ok_functor); +ATF_TEST_CASE_BODY(child__fork_capture__ok_functor) +{ + child__fork_capture__ok(child_printer_functor()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(child__fork_capture__pipe_fail); +ATF_TEST_CASE_BODY(child__fork_capture__pipe_fail) +{ + process::detail::syscall_pipe = pipe_fail< 23 >; + try { + process::child::fork_capture(child_simple_function< 1, 'A' >); + fail("Expected exception but none raised"); + } catch (const process::system_error& e) { + ATF_REQUIRE(atf::utils::grep_string("pipe.*failed", e.what())); + ATF_REQUIRE_EQ(23, e.original_errno()); + } +} + + +ATF_TEST_CASE_WITHOUT_HEAD(child__fork_capture__fork_cannot_exit); +ATF_TEST_CASE_BODY(child__fork_capture__fork_cannot_exit) +{ + const pid_t parent_pid = ::getpid(); + atf::utils::create_file("to-not-be-deleted", ""); + + std::auto_ptr< process::child > child = process::child::fork_capture( + child_return); + if (::getpid() != parent_pid) { + // If we enter this clause, it is because the hook returned. + ::unlink("to-not-be-deleted"); + std::exit(EXIT_SUCCESS); + } + + const process::status status = child->wait(); + ATF_REQUIRE(status.signaled()); + ATF_REQUIRE(fs::exists(fs::path("to-not-be-deleted"))); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(child__fork_capture__fork_cannot_unwind); +ATF_TEST_CASE_BODY(child__fork_capture__fork_cannot_unwind) +{ + const pid_t parent_pid = ::getpid(); + atf::utils::create_file("to-not-be-deleted", ""); + try { + std::auto_ptr< process::child > child = process::child::fork_capture( + child_raise_exception< int, 123 >); + const process::status status = child->wait(); + ATF_REQUIRE(status.signaled()); + ATF_REQUIRE(fs::exists(fs::path("to-not-be-deleted"))); + } catch (const int i) { + // If we enter this clause, it is because an exception leaked from the + // hook. + INV(parent_pid != ::getpid()); + INV(i == 123); + ::unlink("to-not-be-deleted"); + std::exit(EXIT_SUCCESS); + } +} + + +ATF_TEST_CASE_WITHOUT_HEAD(child__fork_capture__fork_fail); +ATF_TEST_CASE_BODY(child__fork_capture__fork_fail) +{ + process::detail::syscall_fork = fork_fail< 89 >; + try { + process::child::fork_capture(child_simple_function< 1, 'A' >); + fail("Expected exception but none raised"); + } catch (const process::system_error& e) { + ATF_REQUIRE(atf::utils::grep_string("fork.*failed", e.what())); + ATF_REQUIRE_EQ(89, e.original_errno()); + } +} + + +ATF_TEST_CASE_WITHOUT_HEAD(child__fork_files__ok_function); +ATF_TEST_CASE_BODY(child__fork_files__ok_function) +{ + const fs::path file1("file1.txt"); + const fs::path file2("file2.txt"); + + std::auto_ptr< process::child > child = process::child::fork_files( + child_simple_function< 15, 'Z' >, file1, file2); + const process::status status = child->wait(); + ATF_REQUIRE(status.exited()); + ATF_REQUIRE_EQ(15, status.exitstatus()); + + ATF_REQUIRE( atf::utils::grep_file("^To stdout: Z$", file1.str())); + ATF_REQUIRE(!atf::utils::grep_file("^To stdout: Z$", file2.str())); + + ATF_REQUIRE( atf::utils::grep_file("^To stderr: Z$", file2.str())); + ATF_REQUIRE(!atf::utils::grep_file("^To stderr: Z$", file1.str())); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(child__fork_files__ok_functor); +ATF_TEST_CASE_BODY(child__fork_files__ok_functor) +{ + const fs::path filea("fileA.txt"); + const fs::path fileb("fileB.txt"); + + atf::utils::create_file(filea.str(), "Initial stdout\n"); + atf::utils::create_file(fileb.str(), "Initial stderr\n"); + + std::auto_ptr< process::child > child = process::child::fork_files( + child_simple_functor(16, "a functor"), filea, fileb); + const process::status status = child->wait(); + ATF_REQUIRE(status.exited()); + ATF_REQUIRE_EQ(16, status.exitstatus()); + + ATF_REQUIRE( atf::utils::grep_file("^Initial stdout$", filea.str())); + ATF_REQUIRE(!atf::utils::grep_file("^Initial stdout$", fileb.str())); + + ATF_REQUIRE( atf::utils::grep_file("^To stdout: a functor$", filea.str())); + ATF_REQUIRE(!atf::utils::grep_file("^To stdout: a functor$", fileb.str())); + + ATF_REQUIRE( atf::utils::grep_file("^Initial stderr$", fileb.str())); + ATF_REQUIRE(!atf::utils::grep_file("^Initial stderr$", filea.str())); + + ATF_REQUIRE( atf::utils::grep_file("^To stderr: a functor$", fileb.str())); + ATF_REQUIRE(!atf::utils::grep_file("^To stderr: a functor$", filea.str())); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(child__fork_files__inherit_stdout); +ATF_TEST_CASE_BODY(child__fork_files__inherit_stdout) +{ + do_inherit_test("/dev/stdout", "stderr.txt", "stdout.txt", STDOUT_FILENO); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(child__fork_files__inherit_stderr); +ATF_TEST_CASE_BODY(child__fork_files__inherit_stderr) +{ + do_inherit_test("stdout.txt", "/dev/stderr", "stderr.txt", STDERR_FILENO); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(child__fork_files__fork_cannot_exit); +ATF_TEST_CASE_BODY(child__fork_files__fork_cannot_exit) +{ + const pid_t parent_pid = ::getpid(); + atf::utils::create_file("to-not-be-deleted", ""); + + std::auto_ptr< process::child > child = process::child::fork_files( + child_return, fs::path("out"), fs::path("err")); + if (::getpid() != parent_pid) { + // If we enter this clause, it is because the hook returned. + ::unlink("to-not-be-deleted"); + std::exit(EXIT_SUCCESS); + } + + const process::status status = child->wait(); + ATF_REQUIRE(status.signaled()); + ATF_REQUIRE(fs::exists(fs::path("to-not-be-deleted"))); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(child__fork_files__fork_cannot_unwind); +ATF_TEST_CASE_BODY(child__fork_files__fork_cannot_unwind) +{ + const pid_t parent_pid = ::getpid(); + atf::utils::create_file("to-not-be-deleted", ""); + try { + std::auto_ptr< process::child > child = process::child::fork_files( + child_raise_exception< int, 123 >, fs::path("out"), + fs::path("err")); + const process::status status = child->wait(); + ATF_REQUIRE(status.signaled()); + ATF_REQUIRE(fs::exists(fs::path("to-not-be-deleted"))); + } catch (const int i) { + // If we enter this clause, it is because an exception leaked from the + // hook. + INV(parent_pid != ::getpid()); + INV(i == 123); + ::unlink("to-not-be-deleted"); + std::exit(EXIT_SUCCESS); + } +} + + +ATF_TEST_CASE_WITHOUT_HEAD(child__fork_files__fork_fail); +ATF_TEST_CASE_BODY(child__fork_files__fork_fail) +{ + process::detail::syscall_fork = fork_fail< 1234 >; + try { + process::child::fork_files(child_simple_function< 1, 'A' >, + fs::path("a.txt"), fs::path("b.txt")); + fail("Expected exception but none raised"); + } catch (const process::system_error& e) { + ATF_REQUIRE(atf::utils::grep_string("fork.*failed", e.what())); + ATF_REQUIRE_EQ(1234, e.original_errno()); + } + ATF_REQUIRE(!fs::exists(fs::path("a.txt"))); + ATF_REQUIRE(!fs::exists(fs::path("b.txt"))); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(child__fork_files__create_stdout_fail); +ATF_TEST_CASE_BODY(child__fork_files__create_stdout_fail) +{ + process::detail::syscall_open = open_fail< ENOENT >; + std::auto_ptr< process::child > child = process::child::fork_files( + child_simple_function< 1, 'A' >, fs::path("raise-error"), + fs::path("created")); + const process::status status = child->wait(); + ATF_REQUIRE(status.signaled()); + ATF_REQUIRE_EQ(SIGABRT, status.termsig()); + ATF_REQUIRE(!fs::exists(fs::path("raise-error"))); + ATF_REQUIRE(!fs::exists(fs::path("created"))); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(child__fork_files__create_stderr_fail); +ATF_TEST_CASE_BODY(child__fork_files__create_stderr_fail) +{ + process::detail::syscall_open = open_fail< ENOENT >; + std::auto_ptr< process::child > child = process::child::fork_files( + child_simple_function< 1, 'A' >, fs::path("created"), + fs::path("raise-error")); + const process::status status = child->wait(); + ATF_REQUIRE(status.signaled()); + ATF_REQUIRE_EQ(SIGABRT, status.termsig()); + ATF_REQUIRE(fs::exists(fs::path("created"))); + ATF_REQUIRE(!fs::exists(fs::path("raise-error"))); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(child__spawn__absolute_path); +ATF_TEST_CASE_BODY(child__spawn__absolute_path) +{ + std::vector< std::string > args; + args.push_back("return-code"); + args.push_back("12"); + + const fs::path program = get_helpers(this); + INV(program.is_absolute()); + std::auto_ptr< process::child > child = process::child::spawn_files( + program, args, fs::path("out"), fs::path("err")); + + const process::status status = child->wait(); + ATF_REQUIRE(status.exited()); + ATF_REQUIRE_EQ(12, status.exitstatus()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(child__spawn__relative_path); +ATF_TEST_CASE_BODY(child__spawn__relative_path) +{ + std::vector< std::string > args; + args.push_back("return-code"); + args.push_back("13"); + + ATF_REQUIRE(::mkdir("root", 0755) != -1); + ATF_REQUIRE(::symlink(get_helpers(this).c_str(), "root/helpers") != -1); + + std::auto_ptr< process::child > child = process::child::spawn_files( + fs::path("root/helpers"), args, fs::path("out"), fs::path("err")); + + const process::status status = child->wait(); + ATF_REQUIRE(status.exited()); + ATF_REQUIRE_EQ(13, status.exitstatus()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(child__spawn__basename_only); +ATF_TEST_CASE_BODY(child__spawn__basename_only) +{ + std::vector< std::string > args; + args.push_back("return-code"); + args.push_back("14"); + + ATF_REQUIRE(::symlink(get_helpers(this).c_str(), "helpers") != -1); + + std::auto_ptr< process::child > child = process::child::spawn_files( + fs::path("helpers"), args, fs::path("out"), fs::path("err")); + + const process::status status = child->wait(); + ATF_REQUIRE(status.exited()); + ATF_REQUIRE_EQ(14, status.exitstatus()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(child__spawn__no_path); +ATF_TEST_CASE_BODY(child__spawn__no_path) +{ + logging::set_inmemory(); + + std::vector< std::string > args; + args.push_back("return-code"); + args.push_back("14"); + + const fs::path helpers = get_helpers(this); + utils::setenv("PATH", helpers.branch_path().c_str()); + std::auto_ptr< process::child > child = process::child::spawn_capture( + fs::path(helpers.leaf_name()), args); + + std::string line; + ATF_REQUIRE(std::getline(child->output(), line).good()); + ATF_REQUIRE_MATCH("Failed to execute", line); + ATF_REQUIRE(!std::getline(child->output(), line)); + + const process::status status = child->wait(); + ATF_REQUIRE(status.signaled()); + ATF_REQUIRE_EQ(SIGABRT, status.termsig()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(child__spawn__no_args); +ATF_TEST_CASE_BODY(child__spawn__no_args) +{ + std::vector< std::string > args; + std::auto_ptr< process::child > child = process::child::spawn_capture( + get_helpers(this), args); + + std::string line; + ATF_REQUIRE(std::getline(child->output(), line).good()); + ATF_REQUIRE_EQ("Must provide a helper name", line); + ATF_REQUIRE(!std::getline(child->output(), line)); + + const process::status status = child->wait(); + ATF_REQUIRE(status.exited()); + ATF_REQUIRE_EQ(EXIT_FAILURE, status.exitstatus()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(child__spawn__some_args); +ATF_TEST_CASE_BODY(child__spawn__some_args) +{ + std::vector< std::string > args; + args.push_back("print-args"); + args.push_back("foo"); + args.push_back(" bar baz "); + std::auto_ptr< process::child > child = process::child::spawn_capture( + get_helpers(this), args); + + std::string line; + ATF_REQUIRE(std::getline(child->output(), line).good()); + ATF_REQUIRE_EQ("argv[0] = " + get_helpers(this).str(), line); + ATF_REQUIRE(std::getline(child->output(), line).good()); + ATF_REQUIRE_EQ("argv[1] = print-args", line); + ATF_REQUIRE(std::getline(child->output(), line)); + ATF_REQUIRE_EQ("argv[2] = foo", line); + ATF_REQUIRE(std::getline(child->output(), line)); + ATF_REQUIRE_EQ("argv[3] = bar baz ", line); + ATF_REQUIRE(std::getline(child->output(), line)); + ATF_REQUIRE_EQ("argv[4] = NULL", line); + ATF_REQUIRE(!std::getline(child->output(), line)); + + const process::status status = child->wait(); + ATF_REQUIRE(status.exited()); + ATF_REQUIRE_EQ(EXIT_SUCCESS, status.exitstatus()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(child__spawn__missing_program); +ATF_TEST_CASE_BODY(child__spawn__missing_program) +{ + std::vector< std::string > args; + std::auto_ptr< process::child > child = process::child::spawn_capture( + fs::path("a/b/c"), args); + + std::string line; + ATF_REQUIRE(std::getline(child->output(), line).good()); + const std::string exp = "Failed to execute a/b/c: "; + ATF_REQUIRE_EQ(exp, line.substr(0, exp.length())); + ATF_REQUIRE(!std::getline(child->output(), line)); + + const process::status status = child->wait(); + ATF_REQUIRE(status.signaled()); + ATF_REQUIRE_EQ(SIGABRT, status.termsig()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(child__pid); +ATF_TEST_CASE_BODY(child__pid) +{ + std::auto_ptr< process::child > child = process::child::fork_capture( + child_write_pid); + + const int pid = child->pid(); + + const process::status status = child->wait(); + ATF_REQUIRE(status.exited()); + ATF_REQUIRE_EQ(EXIT_SUCCESS, status.exitstatus()); + + std::ifstream input("pidfile"); + ATF_REQUIRE(input); + int read_pid; + input >> read_pid; + input.close(); + + ATF_REQUIRE_EQ(read_pid, pid); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, child__fork_capture__ok_function); + ATF_ADD_TEST_CASE(tcs, child__fork_capture__ok_functor); + ATF_ADD_TEST_CASE(tcs, child__fork_capture__pipe_fail); + ATF_ADD_TEST_CASE(tcs, child__fork_capture__fork_cannot_exit); + ATF_ADD_TEST_CASE(tcs, child__fork_capture__fork_cannot_unwind); + ATF_ADD_TEST_CASE(tcs, child__fork_capture__fork_fail); + + ATF_ADD_TEST_CASE(tcs, child__fork_files__ok_function); + ATF_ADD_TEST_CASE(tcs, child__fork_files__ok_functor); + ATF_ADD_TEST_CASE(tcs, child__fork_files__inherit_stdout); + ATF_ADD_TEST_CASE(tcs, child__fork_files__inherit_stderr); + ATF_ADD_TEST_CASE(tcs, child__fork_files__fork_cannot_exit); + ATF_ADD_TEST_CASE(tcs, child__fork_files__fork_cannot_unwind); + ATF_ADD_TEST_CASE(tcs, child__fork_files__fork_fail); + ATF_ADD_TEST_CASE(tcs, child__fork_files__create_stdout_fail); + ATF_ADD_TEST_CASE(tcs, child__fork_files__create_stderr_fail); + + ATF_ADD_TEST_CASE(tcs, child__spawn__absolute_path); + ATF_ADD_TEST_CASE(tcs, child__spawn__relative_path); + ATF_ADD_TEST_CASE(tcs, child__spawn__basename_only); + ATF_ADD_TEST_CASE(tcs, child__spawn__no_path); + ATF_ADD_TEST_CASE(tcs, child__spawn__no_args); + ATF_ADD_TEST_CASE(tcs, child__spawn__some_args); + ATF_ADD_TEST_CASE(tcs, child__spawn__missing_program); + + ATF_ADD_TEST_CASE(tcs, child__pid); +} diff --git a/external/bsd/kyua-cli/dist/utils/process/exceptions.cpp b/external/bsd/kyua-cli/dist/utils/process/exceptions.cpp new file mode 100644 index 000000000..51b314e06 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/process/exceptions.cpp @@ -0,0 +1,91 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/process/exceptions.hpp" + +#include + +#include "utils/format/macros.hpp" + +namespace process = utils::process; + + +/// Constructs a new error with a plain-text message. +/// +/// \param message The plain-text error message. +process::error::error(const std::string& message) : + std::runtime_error(message) +{ +} + + +/// Destructor for the error. +process::error::~error(void) throw() +{ +} + + +/// Constructs a new error based on an errno code. +/// +/// \param message_ The message describing what caused the error. +/// \param errno_ The error code. +process::system_error::system_error(const std::string& message_, + const int errno_) : + error(F("%s: %s") % message_ % strerror(errno_)), + _original_errno(errno_) +{ +} + + +/// Destructor for the error. +process::system_error::~system_error(void) throw() +{ +} + + +/// Gets the original errno code. +int +process::system_error::original_errno(void) const throw() +{ + return _original_errno; +} + + +/// Constructs a new timeout_error. +/// +/// \param message_ The message describing what caused the error. +process::timeout_error::timeout_error(const std::string& message_) : + error(message_) +{ +} + + +/// Destructor for the error. +process::timeout_error::~timeout_error(void) throw() +{ +} diff --git a/external/bsd/kyua-cli/dist/utils/process/exceptions.hpp b/external/bsd/kyua-cli/dist/utils/process/exceptions.hpp new file mode 100644 index 000000000..c02849400 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/process/exceptions.hpp @@ -0,0 +1,78 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file utils/process/exceptions.hpp +/// Exception types raised by the process module. + +#if !defined(UTILS_PROCESS_EXCEPTIONS_HPP) +#define UTILS_PROCESS_EXCEPTIONS_HPP + +#include + +namespace utils { +namespace process { + + +/// Base exceptions for process errors. +class error : public std::runtime_error { +public: + explicit error(const std::string&); + ~error(void) throw(); +}; + + +/// Exceptions for errno-based errors. +/// +/// TODO(jmmv): This code is duplicated in, at least, utils::fs. Figure +/// out a way to reuse this exception while maintaining the correct inheritance +/// (i.e. be able to keep it as a child of process::error). +class system_error : public error { + /// Error number describing this libc error condition. + int _original_errno; + +public: + explicit system_error(const std::string&, const int); + ~system_error(void) throw(); + + int original_errno(void) const throw(); +}; + + +/// Denotes that a deadline was exceeded. +class timeout_error : public error { +public: + explicit timeout_error(const std::string&); + ~timeout_error(void) throw(); +}; + + +} // namespace process +} // namespace utils + + +#endif // !defined(UTILS_PROCESS_EXCEPTIONS_HPP) diff --git a/external/bsd/kyua-cli/dist/utils/process/exceptions_test.cpp b/external/bsd/kyua-cli/dist/utils/process/exceptions_test.cpp new file mode 100644 index 000000000..95768ecb2 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/process/exceptions_test.cpp @@ -0,0 +1,63 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/process/exceptions.hpp" + +#include +#include + +#include + +#include "utils/format/macros.hpp" + +namespace process = utils::process; + + +ATF_TEST_CASE_WITHOUT_HEAD(error); +ATF_TEST_CASE_BODY(error) +{ + const process::error e("Some text"); + ATF_REQUIRE(std::strcmp("Some text", e.what()) == 0); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(system_error); +ATF_TEST_CASE_BODY(system_error) +{ + const process::system_error e("Call failed", ENOENT); + const std::string expected = F("Call failed: %s") % std::strerror(ENOENT); + ATF_REQUIRE_EQ(expected, e.what()); + ATF_REQUIRE_EQ(ENOENT, e.original_errno()); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, error); + ATF_ADD_TEST_CASE(tcs, system_error); +} diff --git a/external/bsd/kyua-cli/dist/utils/process/fdstream.cpp b/external/bsd/kyua-cli/dist/utils/process/fdstream.cpp new file mode 100644 index 000000000..e09601b45 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/process/fdstream.cpp @@ -0,0 +1,75 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/process/fdstream.hpp" + +#include "utils/process/systembuf.hpp" + + +namespace utils { +namespace process { + + +/// Private implementation fields for ifdstream. +struct ifdstream::impl { + /// The systembuf backing this file descriptor. + systembuf _systembuf; + + /// Initializes private implementation data. + /// + /// \param fd The file descriptor. + impl(const int fd) : _systembuf(fd) {} +}; + + +} // namespace process +} // namespace utils + + +namespace process = utils::process; + + +/// Constructs a new ifdstream based on an open file descriptor. +/// +/// This grabs ownership of the file descriptor. +/// +/// \param fd The file descriptor to read from. Must be open and valid. +process::ifdstream::ifdstream(const int fd) : + std::istream(NULL), + _pimpl(new impl(fd)) +{ + rdbuf(&_pimpl->_systembuf); +} + + +/// Destroys an ifdstream object. +/// +/// \post The file descriptor attached to this stream is closed. +process::ifdstream::~ifdstream(void) +{ +} diff --git a/external/bsd/kyua-cli/dist/utils/process/fdstream.hpp b/external/bsd/kyua-cli/dist/utils/process/fdstream.hpp new file mode 100644 index 000000000..b36b0f1d1 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/process/fdstream.hpp @@ -0,0 +1,64 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file utils/process/fdstream.hpp +/// Provides the utils::process::ifdstream class. + +#if !defined(UTILS_PROCESS_FDSTREAM_HPP) +#define UTILS_PROCESS_FDSTREAM_HPP + +#include +#include + +#include "utils/noncopyable.hpp" + +namespace utils { +namespace process { + + +/// An input stream backed by a file descriptor. +/// +/// This class grabs ownership of the file descriptor. I.e. when the class is +/// destroyed, the file descriptor is closed unconditionally. +class ifdstream : public std::istream, noncopyable +{ + struct impl; + + /// Pointer to the shared internal implementation. + std::auto_ptr< impl > _pimpl; + +public: + explicit ifdstream(const int); + ~ifdstream(void); +}; + + +} // namespace process +} // namespace utils + +#endif // !defined(UTILS_PROCESS_FDSTREAM_HPP) diff --git a/external/bsd/kyua-cli/dist/utils/process/fdstream_test.cpp b/external/bsd/kyua-cli/dist/utils/process/fdstream_test.cpp new file mode 100644 index 000000000..f624712bf --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/process/fdstream_test.cpp @@ -0,0 +1,73 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/process/fdstream.hpp" + +extern "C" { +#include +} + +#include + +#include "utils/process/systembuf.hpp" + +using utils::process::ifdstream; +using utils::process::systembuf; + + +ATF_TEST_CASE(ifdstream); +ATF_TEST_CASE_HEAD(ifdstream) +{ + set_md_var("descr", "Tests the ifdstream class"); +} +ATF_TEST_CASE_BODY(ifdstream) +{ + int fds[2]; + ATF_REQUIRE(::pipe(fds) != -1); + + ifdstream rend(fds[0]); + + systembuf wbuf(fds[1]); + std::ostream wend(&wbuf); + + // XXX This assumes that the pipe's buffer is big enough to accept + // the data written without blocking! + wend << "1Test 1message\n"; + wend.flush(); + std::string tmp; + rend >> tmp; + ATF_REQUIRE_EQ(tmp, "1Test"); + rend >> tmp; + ATF_REQUIRE_EQ(tmp, "1message"); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, ifdstream); +} diff --git a/external/bsd/kyua-cli/dist/utils/process/helpers.cpp b/external/bsd/kyua-cli/dist/utils/process/helpers.cpp new file mode 100644 index 000000000..f9887a443 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/process/helpers.cpp @@ -0,0 +1,74 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include +#include +#include +#include + + +static int +print_args(int argc, char* argv[]) +{ + for (int i = 0; i < argc; i++) + std::cout << "argv[" << i << "] = " << argv[i] << "\n"; + std::cout << "argv[" << argc << "] = NULL"; + return EXIT_SUCCESS; +} + + +static int +return_code(int argc, char* argv[]) +{ + if (argc != 3) + std::abort(); + + std::istringstream iss(argv[2]); + int code; + iss >> code; + return code; +} + + +int +main(int argc, char* argv[]) +{ + if (argc < 2) { + std::cerr << "Must provide a helper name\n"; + std::exit(EXIT_FAILURE); + } + + if (std::strcmp(argv[1], "print-args") == 0) { + return print_args(argc, argv); + } else if (std::strcmp(argv[1], "return-code") == 0) { + return return_code(argc, argv); + } else { + std::cerr << "Unknown helper\n"; + return EXIT_FAILURE; + } +} diff --git a/external/bsd/kyua-cli/dist/utils/process/status.cpp b/external/bsd/kyua-cli/dist/utils/process/status.cpp new file mode 100644 index 000000000..ec74aecba --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/process/status.cpp @@ -0,0 +1,179 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/process/status.hpp" + +extern "C" { +#include +} + +#include "utils/optional.ipp" +#include "utils/sanity.hpp" + +namespace process = utils::process; + +using utils::none; +using utils::optional; + +#if !defined(WCOREDUMP) +# define WCOREDUMP(x) false +#endif + + +/// Constructs a new status object based on the status value of waitpid(2). +/// +/// \param dead_pid_ The PID of the process this status belonged to. +/// \param stat_loc The status value returnd by waitpid(2). +process::status::status(const int dead_pid_, int stat_loc) : + _dead_pid(dead_pid_), + _exited(WIFEXITED(stat_loc) ? + optional< int >(WEXITSTATUS(stat_loc)) : none), + _signaled(WIFSIGNALED(stat_loc) ? + optional< std::pair< int, bool > >( + std::make_pair(WTERMSIG(stat_loc), WCOREDUMP(stat_loc))) : + none) +{ +} + + +/// Constructs a new status object based on fake values. +/// +/// \param exited_ If not none, specifies the exit status of the program. +/// \param signaled_ If not none, specifies the termination signal and whether +/// the process dumped core or not. +process::status::status(const optional< int >& exited_, + const optional< std::pair< int, bool > >& signaled_) : + _dead_pid(-1), + _exited(exited_), + _signaled(signaled_) +{ +} + + +/// Constructs a new status object based on a fake exit status. +/// +/// \param exitstatus_ The exit code of the process. +/// +/// \return A status object with fake data. +process::status +process::status::fake_exited(const int exitstatus_) +{ + return status(utils::make_optional(exitstatus_), none); +} + + +/// Constructs a new status object based on a fake exit status. +/// +/// \param termsig_ The termination signal of the process. +/// \param coredump_ Whether the process dumped core or not. +/// +/// \return A status object with fake data. +process::status +process::status::fake_signaled(const int termsig_, const bool coredump_) +{ + return status(none, utils::make_optional(std::make_pair(termsig_, + coredump_))); +} + + +/// Returns the PID of the process this status was taken from. +/// +/// Please note that the process is already dead and gone from the system. This +/// PID can only be used for informational reasons and not to address the +/// process in any way. +/// +/// \return The PID of the original process. +int +process::status::dead_pid(void) const +{ + return _dead_pid; +} + + +/// Returns whether the process exited cleanly or not. +/// +/// \return True if the process exited cleanly, false otherwise. +bool +process::status::exited(void) const +{ + return _exited; +} + + +/// Returns the exit code of the process. +/// +/// \pre The process must have exited cleanly (i.e. exited() must be true). +/// +/// \return The exit code. +int +process::status::exitstatus(void) const +{ + PRE(exited()); + return _exited.get(); +} + + +/// Returns whether the process terminated due to a signal or not. +/// +/// \return True if the process terminated due to a signal, false otherwise. +bool +process::status::signaled(void) const +{ + return _signaled; +} + + +/// Returns the signal that terminated the process. +/// +/// \pre The process must have terminated by a signal (i.e. signaled() must be +/// true. +/// +/// \return The signal number. +int +process::status::termsig(void) const +{ + PRE(signaled()); + return _signaled.get().first; +} + + +/// Returns whether the process core dumped or not. +/// +/// This functionality may be unsupported in some platforms. In such cases, +/// this method returns false unconditionally. +/// +/// \pre The process must have terminated by a signal (i.e. signaled() must be +/// true. +/// +/// \return True if the process dumped core, false otherwise. +bool +process::status::coredump(void) const +{ + PRE(signaled()); + return _signaled.get().second; +} diff --git a/external/bsd/kyua-cli/dist/utils/process/status.hpp b/external/bsd/kyua-cli/dist/utils/process/status.hpp new file mode 100644 index 000000000..2852317a7 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/process/status.hpp @@ -0,0 +1,78 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file utils/process/status.hpp +/// Provides the utils::process::status class. + +#if !defined(UTILS_PROCESS_STATUS_HPP) +#define UTILS_PROCESS_STATUS_HPP + +#include + +#include "utils/optional.ipp" + +namespace utils { +namespace process { + + +/// Representation of the termination status of a process. +class status { + /// The PID of the process that generated this status. + /// + /// Note that the process has exited already and been awaited for, so the + /// PID cannot be used to address the process. + int _dead_pid; + + /// The exit status of the process, if it exited cleanly. + optional< int > _exited; + + /// The signal that terminated the program, if any, and if it dumped core. + optional< std::pair< int, bool > > _signaled; + + status(const optional< int >&, const optional< std::pair< int, bool > >&); + +public: + status(const int, int); + static status fake_exited(const int); + static status fake_signaled(const int, const bool); + + int dead_pid(void) const; + + bool exited(void) const; + int exitstatus(void) const; + + bool signaled(void) const; + int termsig(void) const; + bool coredump(void) const; +}; + + +} // namespace process +} // namespace utils + +#endif // !defined(UTILS_PROCESS_STATUS_HPP) diff --git a/external/bsd/kyua-cli/dist/utils/process/status_test.cpp b/external/bsd/kyua-cli/dist/utils/process/status_test.cpp new file mode 100644 index 000000000..96629a1da --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/process/status_test.cpp @@ -0,0 +1,180 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/process/status.hpp" + +extern "C" { +#include +#include + +#include +#include +} + +#include + +#include + +using utils::process::status; + + +namespace { + + +/// Body of a subprocess that exits with a particular exit status. +/// +/// \tparam ExitStatus The status to exit with. +template< int ExitStatus > +void child_exit(void) +{ + std::exit(ExitStatus); +} + + +/// Body of a subprocess that sends a particular signal to itself. +/// +/// \tparam Signo The signal to send to self. +template< int Signo > +void child_signal(void) +{ + ::kill(::getpid(), Signo); +} + + +/// Spawns a process and waits for completion. +/// +/// \param hook The function to run within the child. Should not return. +/// +/// \return The termination status of the spawned subprocess. +status +fork_and_wait(void (*hook)(void)) +{ + pid_t pid = ::fork(); + ATF_REQUIRE(pid != -1); + if (pid == 0) { + hook(); + std::abort(); + } else { + int stat_loc; + ATF_REQUIRE(::waitpid(pid, &stat_loc, 0) != -1); + const status s = status(pid, stat_loc); + ATF_REQUIRE_EQ(pid, s.dead_pid()); + return s; + } +} + + +} // anonymous namespace + + +ATF_TEST_CASE_WITHOUT_HEAD(fake_exited) +ATF_TEST_CASE_BODY(fake_exited) +{ + const status fake = status::fake_exited(123); + ATF_REQUIRE_EQ(-1, fake.dead_pid()); + ATF_REQUIRE(fake.exited()); + ATF_REQUIRE_EQ(123, fake.exitstatus()); + ATF_REQUIRE(!fake.signaled()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(fake_signaled) +ATF_TEST_CASE_BODY(fake_signaled) +{ + const status fake = status::fake_signaled(567, true); + ATF_REQUIRE_EQ(-1, fake.dead_pid()); + ATF_REQUIRE(!fake.exited()); + ATF_REQUIRE(fake.signaled()); + ATF_REQUIRE_EQ(567, fake.termsig()); + ATF_REQUIRE(fake.coredump()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(integration__exited); +ATF_TEST_CASE_BODY(integration__exited) +{ + const status exit_success = fork_and_wait(child_exit< EXIT_SUCCESS >); + ATF_REQUIRE(exit_success.exited()); + ATF_REQUIRE_EQ(EXIT_SUCCESS, exit_success.exitstatus()); + ATF_REQUIRE(!exit_success.signaled()); + + const status exit_failure = fork_and_wait(child_exit< EXIT_FAILURE >); + ATF_REQUIRE(exit_failure.exited()); + ATF_REQUIRE_EQ(EXIT_FAILURE, exit_failure.exitstatus()); + ATF_REQUIRE(!exit_failure.signaled()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(integration__signaled); +ATF_TEST_CASE_BODY(integration__signaled) +{ + const status sigterm = fork_and_wait(child_signal< SIGTERM >); + ATF_REQUIRE(!sigterm.exited()); + ATF_REQUIRE(sigterm.signaled()); + ATF_REQUIRE_EQ(SIGTERM, sigterm.termsig()); + ATF_REQUIRE(!sigterm.coredump()); + + const status sigkill = fork_and_wait(child_signal< SIGKILL >); + ATF_REQUIRE(!sigkill.exited()); + ATF_REQUIRE(sigkill.signaled()); + ATF_REQUIRE_EQ(SIGKILL, sigkill.termsig()); + ATF_REQUIRE(!sigkill.coredump()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(integration__coredump); +ATF_TEST_CASE_BODY(integration__coredump) +{ +#if !defined(__minix) + struct rlimit rl; + rl.rlim_cur = RLIM_INFINITY; + rl.rlim_max = RLIM_INFINITY; + if (::setrlimit(RLIMIT_CORE, &rl) == -1) + skip("Cannot unlimit the core file size; check limits manually"); +#endif /* !defined(__minix) */ + + const status coredump = fork_and_wait(child_signal< SIGQUIT >); + ATF_REQUIRE(!coredump.exited()); + ATF_REQUIRE(coredump.signaled()); + ATF_REQUIRE_EQ(SIGQUIT, coredump.termsig()); +#if !defined(WCOREDUMP) + expect_fail("Platform does not support checking for coredump"); +#endif + ATF_REQUIRE(coredump.coredump()); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, fake_exited); + ATF_ADD_TEST_CASE(tcs, fake_signaled); + + ATF_ADD_TEST_CASE(tcs, integration__exited); + ATF_ADD_TEST_CASE(tcs, integration__signaled); + ATF_ADD_TEST_CASE(tcs, integration__coredump); +} diff --git a/external/bsd/kyua-cli/dist/utils/process/system.cpp b/external/bsd/kyua-cli/dist/utils/process/system.cpp new file mode 100644 index 000000000..d29a7f211 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/process/system.cpp @@ -0,0 +1,58 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/process/system.hpp" + +extern "C" { +#include + +#include +#include +} + +namespace detail = utils::process::detail; + + +/// Indirection to execute the dup2(2) system call. +int (*detail::syscall_dup2)(const int, const int) = ::dup2; + + +/// Indirection to execute the fork(2) system call. +pid_t (*detail::syscall_fork)(void) = ::fork; + + +/// Indirection to execute the open(2) system call. +int (*detail::syscall_open)(const char*, const int, ...) = ::open; + + +/// Indirection to execute the pipe(2) system call. +int (*detail::syscall_pipe)(int[2]) = ::pipe; + + +/// Indirection to execute the waitpid(2) system call. +pid_t (*detail::syscall_waitpid)(const pid_t, int*, const int) = ::waitpid; diff --git a/external/bsd/kyua-cli/dist/utils/process/system.hpp b/external/bsd/kyua-cli/dist/utils/process/system.hpp new file mode 100644 index 000000000..63dba3813 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/process/system.hpp @@ -0,0 +1,66 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file utils/process/system.hpp +/// Indirection to perform system calls. +/// +/// The indirections exposed in this file are provided to allow unit-testing of +/// particular system behaviors (e.g. failures). The caller of a routine in +/// this library is allowed, for testing purposes only, to explicitly replace +/// the pointers in this file with custom functions to inject a particular +/// behavior into the library code. +/// +/// Do not include this header from other header files. +/// +/// It may be nice to go one step further and completely abstract the library +/// functions in here to provide exception-based error reporting. + +#if !defined(UTILS_PROCESS_SYSTEM_HPP) +#define UTILS_PROCESS_SYSTEM_HPP + +extern "C" { +#include +} + +namespace utils { +namespace process { +namespace detail { + + +extern int (*syscall_dup2)(const int, const int); +extern pid_t (*syscall_fork)(void); +extern int (*syscall_open)(const char*, const int, ...); +extern int (*syscall_pipe)(int[2]); +extern pid_t (*syscall_waitpid)(const pid_t, int*, const int); + + +} // namespace detail +} // namespace process +} // namespace utils + +#endif // !defined(UTILS_PROCESS_SYSTEM_HPP) diff --git a/external/bsd/kyua-cli/dist/utils/process/systembuf.cpp b/external/bsd/kyua-cli/dist/utils/process/systembuf.cpp new file mode 100644 index 000000000..e057bae6e --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/process/systembuf.cpp @@ -0,0 +1,151 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/process/systembuf.hpp" + +extern "C" { +#include +} + +#include "utils/auto_array.ipp" +#include "utils/sanity.hpp" + +using utils::process::systembuf; + + +/// Private implementation fields for systembuf. +struct systembuf::impl { + /// File descriptor attached to the systembuf. + int _fd; + + /// Size of the _read_buf and _write_buf buffers. + std::size_t _bufsize; + + /// In-memory buffer for read operations. + utils::auto_array< char > _read_buf; + + /// In-memory buffer for write operations. + utils::auto_array< char > _write_buf; + + /// Initializes private implementation data. + /// + /// \param fd The file descriptor. + /// \param bufsize The size of the created read and write buffers. + impl(const int fd, const std::size_t bufsize) : + _fd(fd), + _bufsize(bufsize), + _read_buf(new char[bufsize]), + _write_buf(new char[bufsize]) + { + } +}; + + +/// Constructs a new systembuf based on an open file descriptor. +/// +/// This grabs ownership of the file descriptor. +/// +/// \param fd The file descriptor to wrap. Must be open and valid. +/// \param bufsize The size to use for the internal read/write buffers. +systembuf::systembuf(const int fd, std::size_t bufsize) : + _pimpl(new impl(fd, bufsize)) +{ + setp(_pimpl->_write_buf.get(), _pimpl->_write_buf.get() + _pimpl->_bufsize); +} + + +/// Destroys a systembuf object. +/// +/// \post The file descriptor attached to this systembuf is closed. +systembuf::~systembuf(void) +{ + ::close(_pimpl->_fd); +} + + +/// Reads new data when the systembuf read buffer underflows. +/// +/// \return The new character to be read, or EOF if no more. +systembuf::int_type +systembuf::underflow(void) +{ + PRE(gptr() >= egptr()); + + bool ok; + ssize_t cnt = ::read(_pimpl->_fd, _pimpl->_read_buf.get(), + _pimpl->_bufsize); + ok = (cnt != -1 && cnt != 0); + + if (!ok) + return traits_type::eof(); + else { + setg(_pimpl->_read_buf.get(), _pimpl->_read_buf.get(), + _pimpl->_read_buf.get() + cnt); + return traits_type::to_int_type(*gptr()); + } +} + + +/// Writes data to the file descriptor when the write buffer overflows. +/// +/// \param c The character that causes the overflow. +/// +/// \return EOF if error, some other value for success. +/// +/// \throw something TODO(jmmv): According to the documentation, it is OK for +/// this method to throw in case of errors. Revisit this code to see if we +/// can do better. +systembuf::int_type +systembuf::overflow(int c) +{ + PRE(pptr() >= epptr()); + if (sync() == -1) + return traits_type::eof(); + if (!traits_type::eq_int_type(c, traits_type::eof())) { + traits_type::assign(*pptr(), c); + pbump(1); + } + return traits_type::not_eof(c); +} + + +/// Synchronizes the stream with the file descriptor. +/// +/// \return 0 on success, -1 on error. +int +systembuf::sync(void) +{ + ssize_t cnt = pptr() - pbase(); + + bool ok; + ok = ::write(_pimpl->_fd, pbase(), cnt) == cnt; + + if (ok) + pbump(-cnt); + return ok ? 0 : -1; +} diff --git a/external/bsd/kyua-cli/dist/utils/process/systembuf.hpp b/external/bsd/kyua-cli/dist/utils/process/systembuf.hpp new file mode 100644 index 000000000..9474197f6 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/process/systembuf.hpp @@ -0,0 +1,69 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file utils/process/systembuf.hpp +/// Provides the utils::process::systembuf class. + +#if !defined(UTILS_PROCESS_SYSTEMBUF_HPP) +#define UTILS_PROCESS_SYSTEMBUF_HPP + +#include +#include +#include + +#include "utils/noncopyable.hpp" + +namespace utils { +namespace process { + + +/// A std::streambuf implementation for raw file descriptors. +/// +/// This class grabs ownership of the file descriptor. I.e. when the class is +/// destroyed, the file descriptor is closed unconditionally. +class systembuf : public std::streambuf, noncopyable { + struct impl; + + /// Pointer to the shared internal implementation. + std::auto_ptr< impl > _pimpl; + +protected: + int_type underflow(void); + int_type overflow(int); + int sync(void); + +public: + explicit systembuf(const int, std::size_t = 8192); + ~systembuf(void); +}; + + +} // namespace process +} // namespace utils + +#endif // !defined(UTILS_PROCESS_SYSTEMBUF_HPP) diff --git a/external/bsd/kyua-cli/dist/utils/process/systembuf_test.cpp b/external/bsd/kyua-cli/dist/utils/process/systembuf_test.cpp new file mode 100644 index 000000000..ef4fc296d --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/process/systembuf_test.cpp @@ -0,0 +1,166 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/process/systembuf.hpp" + +extern "C" { +#include + +#include +#include +} + +#include + +#include + +using utils::process::systembuf; + + +static void +check_data(std::istream& is, std::size_t length) +{ + char ch = 'A', chr; + std::size_t cnt = 0; + while (is >> chr) { + ATF_REQUIRE_EQ(ch, chr); + if (ch == 'Z') + ch = 'A'; + else + ch++; + cnt++; + } + ATF_REQUIRE_EQ(cnt, length); +} + + +static void +write_data(std::ostream& os, std::size_t length) +{ + char ch = 'A'; + for (std::size_t i = 0; i < length; i++) { + os << ch; + if (ch == 'Z') + ch = 'A'; + else + ch++; + } + os.flush(); +} + + +static void +test_read(std::size_t length, std::size_t bufsize) +{ + std::ofstream f("test_read.txt"); + write_data(f, length); + f.close(); + + int fd = ::open("test_read.txt", O_RDONLY); + ATF_REQUIRE(fd != -1); + systembuf sb(fd, bufsize); + std::istream is(&sb); + check_data(is, length); + ::close(fd); + ::unlink("test_read.txt"); +} + + +static void +test_write(std::size_t length, std::size_t bufsize) +{ + int fd = ::open("test_write.txt", O_WRONLY | O_CREAT | O_TRUNC, + S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + ATF_REQUIRE(fd != -1); + systembuf sb(fd, bufsize); + std::ostream os(&sb); + write_data(os, length); + ::close(fd); + + std::ifstream is("test_write.txt"); + check_data(is, length); + is.close(); + ::unlink("test_write.txt"); +} + + +ATF_TEST_CASE(short_read); +ATF_TEST_CASE_HEAD(short_read) +{ + set_md_var("descr", "Tests that a short read (one that fits in the " + "internal buffer) works when using systembuf"); +} +ATF_TEST_CASE_BODY(short_read) +{ + test_read(64, 1024); +} + + +ATF_TEST_CASE(long_read); +ATF_TEST_CASE_HEAD(long_read) +{ + set_md_var("descr", "Tests that a long read (one that does not fit in " + "the internal buffer) works when using systembuf"); +} +ATF_TEST_CASE_BODY(long_read) +{ + test_read(64 * 1024, 1024); +} + + +ATF_TEST_CASE(short_write); +ATF_TEST_CASE_HEAD(short_write) +{ + set_md_var("descr", "Tests that a short write (one that fits in the " + "internal buffer) works when using systembuf"); +} +ATF_TEST_CASE_BODY(short_write) +{ + test_write(64, 1024); +} + + +ATF_TEST_CASE(long_write); +ATF_TEST_CASE_HEAD(long_write) +{ + set_md_var("descr", "Tests that a long write (one that does not fit " + "in the internal buffer) works when using systembuf"); +} +ATF_TEST_CASE_BODY(long_write) +{ + test_write(64 * 1024, 1024); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, short_read); + ATF_ADD_TEST_CASE(tcs, long_read); + ATF_ADD_TEST_CASE(tcs, short_write); + ATF_ADD_TEST_CASE(tcs, long_write); +} diff --git a/external/bsd/kyua-cli/dist/utils/sanity.cpp b/external/bsd/kyua-cli/dist/utils/sanity.cpp new file mode 100644 index 000000000..4d9656831 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/sanity.cpp @@ -0,0 +1,194 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/sanity.hpp" + +#if defined(HAVE_CONFIG_H) +#include "config.h" +#endif + +extern "C" { +#include +#include +} + +#include +#include +#include +#include + +#include "utils/format/macros.hpp" +#include "utils/logging/macros.hpp" + + +namespace { + + +/// List of fatal signals to be intercepted by the sanity code. +/// +/// The tests hardcode this list; update them whenever the list gets updated. +static int fatal_signals[] = { SIGABRT, SIGBUS, SIGSEGV, 0 }; + + +/// The path to the log file to report on crashes. Be aware that this is empty +/// until install_crash_handlers() is called. +static std::string logfile; + + +/// Prints a message to stderr. +/// +/// Note that this runs from a signal handler. Calling write() is OK. +/// +/// \param message The message to print. +static void +err_write(const std::string& message) +{ + if (::write(STDERR_FILENO, message.c_str(), message.length()) == -1) { + // We are crashing. If ::write fails, there is not much we could do, + // specially considering that we are running within a signal handler. + // Just ignore the error. + } +} + + +/// The crash handler for fatal signals. +/// +/// The sole purpose of this is to print some informational data before +/// reraising the original signal. +/// +/// \param signo The received signal. +static void +crash_handler(const int signo) +{ + PRE(!logfile.empty()); + + err_write(F("*** Fatal signal %s received\n") % signo); + err_write(F("*** Log file is %s\n") % logfile); + err_write(F("*** Please report this problem to %s detailing what you were " + "doing before the crash happened; if possible, include the log " + "file mentioned above\n") % PACKAGE_BUGREPORT); + + /// The handler is installed with SA_RESETHAND, so this is safe to do. We + /// really want to call the default handler to generate any possible core + /// dumps. + ::kill(::getpid(), signo); +} + + +/// Installs a handler for a fatal signal representing a crash. +/// +/// When the specified signal is captured, the crash_handler() will be called to +/// print some informational details to the user and, later, the signal will be +/// redelivered using the default handler to obtain a core dump. +/// +/// \param signo The fatal signal for which to install a handler. +static void +install_one_crash_handler(const int signo) +{ + struct ::sigaction sa; + sa.sa_handler = crash_handler; + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_RESETHAND; + + if (::sigaction(signo, &sa, NULL) == -1) { + const int original_errno = errno; + LW(F("Could not install crash handler for signal %s: %s") % + signo % std::strerror(original_errno)); + } else + LD(F("Installed crash handler for signal %s") % signo); +} + + +/// Returns a textual representation of an assertion type. +/// +/// The textual representation is user facing. +/// +/// \param type The type of the assertion. If the type is unknown for whatever +/// reason, a special message is returned. The code cannot abort in such a +/// case because this code is dealing for assertion errors. +/// +/// \return A textual description of the assertion type. +static std::string +format_type(const utils::assert_type type) +{ + switch (type) { + case utils::invariant: return "Invariant check failed"; + case utils::postcondition: return "Postcondition check failed"; + case utils::precondition: return "Precondition check failed"; + case utils::unreachable: return "Unreachable point reached"; + default: return "UNKNOWN ASSERTION TYPE"; + } +} + + +} // anonymous namespace + + +/// Raises an assertion error. +/// +/// This function prints information about the assertion failure and terminates +/// execution immediately by calling std::abort(). This ensures a coredump so +/// that the failure can be analyzed later. +/// +/// \param type The assertion type; this influences the printed message. +/// \param file The file in which the assertion failed. +/// \param line The line in which the assertion failed. +/// \param message The failure message associated to the condition. +void +utils::sanity_failure(const assert_type type, const char* file, + const size_t line, const std::string& message) +{ + std::cerr << "*** " << file << ":" << line << ": " << format_type(type); + if (!message.empty()) + std::cerr << ": " << message << "\n"; + else + std::cerr << "\n"; + std::abort(); +} + + +/// Installs persistent handlers for crash signals. +/// +/// Should be called at the very beginning of the execution of the program to +/// ensure that a signal handler for fatal crash signals is installed. +/// +/// \pre The function has not been called before. +/// +/// \param logfile_ The path to the log file to report during a crash. +void +utils::install_crash_handlers(const std::string& logfile_) +{ + static bool installed = false; + PRE(!installed); + logfile = logfile_; + + for (const int* iter = &fatal_signals[0]; *iter != 0; iter++) + install_one_crash_handler(*iter); + + installed = true; +} diff --git a/external/bsd/kyua-cli/dist/utils/sanity.hpp b/external/bsd/kyua-cli/dist/utils/sanity.hpp new file mode 100644 index 000000000..402c05e32 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/sanity.hpp @@ -0,0 +1,193 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file utils/sanity.hpp +/// +/// Set of macros that replace the standard assert(3) macro with more semantical +/// expressivity and meaningful diagnostics. Code should never use assert(3) +/// directly. +/// +/// In general, the checks performed by the macros in this code are only +/// executed if the code is built with debugging support (that is, if the NDEBUG +/// macro is NOT defined). + +#if !defined(UTILS_SANITY_HPP) +#define UTILS_SANITY_HPP + +#include +#include + +#include "utils/defs.hpp" + +namespace utils { + + +/// Enumeration to define the assertion type. +/// +/// The assertion type is used by the module to format the assertion messages +/// appropriately. +enum assert_type { + invariant, + postcondition, + precondition, + unreachable, +}; + + +void sanity_failure(const assert_type, const char*, const size_t, + const std::string&) UTILS_NORETURN; + + +void install_crash_handlers(const std::string&); + + +} // namespace utils + + +/// \def _UTILS_ASSERT(type, expr, message) +/// \brief Performs an assertion check. +/// +/// This macro is internal and should not be used directly. +/// +/// Ensures that the given expression expr is true and, if not, terminates +/// execution by calling utils::sanity_failure(). The check is only performed +/// in debug builds. +/// +/// \param type The assertion type as defined by assert_type. +/// \param expr A boolean expression. +/// \param message A string describing the nature of the error. +#if !defined(NDEBUG) +# define _UTILS_ASSERT(type, expr, message) \ + do { \ + if (!(expr)) \ + utils::sanity_failure(type, __FILE__, __LINE__, message); \ + } while (0) +#else // defined(NDEBUG) +# define _UTILS_ASSERT(type, expr, message) do {} while (0) +#endif // !defined(NDEBUG) + + +/// Ensures that an invariant holds. +/// +/// If the invariant does not hold, execution is immediately terminated. The +/// check is only performed in debug builds. +/// +/// The error message printed by this macro is a textual representation of the +/// boolean condition. If you want to provide a custom error message, use +/// INV_MSG instead. +/// +/// \param expr A boolean expression describing the invariant. +#define INV(expr) _UTILS_ASSERT(utils::invariant, expr, #expr) + + +/// Ensures that an invariant holds using a custom error message. +/// +/// If the invariant does not hold, execution is immediately terminated. The +/// check is only performed in debug builds. +/// +/// \param expr A boolean expression describing the invariant. +/// \param msg The error message to print if the condition is false. +#define INV_MSG(expr, msg) _UTILS_ASSERT(utils::invariant, expr, msg) + + +/// Ensures that a precondition holds. +/// +/// If the precondition does not hold, execution is immediately terminated. The +/// check is only performed in debug builds. +/// +/// The error message printed by this macro is a textual representation of the +/// boolean condition. If you want to provide a custom error message, use +/// PRE_MSG instead. +/// +/// \param expr A boolean expression describing the precondition. +#define PRE(expr) _UTILS_ASSERT(utils::precondition, expr, #expr) + + +/// Ensures that a precondition holds using a custom error message. +/// +/// If the precondition does not hold, execution is immediately terminated. The +/// check is only performed in debug builds. +/// +/// \param expr A boolean expression describing the precondition. +/// \param msg The error message to print if the condition is false. +#define PRE_MSG(expr, msg) _UTILS_ASSERT(utils::precondition, expr, msg) + + +/// Ensures that an postcondition holds. +/// +/// If the postcondition does not hold, execution is immediately terminated. +/// The check is only performed in debug builds. +/// +/// The error message printed by this macro is a textual representation of the +/// boolean condition. If you want to provide a custom error message, use +/// POST_MSG instead. +/// +/// \param expr A boolean expression describing the postcondition. +#define POST(expr) _UTILS_ASSERT(utils::postcondition, expr, #expr) + + +/// Ensures that a postcondition holds using a custom error message. +/// +/// If the postcondition does not hold, execution is immediately terminated. +/// The check is only performed in debug builds. +/// +/// \param expr A boolean expression describing the postcondition. +/// \param msg The error message to print if the condition is false. +#define POST_MSG(expr, msg) _UTILS_ASSERT(utils::postcondition, expr, msg) + + +/// Ensures that a code path is not reached. +/// +/// If the code path in which this macro is located is reached, execution is +/// immediately terminated. Given that such a condition is critical for the +/// execution of the program (and to prevent build failures due to some code +/// paths not initializing variables, for example), this condition is fatal both +/// in debug and production builds. +/// +/// The error message printed by this macro is a textual representation of the +/// boolean condition. If you want to provide a custom error message, use +/// POST_MSG instead. +#define UNREACHABLE UNREACHABLE_MSG("") + + +/// Ensures that a code path is not reached using a custom error message. +/// +/// If the code path in which this macro is located is reached, execution is +/// immediately terminated. Given that such a condition is critical for the +/// execution of the program (and to prevent build failures due to some code +/// paths not initializing variables, for example), this condition is fatal both +/// in debug and production builds. +/// +/// \param msg The error message to print if the condition is false. +#define UNREACHABLE_MSG(msg) \ + do { \ + utils::sanity_failure(utils::unreachable, __FILE__, __LINE__, msg); \ + } while (0) + + +#endif // !defined(UTILS_SANITY_HPP) diff --git a/external/bsd/kyua-cli/dist/utils/sanity_test.cpp b/external/bsd/kyua-cli/dist/utils/sanity_test.cpp new file mode 100644 index 000000000..4b281bdfa --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/sanity_test.cpp @@ -0,0 +1,317 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/sanity.hpp" + +extern "C" { +#include +#include +} + +#include +#include + +#include + +#include "utils/format/macros.hpp" +#include "utils/fs/path.hpp" +#include "utils/process/child.ipp" +#include "utils/process/status.hpp" + +namespace fs = utils::fs; +namespace process = utils::process; + + +#define FILE_REGEXP __FILE__ ":[0-9]+: " + + +static const fs::path Stdout_File("stdout.txt"); +static const fs::path Stderr_File("stderr.txt"); + + +#if NDEBUG +static bool NDebug = true; +#else +static bool NDebug = false; +#endif + + +template< typename Function > +static process::status +run_test(Function function) +{ + const process::status status = process::child::fork_files( + function, Stdout_File, Stderr_File)->wait(); + atf::utils::cat_file(Stdout_File.str(), "Helper stdout: "); + atf::utils::cat_file(Stderr_File.str(), "Helper stderr: "); + return status; +} + + +static void +verify_success(const process::status& status) +{ + ATF_REQUIRE(status.exited()); + ATF_REQUIRE_EQ(EXIT_SUCCESS, status.exitstatus()); + ATF_REQUIRE(atf::utils::grep_file("Before test", Stdout_File.str())); + ATF_REQUIRE(atf::utils::grep_file("After test", Stdout_File.str())); +} + + +static void +verify_failed(const process::status& status, const char* type, + const char* exp_message, const bool check_ndebug) +{ + if (check_ndebug && NDebug) { + std::cout << "Built with NDEBUG; skipping verification\n"; + verify_success(status); + } else { + ATF_REQUIRE(status.signaled()); + ATF_REQUIRE_EQ(SIGABRT, status.termsig()); + ATF_REQUIRE(atf::utils::grep_file("Before test", Stdout_File.str())); + ATF_REQUIRE(!atf::utils::grep_file("After test", Stdout_File.str())); + if (exp_message != NULL) + ATF_REQUIRE(atf::utils::grep_file(F(FILE_REGEXP "%s: %s") % + type % exp_message, + Stderr_File.str())); + else + ATF_REQUIRE(atf::utils::grep_file(F(FILE_REGEXP "%s") % type, + Stderr_File.str())); + } +} + + +template< bool Expression, bool WithMessage > +static void +do_inv_test(void) +{ + std::cout << "Before test\n"; + if (WithMessage) + INV_MSG(Expression, "Custom message"); + else + INV(Expression); + std::cout << "After test\n"; + std::exit(EXIT_SUCCESS); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(inv__holds); +ATF_TEST_CASE_BODY(inv__holds) +{ + const process::status status = run_test(do_inv_test< true, false >); + verify_success(status); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(inv__triggers_default_message); +ATF_TEST_CASE_BODY(inv__triggers_default_message) +{ + const process::status status = run_test(do_inv_test< false, false >); + verify_failed(status, "Invariant check failed", "Expression", true); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(inv__triggers_custom_message); +ATF_TEST_CASE_BODY(inv__triggers_custom_message) +{ + const process::status status = run_test(do_inv_test< false, true >); + verify_failed(status, "Invariant check failed", "Custom", true); +} + + +template< bool Expression, bool WithMessage > +static void +do_pre_test(void) +{ + std::cout << "Before test\n"; + if (WithMessage) + PRE_MSG(Expression, "Custom message"); + else + PRE(Expression); + std::cout << "After test\n"; + std::exit(EXIT_SUCCESS); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(pre__holds); +ATF_TEST_CASE_BODY(pre__holds) +{ + const process::status status = run_test(do_pre_test< true, false >); + verify_success(status); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(pre__triggers_default_message); +ATF_TEST_CASE_BODY(pre__triggers_default_message) +{ + const process::status status = run_test(do_pre_test< false, false >); + verify_failed(status, "Precondition check failed", "Expression", true); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(pre__triggers_custom_message); +ATF_TEST_CASE_BODY(pre__triggers_custom_message) +{ + const process::status status = run_test(do_pre_test< false, true >); + verify_failed(status, "Precondition check failed", "Custom", true); +} + + +template< bool Expression, bool WithMessage > +static void +do_post_test(void) +{ + std::cout << "Before test\n"; + if (WithMessage) + POST_MSG(Expression, "Custom message"); + else + POST(Expression); + std::cout << "After test\n"; + std::exit(EXIT_SUCCESS); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(post__holds); +ATF_TEST_CASE_BODY(post__holds) +{ + const process::status status = run_test(do_post_test< true, false >); + verify_success(status); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(post__triggers_default_message); +ATF_TEST_CASE_BODY(post__triggers_default_message) +{ + const process::status status = run_test(do_post_test< false, false >); + verify_failed(status, "Postcondition check failed", "Expression", true); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(post__triggers_custom_message); +ATF_TEST_CASE_BODY(post__triggers_custom_message) +{ + const process::status status = run_test(do_post_test< false, true >); + verify_failed(status, "Postcondition check failed", "Custom", true); +} + + +template< bool WithMessage > +static void +do_unreachable_test(void) +{ + std::cout << "Before test\n"; + if (WithMessage) + UNREACHABLE_MSG("Custom message"); + else + UNREACHABLE; + std::cout << "After test\n"; + std::exit(EXIT_SUCCESS); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(unreachable__default_message); +ATF_TEST_CASE_BODY(unreachable__default_message) +{ + const process::status status = run_test(do_unreachable_test< false >); + verify_failed(status, "Unreachable point reached", NULL, false); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(unreachable__custom_message); +ATF_TEST_CASE_BODY(unreachable__custom_message) +{ + const process::status status = run_test(do_unreachable_test< true >); + verify_failed(status, "Unreachable point reached", "Custom", false); +} + + +template< int Signo > +static void +do_crash_handler_test(void) +{ + utils::install_crash_handlers("test-log.txt"); + ::kill(::getpid(), Signo); + std::cout << "After signal\n"; + std::exit(EXIT_FAILURE); +} + + +template< int Signo > +static void +crash_handler_test(void) +{ + const process::status status = run_test(do_crash_handler_test< Signo >); + ATF_REQUIRE(status.signaled()); + ATF_REQUIRE_EQ(Signo, status.termsig()); + ATF_REQUIRE(atf::utils::grep_file(F("Fatal signal %s") % Signo, + Stderr_File.str())); + ATF_REQUIRE(atf::utils::grep_file("Log file is test-log.txt", + Stderr_File.str())); + ATF_REQUIRE(!atf::utils::grep_file("After signal", Stdout_File.str())); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(install_crash_handlers__sigabrt); +ATF_TEST_CASE_BODY(install_crash_handlers__sigabrt) +{ + crash_handler_test< SIGABRT >(); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(install_crash_handlers__sigbus); +ATF_TEST_CASE_BODY(install_crash_handlers__sigbus) +{ + crash_handler_test< SIGBUS >(); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(install_crash_handlers__sigsegv); +ATF_TEST_CASE_BODY(install_crash_handlers__sigsegv) +{ + crash_handler_test< SIGSEGV >(); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, inv__holds); + ATF_ADD_TEST_CASE(tcs, inv__triggers_default_message); + ATF_ADD_TEST_CASE(tcs, inv__triggers_custom_message); + ATF_ADD_TEST_CASE(tcs, pre__holds); + ATF_ADD_TEST_CASE(tcs, pre__triggers_default_message); + ATF_ADD_TEST_CASE(tcs, pre__triggers_custom_message); + ATF_ADD_TEST_CASE(tcs, post__holds); + ATF_ADD_TEST_CASE(tcs, post__triggers_default_message); + ATF_ADD_TEST_CASE(tcs, post__triggers_custom_message); + ATF_ADD_TEST_CASE(tcs, unreachable__default_message); + ATF_ADD_TEST_CASE(tcs, unreachable__custom_message); + + ATF_ADD_TEST_CASE(tcs, install_crash_handlers__sigabrt); + ATF_ADD_TEST_CASE(tcs, install_crash_handlers__sigbus); + ATF_ADD_TEST_CASE(tcs, install_crash_handlers__sigsegv); +} diff --git a/external/bsd/kyua-cli/dist/utils/signals/Kyuafile b/external/bsd/kyua-cli/dist/utils/signals/Kyuafile new file mode 100644 index 000000000..fe2449748 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/signals/Kyuafile @@ -0,0 +1,8 @@ +syntax(2) + +test_suite("kyua") + +atf_test_program{name="exceptions_test"} +atf_test_program{name="interrupts_test"} +atf_test_program{name="misc_test"} +atf_test_program{name="programmer_test"} diff --git a/external/bsd/kyua-cli/dist/utils/signals/exceptions.cpp b/external/bsd/kyua-cli/dist/utils/signals/exceptions.cpp new file mode 100644 index 000000000..9aa593360 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/signals/exceptions.cpp @@ -0,0 +1,102 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/signals/exceptions.hpp" + +#include + +#include "utils/format/macros.hpp" + +namespace signals = utils::signals; + + +/// Constructs a new error with a plain-text message. +/// +/// \param message The plain-text error message. +signals::error::error(const std::string& message) : + std::runtime_error(message) +{ +} + + +/// Destructor for the error. +signals::error::~error(void) throw() +{ +} + + +/// Constructs a new interrupted error. +/// +/// \param signo_ The signal that caused the interrupt. +signals::interrupted_error::interrupted_error(const int signo_) : + error(F("Interrupted by signal %s") % signo_), + _signo(signo_) +{ +} + + +/// Destructor for the error. +signals::interrupted_error::~interrupted_error(void) throw() +{ +} + + +/// Queries the signal number of the interruption. +/// +/// \return A signal number. +int +signals::interrupted_error::signo(void) const +{ + return _signo; +} + + +/// Constructs a new error based on an errno code. +/// +/// \param message_ The message describing what caused the error. +/// \param errno_ The error code. +signals::system_error::system_error(const std::string& message_, + const int errno_) : + error(F("%s: %s") % message_ % strerror(errno_)), + _original_errno(errno_) +{ +} + + +/// Destructor for the error. +signals::system_error::~system_error(void) throw() +{ +} + + +/// Gets the original errno code. +int +signals::system_error::original_errno(void) const throw() +{ + return _original_errno; +} diff --git a/external/bsd/kyua-cli/dist/utils/signals/exceptions.hpp b/external/bsd/kyua-cli/dist/utils/signals/exceptions.hpp new file mode 100644 index 000000000..968fc870a --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/signals/exceptions.hpp @@ -0,0 +1,83 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file utils/signals/exceptions.hpp +/// Exception types raised by the signals module. + +#if !defined(UTILS_SIGNALS_EXCEPTIONS_HPP) +#define UTILS_SIGNALS_EXCEPTIONS_HPP + +#include + +namespace utils { +namespace signals { + + +/// Base exceptions for signals errors. +class error : public std::runtime_error { +public: + explicit error(const std::string&); + ~error(void) throw(); +}; + + +/// Denotes the reception of a signal to controlledly terminate execution. +class interrupted_error : public error { + /// Signal that caused the interrupt. + int _signo; + +public: + explicit interrupted_error(const int signo_); + ~interrupted_error(void) throw(); + + int signo(void) const; +}; + + +/// Exceptions for errno-based errors. +/// +/// TODO(jmmv): This code is duplicated in, at least, utils::fs. Figure +/// out a way to reuse this exception while maintaining the correct inheritance +/// (i.e. be able to keep it as a child of signals::error). +class system_error : public error { + /// Error number describing this libc error condition. + int _original_errno; + +public: + explicit system_error(const std::string&, const int); + ~system_error(void) throw(); + + int original_errno(void) const throw(); +}; + + +} // namespace signals +} // namespace utils + + +#endif // !defined(UTILS_SIGNALS_EXCEPTIONS_HPP) diff --git a/external/bsd/kyua-cli/dist/utils/signals/exceptions_test.cpp b/external/bsd/kyua-cli/dist/utils/signals/exceptions_test.cpp new file mode 100644 index 000000000..6045f5a2a --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/signals/exceptions_test.cpp @@ -0,0 +1,73 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/signals/exceptions.hpp" + +#include +#include + +#include + +#include "utils/format/macros.hpp" + +namespace signals = utils::signals; + + +ATF_TEST_CASE_WITHOUT_HEAD(error); +ATF_TEST_CASE_BODY(error) +{ + const signals::error e("Some text"); + ATF_REQUIRE(std::strcmp("Some text", e.what()) == 0); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(interrupted_error); +ATF_TEST_CASE_BODY(interrupted_error) +{ + const signals::interrupted_error e(5); + ATF_REQUIRE(std::strcmp("Interrupted by signal 5", e.what()) == 0); + ATF_REQUIRE_EQ(5, e.signo()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(system_error); +ATF_TEST_CASE_BODY(system_error) +{ + const signals::system_error e("Call failed", ENOENT); + const std::string expected = F("Call failed: %s") % std::strerror(ENOENT); + ATF_REQUIRE_EQ(expected, e.what()); + ATF_REQUIRE_EQ(ENOENT, e.original_errno()); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, error); + ATF_ADD_TEST_CASE(tcs, interrupted_error); + ATF_ADD_TEST_CASE(tcs, system_error); +} diff --git a/external/bsd/kyua-cli/dist/utils/signals/interrupts.cpp b/external/bsd/kyua-cli/dist/utils/signals/interrupts.cpp new file mode 100644 index 000000000..98a769571 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/signals/interrupts.cpp @@ -0,0 +1,261 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/signals/interrupts.hpp" + +extern "C" { +#include +#include +} + +#include +#include +#include + +#include "utils/sanity.hpp" +#include "utils/signals/exceptions.hpp" +#include "utils/signals/programmer.hpp" + +namespace signals = utils::signals; + + +namespace { + + +/// The interrupt signal that fired, or -1 if none. +static volatile int fired_signal = -1; + + +/// Collection of PIDs. +typedef std::set< pid_t > pids_set; + + +/// List of processes to kill upon reception of a signal. +static pids_set pids_to_kill; + + +/// Programmer status for the SIGHUP signal. +static std::auto_ptr< signals::programmer > sighup_handler; +/// Programmer status for the SIGINT signal. +static std::auto_ptr< signals::programmer > sigint_handler; +/// Programmer status for the SIGTERM signal. +static std::auto_ptr< signals::programmer > sigterm_handler; + + +/// Signal mask to restore after exiting a signal inhibited section. +static sigset_t old_sigmask; + + +/// Whether there is an interrupts_handler object in existence or not. +bool interrupts_handler_active = false; + + +/// Whether there is an interrupts_inhibiter object in existence or not. +bool interrupts_inhibiter_active = false; + + +/// Generic handler to capture interrupt signals. +/// +/// From this handler, we record that an interrupt has happened so that +/// check_interrupt() can know whether there execution has to be stopped or not. +/// We also terminate any of our child processes (started by the +/// utils::process::children class) so that any ongoing wait(2) system calls +/// terminate. +/// +/// \param signo The signal that caused this handler to be called. +static void +signal_handler(const int signo) +{ + static const char* message = "[-- Signal caught; please wait for " + "cleanup --]\n"; + if (::write(STDERR_FILENO, message, std::strlen(message)) == -1) { + // We are exiting: the message printed here is only for informational + // purposes. If we fail to print it (which probably means something + // is really bad), there is not much we can do within the signal + // handler, so just ignore this. + } + + fired_signal = signo; + + for (pids_set::const_iterator iter = pids_to_kill.begin(); + iter != pids_to_kill.end(); ++iter) { + // Redirecting the interrupt signal to our child processes does NOT + // guarantee that they also terminate. For that to happen, we'd need to + // SIGKILL them. + // + // *However*, because we use this code to invoke the kyua-testers only, + // and because we assume that such processes are well-behaved and + // terminate according to our expectations, we do it this way, which + // allows the testers to know which specific signal made them terminate. + (void)::kill(*iter, signo); + } +} + + +/// Installs signal handlers for potential interrupts. +/// +/// \pre Must not have been called before. +/// \post The various sig*_handler global variables are atomically updated. +static void +setup_handlers(void) +{ + PRE(sighup_handler.get() == NULL); + PRE(sigint_handler.get() == NULL); + PRE(sigterm_handler.get() == NULL); + + // Create the handlers on the stack first so that, if any of them fails, the + // stack unwinding cleans things up. + std::auto_ptr< signals::programmer > tmp_sighup_handler( + new signals::programmer(SIGHUP, signal_handler)); + std::auto_ptr< signals::programmer > tmp_sigint_handler( + new signals::programmer(SIGINT, signal_handler)); + std::auto_ptr< signals::programmer > tmp_sigterm_handler( + new signals::programmer(SIGTERM, signal_handler)); + + // Now, update the global pointers, which is an operation that cannot fail. + sighup_handler = tmp_sighup_handler; + sigint_handler = tmp_sigint_handler; + sigterm_handler = tmp_sigterm_handler; +} + + +/// Uninstalls the signal handlers installed by setup_handlers(). +static void +cleanup_handlers(void) +{ + sighup_handler->unprogram(); sighup_handler.reset(NULL); + sigint_handler->unprogram(); sigint_handler.reset(NULL); + sigterm_handler->unprogram(); sigterm_handler.reset(NULL); +} + + + +/// Masks the signals installed by setup_handlers(). +static void +mask_signals(void) +{ + sigset_t mask; + sigemptyset(&mask); + sigaddset(&mask, SIGHUP); + sigaddset(&mask, SIGINT); + sigaddset(&mask, SIGTERM); + const int ret = ::sigprocmask(SIG_BLOCK, &mask, &old_sigmask); + INV(ret != -1); +} + + +/// Resets the signal masking put in place by mask_signals(). +static void +unmask_signals(void) +{ + const int ret = ::sigprocmask(SIG_SETMASK, &old_sigmask, NULL); + INV(ret != -1); +} + + +} // anonymous namespace + + +/// Constructor that sets up the signal handlers. +signals::interrupts_handler::interrupts_handler(void) +{ + PRE(!interrupts_handler_active); + setup_handlers(); + interrupts_handler_active = true; +} + + +/// Destructor that removes the signal handlers. +signals::interrupts_handler::~interrupts_handler(void) +{ + cleanup_handlers(); + interrupts_handler_active = false; +} + + +/// Constructor that sets up signal masking. +signals::interrupts_inhibiter::interrupts_inhibiter(void) +{ + PRE(!interrupts_inhibiter_active); + mask_signals(); + interrupts_inhibiter_active = true; +} + + +/// Destructor that removes signal masking. +signals::interrupts_inhibiter::~interrupts_inhibiter(void) +{ + unmask_signals(); + interrupts_inhibiter_active = false; +} + + +/// Checks if an interrupt has fired. +/// +/// Calls to this function should be sprinkled in strategic places through the +/// code protected by an interrupts_handler object. +/// +/// \throw interrupted_error If there has been an interrupt. +void +signals::check_interrupt(void) +{ + if (fired_signal != -1) + throw interrupted_error(fired_signal); +} + + +/// Registers a child process to be killed upon reception of an interrupt. +/// +/// \pre Must be called with interrupts being inhibited. The caller must ensure +/// that the call call to fork() and the addition of the PID happen atomically. +/// +/// \param pid The PID of the child process. Must not have been yet regsitered. +void +signals::add_pid_to_kill(const pid_t pid) +{ + PRE(interrupts_inhibiter_active); + PRE(pids_to_kill.find(pid) == pids_to_kill.end()); + pids_to_kill.insert(pid); +} + + +/// Unregisters a child process previously registered via add_pid_to_kill(). +/// +/// \pre Must be called with interrupts being inhibited. This is not necessary, +/// but pushing this to the caller simplifies our logic and provides consistency +/// with the add_pid_to_kill() call. +/// +/// \param pid The PID of the child process. Must have been registered +/// previously, and the process must have already been awaited for. +void +signals::remove_pid_to_kill(const pid_t pid) +{ + PRE(interrupts_inhibiter_active); + PRE(pids_to_kill.find(pid) != pids_to_kill.end()); + pids_to_kill.erase(pid); +} diff --git a/external/bsd/kyua-cli/dist/utils/signals/interrupts.hpp b/external/bsd/kyua-cli/dist/utils/signals/interrupts.hpp new file mode 100644 index 000000000..d92fb3913 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/signals/interrupts.hpp @@ -0,0 +1,73 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file utils/signals/interrupts.hpp +/// Handling of interrupts. + +#if !defined(UTILS_SIGNALS_INTERRUPTS_HPP) +#define UTILS_SIGNALS_INTERRUPTS_HPP + +#include + +#include "utils/noncopyable.hpp" + +namespace utils { +namespace signals { + + +/// Provides a scope in which interrupts can be detected and handled. +/// +/// This RAII-modeled object installs signal handler when instantiated and +/// removes them upon destruction. While this object is active, the +/// check_interrupt() free function can be used to determine if an interrupt has +/// happened. +class interrupts_handler : noncopyable { +public: + interrupts_handler(void); + ~interrupts_handler(void); +}; + + +/// Disables interrupts while the object is alive. +class interrupts_inhibiter : noncopyable { +public: + interrupts_inhibiter(void); + ~interrupts_inhibiter(void); +}; + + +void check_interrupt(void); + +void add_pid_to_kill(const pid_t); +void remove_pid_to_kill(const pid_t); + + +} // namespace signals +} // namespace utils + +#endif // !defined(UTILS_SIGNALS_INTERRUPTS_HPP) diff --git a/external/bsd/kyua-cli/dist/utils/signals/interrupts_test.cpp b/external/bsd/kyua-cli/dist/utils/signals/interrupts_test.cpp new file mode 100644 index 000000000..7bd7e49fc --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/signals/interrupts_test.cpp @@ -0,0 +1,214 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/signals/interrupts.hpp" + +extern "C" { +#include +#include +} + +#include + +#include + +#include "utils/format/macros.hpp" +#include "utils/process/child.ipp" +#include "utils/process/status.hpp" +#include "utils/signals/exceptions.hpp" +#include "utils/signals/programmer.hpp" + +namespace process = utils::process; +namespace signals = utils::signals; + + +namespace { + + +/// Set to the signal that fired; -1 if none. +static volatile int fired_signal = -1; + + +/// Test handler for signals. +/// +/// \post fired_signal is set to the signal that triggered the handler. +/// +/// \param signo The signal that triggered the handler. +static void +signal_handler(const int signo) +{ + fired_signal = signo; +} + + +/// Child process that pauses waiting to be killed. +static void +pause_child(void) +{ + sigset_t mask; + sigemptyset(&mask); + if (sigsuspend(&mask) == -1) + ::exit(EXIT_FAILURE); + else { + // If this happens, it is because we received a non-deadly signal and + // the execution resumed. This is not what we expect, so exit with an + // arbitrary code. + ::exit(45); + } +} + + +/// Checks that interrupts_handler() handles a particular signal. +/// +/// This indirectly checks the check_interrupt() function, which is not part of +/// the class but is tightly related. +/// +/// \param signo The signal to check. +static void +check_interrupts_handler(const int signo) +{ + signals::programmer test_handler(signo, signal_handler); + + { + signals::interrupts_handler interrupts; + + signals::check_interrupt(); + ::kill(getpid(), signo); + ATF_REQUIRE_THROW_RE(signals::interrupted_error, + F("Interrupted by signal %s") % signo, + signals::check_interrupt()); + } + + ATF_REQUIRE_EQ(-1, fired_signal); + ::kill(getpid(), signo); + ATF_REQUIRE_EQ(signo, fired_signal); + + test_handler.unprogram(); +} + + +/// Checks that interrupts_inhibiter() handles a particular signal. +/// +/// \param signo The signal to check. +static void +check_interrupts_inhibiter(const int signo) +{ + signals::programmer test_handler(signo, signal_handler); + + { + signals::interrupts_inhibiter inhibiter; + ::kill(::getpid(), signo); + ATF_REQUIRE_EQ(-1, fired_signal); + } + ATF_REQUIRE_EQ(signo, fired_signal); + + test_handler.unprogram(); +} + + +} // anonymous namespace + + +ATF_TEST_CASE_WITHOUT_HEAD(interrupts_handler__sighup); +ATF_TEST_CASE_BODY(interrupts_handler__sighup) +{ + check_interrupts_handler(SIGHUP); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(interrupts_handler__sigint); +ATF_TEST_CASE_BODY(interrupts_handler__sigint) +{ + check_interrupts_handler(SIGINT); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(interrupts_handler__sigterm); +ATF_TEST_CASE_BODY(interrupts_handler__sigterm) +{ + check_interrupts_handler(SIGTERM); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(interrupts_handler__kill_children); +ATF_TEST_CASE_BODY(interrupts_handler__kill_children) +{ + std::auto_ptr< process::child > child1(process::child::fork_capture( + pause_child)); + std::auto_ptr< process::child > child2(process::child::fork_capture( + pause_child)); + + signals::interrupts_handler interrupts; + + // Our children pause until the reception of a signal. Interrupting + // ourselves will cause the signal to be re-delivered to our children due to + // the interrupts_handler semantics. If this does not happen, the wait + // calls below would block indefinitely and cause our test to time out. + ::kill(::getpid(), SIGHUP); + + const process::status status1 = child1->wait(); + ATF_REQUIRE(status1.signaled()); + ATF_REQUIRE_EQ(SIGHUP, status1.termsig()); + const process::status status2 = child2->wait(); + ATF_REQUIRE(status2.signaled()); + ATF_REQUIRE_EQ(SIGHUP, status2.termsig()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(interrupts_inhibiter__sighup); +ATF_TEST_CASE_BODY(interrupts_inhibiter__sighup) +{ + check_interrupts_inhibiter(SIGHUP); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(interrupts_inhibiter__sigint); +ATF_TEST_CASE_BODY(interrupts_inhibiter__sigint) +{ + check_interrupts_inhibiter(SIGINT); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(interrupts_inhibiter__sigterm); +ATF_TEST_CASE_BODY(interrupts_inhibiter__sigterm) +{ + check_interrupts_inhibiter(SIGTERM); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, interrupts_handler__sighup); + ATF_ADD_TEST_CASE(tcs, interrupts_handler__sigint); + ATF_ADD_TEST_CASE(tcs, interrupts_handler__sigterm); + ATF_ADD_TEST_CASE(tcs, interrupts_handler__kill_children); + + ATF_ADD_TEST_CASE(tcs, interrupts_inhibiter__sighup); + ATF_ADD_TEST_CASE(tcs, interrupts_inhibiter__sigint); + ATF_ADD_TEST_CASE(tcs, interrupts_inhibiter__sigterm); +} diff --git a/external/bsd/kyua-cli/dist/utils/signals/misc.cpp b/external/bsd/kyua-cli/dist/utils/signals/misc.cpp new file mode 100644 index 000000000..36e7966b2 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/signals/misc.cpp @@ -0,0 +1,71 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/signals/misc.hpp" + +#if defined(HAVE_CONFIG_H) +# include "config.h" +#endif + +extern "C" { +#include +} + +#include +#include + +#include "utils/format/macros.hpp" +#include "utils/signals/exceptions.hpp" + +namespace signals = utils::signals; + + +/// Number of the last valid signal. +const int utils::signals::last_signo = LAST_SIGNO; + + +/// Resets a signal handler to its default behavior. +/// +/// \param signo The number of the signal handler to reset. +/// +/// \throw signals::system_error If there is a problem trying to reset the +/// signal handler to its default behavior. +void +signals::reset(const int signo) +{ + struct ::sigaction sa; + sa.sa_handler = SIG_DFL; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + + if (::sigaction(signo, &sa, NULL) == -1) { + const int original_errno = errno; + throw system_error(F("Failed to reset signal %s") % signo, + original_errno); + } +} diff --git a/external/bsd/kyua-cli/dist/utils/signals/misc.hpp b/external/bsd/kyua-cli/dist/utils/signals/misc.hpp new file mode 100644 index 000000000..cd6f6c7ef --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/signals/misc.hpp @@ -0,0 +1,48 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file utils/signals/misc.hpp +/// Free functions and globals. + +#if !defined(UTILS_SIGNALS_MISC_HPP) +#define UTILS_SIGNALS_MISC_HPP + +namespace utils { +namespace signals { + + +extern const int last_signo; + + +void reset(const int); + + +} // namespace signals +} // namespace utils + +#endif // !defined(UTILS_SIGNALS_MISC_HPP) diff --git a/external/bsd/kyua-cli/dist/utils/signals/misc_test.cpp b/external/bsd/kyua-cli/dist/utils/signals/misc_test.cpp new file mode 100644 index 000000000..59d3bb70a --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/signals/misc_test.cpp @@ -0,0 +1,111 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/signals/misc.hpp" + +extern "C" { +#include +#include +} + +#include + +#include + +#include "utils/defs.hpp" +#include "utils/fs/path.hpp" +#include "utils/process/child.ipp" +#include "utils/signals/exceptions.hpp" + +namespace fs = utils::fs; +namespace process = utils::process; +namespace signals = utils::signals; + + +namespace { + + +static void program_reset_raise(void) UTILS_NORETURN; + + +/// Body of a subprocess that tests the signal::reset function. +/// +/// This function programs a signal to be ignored, then uses signal::reset to +/// bring it back to its default handler and then delivers the signal to self. +/// The default behavior of the signal is for the process to die, so this +/// function should never return correctly (and thus the child process should +/// always die due to a signal if all goes well). +static void +program_reset_raise(void) +{ + struct ::sigaction sa; + sa.sa_handler = SIG_IGN; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + if (::sigaction(SIGUSR1, &sa, NULL) == -1) + std::exit(EXIT_FAILURE); + + signals::reset(SIGUSR1); + ::kill(::getpid(), SIGUSR1); + + // Should not be reached, but we do not assert this condition because we + // want to exit cleanly if the signal does not abort our execution to let + // the parent easily know what happened. + std::exit(EXIT_SUCCESS); +} + + +} // anonymous namespace + + +ATF_TEST_CASE_WITHOUT_HEAD(reset__ok); +ATF_TEST_CASE_BODY(reset__ok) +{ + // TODO(jmmv): We should have a child type that inherits both stdout and + // stderr so that we do not have to specify files. + std::auto_ptr< process::child > child = process::child::fork_files( + program_reset_raise, fs::path("stdout.txt"), fs::path("stderr.txt")); + process::status status = child->wait(); + ATF_REQUIRE(status.signaled()); + ATF_REQUIRE_EQ(SIGUSR1, status.termsig()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(reset__immutable); +ATF_TEST_CASE_BODY(reset__immutable) +{ + ATF_REQUIRE_THROW(signals::system_error, signals::reset(SIGKILL)); + ATF_REQUIRE_THROW(signals::system_error, signals::reset(SIGSTOP)); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, reset__ok); + ATF_ADD_TEST_CASE(tcs, reset__immutable); +} diff --git a/external/bsd/kyua-cli/dist/utils/signals/programmer.cpp b/external/bsd/kyua-cli/dist/utils/signals/programmer.cpp new file mode 100644 index 000000000..84386a574 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/signals/programmer.cpp @@ -0,0 +1,137 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/signals/programmer.hpp" + +extern "C" { +#include +} + +#include + +#include "utils/format/macros.hpp" +#include "utils/logging/macros.hpp" +#include "utils/sanity.hpp" +#include "utils/signals/exceptions.hpp" + + +namespace utils { +namespace signals { + + +/// Internal implementation for the signals::programmer class. +struct programmer::impl { + /// The number of the signal managed by this programmer. + int signo; + + /// Whether the signal is currently programmed by us or not. + bool programmed; + + /// The signal handler that we replaced; to be restored on unprogramming. + struct ::sigaction old_sa; + + /// Initializes the internal implementation of the programmer. + /// + /// \param signo_ The signal number. + impl(const int signo_) : + signo(signo_), + programmed(false) + { + } +}; + + +} // namespace signals +} // namespace utils + + +namespace signals = utils::signals; + + +/// Programs a signal handler. +/// +/// \param signo The signal for which to install the handler. +/// \param handler The handler to install. +/// +/// \throw signals::system_error If there is an error programming the signal. +signals::programmer::programmer(const int signo, const handler_type handler) : + _pimpl(new impl(signo)) +{ + struct ::sigaction sa; + sa.sa_handler = handler; + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_RESTART; + + if (::sigaction(_pimpl->signo, &sa, &_pimpl->old_sa) == -1) { + const int original_errno = errno; + throw system_error(F("Could not install handler for signal %s") % + _pimpl->signo, original_errno); + } else + _pimpl->programmed = true; +} + + +/// Destructor; unprograms the signal handler if still programmed. +/// +/// Given that this is a destructor and it can't report errors back to the +/// caller, the caller must attempt to call unprogram() on its own. +signals::programmer::~programmer(void) +{ + if (_pimpl->programmed) { + LW("Destroying still-programmed signals::programmer object"); + try { + unprogram(); + } catch (const system_error& e) { + UNREACHABLE; + } + } +} + + +/// Unprograms the signal handler. +/// +/// \pre The signal handler is programmed (i.e. this can only be called once). +/// +/// \throw system_error If unprogramming the signal failed. If this happens, +/// the signal is left programmed, this object forgets about the signal and +/// therefore there is no way to restore the original handler. +void +signals::programmer::unprogram(void) +{ + PRE(_pimpl->programmed); + + // If we fail, we don't want the destructor to attempt to unprogram the + // handler again, as it would result in a crash. + _pimpl->programmed = false; + + if (::sigaction(_pimpl->signo, &_pimpl->old_sa, NULL) == -1) { + const int original_errno = errno; + throw system_error(F("Could not reset handler for signal %s") % + _pimpl->signo, original_errno); + } +} diff --git a/external/bsd/kyua-cli/dist/utils/signals/programmer.hpp b/external/bsd/kyua-cli/dist/utils/signals/programmer.hpp new file mode 100644 index 000000000..468f2fa4a --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/signals/programmer.hpp @@ -0,0 +1,65 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file utils/signals/programmer.hpp +/// Provides the signals::programmer class. + +#if !defined(UTILS_SIGNALS_PROGRAMMER_HPP) +#define UTILS_SIGNALS_PROGRAMMER_HPP + +#include + +#include "utils/noncopyable.hpp" + +namespace utils { +namespace signals { + + +/// Function type for signal handlers. +typedef void (*handler_type)(const int); + + +/// A RAII class to program signal handlers. +class programmer : noncopyable { + struct impl; + + /// Pointer to the shared internal implementation. + std::auto_ptr< impl > _pimpl; + +public: + programmer(const int, const handler_type); + ~programmer(void); + + void unprogram(void); +}; + + +} // namespace signals +} // namespace utils + +#endif // !defined(UTILS_SIGNALS_PROGRAMMER_HPP) diff --git a/external/bsd/kyua-cli/dist/utils/signals/programmer_test.cpp b/external/bsd/kyua-cli/dist/utils/signals/programmer_test.cpp new file mode 100644 index 000000000..9560aa59b --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/signals/programmer_test.cpp @@ -0,0 +1,140 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/signals/programmer.hpp" + +extern "C" { +#include +#include +} + +#include + +#include "utils/sanity.hpp" + +namespace signals = utils::signals; + + +namespace { + + +namespace sigchld { + + +static bool happened_1; +static bool happened_2; + + +void handler_1(const int signo) { + PRE(signo == SIGCHLD); + happened_1 = true; +} + + +void handler_2(const int signo) { + PRE(signo == SIGCHLD); + happened_2 = true; +} + + +} // namespace sigchld + + +} // anonymous namespace + + +ATF_TEST_CASE_WITHOUT_HEAD(program_unprogram); +ATF_TEST_CASE_BODY(program_unprogram) +{ + signals::programmer programmer(SIGCHLD, sigchld::handler_1); + sigchld::happened_1 = false; + ::kill(::getpid(), SIGCHLD); + ATF_REQUIRE(sigchld::happened_1); + + programmer.unprogram(); + sigchld::happened_1 = false; + ::kill(::getpid(), SIGCHLD); + ATF_REQUIRE(!sigchld::happened_1); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(scope); +ATF_TEST_CASE_BODY(scope) +{ + { + signals::programmer programmer(SIGCHLD, sigchld::handler_1); + sigchld::happened_1 = false; + ::kill(::getpid(), SIGCHLD); + ATF_REQUIRE(sigchld::happened_1); + } + + sigchld::happened_1 = false; + ::kill(::getpid(), SIGCHLD); + ATF_REQUIRE(!sigchld::happened_1); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(nested); +ATF_TEST_CASE_BODY(nested) +{ + signals::programmer programmer_1(SIGCHLD, sigchld::handler_1); + sigchld::happened_1 = false; + sigchld::happened_2 = false; + ::kill(::getpid(), SIGCHLD); + ATF_REQUIRE(sigchld::happened_1); + ATF_REQUIRE(!sigchld::happened_2); + + signals::programmer programmer_2(SIGCHLD, sigchld::handler_2); + sigchld::happened_1 = false; + sigchld::happened_2 = false; + ::kill(::getpid(), SIGCHLD); + ATF_REQUIRE(!sigchld::happened_1); + ATF_REQUIRE(sigchld::happened_2); + + programmer_2.unprogram(); + sigchld::happened_1 = false; + sigchld::happened_2 = false; + ::kill(::getpid(), SIGCHLD); + ATF_REQUIRE(sigchld::happened_1); + ATF_REQUIRE(!sigchld::happened_2); + + programmer_1.unprogram(); + sigchld::happened_1 = false; + sigchld::happened_2 = false; + ::kill(::getpid(), SIGCHLD); + ATF_REQUIRE(!sigchld::happened_1); + ATF_REQUIRE(!sigchld::happened_2); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, program_unprogram); + ATF_ADD_TEST_CASE(tcs, scope); + ATF_ADD_TEST_CASE(tcs, nested); +} diff --git a/external/bsd/kyua-cli/dist/utils/sqlite/Kyuafile b/external/bsd/kyua-cli/dist/utils/sqlite/Kyuafile new file mode 100644 index 000000000..47a8b95da --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/sqlite/Kyuafile @@ -0,0 +1,9 @@ +syntax(2) + +test_suite("kyua") + +atf_test_program{name="c_gate_test"} +atf_test_program{name="database_test"} +atf_test_program{name="exceptions_test"} +atf_test_program{name="statement_test"} +atf_test_program{name="transaction_test"} diff --git a/external/bsd/kyua-cli/dist/utils/sqlite/c_gate.cpp b/external/bsd/kyua-cli/dist/utils/sqlite/c_gate.cpp new file mode 100644 index 000000000..14484679a --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/sqlite/c_gate.cpp @@ -0,0 +1,79 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/sqlite/c_gate.hpp" + +#include "utils/sqlite/database.hpp" + +namespace sqlite = utils::sqlite; + + +/// Creates a new gateway to an existing C++ SQLite database. +/// +/// \param database_ The database to connect to. This object must remain alive +/// while the newly-constructed database_c_gate is alive. +sqlite::database_c_gate::database_c_gate(database& database_) : + _database(database_) +{ +} + + +/// Destructor. +/// +/// Destroying this object has no implications on the life cycle of the SQLite +/// database. Only the corresponding database object controls when the SQLite 3 +/// database is closed. +sqlite::database_c_gate::~database_c_gate(void) +{ +} + + +/// Creates a C++ database for a C SQLite 3 database. +/// +/// \warning The created database object does NOT own the C database. You must +/// take care to properly destroy the input sqlite3 when you are done with it to +/// not leak resources. +/// +/// \param raw_database The raw database to wrap temporarily. +/// +/// \return The wrapped database without strong ownership on the input database. +sqlite::database +sqlite::database_c_gate::connect(::sqlite3* raw_database) +{ + return database(static_cast< void* >(raw_database), false); +} + + +/// Returns the C native SQLite 3 database. +/// +/// \return A native sqlite3 object holding the SQLite 3 C API database. +::sqlite3* +sqlite::database_c_gate::c_database(void) +{ + return static_cast< ::sqlite3* >(_database.raw_database()); +} diff --git a/external/bsd/kyua-cli/dist/utils/sqlite/c_gate.hpp b/external/bsd/kyua-cli/dist/utils/sqlite/c_gate.hpp new file mode 100644 index 000000000..95c3df7d0 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/sqlite/c_gate.hpp @@ -0,0 +1,73 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file c_gate.hpp +/// Provides direct access to the C state of the SQLite wrappers. + +#if !defined(UTILS_SQLITE_C_GATE_HPP) +#define UTILS_SQLITE_C_GATE_HPP + +extern "C" { +#include +} + +namespace utils { +namespace sqlite { + + +class database; + + +/// Gateway to the raw C database of SQLite 3. +/// +/// This class provides a mechanism to muck with the internals of the database +/// wrapper class. +/// +/// \warning The use of this class is discouraged. By using this class, you are +/// entering the world of unsafety. Anything you do through the objects exposed +/// through this class will not be controlled by RAII patterns not validated in +/// any other way, so you can end up corrupting the SQLite 3 state and later get +/// crashes on otherwise perfectly-valid C++ code. +class database_c_gate { + /// The C++ database that this class wraps. + database& _database; + +public: + database_c_gate(database&); + ~database_c_gate(void); + + static database connect(::sqlite3*); + + ::sqlite3* c_database(void); +}; + + +} // namespace sqlite +} // namespace utils + +#endif // !defined(UTILS_SQLITE_C_GATE_HPP) diff --git a/external/bsd/kyua-cli/dist/utils/sqlite/c_gate_test.cpp b/external/bsd/kyua-cli/dist/utils/sqlite/c_gate_test.cpp new file mode 100644 index 000000000..0da6d65e4 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/sqlite/c_gate_test.cpp @@ -0,0 +1,75 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/sqlite/c_gate.hpp" + +#include + +#include "utils/fs/path.hpp" +#include "utils/sqlite/database.hpp" +#include "utils/sqlite/test_utils.hpp" + +namespace fs = utils::fs; +namespace sqlite = utils::sqlite; + + +ATF_TEST_CASE_WITHOUT_HEAD(connect); +ATF_TEST_CASE_BODY(connect) +{ + ::sqlite3* raw_db; + ATF_REQUIRE_EQ(SQLITE_OK, ::sqlite3_open_v2(":memory:", &raw_db, + SQLITE_OPEN_READWRITE, NULL)); + { + sqlite::database database = sqlite::database_c_gate::connect(raw_db); + create_test_table(raw(database)); + } + // If the wrapper object has closed the SQLite 3 database, we will misbehave + // here either by crashing or not finding our test table. + verify_test_table(raw_db); + ::sqlite3_close(raw_db); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(c_database); +ATF_TEST_CASE_BODY(c_database) +{ + sqlite::database db = sqlite::database::in_memory(); + create_test_table(raw(db)); + { + sqlite::database_c_gate gate(db); + ::sqlite3* raw_db = gate.c_database(); + verify_test_table(raw_db); + } +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, c_database); + ATF_ADD_TEST_CASE(tcs, connect); +} diff --git a/external/bsd/kyua-cli/dist/utils/sqlite/database.cpp b/external/bsd/kyua-cli/dist/utils/sqlite/database.cpp new file mode 100644 index 000000000..b073c258c --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/sqlite/database.cpp @@ -0,0 +1,292 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/sqlite/database.hpp" + +extern "C" { +#include +} + +#include + +#include "utils/format/macros.hpp" +#include "utils/logging/macros.hpp" +#include "utils/sanity.hpp" +#include "utils/sqlite/exceptions.hpp" +#include "utils/sqlite/statement.ipp" +#include "utils/sqlite/transaction.hpp" + +namespace sqlite = utils::sqlite; + + +/// Internal implementation for sqlite::database. +struct utils::sqlite::database::impl { + /// The SQLite 3 internal database. + ::sqlite3* db; + + /// Whether we own the database or not (to decide if we close it). + bool owned; + + /// Constructor. + /// + /// \param db_ The SQLite internal database. + /// \param owned_ Whether this object owns the db_ object or not. If it + /// does, the internal db_ will be released during destruction. + impl(::sqlite3* db_, const bool owned_) : + db(db_), + owned(owned_) + { + } + + /// Destructor. + /// + /// It is important to keep this as part of the 'impl' class instead of the + /// container class. The 'impl' class is destroyed exactly once (because it + /// is managed by a shared_ptr) and thus releasing the resources here is + /// OK. However, the container class is potentially released many times, + /// which means that we would be double-freeing the internal object and + /// reusing invalid data. + ~impl(void) + { + if (owned && db != NULL) + close(); + } + + /// Exception-safe version of sqlite3_open_v2. + /// + /// \param file The path to the database file to be opened. + /// \param flags The flags to be passed to the open routine. + /// + /// \return The opened database. + /// + /// \throw std::bad_alloc If there is not enough memory to open the + /// database. + /// \throw api_error If there is any problem opening the database. + static ::sqlite3* + safe_open(const char* file, const int flags) + { + ::sqlite3* db; + const int error = ::sqlite3_open_v2(file, &db, flags, NULL); + if (error != SQLITE_OK) { + if (db == NULL) + throw std::bad_alloc(); + else { + sqlite::database error_db(db, true); + throw sqlite::api_error::from_database(error_db, + "sqlite3_open_v2"); + } + } + INV(db != NULL); + return db; + } + + /// Shared code for the public close() method. + void + close(void) + { + PRE(db != NULL); + int error = ::sqlite3_close(db); + // For now, let's consider a return of SQLITE_BUSY an error. We should + // not be trying to close a busy database in our code. Maybe revisit + // this later to raise busy errors as exceptions. + PRE(error == SQLITE_OK); + db = NULL; + } +}; + + +/// Initializes the SQLite database. +/// +/// You must share the same database object alongside the lifetime of your +/// SQLite session. As soon as the object is destroyed, the session is +/// terminated. +/// +/// \param db_ Raw pointer to the C SQLite 3 object. +/// \param owned_ Whether this instance will own the pointer or not. +sqlite::database::database(void* db_, const bool owned_) : + _pimpl(new impl(static_cast< ::sqlite3* >(db_), owned_)) +{ +} + + +/// Destructor for the SQLite 3 database. +/// +/// Closes the session unless it has already been closed by calling the +/// close() method. It is recommended to explicitly close the session in the +/// code. +sqlite::database::~database(void) +{ +} + + +/// Opens a memory-based temporary SQLite database. +/// +/// \return An in-memory database instance. +/// +/// \throw std::bad_alloc If there is not enough memory to open the database. +/// \throw api_error If there is any problem opening the database. +sqlite::database +sqlite::database::in_memory(void) +{ + return database(impl::safe_open(":memory:", SQLITE_OPEN_READWRITE), true); +} + + +/// Opens a named on-disk SQLite database. +/// +/// \param file The path to the database file to be opened. This does not +/// accept the values "" and ":memory:"; use temporary() and in_memory() +/// instead. +/// \param open_flags The flags to be passed to the open routine. +/// +/// \return A file-backed database instance. +/// +/// \throw std::bad_alloc If there is not enough memory to open the database. +/// \throw api_error If there is any problem opening the database. +sqlite::database +sqlite::database::open(const fs::path& file, int open_flags) +{ + PRE_MSG(!file.str().empty(), "Use database::temporary() instead"); + PRE_MSG(file.str() != ":memory:", "Use database::in_memory() instead"); + + int flags = 0; + if (open_flags & open_readonly) { + flags |= SQLITE_OPEN_READONLY; + open_flags &= ~open_readonly; + } + if (open_flags & open_readwrite) { + flags |= SQLITE_OPEN_READWRITE; + open_flags &= ~open_readwrite; + } + if (open_flags & open_create) { + flags |= SQLITE_OPEN_CREATE; + open_flags &= ~open_create; + } + PRE(open_flags == 0); + + return database(impl::safe_open(file.c_str(), flags), true); +} + + +/// Opens an unnamed on-disk SQLite database. +/// +/// \return A file-backed database instance. +/// +/// \throw std::bad_alloc If there is not enough memory to open the database. +/// \throw api_error If there is any problem opening the database. +sqlite::database +sqlite::database::temporary(void) +{ + return database(impl::safe_open("", SQLITE_OPEN_READWRITE), true); +} + + +/// Gets the internal sqlite3 object. +/// +/// \return The raw SQLite 3 database. This is returned as a void pointer to +/// prevent including the sqlite3.h header file from our public interface. The +/// only way to call this method is by using the c_gate module, and c_gate takes +/// care of casting this object to the appropriate type. +void* +sqlite::database::raw_database(void) +{ + return _pimpl->db; +} + + +/// Terminates the connection to the database. +/// +/// It is recommended to call this instead of relying on the destructor to do +/// the cleanup, but it is not a requirement to use close(). +/// +/// \pre close() has not yet been called. +void +sqlite::database::close(void) +{ + _pimpl->close(); +} + + +/// Executes an arbitrary SQL string. +/// +/// As the documentation explains, this is unsafe. The code should really be +/// preparing statements and executing them step by step. However, it is +/// perfectly fine to use this function for, e.g. the initial creation of +/// tables in a database and in tests. +/// +/// \param sql The SQL commands to be executed. +/// +/// \throw api_error If there is any problem while processing the SQL. +void +sqlite::database::exec(const std::string& sql) +{ + const int error = ::sqlite3_exec(_pimpl->db, sql.c_str(), NULL, NULL, NULL); + if (error != SQLITE_OK) + throw api_error::from_database(*this, "sqlite3_exec"); +} + + +/// Opens a new transaction. +/// +/// \return An object representing the state of the transaction. +/// +/// \throw api_error If there is any problem while opening the transaction. +sqlite::transaction +sqlite::database::begin_transaction(void) +{ + exec("BEGIN TRANSACTION"); + return transaction(*this); +} + + +/// Prepares a new statement. +/// +/// \param sql The SQL statement to prepare. +/// +/// \return The prepared statement. +sqlite::statement +sqlite::database::create_statement(const std::string& sql) +{ + LD(F("Creating statement: %s") % sql); + sqlite3_stmt* stmt; + const int error = ::sqlite3_prepare_v2(_pimpl->db, sql.c_str(), + sql.length() + 1, &stmt, NULL); + if (error != SQLITE_OK) + throw api_error::from_database(*this, "sqlite3_prepare_v2"); + return statement(*this, static_cast< void* >(stmt)); +} + + +/// Returns the row identifier of the last insert. +/// +/// \return A row identifier. +int64_t +sqlite::database::last_insert_rowid(void) +{ + return ::sqlite3_last_insert_rowid(_pimpl->db); +} diff --git a/external/bsd/kyua-cli/dist/utils/sqlite/database.hpp b/external/bsd/kyua-cli/dist/utils/sqlite/database.hpp new file mode 100644 index 000000000..6343ad45b --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/sqlite/database.hpp @@ -0,0 +1,108 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file utils/sqlite/database.hpp +/// Wrapper classes and utilities for the SQLite database state. +/// +/// This module contains thin RAII wrappers around the SQLite 3 structures +/// representing the database, and lightweight. + +#if !defined(UTILS_SQLITE_DATABASE_HPP) +#define UTILS_SQLITE_DATABASE_HPP + +extern "C" { +#include +} + +#include +#include + +#include "utils/fs/path.hpp" + +namespace utils { +namespace sqlite { + + +class database_c_gate; +class statement; +class transaction; + + +/// Constant for the database::open flags: open in read-only mode. +static const int open_readonly = 1 << 0; +/// Constant for the database::open flags: open in read-write mode. +static const int open_readwrite = 1 << 1; +/// Constant for the database::open flags: create on open. +static const int open_create = 1 << 2; + + +/// A RAII model for the SQLite 3 database. +/// +/// This class holds the database of the SQLite 3 interface during its existence +/// and provides wrappers around several SQLite 3 library functions that operate +/// on such database. +/// +/// These wrapper functions differ from the C versions in that they use the +/// implicit database hold by the class, they use C++ types where appropriate +/// and they use exceptions to report errors. +/// +/// The wrappers intend to be as lightweight as possible but, in some +/// situations, they are pretty complex because of the workarounds needed to +/// make the SQLite 3 more C++ friendly. We prefer a clean C++ interface over +/// optimal efficiency, so this is OK. +class database { + struct impl; + + /// Pointer to the shared internal implementation. + std::tr1::shared_ptr< impl > _pimpl; + + friend class database_c_gate; + database(void*, const bool); + void* raw_database(void); + +public: + ~database(void); + + static database in_memory(void); + static database open(const fs::path&, int); + static database temporary(void); + void close(void); + + void exec(const std::string&); + + transaction begin_transaction(void); + statement create_statement(const std::string&); + + int64_t last_insert_rowid(void); +}; + + +} // namespace sqlite +} // namespace utils + +#endif // !defined(UTILS_SQLITE_DATABASE_HPP) diff --git a/external/bsd/kyua-cli/dist/utils/sqlite/database_test.cpp b/external/bsd/kyua-cli/dist/utils/sqlite/database_test.cpp new file mode 100644 index 000000000..7dde84bbe --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/sqlite/database_test.cpp @@ -0,0 +1,241 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/sqlite/database.hpp" + +#include + +#include "utils/fs/operations.hpp" +#include "utils/fs/path.hpp" +#include "utils/sqlite/statement.ipp" +#include "utils/sqlite/test_utils.hpp" +#include "utils/sqlite/transaction.hpp" + +namespace fs = utils::fs; +namespace sqlite = utils::sqlite; + + +ATF_TEST_CASE_WITHOUT_HEAD(in_memory); +ATF_TEST_CASE_BODY(in_memory) +{ + sqlite::database db = sqlite::database::in_memory(); + create_test_table(raw(db)); + verify_test_table(raw(db)); + + ATF_REQUIRE(!fs::exists(fs::path(":memory:"))); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(open__readonly__ok); +ATF_TEST_CASE_BODY(open__readonly__ok) +{ + { + ::sqlite3* db; + ATF_REQUIRE_EQ(SQLITE_OK, ::sqlite3_open_v2("test.db", &db, + SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL)); + create_test_table(db); + ::sqlite3_close(db); + } + { + sqlite::database db = sqlite::database::open(fs::path("test.db"), + sqlite::open_readonly); + verify_test_table(raw(db)); + } +} + + +ATF_TEST_CASE_WITHOUT_HEAD(open__readonly__fail); +ATF_TEST_CASE_BODY(open__readonly__fail) +{ + REQUIRE_API_ERROR("sqlite3_open_v2", + sqlite::database::open(fs::path("missing.db"), sqlite::open_readonly)); + ATF_REQUIRE(!fs::exists(fs::path("missing.db"))); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(open__create__ok); +ATF_TEST_CASE_BODY(open__create__ok) +{ + { + sqlite::database db = sqlite::database::open(fs::path("test.db"), + sqlite::open_readwrite | sqlite::open_create); + ATF_REQUIRE(fs::exists(fs::path("test.db"))); + create_test_table(raw(db)); + } + { + ::sqlite3* db; + ATF_REQUIRE_EQ(SQLITE_OK, ::sqlite3_open_v2("test.db", &db, + SQLITE_OPEN_READONLY, NULL)); + verify_test_table(db); + ::sqlite3_close(db); + } +} + + +ATF_TEST_CASE(open__create__fail); +ATF_TEST_CASE_HEAD(open__create__fail) +{ + set_md_var("require.user", "unprivileged"); +} +ATF_TEST_CASE_BODY(open__create__fail) +{ + fs::mkdir(fs::path("protected"), 0555); + REQUIRE_API_ERROR("sqlite3_open_v2", + sqlite::database::open(fs::path("protected/test.db"), + sqlite::open_readwrite | sqlite::open_create)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(temporary); +ATF_TEST_CASE_BODY(temporary) +{ + // We could validate if files go to disk by setting the temp_store_directory + // PRAGMA to a subdirectory of pwd, and then ensuring the subdirectory is + // not empty. However, there does not seem to be a way to force SQLite to + // unconditionally write the temporary database to disk (even with + // temp_store = FILE), so this scenary is hard to reproduce. + sqlite::database db = sqlite::database::temporary(); + create_test_table(raw(db)); + verify_test_table(raw(db)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(close); +ATF_TEST_CASE_BODY(close) +{ + sqlite::database db = sqlite::database::in_memory(); + db.close(); + // The destructor for the database will run now. If it does a second close, + // we may crash, so let's see if we don't. +} + + +ATF_TEST_CASE_WITHOUT_HEAD(copy); +ATF_TEST_CASE_BODY(copy) +{ + sqlite::database db1 = sqlite::database::in_memory(); + { + sqlite::database db2 = sqlite::database::in_memory(); + create_test_table(raw(db2)); + db1 = db2; + verify_test_table(raw(db1)); + } + // db2 went out of scope. If the destruction is not properly managed, the + // memory of db1 may have been invalidated and this would not work. + verify_test_table(raw(db1)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(exec__ok); +ATF_TEST_CASE_BODY(exec__ok) +{ + sqlite::database db = sqlite::database::in_memory(); + db.exec(create_test_table_sql); + verify_test_table(raw(db)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(exec__fail); +ATF_TEST_CASE_BODY(exec__fail) +{ + sqlite::database db = sqlite::database::in_memory(); + REQUIRE_API_ERROR("sqlite3_exec", + db.exec("SELECT * FROM test")); + REQUIRE_API_ERROR("sqlite3_exec", + db.exec("CREATE TABLE test (col INTEGER PRIMARY KEY);" + "FOO BAR")); + db.exec("SELECT * FROM test"); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(create_statement__ok); +ATF_TEST_CASE_BODY(create_statement__ok) +{ + sqlite::database db = sqlite::database::in_memory(); + sqlite::statement stmt = db.create_statement("SELECT 3"); + // Statement testing happens in statement_test. We are only interested here + // in ensuring that the API call exists and runs. +} + + +ATF_TEST_CASE_WITHOUT_HEAD(begin_transaction); +ATF_TEST_CASE_BODY(begin_transaction) +{ + sqlite::database db = sqlite::database::in_memory(); + sqlite::transaction stmt = db.begin_transaction(); + // Transaction testing happens in transaction_test. We are only interested + // here in ensuring that the API call exists and runs. +} + + +ATF_TEST_CASE_WITHOUT_HEAD(create_statement__fail); +ATF_TEST_CASE_BODY(create_statement__fail) +{ + sqlite::database db = sqlite::database::in_memory(); + REQUIRE_API_ERROR("sqlite3_prepare_v2", + db.create_statement("SELECT * FROM missing")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(last_insert_rowid); +ATF_TEST_CASE_BODY(last_insert_rowid) +{ + sqlite::database db = sqlite::database::in_memory(); + db.exec("CREATE TABLE test (a INTEGER PRIMARY KEY, b INTEGER)"); + db.exec("INSERT INTO test VALUES (723, 5)"); + ATF_REQUIRE_EQ(723, db.last_insert_rowid()); + db.exec("INSERT INTO test VALUES (145, 20)"); + ATF_REQUIRE_EQ(145, db.last_insert_rowid()); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, in_memory); + + ATF_ADD_TEST_CASE(tcs, open__readonly__ok); + ATF_ADD_TEST_CASE(tcs, open__readonly__fail); + ATF_ADD_TEST_CASE(tcs, open__create__ok); + ATF_ADD_TEST_CASE(tcs, open__create__fail); + + ATF_ADD_TEST_CASE(tcs, temporary); + + ATF_ADD_TEST_CASE(tcs, close); + + ATF_ADD_TEST_CASE(tcs, copy); + + ATF_ADD_TEST_CASE(tcs, exec__ok); + ATF_ADD_TEST_CASE(tcs, exec__fail); + + ATF_ADD_TEST_CASE(tcs, begin_transaction); + + ATF_ADD_TEST_CASE(tcs, create_statement__ok); + ATF_ADD_TEST_CASE(tcs, create_statement__fail); + + ATF_ADD_TEST_CASE(tcs, last_insert_rowid); +} diff --git a/external/bsd/kyua-cli/dist/utils/sqlite/exceptions.cpp b/external/bsd/kyua-cli/dist/utils/sqlite/exceptions.cpp new file mode 100644 index 000000000..44faa74e6 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/sqlite/exceptions.cpp @@ -0,0 +1,123 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/sqlite/exceptions.hpp" + +extern "C" { +#include +} + +#include "utils/format/macros.hpp" +#include "utils/sqlite/c_gate.hpp" + +namespace sqlite = utils::sqlite; + + +/// Constructs a new error with a plain-text message. +/// +/// \param message The plain-text error message. +sqlite::error::error(const std::string& message) : + std::runtime_error(message) +{ +} + + +/// Destructor for the error. +sqlite::error::~error(void) throw() +{ +} + + +/// Constructs a new error. +/// +/// \param api_function_ The name of the API function that caused the error. +/// \param message_ The plain-text error message provided by SQLite. +sqlite::api_error::api_error(const std::string& api_function_, + const std::string& message_) : + error(message_), + _api_function(api_function_) +{ +} + + +/// Destructor for the error. +sqlite::api_error::~api_error(void) throw() +{ +} + + +/// Constructs a new api_error with the message in the SQLite database. +/// +/// \param database_ The SQLite database. +/// \param api_function_ The name of the SQLite C API function that caused the +/// error. +/// +/// \return A new api_error with the retrieved message. +sqlite::api_error +sqlite::api_error::from_database(database& database_, + const std::string& api_function_) +{ + ::sqlite3* c_db = database_c_gate(database_).c_database(); + return api_error(api_function_, ::sqlite3_errmsg(c_db)); +} + + +/// Gets the name of the SQlite C API function that caused this error. +/// +/// \return The name of the function. +const std::string& +sqlite::api_error::api_function(void) const +{ + return _api_function; +} + + +/// Constructs a new error. +/// +/// \param name_ The name of the unknown column. +sqlite::invalid_column_error::invalid_column_error(const std::string& name_) : + error(F("Unknown column '%s'") % name_), + _column_name(name_) +{ +} + + +/// Destructor for the error. +sqlite::invalid_column_error::~invalid_column_error(void) throw() +{ +} + + +/// Gets the name of the column that could not be found. +/// +/// \return The name of the column requested by the user. +const std::string& +sqlite::invalid_column_error::column_name(void) const +{ + return _column_name; +} diff --git a/external/bsd/kyua-cli/dist/utils/sqlite/exceptions.hpp b/external/bsd/kyua-cli/dist/utils/sqlite/exceptions.hpp new file mode 100644 index 000000000..55e22b403 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/sqlite/exceptions.hpp @@ -0,0 +1,85 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file utils/sqlite/exceptions.hpp +/// Exception types raised by the sqlite module. + +#if !defined(UTILS_SQLITE_EXCEPTIONS_HPP) +#define UTILS_SQLITE_EXCEPTIONS_HPP + +#include +#include + +namespace utils { +namespace sqlite { + + +class database; + + +/// Base exception for sqlite errors. +class error : public std::runtime_error { +public: + explicit error(const std::string&); + virtual ~error(void) throw(); +}; + + +/// Exception for errors raised by the SQLite 3 API library. +class api_error : public error { + /// The name of the SQLite 3 C API function that caused this error. + std::string _api_function; + +public: + explicit api_error(const std::string&, const std::string&); + virtual ~api_error(void) throw(); + + static api_error from_database(database&, const std::string&); + + const std::string& api_function(void) const; +}; + + +/// The caller requested a non-existent column name. +class invalid_column_error : public error { + /// The name of the invalid column. + std::string _column_name; + +public: + explicit invalid_column_error(const std::string&); + virtual ~invalid_column_error(void) throw(); + + const std::string& column_name(void) const; +}; + + +} // namespace sqlite +} // namespace utils + + +#endif // !defined(UTILS_SQLITE_EXCEPTIONS_HPP) diff --git a/external/bsd/kyua-cli/dist/utils/sqlite/exceptions_test.cpp b/external/bsd/kyua-cli/dist/utils/sqlite/exceptions_test.cpp new file mode 100644 index 000000000..294c15ee7 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/sqlite/exceptions_test.cpp @@ -0,0 +1,92 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/sqlite/exceptions.hpp" + +#include + +#include + +#include "utils/sqlite/c_gate.hpp" +#include "utils/sqlite/database.hpp" + +namespace sqlite = utils::sqlite; + + +ATF_TEST_CASE_WITHOUT_HEAD(error); +ATF_TEST_CASE_BODY(error) +{ + const sqlite::error e("Some text"); + ATF_REQUIRE(std::strcmp("Some text", e.what()) == 0); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(api_error__explicit); +ATF_TEST_CASE_BODY(api_error__explicit) +{ + const sqlite::api_error e("some_function", "Some text"); + ATF_REQUIRE(std::strcmp("Some text", e.what()) == 0); + ATF_REQUIRE_EQ("some_function", e.api_function()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(api_error__from_database); +ATF_TEST_CASE_BODY(api_error__from_database) +{ + ::sqlite3* raw_db; + ATF_REQUIRE_EQ(SQLITE_CANTOPEN, ::sqlite3_open_v2("missing.db", &raw_db, + SQLITE_OPEN_READONLY, NULL)); + + sqlite::database gate = sqlite::database_c_gate::connect(raw_db); + const sqlite::api_error e = sqlite::api_error::from_database( + gate, "real_function"); + ATF_REQUIRE(std::strcmp("unable to open database file", e.what()) == 0); + ATF_REQUIRE_EQ("real_function", e.api_function()); + + ::sqlite3_close(raw_db); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(invalid_column_error); +ATF_TEST_CASE_BODY(invalid_column_error) +{ + const sqlite::invalid_column_error e("some_name"); + ATF_REQUIRE(std::strcmp("Unknown column 'some_name'", e.what()) == 0); + ATF_REQUIRE_EQ("some_name", e.column_name()); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, error); + + ATF_ADD_TEST_CASE(tcs, api_error__explicit); + ATF_ADD_TEST_CASE(tcs, api_error__from_database); + + ATF_ADD_TEST_CASE(tcs, invalid_column_error); +} diff --git a/external/bsd/kyua-cli/dist/utils/sqlite/statement.cpp b/external/bsd/kyua-cli/dist/utils/sqlite/statement.cpp new file mode 100644 index 000000000..f5a9eef9b --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/sqlite/statement.cpp @@ -0,0 +1,615 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/sqlite/statement.hpp" + +extern "C" { +#include +} + +#include + +#include "utils/defs.hpp" +#include "utils/format/macros.hpp" +#include "utils/logging/macros.hpp" +#include "utils/sanity.hpp" +#include "utils/sqlite/c_gate.hpp" +#include "utils/sqlite/exceptions.hpp" + +namespace sqlite = utils::sqlite; + + +namespace { + + +static sqlite::type c_type_to_cxx(const int) UTILS_PURE; + + +/// Maps a SQLite 3 data type to our own representation. +/// +/// \param original The native SQLite 3 data type. +/// +/// \return Our internal representation for the native data type. +static sqlite::type +c_type_to_cxx(const int original) +{ + switch (original) { + case SQLITE_BLOB: return sqlite::type_blob; + case SQLITE_FLOAT: return sqlite::type_float; + case SQLITE_INTEGER: return sqlite::type_integer; + case SQLITE_NULL: return sqlite::type_null; + case SQLITE_TEXT: return sqlite::type_text; + default: UNREACHABLE_MSG("Unknown data type returned by SQLite 3"); + } + UNREACHABLE; +} + + +/// Handles the return value of a sqlite3_bind_* call. +/// +/// \param db The database the call was made on. +/// \param api_function The name of the sqlite3_bind_* function called. +/// \param error The error code returned by the function; can be SQLITE_OK. +/// +/// \throw std::bad_alloc If there was no memory for the binding. +/// \throw api_error If the binding fails for any other reason. +static void +handle_bind_error(sqlite::database& db, const char* api_function, + const int error) +{ + switch (error) { + case SQLITE_OK: + return; + case SQLITE_RANGE: + UNREACHABLE_MSG("Invalid index for bind argument"); + case SQLITE_NOMEM: + throw std::bad_alloc(); + default: + throw sqlite::api_error::from_database(db, api_function); + } +} + + +} // anonymous namespace + + +/// Internal implementation for sqlite::statement. +struct utils::sqlite::statement::impl { + /// The database this statement belongs to. + sqlite::database& db; + + /// The SQLite 3 internal statement. + ::sqlite3_stmt* stmt; + + /// Cache for the column names in a statement; lazily initialized. + std::map< std::string, int > column_cache; + + /// Constructor. + /// + /// \param db_ The database this statement belongs to. Be aware that we + /// keep a *reference* to the database; in other words, if the database + /// vanishes, this object will become invalid. (It'd be trivial to keep + /// a shallow copy here instead, but I feel that statements that outlive + /// their database represents sloppy programming.) + /// \param stmt_ The SQLite internal statement. + impl(database& db_, ::sqlite3_stmt* stmt_) : + db(db_), + stmt(stmt_) + { + } + + /// Destructor. + /// + /// It is important to keep this as part of the 'impl' class instead of the + /// container class. The 'impl' class is destroyed exactly once (because it + /// is managed by a shared_ptr) and thus releasing the resources here is + /// OK. However, the container class is potentially released many times, + /// which means that we would be double-freeing the internal object and + /// reusing invalid data. + ~impl(void) + { + (void)::sqlite3_finalize(stmt); + } +}; + + +/// Initializes a statement object. +/// +/// This is an internal function. Use database::create_statement() to +/// instantiate one of these objects. +/// +/// \param db The database this statement belongs to. +/// \param raw_stmt A void pointer representing a SQLite native statement of +/// type sqlite3_stmt. +sqlite::statement::statement(database& db, void* raw_stmt) : + _pimpl(new impl(db, static_cast< ::sqlite3_stmt* >(raw_stmt))) +{ +} + + +/// Destructor for the statement. +/// +/// Remember that statements are reference-counted, so the statement will only +/// cease to be valid once its last copy is destroyed. +sqlite::statement::~statement(void) +{ +} + + +/// Executes a statement that is not supposed to return any data. +/// +/// Use this function to execute DDL and INSERT statements; i.e. statements that +/// only have one processing step and deliver no rows. This frees the caller +/// from having to deal with the return value of the step() function. +/// +/// \pre The statement to execute will not produce any rows. +void +sqlite::statement::step_without_results(void) +{ + const bool data = step(); + INV_MSG(!data, "The statement should not have produced any rows, but it " + "did"); +} + + +/// Performs a processing step on the statement. +/// +/// \return True if the statement returned a row; false if the processing has +/// finished. +/// +/// \throw api_error If the processing of the step raises an error. +bool +sqlite::statement::step(void) +{ + const int error = ::sqlite3_step(_pimpl->stmt); + switch (error) { + case SQLITE_DONE: + LD("Step statement; no more rows"); + return false; + case SQLITE_ROW: + LD("Step statement; row available for processing"); + return true; + default: + throw api_error::from_database(_pimpl->db, "sqlite3_step"); + } + UNREACHABLE; +} + + +/// Returns the number of columns in the step result. +/// +/// \return The number of columns available for data retrieval. +int +sqlite::statement::column_count(void) +{ + return ::sqlite3_column_count(_pimpl->stmt); +} + + +/// Returns the name of a particular column in the result. +/// +/// \param index The column to request the name of. +/// +/// \return The name of the requested column. +std::string +sqlite::statement::column_name(const int index) +{ + const char* name = ::sqlite3_column_name(_pimpl->stmt, index); + if (name == NULL) + throw api_error::from_database(_pimpl->db, "sqlite3_column_name"); + return name; +} + + +/// Returns the type of a particular column in the result. +/// +/// \param index The column to request the type of. +/// +/// \return The type of the requested column. +sqlite::type +sqlite::statement::column_type(const int index) +{ + return c_type_to_cxx(::sqlite3_column_type(_pimpl->stmt, index)); +} + + +/// Finds a column by name. +/// +/// \param name The name of the column to search for. +/// +/// \return The column identifier. +/// +/// \throw value_error If the name cannot be found. +int +sqlite::statement::column_id(const char* name) +{ + std::map< std::string, int >& cache = _pimpl->column_cache; + + if (cache.empty()) { + for (int i = 0; i < column_count(); i++) { + const std::string aux_name = column_name(i); + INV(cache.find(aux_name) == cache.end()); + cache[aux_name] = i; + } + } + + const std::map< std::string, int >::const_iterator iter = cache.find(name); + if (iter == cache.end()) + throw invalid_column_error(name); + else + return (*iter).second; +} + + +/// Returns a particular column in the result as a blob. +/// +/// \param index The column to retrieve. +/// +/// \return A block of memory with the blob contents. Note that the pointer +/// returned by this call will be invalidated on the next call to any SQLite API +/// function. +sqlite::blob +sqlite::statement::column_blob(const int index) +{ + PRE(column_type(index) == type_blob); + return blob(::sqlite3_column_blob(_pimpl->stmt, index), + ::sqlite3_column_bytes(_pimpl->stmt, index)); +} + + +/// Returns a particular column in the result as a double. +/// +/// \param index The column to retrieve. +/// +/// \return The double value. +double +sqlite::statement::column_double(const int index) +{ + PRE(column_type(index) == type_float); + return ::sqlite3_column_double(_pimpl->stmt, index); +} + + +/// Returns a particular column in the result as an integer. +/// +/// \param index The column to retrieve. +/// +/// \return The integer value. Note that the value may not fit in an integer +/// depending on the platform. Use column_int64 to retrieve the integer without +/// truncation. +int +sqlite::statement::column_int(const int index) +{ + PRE(column_type(index) == type_integer); + return ::sqlite3_column_int(_pimpl->stmt, index); +} + + +/// Returns a particular column in the result as a 64-bit integer. +/// +/// \param index The column to retrieve. +/// +/// \return The integer value. +int64_t +sqlite::statement::column_int64(const int index) +{ + PRE(column_type(index) == type_integer); + return ::sqlite3_column_int64(_pimpl->stmt, index); +} + + +/// Returns a particular column in the result as a double. +/// +/// \param index The column to retrieve. +/// +/// \return A C string with the contents. Note that the pointer returned by +/// this call will be invalidated on the next call to any SQLite API function. +/// If you want to be extra safe, store the result in a std::string to not worry +/// about this. +std::string +sqlite::statement::column_text(const int index) +{ + PRE(column_type(index) == type_text); + return reinterpret_cast< const char* >(::sqlite3_column_text( + _pimpl->stmt, index)); +} + + +/// Returns the number of bytes stored in the column. +/// +/// \pre This is only valid for columns of type blob and text. +/// +/// \param index The column to retrieve the size of. +/// +/// \return The number of bytes in the column. Remember that strings are stored +/// in their UTF-8 representation; this call returns the number of *bytes*, not +/// characters. +int +sqlite::statement::column_bytes(const int index) +{ + PRE(column_type(index) == type_blob || column_type(index) == type_text); + return ::sqlite3_column_bytes(_pimpl->stmt, index); +} + + +/// Type-checked version of column_blob. +/// +/// \param name The name of the column to retrieve. +/// +/// \return The same as column_blob if the value can be retrieved. +/// +/// \throw error If the type of the cell to retrieve is invalid. +/// \throw invalid_column_error If name is invalid. +sqlite::blob +sqlite::statement::safe_column_blob(const char* name) +{ + const int column = column_id(name); + if (column_type(column) != sqlite::type_blob) + throw sqlite::error(F("Column '%s' is not a blob") % name); + return column_blob(column); +} + + +/// Type-checked version of column_double. +/// +/// \param name The name of the column to retrieve. +/// +/// \return The same as column_double if the value can be retrieved. +/// +/// \throw error If the type of the cell to retrieve is invalid. +/// \throw invalid_column_error If name is invalid. +double +sqlite::statement::safe_column_double(const char* name) +{ + const int column = column_id(name); + if (column_type(column) != sqlite::type_float) + throw sqlite::error(F("Column '%s' is not a float") % name); + return column_double(column); +} + + +/// Type-checked version of column_int. +/// +/// \param name The name of the column to retrieve. +/// +/// \return The same as column_int if the value can be retrieved. +/// +/// \throw error If the type of the cell to retrieve is invalid. +/// \throw invalid_column_error If name is invalid. +int +sqlite::statement::safe_column_int(const char* name) +{ + const int column = column_id(name); + if (column_type(column) != sqlite::type_integer) + throw sqlite::error(F("Column '%s' is not an integer") % name); + return column_int(column); +} + + +/// Type-checked version of column_int64. +/// +/// \param name The name of the column to retrieve. +/// +/// \return The same as column_int64 if the value can be retrieved. +/// +/// \throw error If the type of the cell to retrieve is invalid. +/// \throw invalid_column_error If name is invalid. +int64_t +sqlite::statement::safe_column_int64(const char* name) +{ + const int column = column_id(name); + if (column_type(column) != sqlite::type_integer) + throw sqlite::error(F("Column '%s' is not an integer") % name); + return column_int64(column); +} + + +/// Type-checked version of column_text. +/// +/// \param name The name of the column to retrieve. +/// +/// \return The same as column_text if the value can be retrieved. +/// +/// \throw error If the type of the cell to retrieve is invalid. +/// \throw invalid_column_error If name is invalid. +std::string +sqlite::statement::safe_column_text(const char* name) +{ + const int column = column_id(name); + if (column_type(column) != sqlite::type_text) + throw sqlite::error(F("Column '%s' is not a string") % name); + return column_text(column); +} + + +/// Type-checked version of column_bytes. +/// +/// \param name The name of the column to retrieve the size of. +/// +/// \return The same as column_bytes if the value can be retrieved. +/// +/// \throw error If the type of the cell to retrieve the size of is invalid. +/// \throw invalid_column_error If name is invalid. +int +sqlite::statement::safe_column_bytes(const char* name) +{ + const int column = column_id(name); + if (column_type(column) != sqlite::type_blob && + column_type(column) != sqlite::type_text) + throw sqlite::error(F("Column '%s' is not a blob or a string") % name); + return column_bytes(column); +} + + +/// Resets a statement to allow further processing. +void +sqlite::statement::reset(void) +{ + (void)::sqlite3_reset(_pimpl->stmt); +} + + +/// Binds a blob to a prepared statement. +/// +/// \param index The index of the binding. +/// \param b Description of the blob, which must remain valid during the +/// execution of the statement. +/// +/// \throw api_error If the binding fails. +void +sqlite::statement::bind(const int index, const blob& b) +{ + const int error = ::sqlite3_bind_blob(_pimpl->stmt, index, b.memory, b.size, + SQLITE_STATIC); + handle_bind_error(_pimpl->db, "sqlite3_bind_blob", error); +} + + +/// Binds a double value to a prepared statement. +/// +/// \param index The index of the binding. +/// \param value The double value to bind. +/// +/// \throw api_error If the binding fails. +void +sqlite::statement::bind(const int index, const double value) +{ + const int error = ::sqlite3_bind_double(_pimpl->stmt, index, value); + handle_bind_error(_pimpl->db, "sqlite3_bind_double", error); +} + + +/// Binds an integer value to a prepared statement. +/// +/// \param index The index of the binding. +/// \param value The integer value to bind. +/// +/// \throw api_error If the binding fails. +void +sqlite::statement::bind(const int index, const int value) +{ + const int error = ::sqlite3_bind_int(_pimpl->stmt, index, value); + handle_bind_error(_pimpl->db, "sqlite3_bind_int", error); +} + + +/// Binds a 64-bit integer value to a prepared statement. +/// +/// \param index The index of the binding. +/// \param value The 64-bin integer value to bind. +/// +/// \throw api_error If the binding fails. +void +sqlite::statement::bind(const int index, const int64_t value) +{ + const int error = ::sqlite3_bind_int64(_pimpl->stmt, index, value); + handle_bind_error(_pimpl->db, "sqlite3_bind_int64", error); +} + + +/// Binds a NULL value to a prepared statement. +/// +/// \param index The index of the binding. +/// \param unused_null An instance of the null class. +/// +/// \throw api_error If the binding fails. +void +sqlite::statement::bind(const int index, + const null& UTILS_UNUSED_PARAM(null)) +{ + const int error = ::sqlite3_bind_null(_pimpl->stmt, index); + handle_bind_error(_pimpl->db, "sqlite3_bind_null", error); +} + + +/// Binds a text string to a prepared statement. +/// +/// \param index The index of the binding. +/// \param text The string to bind. SQLite generates an internal copy of this +/// string, so the original string object does not have to remain live. We +/// do this because handling the lifetime of std::string objects is very +/// hard (think about implicit conversions), so it is very easy to shoot +/// ourselves in the foot if we don't do this. +/// +/// \throw api_error If the binding fails. +void +sqlite::statement::bind(const int index, const std::string& text) +{ + const int error = ::sqlite3_bind_text(_pimpl->stmt, index, text.c_str(), + text.length(), SQLITE_TRANSIENT); + handle_bind_error(_pimpl->db, "sqlite3_bind_text", error); +} + + +/// Returns the index of the highest parameter. +/// +/// \return A parameter index. +int +sqlite::statement::bind_parameter_count(void) +{ + return ::sqlite3_bind_parameter_count(_pimpl->stmt); +} + + +/// Returns the index of a named parameter. +/// +/// \param name The name of the parameter to be queried; must exist. +/// +/// \return A parameter index. +int +sqlite::statement::bind_parameter_index(const std::string& name) +{ + const int index = ::sqlite3_bind_parameter_index(_pimpl->stmt, + name.c_str()); + PRE_MSG(index > 0, "Parameter name not in statement"); + return index; +} + + +/// Returns the name of a parameter by index. +/// +/// \param index The index to query; must be valid. +/// +/// \return The name of the parameter. +std::string +sqlite::statement::bind_parameter_name(const int index) +{ + const char* name = ::sqlite3_bind_parameter_name(_pimpl->stmt, index); + PRE_MSG(name != NULL, "Index value out of range or nameless parameter"); + return std::string(name); +} + + +/// Clears any bindings and releases their memory. +void +sqlite::statement::clear_bindings(void) +{ + const int error = ::sqlite3_clear_bindings(_pimpl->stmt); + PRE_MSG(error == SQLITE_OK, "SQLite3 contract has changed; it should " + "only return SQLITE_OK"); +} diff --git a/external/bsd/kyua-cli/dist/utils/sqlite/statement.hpp b/external/bsd/kyua-cli/dist/utils/sqlite/statement.hpp new file mode 100644 index 000000000..a556e3671 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/sqlite/statement.hpp @@ -0,0 +1,146 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file utils/sqlite/statement.hpp +/// Wrapper classes and utilities for SQLite statement processing. +/// +/// This module contains thin RAII wrappers around the SQLite 3 structures +/// representing statements. + +#if !defined(UTILS_SQLITE_STATEMENT_HPP) +#define UTILS_SQLITE_STATEMENT_HPP + +extern "C" { +#include +} + +#include +#include + +namespace utils { +namespace sqlite { + + +class database; + + +/// Representation of the SQLite data types. +enum type { + type_blob, + type_float, + type_integer, + type_null, + type_text, +}; + + +/// Representation of a BLOB. +class blob { +public: + /// Memory representing the contents of the blob, or NULL if empty. + /// + /// This memory must remain valid throughout the life of this object, as we + /// do not grab ownership of the memory. + const void* memory; + + /// Number of bytes in memory. + int size; + + /// Constructs a new blob. + /// + /// \param memory_ Pointer to the contents of the blob. + /// \param size_ The size of memory_. + blob(const void* memory_, const int size_) : + memory(memory_), size(size_) + { + } +}; + + +/// Representation of a SQL NULL value. +class null { +}; + + +/// A RAII model for an SQLite 3 statement. +class statement { + struct impl; + + /// Pointer to the shared internal implementation. + std::tr1::shared_ptr< impl > _pimpl; + + statement(database&, void*); + friend class database; + +public: + ~statement(void); + + bool step(void); + void step_without_results(void); + + int column_count(void); + std::string column_name(const int); + type column_type(const int); + int column_id(const char*); + + blob column_blob(const int); + double column_double(const int); + int column_int(const int); + int64_t column_int64(const int); + std::string column_text(const int); + int column_bytes(const int); + + blob safe_column_blob(const char*); + double safe_column_double(const char*); + int safe_column_int(const char*); + int64_t safe_column_int64(const char*); + std::string safe_column_text(const char*); + int safe_column_bytes(const char*); + + void reset(void); + + void bind(const int, const blob&); + void bind(const int, const double); + void bind(const int, const int); + void bind(const int, const int64_t); + void bind(const int, const null&); + void bind(const int, const std::string&); + template< class T > void bind(const char*, const T&); + + int bind_parameter_count(void); + int bind_parameter_index(const std::string&); + std::string bind_parameter_name(const int); + + void clear_bindings(void); +}; + + +} // namespace sqlite +} // namespace utils + +#endif // !defined(UTILS_SQLITE_STATEMENT_HPP) diff --git a/external/bsd/kyua-cli/dist/utils/sqlite/statement.ipp b/external/bsd/kyua-cli/dist/utils/sqlite/statement.ipp new file mode 100644 index 000000000..9df10d068 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/sqlite/statement.ipp @@ -0,0 +1,52 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#if !defined(UTILS_SQLITE_STATEMENT_IPP) +#define UTILS_SQLITE_STATEMENT_IPP + +#include "utils/sqlite/statement.hpp" + + +/// Binds a value to a parameter of a prepared statement. +/// +/// \param parameter The name of the parameter; must exist. This is a raw C +/// string instead of a std::string because statement parameter names are +/// known at compilation time and the program should really not be +/// constructing them dynamically. +/// \param value The value to bind to the parameter. +/// +/// \throw api_error If the binding fails. +template< class T > +void +utils::sqlite::statement::bind(const char* parameter, const T& value) +{ + bind(bind_parameter_index(parameter), value); +} + + +#endif // !defined(UTILS_SQLITE_STATEMENT_IPP) diff --git a/external/bsd/kyua-cli/dist/utils/sqlite/statement_test.cpp b/external/bsd/kyua-cli/dist/utils/sqlite/statement_test.cpp new file mode 100644 index 000000000..7dc313a9d --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/sqlite/statement_test.cpp @@ -0,0 +1,784 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/sqlite/statement.ipp" + +extern "C" { +#include +} + +#include +#include + +#include + +#include "utils/sqlite/database.hpp" +#include "utils/sqlite/test_utils.hpp" + +namespace sqlite = utils::sqlite; + + +ATF_TEST_CASE_WITHOUT_HEAD(step__ok); +ATF_TEST_CASE_BODY(step__ok) +{ + sqlite::database db = sqlite::database::in_memory(); + sqlite::statement stmt = db.create_statement( + "CREATE TABLE foo (a INTEGER PRIMARY KEY)"); + ATF_REQUIRE_THROW(sqlite::error, db.exec("SELECT * FROM foo")); + ATF_REQUIRE(!stmt.step()); + db.exec("SELECT * FROM foo"); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(step__many); +ATF_TEST_CASE_BODY(step__many) +{ + sqlite::database db = sqlite::database::in_memory(); + create_test_table(raw(db)); + sqlite::statement stmt = db.create_statement( + "SELECT prime FROM test ORDER BY prime"); + for (int i = 0; i < 5; i++) + ATF_REQUIRE(stmt.step()); + ATF_REQUIRE(!stmt.step()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(step__fail); +ATF_TEST_CASE_BODY(step__fail) +{ + sqlite::database db = sqlite::database::in_memory(); + sqlite::statement stmt = db.create_statement( + "CREATE TABLE foo (a INTEGER PRIMARY KEY)"); + ATF_REQUIRE(!stmt.step()); + REQUIRE_API_ERROR("sqlite3_step", stmt.step()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(step_without_results__ok); +ATF_TEST_CASE_BODY(step_without_results__ok) +{ + sqlite::database db = sqlite::database::in_memory(); + sqlite::statement stmt = db.create_statement( + "CREATE TABLE foo (a INTEGER PRIMARY KEY)"); + ATF_REQUIRE_THROW(sqlite::error, db.exec("SELECT * FROM foo")); + stmt.step_without_results(); + db.exec("SELECT * FROM foo"); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(step_without_results__fail); +ATF_TEST_CASE_BODY(step_without_results__fail) +{ + sqlite::database db = sqlite::database::in_memory(); + db.exec("CREATE TABLE foo (a INTEGER PRIMARY KEY)"); + db.exec("INSERT INTO foo VALUES (3)"); + sqlite::statement stmt = db.create_statement( + "INSERT INTO foo VALUES (3)"); + REQUIRE_API_ERROR("sqlite3_step", stmt.step_without_results()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(column_count); +ATF_TEST_CASE_BODY(column_count) +{ + sqlite::database db = sqlite::database::in_memory(); + db.exec("CREATE TABLE foo (a INTEGER PRIMARY KEY, b INTEGER, c TEXT);" + "INSERT INTO foo VALUES (5, 3, 'foo');"); + sqlite::statement stmt = db.create_statement("SELECT * FROM foo"); + ATF_REQUIRE(stmt.step()); + ATF_REQUIRE_EQ(3, stmt.column_count()); + ATF_REQUIRE(!stmt.step()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(column_name__ok); +ATF_TEST_CASE_BODY(column_name__ok) +{ + sqlite::database db = sqlite::database::in_memory(); + db.exec("CREATE TABLE foo (first INTEGER PRIMARY KEY, second TEXT);" + "INSERT INTO foo VALUES (5, 'foo');"); + sqlite::statement stmt = db.create_statement("SELECT * FROM foo"); + ATF_REQUIRE(stmt.step()); + ATF_REQUIRE_EQ("first", stmt.column_name(0)); + ATF_REQUIRE_EQ("second", stmt.column_name(1)); + ATF_REQUIRE(!stmt.step()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(column_name__fail); +ATF_TEST_CASE_BODY(column_name__fail) +{ + sqlite::database db = sqlite::database::in_memory(); + db.exec("CREATE TABLE foo (first INTEGER PRIMARY KEY);" + "INSERT INTO foo VALUES (5);"); + sqlite::statement stmt = db.create_statement("SELECT * FROM foo"); + ATF_REQUIRE(stmt.step()); + ATF_REQUIRE_EQ("first", stmt.column_name(0)); + REQUIRE_API_ERROR("sqlite3_column_name", stmt.column_name(1)); + ATF_REQUIRE(!stmt.step()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(column_type__ok); +ATF_TEST_CASE_BODY(column_type__ok) +{ + sqlite::database db = sqlite::database::in_memory(); + db.exec("CREATE TABLE foo (a_blob BLOB," + " a_float FLOAT," + " an_integer INTEGER," + " a_null BLOB," + " a_text TEXT);" + "INSERT INTO foo VALUES (x'0102', 0.3, 5, NULL, 'foo bar');" + "INSERT INTO foo VALUES (NULL, NULL, NULL, NULL, NULL);"); + sqlite::statement stmt = db.create_statement("SELECT * FROM foo"); + ATF_REQUIRE(stmt.step()); + ATF_REQUIRE(sqlite::type_blob == stmt.column_type(0)); + ATF_REQUIRE(sqlite::type_float == stmt.column_type(1)); + ATF_REQUIRE(sqlite::type_integer == stmt.column_type(2)); + ATF_REQUIRE(sqlite::type_null == stmt.column_type(3)); + ATF_REQUIRE(sqlite::type_text == stmt.column_type(4)); + ATF_REQUIRE(stmt.step()); + for (int i = 0; i < stmt.column_count(); i++) + ATF_REQUIRE(sqlite::type_null == stmt.column_type(i)); + ATF_REQUIRE(!stmt.step()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(column_type__out_of_range); +ATF_TEST_CASE_BODY(column_type__out_of_range) +{ + sqlite::database db = sqlite::database::in_memory(); + db.exec("CREATE TABLE foo (a INTEGER PRIMARY KEY);" + "INSERT INTO foo VALUES (1);"); + sqlite::statement stmt = db.create_statement("SELECT * FROM foo"); + ATF_REQUIRE(stmt.step()); + ATF_REQUIRE(sqlite::type_integer == stmt.column_type(0)); + ATF_REQUIRE(sqlite::type_null == stmt.column_type(1)); + ATF_REQUIRE(sqlite::type_null == stmt.column_type(512)); + ATF_REQUIRE(!stmt.step()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(column_id__ok); +ATF_TEST_CASE_BODY(column_id__ok) +{ + sqlite::database db = sqlite::database::in_memory(); + db.exec("CREATE TABLE foo (bar INTEGER PRIMARY KEY, " + " baz INTEGER);" + "INSERT INTO foo VALUES (1, 2);"); + sqlite::statement stmt = db.create_statement("SELECT * FROM foo"); + ATF_REQUIRE(stmt.step()); + ATF_REQUIRE_EQ(0, stmt.column_id("bar")); + ATF_REQUIRE_EQ(1, stmt.column_id("baz")); + ATF_REQUIRE_EQ(0, stmt.column_id("bar")); + ATF_REQUIRE_EQ(1, stmt.column_id("baz")); + ATF_REQUIRE(!stmt.step()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(column_id__missing); +ATF_TEST_CASE_BODY(column_id__missing) +{ + sqlite::database db = sqlite::database::in_memory(); + db.exec("CREATE TABLE foo (bar INTEGER PRIMARY KEY, " + " baz INTEGER);" + "INSERT INTO foo VALUES (1, 2);"); + sqlite::statement stmt = db.create_statement("SELECT * FROM foo"); + ATF_REQUIRE(stmt.step()); + ATF_REQUIRE_EQ(0, stmt.column_id("bar")); + try { + stmt.column_id("bazo"); + fail("invalid_column_error not raised"); + } catch (const sqlite::invalid_column_error& e) { + ATF_REQUIRE_EQ("bazo", e.column_name()); + } + ATF_REQUIRE(!stmt.step()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(column_blob); +ATF_TEST_CASE_BODY(column_blob) +{ + sqlite::database db = sqlite::database::in_memory(); + db.exec("CREATE TABLE foo (a INTEGER, b BLOB, c INTEGER);" + "INSERT INTO foo VALUES (NULL, x'cafe', NULL);"); + sqlite::statement stmt = db.create_statement("SELECT * FROM foo"); + ATF_REQUIRE(stmt.step()); + const sqlite::blob blob = stmt.column_blob(1); + ATF_REQUIRE_EQ(0xca, static_cast< const uint8_t* >(blob.memory)[0]); + ATF_REQUIRE_EQ(0xfe, static_cast< const uint8_t* >(blob.memory)[1]); + ATF_REQUIRE(!stmt.step()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(column_double); +ATF_TEST_CASE_BODY(column_double) +{ + sqlite::database db = sqlite::database::in_memory(); + db.exec("CREATE TABLE foo (a INTEGER, b DOUBLE, c INTEGER);" + "INSERT INTO foo VALUES (NULL, 0.5, NULL);"); + sqlite::statement stmt = db.create_statement("SELECT * FROM foo"); + ATF_REQUIRE(stmt.step()); + ATF_REQUIRE_EQ(0.5, stmt.column_double(1)); + ATF_REQUIRE(!stmt.step()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(column_int__ok); +ATF_TEST_CASE_BODY(column_int__ok) +{ + sqlite::database db = sqlite::database::in_memory(); + db.exec("CREATE TABLE foo (a TEXT, b INTEGER, c TEXT);" + "INSERT INTO foo VALUES (NULL, 987, NULL);"); + sqlite::statement stmt = db.create_statement("SELECT * FROM foo"); + ATF_REQUIRE(stmt.step()); + ATF_REQUIRE_EQ(987, stmt.column_int(1)); + ATF_REQUIRE(!stmt.step()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(column_int__overflow); +ATF_TEST_CASE_BODY(column_int__overflow) +{ + sqlite::database db = sqlite::database::in_memory(); + db.exec("CREATE TABLE foo (a TEXT, b INTEGER, c TEXT);" + "INSERT INTO foo VALUES (NULL, 4294967419, NULL);"); + sqlite::statement stmt = db.create_statement("SELECT * FROM foo"); + ATF_REQUIRE(stmt.step()); + ATF_REQUIRE_EQ(123, stmt.column_int(1)); + ATF_REQUIRE(!stmt.step()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(column_int64); +ATF_TEST_CASE_BODY(column_int64) +{ + sqlite::database db = sqlite::database::in_memory(); + db.exec("CREATE TABLE foo (a TEXT, b INTEGER, c TEXT);" + "INSERT INTO foo VALUES (NULL, 4294967419, NULL);"); + sqlite::statement stmt = db.create_statement("SELECT * FROM foo"); + ATF_REQUIRE(stmt.step()); + ATF_REQUIRE_EQ(4294967419LL, stmt.column_int64(1)); + ATF_REQUIRE(!stmt.step()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(column_text); +ATF_TEST_CASE_BODY(column_text) +{ + sqlite::database db = sqlite::database::in_memory(); + db.exec("CREATE TABLE foo (a INTEGER, b TEXT, c INTEGER);" + "INSERT INTO foo VALUES (NULL, 'foo bar', NULL);"); + sqlite::statement stmt = db.create_statement("SELECT * FROM foo"); + ATF_REQUIRE(stmt.step()); + ATF_REQUIRE_EQ("foo bar", stmt.column_text(1)); + ATF_REQUIRE(!stmt.step()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(column_bytes__blob); +ATF_TEST_CASE_BODY(column_bytes__blob) +{ + sqlite::database db = sqlite::database::in_memory(); + db.exec("CREATE TABLE foo (a BLOB);" + "INSERT INTO foo VALUES (x'12345678');"); + sqlite::statement stmt = db.create_statement("SELECT * FROM foo"); + ATF_REQUIRE(stmt.step()); + ATF_REQUIRE_EQ(4, stmt.column_bytes(0)); + ATF_REQUIRE(!stmt.step()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(column_bytes__text); +ATF_TEST_CASE_BODY(column_bytes__text) +{ + sqlite::database db = sqlite::database::in_memory(); + db.exec("CREATE TABLE foo (a TEXT);" + "INSERT INTO foo VALUES ('foo bar');"); + sqlite::statement stmt = db.create_statement("SELECT * FROM foo"); + ATF_REQUIRE(stmt.step()); + ATF_REQUIRE_EQ(7, stmt.column_bytes(0)); + ATF_REQUIRE(!stmt.step()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(safe_column_blob__ok); +ATF_TEST_CASE_BODY(safe_column_blob__ok) +{ + sqlite::database db = sqlite::database::in_memory(); + db.exec("CREATE TABLE foo (a INTEGER, b BLOB, c INTEGER);" + "INSERT INTO foo VALUES (NULL, x'cafe', NULL);"); + sqlite::statement stmt = db.create_statement("SELECT * FROM foo"); + ATF_REQUIRE(stmt.step()); + const sqlite::blob blob = stmt.safe_column_blob("b"); + ATF_REQUIRE_EQ(0xca, static_cast< const uint8_t* >(blob.memory)[0]); + ATF_REQUIRE_EQ(0xfe, static_cast< const uint8_t* >(blob.memory)[1]); + ATF_REQUIRE(!stmt.step()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(safe_column_blob__fail); +ATF_TEST_CASE_BODY(safe_column_blob__fail) +{ + sqlite::database db = sqlite::database::in_memory(); + db.exec("CREATE TABLE foo (a INTEGER);" + "INSERT INTO foo VALUES (123);"); + sqlite::statement stmt = db.create_statement("SELECT * FROM foo"); + ATF_REQUIRE(stmt.step()); + ATF_REQUIRE_THROW(sqlite::invalid_column_error, + stmt.safe_column_blob("b")); + ATF_REQUIRE_THROW_RE(sqlite::error, "not a blob", + stmt.safe_column_blob("a")); + ATF_REQUIRE(!stmt.step()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(safe_column_double__ok); +ATF_TEST_CASE_BODY(safe_column_double__ok) +{ + sqlite::database db = sqlite::database::in_memory(); + db.exec("CREATE TABLE foo (a INTEGER, b DOUBLE, c INTEGER);" + "INSERT INTO foo VALUES (NULL, 0.5, NULL);"); + sqlite::statement stmt = db.create_statement("SELECT * FROM foo"); + ATF_REQUIRE(stmt.step()); + ATF_REQUIRE_EQ(0.5, stmt.safe_column_double("b")); + ATF_REQUIRE(!stmt.step()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(safe_column_double__fail); +ATF_TEST_CASE_BODY(safe_column_double__fail) +{ + sqlite::database db = sqlite::database::in_memory(); + db.exec("CREATE TABLE foo (a INTEGER);" + "INSERT INTO foo VALUES (NULL);"); + sqlite::statement stmt = db.create_statement("SELECT * FROM foo"); + ATF_REQUIRE(stmt.step()); + ATF_REQUIRE_THROW(sqlite::invalid_column_error, + stmt.safe_column_double("b")); + ATF_REQUIRE_THROW_RE(sqlite::error, "not a float", + stmt.safe_column_double("a")); + ATF_REQUIRE(!stmt.step()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(safe_column_int__ok); +ATF_TEST_CASE_BODY(safe_column_int__ok) +{ + sqlite::database db = sqlite::database::in_memory(); + db.exec("CREATE TABLE foo (a TEXT, b INTEGER, c TEXT);" + "INSERT INTO foo VALUES (NULL, 987, NULL);"); + sqlite::statement stmt = db.create_statement("SELECT * FROM foo"); + ATF_REQUIRE(stmt.step()); + ATF_REQUIRE_EQ(987, stmt.safe_column_int("b")); + ATF_REQUIRE(!stmt.step()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(safe_column_int__fail); +ATF_TEST_CASE_BODY(safe_column_int__fail) +{ + sqlite::database db = sqlite::database::in_memory(); + db.exec("CREATE TABLE foo (a TEXT);" + "INSERT INTO foo VALUES ('def');"); + sqlite::statement stmt = db.create_statement("SELECT * FROM foo"); + ATF_REQUIRE(stmt.step()); + ATF_REQUIRE_THROW(sqlite::invalid_column_error, + stmt.safe_column_int("b")); + ATF_REQUIRE_THROW_RE(sqlite::error, "not an integer", + stmt.safe_column_int("a")); + ATF_REQUIRE(!stmt.step()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(safe_column_int64__ok); +ATF_TEST_CASE_BODY(safe_column_int64__ok) +{ + sqlite::database db = sqlite::database::in_memory(); + db.exec("CREATE TABLE foo (a TEXT, b INTEGER, c TEXT);" + "INSERT INTO foo VALUES (NULL, 4294967419, NULL);"); + sqlite::statement stmt = db.create_statement("SELECT * FROM foo"); + ATF_REQUIRE(stmt.step()); + ATF_REQUIRE_EQ(4294967419LL, stmt.safe_column_int64("b")); + ATF_REQUIRE(!stmt.step()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(safe_column_int64__fail); +ATF_TEST_CASE_BODY(safe_column_int64__fail) +{ + sqlite::database db = sqlite::database::in_memory(); + db.exec("CREATE TABLE foo (a TEXT);" + "INSERT INTO foo VALUES ('abc');"); + sqlite::statement stmt = db.create_statement("SELECT * FROM foo"); + ATF_REQUIRE(stmt.step()); + ATF_REQUIRE_THROW(sqlite::invalid_column_error, + stmt.safe_column_int64("b")); + ATF_REQUIRE_THROW_RE(sqlite::error, "not an integer", + stmt.safe_column_int64("a")); + ATF_REQUIRE(!stmt.step()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(safe_column_text__ok); +ATF_TEST_CASE_BODY(safe_column_text__ok) +{ + sqlite::database db = sqlite::database::in_memory(); + db.exec("CREATE TABLE foo (a INTEGER, b TEXT, c INTEGER);" + "INSERT INTO foo VALUES (NULL, 'foo bar', NULL);"); + sqlite::statement stmt = db.create_statement("SELECT * FROM foo"); + ATF_REQUIRE(stmt.step()); + ATF_REQUIRE_EQ("foo bar", stmt.safe_column_text("b")); + ATF_REQUIRE(!stmt.step()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(safe_column_text__fail); +ATF_TEST_CASE_BODY(safe_column_text__fail) +{ + sqlite::database db = sqlite::database::in_memory(); + db.exec("CREATE TABLE foo (a INTEGER);" + "INSERT INTO foo VALUES (NULL);"); + sqlite::statement stmt = db.create_statement("SELECT * FROM foo"); + ATF_REQUIRE(stmt.step()); + ATF_REQUIRE_THROW(sqlite::invalid_column_error, + stmt.safe_column_text("b")); + ATF_REQUIRE_THROW_RE(sqlite::error, "not a string", + stmt.safe_column_text("a")); + ATF_REQUIRE(!stmt.step()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(safe_column_bytes__ok__blob); +ATF_TEST_CASE_BODY(safe_column_bytes__ok__blob) +{ + sqlite::database db = sqlite::database::in_memory(); + db.exec("CREATE TABLE foo (a BLOB);" + "INSERT INTO foo VALUES (x'12345678');"); + sqlite::statement stmt = db.create_statement("SELECT * FROM foo"); + ATF_REQUIRE(stmt.step()); + ATF_REQUIRE_EQ(4, stmt.safe_column_bytes("a")); + ATF_REQUIRE(!stmt.step()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(safe_column_bytes__ok__text); +ATF_TEST_CASE_BODY(safe_column_bytes__ok__text) +{ + sqlite::database db = sqlite::database::in_memory(); + db.exec("CREATE TABLE foo (a TEXT);" + "INSERT INTO foo VALUES ('foo bar');"); + sqlite::statement stmt = db.create_statement("SELECT * FROM foo"); + ATF_REQUIRE(stmt.step()); + ATF_REQUIRE_EQ(7, stmt.safe_column_bytes("a")); + ATF_REQUIRE(!stmt.step()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(safe_column_bytes__fail); +ATF_TEST_CASE_BODY(safe_column_bytes__fail) +{ + sqlite::database db = sqlite::database::in_memory(); + db.exec("CREATE TABLE foo (a TEXT);" + "INSERT INTO foo VALUES (NULL);"); + sqlite::statement stmt = db.create_statement("SELECT * FROM foo"); + ATF_REQUIRE(stmt.step()); + ATF_REQUIRE_THROW(sqlite::invalid_column_error, + stmt.safe_column_bytes("b")); + ATF_REQUIRE_THROW_RE(sqlite::error, "not a blob or a string", + stmt.safe_column_bytes("a")); + ATF_REQUIRE(!stmt.step()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(reset); +ATF_TEST_CASE_BODY(reset) +{ + sqlite::database db = sqlite::database::in_memory(); + db.exec("CREATE TABLE foo (a TEXT);" + "INSERT INTO foo VALUES ('foo bar');"); + sqlite::statement stmt = db.create_statement("SELECT * FROM foo"); + ATF_REQUIRE(stmt.step()); + ATF_REQUIRE(!stmt.step()); + stmt.reset(); + ATF_REQUIRE(stmt.step()); + ATF_REQUIRE(!stmt.step()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(bind__blob); +ATF_TEST_CASE_BODY(bind__blob) +{ + sqlite::database db = sqlite::database::in_memory(); + sqlite::statement stmt = db.create_statement("SELECT 3, ?"); + + const unsigned char blob[] = {0xca, 0xfe}; + stmt.bind(1, sqlite::blob(static_cast< const void* >(blob), 2)); + ATF_REQUIRE(stmt.step()); + ATF_REQUIRE(sqlite::type_integer == stmt.column_type(0)); + ATF_REQUIRE_EQ(3, stmt.column_int(0)); + ATF_REQUIRE(sqlite::type_blob == stmt.column_type(1)); + const unsigned char* ret_blob = + static_cast< const unsigned char* >(stmt.column_blob(1).memory); + ATF_REQUIRE(std::memcmp(blob, ret_blob, 2) == 0); + ATF_REQUIRE(!stmt.step()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(bind__double); +ATF_TEST_CASE_BODY(bind__double) +{ + sqlite::database db = sqlite::database::in_memory(); + sqlite::statement stmt = db.create_statement("SELECT 3, ?"); + + stmt.bind(1, 0.5); + ATF_REQUIRE(stmt.step()); + ATF_REQUIRE(sqlite::type_integer == stmt.column_type(0)); + ATF_REQUIRE_EQ(3, stmt.column_int(0)); + ATF_REQUIRE(sqlite::type_float == stmt.column_type(1)); + ATF_REQUIRE_EQ(0.5, stmt.column_double(1)); + ATF_REQUIRE(!stmt.step()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(bind__int); +ATF_TEST_CASE_BODY(bind__int) +{ + sqlite::database db = sqlite::database::in_memory(); + sqlite::statement stmt = db.create_statement("SELECT 3, ?"); + + stmt.bind(1, 123); + ATF_REQUIRE(stmt.step()); + ATF_REQUIRE(sqlite::type_integer == stmt.column_type(0)); + ATF_REQUIRE_EQ(3, stmt.column_int(0)); + ATF_REQUIRE(sqlite::type_integer == stmt.column_type(1)); + ATF_REQUIRE_EQ(123, stmt.column_int(1)); + ATF_REQUIRE(!stmt.step()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(bind__int64); +ATF_TEST_CASE_BODY(bind__int64) +{ + sqlite::database db = sqlite::database::in_memory(); + sqlite::statement stmt = db.create_statement("SELECT 3, ?"); + + stmt.bind(1, static_cast< int64_t >(4294967419LL)); + ATF_REQUIRE(stmt.step()); + ATF_REQUIRE(sqlite::type_integer == stmt.column_type(0)); + ATF_REQUIRE_EQ(3, stmt.column_int(0)); + ATF_REQUIRE(sqlite::type_integer == stmt.column_type(1)); + ATF_REQUIRE_EQ(4294967419LL, stmt.column_int64(1)); + ATF_REQUIRE(!stmt.step()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(bind__null); +ATF_TEST_CASE_BODY(bind__null) +{ + sqlite::database db = sqlite::database::in_memory(); + sqlite::statement stmt = db.create_statement("SELECT 3, ?"); + + stmt.bind(1, sqlite::null()); + ATF_REQUIRE(stmt.step()); + ATF_REQUIRE(sqlite::type_integer == stmt.column_type(0)); + ATF_REQUIRE_EQ(3, stmt.column_int(0)); + ATF_REQUIRE(sqlite::type_null == stmt.column_type(1)); + ATF_REQUIRE(!stmt.step()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(bind__text); +ATF_TEST_CASE_BODY(bind__text) +{ + sqlite::database db = sqlite::database::in_memory(); + sqlite::statement stmt = db.create_statement("SELECT 3, ?"); + + const std::string str = "Hello"; + stmt.bind(1, str); + ATF_REQUIRE(stmt.step()); + ATF_REQUIRE(sqlite::type_integer == stmt.column_type(0)); + ATF_REQUIRE_EQ(3, stmt.column_int(0)); + ATF_REQUIRE(sqlite::type_text == stmt.column_type(1)); + ATF_REQUIRE_EQ(str, stmt.column_text(1)); + ATF_REQUIRE(!stmt.step()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(bind__text__transient); +ATF_TEST_CASE_BODY(bind__text__transient) +{ + sqlite::database db = sqlite::database::in_memory(); + sqlite::statement stmt = db.create_statement("SELECT 3, :foo"); + + { + const std::string str = "Hello"; + stmt.bind(":foo", str); + } + + ATF_REQUIRE(stmt.step()); + ATF_REQUIRE(sqlite::type_integer == stmt.column_type(0)); + ATF_REQUIRE_EQ(3, stmt.column_int(0)); + ATF_REQUIRE(sqlite::type_text == stmt.column_type(1)); + ATF_REQUIRE_EQ(std::string("Hello"), stmt.column_text(1)); + ATF_REQUIRE(!stmt.step()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(bind__by_name); +ATF_TEST_CASE_BODY(bind__by_name) +{ + sqlite::database db = sqlite::database::in_memory(); + sqlite::statement stmt = db.create_statement("SELECT 3, :foo"); + + const std::string str = "Hello"; + stmt.bind(":foo", str); + ATF_REQUIRE(stmt.step()); + ATF_REQUIRE(sqlite::type_integer == stmt.column_type(0)); + ATF_REQUIRE_EQ(3, stmt.column_int(0)); + ATF_REQUIRE(sqlite::type_text == stmt.column_type(1)); + ATF_REQUIRE_EQ(str, stmt.column_text(1)); + ATF_REQUIRE(!stmt.step()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(bind_parameter_count); +ATF_TEST_CASE_BODY(bind_parameter_count) +{ + sqlite::database db = sqlite::database::in_memory(); + sqlite::statement stmt = db.create_statement("SELECT 3, ?, ?"); + ATF_REQUIRE_EQ(2, stmt.bind_parameter_count()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(bind_parameter_index); +ATF_TEST_CASE_BODY(bind_parameter_index) +{ + sqlite::database db = sqlite::database::in_memory(); + sqlite::statement stmt = db.create_statement("SELECT 3, :foo, ?, :bar"); + ATF_REQUIRE_EQ(1, stmt.bind_parameter_index(":foo")); + ATF_REQUIRE_EQ(3, stmt.bind_parameter_index(":bar")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(bind_parameter_name); +ATF_TEST_CASE_BODY(bind_parameter_name) +{ + sqlite::database db = sqlite::database::in_memory(); + sqlite::statement stmt = db.create_statement("SELECT 3, :foo, ?, :bar"); + ATF_REQUIRE_EQ(":foo", stmt.bind_parameter_name(1)); + ATF_REQUIRE_EQ(":bar", stmt.bind_parameter_name(3)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(clear_bindings); +ATF_TEST_CASE_BODY(clear_bindings) +{ + sqlite::database db = sqlite::database::in_memory(); + sqlite::statement stmt = db.create_statement("SELECT 3, ?"); + + stmt.bind(1, 5); + ATF_REQUIRE(stmt.step()); + ATF_REQUIRE(sqlite::type_integer == stmt.column_type(0)); + ATF_REQUIRE_EQ(3, stmt.column_int(0)); + ATF_REQUIRE(sqlite::type_integer == stmt.column_type(1)); + ATF_REQUIRE_EQ(5, stmt.column_int(1)); + stmt.clear_bindings(); + stmt.reset(); + + ATF_REQUIRE(stmt.step()); + ATF_REQUIRE(sqlite::type_integer == stmt.column_type(0)); + ATF_REQUIRE_EQ(3, stmt.column_int(0)); + ATF_REQUIRE(sqlite::type_null == stmt.column_type(1)); + + ATF_REQUIRE(!stmt.step()); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, step__ok); + ATF_ADD_TEST_CASE(tcs, step__many); + ATF_ADD_TEST_CASE(tcs, step__fail); + + ATF_ADD_TEST_CASE(tcs, step_without_results__ok); + ATF_ADD_TEST_CASE(tcs, step_without_results__fail); + + ATF_ADD_TEST_CASE(tcs, column_count); + + ATF_ADD_TEST_CASE(tcs, column_name__ok); + ATF_ADD_TEST_CASE(tcs, column_name__fail); + + ATF_ADD_TEST_CASE(tcs, column_type__ok); + ATF_ADD_TEST_CASE(tcs, column_type__out_of_range); + + ATF_ADD_TEST_CASE(tcs, column_id__ok); + ATF_ADD_TEST_CASE(tcs, column_id__missing); + + ATF_ADD_TEST_CASE(tcs, column_blob); + ATF_ADD_TEST_CASE(tcs, column_double); + ATF_ADD_TEST_CASE(tcs, column_int__ok); + ATF_ADD_TEST_CASE(tcs, column_int__overflow); + ATF_ADD_TEST_CASE(tcs, column_int64); + ATF_ADD_TEST_CASE(tcs, column_text); + + ATF_ADD_TEST_CASE(tcs, column_bytes__blob); + ATF_ADD_TEST_CASE(tcs, column_bytes__text); + + ATF_ADD_TEST_CASE(tcs, safe_column_blob__ok); + ATF_ADD_TEST_CASE(tcs, safe_column_blob__fail); + ATF_ADD_TEST_CASE(tcs, safe_column_double__ok); + ATF_ADD_TEST_CASE(tcs, safe_column_double__fail); + ATF_ADD_TEST_CASE(tcs, safe_column_int__ok); + ATF_ADD_TEST_CASE(tcs, safe_column_int__fail); + ATF_ADD_TEST_CASE(tcs, safe_column_int64__ok); + ATF_ADD_TEST_CASE(tcs, safe_column_int64__fail); + ATF_ADD_TEST_CASE(tcs, safe_column_text__ok); + ATF_ADD_TEST_CASE(tcs, safe_column_text__fail); + + ATF_ADD_TEST_CASE(tcs, safe_column_bytes__ok__blob); + ATF_ADD_TEST_CASE(tcs, safe_column_bytes__ok__text); + ATF_ADD_TEST_CASE(tcs, safe_column_bytes__fail); + + ATF_ADD_TEST_CASE(tcs, reset); + + ATF_ADD_TEST_CASE(tcs, bind__blob); + ATF_ADD_TEST_CASE(tcs, bind__double); + ATF_ADD_TEST_CASE(tcs, bind__int64); + ATF_ADD_TEST_CASE(tcs, bind__int); + ATF_ADD_TEST_CASE(tcs, bind__null); + ATF_ADD_TEST_CASE(tcs, bind__text); + ATF_ADD_TEST_CASE(tcs, bind__text__transient); + ATF_ADD_TEST_CASE(tcs, bind__by_name); + + ATF_ADD_TEST_CASE(tcs, bind_parameter_count); + ATF_ADD_TEST_CASE(tcs, bind_parameter_index); + ATF_ADD_TEST_CASE(tcs, bind_parameter_name); + + ATF_ADD_TEST_CASE(tcs, clear_bindings); +} diff --git a/external/bsd/kyua-cli/dist/utils/sqlite/test_utils.hpp b/external/bsd/kyua-cli/dist/utils/sqlite/test_utils.hpp new file mode 100644 index 000000000..d96c960cf --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/sqlite/test_utils.hpp @@ -0,0 +1,151 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file utils/sqlite/test_utils.hpp +/// Utilities for tests of the sqlite modules. +/// +/// This file is intended to be included once, and only once, for every test +/// program that needs it. All the code is herein contained to simplify the +/// dependency chain in the build rules. + +#if !defined(UTILS_SQLITE_TEST_UTILS_HPP) +# define UTILS_SQLITE_TEST_UTILS_HPP +#else +# error "test_utils.hpp can only be included once" +#endif + +#include + +#include + +#include "utils/defs.hpp" +#include "utils/sqlite/c_gate.hpp" +#include "utils/sqlite/exceptions.hpp" + + +namespace { + + +/// Checks that a given expression raises a particular sqlite::api_error. +/// +/// We cannot make any assumptions regarding the error text provided by SQLite, +/// so we resort to checking only which API function raised the error (because +/// our code is the one hardcoding these strings). +/// +/// \param exp_api_function The name of the SQLite 3 C API function that causes +/// the error. +/// \param statement The statement to execute. +#define REQUIRE_API_ERROR(exp_api_function, statement) \ + do { \ + try { \ + statement; \ + ATF_FAIL("api_error not raised by " #statement); \ + } catch (const utils::sqlite::api_error& api_error) { \ + ATF_REQUIRE_EQ(exp_api_function, api_error.api_function()); \ + } \ + } while (0) + + +/// Gets the pointer to the internal sqlite3 of a database object. +/// +/// This is pure syntactic sugar to simplify typing in the test cases. +/// +/// \param db The SQLite database. +/// +/// \return The internal sqlite3 of the input database. +static inline ::sqlite3* +raw(utils::sqlite::database& db) +{ + return utils::sqlite::database_c_gate(db).c_database(); +} + + +/// SQL commands to create a test table. +/// +/// See create_test_table() for more details. +static const char* create_test_table_sql = + "CREATE TABLE test (prime INTEGER PRIMARY KEY);" + "INSERT INTO test (prime) VALUES (1);\n" + "INSERT INTO test (prime) VALUES (2);\n" + "INSERT INTO test (prime) VALUES (7);\n" + "INSERT INTO test (prime) VALUES (5);\n" + "INSERT INTO test (prime) VALUES (3);\n"; + + +static void create_test_table(::sqlite3*) UTILS_UNUSED; + + +/// Creates a 'test' table in a database. +/// +/// The created 'test' table is populated with a few rows. If there are any +/// problems creating the database, this fails the test case. +/// +/// Use the verify_test_table() function on the same database to verify that +/// the table is present and contains the expected data. +/// +/// \param db The database in which to create the test table. +static void +create_test_table(::sqlite3* db) +{ + std::cout << "Creating 'test' table in the database\n"; + ATF_REQUIRE_EQ(SQLITE_OK, ::sqlite3_exec(db, create_test_table_sql, + NULL, NULL, NULL)); +} + + +static void verify_test_table(::sqlite3*) UTILS_UNUSED; + + +/// Verifies that the specified database contains the 'test' table. +/// +/// This function ensures that the provided database contains the 'test' table +/// created by the create_test_table() function on the same database. If it +/// doesn't, this fails the caller test case. +/// +/// \param db The database to validate. +static void +verify_test_table(::sqlite3* db) +{ + std::cout << "Verifying that the 'test' table is in the database\n"; + char **result; + int rows, columns; + ATF_REQUIRE_EQ(SQLITE_OK, ::sqlite3_get_table(db, + "SELECT * FROM test ORDER BY prime", &result, &rows, &columns, NULL)); + ATF_REQUIRE_EQ(5, rows); + ATF_REQUIRE_EQ(1, columns); + ATF_REQUIRE_EQ("prime", std::string(result[0])); + ATF_REQUIRE_EQ("1", std::string(result[1])); + ATF_REQUIRE_EQ("2", std::string(result[2])); + ATF_REQUIRE_EQ("3", std::string(result[3])); + ATF_REQUIRE_EQ("5", std::string(result[4])); + ATF_REQUIRE_EQ("7", std::string(result[5])); + ::sqlite3_free_table(result); +} + + +} // anonymous namespace diff --git a/external/bsd/kyua-cli/dist/utils/sqlite/transaction.cpp b/external/bsd/kyua-cli/dist/utils/sqlite/transaction.cpp new file mode 100644 index 000000000..46ded4de2 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/sqlite/transaction.cpp @@ -0,0 +1,141 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/sqlite/transaction.hpp" + +#include "utils/format/macros.hpp" +#include "utils/logging/macros.hpp" +#include "utils/sanity.hpp" +#include "utils/sqlite/database.hpp" +#include "utils/sqlite/exceptions.hpp" +#include "utils/sqlite/statement.ipp" + +namespace sqlite = utils::sqlite; + + +/// Internal implementation for the transaction. +struct utils::sqlite::transaction::impl { + /// The database this transaction belongs to. + database& db; + + /// Possible statuses of a transaction. + enum statuses { + open_status, + committed_status, + rolled_back_status, + }; + + /// The current status of the transaction. + statuses status; + + /// Constructs a new transaction. + /// + /// \param db_ The database this transaction belongs to. + /// \param status_ The status of the new transaction. + impl(database& db_, const statuses status_) : + db(db_), + status(status_) + { + } + + /// Destroys the transaction. + /// + /// This rolls back the transaction if it is open. + ~impl(void) + { + if (status == impl::open_status) { + try { + rollback(); + } catch (const sqlite::error& e) { + LW(F("Error while rolling back a transaction: %s") % e.what()); + } + } + } + + /// Commits the transaction. + /// + /// \throw api_error If there is any problem while committing the + /// transaction. + void + commit(void) + { + PRE(status == impl::open_status); + db.exec("COMMIT"); + status = impl::committed_status; + } + + /// Rolls the transaction back. + /// + /// \throw api_error If there is any problem while rolling the + /// transaction back. + void + rollback(void) + { + PRE(status == impl::open_status); + db.exec("ROLLBACK"); + status = impl::rolled_back_status; + } +}; + + +/// Initializes a transaction object. +/// +/// This is an internal function. Use database::begin_transaction() to +/// instantiate one of these objects. +/// +/// \param db The database this transaction belongs to. +sqlite::transaction::transaction(database& db) : + _pimpl(new impl(db, impl::open_status)) +{ +} + + +/// Destructor for the transaction. +sqlite::transaction::~transaction(void) +{ +} + + +/// Commits the transaction. +/// +/// \throw api_error If there is any problem while committing the transaction. +void +sqlite::transaction::commit(void) +{ + _pimpl->commit(); +} + + +/// Rolls the transaction back. +/// +/// \throw api_error If there is any problem while rolling the transaction back. +void +sqlite::transaction::rollback(void) +{ + _pimpl->rollback(); +} diff --git a/external/bsd/kyua-cli/dist/utils/sqlite/transaction.hpp b/external/bsd/kyua-cli/dist/utils/sqlite/transaction.hpp new file mode 100644 index 000000000..9ded63ae5 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/sqlite/transaction.hpp @@ -0,0 +1,68 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file utils/sqlite/transaction.hpp +/// A RAII model for SQLite transactions. + +#if !defined(UTILS_SQLITE_TRANSACTION_HPP) +#define UTILS_SQLITE_TRANSACTION_HPP + +#include + +namespace utils { +namespace sqlite { + + +class database; + + +/// A RAII model for an SQLite 3 statement. +/// +/// A transaction is automatically rolled back when it goes out of scope unless +/// it has been explicitly committed. +class transaction { + struct impl; + + /// Pointer to the shared internal implementation. + std::tr1::shared_ptr< impl > _pimpl; + + explicit transaction(database&); + friend class database; + +public: + ~transaction(void); + + void commit(void); + void rollback(void); +}; + + +} // namespace sqlite +} // namespace utils + +#endif // !defined(UTILS_SQLITE_TRANSACTION_HPP) diff --git a/external/bsd/kyua-cli/dist/utils/sqlite/transaction_test.cpp b/external/bsd/kyua-cli/dist/utils/sqlite/transaction_test.cpp new file mode 100644 index 000000000..a422db682 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/sqlite/transaction_test.cpp @@ -0,0 +1,135 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/sqlite/transaction.hpp" + +#include + +#include "utils/format/macros.hpp" +#include "utils/sqlite/database.hpp" +#include "utils/sqlite/exceptions.hpp" +#include "utils/sqlite/statement.ipp" + +namespace sqlite = utils::sqlite; + + +namespace { + + +/// Ensures that a table has a single specific value in a column. +/// +/// \param db The SQLite database. +/// \param table_name The table to be checked. +/// \param column_name The column to be checked. +/// \param exp_value The value expected to be found in the column. +/// +/// \return True if the column contains a single value and it matches exp_value; +/// false if not. If the query fails, the calling test is marked as bad. +static bool +check_in_table(sqlite::database& db, const char* table_name, + const char* column_name, int exp_value) +{ + sqlite::statement stmt = db.create_statement( + F("SELECT * FROM %s WHERE %s == %s") % table_name % column_name % + exp_value); + if (!stmt.step()) + return false; + if (stmt.step()) + ATF_FAIL("More than one value found in table"); + return true; +} + + +} // anonymous namespace + + +ATF_TEST_CASE_WITHOUT_HEAD(automatic_rollback); +ATF_TEST_CASE_BODY(automatic_rollback) +{ + sqlite::database db = sqlite::database::in_memory(); + db.exec("CREATE TABLE t (col INTEGER PRIMARY KEY)"); + db.exec("INSERT INTO t VALUES (3)"); + { + sqlite::transaction tx = db.begin_transaction(); + db.exec("INSERT INTO t VALUES (5)"); + } + ATF_REQUIRE( check_in_table(db, "t", "col", 3)); + ATF_REQUIRE(!check_in_table(db, "t", "col", 5)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(explicit_commit); +ATF_TEST_CASE_BODY(explicit_commit) +{ + sqlite::database db = sqlite::database::in_memory(); + db.exec("CREATE TABLE t (col INTEGER PRIMARY KEY)"); + db.exec("INSERT INTO t VALUES (3)"); + { + sqlite::transaction tx = db.begin_transaction(); + db.exec("INSERT INTO t VALUES (5)"); + tx.commit(); + } + ATF_REQUIRE(check_in_table(db, "t", "col", 3)); + ATF_REQUIRE(check_in_table(db, "t", "col", 5)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(explicit_rollback); +ATF_TEST_CASE_BODY(explicit_rollback) +{ + sqlite::database db = sqlite::database::in_memory(); + db.exec("CREATE TABLE t (col INTEGER PRIMARY KEY)"); + db.exec("INSERT INTO t VALUES (3)"); + { + sqlite::transaction tx = db.begin_transaction(); + db.exec("INSERT INTO t VALUES (5)"); + tx.rollback(); + } + ATF_REQUIRE( check_in_table(db, "t", "col", 3)); + ATF_REQUIRE(!check_in_table(db, "t", "col", 5)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(nested_fail); +ATF_TEST_CASE_BODY(nested_fail) +{ + sqlite::database db = sqlite::database::in_memory(); + { + sqlite::transaction tx = db.begin_transaction(); + ATF_REQUIRE_THROW(sqlite::error, db.begin_transaction()); + } +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, automatic_rollback); + ATF_ADD_TEST_CASE(tcs, explicit_commit); + ATF_ADD_TEST_CASE(tcs, explicit_rollback); + ATF_ADD_TEST_CASE(tcs, nested_fail); +} diff --git a/external/bsd/kyua-cli/dist/utils/stream.cpp b/external/bsd/kyua-cli/dist/utils/stream.cpp new file mode 100644 index 000000000..e096c571c --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/stream.cpp @@ -0,0 +1,83 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/stream.hpp" + +#include +#include + +#include "utils/format/macros.hpp" +#include "utils/sanity.hpp" + + +/// Gets the length of a stream. +/// +/// \param is The input stream for which to calculate its length. +/// +/// \return The length of the stream. This is of size_t type instead of +/// directly std::streampos to simplify the caller. Some systems do not +/// support comparing a std::streampos directly to an integer (see +/// NetBSD 1.5.x), which is what we often want to do. +/// +/// \throw std::exception If calculating the length fails due to a stream error. +std::size_t +utils::stream_length(std::istream& is) +{ + const std::streampos current_pos = is.tellg(); + try { + is.seekg(0, std::ios::end); + const std::streampos length = is.tellg(); + is.seekg(current_pos, std::ios::beg); + return static_cast< std::size_t >(length); + } catch (...) { + is.seekg(current_pos, std::ios::beg); + throw; + } +} + + +/// Reads the whole contents of a stream into memory. +/// +/// \param input The input stream from which to read. +/// +/// \return A plain string containing the raw contents of the file. +std::string +utils::read_stream(std::istream& input) +{ + std::ostringstream buffer; + + char tmp[1024]; + while (input.good()) { + input.read(tmp, sizeof(tmp)); + if (input.good() || input.eof()) { + buffer.write(tmp, input.gcount()); + } + } + + return buffer.str(); +} diff --git a/external/bsd/kyua-cli/dist/utils/stream.hpp b/external/bsd/kyua-cli/dist/utils/stream.hpp new file mode 100644 index 000000000..1b056abc6 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/stream.hpp @@ -0,0 +1,51 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file utils/stream.hpp +/// Stream manipulation utilities. +/// +/// Note that file-manipulation utilities live in utils::fs instead. The +/// utilities here deal with already-open streams. + +#if !defined(UTILS_STREAM_HPP) +#define UTILS_STREAM_HPP + +#include +#include +#include + +namespace utils { + + +std::size_t stream_length(std::istream&); +std::string read_stream(std::istream&); + + +} // namespace utils + +#endif // !defined(UTILS_STREAM_HPP) diff --git a/external/bsd/kyua-cli/dist/utils/stream_test.cpp b/external/bsd/kyua-cli/dist/utils/stream_test.cpp new file mode 100644 index 000000000..929e33cad --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/stream_test.cpp @@ -0,0 +1,81 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/stream.hpp" + +#include + +#include + + +ATF_TEST_CASE_WITHOUT_HEAD(stream_length__empty); +ATF_TEST_CASE_BODY(stream_length__empty) +{ + std::istringstream input(""); + ATF_REQUIRE_EQ(0, utils::stream_length(input)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(stream_length__some); +ATF_TEST_CASE_BODY(stream_length__some) +{ + const std::string contents(8192, 'x'); + std::istringstream input(contents); + ATF_REQUIRE_EQ( + contents.length(), + static_cast< std::string::size_type >(utils::stream_length(input))); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(read_stream__empty); +ATF_TEST_CASE_BODY(read_stream__empty) +{ + std::istringstream input(""); + ATF_REQUIRE_EQ("", utils::read_stream(input)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(read_stream__some); +ATF_TEST_CASE_BODY(read_stream__some) +{ + std::string contents; + for (int i = 0; i < 1000; i++) + contents += "abcdef"; + std::istringstream input(contents); + ATF_REQUIRE_EQ(contents, utils::read_stream(input)); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, stream_length__empty); + ATF_ADD_TEST_CASE(tcs, stream_length__some); + + ATF_ADD_TEST_CASE(tcs, read_stream__empty); + ATF_ADD_TEST_CASE(tcs, read_stream__some); +} diff --git a/external/bsd/kyua-cli/dist/utils/text/Kyuafile b/external/bsd/kyua-cli/dist/utils/text/Kyuafile new file mode 100644 index 000000000..954d446a1 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/text/Kyuafile @@ -0,0 +1,8 @@ +syntax(2) + +test_suite("kyua") + +atf_test_program{name="exceptions_test"} +atf_test_program{name="operations_test"} +atf_test_program{name="table_test"} +atf_test_program{name="templates_test"} diff --git a/external/bsd/kyua-cli/dist/utils/text/exceptions.cpp b/external/bsd/kyua-cli/dist/utils/text/exceptions.cpp new file mode 100644 index 000000000..7dbab5787 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/text/exceptions.cpp @@ -0,0 +1,76 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/text/exceptions.hpp" + +namespace text = utils::text; + + +/// Constructs a new error with a plain-text message. +/// +/// \param message The plain-text error message. +text::error::error(const std::string& message) : + std::runtime_error(message) +{ +} + + +/// Destructor for the error. +text::error::~error(void) throw() +{ +} + + +/// Constructs a new error with a plain-text message. +/// +/// \param message The plain-text error message. +text::syntax_error::syntax_error(const std::string& message) : + error(message) +{ +} + + +/// Destructor for the error. +text::syntax_error::~syntax_error(void) throw() +{ +} + + +/// Constructs a new error with a plain-text message. +/// +/// \param message The plain-text error message. +text::value_error::value_error(const std::string& message) : + error(message) +{ +} + + +/// Destructor for the error. +text::value_error::~value_error(void) throw() +{ +} diff --git a/external/bsd/kyua-cli/dist/utils/text/exceptions.hpp b/external/bsd/kyua-cli/dist/utils/text/exceptions.hpp new file mode 100644 index 000000000..b5e39e3e2 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/text/exceptions.hpp @@ -0,0 +1,69 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file utils/text/exceptions.hpp +/// Exception types raised by the text module. + +#if !defined(UTILS_TEXT_EXCEPTIONS_HPP) +#define UTILS_TEXT_EXCEPTIONS_HPP + +#include + +namespace utils { +namespace text { + + +/// Base exceptions for text errors. +class error : public std::runtime_error { +public: + explicit error(const std::string&); + ~error(void) throw(); +}; + + +/// Exception denoting an error while parsing templates. +class syntax_error : public error { +public: + explicit syntax_error(const std::string&); + ~syntax_error(void) throw(); +}; + + +/// Exception denoting an error in a text value format. +class value_error : public error { +public: + explicit value_error(const std::string&); + ~value_error(void) throw(); +}; + + +} // namespace text +} // namespace utils + + +#endif // !defined(UTILS_TEXT_EXCEPTIONS_HPP) diff --git a/external/bsd/kyua-cli/dist/utils/text/exceptions_test.cpp b/external/bsd/kyua-cli/dist/utils/text/exceptions_test.cpp new file mode 100644 index 000000000..b2e09c5bf --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/text/exceptions_test.cpp @@ -0,0 +1,67 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/text/exceptions.hpp" + +#include + +#include + +namespace text = utils::text; + + +ATF_TEST_CASE_WITHOUT_HEAD(error); +ATF_TEST_CASE_BODY(error) +{ + const text::error e("Some text"); + ATF_REQUIRE(std::strcmp("Some text", e.what()) == 0); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(syntax_error); +ATF_TEST_CASE_BODY(syntax_error) +{ + const text::syntax_error e("Some text"); + ATF_REQUIRE(std::strcmp("Some text", e.what()) == 0); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(value_error); +ATF_TEST_CASE_BODY(value_error) +{ + const text::value_error e("Some text"); + ATF_REQUIRE(std::strcmp("Some text", e.what()) == 0); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, error); + ATF_ADD_TEST_CASE(tcs, syntax_error); + ATF_ADD_TEST_CASE(tcs, value_error); +} diff --git a/external/bsd/kyua-cli/dist/utils/text/operations.cpp b/external/bsd/kyua-cli/dist/utils/text/operations.cpp new file mode 100644 index 000000000..e7d15728c --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/text/operations.cpp @@ -0,0 +1,191 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/text/operations.ipp" + +#include + +#include "utils/format/macros.hpp" +#include "utils/sanity.hpp" + +namespace text = utils::text; + + +/// Surrounds a string with quotes, escaping the quote itself if needed. +/// +/// \param text The string to quote. +/// \param quote The quote character to use. +/// +/// \return The quoted string. +std::string +text::quote(const std::string& text, const char quote) +{ + std::ostringstream quoted; + quoted << quote; + + std::string::size_type start_pos = 0; + std::string::size_type last_pos = text.find(quote); + while (last_pos != std::string::npos) { + quoted << text.substr(start_pos, last_pos - start_pos) << '\\'; + start_pos = last_pos; + last_pos = text.find(quote, start_pos + 1); + } + quoted << text.substr(start_pos); + + quoted << quote; + return quoted.str(); +} + + +/// Fills a paragraph to the specified length. +/// +/// This preserves any sequence of spaces in the input and any possible +/// newlines. Sequences of spaces may be split in half (and thus one space is +/// lost), but the rest of the spaces will be preserved as either trailing or +/// leading spaces. +/// +/// \param input The string to refill. +/// \param target_width The width to refill the paragraph to. +/// +/// \return The refilled paragraph as a sequence of independent lines. +std::vector< std::string > +text::refill(const std::string& input, const std::size_t target_width) +{ + std::vector< std::string > output; + + std::string::size_type start = 0; + while (start < input.length()) { + std::string::size_type width; + if (start + target_width >= input.length()) + width = input.length() - start; + else { + if (input[start + target_width] == ' ') { + width = target_width; + } else { + const std::string::size_type pos = input.find_last_of( + " ", start + target_width - 1); + if (pos == std::string::npos || pos < start + 1) { + width = input.find_first_of(" ", start + target_width); + if (width == std::string::npos) + width = input.length() - start; + else + width -= start; + } else { + width = pos - start; + } + } + } + INV(width != std::string::npos); + INV(start + width <= input.length()); + INV(input[start + width] == ' ' || input[start + width] == '\0'); + output.push_back(input.substr(start, width)); + + start += width + 1; + } + + if (input.empty()) { + INV(output.empty()); + output.push_back(""); + } + + return output; +} + + +/// Fills a paragraph to the specified length. +/// +/// See the documentation for refill() for additional details. +/// +/// \param input The string to refill. +/// \param target_width The width to refill the paragraph to. +/// +/// \return The refilled paragraph as a string with embedded newlines. +std::string +text::refill_as_string(const std::string& input, const std::size_t target_width) +{ + return join(refill(input, target_width), "\n"); +} + + +/// Splits a string into different components. +/// +/// \param str The string to split. +/// \param delimiter The separator to use to split the words. +/// +/// \return The different words in the input string as split by the provided +/// delimiter. +std::vector< std::string > +text::split(const std::string& str, const char delimiter) +{ + std::vector< std::string > words; + if (!str.empty()) { + std::string::size_type pos = str.find(delimiter); + words.push_back(str.substr(0, pos)); + while (pos != std::string::npos) { + ++pos; + const std::string::size_type next = str.find(delimiter, pos); + words.push_back(str.substr(pos, next - pos)); + pos = next; + } + } + return words; +} + + +/// Converts a string to a boolean. +/// +/// \param str The string to convert. +/// +/// \return The converted string, if the input string was valid. +/// +/// \throw std::value_error If the input string does not represent a valid +/// boolean value. +template<> +bool +text::to_type(const std::string& str) +{ + if (str == "true") + return true; + else if (str == "false") + return false; + else + throw value_error(F("Invalid boolean value '%s'") % str); +} + + +/// Identity function for to_type, for genericity purposes. +/// +/// \param str The string to convert. +/// +/// \return The input string. +template<> +std::string +text::to_type(const std::string& str) +{ + return str; +} diff --git a/external/bsd/kyua-cli/dist/utils/text/operations.hpp b/external/bsd/kyua-cli/dist/utils/text/operations.hpp new file mode 100644 index 000000000..09fb381f7 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/text/operations.hpp @@ -0,0 +1,64 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file utils/text/operations.hpp +/// Utilities to manipulate strings. + +#if !defined(UTILS_TEXT_OPERATIONS_HPP) +#define UTILS_TEXT_OPERATIONS_HPP + +#include +#include +#include + +namespace utils { +namespace text { + + +std::string quote(const std::string&, const char); + + +std::vector< std::string > refill(const std::string&, const std::size_t); +std::string refill_as_string(const std::string&, const std::size_t); + +template< typename Collection > +std::string join(const Collection&, const std::string&); +std::vector< std::string > split(const std::string&, const char); + +template< typename Type > +Type to_type(const std::string&); +template<> +bool to_type(const std::string&); +template<> +std::string to_type(const std::string&); + + +} // namespace text +} // namespace utils + +#endif // !defined(UTILS_TEXT_OPERATIONS_HPP) diff --git a/external/bsd/kyua-cli/dist/utils/text/operations.ipp b/external/bsd/kyua-cli/dist/utils/text/operations.ipp new file mode 100644 index 000000000..06b299d19 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/text/operations.ipp @@ -0,0 +1,91 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#if !defined(UTILS_TEXT_OPERATIONS_IPP) +#define UTILS_TEXT_OPERATIONS_IPP + +#include "utils/text/operations.hpp" + +#include + +#include "utils/text/exceptions.hpp" + + +/// Concatenates a collection of strings into a single string. +/// +/// \param strings The collection of strings to concatenate. If the collection +/// is unordered, the ordering in the output is undefined. +/// \param delimiter The delimiter to use to separate the strings. +/// +/// \return The concatenated strings. +template< typename Collection > +std::string +utils::text::join(const Collection& strings, const std::string& delimiter) +{ + std::ostringstream output; + if (strings.size() > 1) { + for (typename Collection::const_iterator iter = strings.begin(); + iter != --strings.end(); ++iter) + output << (*iter) << delimiter; + } + if (strings.size() > 0) + output << *(--strings.end()); + return output.str(); +} + + +/// Converts a string to a native type. +/// +/// \tparam Type The type to convert the string to. An input stream operator +/// must exist to extract such a type from an std::istream. +/// \param str The string to convert. +/// +/// \return The converted string, if the input string was valid. +/// +/// \throw std::value_error If the input string does not represent a valid +/// target type. This exception does not include any details, so the caller +/// must take care to re-raise it with appropriate details. +template< typename Type > +Type +utils::text::to_type(const std::string& str) +{ + if (str.empty()) + throw text::value_error("Empty string"); + if (str[0] == ' ') + throw text::value_error("Invalid value"); + + std::istringstream input(str); + Type value; + input >> value; + if (!input.eof() || input.bad() || input.fail()) + throw text::value_error("Invalid value"); + return value; +} + + +#endif // !defined(UTILS_TEXT_OPERATIONS_IPP) diff --git a/external/bsd/kyua-cli/dist/utils/text/operations_test.cpp b/external/bsd/kyua-cli/dist/utils/text/operations_test.cpp new file mode 100644 index 000000000..d0e760a13 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/text/operations_test.cpp @@ -0,0 +1,361 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/text/operations.ipp" + +#include +#include +#include +#include + +#include + +#include "utils/text/exceptions.hpp" + +namespace text = utils::text; + + +namespace { + + +/// Tests text::refill() on an input string with a range of widths. +/// +/// \param expected The expected refilled paragraph. +/// \param input The input paragraph to be refilled. +/// \param first_width The first width to validate. +/// \param last_width The last width to validate (inclusive). +static void +refill_test(const char* expected, const char* input, + const std::size_t first_width, const std::size_t last_width) +{ + for (std::size_t width = first_width; width <= last_width; ++width) { + const std::vector< std::string > lines = text::split(expected, '\n'); + std::cout << "Breaking at width " << width << '\n'; + ATF_REQUIRE_EQ(expected, text::refill_as_string(input, width)); + ATF_REQUIRE(lines == text::refill(input, width)); + } +} + + +} // anonymous namespace + + +ATF_TEST_CASE_WITHOUT_HEAD(quote__empty); +ATF_TEST_CASE_BODY(quote__empty) +{ + ATF_REQUIRE_EQ("''", text::quote("", '\'')); + ATF_REQUIRE_EQ("##", text::quote("", '#')); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(quote__no_escaping); +ATF_TEST_CASE_BODY(quote__no_escaping) +{ + ATF_REQUIRE_EQ("'Some text\"'", text::quote("Some text\"", '\'')); + ATF_REQUIRE_EQ("#Another'string#", text::quote("Another'string", '#')); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(quote__some_escaping); +ATF_TEST_CASE_BODY(quote__some_escaping) +{ + ATF_REQUIRE_EQ("'Some\\'text'", text::quote("Some'text", '\'')); + ATF_REQUIRE_EQ("#Some\\#text#", text::quote("Some#text", '#')); + + ATF_REQUIRE_EQ("'More than one\\' quote\\''", + text::quote("More than one' quote'", '\'')); + ATF_REQUIRE_EQ("'Multiple quotes \\'\\'\\' together'", + text::quote("Multiple quotes ''' together", '\'')); + + ATF_REQUIRE_EQ("'\\'escape at the beginning'", + text::quote("'escape at the beginning", '\'')); + ATF_REQUIRE_EQ("'escape at the end\\''", + text::quote("escape at the end'", '\'')); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(refill__empty); +ATF_TEST_CASE_BODY(refill__empty) +{ + ATF_REQUIRE_EQ(1, text::refill("", 0).size()); + ATF_REQUIRE(text::refill("", 0)[0].empty()); + ATF_REQUIRE_EQ("", text::refill_as_string("", 0)); + + ATF_REQUIRE_EQ(1, text::refill("", 10).size()); + ATF_REQUIRE(text::refill("", 10)[0].empty()); + ATF_REQUIRE_EQ("", text::refill_as_string("", 10)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(refill__no_changes); +ATF_TEST_CASE_BODY(refill__no_changes) +{ + std::vector< std::string > exp_lines; + exp_lines.push_back("foo bar\nbaz"); + + ATF_REQUIRE(exp_lines == text::refill("foo bar\nbaz", 12)); + ATF_REQUIRE_EQ("foo bar\nbaz", text::refill_as_string("foo bar\nbaz", 12)); + + ATF_REQUIRE(exp_lines == text::refill("foo bar\nbaz", 18)); + ATF_REQUIRE_EQ("foo bar\nbaz", text::refill_as_string("foo bar\nbaz", 80)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(refill__break_one); +ATF_TEST_CASE_BODY(refill__break_one) +{ + refill_test("only break the\nfirst line", "only break the first line", + 14, 19); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(refill__break_one__not_first_word); +ATF_TEST_CASE_BODY(refill__break_one__not_first_word) +{ + refill_test("first-long-word\nother\nwords", "first-long-word other words", + 6, 10); + refill_test("first-long-word\nother words", "first-long-word other words", + 11, 20); + refill_test("first-long-word other\nwords", "first-long-word other words", + 21, 26); + refill_test("first-long-word other words", "first-long-word other words", + 27, 28); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(refill__break_many); +ATF_TEST_CASE_BODY(refill__break_many) +{ + refill_test("this is a long\nparagraph to be\nsplit into\npieces", + "this is a long paragraph to be split into pieces", + 15, 15); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(refill__cannot_break); +ATF_TEST_CASE_BODY(refill__cannot_break) +{ + refill_test("this-is-a-long-string", "this-is-a-long-string", 5, 5); + + refill_test("this is\na-string-with-long-words", + "this is a-string-with-long-words", 10, 10); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(refill__preserve_whitespace); +ATF_TEST_CASE_BODY(refill__preserve_whitespace) +{ + refill_test("foo bar baz ", "foo bar baz ", 80, 80); + refill_test("foo \n bar", "foo bar", 5, 5); + + std::vector< std::string > exp_lines; + exp_lines.push_back("foo \n"); + exp_lines.push_back(" bar"); + ATF_REQUIRE(exp_lines == text::refill("foo \n bar", 5)); + ATF_REQUIRE_EQ("foo \n\n bar", text::refill_as_string("foo \n bar", 5)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(join__empty); +ATF_TEST_CASE_BODY(join__empty) +{ + std::vector< std::string > lines; + ATF_REQUIRE_EQ("", text::join(lines, " ")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(join__one); +ATF_TEST_CASE_BODY(join__one) +{ + std::vector< std::string > lines; + lines.push_back("first line"); + ATF_REQUIRE_EQ("first line", text::join(lines, "*")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(join__several); +ATF_TEST_CASE_BODY(join__several) +{ + std::vector< std::string > lines; + lines.push_back("first abc"); + lines.push_back("second"); + lines.push_back("and last line"); + ATF_REQUIRE_EQ("first abc second and last line", text::join(lines, " ")); + ATF_REQUIRE_EQ("first abc***second***and last line", + text::join(lines, "***")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(join__unordered); +ATF_TEST_CASE_BODY(join__unordered) +{ + std::set< std::string > lines; + lines.insert("first"); + lines.insert("second"); + const std::string joined = text::join(lines, " "); + ATF_REQUIRE(joined == "first second" || joined == "second first"); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(split__empty); +ATF_TEST_CASE_BODY(split__empty) +{ + std::vector< std::string > words = text::split("", ' '); + std::vector< std::string > exp_words; + ATF_REQUIRE(exp_words == words); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(split__one); +ATF_TEST_CASE_BODY(split__one) +{ + std::vector< std::string > words = text::split("foo", ' '); + std::vector< std::string > exp_words; + exp_words.push_back("foo"); + ATF_REQUIRE(exp_words == words); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(split__several__simple); +ATF_TEST_CASE_BODY(split__several__simple) +{ + std::vector< std::string > words = text::split("foo bar baz", ' '); + std::vector< std::string > exp_words; + exp_words.push_back("foo"); + exp_words.push_back("bar"); + exp_words.push_back("baz"); + ATF_REQUIRE(exp_words == words); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(split__several__delimiters); +ATF_TEST_CASE_BODY(split__several__delimiters) +{ + std::vector< std::string > words = text::split("XfooXXbarXXXbazXX", 'X'); + std::vector< std::string > exp_words; + exp_words.push_back(""); + exp_words.push_back("foo"); + exp_words.push_back(""); + exp_words.push_back("bar"); + exp_words.push_back(""); + exp_words.push_back(""); + exp_words.push_back("baz"); + exp_words.push_back(""); + exp_words.push_back(""); + ATF_REQUIRE(exp_words == words); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(to_type__ok__bool); +ATF_TEST_CASE_BODY(to_type__ok__bool) +{ + ATF_REQUIRE( text::to_type< bool >("true")); + ATF_REQUIRE(!text::to_type< bool >("false")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(to_type__ok__numerical); +ATF_TEST_CASE_BODY(to_type__ok__numerical) +{ + ATF_REQUIRE_EQ(12, text::to_type< int >("12")); + ATF_REQUIRE_EQ(18745, text::to_type< int >("18745")); + ATF_REQUIRE_EQ(-12345, text::to_type< int >("-12345")); + + ATF_REQUIRE_EQ(12.0, text::to_type< double >("12")); + ATF_REQUIRE_EQ(12.5, text::to_type< double >("12.5")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(to_type__ok__string); +ATF_TEST_CASE_BODY(to_type__ok__string) +{ + // While this seems redundant, having this particular specialization that + // does nothing allows callers to delegate work to to_type without worrying + // about the particular type being converted. + ATF_REQUIRE_EQ("", text::to_type< std::string >("")); + ATF_REQUIRE_EQ(" abcd ", text::to_type< std::string >(" abcd ")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(to_type__empty); +ATF_TEST_CASE_BODY(to_type__empty) +{ + ATF_REQUIRE_THROW(text::value_error, text::to_type< int >("")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(to_type__invalid__bool); +ATF_TEST_CASE_BODY(to_type__invalid__bool) +{ + ATF_REQUIRE_THROW(text::value_error, text::to_type< bool >("")); + ATF_REQUIRE_THROW(text::value_error, text::to_type< bool >("true ")); + ATF_REQUIRE_THROW(text::value_error, text::to_type< bool >("foo")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(to_type__invalid__numerical); +ATF_TEST_CASE_BODY(to_type__invalid__numerical) +{ + ATF_REQUIRE_THROW(text::value_error, text::to_type< int >(" 3")); + ATF_REQUIRE_THROW(text::value_error, text::to_type< int >("3 ")); + ATF_REQUIRE_THROW(text::value_error, text::to_type< int >("3a")); + ATF_REQUIRE_THROW(text::value_error, text::to_type< int >("a3")); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, quote__empty); + ATF_ADD_TEST_CASE(tcs, quote__no_escaping); + ATF_ADD_TEST_CASE(tcs, quote__some_escaping); + + ATF_ADD_TEST_CASE(tcs, refill__empty); + ATF_ADD_TEST_CASE(tcs, refill__no_changes); + ATF_ADD_TEST_CASE(tcs, refill__break_one); + ATF_ADD_TEST_CASE(tcs, refill__break_one__not_first_word); + ATF_ADD_TEST_CASE(tcs, refill__break_many); + ATF_ADD_TEST_CASE(tcs, refill__cannot_break); + ATF_ADD_TEST_CASE(tcs, refill__preserve_whitespace); + + ATF_ADD_TEST_CASE(tcs, join__empty); + ATF_ADD_TEST_CASE(tcs, join__one); + ATF_ADD_TEST_CASE(tcs, join__several); + ATF_ADD_TEST_CASE(tcs, join__unordered); + + ATF_ADD_TEST_CASE(tcs, split__empty); + ATF_ADD_TEST_CASE(tcs, split__one); + ATF_ADD_TEST_CASE(tcs, split__several__simple); + ATF_ADD_TEST_CASE(tcs, split__several__delimiters); + + ATF_ADD_TEST_CASE(tcs, to_type__ok__bool); + ATF_ADD_TEST_CASE(tcs, to_type__ok__numerical); + ATF_ADD_TEST_CASE(tcs, to_type__ok__string); + ATF_ADD_TEST_CASE(tcs, to_type__empty); + ATF_ADD_TEST_CASE(tcs, to_type__invalid__bool); + ATF_ADD_TEST_CASE(tcs, to_type__invalid__numerical); +} diff --git a/external/bsd/kyua-cli/dist/utils/text/table.cpp b/external/bsd/kyua-cli/dist/utils/text/table.cpp new file mode 100644 index 000000000..f59b9540f --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/text/table.cpp @@ -0,0 +1,428 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/text/table.hpp" + +#include +#include +#include +#include + +#include "utils/sanity.hpp" +#include "utils/text/operations.ipp" + +namespace text = utils::text; + + +namespace { + + +/// Applies user overrides to the column widths of a table. +/// +/// \param table The table from which to calculate the column widths. +/// \param user_widths The column widths provided by the user. This vector must +/// have less or the same number of elements as the columns of the table. +/// Values of width_auto are ignored; any other explicit values are copied +/// to the output widths vector, including width_refill. +/// +/// \return A vector with the widths of the columns of the input table with any +/// user overrides applied. +static text::widths_vector +override_column_widths(const text::table& table, + const text::widths_vector& user_widths) +{ + PRE(user_widths.size() <= table.ncolumns()); + text::widths_vector widths = table.column_widths(); + + // Override the actual width of the columns based on user-specified widths. + for (text::widths_vector::size_type i = 0; i < user_widths.size(); ++i) { + const text::widths_vector::value_type& user_width = user_widths[i]; + if (user_width != text::table_formatter::width_auto) { + PRE_MSG(user_width == text::table_formatter::width_refill || + user_width >= widths[i], + "User-provided column widths must be larger than the " + "column contents (except for the width_refill column)"); + widths[i] = user_width; + } + } + + return widths; +} + + +/// Locates the refill column, if any. +/// +/// \param widths The widths of the columns as returned by +/// override_column_widths(). Note that one of the columns may or may not +/// be width_refill, which is the column we are looking for. +/// +/// \return The index of the refill column with a width_refill width if any, or +/// otherwise the index of the last column (which is the default refill column). +static text::widths_vector::size_type +find_refill_column(const text::widths_vector& widths) +{ + text::widths_vector::size_type i = 0; + for (; i < widths.size(); ++i) { + if (widths[i] == text::table_formatter::width_refill) + return i; + } + return i - 1; +} + + +/// Pads the widths of the table to fit within a maximum width. +/// +/// On output, a column of the widths vector is truncated to a shorter length +/// than its current value, if the total width of the table would exceed the +/// maximum table width. +/// +/// \param [in,out] widths The widths of the columns as returned by +/// override_column_widths(). One of these columns should have a value of +/// width_refill; if not, a default column is refilled. +/// \param user_max_width The target width of the table; must not be zero. +/// \param column_padding The padding between the cells, if any. The target +/// width should be larger than the padding times the number of columns; if +/// that is not the case, we attempt a readjustment here. +static void +refill_widths(text::widths_vector& widths, + const text::widths_vector::value_type user_max_width, + const std::size_t column_padding) +{ + PRE(user_max_width != 0); + + // widths.size() is a proxy for the number of columns of the table. + const std::size_t total_padding = column_padding * (widths.size() - 1); + const text::widths_vector::value_type max_width = std::max( + user_max_width, total_padding) - total_padding; + + const text::widths_vector::size_type refill_column = + find_refill_column(widths); + INV(refill_column < widths.size()); + + text::widths_vector::value_type width = 0; + for (text::widths_vector::size_type i = 0; i < widths.size(); ++i) { + if (i != refill_column) + width += widths[i]; + } + widths[refill_column] = max_width - width; +} + + +/// Pads an input text to a specified width with spaces. +/// +/// \param input The text to add padding to (may be empty). +/// \param length The desired length of the output. +/// \param is_last Whether the text being processed belongs to the last column +/// of a row or not. Values in the last column should not be padded to +/// prevent trailing whitespace on the screen (which affects copy/pasting +/// for example). +/// +/// \return The padded cell. If the input string is longer than the desired +/// length, the input string is returned verbatim. The padded table won't be +/// correct, but we don't expect this to be a common case to worry about. +static std::string +pad_cell(const std::string& input, const std::size_t length, const bool is_last) +{ + if (is_last) + return input; + else { + if (input.length() < length) + return input + std::string(length - input.length(), ' '); + else + return input; + } +} + + +/// Refills a cell and adds it to the output lines. +/// +/// \param row The row containing the cell to be refilled. +/// \param widths The widths of the row. +/// \param column The column being refilled. +/// \param [in,out] textual_rows The output lines as processed so far. This is +/// updated to accomodate for the contents of the refilled cell, extending +/// the rows as necessary. +static void +refill_cell(const text::table_row& row, const text::widths_vector& widths, + const text::table_row::size_type column, + std::vector< text::table_row >& textual_rows) +{ + const std::vector< std::string > rows = text::refill(row[column], + widths[column]); + + if (textual_rows.size() < rows.size()) + textual_rows.resize(rows.size(), text::table_row(row.size())); + + for (std::vector< std::string >::size_type i = 0; i < rows.size(); ++i) { + for (text::table_row::size_type j = 0; j < row.size(); ++j) { + const bool is_last = j == row.size() - 1; + if (j == column) + textual_rows[i][j] = pad_cell(rows[i], widths[j], is_last); + else { + if (textual_rows[i][j].empty()) + textual_rows[i][j] = pad_cell("", widths[j], is_last); + } + } + } +} + + +/// Formats a single table row. +/// +/// \param row The row to format. +/// \param widths The widths of the columns to apply during formatting. Cells +/// wider than the specified width are refilled to attempt to fit in the +/// cell. Cells narrower than the width are right-padded with spaces. +/// \param separator The column separator to use. +/// +/// \return The textual lines that contain the formatted row. +static std::vector< std::string > +format_row(const text::table_row& row, const text::widths_vector& widths, + const std::string& separator) +{ + PRE(row.size() == widths.size()); + + std::vector< text::table_row > textual_rows(1, text::table_row(row.size())); + + for (text::table_row::size_type column = 0; column < row.size(); ++column) { + if (widths[column] > row[column].length()) + textual_rows[0][column] = pad_cell(row[column], widths[column], + column == row.size() - 1); + else + refill_cell(row, widths, column, textual_rows); + } + + std::vector< std::string > lines; + for (std::vector< text::table_row >::const_iterator + iter = textual_rows.begin(); iter != textual_rows.end(); ++iter) { + lines.push_back(text::join(*iter, separator)); + } + return lines; +} + + +} // anonymous namespace + + +/// Constructs a new table. +/// +/// \param ncolumns_ The number of columns that the table will have. +text::table::table(const table_row::size_type ncolumns_) +{ + _column_widths.resize(ncolumns_, 0); +} + + +/// Gets the number of columns in the table. +/// +/// \return The number of columns in the table. This value remains constant +/// during the existence of the table. +text::widths_vector::size_type +text::table::ncolumns(void) const +{ + return _column_widths.size(); +} + + +/// Gets the width of a column. +/// +/// The returned value is not valid if add_row() is called again, as the column +/// may have grown in width. +/// +/// \param column The index of the column of which to get the width. Must be +/// less than the total number of columns. +/// +/// \return The width of a column. +text::widths_vector::value_type +text::table::column_width(const widths_vector::size_type column) const +{ + PRE(column < _column_widths.size()); + return _column_widths[column]; +} + + +/// Gets the widths of all columns. +/// +/// The returned value is not valid if add_row() is called again, as the columns +/// may have grown in width. +/// +/// \return A vector with the width of all columns. +const text::widths_vector& +text::table::column_widths(void) const +{ + return _column_widths; +} + + +/// Checks whether the table is empty or not. +/// +/// \return True if the table is empty; false otherwise. +bool +text::table::empty(void) const +{ + return _rows.empty(); +} + + +/// Adds a row to the table. +/// +/// \param row The row to be added. This row must have the same amount of +/// columns as defined during the construction of the table. +void +text::table::add_row(const table_row& row) +{ + PRE(row.size() == _column_widths.size()); + _rows.push_back(row); + + for (table_row::size_type i = 0; i < row.size(); ++i) + if (_column_widths[i] < row[i].length()) + _column_widths[i] = row[i].length(); +} + + +/// Gets an iterator pointing to the beginning of the rows of the table. +/// +/// \return An iterator on the rows. +text::table::const_iterator +text::table::begin(void) const +{ + return _rows.begin(); +} + + +/// Gets an iterator pointing to the end of the rows of the table. +/// +/// \return An iterator on the rows. +text::table::const_iterator +text::table::end(void) const +{ + return _rows.end(); +} + + +/// Column width to denote that the column has to fit all of its cells. +const std::size_t text::table_formatter::width_auto = 0; + + +/// Column width to denote that the column can be refilled to fit the table. +const std::size_t text::table_formatter::width_refill = + std::numeric_limits< std::size_t >::max(); + + +/// Constructs a new table formatter. +text::table_formatter::table_formatter(void) : + _separator(""), + _table_width(0) +{ +} + + +/// Sets the width of a column. +/// +/// All columns except one must have a width that is, at least, as wide as the +/// widest cell in the column. One of the columns can have a width of +/// width_refill, which indicates that the column will be refilled if the table +/// does not fit in its maximum width. +/// +/// \param column The index of the column to set the width for. +/// \param width The width to set the column to. +/// +/// \return A reference to this formatter to allow using the builder pattern. +text::table_formatter& +text::table_formatter::set_column_width(const table_row::size_type column, + const std::size_t width) +{ +#if !defined(NDEBUG) + if (width == width_refill) { + for (widths_vector::size_type i = 0; i < _column_widths.size(); i++) { + if (i != column) + PRE_MSG(_column_widths[i] != width_refill, + "Only one column width can be set to width_refill"); + } + } +#endif + + if (_column_widths.size() < column + 1) + _column_widths.resize(column + 1, width_auto); + _column_widths[column] = width; + return *this; +} + + +/// Sets the separator to use between the cells. +/// +/// \param separator The separator to use. +/// +/// \return A reference to this formatter to allow using the builder pattern. +text::table_formatter& +text::table_formatter::set_separator(const char* separator) +{ + _separator = separator; + return *this; +} + + +/// Sets the maximum width of the table. +/// +/// \param table_width The maximum width of the table; cannot be zero. +/// +/// \return A reference to this formatter to allow using the builder pattern. +text::table_formatter& +text::table_formatter::set_table_width(const std::size_t table_width) +{ + PRE(table_width > 0); + _table_width = table_width; + return *this; +} + + +/// Formats a table into a collection of textual lines. +/// +/// \param t Table to format. +/// +/// \return A collection of textual lines. +std::vector< std::string > +text::table_formatter::format(const table& t) const +{ + std::vector< std::string > lines; + + if (!t.empty()) { + widths_vector widths = override_column_widths(t, _column_widths); + if (_table_width != 0) + refill_widths(widths, _table_width, _separator.length()); + + for (table::const_iterator iter = t.begin(); iter != t.end(); ++iter) { + const std::vector< std::string > sublines = + format_row(*iter, widths, _separator); + std::copy(sublines.begin(), sublines.end(), + std::back_inserter(lines)); + } + } + + return lines; +} diff --git a/external/bsd/kyua-cli/dist/utils/text/table.hpp b/external/bsd/kyua-cli/dist/utils/text/table.hpp new file mode 100644 index 000000000..87e2626a6 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/text/table.hpp @@ -0,0 +1,131 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file utils/text/table.hpp +/// Table construction and formatting. + +#if !defined(UTILS_TEXT_TABLE_HPP) +#define UTILS_TEXT_TABLE_HPP + +#include +#include +#include + +namespace utils { +namespace text { + + +/// Values of the cells of a particular table row. +typedef std::vector< std::string > table_row; + + +/// Vector of column widths. +typedef std::vector< std::size_t > widths_vector; + + +/// Representation of a table. +/// +/// A table is nothing more than a matrix of rows by columns. The number of +/// columns is hardcoded at construction times, and the rows can be accumulated +/// at a later stage. +/// +/// The only value of this class is a simpler and more natural mechanism of the +/// construction of a table, with additional sanity checks. We could as well +/// just expose the internal data representation to our users. +class table { + /// Widths of the table columns so far. + widths_vector _column_widths; + + /// Type defining the collection of rows in the table. + typedef std::vector< table_row > rows_vector; + + /// The rows of the table. + /// + /// This is actually the matrix representing the table. Every element of + /// this vector (which are vectors themselves) must have _ncolumns items. + rows_vector _rows; + +public: + table(const table_row::size_type); + + widths_vector::size_type ncolumns(void) const; + widths_vector::value_type column_width(const widths_vector::size_type) + const; + const widths_vector& column_widths(void) const; + + void add_row(const table_row&); + + bool empty(void) const; + + /// Constant iterator on the rows of the table. + typedef rows_vector::const_iterator const_iterator; + + const_iterator begin(void) const; + const_iterator end(void) const; +}; + + +/// Settings to format a table. +/// +/// This class implements a builder pattern to construct an object that contains +/// all the knowledge to format a table. Once all the settings have been set, +/// the format() method provides the algorithm to apply such formatting settings +/// to any input table. +class table_formatter { + /// Text to use as the separator between cells. + std::string _separator; + + /// Colletion of widths of the columns of a table. + std::size_t _table_width; + + /// Widths of the table columns. + /// + /// Note that this only includes widths for the column widths explicitly + /// overriden by the caller. In other words, this vector can be shorter + /// than the table passed to the format() method, which is just fine. Any + /// non-specified column widths are assumed to be width_auto. + widths_vector _column_widths; + +public: + table_formatter(void); + + static const std::size_t width_auto; + static const std::size_t width_refill; + table_formatter& set_column_width(const table_row::size_type, + const std::size_t); + table_formatter& set_separator(const char*); + table_formatter& set_table_width(const std::size_t); + + std::vector< std::string > format(const table&) const; +}; + + +} // namespace text +} // namespace utils + +#endif // !defined(UTILS_TEXT_TABLE_HPP) diff --git a/external/bsd/kyua-cli/dist/utils/text/table_test.cpp b/external/bsd/kyua-cli/dist/utils/text/table_test.cpp new file mode 100644 index 000000000..f4be2c3cf --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/text/table_test.cpp @@ -0,0 +1,413 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/text/table.hpp" + +#include + +#include + +#include "utils/text/operations.ipp" + +namespace text = utils::text; + + +/// Performs a check on text::table_formatter. +/// +/// This is provided for test simplicity's sake. Having to match the result of +/// the formatting on a line by line basis would result in too verbose tests +/// (maybe not with C++11, but not using this yet). +/// +/// Because of the flattening of the formatted table into a string, we risk +/// misdetecting problems when the algorithm bundles newlines into the lines of +/// a table. This should not happen, and not accounting for this little detail +/// makes testing so much easier. +/// +/// \param expected Textual representation of the table, as a collection of +/// lines separated by newline characters. +/// \param formatter The formatter to use. +/// \param table The table to format. +static void +table_formatter_check(const std::string& expected, + const text::table_formatter& formatter, + const text::table& table) +{ + ATF_REQUIRE_EQ(expected, text::join(formatter.format(table), "\n") + "\n"); +} + + + +ATF_TEST_CASE_WITHOUT_HEAD(table__ncolumns); +ATF_TEST_CASE_BODY(table__ncolumns) +{ + ATF_REQUIRE_EQ(5, text::table(5).ncolumns()); + ATF_REQUIRE_EQ(10, text::table(10).ncolumns()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(table__column_width); +ATF_TEST_CASE_BODY(table__column_width) +{ + text::table_row row1; + row1.push_back("1234"); + row1.push_back("123456"); + text::table_row row2; + row2.push_back("12"); + row2.push_back("12345678"); + + text::table table(2); + table.add_row(row1); + table.add_row(row2); + + ATF_REQUIRE_EQ(4, table.column_width(0)); + ATF_REQUIRE_EQ(8, table.column_width(1)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(table__column_widths); +ATF_TEST_CASE_BODY(table__column_widths) +{ + text::table_row row1; + row1.push_back("1234"); + row1.push_back("123456"); + text::table_row row2; + row2.push_back("12"); + row2.push_back("12345678"); + + text::table table(2); + table.add_row(row1); + table.add_row(row2); + + ATF_REQUIRE_EQ(4, table.column_widths()[0]); + ATF_REQUIRE_EQ(8, table.column_widths()[1]); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(table__empty); +ATF_TEST_CASE_BODY(table__empty) +{ + text::table table(2); + ATF_REQUIRE(table.empty()); + table.add_row(text::table_row(2)); + ATF_REQUIRE(!table.empty()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(table__iterate); +ATF_TEST_CASE_BODY(table__iterate) +{ + text::table_row row1; + row1.push_back("foo"); + text::table_row row2; + row2.push_back("bar"); + + text::table table(1); + table.add_row(row1); + table.add_row(row2); + + text::table::const_iterator iter = table.begin(); + ATF_REQUIRE(iter != table.end()); + ATF_REQUIRE(row1 == *iter); + ++iter; + ATF_REQUIRE(iter != table.end()); + ATF_REQUIRE(row2 == *iter); + ++iter; + ATF_REQUIRE(iter == table.end()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(table_formatter__empty); +ATF_TEST_CASE_BODY(table_formatter__empty) +{ + ATF_REQUIRE(text::table_formatter().set_separator(" ") + .format(text::table(1)).empty()); + ATF_REQUIRE(text::table_formatter().set_separator(" ") + .format(text::table(10)).empty()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(table_formatter__defaults); +ATF_TEST_CASE_BODY(table_formatter__defaults) +{ + text::table table(3); + { + text::table_row row; + row.push_back("First"); + row.push_back("Second"); + row.push_back("Third"); + table.add_row(row); + } + { + text::table_row row; + row.push_back("Fourth with some text"); + row.push_back("Fifth with some more text"); + row.push_back("Sixth foo"); + table.add_row(row); + } + + table_formatter_check( + "First Second Third\n" + "Fourth with some textFifth with some more textSixth foo\n", + text::table_formatter(), table); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(table_formatter__one_column__no_max_width); +ATF_TEST_CASE_BODY(table_formatter__one_column__no_max_width) +{ + text::table table(1); + { + text::table_row row; + row.push_back("First row with some words"); + table.add_row(row); + } + { + text::table_row row; + row.push_back("Second row with some words"); + table.add_row(row); + } + + table_formatter_check( + "First row with some words\n" + "Second row with some words\n", + text::table_formatter().set_separator(" | "), table); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(table_formatter__one_column__explicit_width); +ATF_TEST_CASE_BODY(table_formatter__one_column__explicit_width) +{ + text::table table(1); + { + text::table_row row; + row.push_back("First row with some words"); + table.add_row(row); + } + { + text::table_row row; + row.push_back("Second row with some words"); + table.add_row(row); + } + + table_formatter_check( + "First row with some words\n" + "Second row with some words\n", + text::table_formatter().set_separator(" | ").set_column_width(0, 1024), + table); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(table_formatter__one_column__max_width); +ATF_TEST_CASE_BODY(table_formatter__one_column__max_width) +{ + text::table table(1); + { + text::table_row row; + row.push_back("First row with some words"); + table.add_row(row); + } + { + text::table_row row; + row.push_back("Second row with some words"); + table.add_row(row); + } + + table_formatter_check( + "First row\nwith some\nwords\n" + "Second row\nwith some\nwords\n", + text::table_formatter().set_separator(" | ").set_table_width(11), + table); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(table_formatter__many_columns__no_max_width); +ATF_TEST_CASE_BODY(table_formatter__many_columns__no_max_width) +{ + text::table table(3); + { + text::table_row row; + row.push_back("First"); + row.push_back("Second"); + row.push_back("Third"); + table.add_row(row); + } + { + text::table_row row; + row.push_back("Fourth with some text"); + row.push_back("Fifth with some more text"); + row.push_back("Sixth foo"); + table.add_row(row); + } + + table_formatter_check( + "First | Second | Third\n" + "Fourth with some text | Fifth with some more text | Sixth foo\n", + text::table_formatter().set_separator(" | "), table); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(table_formatter__many_columns__explicit_width); +ATF_TEST_CASE_BODY(table_formatter__many_columns__explicit_width) +{ + text::table table(3); + { + text::table_row row; + row.push_back("First"); + row.push_back("Second"); + row.push_back("Third"); + table.add_row(row); + } + { + text::table_row row; + row.push_back("Fourth with some text"); + row.push_back("Fifth with some more text"); + row.push_back("Sixth foo"); + table.add_row(row); + } + + table_formatter_check( + "First | Second | Third\n" + "Fourth with some text | Fifth with some more text | Sixth foo\n", + text::table_formatter().set_separator(" | ").set_column_width(0, 23) + .set_column_width(1, 28), table); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(table_formatter__many_columns__max_width); +ATF_TEST_CASE_BODY(table_formatter__many_columns__max_width) +{ + text::table table(3); + { + text::table_row row; + row.push_back("First"); + row.push_back("Second"); + row.push_back("Third"); + table.add_row(row); + } + { + text::table_row row; + row.push_back("Fourth with some text"); + row.push_back("Fifth with some more text"); + row.push_back("Sixth foo"); + table.add_row(row); + } + + table_formatter_check( + "First | Second | Third\n" + "Fourth with some text | Fifth with | Sixth foo\n" + " | some more | \n" + " | text | \n", + text::table_formatter().set_separator(" | ").set_table_width(46) + .set_column_width(1, text::table_formatter::width_refill) + .set_column_width(0, text::table_formatter::width_auto), table); + + table_formatter_check( + "First | Second | Third\n" + "Fourth with some text | Fifth with | Sixth foo\n" + " | some more | \n" + " | text | \n", + text::table_formatter().set_separator(" | ").set_table_width(48) + .set_column_width(1, text::table_formatter::width_refill) + .set_column_width(0, 23), table); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(table_formatter__use_case__cli_help); +ATF_TEST_CASE_BODY(table_formatter__use_case__cli_help) +{ + text::table options_table(2); + { + text::table_row row; + row.push_back("-a a_value"); + row.push_back("This is the description of the first flag"); + options_table.add_row(row); + } + { + text::table_row row; + row.push_back("-b"); + row.push_back("And this is the text for the second flag"); + options_table.add_row(row); + } + + text::table commands_table(2); + { + text::table_row row; + row.push_back("first"); + row.push_back("This is the first command"); + commands_table.add_row(row); + } + { + text::table_row row; + row.push_back("second"); + row.push_back("And this is the second command"); + commands_table.add_row(row); + } + + const text::widths_vector::value_type first_width = + std::max(options_table.column_width(0), commands_table.column_width(0)); + + table_formatter_check( + "-a a_value This is the description\n" + " of the first flag\n" + "-b And this is the text for\n" + " the second flag\n", + text::table_formatter().set_separator(" ").set_table_width(36) + .set_column_width(0, first_width) + .set_column_width(1, text::table_formatter::width_refill), + options_table); + + table_formatter_check( + "first This is the first\n" + " command\n" + "second And this is the second\n" + " command\n", + text::table_formatter().set_separator(" ").set_table_width(36) + .set_column_width(0, first_width) + .set_column_width(1, text::table_formatter::width_refill), + commands_table); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, table__ncolumns); + ATF_ADD_TEST_CASE(tcs, table__column_width); + ATF_ADD_TEST_CASE(tcs, table__column_widths); + ATF_ADD_TEST_CASE(tcs, table__empty); + ATF_ADD_TEST_CASE(tcs, table__iterate); + + ATF_ADD_TEST_CASE(tcs, table_formatter__empty); + ATF_ADD_TEST_CASE(tcs, table_formatter__defaults); + ATF_ADD_TEST_CASE(tcs, table_formatter__one_column__no_max_width); + ATF_ADD_TEST_CASE(tcs, table_formatter__one_column__explicit_width); + ATF_ADD_TEST_CASE(tcs, table_formatter__one_column__max_width); + ATF_ADD_TEST_CASE(tcs, table_formatter__many_columns__no_max_width); + ATF_ADD_TEST_CASE(tcs, table_formatter__many_columns__explicit_width); + ATF_ADD_TEST_CASE(tcs, table_formatter__many_columns__max_width); + ATF_ADD_TEST_CASE(tcs, table_formatter__use_case__cli_help); +} diff --git a/external/bsd/kyua-cli/dist/utils/text/templates.cpp b/external/bsd/kyua-cli/dist/utils/text/templates.cpp new file mode 100644 index 000000000..8b785835f --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/text/templates.cpp @@ -0,0 +1,763 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/text/templates.hpp" + +#include +#include +#include +#include + +#include "utils/format/macros.hpp" +#include "utils/noncopyable.hpp" +#include "utils/sanity.hpp" +#include "utils/text/exceptions.hpp" +#include "utils/text/operations.ipp" + +namespace text = utils::text; + + +namespace { + + +/// Definition of a template statement. +/// +/// A template statement is a particular line in the input file that is +/// preceeded by a template marker. This class provides a high-level +/// representation of the contents of such statement and a mechanism to parse +/// the textual line into this high-level representation. +class statement_def { +public: + /// Types of the known statements. + enum statement_type { + /// Alternative clause of a conditional. + /// + /// Takes no arguments. + type_else, + + /// End of conditional marker. + /// + /// Takes no arguments. + type_endif, + + /// End of loop marker. + /// + /// Takes no arguments. + type_endloop, + + /// Beginning of a conditional. + /// + /// Takes a single argument, which denotes the name of the variable or + /// vector to check for existence. This is the only expression + /// supported. + type_if, + + /// Beginning of a loop over all the elements of a vector. + /// + /// Takes two arguments: the name of the vector over which to iterate + /// and the name of the iterator to later index this vector. + type_loop, + }; + +private: + /// Internal data describing the structure of a particular statement type. + struct type_descriptor { + /// The native type of the statement. + statement_type type; + + /// The expected number of arguments. + unsigned int n_arguments; + + /// Constructs a new type descriptor. + /// + /// \param type_ The native type of the statement. + /// \param n_arguments_ The expected number of arguments. + type_descriptor(const statement_type type_, + const unsigned int n_arguments_) + : type(type_), n_arguments(n_arguments_) + { + } + }; + + /// Mapping of statement type names to their definitions. + typedef std::map< std::string, type_descriptor > types_map; + + /// Description of the different statement types. + /// + /// This static map is initialized once and reused later for any statement + /// lookup. Unfortunately, we cannot perform this initialization in a + /// static manner without C++11. + static types_map _types; + + /// Generates a new types definition map. + /// + /// \return A new types definition map, to be assigned to _types. + static types_map + generate_types_map(void) + { + // If you change this, please edit the comments in the enum above. + types_map types; + types.insert(types_map::value_type( + "else", type_descriptor(type_else, 0))); + types.insert(types_map::value_type( + "endif", type_descriptor(type_endif, 0))); + types.insert(types_map::value_type( + "endloop", type_descriptor(type_endloop, 0))); + types.insert(types_map::value_type( + "if", type_descriptor(type_if, 1))); + types.insert(types_map::value_type( + "loop", type_descriptor(type_loop, 2))); + return types; + } + +public: + /// The type of the statement. + statement_type type; + + /// The arguments to the statement, in textual form. + const std::vector< std::string > arguments; + + /// Creates a new statement. + /// + /// \param type_ The type of the statement. + /// \param arguments_ The arguments to the statement. + statement_def(const statement_type& type_, + const std::vector< std::string >& arguments_) : + type(type_), arguments(arguments_) + { +#if !defined(NDEBUG) + for (types_map::const_iterator iter = _types.begin(); + iter != _types.end(); ++iter) { + const type_descriptor& descriptor = (*iter).second; + if (descriptor.type == type_) { + PRE(descriptor.n_arguments == arguments_.size()); + return; + } + } + UNREACHABLE; +#endif + } + + /// Parses a statement. + /// + /// \param line The textual representation of the statement without any + /// prefix. + /// + /// \return The parsed statement. + /// + /// \throw text::syntax_error If the statement is not correctly defined. + static statement_def + parse(const std::string& line) + { + if (_types.empty()) + _types = generate_types_map(); + + const std::vector< std::string > words = text::split(line, ' '); + if (words.empty()) + throw text::syntax_error("Empty statement"); + + const types_map::const_iterator iter = _types.find(words[0]); + if (iter == _types.end()) + throw text::syntax_error(F("Unknown statement '%s'") % words[0]); + const type_descriptor& descriptor = (*iter).second; + + if (words.size() - 1 != descriptor.n_arguments) + throw text::syntax_error(F("Invalid number of arguments for " + "statement '%s'") % words[0]); + + std::vector< std::string > new_arguments; + new_arguments.resize(words.size() - 1); + std::copy(words.begin() + 1, words.end(), new_arguments.begin()); + + return statement_def(descriptor.type, new_arguments); + } +}; + + +statement_def::types_map statement_def::_types; + + +/// Definition of a loop. +/// +/// This simple structure is used to keep track of the parameters of a loop. +struct loop_def { + /// The name of the vector over which this loop is iterating. + std::string vector; + + /// The name of the iterator defined by this loop. + std::string iterator; + + /// Position in the input to which to rewind to on looping. + /// + /// This position points to the line after the loop statement, not the loop + /// itself. This is one of the reasons why we have this structure, so that + /// we can maintain the data about the loop without having to re-process it. + std::istream::pos_type position; + + /// Constructs a new loop definition. + /// + /// \param vector_ The name of the vector (first argument). + /// \param iterator_ The name of the iterator (second argumnet). + /// \param position_ Position of the next line after the loop statement. + loop_def(const std::string& vector_, const std::string& iterator_, + const std::istream::pos_type position_) : + vector(vector_), iterator(iterator_), position(position_) + { + } +}; + + +/// Stateful class to instantiate the templates in an input stream. +/// +/// The goal of this parser is to scan the input once and not buffer anything in +/// memory. The only exception are loops: loops are reinterpreted on every +/// iteration from the same input file by rewidining the stream to the +/// appropriate position. +class templates_parser : utils::noncopyable { + /// The templates to apply. + /// + /// Note that this is not const because the parser has to have write access + /// to the templates. In particular, it needs to be able to define the + /// iterators as regular variables. + text::templates_def _templates; + + /// Prefix that marks a line as a statement. + const std::string _prefix; + + /// Delimiter to surround an expression instantiation. + const std::string _delimiter; + + /// Whether to skip incoming lines or not. + /// + /// The top of the stack is true whenever we encounter a conditional that + /// evaluates to false or a loop that does not have any iterations left. + /// Under these circumstances, we need to continue scanning the input stream + /// until we find the matching closing endif or endloop construct. + /// + /// This is a stack rather than a plain boolean to allow us deal with + /// if-else clauses. + std::stack< bool > _skip; + + /// Current count of nested conditionals. + unsigned int _if_level; + + /// Level of the top-most conditional that evaluated to false. + unsigned int _exit_if_level; + + /// Current count of nested loops. + unsigned int _loop_level; + + /// Level of the top-most loop that does not have any iterations left. + unsigned int _exit_loop_level; + + /// Information about all the nested loops up to the current point. + std::stack< loop_def > _loops; + + /// Checks if a line is a statement or not. + /// + /// \param line The line to validate. + /// + /// \return True if the line looks like a statement, which is determined by + /// checking if the line starts by the predefined prefix. + bool + is_statement(const std::string& line) + { + return ((line.length() >= _prefix.length() && + line.substr(0, _prefix.length()) == _prefix) && + (line.length() < _delimiter.length() || + line.substr(0, _delimiter.length()) != _delimiter)); + } + + /// Parses a given statement line into a statement definition. + /// + /// \param line The line to validate; it must be a valid statement. + /// + /// \return The parsed statement. + /// + /// \throw text::syntax_error If the input is not a valid statement. + statement_def + parse_statement(const std::string& line) + { + PRE(is_statement(line)); + return statement_def::parse(line.substr(_prefix.length())); + } + + /// Processes a line from the input when not in skip mode. + /// + /// \param line The line to be processed. + /// \param input The input stream from which the line was read. The current + /// position in the stream must be after the line being processed. + /// \param output The output stream into which to write the results. + /// + /// \throw text::syntax_error If the input is not valid. + void + handle_normal(const std::string& line, std::istream& input, + std::ostream& output) + { + if (!is_statement(line)) { + // Fast path. Mostly to avoid an indentation level for the big + // chunk of code below. + output << line << '\n'; + return; + } + + const statement_def statement = parse_statement(line); + + switch (statement.type) { + case statement_def::type_else: + _skip.top() = !_skip.top(); + break; + + case statement_def::type_endif: + _if_level--; + break; + + case statement_def::type_endloop: { + PRE(_loops.size() == _loop_level); + loop_def& loop = _loops.top(); + + const std::size_t next_index = 1 + text::to_type< std::size_t >( + _templates.get_variable(loop.iterator)); + + if (next_index < _templates.get_vector(loop.vector).size()) { + _templates.add_variable(loop.iterator, F("%s") % next_index); + input.seekg(loop.position); + } else { + _loop_level--; + _loops.pop(); + _templates.remove_variable(loop.iterator); + } + } break; + + case statement_def::type_if: { + _if_level++; + const std::string value = _templates.evaluate( + statement.arguments[0]); + if (value.empty() || value == "0" || value == "false") { + _exit_if_level = _if_level; + _skip.push(true); + } else { + _skip.push(false); + } + } break; + + case statement_def::type_loop: { + _loop_level++; + + const loop_def loop(statement.arguments[0], statement.arguments[1], + input.tellg()); + if (_templates.get_vector(loop.vector).empty()) { + _exit_loop_level = _loop_level; + _skip.push(true); + } else { + _templates.add_variable(loop.iterator, "0"); + _loops.push(loop); + _skip.push(false); + } + } break; + } + } + + /// Processes a line from the input when in skip mode. + /// + /// \param line The line to be processed. + /// + /// \throw text::syntax_error If the input is not valid. + void + handle_skip(const std::string& line) + { + PRE(_skip.top()); + + if (!is_statement(line)) + return; + + const statement_def statement = parse_statement(line); + switch (statement.type) { + case statement_def::type_else: + if (_exit_if_level == _if_level) + _skip.top() = !_skip.top(); + break; + + case statement_def::type_endif: + INV(_if_level >= _exit_if_level); + if (_if_level == _exit_if_level) + _skip.top() = false; + _if_level--; + _skip.pop(); + break; + + case statement_def::type_endloop: + INV(_loop_level >= _exit_loop_level); + if (_loop_level == _exit_loop_level) + _skip.top() = false; + _loop_level--; + _skip.pop(); + break; + + case statement_def::type_if: + _if_level++; + _skip.push(true); + break; + + case statement_def::type_loop: + _loop_level++; + _skip.push(true); + break; + + default: + break; + } + } + + /// Evaluates expressions on a given input line. + /// + /// An expression is surrounded by _delimiter on both sides. We scan the + /// string from left to right finding any expressions that may appear, yank + /// them out and call templates_def::evaluate() to get their value. + /// + /// Lonely or unbalanced appearances of _delimiter on the input line are + /// not considered an error, given that the user may actually want to supply + /// that character sequence without being interpreted as a template. + /// + /// \param in_line The input line from which to evaluate expressions. + /// + /// \return The evaluated line. + /// + /// \throw text::syntax_error If the expressions in the line are malformed. + std::string + evaluate(const std::string& in_line) + { + std::string out_line; + + std::string::size_type last_pos = 0; + while (last_pos != std::string::npos) { + const std::string::size_type open_pos = in_line.find( + _delimiter, last_pos); + if (open_pos == std::string::npos) { + out_line += in_line.substr(last_pos); + last_pos = std::string::npos; + } else { + const std::string::size_type close_pos = in_line.find( + _delimiter, open_pos + _delimiter.length()); + if (close_pos == std::string::npos) { + out_line += in_line.substr(last_pos); + last_pos = std::string::npos; + } else { + out_line += in_line.substr(last_pos, open_pos - last_pos); + out_line += _templates.evaluate(in_line.substr( + open_pos + _delimiter.length(), + close_pos - open_pos - _delimiter.length())); + last_pos = close_pos + _delimiter.length(); + } + } + } + + return out_line; + } + +public: + /// Constructs a new template parser. + /// + /// \param templates_ The templates to apply to the processed file. + /// \param prefix_ The prefix that identifies lines as statements. + /// \param delimiter_ Delimiter to surround a variable instantiation. + templates_parser(const text::templates_def& templates_, + const std::string& prefix_, + const std::string& delimiter_) : + _templates(templates_), + _prefix(prefix_), + _delimiter(delimiter_), + _if_level(0), + _exit_if_level(0), + _loop_level(0), + _exit_loop_level(0) + { + } + + /// Applies the templates to a given input. + /// + /// \param input The stream to which to apply the templates. + /// \param output The stream into which to write the results. + /// + /// \throw text::syntax_error If the input is not valid. Note that the + /// is not guaranteed to be unmodified on exit if an error is + /// encountered. + void + instantiate(std::istream& input, std::ostream& output) + { + std::string line; + while (std::getline(input, line).good()) { + if (!_skip.empty() && _skip.top()) + handle_skip(line); + else + handle_normal(evaluate(line), input, output); + } + } +}; + + +} // anonymous namespace + + +/// Constructs an empty templates definition. +text::templates_def::templates_def(void) +{ +} + + +/// Sets a string variable in the templates. +/// +/// If the variable already exists, its value is replaced. This behavior is +/// required to implement iterators, but client code should really not be +/// redefining variables. +/// +/// \pre The variable must not already exist as a vector. +/// +/// \param name The name of the variable to set. +/// \param value The value to set the given variable to. +void +text::templates_def::add_variable(const std::string& name, + const std::string& value) +{ + PRE(_vectors.find(name) == _vectors.end()); + _variables[name] = value; +} + + +/// Unsets a string variable from the templates. +/// +/// Client code has no reason to use this. This is only required to implement +/// proper scoping of loop iterators. +/// +/// \pre The variable must exist. +/// +/// \param name The name of the variable to remove from the templates. +void +text::templates_def::remove_variable(const std::string& name) +{ + PRE(_variables.find(name) != _variables.end()); + _variables.erase(_variables.find(name)); +} + + +/// Creates a new vector in the templates. +/// +/// If the vector already exists, it is cleared. Client code should really not +/// be redefining variables. +/// +/// \pre The vector must not already exist as a variable. +/// +/// \param name The name of the vector to set. +void +text::templates_def::add_vector(const std::string& name) +{ + PRE(_variables.find(name) == _variables.end()); + _vectors[name] = strings_vector(); +} + + +/// Adds a value to an existing vector in the templates. +/// +/// \pre name The vector must exist. +/// +/// \param name The name of the vector to append the value to. +/// \param value The textual value to append to the vector. +void +text::templates_def::add_to_vector(const std::string& name, + const std::string& value) +{ + PRE(_variables.find(name) == _variables.end()); + PRE(_vectors.find(name) != _vectors.end()); + _vectors[name].push_back(value); +} + + +/// Checks whether a given identifier exists as a variable or a vector. +/// +/// This is used to implement the evaluation of conditions in if clauses. +/// +/// \param name The name of the variable or vector. +/// +/// \return True if the given name exists as a variable or a vector; false +/// otherwise. +bool +text::templates_def::exists(const std::string& name) const +{ + return (_variables.find(name) != _variables.end() || + _vectors.find(name) != _vectors.end()); +} + + +/// Gets the value of a variable. +/// +/// \param name The name of the variable. +/// +/// \return The value of the requested variable. +/// +/// \throw text::syntax_error If the variable does not exist. +const std::string& +text::templates_def::get_variable(const std::string& name) const +{ + const variables_map::const_iterator iter = _variables.find(name); + if (iter == _variables.end()) + throw text::syntax_error(F("Unknown variable '%s'") % name); + return (*iter).second; +} + + +/// Gets a vector. +/// +/// \param name The name of the vector. +/// +/// \return A reference to the requested vector. +/// +/// \throw text::syntax_error If the vector does not exist. +const text::templates_def::strings_vector& +text::templates_def::get_vector(const std::string& name) const +{ + const vectors_map::const_iterator iter = _vectors.find(name); + if (iter == _vectors.end()) + throw text::syntax_error(F("Unknown vector '%s'") % name); + return (*iter).second; +} + + +/// Indexes a vector and gets the value. +/// +/// \param name The name of the vector to index. +/// \param index_name The name of a variable representing the index to use. +/// This must be convertible to a natural. +/// +/// \return The value of the vector at the given index. +/// +/// \throw text::syntax_error If the vector does not existor if the index is out +/// of range. +const std::string& +text::templates_def::get_vector(const std::string& name, + const std::string& index_name) const +{ + const strings_vector& vector = get_vector(name); + const std::string& index_str = get_variable(index_name); + + std::size_t index; + try { + index = text::to_type< std::size_t >(index_str); + } catch (const text::syntax_error& e) { + throw text::syntax_error(F("Index '%s' not an integer, value '%s'") % + index_name % index_str); + } + if (index >= vector.size()) + throw text::syntax_error(F("Index '%s' out of range at position '%s'") % + index_name % index); + + return vector[index]; +} + + +/// Evaluates a expression using these templates. +/// +/// An expression is a query on the current templates to fetch a particular +/// value. The value is always returned as a string, as this is how templates +/// are internally stored. +/// +/// \param expression The expression to evaluate. This should not include any +/// of the delimiters used in the user input, as otherwise the expression +/// will not be evaluated properly. +/// +/// \return The result of the expression evaluation as a string. +/// +/// \throw text::syntax_error If there is any problem while evaluating the +/// expression. +std::string +text::templates_def::evaluate(const std::string& expression) const +{ + const std::string::size_type paren_open = expression.find('('); + if (paren_open == std::string::npos) { + return get_variable(expression); + } else { + const std::string::size_type paren_close = expression.find( + ')', paren_open); + if (paren_close == std::string::npos) + throw text::syntax_error(F("Expected ')' in expression '%s')") % + expression); + if (paren_close != expression.length() - 1) + throw text::syntax_error(F("Unexpected text found after ')' in " + "expression '%s'") % expression); + + const std::string arg0 = expression.substr(0, paren_open); + const std::string arg1 = expression.substr( + paren_open + 1, paren_close - paren_open - 1); + if (arg0 == "defined") { + return exists(arg1) ? "true" : "false"; + } else if (arg0 == "length") { + return F("%s") % get_vector(arg1).size(); + } else { + return get_vector(arg0, arg1); + } + } +} + + +/// Applies a set of templates to an input stream. +/// +/// \param templates The templates to use. +/// \param input The input to process. +/// \param output The stream to which to write the processed text. +/// +/// \throw text::syntax_error If there is any problem processing the input. +void +text::instantiate(const templates_def& templates, + std::istream& input, std::ostream& output) +{ + templates_parser parser(templates, "%", "%%"); + parser.instantiate(input, output); +} + + +/// Applies a set of templates to an input file and writes an output file. +/// +/// \param templates The templates to use. +/// \param input_file The path to the input to process. +/// \param output_file The path to the file into which to write the output. +/// +/// \throw text::error If the input or output files cannot be opened. +/// \throw text::syntax_error If there is any problem processing the input. +void +text::instantiate(const templates_def& templates, + const fs::path& input_file, const fs::path& output_file) +{ + std::ifstream input(input_file.c_str()); + if (!input) + throw text::error(F("Failed to open %s for read") % input_file); + + std::ofstream output(output_file.c_str()); + if (!output) + throw text::error(F("Failed to open %s for write") % output_file); + + instantiate(templates, input, output); +} diff --git a/external/bsd/kyua-cli/dist/utils/text/templates.hpp b/external/bsd/kyua-cli/dist/utils/text/templates.hpp new file mode 100644 index 000000000..e48055fde --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/text/templates.hpp @@ -0,0 +1,120 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file utils/text/templates.hpp +/// Custom templating engine for text documents. +/// +/// This module provides a simple mechanism to generate text documents based on +/// templates. The templates are just text files that contain template +/// statements that instruct this processor to perform transformations on the +/// input. +/// +/// While this was originally written to handle HTML templates, it is actually +/// generic enough to handle any kind of text document, hence why it lives +/// within the utils::text library. +/// +/// An example of how the templates look like: +/// +/// %if names +/// List of names +/// ------------- +/// Amount of names: %%length(names)%% +/// Most preferred name: %%preferred_name%% +/// Full list: +/// %loop names iter +/// * %%last_names(iter)%%, %%names(iter)%% +/// %endloop +/// %endif names + +#if !defined(UTILS_TEXT_TEMPLATES_HPP) +#define UTILS_TEXT_TEMPLATES_HPP + +#include +#include +#include +#include +#include + +#include "utils/fs/path.hpp" + +namespace utils { +namespace text { + + +/// Definitions of the templates to apply to a file. +/// +/// This class provides the environment (e.g. the list of variables) that the +/// templating system has to use when generating the output files. This +/// definition is static in the sense that this is what the caller program +/// specifies. +class templates_def { + /// Mapping of variable names to their values. + typedef std::map< std::string, std::string > variables_map; + + /// Collection of global variables available to the templates. + variables_map _variables; + + /// Convenience name for a vector of strings. + typedef std::vector< std::string > strings_vector; + + /// Mapping of vector names to their contents. + /// + /// Ideally, these would be represented as part of the _variables, but we + /// would need a complex mechanism to identify whether a variable is a + /// string or a vector. + typedef std::map< std::string, strings_vector > vectors_map; + + /// Collection of vectors available to the templates. + vectors_map _vectors; + + const std::string& get_vector(const std::string&, const std::string&) const; + +public: + templates_def(void); + + void add_variable(const std::string&, const std::string&); + void remove_variable(const std::string&); + void add_vector(const std::string&); + void add_to_vector(const std::string&, const std::string&); + + bool exists(const std::string&) const; + const std::string& get_variable(const std::string&) const; + const strings_vector& get_vector(const std::string&) const; + + std::string evaluate(const std::string&) const; +}; + + +void instantiate(const templates_def&, std::istream&, std::ostream&); +void instantiate(const templates_def&, const fs::path&, const fs::path&); + + +} // namespace text +} // namespace utils + +#endif // !defined(UTILS_TEXT_TEMPLATES_HPP) diff --git a/external/bsd/kyua-cli/dist/utils/text/templates_test.cpp b/external/bsd/kyua-cli/dist/utils/text/templates_test.cpp new file mode 100644 index 000000000..fa34a0e8e --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/text/templates_test.cpp @@ -0,0 +1,1001 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/text/templates.hpp" + +#include +#include + +#include + +#include "utils/fs/operations.hpp" +#include "utils/fs/path.hpp" +#include "utils/text/exceptions.hpp" + +namespace fs = utils::fs; +namespace text = utils::text; + + +namespace { + + +/// Applies a set of templates to an input string and validates the output. +/// +/// This fails the test case if exp_output does not match the document generated +/// by the application of the templates. +/// +/// \param templates The templates to apply. +/// \param input_str The input document to which to apply the templates. +/// \param exp_output The expected output document. +static void +do_test_ok(const text::templates_def& templates, const std::string& input_str, + const std::string& exp_output) +{ + std::istringstream input(input_str); + std::ostringstream output; + + text::instantiate(templates, input, output); + ATF_REQUIRE_EQ(exp_output, output.str()); +} + + +/// Applies a set of templates to an input string and checks for an error. +/// +/// This fails the test case if the exception raised by the template processing +/// does not match the expected message. +/// +/// \param templates The templates to apply. +/// \param input_str The input document to which to apply the templates. +/// \param exp_message The expected error message in the raised exception. +static void +do_test_fail(const text::templates_def& templates, const std::string& input_str, + const std::string& exp_message) +{ + std::istringstream input(input_str); + std::ostringstream output; + + ATF_REQUIRE_THROW_RE(text::syntax_error, exp_message, + text::instantiate(templates, input, output)); +} + + +} // anonymous namespace + + +ATF_TEST_CASE_WITHOUT_HEAD(templates_def__add_variable__first); +ATF_TEST_CASE_BODY(templates_def__add_variable__first) +{ + text::templates_def templates; + templates.add_variable("the-name", "first-value"); + ATF_REQUIRE_EQ("first-value", templates.get_variable("the-name")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(templates_def__add_variable__replace); +ATF_TEST_CASE_BODY(templates_def__add_variable__replace) +{ + text::templates_def templates; + templates.add_variable("the-name", "first-value"); + templates.add_variable("the-name", "second-value"); + ATF_REQUIRE_EQ("second-value", templates.get_variable("the-name")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(templates_def__remove_variable); +ATF_TEST_CASE_BODY(templates_def__remove_variable) +{ + text::templates_def templates; + templates.add_variable("the-name", "the-value"); + templates.get_variable("the-name"); // Should not throw. + templates.remove_variable("the-name"); + ATF_REQUIRE_THROW(text::syntax_error, templates.get_variable("the-name")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(templates_def__add_vector__first); +ATF_TEST_CASE_BODY(templates_def__add_vector__first) +{ + text::templates_def templates; + templates.add_vector("the-name"); + ATF_REQUIRE(templates.get_vector("the-name").empty()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(templates_def__add_vector__replace); +ATF_TEST_CASE_BODY(templates_def__add_vector__replace) +{ + text::templates_def templates; + templates.add_vector("the-name"); + templates.add_to_vector("the-name", "foo"); + ATF_REQUIRE(!templates.get_vector("the-name").empty()); + templates.add_vector("the-name"); + ATF_REQUIRE(templates.get_vector("the-name").empty()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(templates_def__add_to_vector); +ATF_TEST_CASE_BODY(templates_def__add_to_vector) +{ + text::templates_def templates; + templates.add_vector("the-name"); + ATF_REQUIRE_EQ(0, templates.get_vector("the-name").size()); + templates.add_to_vector("the-name", "first"); + ATF_REQUIRE_EQ(1, templates.get_vector("the-name").size()); + templates.add_to_vector("the-name", "second"); + ATF_REQUIRE_EQ(2, templates.get_vector("the-name").size()); + templates.add_to_vector("the-name", "third"); + ATF_REQUIRE_EQ(3, templates.get_vector("the-name").size()); + + std::vector< std::string > expected; + expected.push_back("first"); + expected.push_back("second"); + expected.push_back("third"); + ATF_REQUIRE(expected == templates.get_vector("the-name")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(templates_def__exists__variable); +ATF_TEST_CASE_BODY(templates_def__exists__variable) +{ + text::templates_def templates; + ATF_REQUIRE(!templates.exists("some-name")); + templates.add_variable("some-name ", "foo"); + ATF_REQUIRE(!templates.exists("some-name")); + templates.add_variable("some-name", "foo"); + ATF_REQUIRE(templates.exists("some-name")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(templates_def__exists__vector); +ATF_TEST_CASE_BODY(templates_def__exists__vector) +{ + text::templates_def templates; + ATF_REQUIRE(!templates.exists("some-name")); + templates.add_vector("some-name "); + ATF_REQUIRE(!templates.exists("some-name")); + templates.add_vector("some-name"); + ATF_REQUIRE(templates.exists("some-name")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(templates_def__get_variable__ok); +ATF_TEST_CASE_BODY(templates_def__get_variable__ok) +{ + text::templates_def templates; + templates.add_variable("foo", ""); + templates.add_variable("bar", " baz "); + ATF_REQUIRE_EQ("", templates.get_variable("foo")); + ATF_REQUIRE_EQ(" baz ", templates.get_variable("bar")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(templates_def__get_variable__unknown); +ATF_TEST_CASE_BODY(templates_def__get_variable__unknown) +{ + text::templates_def templates; + templates.add_variable("foo", ""); + ATF_REQUIRE_THROW_RE(text::syntax_error, "Unknown variable 'foo '", + templates.get_variable("foo ")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(templates_def__get_vector__ok); +ATF_TEST_CASE_BODY(templates_def__get_vector__ok) +{ + text::templates_def templates; + templates.add_vector("foo"); + templates.add_vector("bar"); + templates.add_to_vector("bar", "baz"); + ATF_REQUIRE_EQ(0, templates.get_vector("foo").size()); + ATF_REQUIRE_EQ(1, templates.get_vector("bar").size()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(templates_def__get_vector__unknown); +ATF_TEST_CASE_BODY(templates_def__get_vector__unknown) +{ + text::templates_def templates; + templates.add_vector("foo"); + ATF_REQUIRE_THROW_RE(text::syntax_error, "Unknown vector 'foo '", + templates.get_vector("foo ")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(templates_def__evaluate__variable__ok); +ATF_TEST_CASE_BODY(templates_def__evaluate__variable__ok) +{ + text::templates_def templates; + templates.add_variable("foo", ""); + templates.add_variable("bar", " baz "); + ATF_REQUIRE_EQ("", templates.evaluate("foo")); + ATF_REQUIRE_EQ(" baz ", templates.evaluate("bar")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(templates_def__evaluate__variable__unknown); +ATF_TEST_CASE_BODY(templates_def__evaluate__variable__unknown) +{ + text::templates_def templates; + templates.add_variable("foo", ""); + ATF_REQUIRE_THROW_RE(text::syntax_error, "Unknown variable 'foo1'", + templates.evaluate("foo1")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(templates_def__evaluate__vector__ok); +ATF_TEST_CASE_BODY(templates_def__evaluate__vector__ok) +{ + text::templates_def templates; + templates.add_vector("v"); + templates.add_to_vector("v", "foo"); + templates.add_to_vector("v", "bar"); + templates.add_to_vector("v", "baz"); + + templates.add_variable("index", "0"); + ATF_REQUIRE_EQ("foo", templates.evaluate("v(index)")); + templates.add_variable("index", "1"); + ATF_REQUIRE_EQ("bar", templates.evaluate("v(index)")); + templates.add_variable("index", "2"); + ATF_REQUIRE_EQ("baz", templates.evaluate("v(index)")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(templates_def__evaluate__vector__unknown_vector); +ATF_TEST_CASE_BODY(templates_def__evaluate__vector__unknown_vector) +{ + text::templates_def templates; + templates.add_vector("v"); + templates.add_to_vector("v", "foo"); + templates.add_variable("index", "0"); + ATF_REQUIRE_THROW_RE(text::syntax_error, "Unknown vector 'fooz'", + templates.evaluate("fooz(index)")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(templates_def__evaluate__vector__unknown_index); +ATF_TEST_CASE_BODY(templates_def__evaluate__vector__unknown_index) +{ + text::templates_def templates; + templates.add_vector("v"); + templates.add_to_vector("v", "foo"); + templates.add_variable("index", "0"); + ATF_REQUIRE_THROW_RE(text::syntax_error, "Unknown variable 'indexz'", + templates.evaluate("v(indexz)")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(templates_def__evaluate__vector__out_of_range); +ATF_TEST_CASE_BODY(templates_def__evaluate__vector__out_of_range) +{ + text::templates_def templates; + templates.add_vector("v"); + templates.add_to_vector("v", "foo"); + templates.add_variable("index", "1"); + ATF_REQUIRE_THROW_RE(text::syntax_error, "Index 'index' out of range " + "at position '1'", templates.evaluate("v(index)")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(templates_def__evaluate__defined); +ATF_TEST_CASE_BODY(templates_def__evaluate__defined) +{ + text::templates_def templates; + templates.add_vector("the-variable"); + templates.add_vector("the-vector"); + ATF_REQUIRE_EQ("false", templates.evaluate("defined(the-variabl)")); + ATF_REQUIRE_EQ("false", templates.evaluate("defined(the-vecto)")); + ATF_REQUIRE_EQ("true", templates.evaluate("defined(the-variable)")); + ATF_REQUIRE_EQ("true", templates.evaluate("defined(the-vector)")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(templates_def__evaluate__length__ok); +ATF_TEST_CASE_BODY(templates_def__evaluate__length__ok) +{ + text::templates_def templates; + templates.add_vector("v"); + ATF_REQUIRE_EQ("0", templates.evaluate("length(v)")); + templates.add_to_vector("v", "foo"); + ATF_REQUIRE_EQ("1", templates.evaluate("length(v)")); + templates.add_to_vector("v", "bar"); + ATF_REQUIRE_EQ("2", templates.evaluate("length(v)")); + templates.add_to_vector("v", "baz"); + ATF_REQUIRE_EQ("3", templates.evaluate("length(v)")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(templates_def__evaluate__length__unknown_vector); +ATF_TEST_CASE_BODY(templates_def__evaluate__length__unknown_vector) +{ + text::templates_def templates; + templates.add_vector("foo1"); + ATF_REQUIRE_THROW_RE(text::syntax_error, "Unknown vector 'foo'", + templates.evaluate("length(foo)")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(templates_def__evaluate__parenthesis_error); +ATF_TEST_CASE_BODY(templates_def__evaluate__parenthesis_error) +{ + text::templates_def templates; + ATF_REQUIRE_THROW_RE(text::syntax_error, + "Expected '\\)' in.*'foo\\(abc'", + templates.evaluate("foo(abc")); + ATF_REQUIRE_THROW_RE(text::syntax_error, + "Unexpected text.*'\\)' in.*'a\\(b\\)c'", + templates.evaluate("a(b)c")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(instantiate__empty_input); +ATF_TEST_CASE_BODY(instantiate__empty_input) +{ + const text::templates_def templates; + do_test_ok(templates, "", ""); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(instantiate__value__ok); +ATF_TEST_CASE_BODY(instantiate__value__ok) +{ + const std::string input = + "first line\n" + "%%testvar1%%\n" + "third line\n" + "%%testvar2%% %%testvar3%%%%testvar4%%\n" + "fifth line\n"; + + const std::string exp_output = + "first line\n" + "second line\n" + "third line\n" + "fourth line.\n" + "fifth line\n"; + + text::templates_def templates; + templates.add_variable("testvar1", "second line"); + templates.add_variable("testvar2", "fourth"); + templates.add_variable("testvar3", "line"); + templates.add_variable("testvar4", "."); + + do_test_ok(templates, input, exp_output); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(instantiate__value__unknown_variable); +ATF_TEST_CASE_BODY(instantiate__value__unknown_variable) +{ + const std::string input = + "%%testvar1%%\n"; + + text::templates_def templates; + templates.add_variable("testvar2", "fourth line"); + + do_test_fail(templates, input, "Unknown variable 'testvar1'"); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(instantiate__vector_length__ok); +ATF_TEST_CASE_BODY(instantiate__vector_length__ok) +{ + const std::string input = + "%%length(testvector1)%%\n" + "%%length(testvector2)%% - %%length(testvector3)%%\n"; + + const std::string exp_output = + "4\n" + "0 - 1\n"; + + text::templates_def templates; + templates.add_vector("testvector1"); + templates.add_to_vector("testvector1", "000"); + templates.add_to_vector("testvector1", "111"); + templates.add_to_vector("testvector1", "543"); + templates.add_to_vector("testvector1", "999"); + templates.add_vector("testvector2"); + templates.add_vector("testvector3"); + templates.add_to_vector("testvector3", "123"); + + do_test_ok(templates, input, exp_output); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(instantiate__vector_length__unknown_vector); +ATF_TEST_CASE_BODY(instantiate__vector_length__unknown_vector) +{ + const std::string input = + "%%length(testvector)%%\n"; + + text::templates_def templates; + templates.add_vector("testvector2"); + + do_test_fail(templates, input, "Unknown vector 'testvector'"); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(instantiate__vector_value__ok); +ATF_TEST_CASE_BODY(instantiate__vector_value__ok) +{ + const std::string input = + "first line\n" + "%%testvector1(i)%%\n" + "third line\n" + "%%testvector2(j)%%\n" + "fifth line\n"; + + const std::string exp_output = + "first line\n" + "543\n" + "third line\n" + "123\n" + "fifth line\n"; + + text::templates_def templates; + templates.add_variable("i", "2"); + templates.add_variable("j", "0"); + templates.add_vector("testvector1"); + templates.add_to_vector("testvector1", "000"); + templates.add_to_vector("testvector1", "111"); + templates.add_to_vector("testvector1", "543"); + templates.add_to_vector("testvector1", "999"); + templates.add_vector("testvector2"); + templates.add_to_vector("testvector2", "123"); + + do_test_ok(templates, input, exp_output); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(instantiate__vector_value__unknown_vector); +ATF_TEST_CASE_BODY(instantiate__vector_value__unknown_vector) +{ + const std::string input = + "%%testvector(j)%%\n"; + + text::templates_def templates; + templates.add_vector("testvector2"); + + do_test_fail(templates, input, "Unknown vector 'testvector'"); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(instantiate__vector_value__out_of_range__empty); +ATF_TEST_CASE_BODY(instantiate__vector_value__out_of_range__empty) +{ + const std::string input = + "%%testvector(j)%%\n"; + + text::templates_def templates; + templates.add_vector("testvector"); + templates.add_variable("j", "0"); + + do_test_fail(templates, input, "Index 'j' out of range at position '0'"); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(instantiate__vector_value__out_of_range__not_empty); +ATF_TEST_CASE_BODY(instantiate__vector_value__out_of_range__not_empty) +{ + const std::string input = + "%%testvector(j)%%\n"; + + text::templates_def templates; + templates.add_vector("testvector"); + templates.add_to_vector("testvector", "a"); + templates.add_to_vector("testvector", "b"); + templates.add_variable("j", "2"); + + do_test_fail(templates, input, "Index 'j' out of range at position '2'"); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(instantiate__if__one_level__taken); +ATF_TEST_CASE_BODY(instantiate__if__one_level__taken) +{ + const std::string input = + "first line\n" + "%if defined(some_var)\n" + "hello from within the variable conditional\n" + "%endif\n" + "%if defined(some_vector)\n" + "hello from within the vector conditional\n" + "%else\n" + "bye from within the vector conditional\n" + "%endif\n" + "some more\n"; + + const std::string exp_output = + "first line\n" + "hello from within the variable conditional\n" + "hello from within the vector conditional\n" + "some more\n"; + + text::templates_def templates; + templates.add_variable("some_var", "zzz"); + templates.add_vector("some_vector"); + + do_test_ok(templates, input, exp_output); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(instantiate__if__one_level__not_taken); +ATF_TEST_CASE_BODY(instantiate__if__one_level__not_taken) +{ + const std::string input = + "first line\n" + "%if defined(some_var)\n" + "hello from within the variable conditional\n" + "%endif\n" + "%if defined(some_vector)\n" + "hello from within the vector conditional\n" + "%else\n" + "bye from within the vector conditional\n" + "%endif\n" + "some more\n"; + + const std::string exp_output = + "first line\n" + "bye from within the vector conditional\n" + "some more\n"; + + text::templates_def templates; + + do_test_ok(templates, input, exp_output); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(instantiate__if__multiple_levels__taken); +ATF_TEST_CASE_BODY(instantiate__if__multiple_levels__taken) +{ + const std::string input = + "first line\n" + "%if defined(var1)\n" + "first before\n" + "%if length(var2)\n" + "second before\n" + "%if defined(var3)\n" + "third before\n" + "hello from within the conditional\n" + "third after\n" + "%endif\n" + "second after\n" + "%else\n" + "second after not shown\n" + "%endif\n" + "first after\n" + "%endif\n" + "some more\n"; + + const std::string exp_output = + "first line\n" + "first before\n" + "second before\n" + "third before\n" + "hello from within the conditional\n" + "third after\n" + "second after\n" + "first after\n" + "some more\n"; + + text::templates_def templates; + templates.add_variable("var1", "false"); + templates.add_vector("var2"); + templates.add_to_vector("var2", "not-empty"); + templates.add_variable("var3", "foobar"); + + do_test_ok(templates, input, exp_output); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(instantiate__if__multiple_levels__not_taken); +ATF_TEST_CASE_BODY(instantiate__if__multiple_levels__not_taken) +{ + const std::string input = + "first line\n" + "%if defined(var1)\n" + "first before\n" + "%if length(var2)\n" + "second before\n" + "%if defined(var3)\n" + "third before\n" + "hello from within the conditional\n" + "third after\n" + "%else\n" + "will not be shown either\n" + "%endif\n" + "second after\n" + "%else\n" + "second after shown\n" + "%endif\n" + "first after\n" + "%endif\n" + "some more\n"; + + const std::string exp_output = + "first line\n" + "first before\n" + "second after shown\n" + "first after\n" + "some more\n"; + + text::templates_def templates; + templates.add_variable("var1", "false"); + templates.add_vector("var2"); + templates.add_vector("var3"); + + do_test_ok(templates, input, exp_output); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(instantiate__loop__no_iterations); +ATF_TEST_CASE_BODY(instantiate__loop__no_iterations) +{ + const std::string input = + "first line\n" + "%loop table1 i\n" + "hello\n" + "value in vector: %%table1(i)%%\n" + "%if defined(var1)\n" "some other text\n" "%endif\n" + "%endloop\n" + "some more\n"; + + const std::string exp_output = + "first line\n" + "some more\n"; + + text::templates_def templates; + templates.add_variable("var1", "defined"); + templates.add_vector("table1"); + + do_test_ok(templates, input, exp_output); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(instantiate__loop__multiple_iterations); +ATF_TEST_CASE_BODY(instantiate__loop__multiple_iterations) +{ + const std::string input = + "first line\n" + "%loop table1 i\n" + "hello %%table1(i)%% %%table2(i)%%\n" + "%endloop\n" + "some more\n"; + + const std::string exp_output = + "first line\n" + "hello foo1 foo2\n" + "hello bar1 bar2\n" + "some more\n"; + + text::templates_def templates; + templates.add_vector("table1"); + templates.add_to_vector("table1", "foo1"); + templates.add_to_vector("table1", "bar1"); + templates.add_vector("table2"); + templates.add_to_vector("table2", "foo2"); + templates.add_to_vector("table2", "bar2"); + + do_test_ok(templates, input, exp_output); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(instantiate__loop__nested__no_iterations); +ATF_TEST_CASE_BODY(instantiate__loop__nested__no_iterations) +{ + const std::string input = + "first line\n" + "%loop table1 i\n" + "before: %%table1(i)%%\n" + "%loop table2 j\n" + "before: %%table2(j)%%\n" + "%loop table3 k\n" + "%%table3(k)%%\n" + "%endloop\n" + "after: %%table2(i)%%\n" + "%endloop\n" + "after: %%table1(i)%%\n" + "%endloop\n" + "some more\n"; + + const std::string exp_output = + "first line\n" + "before: a\n" + "after: a\n" + "before: b\n" + "after: b\n" + "some more\n"; + + text::templates_def templates; + templates.add_vector("table1"); + templates.add_to_vector("table1", "a"); + templates.add_to_vector("table1", "b"); + templates.add_vector("table2"); + templates.add_vector("table3"); + templates.add_to_vector("table3", "1"); + + do_test_ok(templates, input, exp_output); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(instantiate__loop__nested__multiple_iterations); +ATF_TEST_CASE_BODY(instantiate__loop__nested__multiple_iterations) +{ + const std::string input = + "first line\n" + "%loop table1 i\n" + "%loop table2 j\n" + "%%table1(i)%% %%table2(j)%%\n" + "%endloop\n" + "%endloop\n" + "some more\n"; + + const std::string exp_output = + "first line\n" + "a 1\n" + "a 2\n" + "a 3\n" + "b 1\n" + "b 2\n" + "b 3\n" + "some more\n"; + + text::templates_def templates; + templates.add_vector("table1"); + templates.add_to_vector("table1", "a"); + templates.add_to_vector("table1", "b"); + templates.add_vector("table2"); + templates.add_to_vector("table2", "1"); + templates.add_to_vector("table2", "2"); + templates.add_to_vector("table2", "3"); + + do_test_ok(templates, input, exp_output); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(instantiate__loop__sequential); +ATF_TEST_CASE_BODY(instantiate__loop__sequential) +{ + const std::string input = + "first line\n" + "%loop table1 iter\n" + "1: %%table1(iter)%%\n" + "%endloop\n" + "divider\n" + "%loop table2 iter\n" + "2: %%table2(iter)%%\n" + "%endloop\n" + "divider\n" + "%loop table3 iter\n" + "3: %%table3(iter)%%\n" + "%endloop\n" + "divider\n" + "%loop table4 iter\n" + "4: %%table4(iter)%%\n" + "%endloop\n" + "some more\n"; + + const std::string exp_output = + "first line\n" + "1: a\n" + "1: b\n" + "divider\n" + "divider\n" + "divider\n" + "4: 1\n" + "4: 2\n" + "4: 3\n" + "some more\n"; + + text::templates_def templates; + templates.add_vector("table1"); + templates.add_to_vector("table1", "a"); + templates.add_to_vector("table1", "b"); + templates.add_vector("table2"); + templates.add_vector("table3"); + templates.add_vector("table4"); + templates.add_to_vector("table4", "1"); + templates.add_to_vector("table4", "2"); + templates.add_to_vector("table4", "3"); + + do_test_ok(templates, input, exp_output); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(instantiate__loop__scoping); +ATF_TEST_CASE_BODY(instantiate__loop__scoping) +{ + const std::string input = + "%loop table1 i\n" + "%if defined(i)\n" "i defined inside scope 1\n" "%endif\n" + "%loop table2 j\n" + "%if defined(i)\n" "i defined inside scope 2\n" "%endif\n" + "%if defined(j)\n" "j defined inside scope 2\n" "%endif\n" + "%endloop\n" + "%if defined(j)\n" "j defined inside scope 1\n" "%endif\n" + "%endloop\n" + "%if defined(i)\n" "i defined outside\n" "%endif\n" + "%if defined(j)\n" "j defined outside\n" "%endif\n"; + + const std::string exp_output = + "i defined inside scope 1\n" + "i defined inside scope 2\n" + "j defined inside scope 2\n" + "i defined inside scope 1\n" + "i defined inside scope 2\n" + "j defined inside scope 2\n"; + + text::templates_def templates; + templates.add_vector("table1"); + templates.add_to_vector("table1", "first"); + templates.add_to_vector("table1", "second"); + templates.add_vector("table2"); + templates.add_to_vector("table2", "first"); + + do_test_ok(templates, input, exp_output); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(instantiate__mismatched_delimiters); +ATF_TEST_CASE_BODY(instantiate__mismatched_delimiters) +{ + const std::string input = + "this is some %% text\n" + "and this is %%var%% text%%\n"; + + const std::string exp_output = + "this is some %% text\n" + "and this is some more text%%\n"; + + text::templates_def templates; + templates.add_variable("var", "some more"); + + do_test_ok(templates, input, exp_output); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(instantiate__empty_statement); +ATF_TEST_CASE_BODY(instantiate__empty_statement) +{ + do_test_fail(text::templates_def(), "%\n", "Empty statement"); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(instantiate__unknown_statement); +ATF_TEST_CASE_BODY(instantiate__unknown_statement) +{ + do_test_fail(text::templates_def(), "%if2\n", "Unknown statement 'if2'"); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(instantiate__invalid_narguments); +ATF_TEST_CASE_BODY(instantiate__invalid_narguments) +{ + do_test_fail(text::templates_def(), "%if a b\n", + "Invalid number of arguments for statement 'if'"); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(instantiate__files__ok); +ATF_TEST_CASE_BODY(instantiate__files__ok) +{ + text::templates_def templates; + templates.add_variable("string", "Hello, world!"); + + atf::utils::create_file("input.txt", "The string is: %%string%%\n"); + + text::instantiate(templates, fs::path("input.txt"), fs::path("output.txt")); + + std::ifstream output("output.txt"); + std::string line; + ATF_REQUIRE(std::getline(output, line).good()); + ATF_REQUIRE_EQ(line, "The string is: Hello, world!"); + ATF_REQUIRE(std::getline(output, line).eof()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(instantiate__files__input_error); +ATF_TEST_CASE_BODY(instantiate__files__input_error) +{ + text::templates_def templates; + ATF_REQUIRE_THROW_RE(text::error, "Failed to open input.txt for read", + text::instantiate(templates, fs::path("input.txt"), + fs::path("output.txt"))); +} + + +ATF_TEST_CASE(instantiate__files__output_error); +ATF_TEST_CASE_HEAD(instantiate__files__output_error) +{ + set_md_var("require.user", "unprivileged"); +} +ATF_TEST_CASE_BODY(instantiate__files__output_error) +{ + text::templates_def templates; + + atf::utils::create_file("input.txt", ""); + + fs::mkdir(fs::path("dir"), 0444); + + ATF_REQUIRE_THROW_RE(text::error, "Failed to open dir/output.txt for write", + text::instantiate(templates, fs::path("input.txt"), + fs::path("dir/output.txt"))); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, templates_def__add_variable__first); + ATF_ADD_TEST_CASE(tcs, templates_def__add_variable__replace); + ATF_ADD_TEST_CASE(tcs, templates_def__remove_variable); + ATF_ADD_TEST_CASE(tcs, templates_def__add_vector__first); + ATF_ADD_TEST_CASE(tcs, templates_def__add_vector__replace); + ATF_ADD_TEST_CASE(tcs, templates_def__add_to_vector); + ATF_ADD_TEST_CASE(tcs, templates_def__exists__variable); + ATF_ADD_TEST_CASE(tcs, templates_def__exists__vector); + ATF_ADD_TEST_CASE(tcs, templates_def__get_variable__ok); + ATF_ADD_TEST_CASE(tcs, templates_def__get_variable__unknown); + ATF_ADD_TEST_CASE(tcs, templates_def__get_vector__ok); + ATF_ADD_TEST_CASE(tcs, templates_def__get_vector__unknown); + ATF_ADD_TEST_CASE(tcs, templates_def__evaluate__variable__ok); + ATF_ADD_TEST_CASE(tcs, templates_def__evaluate__variable__unknown); + ATF_ADD_TEST_CASE(tcs, templates_def__evaluate__vector__ok); + ATF_ADD_TEST_CASE(tcs, templates_def__evaluate__vector__unknown_vector); + ATF_ADD_TEST_CASE(tcs, templates_def__evaluate__vector__unknown_index); + ATF_ADD_TEST_CASE(tcs, templates_def__evaluate__vector__out_of_range); + ATF_ADD_TEST_CASE(tcs, templates_def__evaluate__defined); + ATF_ADD_TEST_CASE(tcs, templates_def__evaluate__length__ok); + ATF_ADD_TEST_CASE(tcs, templates_def__evaluate__length__unknown_vector); + ATF_ADD_TEST_CASE(tcs, templates_def__evaluate__parenthesis_error); + + ATF_ADD_TEST_CASE(tcs, instantiate__empty_input); + ATF_ADD_TEST_CASE(tcs, instantiate__value__ok); + ATF_ADD_TEST_CASE(tcs, instantiate__value__unknown_variable); + ATF_ADD_TEST_CASE(tcs, instantiate__vector_length__ok); + ATF_ADD_TEST_CASE(tcs, instantiate__vector_length__unknown_vector); + ATF_ADD_TEST_CASE(tcs, instantiate__vector_value__ok); + ATF_ADD_TEST_CASE(tcs, instantiate__vector_value__unknown_vector); + ATF_ADD_TEST_CASE(tcs, instantiate__vector_value__out_of_range__empty); + ATF_ADD_TEST_CASE(tcs, instantiate__vector_value__out_of_range__not_empty); + ATF_ADD_TEST_CASE(tcs, instantiate__if__one_level__taken); + ATF_ADD_TEST_CASE(tcs, instantiate__if__one_level__not_taken); + ATF_ADD_TEST_CASE(tcs, instantiate__if__multiple_levels__taken); + ATF_ADD_TEST_CASE(tcs, instantiate__if__multiple_levels__not_taken); + ATF_ADD_TEST_CASE(tcs, instantiate__loop__no_iterations); + ATF_ADD_TEST_CASE(tcs, instantiate__loop__multiple_iterations); + ATF_ADD_TEST_CASE(tcs, instantiate__loop__nested__no_iterations); + ATF_ADD_TEST_CASE(tcs, instantiate__loop__nested__multiple_iterations); + ATF_ADD_TEST_CASE(tcs, instantiate__loop__sequential); + ATF_ADD_TEST_CASE(tcs, instantiate__loop__scoping); + ATF_ADD_TEST_CASE(tcs, instantiate__mismatched_delimiters); + ATF_ADD_TEST_CASE(tcs, instantiate__empty_statement); + ATF_ADD_TEST_CASE(tcs, instantiate__unknown_statement); + ATF_ADD_TEST_CASE(tcs, instantiate__invalid_narguments); + + ATF_ADD_TEST_CASE(tcs, instantiate__files__ok); + ATF_ADD_TEST_CASE(tcs, instantiate__files__input_error); + ATF_ADD_TEST_CASE(tcs, instantiate__files__output_error); +} diff --git a/external/bsd/kyua-cli/dist/utils/units.cpp b/external/bsd/kyua-cli/dist/utils/units.cpp new file mode 100644 index 000000000..d2e7fcc8c --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/units.cpp @@ -0,0 +1,172 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/units.hpp" + +extern "C" { +#include +} + +#include + +#include "utils/format/macros.hpp" +#include "utils/text/exceptions.hpp" +#include "utils/text/operations.ipp" + +namespace units = utils::units; + + +/// Constructs a zero bytes quantity. +units::bytes::bytes(void) : + _count(0) +{ +} + + +/// Constructs an arbitrary bytes quantity. +/// +/// \param count_ The amount of bytes in the quantity. +units::bytes::bytes(const uint64_t count_) : + _count(count_) +{ +} + + +/// Parses a string into a bytes quantity. +/// +/// \param in_str The user-provided string to be converted. +/// +/// \return The converted bytes quantity. +/// +/// \throw std::runtime_error If the input string is empty or invalid. +units::bytes +units::bytes::parse(const std::string& in_str) +{ + if (in_str.empty()) + throw std::runtime_error("Bytes quantity cannot be empty"); + + uint64_t multiplier; + std::string str = in_str; + { + const char unit = str[str.length() - 1]; + switch (unit) { + case 'T': case 't': multiplier = TB; break; + case 'G': case 'g': multiplier = GB; break; + case 'M': case 'm': multiplier = MB; break; + case 'K': case 'k': multiplier = KB; break; + default: multiplier = 1; + } + if (multiplier != 1) + str.erase(str.length() - 1); + } + + if (str.empty()) + throw std::runtime_error("Bytes quantity cannot be empty"); + if (str[0] == '.' || str[str.length() - 1] == '.') { + // The standard parser for float values accepts things like ".3" and + // "3.", which means that we would interpret ".3K" and "3.K" as valid + // quantities. I think this is ugly and should not be allowed, so + // special-case this condition and just error out. + throw std::runtime_error(F("Invalid bytes quantity '%s'") % in_str); + } + + double count; + try { + count = text::to_type< double >(str); + } catch (const text::value_error& e) { + throw std::runtime_error(F("Invalid bytes quantity '%s'") % in_str); + } + + return bytes(uint64_t(count * multiplier)); +} + + +/// Formats a bytes quantity for user consumption. +/// +/// \return A textual representation of the bytes quantiy. +std::string +units::bytes::format(void) const +{ + if (_count >= TB) { + return F("%.2sT") % (static_cast< float >(_count) / TB); + } else if (_count >= GB) { + return F("%.2sG") % (static_cast< float >(_count) / GB); + } else if (_count >= MB) { + return F("%.2sM") % (static_cast< float >(_count) / MB); + } else if (_count >= KB) { + return F("%.2sK") % (static_cast< float >(_count) / KB); + } else { + return F("%s") % _count; + } +} + + +/// Implicit conversion to an integral representation. +units::bytes::operator uint64_t(void) const +{ + return _count; +} + + +/// Extracts a bytes quantity from a stream. +/// +/// \param input The stream from which to read a single word representing the +/// bytes quantity. +/// \param rhs The variable into which to store the parsed value. +/// +/// \return The input stream. +/// +/// \post The bad bit of input is set to 1 if the parsing failed. +std::istream& +operator>>(std::istream& input, units::bytes& rhs) +{ + std::string word; + input >> word; + if (input.good() || input.eof()) { + try { + rhs = units::bytes::parse(word); + } catch (const std::runtime_error& e) { + input.setstate(std::ios::badbit); + } + } + return input; +} + + +/// Injects a bytes quantity into a stream. +/// +/// \param output The stream into which to inject the bytes quantity as a +/// user-readable string. +/// \param rhs The bytes quantity to format. +/// +/// \return The output stream. +std::ostream& +operator<<(std::ostream& output, const units::bytes& rhs) +{ + return (output << rhs.format()); +} diff --git a/external/bsd/kyua-cli/dist/utils/units.hpp b/external/bsd/kyua-cli/dist/utils/units.hpp new file mode 100644 index 000000000..b716e0863 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/units.hpp @@ -0,0 +1,93 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file utils/units.hpp +/// Formatters and parsers of user-friendly units. + +#if !defined(UTILS_UNITS_HPP) +#define UTILS_UNITS_HPP + +extern "C" { +#include +} + +#include +#include +#include + +namespace utils { +namespace units { + + +namespace { + +/// Constant representing 1 kilobyte. +const uint64_t KB = int64_t(1) << 10; + +/// Constant representing 1 megabyte. +const uint64_t MB = int64_t(1) << 20; + +/// Constant representing 1 gigabyte. +const uint64_t GB = int64_t(1) << 30; + +/// Constant representing 1 terabyte. +const uint64_t TB = int64_t(1) << 40; + +} // anonymous namespace + + +/// Representation of a bytes quantity. +/// +/// The purpose of this class is to represent an amount of bytes in a semantic +/// manner, and to provide functions to format such numbers for nice user +/// presentation and to parse back such numbers. +/// +/// The input follows this regular expression: [0-9]+(|\.[0-9]+)[GgKkMmTt]? +/// The output follows this regular expression: [0-9]+\.[0-9]{3}[GKMT]? +class bytes { + /// Raw representation, in bytes, of the quantity. + uint64_t _count; + +public: + bytes(void); + explicit bytes(const uint64_t); + + static bytes parse(const std::string&); + std::string format(void) const; + + operator uint64_t(void) const; +}; + + +} // namespace units +} // namespace utils + +std::istream& operator>>(std::istream&, utils::units::bytes&); +std::ostream& operator<<(std::ostream&, const utils::units::bytes&); + +#endif // !defined(UTILS_UNITS_HPP) diff --git a/external/bsd/kyua-cli/dist/utils/units_test.cpp b/external/bsd/kyua-cli/dist/utils/units_test.cpp new file mode 100644 index 000000000..9590f9db1 --- /dev/null +++ b/external/bsd/kyua-cli/dist/utils/units_test.cpp @@ -0,0 +1,248 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/units.hpp" + +#include +#include + +#include + +namespace units = utils::units; + + +ATF_TEST_CASE_WITHOUT_HEAD(bytes__format__tb); +ATF_TEST_CASE_BODY(bytes__format__tb) +{ + using units::TB; + using units::GB; + + ATF_REQUIRE_EQ("2.00T", units::bytes(2 * TB).format()); + ATF_REQUIRE_EQ("45.12T", units::bytes(45 * TB + 120 * GB).format()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(bytes__format__gb); +ATF_TEST_CASE_BODY(bytes__format__gb) +{ + using units::GB; + using units::MB; + + ATF_REQUIRE_EQ("5.00G", units::bytes(5 * GB).format()); + ATF_REQUIRE_EQ("745.96G", units::bytes(745 * GB + 980 * MB).format()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(bytes__format__mb); +ATF_TEST_CASE_BODY(bytes__format__mb) +{ + using units::MB; + using units::KB; + + ATF_REQUIRE_EQ("1.00M", units::bytes(1 * MB).format()); + ATF_REQUIRE_EQ("1023.50M", units::bytes(1023 * MB + 512 * KB).format()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(bytes__format__kb); +ATF_TEST_CASE_BODY(bytes__format__kb) +{ + using units::KB; + + ATF_REQUIRE_EQ("3.00K", units::bytes(3 * KB).format()); + ATF_REQUIRE_EQ("1.33K", units::bytes(1 * KB + 340).format()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(bytes__format__b); +ATF_TEST_CASE_BODY(bytes__format__b) +{ + ATF_REQUIRE_EQ("0", units::bytes().format()); + ATF_REQUIRE_EQ("0", units::bytes(0).format()); + ATF_REQUIRE_EQ("1023", units::bytes(1023).format()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(bytes__parse__tb); +ATF_TEST_CASE_BODY(bytes__parse__tb) +{ + using units::TB; + using units::GB; + + ATF_REQUIRE_EQ(0, units::bytes::parse("0T")); + ATF_REQUIRE_EQ(units::bytes(TB), units::bytes::parse("1T")); + ATF_REQUIRE_EQ(units::bytes(TB), units::bytes::parse("1t")); + ATF_REQUIRE_EQ(13567973486755LL, units::bytes::parse("12.340000T")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(bytes__parse__gb); +ATF_TEST_CASE_BODY(bytes__parse__gb) +{ + using units::GB; + using units::MB; + + ATF_REQUIRE_EQ(0, units::bytes::parse("0G")); + ATF_REQUIRE_EQ(units::bytes(GB), units::bytes::parse("1G")); + ATF_REQUIRE_EQ(units::bytes(GB), units::bytes::parse("1g")); + ATF_REQUIRE_EQ(13249974108LL, units::bytes::parse("12.340G")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(bytes__parse__mb); +ATF_TEST_CASE_BODY(bytes__parse__mb) +{ + using units::MB; + using units::KB; + + ATF_REQUIRE_EQ(0, units::bytes::parse("0M")); + ATF_REQUIRE_EQ(units::bytes(MB), units::bytes::parse("1M")); + ATF_REQUIRE_EQ(units::bytes(MB), units::bytes::parse("1m")); + ATF_REQUIRE_EQ(12939427, units::bytes::parse("12.34000M")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(bytes__parse__kb); +ATF_TEST_CASE_BODY(bytes__parse__kb) +{ + using units::KB; + + ATF_REQUIRE_EQ(0, units::bytes::parse("0K")); + ATF_REQUIRE_EQ(units::bytes(KB), units::bytes::parse("1K")); + ATF_REQUIRE_EQ(units::bytes(KB), units::bytes::parse("1k")); + ATF_REQUIRE_EQ(12636, units::bytes::parse("12.34K")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(bytes__parse__b); +ATF_TEST_CASE_BODY(bytes__parse__b) +{ + ATF_REQUIRE_EQ(0, units::bytes::parse("0")); + ATF_REQUIRE_EQ(89, units::bytes::parse("89")); + ATF_REQUIRE_EQ(1234, units::bytes::parse("1234")); + ATF_REQUIRE_EQ(1234567890, units::bytes::parse("1234567890")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(bytes__parse__error); +ATF_TEST_CASE_BODY(bytes__parse__error) +{ + ATF_REQUIRE_THROW_RE(std::runtime_error, "empty", units::bytes::parse("")); + ATF_REQUIRE_THROW_RE(std::runtime_error, "empty", units::bytes::parse("k")); + + ATF_REQUIRE_THROW_RE(std::runtime_error, "Invalid.*'.'", + units::bytes::parse(".")); + ATF_REQUIRE_THROW_RE(std::runtime_error, "Invalid.*'3.'", + units::bytes::parse("3.")); + ATF_REQUIRE_THROW_RE(std::runtime_error, "Invalid.*'.3'", + units::bytes::parse(".3")); + + ATF_REQUIRE_THROW_RE(std::runtime_error, "Invalid.*' t'", + units::bytes::parse(" t")); + ATF_REQUIRE_THROW_RE(std::runtime_error, "Invalid.*'.t'", + units::bytes::parse(".t")); + ATF_REQUIRE_THROW_RE(std::runtime_error, "Invalid.*'12 t'", + units::bytes::parse("12 t")); + ATF_REQUIRE_THROW_RE(std::runtime_error, "Invalid.*'12.t'", + units::bytes::parse("12.t")); + ATF_REQUIRE_THROW_RE(std::runtime_error, "Invalid.*'.12t'", + units::bytes::parse(".12t")); + ATF_REQUIRE_THROW_RE(std::runtime_error, "Invalid.*'abt'", + units::bytes::parse("abt")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(bytes__istream__one_word); +ATF_TEST_CASE_BODY(bytes__istream__one_word) +{ + std::istringstream input("12M"); + + units::bytes bytes; + input >> bytes; + ATF_REQUIRE(input.eof()); + ATF_REQUIRE_EQ(units::bytes(12 * units::MB), bytes); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(bytes__istream__many_words); +ATF_TEST_CASE_BODY(bytes__istream__many_words) +{ + std::istringstream input("12M more"); + + units::bytes bytes; + input >> bytes; + ATF_REQUIRE(input.good()); + ATF_REQUIRE_EQ(units::bytes(12 * units::MB), bytes); + + std::string word; + input >> word; + ATF_REQUIRE_EQ("more", word); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(bytes__istream__error); +ATF_TEST_CASE_BODY(bytes__istream__error) +{ + std::istringstream input("12.M more"); + + units::bytes bytes(123456789); + input >> bytes; + ATF_REQUIRE(input.bad()); + ATF_REQUIRE_EQ(units::bytes(123456789), bytes); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(bytes__ostream); +ATF_TEST_CASE_BODY(bytes__ostream) +{ + std::ostringstream output; + output << "foo " << units::bytes(5 * units::KB) << " bar"; + ATF_REQUIRE_EQ("foo 5.00K bar", output.str()); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, bytes__format__tb); + ATF_ADD_TEST_CASE(tcs, bytes__format__gb); + ATF_ADD_TEST_CASE(tcs, bytes__format__mb); + ATF_ADD_TEST_CASE(tcs, bytes__format__kb); + ATF_ADD_TEST_CASE(tcs, bytes__format__b); + + ATF_ADD_TEST_CASE(tcs, bytes__parse__tb); + ATF_ADD_TEST_CASE(tcs, bytes__parse__gb); + ATF_ADD_TEST_CASE(tcs, bytes__parse__mb); + ATF_ADD_TEST_CASE(tcs, bytes__parse__kb); + ATF_ADD_TEST_CASE(tcs, bytes__parse__b); + ATF_ADD_TEST_CASE(tcs, bytes__parse__error); + + ATF_ADD_TEST_CASE(tcs, bytes__istream__one_word); + ATF_ADD_TEST_CASE(tcs, bytes__istream__many_words); + ATF_ADD_TEST_CASE(tcs, bytes__istream__error); + ATF_ADD_TEST_CASE(tcs, bytes__ostream); +} diff --git a/external/bsd/kyua-cli/etc/Makefile b/external/bsd/kyua-cli/etc/Makefile new file mode 100644 index 000000000..95df4db43 --- /dev/null +++ b/external/bsd/kyua-cli/etc/Makefile @@ -0,0 +1,5 @@ +# $NetBSD: Makefile,v 1.1 2013/02/24 03:06:15 jmmv Exp $ + +SUBDIR= kyua + +.include diff --git a/external/bsd/kyua-cli/etc/Makefile.inc b/external/bsd/kyua-cli/etc/Makefile.inc new file mode 100644 index 000000000..bbd0af79f --- /dev/null +++ b/external/bsd/kyua-cli/etc/Makefile.inc @@ -0,0 +1,3 @@ +# $NetBSD: Makefile.inc,v 1.1 2013/02/24 03:06:15 jmmv Exp $ + +.include "../Makefile.inc" diff --git a/external/bsd/kyua-cli/etc/kyua/Makefile b/external/bsd/kyua-cli/etc/kyua/Makefile new file mode 100644 index 000000000..476465ae7 --- /dev/null +++ b/external/bsd/kyua-cli/etc/kyua/Makefile @@ -0,0 +1,10 @@ +# $NetBSD: Makefile,v 1.1 2013/02/24 03:06:15 jmmv Exp $ + +.include + +CONFIGFILES= kyua.conf +FILESDIR= ${KYUA_CONFDIR} +FILESMODE= 644 + +.include # For clean and cleandir +.include diff --git a/external/bsd/kyua-cli/etc/kyua/kyua.conf b/external/bsd/kyua-cli/etc/kyua/kyua.conf new file mode 100644 index 000000000..eff56be41 --- /dev/null +++ b/external/bsd/kyua-cli/etc/kyua/kyua.conf @@ -0,0 +1,14 @@ +-- $NetBSD: kyua.conf,v 1.1 2013/02/24 03:06:15 jmmv Exp $ +-- +-- System-wide configuration file for kyua(1). See kyua.conf(5) for details +-- on the syntax and tests(7) for any NetBSD-specific tweaks that may apply. +-- + +syntax(2) + +-- User to drop privileges to when invoking kyua(1) as root and a test case +-- requests to be run with non-root permissions. +unprivileged_user = '_tests' + +-- An example to set a configuration property specific to NetBSD. +--test_suites.NetBSD.fstype = 'ffs' diff --git a/external/bsd/kyua-cli/lib/Makefile b/external/bsd/kyua-cli/lib/Makefile new file mode 100644 index 000000000..e4119f958 --- /dev/null +++ b/external/bsd/kyua-cli/lib/Makefile @@ -0,0 +1,5 @@ +# $NetBSD: Makefile,v 1.1 2013/02/23 14:16:49 jmmv Exp $ + +SUBDIR= utils store engine cli + +.include diff --git a/external/bsd/kyua-cli/lib/Makefile.inc b/external/bsd/kyua-cli/lib/Makefile.inc new file mode 100644 index 000000000..b54e5daf5 --- /dev/null +++ b/external/bsd/kyua-cli/lib/Makefile.inc @@ -0,0 +1,14 @@ +# $NetBSD: Makefile.inc,v 1.1 2013/02/23 14:16:49 jmmv Exp $ + +.include "../Makefile.inc" + +LIBISCXX= yes +LIBISPRIVATE= yes + +LIBDPLIBS+= lua ${.CURDIR}/../../../../mit/lua/lib/liblua +.if ${HAVE_GCC} == 4 +LIBDPLIBS+= stdc++ ${.CURDIR}/../../../../../gnu/lib/libstdc++-v3_4 +.else +LIBDPLIBS+= stdc++ ${.CURDIR}/../../../../../external/gpl3/gcc/lib/libstdc++-v3 +.endif +LIBDPLIBS+= m ${.CURDIR}/../../../../../lib/libm diff --git a/external/bsd/kyua-cli/lib/cli/Makefile b/external/bsd/kyua-cli/lib/cli/Makefile new file mode 100644 index 000000000..3f5ee1011 --- /dev/null +++ b/external/bsd/kyua-cli/lib/cli/Makefile @@ -0,0 +1,27 @@ +# $NetBSD: Makefile,v 1.1 2013/02/23 14:16:50 jmmv Exp $ + +KYUA_LIBS= engine store utils + +.include + +.PATH: ${SRCDIR}/cli + +LIB= cli + +WARNS?= 3 + +SRCS= cmd_about.cpp \ + cmd_config.cpp \ + cmd_db_exec.cpp \ + cmd_db_migrate.cpp \ + cmd_debug.cpp \ + cmd_help.cpp \ + cmd_list.cpp \ + cmd_report.cpp \ + cmd_report_html.cpp \ + cmd_test.cpp \ + common.cpp \ + config.cpp \ + main.cpp + +.include diff --git a/external/bsd/kyua-cli/lib/engine/Makefile b/external/bsd/kyua-cli/lib/engine/Makefile new file mode 100644 index 000000000..62442d24a --- /dev/null +++ b/external/bsd/kyua-cli/lib/engine/Makefile @@ -0,0 +1,32 @@ +# $NetBSD: Makefile,v 1.1 2013/02/23 14:16:50 jmmv Exp $ + +KYUA_LIBS= store utils + +.include + +.PATH: ${SRCDIR}/engine +.PATH: ${SRCDIR}/engine/drivers + +LIB= engine + +WARNS?= 3 + +SRCS= action.cpp \ + config.cpp \ + context.cpp \ + exceptions.cpp \ + filters.cpp \ + kyuafile.cpp \ + metadata.cpp \ + test_case.cpp \ + test_program.cpp \ + test_result.cpp \ + testers.cpp + +# engine/drivers subdirectory. +SRCS+= debug_test.cpp \ + list_tests.cpp \ + run_tests.cpp \ + scan_action.cpp + +.include diff --git a/external/bsd/kyua-cli/lib/store/Makefile b/external/bsd/kyua-cli/lib/store/Makefile new file mode 100644 index 000000000..b1118e32e --- /dev/null +++ b/external/bsd/kyua-cli/lib/store/Makefile @@ -0,0 +1,19 @@ +# $NetBSD: Makefile,v 1.1 2013/02/23 14:16:50 jmmv Exp $ + +KYUA_LIBS= utils + +.include + +.PATH: ${SRCDIR}/store + +LIB= store + +WARNS?= 3 + +SRCS= backend.cpp \ + dbtypes.cpp \ + exceptions.cpp \ + metadata.cpp \ + transaction.cpp + +.include diff --git a/external/bsd/kyua-cli/lib/utils/Makefile b/external/bsd/kyua-cli/lib/utils/Makefile new file mode 100644 index 000000000..ed245c7c7 --- /dev/null +++ b/external/bsd/kyua-cli/lib/utils/Makefile @@ -0,0 +1,87 @@ +# $NetBSD: Makefile,v 1.1 2013/02/23 14:16:50 jmmv Exp $ + +.include + +.PATH: ${SRCDIR}/utils + +LIB= utils + +WARNS?= 2 + +SRCS= datetime.cpp \ + env.cpp \ + memory.cpp \ + passwd.cpp \ + sanity.cpp \ + stream.cpp \ + units.cpp + +SRCS+= cmdline/base_command.cpp \ + cmdline/exceptions.cpp \ + cmdline/globals.cpp \ + cmdline/options.cpp \ + cmdline/parser.cpp \ + cmdline/ui.cpp \ + cmdline/ui_mock.cpp + +SRCS+= config/exceptions.cpp \ + config/keys.cpp \ + config/lua_module.cpp \ + config/nodes.cpp \ + config/parser.cpp \ + config/tree.cpp + +SRCS+= format/exceptions.cpp \ + format/formatter.cpp + +SRCS+= fs/auto_cleaners.cpp \ + fs/exceptions.cpp \ + fs/lua_module.cpp \ + fs/operations.cpp \ + fs/path.cpp + +SRCS+= logging/operations.cpp + +SRCS+= process/child.cpp \ + process/exceptions.cpp \ + process/fdstream.cpp \ + process/status.cpp \ + process/system.cpp \ + process/systembuf.cpp + +SRCS+= signals/exceptions.cpp \ + signals/interrupts.cpp \ + signals/misc.cpp \ + signals/programmer.cpp + +SRCS+= sqlite/c_gate.cpp \ + sqlite/database.cpp \ + sqlite/exceptions.cpp \ + sqlite/statement.cpp \ + sqlite/transaction.cpp + +SRCS+= text/exceptions.cpp \ + text/operations.cpp \ + text/table.cpp \ + text/templates.cpp + +# The subdirectories into which we recurse only exist to create the necessary +# obj directories for the above SRCS declarations to work. We need to be able +# to create object files of the form /.o, and therefore +# the subdirectory must exist upfront. +# +# Note that there are source files of the same name in various subdirectories, +# so we just cannot use .PATH to look for files in all of them at once. +# +# TODO: Would be nice if bsd.obj.mk (or whichever other module) did the right +# thing here and just created these obj directories for us. Or, alternatively, +# we could have every subdirectory Makefile create a temporary .a and we could +# pull all the .a files together from here into libutil.a. +SUBDIR= cmdline config format fs logging process signals sqlite text +.for dir in ${SUBDIR} +clean-${dir} cleandir-${dir} includes-${dir}: .PHONY + @true +.endfor + +.include +.include diff --git a/external/bsd/kyua-cli/lib/utils/Makefile.inc b/external/bsd/kyua-cli/lib/utils/Makefile.inc new file mode 100644 index 000000000..d515d2e18 --- /dev/null +++ b/external/bsd/kyua-cli/lib/utils/Makefile.inc @@ -0,0 +1,3 @@ +# $NetBSD: Makefile.inc,v 1.1 2013/02/23 14:16:50 jmmv Exp $ + +.include "../Makefile.inc" diff --git a/external/bsd/kyua-cli/lib/utils/cmdline/Makefile b/external/bsd/kyua-cli/lib/utils/cmdline/Makefile new file mode 100644 index 000000000..831996662 --- /dev/null +++ b/external/bsd/kyua-cli/lib/utils/cmdline/Makefile @@ -0,0 +1,3 @@ +# $NetBSD: Makefile,v 1.1 2013/02/23 14:16:50 jmmv Exp $ + +.include diff --git a/external/bsd/kyua-cli/lib/utils/config/Makefile b/external/bsd/kyua-cli/lib/utils/config/Makefile new file mode 100644 index 000000000..3c244cd0f --- /dev/null +++ b/external/bsd/kyua-cli/lib/utils/config/Makefile @@ -0,0 +1,3 @@ +# $NetBSD: Makefile,v 1.1 2013/02/23 14:16:51 jmmv Exp $ + +.include diff --git a/external/bsd/kyua-cli/lib/utils/defs.hpp b/external/bsd/kyua-cli/lib/utils/defs.hpp new file mode 100644 index 000000000..cf9fee90b --- /dev/null +++ b/external/bsd/kyua-cli/lib/utils/defs.hpp @@ -0,0 +1,63 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file utils/defs.hpp +/// +/// Definitions for compiler and system features autodetected at configuration +/// time. + +#if !defined(UTILS_DEFS_HPP) +#define UTILS_DEFS_HPP + + +/// Attribute to mark a function as non-returning. +#define UTILS_NORETURN __attribute__((noreturn)) + + +/// Attribute to mark a function as pure. +#define UTILS_PURE __attribute__((__pure__)) + + +/// Attribute to mark an entity as unused. +#define UTILS_UNUSED __attribute__((__unused__)) + + +/// Macro to mark a parameter as unused. +/// +/// This macro has to be called on the name of a parameter during the +/// definition (not declaration) of a function. When doing so, it declares +/// the parameter as unused to silence compiler warnings and also renames +/// the parameter by prefixing "unused_" to it. This is to ensure that the +/// developer remembers to remove the call to this macro from the parameter +/// when he actually starts using it. +/// +/// \param name The name of the function parameter to mark as unused. +#define UTILS_UNUSED_PARAM(name) unused_ ## name UTILS_UNUSED + + +#endif // !defined(UTILS_DEFS_HPP) diff --git a/external/bsd/kyua-cli/lib/utils/format/Makefile b/external/bsd/kyua-cli/lib/utils/format/Makefile new file mode 100644 index 000000000..3c244cd0f --- /dev/null +++ b/external/bsd/kyua-cli/lib/utils/format/Makefile @@ -0,0 +1,3 @@ +# $NetBSD: Makefile,v 1.1 2013/02/23 14:16:51 jmmv Exp $ + +.include diff --git a/external/bsd/kyua-cli/lib/utils/fs/Makefile b/external/bsd/kyua-cli/lib/utils/fs/Makefile new file mode 100644 index 000000000..3c244cd0f --- /dev/null +++ b/external/bsd/kyua-cli/lib/utils/fs/Makefile @@ -0,0 +1,3 @@ +# $NetBSD: Makefile,v 1.1 2013/02/23 14:16:51 jmmv Exp $ + +.include diff --git a/external/bsd/kyua-cli/lib/utils/logging/Makefile b/external/bsd/kyua-cli/lib/utils/logging/Makefile new file mode 100644 index 000000000..3c244cd0f --- /dev/null +++ b/external/bsd/kyua-cli/lib/utils/logging/Makefile @@ -0,0 +1,3 @@ +# $NetBSD: Makefile,v 1.1 2013/02/23 14:16:51 jmmv Exp $ + +.include diff --git a/external/bsd/kyua-cli/lib/utils/process/Makefile b/external/bsd/kyua-cli/lib/utils/process/Makefile new file mode 100644 index 000000000..3c244cd0f --- /dev/null +++ b/external/bsd/kyua-cli/lib/utils/process/Makefile @@ -0,0 +1,3 @@ +# $NetBSD: Makefile,v 1.1 2013/02/23 14:16:51 jmmv Exp $ + +.include diff --git a/external/bsd/kyua-cli/lib/utils/signals/Makefile b/external/bsd/kyua-cli/lib/utils/signals/Makefile new file mode 100644 index 000000000..3c244cd0f --- /dev/null +++ b/external/bsd/kyua-cli/lib/utils/signals/Makefile @@ -0,0 +1,3 @@ +# $NetBSD: Makefile,v 1.1 2013/02/23 14:16:51 jmmv Exp $ + +.include diff --git a/external/bsd/kyua-cli/lib/utils/sqlite/Makefile b/external/bsd/kyua-cli/lib/utils/sqlite/Makefile new file mode 100644 index 000000000..568c79189 --- /dev/null +++ b/external/bsd/kyua-cli/lib/utils/sqlite/Makefile @@ -0,0 +1,3 @@ +# $NetBSD: Makefile,v 1.1 2013/02/23 14:16:52 jmmv Exp $ + +.include diff --git a/external/bsd/kyua-cli/lib/utils/text/Makefile b/external/bsd/kyua-cli/lib/utils/text/Makefile new file mode 100644 index 000000000..568c79189 --- /dev/null +++ b/external/bsd/kyua-cli/lib/utils/text/Makefile @@ -0,0 +1,3 @@ +# $NetBSD: Makefile,v 1.1 2013/02/23 14:16:52 jmmv Exp $ + +.include diff --git a/external/bsd/kyua-cli/prepare-import.sh b/external/bsd/kyua-cli/prepare-import.sh new file mode 100755 index 000000000..09d2e5871 --- /dev/null +++ b/external/bsd/kyua-cli/prepare-import.sh @@ -0,0 +1,107 @@ +#!/bin/sh +# $NetBSD: prepare-import.sh,v 1.1 2013/02/23 14:16:49 jmmv Exp $ +# +# Use this script to recreate the 'dist' subdirectory from a newly released +# distfile. The script takes care of unpacking the distfile, removing any +# files that are not relevant to NetBSD and checking if there are any new +# files in the new release that need to be addressed. +# + +set -e + +ProgName=${0##*/} + +CLEAN_PATTERNS= +CLEAN_PATTERNS="${CLEAN_PATTERNS} *.m4" +CLEAN_PATTERNS="${CLEAN_PATTERNS} INSTALL TODO" +CLEAN_PATTERNS="${CLEAN_PATTERNS} Doxyfile*" +CLEAN_PATTERNS="${CLEAN_PATTERNS} Makefile* */Makefile* */*/Makefile*" +CLEAN_PATTERNS="${CLEAN_PATTERNS} admin" +CLEAN_PATTERNS="${CLEAN_PATTERNS} api-docs" +CLEAN_PATTERNS="${CLEAN_PATTERNS} config.h.in" +CLEAN_PATTERNS="${CLEAN_PATTERNS} configure*" +CLEAN_PATTERNS="${CLEAN_PATTERNS} m4" +CLEAN_PATTERNS="${CLEAN_PATTERNS} utils/defs.hpp" + +err() { + echo "${ProgName}:" "${@}" 1>&2 + exit 1 +} + +log() { + echo "${ProgName}:" "${@}" +} + +backup_dist() { + if [ -d dist.old ]; then + log "Removing dist; dist.old exists" + rm -rf dist + else + log "Backing up dist as dist.old" + mv dist dist.old + fi +} + +extract_distfile() { + local distfile="${1}"; shift + local distname="${1}"; shift + + log "Extracting ${distfile}" + tar -xzf "${distfile}" + [ -d "${distname}" ] || err "Distfile did not create ${distname}" + log "Renaming ${distname} to dist" + mv "${distname}" dist +} + +get_distname() { + local distfile="${1}"; shift + basename "${distfile}" | sed -e 's,\.tar.*,,' +} + +cleanup_dist() { + log "Removing unnecessary files from dist" + ( cd dist && rm -rf ${CLEAN_PATTERNS} ) +} + +diff_dirs() { + local old_dir="${1}"; shift + local new_dir="${1}"; shift + + local old_list=$(mktemp -t kyua-cli-import.XXXXXX) + local new_list=$(mktemp -t kyua-cli-import.XXXXXX) + local diff=$(mktemp -t kyua-cli-import.XXXXXX) + trap "rm -f '${old_list}' '${new_list}' '${diff}'; exit 1" \ + HUP INT QUIT TERM + + ( cd "${old_dir}" && find . | sort >>"${old_list}" ) + ( cd "${new_dir}" && find . | sort >>"${new_list}" ) + + diff -u "${old_list}" "${new_list}" | grep '^+\.' >>"${diff}" || true + if [ -s "${diff}" ]; then + log "New files found" + diff -u "${old_list}" "${new_list}" | grep '^+\.' + log "Check if any files have to be cleaned up and update" \ + "the prepare-import.sh script accordingly" + else + log "No new files; all good!" + fi + + rm -f "${old_list}" "${new_list}" "${diff}" +} + +main() { + [ ${#} -eq 1 ] || err "Must provide a distfile name" + local distfile="${1}"; shift + + [ -f Makefile -a -f prepare-import.sh ] || \ + err "Must be run from the src/external/bsd/kyua-cli subdirectory" + + local distname="$(get_distname ${distfile})" + + backup_dist + extract_distfile "${distfile}" "${distname}" + cleanup_dist + diff_dirs dist.old dist +} + +main "${@}" diff --git a/external/bsd/kyua-cli/share/Makefile b/external/bsd/kyua-cli/share/Makefile new file mode 100644 index 000000000..50f1770f9 --- /dev/null +++ b/external/bsd/kyua-cli/share/Makefile @@ -0,0 +1,5 @@ +# $NetBSD: Makefile,v 1.1 2013/02/23 14:16:52 jmmv Exp $ + +SUBDIR= doc examples kyua-cli man + +.include diff --git a/external/bsd/kyua-cli/share/Makefile.inc b/external/bsd/kyua-cli/share/Makefile.inc new file mode 100644 index 000000000..4160a5ee8 --- /dev/null +++ b/external/bsd/kyua-cli/share/Makefile.inc @@ -0,0 +1,3 @@ +# $NetBSD: Makefile.inc,v 1.1 2013/02/23 14:16:52 jmmv Exp $ + +.include "../Makefile.inc" diff --git a/external/bsd/kyua-cli/share/doc/Makefile b/external/bsd/kyua-cli/share/doc/Makefile new file mode 100644 index 000000000..2f50863d2 --- /dev/null +++ b/external/bsd/kyua-cli/share/doc/Makefile @@ -0,0 +1,5 @@ +# $NetBSD: Makefile,v 1.1 2013/02/23 14:16:52 jmmv Exp $ + +SUBDIR= kyua-cli + +.include diff --git a/external/bsd/kyua-cli/share/doc/Makefile.inc b/external/bsd/kyua-cli/share/doc/Makefile.inc new file mode 100644 index 000000000..4160a5ee8 --- /dev/null +++ b/external/bsd/kyua-cli/share/doc/Makefile.inc @@ -0,0 +1,3 @@ +# $NetBSD: Makefile.inc,v 1.1 2013/02/23 14:16:52 jmmv Exp $ + +.include "../Makefile.inc" diff --git a/external/bsd/kyua-cli/share/doc/kyua-cli/Makefile b/external/bsd/kyua-cli/share/doc/kyua-cli/Makefile new file mode 100644 index 000000000..33171ee19 --- /dev/null +++ b/external/bsd/kyua-cli/share/doc/kyua-cli/Makefile @@ -0,0 +1,13 @@ +# $NetBSD: Makefile,v 1.1 2013/02/23 14:16:52 jmmv Exp $ + +.include + +.if ${MKSHARE} != "no" +.PATH: ${SRCDIR} + +FILESDIR= ${KYUA_DOCDIR} +FILESMODE= 444 +FILES= AUTHORS COPYING NEWS README +.endif + +.include diff --git a/external/bsd/kyua-cli/share/examples/Makefile b/external/bsd/kyua-cli/share/examples/Makefile new file mode 100644 index 000000000..1a7cbb5de --- /dev/null +++ b/external/bsd/kyua-cli/share/examples/Makefile @@ -0,0 +1,5 @@ +# $NetBSD: Makefile,v 1.1 2013/02/23 14:16:53 jmmv Exp $ + +SUBDIR= kyua-cli + +.include diff --git a/external/bsd/kyua-cli/share/examples/Makefile.inc b/external/bsd/kyua-cli/share/examples/Makefile.inc new file mode 100644 index 000000000..44834a754 --- /dev/null +++ b/external/bsd/kyua-cli/share/examples/Makefile.inc @@ -0,0 +1,3 @@ +# $NetBSD: Makefile.inc,v 1.1 2013/02/23 14:16:53 jmmv Exp $ + +.include "../Makefile.inc" diff --git a/external/bsd/kyua-cli/share/examples/kyua-cli/Makefile b/external/bsd/kyua-cli/share/examples/kyua-cli/Makefile new file mode 100644 index 000000000..a07c9681a --- /dev/null +++ b/external/bsd/kyua-cli/share/examples/kyua-cli/Makefile @@ -0,0 +1,13 @@ +# $NetBSD: Makefile,v 1.1 2013/02/23 14:16:53 jmmv Exp $ + +.include + +.if ${MKSHARE} != "no" +.PATH: ${SRCDIR}/examples + +FILESDIR= ${KYUA_EXAMPLESDIR} +FILESMODE= 444 +FILES= Kyuafile.top kyua.conf +.endif + +.include diff --git a/external/bsd/kyua-cli/share/kyua-cli/Makefile b/external/bsd/kyua-cli/share/kyua-cli/Makefile new file mode 100644 index 000000000..9fa7767c8 --- /dev/null +++ b/external/bsd/kyua-cli/share/kyua-cli/Makefile @@ -0,0 +1,5 @@ +# $NetBSD: Makefile,v 1.1 2013/02/23 14:16:53 jmmv Exp $ + +SUBDIR= misc store + +.include diff --git a/external/bsd/kyua-cli/share/kyua-cli/Makefile.inc b/external/bsd/kyua-cli/share/kyua-cli/Makefile.inc new file mode 100644 index 000000000..44834a754 --- /dev/null +++ b/external/bsd/kyua-cli/share/kyua-cli/Makefile.inc @@ -0,0 +1,3 @@ +# $NetBSD: Makefile.inc,v 1.1 2013/02/23 14:16:53 jmmv Exp $ + +.include "../Makefile.inc" diff --git a/external/bsd/kyua-cli/share/kyua-cli/misc/Makefile b/external/bsd/kyua-cli/share/kyua-cli/misc/Makefile new file mode 100644 index 000000000..e5e2945a1 --- /dev/null +++ b/external/bsd/kyua-cli/share/kyua-cli/misc/Makefile @@ -0,0 +1,16 @@ +# $NetBSD: Makefile,v 1.1 2013/02/23 14:16:53 jmmv Exp $ + +.include + +.if ${MKSHARE} != "no" +.PATH: ${SRCDIR}/misc + +FILESDIR= ${KYUA_MISCDIR} +FILESMODE= 444 +FILES= context.html \ + index.html \ + report.css \ + test_result.html +.endif + +.include diff --git a/external/bsd/kyua-cli/share/kyua-cli/store/Makefile b/external/bsd/kyua-cli/share/kyua-cli/store/Makefile new file mode 100644 index 000000000..fc065164f --- /dev/null +++ b/external/bsd/kyua-cli/share/kyua-cli/store/Makefile @@ -0,0 +1,14 @@ +# $NetBSD: Makefile,v 1.1 2013/02/23 14:16:54 jmmv Exp $ + +.include + +.if ${MKSHARE} != "no" +.PATH: ${SRCDIR}/store + +FILESDIR= ${KYUA_STOREDIR} +FILESMODE= 444 +FILES= migrate_v1_v2.sql \ + schema_v2.sql +.endif + +.include diff --git a/external/bsd/kyua-cli/share/man/Makefile b/external/bsd/kyua-cli/share/man/Makefile new file mode 100644 index 000000000..303c42b8a --- /dev/null +++ b/external/bsd/kyua-cli/share/man/Makefile @@ -0,0 +1,5 @@ +# $NetBSD: Makefile,v 1.1 2013/02/23 14:16:54 jmmv Exp $ + +SUBDIR= man5 man7 + +.include diff --git a/external/bsd/kyua-cli/share/man/Makefile.inc b/external/bsd/kyua-cli/share/man/Makefile.inc new file mode 100644 index 000000000..f8b22efe8 --- /dev/null +++ b/external/bsd/kyua-cli/share/man/Makefile.inc @@ -0,0 +1,3 @@ +# $NetBSD: Makefile.inc,v 1.1 2013/02/23 14:16:54 jmmv Exp $ + +.include "../Makefile.inc" diff --git a/external/bsd/kyua-cli/share/man/man5/Makefile b/external/bsd/kyua-cli/share/man/man5/Makefile new file mode 100644 index 000000000..e9b309086 --- /dev/null +++ b/external/bsd/kyua-cli/share/man/man5/Makefile @@ -0,0 +1,13 @@ +# $NetBSD: Makefile,v 1.1 2013/02/23 14:16:54 jmmv Exp $ + +.include + +.PATH: ${SRCDIR}/doc + +.for name in kyua.conf.5 kyuafile.5 +MAN+= ${name} +${name}: ${name}.in + name=${name}; ${BUILD_MANPAGE} +.endfor + +.include diff --git a/external/bsd/kyua-cli/share/man/man7/Makefile b/external/bsd/kyua-cli/share/man/man7/Makefile new file mode 100644 index 000000000..1e5266409 --- /dev/null +++ b/external/bsd/kyua-cli/share/man/man7/Makefile @@ -0,0 +1,13 @@ +# $NetBSD: Makefile,v 1.1 2013/02/23 14:16:54 jmmv Exp $ + +.include + +.PATH: ${SRCDIR}/doc + +.for name in kyua-build-root.7 kyua-test-filters.7 +MAN+= ${name} +${name}: ${name}.in + name=${name}; ${BUILD_MANPAGE} +.endfor + +.include diff --git a/external/bsd/kyua-cli/tests/Makefile b/external/bsd/kyua-cli/tests/Makefile new file mode 100644 index 000000000..5a78e6996 --- /dev/null +++ b/external/bsd/kyua-cli/tests/Makefile @@ -0,0 +1,5 @@ +# $NetBSD: Makefile,v 1.1 2013/02/23 14:16:54 jmmv Exp $ + +SUBDIR= kyua-cli + +.include diff --git a/external/bsd/kyua-cli/tests/Makefile.inc b/external/bsd/kyua-cli/tests/Makefile.inc new file mode 100644 index 000000000..f8b22efe8 --- /dev/null +++ b/external/bsd/kyua-cli/tests/Makefile.inc @@ -0,0 +1,3 @@ +# $NetBSD: Makefile.inc,v 1.1 2013/02/23 14:16:54 jmmv Exp $ + +.include "../Makefile.inc" diff --git a/external/bsd/kyua-cli/tests/kyua-cli/Makefile b/external/bsd/kyua-cli/tests/kyua-cli/Makefile new file mode 100644 index 000000000..26f8f6fda --- /dev/null +++ b/external/bsd/kyua-cli/tests/kyua-cli/Makefile @@ -0,0 +1,15 @@ +# $NetBSD: Makefile,v 1.1 2013/02/23 14:16:54 jmmv Exp $ + +.include + +TESTSDIR= ${TESTSBASE}/kyua-cli + +TESTS_SUBDIRS= cli engine examples integration store utils + +# Build and install the 'bootstrap' tests but prevent them from being +# recursed into from the Atffile. These tests are broken in platforms +# where /bin/sh is not bash (like NetBSD). Kyua's Issue 24 has more +# details. +SUBDIR= bootstrap + +.include diff --git a/external/bsd/kyua-cli/tests/kyua-cli/Makefile.inc b/external/bsd/kyua-cli/tests/kyua-cli/Makefile.inc new file mode 100644 index 000000000..ada437445 --- /dev/null +++ b/external/bsd/kyua-cli/tests/kyua-cli/Makefile.inc @@ -0,0 +1,3 @@ +# $NetBSD: Makefile.inc,v 1.1 2013/02/23 14:16:55 jmmv Exp $ + +.include "../Makefile.inc" diff --git a/external/bsd/kyua-cli/tests/kyua-cli/bootstrap/Makefile b/external/bsd/kyua-cli/tests/kyua-cli/bootstrap/Makefile new file mode 100644 index 000000000..9844a8659 --- /dev/null +++ b/external/bsd/kyua-cli/tests/kyua-cli/bootstrap/Makefile @@ -0,0 +1,29 @@ +# $NetBSD: Makefile,v 1.1 2013/02/23 14:16:55 jmmv Exp $ + +.include + +TESTSDIR= ${TESTSBASE}/kyua-cli/bootstrap +ATFFILE= no + +.PATH: ${SRCDIR}/bootstrap + +FILES= testsuite +FILESDIR= ${TESTSDIR} +FILESMODE= ${BINMODE} + +PROGS_CXX= atf_helpers +BINDIR.atf_helpers= ${TESTSDIR} +MAN.atf_helpers= # none +LDADD.atf_helpers= -latf-c++ -latf-c +DPADD.atf_helpers= ${LIBATF_CXX} ${LIBATF_C} + +.if defined(__MINIX) +LDADD+= -lgcc_s +.endif # defined(__MINIX) + +PROGS_CXX+= plain_helpers +BINDIR.plain_helpers= ${TESTSDIR} +MAN.plain_helpers= # none + +.include +.include diff --git a/external/bsd/kyua-cli/tests/kyua-cli/cli/Makefile b/external/bsd/kyua-cli/tests/kyua-cli/cli/Makefile new file mode 100644 index 000000000..f88c85db5 --- /dev/null +++ b/external/bsd/kyua-cli/tests/kyua-cli/cli/Makefile @@ -0,0 +1,25 @@ +# $NetBSD: Makefile,v 1.1 2013/02/23 14:16:55 jmmv Exp $ + +KYUA_LIBS= cli engine store engine utils + +.include + +TESTSDIR= ${TESTSBASE}/kyua-cli/cli + +.PATH: ${SRCDIR}/cli + +TESTS_CXX= cmd_about_test \ + cmd_config_test \ + cmd_db_exec_test \ + cmd_db_migrate_test \ + cmd_debug_test \ + cmd_help_test \ + cmd_list_test \ + cmd_report_html_test \ + cmd_report_test \ + cmd_test_test \ + common_test \ + config_test \ + main_test + +.include diff --git a/external/bsd/kyua-cli/tests/kyua-cli/engine/Makefile b/external/bsd/kyua-cli/tests/kyua-cli/engine/Makefile new file mode 100644 index 000000000..4e70dd41a --- /dev/null +++ b/external/bsd/kyua-cli/tests/kyua-cli/engine/Makefile @@ -0,0 +1,35 @@ +# $NetBSD: Makefile,v 1.1 2013/02/23 14:16:55 jmmv Exp $ + +KYUA_LIBS= engine store engine utils + +.include + +TESTSDIR= ${TESTSBASE}/kyua-cli/engine + +.PATH: ${SRCDIR}/engine + +TESTS_CXX= action_test \ + config_test \ + context_test \ + exceptions_test \ + filters_test \ + kyuafile_test \ + metadata_test \ + test_case_test \ + test_program_test \ + test_result_test \ + testers_test + +PROGS_CXX= test_case_atf_helpers +BINDIR.test_case_atf_helpers= ${TESTSDIR} +MAN.test_case_atf_helpers= # none +LDADD.test_case_atf_helpers= -latf-c++ -latf-c +DPADD.test_case_atf_helpers= ${LIBATF_CXX} ${LIBATF_C} + +PROGS_CXX+= test_case_plain_helpers +BINDIR.test_case_plain_helpers= ${TESTSDIR} +MAN.test_case_plain_helpers= # none + +TESTS_SUBDIRS+= drivers + +.include diff --git a/external/bsd/kyua-cli/tests/kyua-cli/engine/Makefile.inc b/external/bsd/kyua-cli/tests/kyua-cli/engine/Makefile.inc new file mode 100644 index 000000000..ada437445 --- /dev/null +++ b/external/bsd/kyua-cli/tests/kyua-cli/engine/Makefile.inc @@ -0,0 +1,3 @@ +# $NetBSD: Makefile.inc,v 1.1 2013/02/23 14:16:55 jmmv Exp $ + +.include "../Makefile.inc" diff --git a/external/bsd/kyua-cli/tests/kyua-cli/engine/drivers/Makefile b/external/bsd/kyua-cli/tests/kyua-cli/engine/drivers/Makefile new file mode 100644 index 000000000..da6424082 --- /dev/null +++ b/external/bsd/kyua-cli/tests/kyua-cli/engine/drivers/Makefile @@ -0,0 +1,22 @@ +# $NetBSD: Makefile,v 1.1 2013/02/23 14:16:55 jmmv Exp $ + +KYUA_LIBS= engine store engine utils + +.include + +TESTSDIR= ${TESTSBASE}/kyua-cli/engine/drivers + +.PATH: ${SRCDIR}/engine/drivers + +TESTS_CXX= debug_test_test \ + list_tests_test \ + run_tests_test \ + scan_action_test + +PROGS_CXX= list_tests_helpers +BINDIR.list_tests_helpers= ${TESTSDIR} +MAN.list_tests_helpers= # none +LDADD.list_tests_helpers= -latf-c++ -latf-c +DPADD.list_tests_helpers= ${LIBATF_CXX} ${LIBATF_C} + +.include diff --git a/external/bsd/kyua-cli/tests/kyua-cli/examples/Makefile b/external/bsd/kyua-cli/tests/kyua-cli/examples/Makefile new file mode 100644 index 000000000..8bf986051 --- /dev/null +++ b/external/bsd/kyua-cli/tests/kyua-cli/examples/Makefile @@ -0,0 +1,13 @@ +# $NetBSD: Makefile,v 1.1 2013/02/23 14:16:55 jmmv Exp $ + +KYUA_LIBS= engine utils + +.include + +TESTSDIR= ${TESTSBASE}/kyua-cli/examples + +.PATH: ${SRCDIR}/examples + +TESTS_CXX= syntax_test + +.include diff --git a/external/bsd/kyua-cli/tests/kyua-cli/integration/Makefile b/external/bsd/kyua-cli/tests/kyua-cli/integration/Makefile new file mode 100644 index 000000000..f982d2cf3 --- /dev/null +++ b/external/bsd/kyua-cli/tests/kyua-cli/integration/Makefile @@ -0,0 +1,34 @@ +# $NetBSD: Makefile,v 1.1 2013/02/23 14:16:56 jmmv Exp $ + +.include + +TESTSDIR= ${TESTSBASE}/kyua-cli/integration + +.PATH: ${SRCDIR}/integration + +TESTS_SH+= cmd_about_test +TESTS_SH_SRC_cmd_about_test= utils.sh cmd_about_test.tmp.sh +CLEANFILES+= cmd_about_test.tmp.sh cmd_about_test.tmp.sh.tmp +cmd_about_test.tmp.sh: cmd_about_test.sh + sed -e 's,__KYUA_DOCDIR__,${KYUA_DOCDIR},g' \ + <${.ALLSRC} >${.TARGET}.tmp + mv ${.TARGET}.tmp ${.TARGET} + +.for test in \ + cmd_config_test \ + cmd_db_exec_test \ + cmd_db_migrate_test \ + cmd_debug_test \ + cmd_help_test \ + cmd_list_test \ + cmd_report_html_test \ + cmd_report_test \ + cmd_test_test \ + global_test +TESTS_SH+= ${test} +TESTS_SH_SRC_${test}= utils.sh ${test}.sh +.endfor + +SUBDIR+= helpers + +.include diff --git a/external/bsd/kyua-cli/tests/kyua-cli/integration/Makefile.inc b/external/bsd/kyua-cli/tests/kyua-cli/integration/Makefile.inc new file mode 100644 index 000000000..2143b50f5 --- /dev/null +++ b/external/bsd/kyua-cli/tests/kyua-cli/integration/Makefile.inc @@ -0,0 +1,3 @@ +# $NetBSD: Makefile.inc,v 1.1 2013/02/23 14:16:56 jmmv Exp $ + +.include "../Makefile.inc" diff --git a/external/bsd/kyua-cli/tests/kyua-cli/integration/helpers/Makefile b/external/bsd/kyua-cli/tests/kyua-cli/integration/helpers/Makefile new file mode 100644 index 000000000..3683b3f2e --- /dev/null +++ b/external/bsd/kyua-cli/tests/kyua-cli/integration/helpers/Makefile @@ -0,0 +1,26 @@ +# $NetBSD: Makefile,v 1.1 2013/02/23 14:16:56 jmmv Exp $ + +.include + +TESTSDIR= ${TESTSBASE}/kyua-cli/integration/helpers +# Even though we use bsd.test.mk here because some of the helpers are +# actually ATF-based test programs, we don't want to install an Atffile +# because they are not runnable on their own. +ATFFILE= no + +.PATH: ${SRCDIR}/integration/helpers + +TESTS_CXX= bogus_test_cases \ + config \ + expect_all_pass \ + expect_some_fail \ + interrupts \ + metadata \ + simple_all_pass \ + simple_some_fail + +PROGS_CXX= bad_test_program +BINDIR.bad_test_program= ${TESTSDIR} +MAN.bad_test_program= # none + +.include diff --git a/external/bsd/kyua-cli/tests/kyua-cli/store/Makefile b/external/bsd/kyua-cli/tests/kyua-cli/store/Makefile new file mode 100644 index 000000000..aabc7e7e3 --- /dev/null +++ b/external/bsd/kyua-cli/tests/kyua-cli/store/Makefile @@ -0,0 +1,24 @@ +# $NetBSD: Makefile,v 1.1 2013/02/23 14:16:56 jmmv Exp $ + +KYUA_LIBS= store engine utils + +.include + +TESTSDIR= ${TESTSBASE}/kyua-cli/store + +.PATH: ${SRCDIR}/store + +TESTS_CXX= backend_test \ + dbtypes_test \ + exceptions_test \ + metadata_test \ + schema_inttest \ + transaction_test + +FILESDIR= ${TESTSDIR} +FILESMODE= 444 +FILES= schema_v1.sql \ + testdata_v1.sql \ + testdata_v2.sql + +.include diff --git a/external/bsd/kyua-cli/tests/kyua-cli/utils/Makefile b/external/bsd/kyua-cli/tests/kyua-cli/utils/Makefile new file mode 100644 index 000000000..b8e5d79db --- /dev/null +++ b/external/bsd/kyua-cli/tests/kyua-cli/utils/Makefile @@ -0,0 +1,23 @@ +# $NetBSD: Makefile,v 1.1 2013/02/23 14:16:56 jmmv Exp $ + +KYUA_LIBS= utils + +.include + +TESTSDIR= ${TESTSBASE}/kyua-cli/utils + +.PATH: ${SRCDIR}/utils + +TESTS_CXX= auto_array_test \ + datetime_test \ + env_test \ + memory_test \ + optional_test \ + passwd_test \ + sanity_test \ + stream_test \ + units_test + +TESTS_SUBDIRS+= cmdline config format fs logging process signals sqlite text + +.include diff --git a/external/bsd/kyua-cli/tests/kyua-cli/utils/Makefile.inc b/external/bsd/kyua-cli/tests/kyua-cli/utils/Makefile.inc new file mode 100644 index 000000000..2143b50f5 --- /dev/null +++ b/external/bsd/kyua-cli/tests/kyua-cli/utils/Makefile.inc @@ -0,0 +1,3 @@ +# $NetBSD: Makefile.inc,v 1.1 2013/02/23 14:16:56 jmmv Exp $ + +.include "../Makefile.inc" diff --git a/external/bsd/kyua-cli/tests/kyua-cli/utils/cmdline/Makefile b/external/bsd/kyua-cli/tests/kyua-cli/utils/cmdline/Makefile new file mode 100644 index 000000000..f9d1b95be --- /dev/null +++ b/external/bsd/kyua-cli/tests/kyua-cli/utils/cmdline/Makefile @@ -0,0 +1,19 @@ +# $NetBSD: Makefile,v 1.1 2013/02/23 14:16:56 jmmv Exp $ + +KYUA_LIBS= utils + +.include + +TESTSDIR= ${TESTSBASE}/kyua-cli/utils/cmdline + +.PATH: ${SRCDIR}/utils/cmdline + +TESTS_CXX= base_command_test \ + commands_map_test \ + exceptions_test \ + globals_test \ + options_test \ + parser_test \ + ui_test + +.include diff --git a/external/bsd/kyua-cli/tests/kyua-cli/utils/config/Makefile b/external/bsd/kyua-cli/tests/kyua-cli/utils/config/Makefile new file mode 100644 index 000000000..28aa4c822 --- /dev/null +++ b/external/bsd/kyua-cli/tests/kyua-cli/utils/config/Makefile @@ -0,0 +1,18 @@ +# $NetBSD: Makefile,v 1.1 2013/02/23 14:16:57 jmmv Exp $ + +KYUA_LIBS= utils + +.include + +TESTSDIR= ${TESTSBASE}/kyua-cli/utils/config + +.PATH: ${SRCDIR}/utils/config + +TESTS_CXX= exceptions_test \ + keys_test \ + lua_module_test \ + nodes_test \ + parser_test \ + tree_test + +.include diff --git a/external/bsd/kyua-cli/tests/kyua-cli/utils/format/Makefile b/external/bsd/kyua-cli/tests/kyua-cli/utils/format/Makefile new file mode 100644 index 000000000..32a19d2d3 --- /dev/null +++ b/external/bsd/kyua-cli/tests/kyua-cli/utils/format/Makefile @@ -0,0 +1,14 @@ +# $NetBSD: Makefile,v 1.1 2013/02/23 14:16:57 jmmv Exp $ + +KYUA_LIBS= utils + +.include + +TESTSDIR= ${TESTSBASE}/kyua-cli/utils/format + +.PATH: ${SRCDIR}/utils/format + +TESTS_CXX= exceptions_test \ + formatter_test + +.include diff --git a/external/bsd/kyua-cli/tests/kyua-cli/utils/fs/Makefile b/external/bsd/kyua-cli/tests/kyua-cli/utils/fs/Makefile new file mode 100644 index 000000000..baef27aff --- /dev/null +++ b/external/bsd/kyua-cli/tests/kyua-cli/utils/fs/Makefile @@ -0,0 +1,19 @@ +# $NetBSD: Makefile,v 1.1 2013/02/23 14:16:57 jmmv Exp $ + +KYUA_LIBS= utils + +.include + +TESTSDIR= ${TESTSBASE}/kyua-cli/utils/fs + +.PATH: ${SRCDIR}/utils/fs + +#LSC: Unsupported on MINIX +# operations_test + +TESTS_CXX= auto_cleaners_test \ + exceptions_test \ + lua_module_test \ + path_test + +.include diff --git a/external/bsd/kyua-cli/tests/kyua-cli/utils/logging/Makefile b/external/bsd/kyua-cli/tests/kyua-cli/utils/logging/Makefile new file mode 100644 index 000000000..56e3c35f5 --- /dev/null +++ b/external/bsd/kyua-cli/tests/kyua-cli/utils/logging/Makefile @@ -0,0 +1,14 @@ +# $NetBSD: Makefile,v 1.1 2013/02/23 14:16:57 jmmv Exp $ + +KYUA_LIBS= utils + +.include + +TESTSDIR= ${TESTSBASE}/kyua-cli/utils/logging + +.PATH: ${SRCDIR}/utils/logging + +TESTS_CXX= macros_test \ + operations_test + +.include diff --git a/external/bsd/kyua-cli/tests/kyua-cli/utils/process/Makefile b/external/bsd/kyua-cli/tests/kyua-cli/utils/process/Makefile new file mode 100644 index 000000000..4d0eb76cb --- /dev/null +++ b/external/bsd/kyua-cli/tests/kyua-cli/utils/process/Makefile @@ -0,0 +1,21 @@ +# $NetBSD: Makefile,v 1.1 2013/02/23 14:16:57 jmmv Exp $ + +KYUA_LIBS= utils + +.include + +TESTSDIR= ${TESTSBASE}/kyua-cli/utils/process + +.PATH: ${SRCDIR}/utils/process + +TESTS_CXX= child_test \ + exceptions_test \ + fdstream_test \ + status_test \ + systembuf_test + +PROGS_CXX= helpers +BINDIR.helpers= ${TESTSDIR} +MAN.helpers= # none + +.include diff --git a/external/bsd/kyua-cli/tests/kyua-cli/utils/signals/Makefile b/external/bsd/kyua-cli/tests/kyua-cli/utils/signals/Makefile new file mode 100644 index 000000000..7d403faaa --- /dev/null +++ b/external/bsd/kyua-cli/tests/kyua-cli/utils/signals/Makefile @@ -0,0 +1,16 @@ +# $NetBSD: Makefile,v 1.1 2013/02/23 14:16:57 jmmv Exp $ + +KYUA_LIBS= utils + +.include + +TESTSDIR= ${TESTSBASE}/kyua-cli/utils/signals + +.PATH: ${SRCDIR}/utils/signals + +TESTS_CXX= exceptions_test \ + interrupts_test \ + misc_test \ + programmer_test + +.include diff --git a/external/bsd/kyua-cli/tests/kyua-cli/utils/sqlite/Makefile b/external/bsd/kyua-cli/tests/kyua-cli/utils/sqlite/Makefile new file mode 100644 index 000000000..00445b36e --- /dev/null +++ b/external/bsd/kyua-cli/tests/kyua-cli/utils/sqlite/Makefile @@ -0,0 +1,17 @@ +# $NetBSD: Makefile,v 1.1 2013/02/23 14:16:58 jmmv Exp $ + +KYUA_LIBS= utils + +.include + +TESTSDIR= ${TESTSBASE}/kyua-cli/utils/sqlite + +.PATH: ${SRCDIR}/utils/sqlite + +TESTS_CXX= c_gate_test \ + database_test \ + exceptions_test \ + statement_test \ + transaction_test + +.include diff --git a/external/bsd/kyua-cli/tests/kyua-cli/utils/text/Makefile b/external/bsd/kyua-cli/tests/kyua-cli/utils/text/Makefile new file mode 100644 index 000000000..202f8a160 --- /dev/null +++ b/external/bsd/kyua-cli/tests/kyua-cli/utils/text/Makefile @@ -0,0 +1,16 @@ +# $NetBSD: Makefile,v 1.1 2013/02/23 14:16:58 jmmv Exp $ + +KYUA_LIBS= utils + +.include + +TESTSDIR= ${TESTSBASE}/kyua-cli/utils/text + +.PATH: ${SRCDIR}/utils/text + +TESTS_CXX= exceptions_test \ + operations_test \ + table_test \ + templates_test + +.include diff --git a/external/bsd/kyua-cli/usr.bin/Makefile b/external/bsd/kyua-cli/usr.bin/Makefile new file mode 100644 index 000000000..4ced4e23f --- /dev/null +++ b/external/bsd/kyua-cli/usr.bin/Makefile @@ -0,0 +1,5 @@ +# $NetBSD: Makefile,v 1.1 2013/02/23 14:16:58 jmmv Exp $ + +SUBDIR= kyua + +.include diff --git a/external/bsd/kyua-cli/usr.bin/Makefile.inc b/external/bsd/kyua-cli/usr.bin/Makefile.inc new file mode 100644 index 000000000..5e09bb975 --- /dev/null +++ b/external/bsd/kyua-cli/usr.bin/Makefile.inc @@ -0,0 +1,3 @@ +# $NetBSD: Makefile.inc,v 1.1 2013/02/23 14:16:58 jmmv Exp $ + +.include "../Makefile.inc" diff --git a/external/bsd/kyua-cli/usr.bin/kyua/Makefile b/external/bsd/kyua-cli/usr.bin/kyua/Makefile new file mode 100644 index 000000000..3e4ba0354 --- /dev/null +++ b/external/bsd/kyua-cli/usr.bin/kyua/Makefile @@ -0,0 +1,24 @@ +# $NetBSD: Makefile,v 1.1 2013/02/23 14:16:58 jmmv Exp $ + +KYUA_LIBS= cli engine store engine utils + +.include + +.PATH: ${SRCDIR} ${SRCDIR}/doc + +BINDIR= ${KYUA_BINDIR} +PROG_CXX= kyua +SRCS= main.cpp + +WARNS?= 3 + +.for name in \ + kyua-about.1 kyua-config.1 kyua-db-exec.1 kyua-db-migrate.1 \ + kyua-debug.1 kyua-help.1 kyua-list.1 kyua-report-html.1 \ + kyua-report.1 kyua-test.1 kyua.1 +MAN+= ${name} +${name}: ${name}.in + name=${name}; ${BUILD_MANPAGE} +.endfor + +.include diff --git a/external/bsd/kyua-testers/Makefile b/external/bsd/kyua-testers/Makefile new file mode 100644 index 000000000..c7453cb93 --- /dev/null +++ b/external/bsd/kyua-testers/Makefile @@ -0,0 +1,10 @@ +# $NetBSD: Makefile,v 1.2 2013/02/23 14:58:11 jmmv Exp $ + +SUBDIR= lib .WAIT libexec share tests + +.for dir in libexec share tests +includes-${dir}: .PHONY + @true +.endfor + +.include diff --git a/external/bsd/kyua-testers/dist/AUTHORS b/external/bsd/kyua-testers/dist/AUTHORS new file mode 100644 index 000000000..0f707683a --- /dev/null +++ b/external/bsd/kyua-testers/dist/AUTHORS @@ -0,0 +1 @@ +* Julio Merino diff --git a/external/bsd/kyua-testers/dist/COPYING b/external/bsd/kyua-testers/dist/COPYING new file mode 100644 index 000000000..c8adbc7b0 --- /dev/null +++ b/external/bsd/kyua-testers/dist/COPYING @@ -0,0 +1,27 @@ +Copyright 2012 Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +* Neither the name of Google Inc. nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/external/bsd/kyua-testers/dist/Kyuafile b/external/bsd/kyua-testers/dist/Kyuafile new file mode 100644 index 000000000..3c5ccf6be --- /dev/null +++ b/external/bsd/kyua-testers/dist/Kyuafile @@ -0,0 +1,21 @@ +syntax("kyuafile", 1) + +test_suite("kyua") + +-- Tests for common modules. +atf_test_program{name="cli_test"} +atf_test_program{name="env_test"} +atf_test_program{name="error_test"} +atf_test_program{name="fs_test"} +atf_test_program{name="result_test"} +atf_test_program{name="run_test"} +atf_test_program{name="stacktrace_test"} +atf_test_program{name="text_test"} + +-- Tests for the atf_tester. +atf_test_program{name="atf_list_test"} +atf_test_program{name="atf_result_test"} +atf_test_program{name="atf_inttest"} + +-- Tests for the plain_tester. +atf_test_program{name="plain_inttest"} diff --git a/external/bsd/kyua-testers/dist/NEWS b/external/bsd/kyua-testers/dist/NEWS new file mode 100644 index 000000000..39b64faef --- /dev/null +++ b/external/bsd/kyua-testers/dist/NEWS @@ -0,0 +1,16 @@ +Changes in version 0.1 +====================== + +Experimental version released on February 19th, 2013. + +This is the first public release of the kyua-testers package. + +The goal of this first release is to adopt all the test case execution +code of kyua-cli 0.5 and ship it as a collection of independent tester +binaries. The kyua-cli package will rely on these binaries to run the +tests, which provides better modularity and simplicity to the +architecture of Kyua. + +The code in this package is all C as opposed to the current C++ codebase +of kyua-cli, which means that the overall build times of Kyua are now +reduced. diff --git a/external/bsd/kyua-testers/dist/README b/external/bsd/kyua-testers/dist/README new file mode 100644 index 000000000..95c5ffc0b --- /dev/null +++ b/external/bsd/kyua-testers/dist/README @@ -0,0 +1,22 @@ +Kyua (pronounced Q.A.) is a testing framework for both developers and +users. Kyua is different from most other testing frameworks in that it +puts the end user experience before anything else. There are multiple +reasons for users to run the tests themselves, and Kyua ensures that +they can do so in the most convenient way. + +This module, kyua-testers, provides scriptable interfaces to interact +with test programs of various kinds. The interface of such testers +allows the caller to execute a single test case of a single test program +in a controlled and homogeneous manner. + +For further information on the contents of this distribution file, +please refer to the following other documents: + +* AUTHORS: List of authors and contributors to this project. +* COPYING: License information. +* INSTALL: Compilation and installation instructions. +* NEWS: List of major changes between formal releases. + +For general project information, please visit: + + http://code.google.com/p/kyua/ diff --git a/external/bsd/kyua-testers/dist/atf_helpers.c b/external/bsd/kyua-testers/dist/atf_helpers.c new file mode 100644 index 000000000..d80cfe88b --- /dev/null +++ b/external/bsd/kyua-testers/dist/atf_helpers.c @@ -0,0 +1,193 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include +#include +#include +#include + +#include + + +ATF_TC_WITHOUT_HEAD(fail); +ATF_TC_BODY(fail, tc) +{ + fprintf(stdout, "First line to stdout\n"); + fprintf(stderr, "First line to stderr\n"); + atf_tc_fail("This is the failure message"); +} + + +ATF_TC_WITHOUT_HEAD(pass); +ATF_TC_BODY(pass, tc) +{ + fprintf(stdout, "First line to stdout\n"); + fprintf(stdout, "Second line to stdout\n"); + fprintf(stderr, "First line to stderr\n"); + fprintf(stderr, "Second line to stderr\n"); +} + + +ATF_TC_WITHOUT_HEAD(signal); +ATF_TC_BODY(signal, tc) +{ + fprintf(stderr, "About to die due to SIGABRT!\n"); + abort(); +} + + +ATF_TC_WITHOUT_HEAD(sleep); +ATF_TC_BODY(sleep, tc) +{ + sleep(300); +} + + +ATF_TC_WITH_CLEANUP(cleanup_check_work_directory); +ATF_TC_HEAD(cleanup_check_work_directory, tc) { } +ATF_TC_BODY(cleanup_check_work_directory, tc) +{ + fprintf(stdout, "Body stdout\n"); + fprintf(stderr, "Body stderr\n"); + atf_utils_create_file("cookie-in-work-directory", "the value\n"); +} +ATF_TC_CLEANUP(cleanup_check_work_directory, tc) +{ + fprintf(stdout, "Cleanup stdout\n"); + fprintf(stderr, "Cleanup stderr\n"); + if (atf_utils_compare_file("cookie-in-work-directory", "the value\n")) { + printf("Cleanup properly ran in the same directory as the body\n"); + } else { + printf("Cleanup did not run in the same directory as the body\n"); + } +} + + +ATF_TC_WITH_CLEANUP(cleanup_fail); +ATF_TC_HEAD(cleanup_fail, tc) { } +ATF_TC_BODY(cleanup_fail, tc) +{ +} +ATF_TC_CLEANUP(cleanup_fail, tc) +{ + exit(EXIT_FAILURE); +} + + +ATF_TC_WITH_CLEANUP(cleanup_signal); +ATF_TC_HEAD(cleanup_signal, tc) { } +ATF_TC_BODY(cleanup_signal, tc) { } +ATF_TC_CLEANUP(cleanup_signal, tc) +{ + fprintf(stderr, "About to die due to SIGABRT!\n"); + abort(); +} + + +ATF_TC_WITH_CLEANUP(cleanup_sleep); +ATF_TC_HEAD(cleanup_sleep, tc) { } +ATF_TC_BODY(cleanup_sleep, tc) { } +ATF_TC_CLEANUP(cleanup_sleep, tc) +{ + sleep(300); +} + + +ATF_TC_WITH_CLEANUP(body_and_cleanup_fail); +ATF_TC_HEAD(body_and_cleanup_fail, tc) { } +ATF_TC_BODY(body_and_cleanup_fail, tc) +{ + atf_tc_fail("Body fails"); +} +ATF_TC_CLEANUP(body_and_cleanup_fail, tc) +{ + printf("Killing cleanup\n"); + fflush(stdout); + kill(getpid(), SIGKILL); +} + + +/// Prints a configuration variable if it exists. +/// +/// \param tc Caller test case. +/// \param part Identifier for the part of the test case. +/// \param name Name of the configuration variable. +static void +print_config_var(const atf_tc_t* tc, const char* part, const char* name) +{ + if (atf_tc_has_config_var(tc, name)) + printf("%s %s %s\n", part, name, atf_tc_get_config_var(tc, name)); +} + + +/// Prints the configuration variables of the test case. +/// +/// Ideally we'd print all variables but the ATF interface does not have an API +/// to iterate over them all. Instead, this just prints the variables we are +/// interested in for testing purposes. +/// +/// \param tc Caller test case. +/// \param part Identifier for the part of the test case. +static void +print_config_vars(const atf_tc_t* tc, const char* part) +{ + print_config_var(tc, part, "my-var1"); + print_config_var(tc, part, "v2"); +} + + +ATF_TC_WITH_CLEANUP(print_config); +ATF_TC_HEAD(print_config, tc) {} +ATF_TC_BODY(print_config, tc) +{ + print_config_vars(tc, "body"); +} +ATF_TC_CLEANUP(print_config, tc) +{ + print_config_vars(tc, "cleanup"); +} + + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, fail); + ATF_TP_ADD_TC(tp, pass); + ATF_TP_ADD_TC(tp, signal); + ATF_TP_ADD_TC(tp, sleep); + + ATF_TP_ADD_TC(tp, cleanup_check_work_directory); + ATF_TP_ADD_TC(tp, cleanup_fail); + ATF_TP_ADD_TC(tp, cleanup_signal); + ATF_TP_ADD_TC(tp, cleanup_sleep); + + ATF_TP_ADD_TC(tp, body_and_cleanup_fail); + + ATF_TP_ADD_TC(tp, print_config); + + return atf_no_error(); +} diff --git a/external/bsd/kyua-testers/dist/atf_inttest.c b/external/bsd/kyua-testers/dist/atf_inttest.c new file mode 100644 index 000000000..374089f4e --- /dev/null +++ b/external/bsd/kyua-testers/dist/atf_inttest.c @@ -0,0 +1,284 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include + +#include + +#define INTERFACE "atf" +#include "common_inttest.h" + + +ATF_TC(list__ok); +ATF_TC_HEAD(list__ok, tc) { setup(tc, true); } +ATF_TC_BODY(list__ok, tc) +{ + char* helpers = helpers_path(tc); + check(EXIT_SUCCESS, + "test_case{name='fail'}\n" + "test_case{name='pass'}\n" + "test_case{name='signal'}\n" + "test_case{name='sleep'}\n" + "test_case{name='cleanup_check_work_directory', has_cleanup='true'}\n" + "test_case{name='cleanup_fail', has_cleanup='true'}\n" + "test_case{name='cleanup_signal', has_cleanup='true'}\n" + "test_case{name='cleanup_sleep', has_cleanup='true'}\n" + "test_case{name='body_and_cleanup_fail', has_cleanup='true'}\n" + "test_case{name='print_config', has_cleanup='true'}\n", + "", + "list", helpers, NULL); + free(helpers); +} + + +ATF_TC(test__pass); +ATF_TC_HEAD(test__pass, tc) { setup(tc, true); } +ATF_TC_BODY(test__pass, tc) +{ + char* helpers = helpers_path(tc); + check(EXIT_SUCCESS, + "First line to stdout\nSecond line to stdout\n", + "First line to stderr\nSecond line to stderr\n", + "test", helpers, "pass", "test-result", NULL); + free(helpers); + + ATF_REQUIRE(atf_utils_compare_file("test-result", "passed\n")); +} + + +ATF_TC(test__fail); +ATF_TC_HEAD(test__fail, tc) { setup(tc, true); } +ATF_TC_BODY(test__fail, tc) +{ + char* helpers = helpers_path(tc); + check(EXIT_FAILURE, "First line to stdout\n", "First line to stderr\n", + "test", helpers, "fail", "test-result", NULL); + free(helpers); + + ATF_REQUIRE(atf_utils_compare_file("test-result", + "failed: This is the failure message\n")); +} + + +ATF_TC(test__crash); +ATF_TC_HEAD(test__crash, tc) { setup(tc, true); } +ATF_TC_BODY(test__crash, tc) +{ + char* helpers = helpers_path(tc); + check(EXIT_FAILURE, "", "save:crash.err", + "test", helpers, "signal", "test-result", NULL); + free(helpers); + + ATF_REQUIRE(atf_utils_compare_file("test-result", + "broken: Premature exit; test case received signal 6 (core dumped)\n")); + + ATF_REQUIRE(atf_utils_grep_file("About to die due to SIGABRT!", + "crash.err")); + ATF_REQUIRE(atf_utils_grep_file("attempting to gather stack trace", + "crash.err")); +} + + +ATF_TC(test__timeout); +ATF_TC_HEAD(test__timeout, tc) { setup(tc, true); } +ATF_TC_BODY(test__timeout, tc) +{ + char* helpers = helpers_path(tc); + check(EXIT_FAILURE, "", "Subprocess timed out; sending KILL signal...\n", + "-t1", "test", helpers, "sleep", "test-result", NULL); + free(helpers); + + ATF_REQUIRE(atf_utils_compare_file("test-result", + "broken: Test case body timed out\n")); +} + + +ATF_TC(test__result_priority); +ATF_TC_HEAD(test__result_priority, tc) { setup(tc, true); } +ATF_TC_BODY(test__result_priority, tc) +{ + char* helpers = helpers_path(tc); + check(EXIT_FAILURE, "Killing cleanup\n", "", + "test", "-vhas.cleanup=true", helpers, "body_and_cleanup_fail", + "test-result", NULL); + free(helpers); + + ATF_REQUIRE(atf_utils_compare_file("test-result", "failed: Body fails\n")); +} + + +ATF_TC(test__cleanup__ok); +ATF_TC_HEAD(test__cleanup__ok, tc) { setup(tc, true); } +ATF_TC_BODY(test__cleanup__ok, tc) +{ + char* helpers = helpers_path(tc); + check(EXIT_SUCCESS, + "Body stdout\nCleanup stdout\n" + "Cleanup properly ran in the same directory as the body\n", + "Body stderr\nCleanup stderr\n", + "test", "-vhas.cleanup=true", helpers, "cleanup_check_work_directory", + "test-result", NULL); + free(helpers); + + ATF_REQUIRE(atf_utils_compare_file("test-result", "passed\n")); +} + + +ATF_TC(test__cleanup__fail); +ATF_TC_HEAD(test__cleanup__fail, tc) { setup(tc, true); } +ATF_TC_BODY(test__cleanup__fail, tc) +{ + char* helpers = helpers_path(tc); + check(EXIT_FAILURE, "", "", + "test", "-vhas.cleanup=true", helpers, "cleanup_fail", "test-result", + NULL); + free(helpers); + + ATF_REQUIRE(atf_utils_compare_file("test-result", "broken: Test case " + "cleanup exited with code 1\n")); +} + + +ATF_TC(test__cleanup__crash); +ATF_TC_HEAD(test__cleanup__crash, tc) { setup(tc, true); } +ATF_TC_BODY(test__cleanup__crash, tc) +{ + char* helpers = helpers_path(tc); + check(EXIT_FAILURE, "", "save:crash.err", + "test", "-vhas.cleanup=true", helpers, "cleanup_signal", + "test-result", NULL); + free(helpers); + + ATF_REQUIRE(atf_utils_compare_file("test-result", + "broken: Test case cleanup received signal 6 (core dumped)\n")); + + ATF_REQUIRE(atf_utils_grep_file("About to die due to SIGABRT!", + "crash.err")); + ATF_REQUIRE(atf_utils_grep_file("attempting to gather stack trace", + "crash.err")); +} + + +ATF_TC(test__cleanup__timeout); +ATF_TC_HEAD(test__cleanup__timeout, tc) { setup(tc, true); } +ATF_TC_BODY(test__cleanup__timeout, tc) +{ + char* helpers = helpers_path(tc); + check(EXIT_FAILURE, "", "Subprocess timed out; sending KILL signal...\n", + "-t1", "test", "-vhas.cleanup=true", helpers, "cleanup_sleep", + "test-result", NULL); + free(helpers); + + ATF_REQUIRE(atf_utils_compare_file("test-result", "broken: Test case " + "cleanup timed out\n")); +} + + +ATF_TC(test__config__builtin); +ATF_TC_HEAD(test__config__builtin, tc) { setup(tc, true); } +ATF_TC_BODY(test__config__builtin, tc) +{ + char* helpers = helpers_path(tc); + check(EXIT_SUCCESS, "", "", + "test", helpers, "print_config", "test-result", NULL); + free(helpers); + + ATF_REQUIRE(atf_utils_compare_file("test-result", "passed\n")); +} + + +ATF_TC(test__config__custom); +ATF_TC_HEAD(test__config__custom, tc) { setup(tc, true); } +ATF_TC_BODY(test__config__custom, tc) +{ + char* helpers = helpers_path(tc); + check(EXIT_SUCCESS, + "body my-var1 value1\n" + "body v2 a b c foo\n" + "cleanup my-var1 value1\n" + "cleanup v2 a b c foo\n", + "", + "test", "-vmy-var1=value1", "-vv2=a b c foo", helpers, + "print_config", "test-result", NULL); + free(helpers); + + ATF_REQUIRE(atf_utils_compare_file("test-result", "passed\n")); +} + + +ATF_TC(test__invalid_test_case_name); +ATF_TC_HEAD(test__invalid_test_case_name, tc) { setup(tc, false); } +ATF_TC_BODY(test__invalid_test_case_name, tc) +{ + char* helpers = helpers_path(tc); + check(EXIT_FAILURE, "", // TODO(jmmv): Should be EXIT_INTERNAL_ERROR. + "atf_helpers: ERROR: Unknown test case `foo'\n" + "atf_helpers: See atf-test-program(1) for usage details.\n", + "test", "-vhas.cleanup=false", helpers, "foo", "test-result", NULL); + free(helpers); + + ATF_REQUIRE(atf_utils_compare_file("test-result", + "broken: Premature exit; test case exited with code 1\n")); +} + + +ATF_TC(test__missing_test_program); +ATF_TC_HEAD(test__missing_test_program, tc) { setup(tc, false); } +ATF_TC_BODY(test__missing_test_program, tc) +{ + check(EXIT_INTERNAL_ERROR, "", + "kyua-atf-tester: execvp failed: No such file or directory\n", + "test", "./non-existent", "pass", "test-result", NULL); + + ATF_REQUIRE(!atf_utils_file_exists("test-result")); +} + + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, top__missing_command); + ATF_TP_ADD_TC(tp, top__unknown_command); + + ATF_TP_ADD_TC(tp, list__ok); + + ATF_TP_ADD_TC(tp, test__pass); + ATF_TP_ADD_TC(tp, test__fail); + ATF_TP_ADD_TC(tp, test__crash); + ATF_TP_ADD_TC(tp, test__timeout); + ATF_TP_ADD_TC(tp, test__result_priority); + ATF_TP_ADD_TC(tp, test__cleanup__ok); + ATF_TP_ADD_TC(tp, test__cleanup__fail); + ATF_TP_ADD_TC(tp, test__cleanup__crash); + ATF_TP_ADD_TC(tp, test__cleanup__timeout); + ATF_TP_ADD_TC(tp, test__config__builtin); + ATF_TP_ADD_TC(tp, test__config__custom); + ATF_TP_ADD_TC(tp, test__missing_test_program); + ATF_TP_ADD_TC(tp, test__invalid_test_case_name); + + return atf_no_error(); +} diff --git a/external/bsd/kyua-testers/dist/atf_list.c b/external/bsd/kyua-testers/dist/atf_list.c new file mode 100644 index 000000000..b6d46a8c9 --- /dev/null +++ b/external/bsd/kyua-testers/dist/atf_list.c @@ -0,0 +1,355 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "atf_list.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "error.h" + + +/// Expected header in the test program list. +#define TP_LIST_HEADER "Content-Type: application/X-atf-tp; version=\"1\"" + + +/// Same as fgets, but removes any trailing newline from the output string. +/// +/// \param [out] str Pointer to the output buffer. +/// \param size Length of the output buffer. +/// \param [in,out] stream File from which to read the line. +/// +/// \return A pointer to the output buffer if successful; otherwise NULL. +static char* +fgets_no_newline(char* str, int size, FILE* stream) +{ + char* result = fgets(str, size, stream); + if (result != NULL) { + const size_t length = strlen(str); + if (length > 0 && str[length - 1] == '\n') + str[length - 1] = '\0'; + } + return result; +} + + +/// Generates an error for the case where fgets() returns NULL. +/// +/// \param input Stream on which fgets() returned an error. +/// \param message Error message. +/// +/// \return An error object with the error message and any relevant details. +static kyua_error_t +fgets_error(FILE* input, const char* message) +{ + if (feof(input)) { + return kyua_generic_error_new("%s: unexpected EOF", message); + } else { + assert(ferror(input)); + return kyua_libc_error_new(errno, "%s", message); + } +} + + +/// Reads the header of the test cases list. +/// +/// The header does not carry any useful information, so all this function does +/// is ensure the header is valid. +/// +/// \param [in,out] input File from which to read the header. +/// +/// \return OK if the header is valid; an error if it is not. +static kyua_error_t +parse_header(FILE* input) +{ + char line[80]; // It's ugly to have a limit, but it's easier this way. + + if (fgets_no_newline(line, sizeof(line), input) == NULL) + return fgets_error(input, "fgets failed to read test cases list " + "header"); + if (strcmp(line, TP_LIST_HEADER) != 0) + return kyua_generic_error_new("Invalid test cases list header '%s'", + line); + + if (fgets_no_newline(line, sizeof(line), input) == NULL) + return fgets_error(input, "fgets failed to read test cases list " + "header"); + if (strcmp(line, "") != 0) + return kyua_generic_error_new("Incomplete test cases list header"); + + return kyua_error_ok(); +} + + +/// Looks for the first occurrence of any of the specified delimiters. +/// +/// \param container String in which to look for the delimiters. +/// \param delimiters List of delimiters to look for. +/// +/// \return A pointer to the first occurrence of the delimiter, or NULL if +/// there is none. +static char* +find_first_of(char* container, const char* delimiters) +{ + char* ptr = container; + while (*ptr != '\0') { + if (strchr(delimiters, *ptr) != NULL) + return ptr; + ++ptr; + } + return NULL; +} + + +/// Prints a string within single quotes, with proper escaping. +/// +/// \param [in,out] line The line to be printed. This is a non-const pointer +/// and the input string is modified to simplify tokenization. +/// \param [in,out] output Buffer onto which to write the quoted string. +/// \param surrounding If true, surround the printed value with single quotes. +static void +print_quoted(char* line, FILE* output, const bool surrounding) +{ + if (surrounding) + fprintf(output, "'"); + + char* quoteptr; + while ((quoteptr = find_first_of(line, "\'\\")) != NULL) { + const char quote = *quoteptr; + *quoteptr = '\0'; + fprintf(output, "%s\\%c", line, quote); + line = quoteptr + 1; + } + + if (surrounding) + fprintf(output, "%s'", line); + else + fprintf(output, "%s", line); +} + + +/// Parses a property from the test cases list. +/// +/// The property is of the form "name: value", where the value extends to the +/// end of the line without quotations. +/// +/// \param [in,out] line The line to be parsed. This is a non-const pointer +/// and the input string is modified to simplify tokenization. +/// \param [out] key The name of the property if the parsing succeeds. This +/// is a pointer within the input line. +/// \param [out] value The value of the property if the parsing succeeds. This +/// is a pointer within the input line. +/// +/// \return OK if the line contains a valid property; an error otherwise. +/// In case of success, both key and value are updated. +static kyua_error_t +parse_property(char* line, char** const key, char** const value) +{ + char* delim = strstr(line, ": "); + if (delim == NULL) + return kyua_generic_error_new("Invalid property '%s'", line); + *delim = '\0'; *(delim + 1) = '\0'; + + *key = line; + *value = delim + 2; + return kyua_error_ok(); +} + + +/// Static value to denote an error in the return of rewrite_property; +static const char* rewrite_error = "ERROR"; + + +/// Converts the name of an ATF property to a Kyua generic property. +/// +/// \param name The name of the ATF property to process. +/// +/// \return The name of the corresponding Kyua property if the input property is +/// valid; NULL if the property has a custom name that has to be handled in the +/// parent; or rewrite_error if the property is invalid. If this returns +/// rewrite_error, it's OK to pointer-compare the return value to the static +/// symbol for equality. +static const char* +rewrite_property(const char* name) +{ + if (strcmp(name, "descr") == 0) + return "description"; + else if (strcmp(name, "has.cleanup") == 0) + return "has_cleanup"; + else if (strcmp(name, "require.arch") == 0) + return "allowed_architectures"; + else if (strcmp(name, "require.config") == 0) + return "required_configs"; + else if (strcmp(name, "require.files") == 0) + return "required_files"; + else if (strcmp(name, "require.machine") == 0) + return "allowed_platforms"; + else if (strcmp(name, "require.memory") == 0) + return "required_memory"; + else if (strcmp(name, "require.progs") == 0) + return "required_programs"; + else if (strcmp(name, "require.user") == 0) + return "required_user"; + else if (strcmp(name, "timeout") == 0) + return "timeout"; + else if (strlen(name) > 2 && name[0] == 'X' && name[1] == '-') + return NULL; + else + return rewrite_error; +} + + +/// Parses a single test case and writes it to the output. +/// +/// This has to be called after the ident property has been read, and takes care +/// of reading the rest of the test case and printing the parsed result. +/// +/// Be aware that this consumes the newline after the test case. The caller +/// should not look for it. +/// +/// \param [in,out] input File from which to read the header. +/// \param [in,out] output File to which to write the parsed test case. +/// \param [in,out] name The name of the test case. This is a non-const pointer +/// and the input string is modified to simplify tokenization. +/// +/// \return OK if the parsing succeeds; an error otherwise. +static kyua_error_t +parse_test_case(FILE* input, FILE* output, char* name) +{ + kyua_error_t error; + char line[1024]; // It's ugly to have a limit, but it's easier this way. + + fprintf(output, "test_case{name="); + print_quoted(name, output, true); + + error = kyua_error_ok(); + while (!kyua_error_is_set(error) && + fgets_no_newline(line, sizeof(line), input) != NULL && + strcmp(line, "") != 0) { + char* key; char* value; + error = parse_property(line, &key, &value); + if (!kyua_error_is_set(error)) { + const char* out_key = rewrite_property(key); + if (out_key == rewrite_error) { + error = kyua_generic_error_new("Unknown ATF property %s", key); + } else if (out_key == NULL) { + fprintf(output, ", ['custom."); + print_quoted(key, output, false); + fprintf(output, "']="); + print_quoted(value, output, true); + } else { + fprintf(output, ", %s=", out_key); + print_quoted(value, output, true); + } + } + } + + fprintf(output, "}\n"); + + return error; +} + + +/// Rewrites the test cases list from the input to the output. +/// +/// \param [in,out] input Stream from which to read the test program's test +/// cases list. The current location must be after the header and at the +/// first identifier (if any). +/// \param [out] output Stream to which to write the generic list. +/// +/// \return An error object. +static kyua_error_t +parse_tests(FILE* input, FILE* output) +{ + char line[512]; // It's ugly to have a limit, but it's easier this way. + + if (fgets_no_newline(line, sizeof(line), input) == NULL) { + return fgets_error(input, "Empty test cases list"); + } + + kyua_error_t error; + + do { + char* key; char* value; + error = parse_property(line, &key, &value); + if (kyua_error_is_set(error)) + break; + + if (strcmp(key, "ident") == 0) { + error = parse_test_case(input, output, value); + } else { + error = kyua_generic_error_new("Expected ident property, got %s", + key); + } + } while (!kyua_error_is_set(error) && + fgets_no_newline(line, sizeof(line), input) != NULL); + + if (!kyua_error_is_set(error)) { + if (ferror(input)) + error = kyua_libc_error_new(errno, "fgets failed"); + else + assert(feof(input)); + } + + return error; +} + + +/// Reads an ATF test cases list and prints a Kyua definition. +/// +/// \param fd A file descriptor from which to read the test cases list of a test +/// program. Should be connected to the stdout of the latter. This +/// function grabs ownership of the descriptor and releases it in all cases. +/// \param [in,out] output File to which to write the Kyua definition. +/// +/// \return OK if the parsing succeeds; an error otherwise. Note that, if there +/// is an error, the output may not be consistent and should not be used. +kyua_error_t +atf_list_parse(const int fd, FILE* output) +{ + kyua_error_t error; + + FILE* input = fdopen(fd, "r"); + if (input == NULL) { + error = kyua_libc_error_new(errno, "fdopen(%d) failed", fd); + close(fd); + } else { + error = parse_header(input); + if (!kyua_error_is_set(error)) { + error = parse_tests(input, output); + } + fclose(input); + } + + return error; +} diff --git a/external/bsd/kyua-testers/dist/atf_list.h b/external/bsd/kyua-testers/dist/atf_list.h new file mode 100644 index 000000000..4eb6579e2 --- /dev/null +++ b/external/bsd/kyua-testers/dist/atf_list.h @@ -0,0 +1,43 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file atf_list.h +/// Utilities to parse the list of tests cases printed by ATF test programs. + +#if !defined(KYUA_ATF_LIST_H) +#define KYUA_ATF_LIST_H + +#include + +#include "error_fwd.h" + + +kyua_error_t atf_list_parse(const int, FILE*); + + +#endif // !defined(KYUA_ATF_LIST_H) diff --git a/external/bsd/kyua-testers/dist/atf_list_test.c b/external/bsd/kyua-testers/dist/atf_list_test.c new file mode 100644 index 000000000..20197e17c --- /dev/null +++ b/external/bsd/kyua-testers/dist/atf_list_test.c @@ -0,0 +1,237 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "atf_list.h" + +#include + +#include + +#include "error.h" + + +/// Opens a file for reading and fails the test case if the open fails. +/// +/// \param name The file to open. +/// +/// \return A valid file descriptor. +static int +safe_open(const char* name) +{ + const int fd = open(name, O_RDONLY); + ATF_REQUIRE(fd != -1); + return fd; +} + + +/// Test atf_list_parse for a valid case. +/// +/// \param input_name Result file to parse. +/// \param exp_output Expected output of the parsing. +static void +do_ok_test(const char* input_name, const char* exp_output) +{ + FILE* output = fopen("output.txt", "w"); + kyua_error_t error = atf_list_parse(safe_open(input_name), output); + fclose(output); + + if (!atf_utils_compare_file("output.txt", exp_output)) { + atf_utils_create_file("expout.txt", "%s", exp_output); + atf_utils_cat_file("expout.txt", "EXPECTED: "); + atf_utils_cat_file("output.txt", "ACTUAL: "); + atf_tc_fail_nonfatal("Output of atf_list_parse does not match expected " + "results"); + } + + if (kyua_error_is_set(error)) { + char message[1024]; + kyua_error_format(error, message, sizeof(message)); + kyua_error_free(error); + atf_tc_fail("%s", message); + } +} + + +/// Test atf_list_parse for an error case. +/// +/// \param input_name Invalid result file to parse. +/// \param exp_type Expected error type. +/// \param exp_message Expected error message. +static void +do_fail_test(const char* input_name, const char* exp_type, + const char* exp_message) +{ + FILE* output = fopen("output.txt", "w"); + kyua_error_t error = atf_list_parse(safe_open(input_name), output); + fclose(output); + + ATF_REQUIRE(kyua_error_is_set(error)); + ATF_REQUIRE(kyua_error_is_type(error, exp_type)); + + char message[1024]; + kyua_error_format(error, message, sizeof(message)); + kyua_error_free(error); + ATF_REQUIRE_MATCH(exp_message, message); +} + + +ATF_TC_WITHOUT_HEAD(parse__ok__one); +ATF_TC_BODY(parse__ok__one, tc) +{ + atf_utils_create_file( + "input.txt", + "Content-Type: application/X-atf-tp; version=\"1\"\n" + "\n" + "ident: first\n"); + do_ok_test( + "input.txt", + "test_case{name='first'}\n"); +} + + +ATF_TC_WITHOUT_HEAD(parse__ok__several); +ATF_TC_BODY(parse__ok__several, tc) +{ + atf_utils_create_file( + "input.txt", + "Content-Type: application/X-atf-tp; version=\"1\"\n" + "\n" + "ident: first\n" + "require.user: root\n" + "\n" + "ident: second\n" + "\n" + "ident: third\n" + "descr: A string with an embedded ' and \\' in it\n" + "has.cleanup: true\n" + "X-custom: foo\n" + "X-a'b: bar\n"); + do_ok_test( + "input.txt", + "test_case{name='first', required_user='root'}\n" + "test_case{name='second'}\n" + "test_case{name='third', description='A string with an embedded \\' " + "and \\\\\\' in it', has_cleanup='true', ['custom.X-custom']='foo', " + "['custom.X-a\\'b']='bar'}\n"); +} + + +ATF_TC_WITHOUT_HEAD(parse__error__bad_fd); +ATF_TC_BODY(parse__error__bad_fd, tc) +{ + (void)close(10); + kyua_error_t error = atf_list_parse(10, stdout); + + ATF_REQUIRE(kyua_error_is_set(error)); + ATF_REQUIRE(kyua_error_is_type(error, "libc")); + + char message[1024]; + kyua_error_format(error, message, sizeof(message)); + kyua_error_free(error); + ATF_REQUIRE_MATCH("fdopen\\(10\\) failed", message); +} + + +ATF_TC_WITHOUT_HEAD(parse__error__bad_header); +ATF_TC_BODY(parse__error__bad_header, tc) +{ + atf_utils_create_file("input.txt", "%s", ""); + do_fail_test("input.txt", "generic", + "fgets failed to read test cases list header"); + + atf_utils_create_file( + "input.txt", + "Content-Type: application/X-atf-tp; version=\"1234\""); + do_fail_test("input.txt", "generic", + "Invalid test cases list header '.*X-atf-tp.*1234.*'"); + + atf_utils_create_file( + "input.txt", + "Content-Type: application/X-atf-tp; version=\"1\"\n"); + do_fail_test("input.txt", "generic", + "fgets failed to read test cases list header"); + + atf_utils_create_file( + "input.txt", + "Content-Type: application/X-atf-tp; version=\"1\"\n" + "some garbage\n" + "\n"); + do_fail_test("input.txt", "generic", + "Incomplete test cases list header"); +} + + +ATF_TC_WITHOUT_HEAD(parse__error__empty); +ATF_TC_BODY(parse__error__empty, tc) +{ + atf_utils_create_file( + "input.txt", + "Content-Type: application/X-atf-tp; version=\"1\"\n" + "\n"); + do_fail_test("input.txt", "generic", + "Empty test cases list: unexpected EOF"); +} + + +ATF_TC_WITHOUT_HEAD(parse__error__bad_property); +ATF_TC_BODY(parse__error__bad_property, tc) +{ + atf_utils_create_file( + "input.txt", + "Content-Type: application/X-atf-tp; version=\"1\"\n" + "\n" + "oh noes; 2\n"); + do_fail_test("input.txt", "generic", "Invalid property 'oh noes; 2'"); +} + + +ATF_TC_WITHOUT_HEAD(parse__error__bad_order); +ATF_TC_BODY(parse__error__bad_order, tc) +{ + atf_utils_create_file( + "input.txt", + "Content-Type: application/X-atf-tp; version=\"1\"\n" + "\n" + "descr: Some text\n" + "ident: first\n"); + do_fail_test("input.txt", "generic", "Expected ident property, got descr"); +} + + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, parse__ok__one); + ATF_TP_ADD_TC(tp, parse__ok__several); + ATF_TP_ADD_TC(tp, parse__error__bad_fd); + ATF_TP_ADD_TC(tp, parse__error__bad_header); + ATF_TP_ADD_TC(tp, parse__error__empty); + ATF_TP_ADD_TC(tp, parse__error__bad_property); + ATF_TP_ADD_TC(tp, parse__error__bad_order); + + return atf_no_error(); +} diff --git a/external/bsd/kyua-testers/dist/atf_main.c b/external/bsd/kyua-testers/dist/atf_main.c new file mode 100644 index 000000000..66f6642df --- /dev/null +++ b/external/bsd/kyua-testers/dist/atf_main.c @@ -0,0 +1,527 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include + +#include +#include +#include +#include +#include +#include + +#include "atf_list.h" +#include "atf_result.h" +#include "cli.h" +#include "defs.h" +#include "error.h" +#include "fs.h" +#include "run.h" +#include "stacktrace.h" +#include "text.h" + +#if !defined(WCOREDUMP) && defined(__minix) +#define WCOREDUMP(x) ((x) & 0x80) +#endif /*!defined(WCOREDUMP) && defined(__minix) */ + + +/// Template for the creation of the temporary work directories. +#define WORKDIR_TEMPLATE "kyua.atf-tester.XXXXXX" + + +static void run_list(const char*, const int[2]) KYUA_DEFS_NORETURN; + + +/// Executes the test program in list mode. +/// +/// \param test_program Path to the test program to execute; should be absolute. +/// \param stdout_fds Pipe to write the output of the test program to. +static void +run_list(const char* test_program, const int stdout_fds[2]) +{ + (void)close(stdout_fds[0]); + + if (stdout_fds[1] != STDOUT_FILENO) { + if (dup2(stdout_fds[1], STDOUT_FILENO) == -1) + err(EXIT_FAILURE, "dup2 failed"); + (void)close(stdout_fds[1]); + } + + if (dup2(STDOUT_FILENO, STDERR_FILENO) == -1) + err(EXIT_FAILURE, "dup2 failed"); + + const char* const program_args[] = { test_program, "-l", NULL }; + kyua_run_exec(test_program, program_args); +} + + +/// Dumps the contents of the input file into the output. +/// +/// \param input File from which to read. +/// \param output File to which to write. +/// +/// \return An error if there is a problem. +static kyua_error_t +dump_file(FILE* input, FILE* output) +{ + char buffer[1024]; + size_t length; + + while ((length = fread(buffer, 1, sizeof(buffer), input)) > 0) { + if (fwrite(buffer, 1, length, output) != length) { + return kyua_generic_error_new("Failed to write to output file"); + } + } + if (ferror(input)) + return kyua_libc_error_new(errno, "Failed to read test cases list"); + + return kyua_error_ok(); +} + + +/// Creates a file within the work directory. +/// +/// \param work_directory Path to the work directory. +/// \param name Name of the file to create. +/// \param mode Mode of the file, as specified by fopen(3). +/// \param [out] file Pointer to the created stream. +/// +/// \return An error if there is a problem. +static kyua_error_t +create_file_in_work_directory(const char* work_directory, const char* name, + const char* mode, FILE** file) +{ + char* path; + kyua_error_t error = kyua_fs_concat(&path, work_directory, name, NULL); + if (kyua_error_is_set(error)) + goto out; + + FILE* tmp_file = fopen(path, mode); + if (tmp_file == NULL) { + error = kyua_libc_error_new(errno, "Failed to create %s", path); + goto out_path; + } + + *file = tmp_file; + + assert(!kyua_error_is_set(error)); +out_path: + free(path); +out: + return error; +} + + +/// Lists the test cases in a test program. +/// +/// \param test_program Path to the test program for which to list the test +/// cases. Should be absolute. +/// \param run_params Execution parameters to configure the test process. +/// +/// \return An error if the listing fails; OK otherwise. +static kyua_error_t +list_test_cases(const char* test_program, const kyua_run_params_t* run_params) +{ + kyua_error_t error; + + char* work_directory; + error = kyua_run_work_directory_enter(WORKDIR_TEMPLATE, + run_params->unprivileged_user, + run_params->unprivileged_group, + &work_directory); + if (kyua_error_is_set(error)) + goto out; + kyua_run_params_t real_run_params = *run_params; + real_run_params.work_directory = work_directory; + + int stdout_fds[2]; + if (pipe(stdout_fds) == -1) { + error = kyua_libc_error_new(errno, "pipe failed"); + goto out_work_directory; + } + + pid_t pid; + error = kyua_run_fork(&real_run_params, &pid); + if (!kyua_error_is_set(error) && pid == 0) { + run_list(test_program, stdout_fds); + } + assert(pid != -1 && pid != 0); + if (kyua_error_is_set(error)) + goto out_stdout_fds; + + FILE* tmp_output = NULL; // Initialize to shut up gcc warning. + error = create_file_in_work_directory(real_run_params.work_directory, + "list.txt", "w+", &tmp_output); + if (kyua_error_is_set(error)) + goto out_stdout_fds; + + close(stdout_fds[1]); stdout_fds[1] = -1; + kyua_error_t parse_error = atf_list_parse(stdout_fds[0], tmp_output); + stdout_fds[0] = -1; // Guaranteed closed by atf_list_parse. + // Delay reporting of parse errors to later. If we detect a problem while + // waiting for the test program, we know that the parsing has most likely + // failed and therefore the error with the program is more important for + // reporting purposes. + + int status; bool timed_out; + error = kyua_run_wait(pid, &status, &timed_out); + if (kyua_error_is_set(error)) + goto out_tmp_output; + if (!WIFEXITED(status) || WEXITSTATUS(status) != EXIT_SUCCESS) { + error = kyua_generic_error_new("Test program list did not return " + "success"); + goto out_tmp_output; + } + + error = kyua_error_subsume(error, parse_error); + if (!kyua_error_is_set(error)) { + rewind(tmp_output); + error = dump_file(tmp_output, stdout); + } + +out_tmp_output: + fclose(tmp_output); +out_stdout_fds: + if (stdout_fds[0] != -1) + close(stdout_fds[0]); + if (stdout_fds[1] != -1) + close(stdout_fds[1]); +out_work_directory: + error = kyua_error_subsume(error, + kyua_run_work_directory_leave(&work_directory)); +out: + return error; +} + + +/// Counts the length of a user variables array. +/// +/// \param user_variables The array of elements to be counted. +/// +/// \return The length of the array. +static size_t +count_variables(const char* const user_variables[]) +{ + size_t count = 0; + const char* const* iter; + for (iter = user_variables; *iter != NULL; ++iter) + count++; + return count; +} + + +static void exec_body(const char* test_program, const char* test_case, + const char* result_file, + const char* const user_variables[]) KYUA_DEFS_NORETURN; + + +/// Executes the body of a test case. +/// +/// \param test_program Path to the test program to execute. +/// \param test_case Name of the test case to run. +/// \param result_file Path to the ATF result file to be created. +/// \param user_variables Set of configuration variables to pass to the test. +static void +exec_body(const char* test_program, const char* test_case, + const char* result_file, const char* const user_variables[]) +{ + const size_t nargs = + 1 /* test_program */ + + 2 /* -r result_file */ + + 2 * count_variables(user_variables) /* -v name=value */ + + 1 /* test_case */ + + 1 /* NULL */; + + const char** args = malloc(sizeof(const char*) * nargs); + if (args == NULL) + kyua_error_err(EXIT_FAILURE, kyua_oom_error_new(), + "Failed to construct arguments list"); + + size_t i = 0; + args[i++] = test_program; + args[i++] = "-r"; + args[i++] = result_file; + const char* const* iter; + for (iter = user_variables; *iter != NULL; ++iter) { + args[i++] = "-v"; + args[i++] = *iter; + } + args[i++] = test_case; + args[i++] = NULL; + assert(i == nargs); + + kyua_run_exec(test_program, args); +} + + +/// Forks and executes the body of a test case in a controlled manner. +/// +/// \param test_program Path to the test program to execute. +/// \param test_case Name of the test case to run. +/// \param result_file Path to the ATF result file to be created. +/// \param user_variables Set of configuration variables to pass to the test. +/// \param run_params Settings to control the subprocess. +/// \param [out] success Set to true if the test case runs properly and returns +/// a result that is to be considered as successful. +/// +/// \return OK if all goes well, an error otherwise. Note that a failed test +/// case is denoted by setting success to false on exit, not by returning an +/// error. +static kyua_error_t +run_body(const char* test_program, const char* test_case, + const char* result_file, const char* const user_variables[], + const kyua_run_params_t* run_params, bool* success) +{ + kyua_error_t error; + + char* tmp_result_file; + error = kyua_fs_concat(&tmp_result_file, run_params->work_directory, + "result.txt", NULL); + if (kyua_error_is_set(error)) + goto out; + + pid_t pid; + error = kyua_run_fork(run_params, &pid); + if (!kyua_error_is_set(error) && pid == 0) { + exec_body(test_program, test_case, tmp_result_file, user_variables); + } + assert(pid != -1 && pid != 0); + if (kyua_error_is_set(error)) + goto out_tmp_result_file; + + int status; bool timed_out; + error = kyua_run_wait(pid, &status, &timed_out); + if (kyua_error_is_set(error)) + goto out_tmp_result_file; + + if (WIFSIGNALED(status) && WCOREDUMP(status)) { + kyua_stacktrace_dump(test_program, pid, run_params, stderr); + } + + error = kyua_atf_result_rewrite(tmp_result_file, result_file, status, + timed_out, success); + +out_tmp_result_file: + free(tmp_result_file); +out: + return error; +} + + +static void exec_cleanup(const char* test_program, const char* test_case, + const char* const user_variables[]) KYUA_DEFS_NORETURN; + + +/// Executes the cleanup of a test case. +/// +/// \param test_program Path to the test program to execute. +/// \param test_case Name of the test case to run. +/// \param user_variables Set of configuration variables to pass to the test. +static void +exec_cleanup(const char* test_program, const char* test_case, + const char* const user_variables[]) +{ + char* name; + kyua_error_t error = kyua_text_printf(&name, "%s:cleanup", test_case); + if (kyua_error_is_set(error)) + kyua_error_err(EXIT_FAILURE, error, + "Failed to construct argument list"); + + const size_t nargs = + 1 /* test_program */ + + + 2 * count_variables(user_variables) /* -v name=value */ + + 1 /* test_case */ + + 1 /* NULL */; + + const char** args = malloc(sizeof(const char*) * nargs); + if (args == NULL) + kyua_error_err(EXIT_FAILURE, kyua_oom_error_new(), + "Failed to construct arguments list"); + + size_t i = 0; + args[i++] = test_program; + const char* const* iter; + for (iter = user_variables; *iter != NULL; ++iter) { + args[i++] = "-v"; + args[i++] = *iter; + } + args[i++] = name; + args[i++] = NULL; + assert(i == nargs); + + kyua_run_exec(test_program, args); +} + + +/// Forks and executes the cleanup of a test case in a controlled manner. +/// +/// \param test_program Path to the test program to execute. +/// \param test_case Name of the test case to run. +/// \param result_file Path to the ATF result file created by the body of the +/// test case. The cleanup may update such file if it fails. +/// \param user_variables Set of configuration variables to pass to the test. +/// \param run_params Settings to control the subprocess. +/// \param body_success The success value returned by run_body(). +/// \param [out] success Set to true if the test case runs properly and returns +/// a result that is to be considered as successful. +/// +/// \return OK if all goes well, an error otherwise. Note that a failed test +/// case cleanup is denoted by setting success to false on exit, not by +/// returning an error. +static kyua_error_t +run_cleanup(const char* test_program, const char* test_case, + const char* result_file, const char* const user_variables[], + const kyua_run_params_t* run_params, const bool body_success, + bool* success) +{ + kyua_error_t error; + + pid_t pid; + error = kyua_run_fork(run_params, &pid); + if (!kyua_error_is_set(error) && pid == 0) { + exec_cleanup(test_program, test_case, user_variables); + } + assert(pid != -1 && pid != 0); + if (kyua_error_is_set(error)) + goto out; + + int status; bool timed_out; + error = kyua_run_wait(pid, &status, &timed_out); + if (kyua_error_is_set(error)) + goto out; + + if (WIFSIGNALED(status) && WCOREDUMP(status)) { + kyua_stacktrace_dump(test_program, pid, run_params, stderr); + } + + if (body_success) { + // If the body has reported a successful result, we inspect the status + // of the cleanup routine. If the cleanup has failed, then we need to + // mark the test as broken. However, if the body itself had failed, we + // don't do this to give preference to the original result, which is + // probably more informative. + error = kyua_atf_result_cleanup_rewrite(result_file, status, + timed_out, success); + } + +out: + return error; +} + + +/// Checks if the user variables indicate that a test has a cleanup routine. +/// +/// This is an ugly hack to allow us to run the cleanup routine only when a test +/// case has it. When Kyua invokes the tester to generate the test case list, +/// the tester tells Kyua which tests have a cleanup routine. However, when the +/// tests are later run from here (as a different invocation) we cannot know if +/// the test had a cleanup routine or not. We rely on Kyua telling us this fact +/// by specifying has.cleanup=true in the variables. +/// +/// \param user_variables Array of name=value pairs that describe the user +/// configuration variables for the test case. +static bool +has_cleanup(const char* const* user_variables) +{ + const char* const* iter; + for (iter = user_variables; *iter != NULL; ++iter) { + if (strcmp(*iter, "has.cleanup=false") == 0) + return false; + } + + // The default is true because not running a cleanup routine when it exists + // is worse than running an empty routine when not told to do so. + return true; +} + + +/// Runs a single test cases of a test program. +/// +/// \param test_program Path to the test program for which to list the test +/// cases. Should be absolute. +/// \param test_case Name of the test case to run. +/// \param result_file Path to the file to which to write the result of the +/// test. Should be absolute. +/// \param user_variables Array of name=value pairs that describe the user +/// configuration variables for the test case. +/// \param run_params Execution parameters to configure the test process. +/// \param [out] success Set to true if the test case reported a valid exit +/// condition (like "passed" or "skipped"); false otherwise. This is +/// only updated if the method returns OK. +/// +/// \return An error if the listing fails; OK otherwise. +static kyua_error_t +run_test_case(const char* test_program, const char* test_case, + const char* result_file, const char* const user_variables[], + const kyua_run_params_t* run_params, bool* success) +{ + kyua_error_t error; + + char* work_directory; + error = kyua_run_work_directory_enter(WORKDIR_TEMPLATE, + run_params->unprivileged_user, + run_params->unprivileged_group, + &work_directory); + if (kyua_error_is_set(error)) + goto out; + kyua_run_params_t real_run_params = *run_params; + real_run_params.work_directory = work_directory; + + error = run_body(test_program, test_case, result_file, user_variables, + &real_run_params, success); + if (has_cleanup(user_variables)) { + error = run_cleanup(test_program, test_case, result_file, + user_variables, &real_run_params, *success, + success); + } + + error = kyua_error_subsume(error, + kyua_run_work_directory_leave(&work_directory)); +out: + return error; +} + + +/// Definition of the tester. +static kyua_cli_tester_t atf_tester = { + .list_test_cases = list_test_cases, + .run_test_case = run_test_case, +}; + + +/// Tester entry point. +/// +/// \param argc Number of command line arguments. +/// \param argv NULL-terminated array of command line arguments. +/// +/// \return An exit code. +int +main(const int argc, char* const* const argv) +{ + return kyua_cli_main(argc, argv, &atf_tester); +} diff --git a/external/bsd/kyua-testers/dist/atf_result.c b/external/bsd/kyua-testers/dist/atf_result.c new file mode 100644 index 000000000..d2b05f015 --- /dev/null +++ b/external/bsd/kyua-testers/dist/atf_result.c @@ -0,0 +1,767 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "atf_result.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "error.h" +#include "result.h" + +#if !defined(WCOREDUMP) && defined(__minix) +#define WCOREDUMP(x) ((x) & 0x80) +#endif /*!defined(WCOREDUMP) && defined(__minix) */ + + +// Enumeration of the different result types returned by an ATF test case. +enum atf_status { + ATF_STATUS_EXPECTED_DEATH, + ATF_STATUS_EXPECTED_EXIT, + ATF_STATUS_EXPECTED_FAILURE, + ATF_STATUS_EXPECTED_SIGNAL, + ATF_STATUS_EXPECTED_TIMEOUT, + ATF_STATUS_FAILED, + ATF_STATUS_PASSED, + ATF_STATUS_SKIPPED, + + // The broken status below is never returned by the test cases themselves. + // We use it internally to pass around problems detected while dealing with + // the test case itself (like an invalid result file). + ATF_STATUS_BROKEN, +}; + + +/// Magic number representing a missing argument to the test result status. +/// +/// Use this to specify that an expected_exit or expected_signal result accepts +/// any exit code or signal, respectively. +#define NO_STATUS_ARG -1 + + +/// Removes a trailing newline from a string (supposedly read by fgets(3)). +/// +/// \param [in,out] str The string to remove the trailing newline from. +/// +/// \return True if there was a newline character; false otherwise. +static bool +trim_newline(char* str) +{ + const size_t length = strlen(str); + if (length == 0) { + return false; + } else { + if (str[length - 1] == '\n') { + str[length - 1] = '\0'; + return true; + } else { + return false; + } + } +} + + +/// Force read on stream to see if we are really at EOF. +/// +/// A call to fgets(3) will not return EOF when it returns valid data. But +/// because of our semantics below, we need to be able to tell if more lines are +/// available before actually reading them. +/// +/// \param input The stream to check for EOF. +/// +/// \return True if the stream is not at EOF yet; false otherwise. +static bool +is_really_eof(FILE* input) +{ + const int ch = getc(input); + const bool real_eof = feof(input); + (void)ungetc(ch, input); + return real_eof; +} + + +/// Parses the optional argument to a result status. +/// +/// \param str Pointer to the argument. May be \0 in those cases where the +/// status does not have any argument. +/// \param [out] status_arg Value of the parsed argument. +/// +/// \return OK if the argument exists and is valid, or if it does not exist; an +/// error otherwise. +static kyua_error_t +parse_status_arg(const char* str, int* status_arg) +{ + if (*str == '\0') { + *status_arg = NO_STATUS_ARG; + return kyua_error_ok(); + } + + const size_t length = strlen(str); + if (*str != '(' || *(str + length - 1) != ')') + return kyua_generic_error_new("Invalid status argument %s", str); + const char* const arg = str + 1; + + char* endptr; + const long value = strtol(arg, &endptr, 10); + if (arg[0] == '\0' || endptr != str + length - 1) + return kyua_generic_error_new("Invalid status argument %s: not a " + "number", str); + if (errno == ERANGE && (value == LONG_MAX || value == LONG_MIN)) + return kyua_generic_error_new("Invalid status argument %s: out of " + "range", str); + if (value < INT_MIN || value > INT_MAX) + return kyua_generic_error_new("Invalid status argument %s: out of " + "range", str); + + *status_arg = (int)value; + return kyua_error_ok(); +} + + +/// Parses a textual result status. +/// +/// \param str The text to parse. +/// \param [out] status Status type if the input is valid. +/// \param [out] status_arg Optional integral argument to the status. +/// \param [out] need_reason Whether the detected status requires a reason. +/// +/// \return An error if the status is not valid. +static kyua_error_t +parse_status(const char* str, enum atf_status* status, int* status_arg, + bool* need_reason) +{ + if (strcmp(str, "passed") == 0) { + *status = ATF_STATUS_PASSED; + *need_reason = false; + return kyua_error_ok(); + } else if (strcmp(str, "failed") == 0) { + *status = ATF_STATUS_FAILED; + *need_reason = true; + return kyua_error_ok(); + } else if (strcmp(str, "skipped") == 0) { + *status = ATF_STATUS_SKIPPED; + *need_reason = true; + return kyua_error_ok(); + } else if (strcmp(str, "expected_death") == 0) { + *status = ATF_STATUS_EXPECTED_DEATH; + *need_reason = true; + return kyua_error_ok(); + } else if (strncmp(str, "expected_exit", 13) == 0) { + *status = ATF_STATUS_EXPECTED_EXIT; + *need_reason = true; + return parse_status_arg(str + 13, status_arg); + } else if (strcmp(str, "expected_failure") == 0) { + *status = ATF_STATUS_EXPECTED_FAILURE; + *need_reason = true; + return kyua_error_ok(); + } else if (strncmp(str, "expected_signal", 15) == 0){ + *status = ATF_STATUS_EXPECTED_SIGNAL; + *need_reason = true; + return parse_status_arg(str + 15, status_arg); + } else if (strcmp(str, "expected_timeout") == 0) { + *status = ATF_STATUS_EXPECTED_TIMEOUT; + *need_reason = true; + return kyua_error_ok(); + } else { + return kyua_generic_error_new("Unknown test case result status %s", + str); + } +} + + +/// Advances a pointer to a buffer to its end. +/// +/// \param [in,out] buffer Current buffer contents; updated on exit to point to +/// the termination character. +/// \param [in,out] buffer_size Current buffer size; updated on exit to account +/// for the decreased capacity due to the pointer increase. +static void +advance(char** buffer, size_t* buffer_size) +{ + const size_t increment = strlen(*buffer); + *buffer += increment; + *buffer_size -= increment; +} + + +/// Extracts the result reason from the input file. +/// +/// \pre This can only be called for those result types that require a reason. +/// +/// \param [in,out] input The file from which to read. +/// \param first_line The first line of the reason. Because this is part of the +/// same line in which the result status is printed, this line has already +/// been read by the caller and thus must be provided here. +/// \param [out] output Buffer to which to write the full reason. +/// \param output_size Size of the output buffer. +/// +/// \return An error if there was no reason in the input or if there is a +/// problem reading it. +static kyua_error_t +read_reason(FILE* input, const char* first_line, char* output, + size_t output_size) +{ + if (first_line == NULL || *first_line == '\0') + return kyua_generic_error_new("Test case should have reported a " + "failure reason but didn't"); + + snprintf(output, output_size, "%s", first_line); + advance(&output, &output_size); + + bool had_newline = true; + while (!is_really_eof(input)) { + if (had_newline) { + snprintf(output, output_size, "<>"); + advance(&output, &output_size); + } + + if (fgets(output, output_size, input) == NULL) { + assert(ferror(input)); + return kyua_libc_error_new(errno, "Failed to read reason from " + "result file"); + } + had_newline = trim_newline(output); + advance(&output, &output_size); + } + + return kyua_error_ok(); +} + + +/// Parses a results file written by an ATF test case. +/// +/// \param input_name Path to the result file to parse. +/// \param [out] status Type of result. +/// \param [out] status_arg Optional integral argument to the status. +/// \param [out] reason Textual explanation of the result, if any. +/// \param reason_size Length of the reason output buffer. +/// +/// \return An error if the input_name file has an invalid syntax; OK otherwise. +static kyua_error_t +read_atf_result(const char* input_name, enum atf_status* status, + int* status_arg, char* const reason, const size_t reason_size) +{ + kyua_error_t error = kyua_error_ok(); + + FILE* input = fopen(input_name, "r"); + if (input == NULL) { + error = kyua_generic_error_new("Premature exit"); + goto out; + } + + char line[1024]; + if (fgets(line, sizeof(line), input) == NULL) { + if (ferror(input)) { + error = kyua_libc_error_new(errno, "Failed to read result from " + "file %s", input_name); + goto out_input; + } else { + assert(feof(input)); + error = kyua_generic_error_new("Empty result file %s", input_name); + goto out_input; + } + } + + if (!trim_newline(line)) { + error = kyua_generic_error_new("Missing newline in result file"); + goto out_input; + } + + char* reason_start = strstr(line, ": "); + if (reason_start != NULL) { + *reason_start = '\0'; + *(reason_start + 1) = '\0'; + reason_start += 2; + } + + bool need_reason = false; // Initialize to shut up gcc warning. + error = parse_status(line, status, status_arg, &need_reason); + if (kyua_error_is_set(error)) + goto out_input; + + if (need_reason) { + error = read_reason(input, reason_start, reason, reason_size); + } else { + if (reason_start != NULL || !is_really_eof(input)) { + error = kyua_generic_error_new("Found unexpected reason in passed " + "test result"); + goto out_input; + } + reason[0] = '\0'; + } + +out_input: + fclose(input); +out: + return error; +} + + +/// Writes a generic result file for an ATF broken result. +/// +/// \param reason Textual explanation of the result. +/// \param status Exit code of the test program as returned by wait(). +/// \param output Path to the generic result file to create. +/// \param [out] success Whether the result should be considered a success or +/// not; e.g. passed and skipped are successful, but failed is not. +/// +/// \return An error if the conversion fails; OK otherwise. +static kyua_error_t +convert_broken(const char* reason, int status, const char* output, + bool* success) +{ + if (WIFEXITED(status)) { + *success = false; + return kyua_result_write( + output, KYUA_RESULT_BROKEN, "%s; test case exited with code %d", + reason, WEXITSTATUS(status)); + } else { + assert(WIFSIGNALED(status)); + *success = false; + return kyua_result_write( + output, KYUA_RESULT_BROKEN, "%s; test case received signal %d%s", + reason, WTERMSIG(status), + WCOREDUMP(status) ? " (core dumped)" : ""); + } +} + + +/// Writes a generic result file for an ATF expected_death result. +/// +/// \param reason Textual explanation of the result. +/// \param status Exit code of the test program as returned by wait(). +/// \param output Path to the generic result file to create. +/// \param [out] success Whether the result should be considered a success or +/// not; e.g. passed and skipped are successful, but failed is not. +/// +/// \return An error if the conversion fails; OK otherwise. +static kyua_error_t +convert_expected_death(const char* reason, int status, const char* output, + bool* success) +{ + if (WIFEXITED(status) && WEXITSTATUS(status) == EXIT_SUCCESS) { + *success = false; + return kyua_result_write( + output, KYUA_RESULT_FAILED, "Test case expected to die but exited " + "successfully"); + } else { + *success = true; + return kyua_result_write( + output, KYUA_RESULT_EXPECTED_FAILURE, "%s", reason); + } +} + + +/// Writes a generic result file for an ATF expected_exit result +/// +/// \param status_arg Optional integral argument to the status. +/// \param reason Textual explanation of the result. +/// \param status Exit code of the test program as returned by wait(). +/// \param output Path to the generic result file to create. +/// \param [out] success Whether the result should be considered a success or +/// not; e.g. passed and skipped are successful, but failed is not. +/// +/// \return An error if the conversion fails; OK otherwise. +static kyua_error_t +convert_expected_exit(const int status_arg, const char* reason, int status, + const char* output, bool* success) +{ + if (WIFEXITED(status)) { + if (status_arg == NO_STATUS_ARG || status_arg == WEXITSTATUS(status)) { + *success = true; + return kyua_result_write( + output, KYUA_RESULT_EXPECTED_FAILURE, "%s", reason); + } else { + *success = false; + return kyua_result_write( + output, KYUA_RESULT_FAILED, "Test case expected to exit with " + "code %d but got code %d", status_arg, WEXITSTATUS(status)); + } + } else { + assert(WIFSIGNALED(status)); + *success = false; + return kyua_result_write( + output, KYUA_RESULT_FAILED, "Test case expected to exit normally " + "but received signal %d%s", WTERMSIG(status), + WCOREDUMP(status) ? " (core dumped)" : ""); + } +} + + +/// Writes a generic result file for an ATF expected_failure result. +/// +/// \param reason Textual explanation of the result. +/// \param status Exit code of the test program as returned by wait(). +/// \param output Path to the generic result file to create. +/// \param [out] success Whether the result should be considered a success or +/// not; e.g. passed and skipped are successful, but failed is not. +/// +/// \return An error if the conversion fails; OK otherwise. +static kyua_error_t +convert_expected_failure(const char* reason, int status, const char* output, + bool* success) +{ + if (WIFEXITED(status)) { + if (WEXITSTATUS(status) == EXIT_SUCCESS) { + *success = true; + return kyua_result_write( + output, KYUA_RESULT_EXPECTED_FAILURE, "%s", reason); + } else { + *success = false; + return kyua_result_write( + output, KYUA_RESULT_FAILED, "Test case expected a failure but " + "exited with error code %d", WEXITSTATUS(status)); + } + } else { + assert(WIFSIGNALED(status)); + *success = false; + return kyua_result_write( + output, KYUA_RESULT_FAILED, "Test case expected a failure but " + "received signal %d%s", WTERMSIG(status), + WCOREDUMP(status) ? " (core dumped)" : ""); + } +} + + +/// Writes a generic result file for an ATF expected_signal result. +/// +/// \param status_arg Optional integral argument to the status. +/// \param reason Textual explanation of the result. +/// \param status Exit code of the test program as returned by wait(). +/// \param output Path to the generic result file to create. +/// \param [out] success Whether the result should be considered a success or +/// not; e.g. passed and skipped are successful, but failed is not. +/// +/// \return An error if the conversion fails; OK otherwise. +static kyua_error_t +convert_expected_signal(const int status_arg, const char* reason, int status, + const char* output, bool* success) +{ + if (WIFSIGNALED(status)) { + if (status_arg == NO_STATUS_ARG || status_arg == WTERMSIG(status)) { + *success = true; + return kyua_result_write( + output, KYUA_RESULT_EXPECTED_FAILURE, "%s", reason); + } else { + *success = false; + return kyua_result_write( + output, KYUA_RESULT_FAILED, "Test case expected to receive " + "signal %d but got %d", status_arg, WTERMSIG(status)); + } + } else { + assert(WIFEXITED(status)); + *success = false; + return kyua_result_write( + output, KYUA_RESULT_FAILED, "Test case expected to receive a " + "signal but exited with code %d", WEXITSTATUS(status)); + } +} + + +/// Writes a generic result file for an ATF expected_timeout result. +/// +/// \param status Exit code of the test program as returned by wait(). +/// \param output Path to the generic result file to create. +/// \param [out] success Whether the result should be considered a success or +/// not; e.g. passed and skipped are successful, but failed is not. +/// +/// \return An error if the conversion fails; OK otherwise. +static kyua_error_t +convert_expected_timeout(int status, const char* output, bool* success) +{ + if (WIFEXITED(status)) { + *success = false; + return kyua_result_write( + output, KYUA_RESULT_FAILED, "Test case expected to time out but " + "exited with code %d", WEXITSTATUS(status)); + } else { + assert(WIFSIGNALED(status)); + *success = false; + return kyua_result_write( + output, KYUA_RESULT_FAILED, "Test case expected to time out but " + "received signal %d%s", WTERMSIG(status), + WCOREDUMP(status) ? " (core dumped)" : ""); + } +} + + +/// Writes a generic result file for an ATF failed result. +/// +/// \param reason Textual explanation of the result. +/// \param status Exit code of the test program as returned by wait(). +/// \param output Path to the generic result file to create. +/// \param [out] success Whether the result should be considered a success or +/// not; e.g. passed and skipped are successful, but failed is not. +/// +/// \return An error if the conversion fails; OK otherwise. +static kyua_error_t +convert_failed(const char* reason, int status, const char* output, + bool* success) +{ + if (WIFEXITED(status)) { + if (WEXITSTATUS(status) == EXIT_SUCCESS) { + *success = false; + return kyua_result_write( + output, KYUA_RESULT_BROKEN, "Test case reported a failed " + "result but exited with a successful exit code"); + } else { + *success = false; + return kyua_result_write( + output, KYUA_RESULT_FAILED, "%s", reason); + } + } else { + assert(WIFSIGNALED(status)); + *success = false; + return kyua_result_write( + output, KYUA_RESULT_BROKEN, "Test case reported a failed result " + "but received signal %d%s", WTERMSIG(status), + WCOREDUMP(status) ? " (core dumped)" : ""); + } +} + + +/// Writes a generic result file for an ATF passed result. +/// +/// \param status Exit code of the test program as returned by wait(). +/// \param output Path to the generic result file to create. +/// \param [out] success Whether the result should be considered a success or +/// not; e.g. passed and skipped are successful, but failed is not. +/// +/// \return An error if the conversion fails; OK otherwise. +static kyua_error_t +convert_passed(int status, const char* output, bool* success) +{ + if (WIFEXITED(status)) { + if (WEXITSTATUS(status) == EXIT_SUCCESS) { + *success = true; + return kyua_result_write(output, KYUA_RESULT_PASSED, NULL); + } else { + *success = false; + return kyua_result_write( + output, KYUA_RESULT_BROKEN, "Test case reported a passed " + "result but returned a non-zero exit code %d", + WEXITSTATUS(status)); + } + } else { + assert(WIFSIGNALED(status)); + *success = false; + return kyua_result_write( + output, KYUA_RESULT_BROKEN, "Test case reported a passed result " + "but received signal %d%s", WTERMSIG(status), + WCOREDUMP(status) ? " (core dumped)" : ""); + } +} + + +/// Writes a generic result file for an ATF skipped result. +/// +/// \param reason Textual explanation of the result. +/// \param status Exit code of the test program as returned by wait(). +/// \param output Path to the generic result file to create. +/// \param [out] success Whether the result should be considered a success or +/// not; e.g. passed and skipped are successful, but failed is not. +/// +/// \return An error if the conversion fails; OK otherwise. +static kyua_error_t +convert_skipped(const char* reason, int status, const char* output, + bool* success) +{ + if (WIFEXITED(status)) { + if (WEXITSTATUS(status) == EXIT_SUCCESS) { + *success = true; + return kyua_result_write(output, KYUA_RESULT_SKIPPED, "%s", reason); + } else { + *success = false; + return kyua_result_write( + output, KYUA_RESULT_BROKEN, "Test case reported a skipped " + "result but returned a non-zero exit code %d", + WEXITSTATUS(status)); + } + } else { + *success = false; + assert(WIFSIGNALED(status)); + return kyua_result_write( + output, KYUA_RESULT_BROKEN, "Test case reported a skipped result " + "but received signal %d%s", WTERMSIG(status), + WCOREDUMP(status) ? " (core dumped)" : ""); + } +} + + +/// Writes a generic result file based on an ATF result and an exit code. +/// +/// \param status Type of the ATF result. +/// \param status_arg Optional integral argument to the status. +/// \param reason Textual explanation of the result. +/// \param wait_status Exit code of the test program as returned by wait(). +/// \param timed_out Whether the test program timed out or not. +/// \param output Path to the generic result file to create. +/// \param [out] success Whether the result should be considered a success or +/// not; e.g. passed and skipped are successful, but failed is not. +/// +/// \return An error if the conversion fails; OK otherwise. +static kyua_error_t +convert_result(const enum atf_status status, const int status_arg, + const char* reason, const int wait_status, const bool timed_out, + const char* output, bool* success) +{ + if (timed_out) { + if (status == ATF_STATUS_EXPECTED_TIMEOUT) { + *success = true; + return kyua_result_write( + output, KYUA_RESULT_EXPECTED_FAILURE, "%s", reason); + } else { + assert(status == ATF_STATUS_BROKEN); + *success = false; + return kyua_result_write( + output, KYUA_RESULT_BROKEN, "Test case body timed out"); + } + } + + switch (status) { + case ATF_STATUS_BROKEN: + return convert_broken(reason, wait_status, output, success); + + case ATF_STATUS_EXPECTED_DEATH: + return convert_expected_death(reason, wait_status, output, success); + + case ATF_STATUS_EXPECTED_EXIT: + return convert_expected_exit(status_arg, reason, wait_status, output, + success); + + case ATF_STATUS_EXPECTED_FAILURE: + return convert_expected_failure(reason, wait_status, output, success); + + case ATF_STATUS_EXPECTED_SIGNAL: + return convert_expected_signal(status_arg, reason, wait_status, output, + success); + + case ATF_STATUS_EXPECTED_TIMEOUT: + return convert_expected_timeout(wait_status, output, success); + + case ATF_STATUS_FAILED: + return convert_failed(reason, wait_status, output, success); + + case ATF_STATUS_PASSED: + return convert_passed(wait_status, output, success); + + case ATF_STATUS_SKIPPED: + return convert_skipped(reason, wait_status, output, success); + } + + assert(false); +} + + +/// Writes a generic result file based on an ATF result file and an exit code. +/// +/// \param input_name Path to the ATF result file to parse. +/// \param output_name Path to the generic result file to create. +/// \param wait_status Exit code of the test program as returned by wait(). +/// \param timed_out Whether the test program timed out or not. +/// \param [out] success Whether the result should be considered a success or +/// not; e.g. passed and skipped are successful, but failed is not. +/// +/// \return An error if the conversion fails; OK otherwise. +kyua_error_t +kyua_atf_result_rewrite(const char* input_name, const char* output_name, + const int wait_status, const bool timed_out, + bool* success) +{ + enum atf_status status; int status_arg; char reason[1024]; + status = ATF_STATUS_BROKEN; // Initialize to shut up gcc warning. + const kyua_error_t error = read_atf_result(input_name, &status, &status_arg, + reason, sizeof(reason)); + if (kyua_error_is_set(error)) { + // Errors while parsing the ATF result file can often be attributed to + // the result file being bogus. Therefore, just mark the test case as + // broken, because it possibly is. + status = ATF_STATUS_BROKEN; + kyua_error_format(error, reason, sizeof(reason)); + kyua_error_free(error); + } + + // Errors converting the loaded result to the final result file are not due + // to a bad test program: they are because our own code fails (e.g. cannot + // create the output file). These need to be returned to the caller. + return convert_result(status, status_arg, reason, wait_status, timed_out, + output_name, success); +} + + +/// Creates a result file for a failed cleanup routine. +/// +/// This function is supposed to be invoked after the body has had a chance to +/// create its own result file, and only if the body has terminated with a +/// non-failure result. +/// +/// \param output_name Path to the generic result file to create. +/// \param wait_status Exit code of the test program as returned by wait(). +/// \param timed_out Whether the test program timed out or not. +/// \param [out] success Whether the result should be considered a success or +/// not; i.e. a clean exit is successful, but anything else is a failure. +/// +/// \return An error if there is a problem writing the result; OK otherwise. +kyua_error_t +kyua_atf_result_cleanup_rewrite(const char* output_name, int wait_status, + const bool timed_out, bool* success) +{ + if (timed_out) { + *success = false; + return kyua_result_write( + output_name, KYUA_RESULT_BROKEN, "Test case cleanup timed out"); + } else { + if (WIFEXITED(wait_status)) { + if (WEXITSTATUS(wait_status) == EXIT_SUCCESS) { + *success = true; + // Reuse the result file created by the body. I.e. avoid + // creating a new file here. + return kyua_error_ok(); + } else { + *success = false; + return kyua_result_write( + output_name, KYUA_RESULT_BROKEN, "Test case cleanup exited " + "with code %d", WEXITSTATUS(wait_status)); + } + } else { + *success = false; + return kyua_result_write( + output_name, KYUA_RESULT_BROKEN, "Test case cleanup received " + "signal %d%s", WTERMSIG(wait_status), + WCOREDUMP(wait_status) ? " (core dumped)" : ""); + } + } +} diff --git a/external/bsd/kyua-testers/dist/atf_result.h b/external/bsd/kyua-testers/dist/atf_result.h new file mode 100644 index 000000000..b7aa65117 --- /dev/null +++ b/external/bsd/kyua-testers/dist/atf_result.h @@ -0,0 +1,46 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file atf_result.h +/// Utilities to parse the result of tests cases returned by ATF test programs. + +#if !defined(KYUA_ATF_RESULT_H) +#define KYUA_ATF_RESULT_H + +#include + +#include "error_fwd.h" + + +kyua_error_t kyua_atf_result_rewrite(const char*, const char*, const int, + const bool, bool*); +kyua_error_t kyua_atf_result_cleanup_rewrite(const char*, int, const bool, + bool* success); + + +#endif // !defined(KYUA_ATF_RESULT_H) diff --git a/external/bsd/kyua-testers/dist/atf_result_test.c b/external/bsd/kyua-testers/dist/atf_result_test.c new file mode 100644 index 000000000..181d3e5ae --- /dev/null +++ b/external/bsd/kyua-testers/dist/atf_result_test.c @@ -0,0 +1,535 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "atf_result.h" + +#include +#include + +#include +#include +#include + +#include + +#include "error.h" + + +/// Evalutes an expression and ensures it does not return an error. +/// +/// \param expr A expression that must evaluate to kyua_error_t. +#define RE(expr) ATF_REQUIRE(!kyua_error_is_set(expr)) + + +/// Generates a wait(2) status for a successful exit code. +/// +/// \param exitstatus The exit status to encode in the status. +/// +/// \return The wait(2) status. +static int +generate_wait_exitstatus(const int exitstatus) +{ + const pid_t pid = fork(); + ATF_REQUIRE(pid != -1); + if (pid == 0) { + exit(exitstatus); + } else { + int status; + ATF_REQUIRE(waitpid(pid, &status, 0) != -1); + return status; + } +} + + +/// Generates a wait(2) status for a termination due to a signal. +/// +/// \param signo The signal number to encode in the status. +/// +/// \return The wait(2) status. +static int +generate_wait_termsig(const int signo) +{ +#if !defined(__minix) + // Explicitly disable core files to avoid inconsistent behaviors across + // operating systems. Some of the signal numbers passed to this function + // may have a meaning or not depending on the system, and this might mean + // that a core gets generated arbitrarily. As a result of this, our string + // comparisons below fail. + struct rlimit rl; + rl.rlim_cur = 0; + rl.rlim_max = RLIM_INFINITY; + if (setrlimit(RLIMIT_CORE, &rl) == -1) + atf_tc_skip("Failed to lower the core size limit"); +#endif /* !defined(__minix) */ + + const pid_t pid = fork(); + ATF_REQUIRE(pid != -1); + if (pid == 0) { + kill(getpid(), signo); + abort(); + } else { + int status; + ATF_REQUIRE(waitpid(pid, &status, 0) != -1); + return status; + } +} + + +/// Validates an execution of kyua_atf_result_rewrite(). +/// +/// The code of this check is all within the macro instead of in a separate +/// function so that we get meaningful line numbers in test failure messages. +/// +/// \param name Name of the test case. +/// \param input Text of the ATF result. +/// \param wait_status Exit status of the ATF test case, as returned by wait(2). +/// \param timed_out Whether the test case timed out or not. +/// \param exp_output Text of the expected generic result. +/// \param exp_success Expected value of the success result. +#define CHECK(name, input, wait_status, timed_out, exp_output, exp_success) \ + ATF_TC_WITHOUT_HEAD(name); \ + ATF_TC_BODY(name, tc) \ + { \ + bool success; \ + atf_utils_create_file("in.txt", "%s", input); \ + RE(kyua_atf_result_rewrite("in.txt", "out.txt", wait_status, \ + timed_out, &success)); \ + atf_utils_cat_file("out.txt", "OUTPUT: "); \ + ATF_REQUIRE(atf_utils_compare_file("out.txt", exp_output)); \ + ATF_REQUIRE_EQ(exp_success, success); \ + } + + +CHECK(rewrite__expected_death__exit_failure, + "expected_death: Some text\n", + generate_wait_exitstatus(EXIT_FAILURE), false, + "expected_failure: Some text\n", + true); +CHECK(rewrite__expected_death__signaled, + "expected_death: Foo bar\n", + generate_wait_termsig(1), false, + "expected_failure: Foo bar\n", + true); +CHECK(rewrite__expected_death__exit_success, + "expected_death: Some text\n", + generate_wait_exitstatus(EXIT_SUCCESS), false, + "failed: Test case expected to die but exited successfully\n", + false); +CHECK(rewrite__expected_death__no_reason, + "expected_death\n", + generate_wait_exitstatus(EXIT_FAILURE), false, + "broken: Test case should have reported a failure reason but didn't; " + "test case exited with code 1\n", + false); +CHECK(rewrite__expected_death__unexpected_arg, + "expected_death(23): Some text\n", + generate_wait_exitstatus(EXIT_FAILURE), false, + "broken: Unknown test case result status expected_death(23); " + "test case exited with code 1\n", + false); + + +CHECK(rewrite__expected_exit__exit_success, + "expected_exit: Some text\n", + generate_wait_exitstatus(EXIT_SUCCESS), false, + "expected_failure: Some text\n", + true); +CHECK(rewrite__expected_exit__exit_failure, + "expected_exit: Some other text\n", + generate_wait_exitstatus(EXIT_FAILURE), false, + "expected_failure: Some other text\n", + true); +CHECK(rewrite__expected_exit__arg_match, + "expected_exit(15): Some text\n", + generate_wait_exitstatus(15), false, + "expected_failure: Some text\n", + true); +CHECK(rewrite__expected_exit__arg_not_match, + "expected_exit(18): Some text\n", + generate_wait_exitstatus(15), false, + "failed: Test case expected to exit with code 18 but got code 15\n", + false); +CHECK(rewrite__expected_exit__signaled, + "expected_exit: Foo bar\n", + generate_wait_termsig(1), false, + "failed: Test case expected to exit normally but received signal 1\n", + false); +CHECK(rewrite__expected_exit__no_reason, + "expected_exit\n", + generate_wait_exitstatus(EXIT_FAILURE), false, + "broken: Test case should have reported a failure reason but didn't; " + "test case exited with code 1\n", + false); +CHECK(rewrite__expected_exit__bad_arg, + "expected_exit(abc): Some text\n", + generate_wait_exitstatus(25), false, + "broken: Invalid status argument (abc): not a number; test case exited " + "with code 25\n", + false); + + +CHECK(rewrite__expected_failure__ok, + "expected_failure: Some text\n", + generate_wait_exitstatus(EXIT_SUCCESS), false, + "expected_failure: Some text\n", + true); +CHECK(rewrite__expected_failure__failed, + "expected_failure: Some text\n", + generate_wait_exitstatus(EXIT_FAILURE), false, + "failed: Test case expected a failure but exited with error code 1\n", + false); +CHECK(rewrite__expected_failure__signaled, + "expected_failure: Foo bar\n", + generate_wait_termsig(1), false, + "failed: Test case expected a failure but received signal 1\n", + false); +CHECK(rewrite__expected_failure__no_reason, + "expected_failure\n", + generate_wait_exitstatus(EXIT_FAILURE), false, + "broken: Test case should have reported a failure reason but didn't; " + "test case exited with code 1\n", + false); +CHECK(rewrite__expected_failure__unexpected_arg, + "expected_failure(23): Some text\n", + generate_wait_exitstatus(EXIT_FAILURE), false, + "broken: Unknown test case result status expected_failure(23); " + "test case exited with code 1\n", + false); + + +CHECK(rewrite__expected_signal__ok, + "expected_signal: Some text\n", + generate_wait_termsig(6), false, + "expected_failure: Some text\n", + true); +CHECK(rewrite__expected_signal__arg_match, + "expected_signal(15): Some text\n", + generate_wait_termsig(15), false, + "expected_failure: Some text\n", + true); +CHECK(rewrite__expected_signal__arg_not_match, + "expected_signal(18): Some text\n", + generate_wait_termsig(15), false, + "failed: Test case expected to receive signal 18 but got 15\n", + false); +CHECK(rewrite__expected_signal__exited, + "expected_signal: Foo bar\n", + generate_wait_exitstatus(12), false, + "failed: Test case expected to receive a signal but exited with code 12\n", + false); +CHECK(rewrite__expected_signal__no_reason, + "expected_signal\n", + generate_wait_termsig(15), false, + "broken: Test case should have reported a failure reason but didn't; " + "test case received signal 15\n", + false); +CHECK(rewrite__expected_signal__bad_arg, + "expected_signal(abc): Some text\n", + generate_wait_termsig(25), false, + "broken: Invalid status argument (abc): not a number; test case received " + "signal 25\n", + false); + + +CHECK(rewrite__expected_timeout__ok, + "expected_timeout: Some text\n", + generate_wait_exitstatus(EXIT_SUCCESS), true, + "expected_failure: Some text\n", + true); +CHECK(rewrite__expected_timeout__exited, + "expected_timeout: Foo bar\n", + generate_wait_exitstatus(12), false, + "failed: Test case expected to time out but exited with code 12\n", + false); +CHECK(rewrite__expected_timeout__signaled, + "expected_timeout: Foo bar\n", + generate_wait_termsig(15), false, + "failed: Test case expected to time out but received signal 15\n", + false); +CHECK(rewrite__expected_timeout__no_reason, + "expected_timeout\n", + generate_wait_exitstatus(EXIT_FAILURE), false, + "broken: Test case should have reported a failure reason but didn't; " + "test case exited with code 1\n", + false); +CHECK(rewrite__expected_timeout__unexpected_arg, + "expected_timeout(23): Some text\n", + generate_wait_exitstatus(EXIT_FAILURE), false, + "broken: Unknown test case result status expected_timeout(23); " + "test case exited with code 1\n", + false); + + +CHECK(rewrite__failed__ok, + "failed: Some text\n", + generate_wait_exitstatus(EXIT_FAILURE), false, + "failed: Some text\n", + false); +CHECK(rewrite__failed__exit_success, + "failed: Some text\n", + generate_wait_exitstatus(EXIT_SUCCESS), false, + "broken: Test case reported a failed result but exited with a successful " + "exit code\n", + false); +CHECK(rewrite__failed__signaled, + "failed: Not used\n", + generate_wait_termsig(1), false, + "broken: Test case reported a failed result but received signal 1\n", + false); +CHECK(rewrite__failed__no_reason, + "failed\n", + generate_wait_exitstatus(EXIT_FAILURE), false, + "broken: Test case should have reported a failure reason but didn't; " + "test case exited with code 1\n", + false); +CHECK(rewrite__failed__unexpected_arg, + "failed(23): Some text\n", + generate_wait_exitstatus(EXIT_FAILURE), false, + "broken: Unknown test case result status failed(23); " + "test case exited with code 1\n", + false); + + +CHECK(rewrite__passed__ok, + "passed\n", + generate_wait_exitstatus(EXIT_SUCCESS), false, + "passed\n", + true); +CHECK(rewrite__passed__exit_failure, + "passed\n", + generate_wait_exitstatus(EXIT_FAILURE), false, + "broken: Test case reported a passed result but returned a non-zero " + "exit code 1\n", + false); +CHECK(rewrite__passed__signaled, + "passed\n", + generate_wait_termsig(1), false, + "broken: Test case reported a passed result but received signal 1\n", + false); +CHECK(rewrite__passed__unexpected_reason, + "passed: This should not be here\n", + generate_wait_exitstatus(EXIT_SUCCESS), false, + "broken: Found unexpected reason in passed test result; test case exited " + "with code 0\n", + false); +CHECK(rewrite__passed__unexpected_arg, + "passed(0)\n", + generate_wait_exitstatus(EXIT_SUCCESS), false, + "broken: Unknown test case result status passed(0); " + "test case exited with code 0\n", + false); + + +CHECK(rewrite__skipped__ok, + "skipped: Does not apply\n", + generate_wait_exitstatus(EXIT_SUCCESS), false, + "skipped: Does not apply\n", + true); +CHECK(rewrite__skipped__exit_failure, + "skipped: Some reason\n", + generate_wait_exitstatus(EXIT_FAILURE), false, + "broken: Test case reported a skipped result but returned a non-zero " + "exit code 1\n", + false); +CHECK(rewrite__skipped__signaled, + "skipped: Not used\n", + generate_wait_termsig(1), false, + "broken: Test case reported a skipped result but received signal 1\n", + false); +CHECK(rewrite__skipped__no_reason, + "skipped\n", + generate_wait_exitstatus(EXIT_SUCCESS), false, + "broken: Test case should have reported a failure reason but didn't; " + "test case exited with code 0\n", + false); +CHECK(rewrite__skipped__unexpected_arg, + "skipped(1): Some text\n", + generate_wait_exitstatus(EXIT_SUCCESS), false, + "broken: Unknown test case result status skipped(1); " + "test case exited with code 0\n", + false); + + +CHECK(rewrite__timed_out, + "this invalid result file should not be parsed\n", + generate_wait_exitstatus(EXIT_SUCCESS), true, + "broken: Test case body timed out\n", + false); + + +ATF_TC_WITHOUT_HEAD(rewrite__missing_file); +ATF_TC_BODY(rewrite__missing_file, tc) +{ + bool success; + RE(kyua_atf_result_rewrite("in.txt", "out.txt", + generate_wait_exitstatus(EXIT_SUCCESS), + false, &success)); + atf_utils_cat_file("out.txt", "OUTPUT: "); + ATF_REQUIRE(atf_utils_compare_file("out.txt", + "broken: Premature exit; test case exited with code 0\n")); + ATF_REQUIRE(!success); +} +CHECK(rewrite__empty, + "", + generate_wait_exitstatus(EXIT_FAILURE), false, + "broken: Empty result file in.txt; test case exited with code 1\n", + false); +CHECK(rewrite__unknown_status, + "foo\n", + generate_wait_exitstatus(123), false, + "broken: Unknown test case result status foo; test case exited with " + "code 123\n", + false); +CHECK(rewrite__status_without_newline, + "failed", + generate_wait_termsig(1), false, + "broken: Missing newline in result file; test case received signal 1\n", + false); +CHECK(rewrite__status_multiline, + "failed: First line\nSecond line\nThird line", + generate_wait_exitstatus(EXIT_FAILURE), false, + "failed: First line<>Second line<>Third line\n", + false); +CHECK(rewrite__status_multiline_2, + "failed: First line\nSecond line\nThird line\n", + generate_wait_exitstatus(EXIT_FAILURE), false, + "failed: First line<>Second line<>Third line\n", + false); + + +/// Validates an execution of kyua_atf_result_cleanup_rewrite(). +/// +/// The code of this check is all within the macro instead of in a separate +/// function so that we get meaningful line numbers in test failure messages. +/// +/// \param name Name of the test case. +/// \param wait_status Exit status of the ATF test case, as returned by wait(2). +/// \param timed_out Whether the test case timed out or not. +/// \param exp_output Text of the expected generic result. +/// \param exp_success Expected value of the success result. +#define CHECK_CLEANUP(name, wait_status, timed_out, exp_output, exp_success) \ + ATF_TC_WITHOUT_HEAD(name); \ + ATF_TC_BODY(name, tc) \ + { \ + bool success; \ + atf_utils_create_file("out.txt", "skipped: Preexistent file\n"); \ + RE(kyua_atf_result_cleanup_rewrite("out.txt", wait_status, \ + timed_out, &success)); \ + atf_utils_cat_file("out.txt", "OUTPUT: "); \ + ATF_REQUIRE(atf_utils_compare_file("out.txt", exp_output)); \ + ATF_REQUIRE_EQ(exp_success, success); \ + } + + +CHECK_CLEANUP(cleanup_rewrite__ok, + generate_wait_exitstatus(EXIT_SUCCESS), false, + "skipped: Preexistent file\n", // Previous file not overwritten. + true); +CHECK_CLEANUP(cleanup_rewrite__exit_failure, + generate_wait_exitstatus(EXIT_FAILURE), false, + "broken: Test case cleanup exited with code 1\n", + false); +CHECK_CLEANUP(cleanup_rewrite__signaled, + generate_wait_termsig(1), false, + "broken: Test case cleanup received signal 1\n", + false); +CHECK_CLEANUP(cleanup_rewrite__timed_out, + generate_wait_exitstatus(EXIT_SUCCESS), true, + "broken: Test case cleanup timed out\n", + false); + + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, rewrite__expected_death__exit_failure); + ATF_TP_ADD_TC(tp, rewrite__expected_death__signaled); + ATF_TP_ADD_TC(tp, rewrite__expected_death__exit_success); + ATF_TP_ADD_TC(tp, rewrite__expected_death__no_reason); + ATF_TP_ADD_TC(tp, rewrite__expected_death__unexpected_arg); + + ATF_TP_ADD_TC(tp, rewrite__expected_exit__exit_success); + ATF_TP_ADD_TC(tp, rewrite__expected_exit__exit_failure); + ATF_TP_ADD_TC(tp, rewrite__expected_exit__arg_match); + ATF_TP_ADD_TC(tp, rewrite__expected_exit__arg_not_match); + ATF_TP_ADD_TC(tp, rewrite__expected_exit__signaled); + ATF_TP_ADD_TC(tp, rewrite__expected_exit__no_reason); + ATF_TP_ADD_TC(tp, rewrite__expected_exit__bad_arg); + + ATF_TP_ADD_TC(tp, rewrite__expected_failure__ok); + ATF_TP_ADD_TC(tp, rewrite__expected_failure__failed); + ATF_TP_ADD_TC(tp, rewrite__expected_failure__signaled); + ATF_TP_ADD_TC(tp, rewrite__expected_failure__no_reason); + ATF_TP_ADD_TC(tp, rewrite__expected_failure__unexpected_arg); + + ATF_TP_ADD_TC(tp, rewrite__expected_signal__ok); + ATF_TP_ADD_TC(tp, rewrite__expected_signal__arg_match); + ATF_TP_ADD_TC(tp, rewrite__expected_signal__arg_not_match); + ATF_TP_ADD_TC(tp, rewrite__expected_signal__exited); + ATF_TP_ADD_TC(tp, rewrite__expected_signal__no_reason); + ATF_TP_ADD_TC(tp, rewrite__expected_signal__bad_arg); + + ATF_TP_ADD_TC(tp, rewrite__expected_timeout__ok); + ATF_TP_ADD_TC(tp, rewrite__expected_timeout__exited); + ATF_TP_ADD_TC(tp, rewrite__expected_timeout__signaled); + ATF_TP_ADD_TC(tp, rewrite__expected_timeout__no_reason); + ATF_TP_ADD_TC(tp, rewrite__expected_timeout__unexpected_arg); + + ATF_TP_ADD_TC(tp, rewrite__failed__ok); + ATF_TP_ADD_TC(tp, rewrite__failed__exit_success); + ATF_TP_ADD_TC(tp, rewrite__failed__signaled); + ATF_TP_ADD_TC(tp, rewrite__failed__no_reason); + ATF_TP_ADD_TC(tp, rewrite__failed__unexpected_arg); + + ATF_TP_ADD_TC(tp, rewrite__passed__ok); + ATF_TP_ADD_TC(tp, rewrite__passed__exit_failure); + ATF_TP_ADD_TC(tp, rewrite__passed__signaled); + ATF_TP_ADD_TC(tp, rewrite__passed__unexpected_reason); + ATF_TP_ADD_TC(tp, rewrite__passed__unexpected_arg); + + ATF_TP_ADD_TC(tp, rewrite__skipped__ok); + ATF_TP_ADD_TC(tp, rewrite__skipped__exit_failure); + ATF_TP_ADD_TC(tp, rewrite__skipped__signaled); + ATF_TP_ADD_TC(tp, rewrite__skipped__no_reason); + ATF_TP_ADD_TC(tp, rewrite__skipped__unexpected_arg); + + ATF_TP_ADD_TC(tp, rewrite__timed_out); + + ATF_TP_ADD_TC(tp, rewrite__missing_file); + ATF_TP_ADD_TC(tp, rewrite__empty); + ATF_TP_ADD_TC(tp, rewrite__unknown_status); + ATF_TP_ADD_TC(tp, rewrite__status_without_newline); + ATF_TP_ADD_TC(tp, rewrite__status_multiline); + ATF_TP_ADD_TC(tp, rewrite__status_multiline_2); + + ATF_TP_ADD_TC(tp, cleanup_rewrite__ok); + ATF_TP_ADD_TC(tp, cleanup_rewrite__exit_failure); + ATF_TP_ADD_TC(tp, cleanup_rewrite__signaled); + ATF_TP_ADD_TC(tp, cleanup_rewrite__timed_out); + + return atf_no_error(); +} diff --git a/external/bsd/kyua-testers/dist/cli.c b/external/bsd/kyua-testers/dist/cli.c new file mode 100644 index 000000000..220d59560 --- /dev/null +++ b/external/bsd/kyua-testers/dist/cli.c @@ -0,0 +1,260 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#if defined(HAVE_CONFIG_H) +#include "config.h" +#endif + +#include "cli.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "defs.h" +#include "error.h" +#include "run.h" + +#if !defined(GID_MAX) +# define GID_MAX INT_MAX +#endif +#if !defined(UID_MAX) +# define UID_MAX INT_MAX +#endif + +#if defined(HAVE_GETOPT_GNU) +# define GETOPT_PLUS "+" +#else +# define GETOPT_PLUS +#endif + + +/// Terminates execution if the given error is set. +/// +/// \param error The error to validate. +/// +/// \post The program terminates if the given error is set. +static void +check_error(kyua_error_t error) +{ + if (kyua_error_is_set(error)) { + const bool usage_error = kyua_error_is_type(error, + kyua_usage_error_type); + + char buffer[1024]; + kyua_error_format(error, buffer, sizeof(buffer)); + kyua_error_free(error); + + errx(usage_error ? EXIT_USAGE_ERROR : EXIT_INTERNAL_ERROR, + "%s", buffer); + } +} + + +/// Converts a string to an unsigned long. +/// +/// \param str The string to convert. +/// \param message Part of the error message to print if the string does not +/// represent a valid unsigned long number. +/// \param max Maximum accepted value. +/// +/// \return The converted numerical value. +/// +/// \post The program terminates if the value is invalid. +static unsigned long +parse_ulong(const char* str, const char* message, const unsigned long max) +{ + char *endptr; + + errno = 0; + const unsigned long value = strtoul(str, &endptr, 10); + if (str[0] == '\0' || *endptr != '\0') + errx(EXIT_USAGE_ERROR, "%s '%s' (not a number)", message, str); + else if (errno == ERANGE || value == LONG_MAX || value > max) + errx(EXIT_USAGE_ERROR, "%s '%s' (out of range)", message, str); + return value; +} + + +/// Clears getopt(3) state to allow calling the function again. +static void +reset_getopt(void) +{ + opterr = 0; + optind = GETOPT_OPTIND_RESET_VALUE; +#if defined(HAVE_GETOPT_WITH_OPTRESET) + optreset = 1; +#endif +} + + +/// Prints the list of test cases and their metadata in a test program. +/// +/// \param argc Number of arguments to the command, including the command name. +/// \param argv Arguments to the command, including the command name. +/// \param tester Description of the tester implemented by this binary. +/// \param run_params Execution parameters to configure the test process. +/// +/// \return An exit status to indicate the success or failure of the listing. +/// +/// \post Usage errors terminate the execution of the program right away. +static int +list_command(const int argc, char* const* const argv, + const kyua_cli_tester_t* tester, + const kyua_run_params_t* run_params) +{ + if (argc < 2) + errx(EXIT_USAGE_ERROR, "No test program provided"); + else if (argc > 2) + errx(EXIT_USAGE_ERROR, "Only one test program allowed"); + const char* test_program = argv[1]; + + check_error(tester->list_test_cases(test_program, run_params)); + return EXIT_SUCCESS; +} + + +/// Runs and cleans up a single test case. +/// +/// \param argc Number of arguments to the command, including the command name. +/// \param argv Arguments to the command, including the command name. +/// \param tester Description of the tester implemented by this binary. +/// \param run_params Execution parameters to configure the test process. +/// +/// \return An exit status to indicate the success or failure of the test case +/// execution. +/// +/// \post Usage errors terminate the execution of the program right away. +static int +test_command(int argc, char* const* argv, const kyua_cli_tester_t* tester, + const kyua_run_params_t* run_params) +{ +# define MAX_USER_VARIABLES 256 + const char* user_variables[MAX_USER_VARIABLES]; + + const char** last_variable = user_variables; + int ch; + while ((ch = getopt(argc, argv, GETOPT_PLUS":v:")) != -1) { + switch (ch) { + case 'v': + *last_variable++ = optarg; + break; + + case ':': + errx(EXIT_USAGE_ERROR, "%s's -%c requires an argument", argv[0], + optopt); + + case '?': + errx(EXIT_USAGE_ERROR, "Unknown %s option -%c", argv[0], optopt); + + default: + assert(false); + } + } + argc -= optind; + argv += optind; + *last_variable = NULL; + + if (argc != 3) + errx(EXIT_USAGE_ERROR, "Must provide a test program, a test case name " + "and a result file"); + const char* test_program = argv[0]; + const char* test_case = argv[1]; + const char* result_file = argv[2]; + + bool success; + check_error(tester->run_test_case(test_program, test_case, result_file, + user_variables, run_params, &success)); + return success ? EXIT_SUCCESS : EXIT_FAILURE; +} + + +/// Generic entry point to the tester's command-line interface. +/// +/// \param argc Verbatim argc passed to main(). +/// \param argv Verbatim argv passed to main(). +/// \param tester Description of the tester implemented by this binary. +/// +/// \return An exit status. +/// +/// \post Usage errors terminate the execution of the program right away. +int +kyua_cli_main(int argc, char* const* argv, const kyua_cli_tester_t* tester) +{ + kyua_run_params_t run_params; + kyua_run_params_init(&run_params); + + int ch; + while ((ch = getopt(argc, argv, GETOPT_PLUS":g:t:u:")) != -1) { + switch (ch) { + case 'g': + run_params.unprivileged_group = (uid_t)parse_ulong( + optarg, "Invalid GID", GID_MAX); + break; + + case 't': + run_params.timeout_seconds = parse_ulong( + optarg, "Invalid timeout value", LONG_MAX); + break; + + case 'u': + run_params.unprivileged_user = (uid_t)parse_ulong( + optarg, "Invalid UID", UID_MAX); + break; + + case ':': + errx(EXIT_USAGE_ERROR, "-%c requires an argument", optopt); + + case '?': + errx(EXIT_USAGE_ERROR, "Unknown option -%c", optopt); + + default: + assert(false); + } + } + argc -= optind; + argv += optind; + reset_getopt(); + + if (argc == 0) + errx(EXIT_USAGE_ERROR, "Must provide a command"); + const char* command = argv[0]; + + // Keep sorted by order of likelyhood (yeah, micro-optimization). + if (strcmp(command, "test") == 0) + return test_command(argc, argv, tester, &run_params); + else if (strcmp(command, "list") == 0) + return list_command(argc, argv, tester, &run_params); + else + errx(EXIT_USAGE_ERROR, "Unknown command '%s'", command); +} diff --git a/external/bsd/kyua-testers/dist/cli.h b/external/bsd/kyua-testers/dist/cli.h new file mode 100644 index 000000000..deb74d7ed --- /dev/null +++ b/external/bsd/kyua-testers/dist/cli.h @@ -0,0 +1,103 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file cli.h +/// Generic command-line implementation of a tester. +/// +/// The cli module implements a generic command-line for a tester +/// regardless of the test interface it implements. This command-line must +/// be consistent across all implementations so that the Kyua runtime does +/// not need to have any knowledge of the specific test interfaces. + +#if !defined(KYUA_CLI_H) +#define KYUA_CLI_H + +#include "cli_fwd.h" + +#include + +#include "error_fwd.h" +#include "run_fwd.h" + + +// Error codes returned by the CLI are as follows. These match the rationale of +// the return values of the kyua(1) tool. +// +// EXIT_SUCCESS -> The command and the tester ran correctly. +// EXIT_FAILURE -> The command reported an error, but the tester ran correctly. +// For example: the test command reports that the test itself failed, but +// nothing in the tester misbehaved. +// EXIT_INTERNAL_ERROR -> The tester itself failed. +// EXIT_USAGE_ERROR -> The user caused an error in the command line. + +/// Constant to indicate an unexpected error in the tester. +#define EXIT_INTERNAL_ERROR 2 +/// Constant to indicate a usage error. +#define EXIT_USAGE_ERROR 3 + + +/// Description of a tester. +struct kyua_cli_tester { + /// Lists the test cases in a test program. + /// + /// \param test_program Path to the test program for which to list the test + /// cases. Should be absolute. + /// \param run_params Execution parameters to configure the test process. + /// + /// \return An error if the listing fails; OK otherwise. + kyua_error_t (*list_test_cases)(const char* test_program, + const kyua_run_params_t* run_params); + + /// Runs a single test cases of a test program. + /// + /// \param test_program Path to the test program for which to list the test + /// cases. Should be absolute. + /// \param test_case Name of the test case to run. + /// \param result_file Path to the file to which to write the result of the + /// test. Should be absolute. + /// \param user_variables Array of name=value pairs that describe the user + /// configuration variables for the test case. + /// \param run_params Execution parameters to configure the test process. + /// \param [out] success Set to true if the test case reported a valid exit + /// condition (like "passed" or "skipped"); false otherwise. This is + /// only updated if the method returns OK. + /// + /// \return An error if the listing fails; OK otherwise. + kyua_error_t (*run_test_case)(const char* test_program, + const char* test_case, + const char* result_file, + const char* const user_variables[], + const kyua_run_params_t* run_params, + bool* success); +}; + + +int kyua_cli_main(const int, char* const* const, const kyua_cli_tester_t*); + + +#endif // !defined(KYUA_CLI_H) diff --git a/external/bsd/kyua-testers/dist/cli_fwd.h b/external/bsd/kyua-testers/dist/cli_fwd.h new file mode 100644 index 000000000..056f350ed --- /dev/null +++ b/external/bsd/kyua-testers/dist/cli_fwd.h @@ -0,0 +1,43 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file cli_fwd.h +/// Forward declarations for the cli.h header. + +#if !defined(KYUA_CLI_FWD_H) +#define KYUA_CLI_FWD_H + + +struct kyua_cli_tester; + + +/// Shorthand for a kyua_cli_tester structure. +typedef struct kyua_cli_tester kyua_cli_tester_t; + + +#endif // !defined(KYUA_CLI_FWD_H) diff --git a/external/bsd/kyua-testers/dist/cli_test.c b/external/bsd/kyua-testers/dist/cli_test.c new file mode 100644 index 000000000..924143591 --- /dev/null +++ b/external/bsd/kyua-testers/dist/cli_test.c @@ -0,0 +1,607 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "cli.h" + +#include +#include +#include +#include + +#include + +#include "defs.h" +#include "error.h" +#include "run.h" + + +/// Dumps the contents of a run_params object to stdout. +/// +/// We only print the settings that are relevant for testing purposes. +/// +/// \param run_params The run parameters to be printed. +static void +dump_run_params(const kyua_run_params_t* run_params) +{ + printf("timeout_seconds: %lu\n", run_params->timeout_seconds); + + if (run_params->unprivileged_user == getuid()) + printf("unprivileged_user: self\n"); + else + printf("unprivileged_user: %ld\n", (long)run_params->unprivileged_user); + + if (run_params->unprivileged_group == getgid()) + printf("unprivileged_group: self\n"); + else + printf("unprivileged_group: %ld\n", + (long)run_params->unprivileged_group); +} + + +/// Helper to validate argument passing to the list_test_cases method. +/// +/// This prints the value of all arguments to stdout so that the caller can +/// compare the printed output to the expected values. +/// +/// \param test_program Test program path. +/// \param run_params Execution parameters to configure the test process. +/// +/// \return An error if the test_program is set to the magic keyword 'error'; OK +/// otherwise. +static kyua_error_t +list_test_cases(const char* test_program, const kyua_run_params_t* run_params) +{ + if (strcmp(test_program, "error") == 0) + return kyua_oom_error_new(); + else { + printf("test_program: %s\n", test_program); + dump_run_params(run_params); + return kyua_error_ok(); + } +} + + +/// Helper to validate argument passing to the run_test_cases method. +/// +/// This prints the value of all arguments to stdout so that the caller can +/// compare the printed output to the expected values. +/// +/// \param test_program Test program path. +/// \param test_case Test case name. +/// \param result_file Path to the result file. +/// \param user_variables User configuration variables. +/// \param run_params Execution parameters to configure the test process. +/// \param [out] success Whether the test case returned with a successful result +/// or not. Set to true if result_file is the magic word 'pass'. +/// +/// \return An error if the test_program is set to the magic keyword 'error'; OK +/// otherwise. +static kyua_error_t +run_test_case(const char* test_program, const char* test_case, + const char* result_file, const char* const user_variables[], + const kyua_run_params_t* run_params, bool* success) +{ + if (strcmp(test_program, "error") == 0) + return kyua_oom_error_new(); + else { + printf("test_program: %s\n", test_program); + printf("test_case: %s\n", test_case); + printf("result_file: %s\n", result_file); + const char* const* iter; + for (iter = user_variables; *iter != NULL; ++iter) + printf("variable: %s\n", *iter); + dump_run_params(run_params); + *success = strcmp(result_file, "pass") == 0; + return kyua_error_ok(); + } +} + + +/// Definition of a mock tester. +static kyua_cli_tester_t mock_tester = { + .list_test_cases = list_test_cases, + .run_test_case = run_test_case, +}; + + +/// Definition of a tester with invalid values. +/// +/// This is to be used when the called code is not supposed to invoke any of the +/// tester methods. +static kyua_cli_tester_t unused_tester = { + .list_test_cases = NULL, + .run_test_case = NULL, +}; + + +/// Counts the number of arguments in an argv vector. +/// +/// \param argv The NULL-terminated arguments vector to be passed to the +/// kyua_cli_main function. +/// +/// \return The number of arguments in argv. +static int +count_argv(char* const* const argv) +{ + int argc = 0; + char* const* arg; + for (arg = argv; *arg != NULL; arg++) + argc++; + return argc; +} + + +ATF_TC_WITHOUT_HEAD(main__unknown_option); +ATF_TC_BODY(main__unknown_option, tc) +{ + const pid_t pid = atf_utils_fork(); + if (pid == 0) { + char arg0[] = "unused-progname"; + char arg1[] = "-Z"; + char* const argv[] = {arg0, arg1, NULL}; + exit(kyua_cli_main(count_argv(argv), argv, &unused_tester)); + } + atf_utils_wait(pid, EXIT_USAGE_ERROR, "", "cli_test: Unknown option -Z\n"); +} + + +ATF_TC_WITHOUT_HEAD(main__missing_option_argument); +ATF_TC_BODY(main__missing_option_argument, tc) +{ + const pid_t pid = atf_utils_fork(); + if (pid == 0) { + char arg0[] = "unused-progname"; + char arg1[] = "-t"; + char* const argv[] = {arg0, arg1, NULL}; + exit(kyua_cli_main(count_argv(argv), argv, &unused_tester)); + } + atf_utils_wait(pid, EXIT_USAGE_ERROR, "", "cli_test: -t requires an " + "argument\n"); +} + + +ATF_TC_WITHOUT_HEAD(main__unknown_command); +ATF_TC_BODY(main__unknown_command, tc) +{ + const pid_t pid = atf_utils_fork(); + if (pid == 0) { + char arg0[] = "unused-progname"; + char arg1[] = "foobar"; + char* const argv[] = {arg0, arg1, NULL}; + exit(kyua_cli_main(count_argv(argv), argv, &unused_tester)); + } + atf_utils_wait(pid, EXIT_USAGE_ERROR, "", "cli_test: Unknown command " + "'foobar'\n"); +} + + +ATF_TC_WITHOUT_HEAD(main__missing_command); +ATF_TC_BODY(main__missing_command, tc) +{ + const pid_t pid = atf_utils_fork(); + if (pid == 0) { + char arg0[] = "unused-progname"; + char* const argv[] = {arg0, NULL}; + exit(kyua_cli_main(count_argv(argv), argv, &unused_tester)); + } + atf_utils_wait(pid, EXIT_USAGE_ERROR, "", "cli_test: Must provide a " + "command\n"); +} + + +/// Checks that a textual argument to a numerical flag raises an error. +/// +/// \param flag The generic flag to test. +/// \param error_message The expected error message when the flag is invalid. +static void +check_flag_not_a_number(const char flag, const char *error_message) +{ + const pid_t pid = atf_utils_fork(); + if (pid == 0) { + char arg0[] = "unused-progname"; + char arg1[] = "-?foo"; + arg1[1] = flag; + char* const argv[] = {arg0, arg1, NULL}; + exit(kyua_cli_main(count_argv(argv), argv, &unused_tester)); + } + char experr[256]; + snprintf(experr, sizeof(experr), "cli_test: %s 'foo' (not a number)\n", + error_message); + atf_utils_wait(pid, EXIT_USAGE_ERROR, "", experr); +} + + +/// Checks that an out of range value to a numerical flag raises an error. +/// +/// \param flag The generic flag to test. +/// \param error_message The expected error message when the flag is invalid. +static void +check_flag_out_of_range(const char flag, const char *error_message) +{ + const pid_t pid = atf_utils_fork(); + if (pid == 0) { + char arg0[] = "unused-progname"; + char arg1[] = "-?99999999999999999999"; + arg1[1] = flag; + char* const argv[] = {arg0, arg1, NULL}; + exit(kyua_cli_main(count_argv(argv), argv, &unused_tester)); + } + char experr[256]; + snprintf(experr, sizeof(experr), "cli_test: %s '99999999999999999999' " + "(out of range)\n", error_message); + atf_utils_wait(pid, EXIT_USAGE_ERROR, "", experr); +} + + +ATF_TC_WITHOUT_HEAD(main__gflag__not_a_number); +ATF_TC_BODY(main__gflag__not_a_number, tc) +{ + check_flag_not_a_number('g', "Invalid GID"); +} + + +ATF_TC_WITHOUT_HEAD(main__gflag__out_of_range); +ATF_TC_BODY(main__gflag__out_of_range, tc) +{ + check_flag_out_of_range('g', "Invalid GID"); +} + + +ATF_TC_WITHOUT_HEAD(main__tflag__not_a_number); +ATF_TC_BODY(main__tflag__not_a_number, tc) +{ + check_flag_not_a_number('t', "Invalid timeout value"); +} + + +ATF_TC_WITHOUT_HEAD(main__tflag__out_of_range); +ATF_TC_BODY(main__tflag__out_of_range, tc) +{ + check_flag_out_of_range('t', "Invalid timeout value"); +} + + +ATF_TC_WITHOUT_HEAD(main__uflag__not_a_number); +ATF_TC_BODY(main__uflag__not_a_number, tc) +{ + check_flag_not_a_number('u', "Invalid UID"); +} + + +ATF_TC_WITHOUT_HEAD(main__uflag__out_of_range); +ATF_TC_BODY(main__uflag__out_of_range, tc) +{ + check_flag_out_of_range('u', "Invalid UID"); +} + + +ATF_TC_WITHOUT_HEAD(list__ok); +ATF_TC_BODY(list__ok, tc) +{ + const pid_t pid = atf_utils_fork(); + if (pid == 0) { + char arg0[] = "unused-progname"; + char arg1[] = "list"; + char arg2[] = "the-program"; + char* const argv[] = {arg0, arg1, arg2, NULL}; + exit(kyua_cli_main(count_argv(argv), argv, &mock_tester)); + } + atf_utils_wait(pid, EXIT_SUCCESS, + "test_program: the-program\n" + "timeout_seconds: 60\n" + "unprivileged_user: self\n" + "unprivileged_group: self\n", + ""); +} + + +ATF_TC_WITHOUT_HEAD(list__custom_run_params); +ATF_TC_BODY(list__custom_run_params, tc) +{ + const pid_t pid = atf_utils_fork(); + if (pid == 0) { + char arg0[] = "unused-progname"; + char arg1[] = "-g987"; + char arg2[] = "-t123"; + char arg3[] = "-u45"; + char arg4[] = "list"; + char arg5[] = "the-program"; + char* const argv[] = {arg0, arg1, arg2, arg3, arg4, arg5, NULL}; + exit(kyua_cli_main(count_argv(argv), argv, &mock_tester)); + } + atf_utils_wait(pid, EXIT_SUCCESS, + "test_program: the-program\n" + "timeout_seconds: 123\n" + "unprivileged_user: 45\n" + "unprivileged_group: 987\n", + ""); +} + + +ATF_TC_WITHOUT_HEAD(list__error); +ATF_TC_BODY(list__error, tc) +{ + const pid_t pid = atf_utils_fork(); + if (pid == 0) { + char arg0[] = "unused-progname"; + char arg1[] = "list"; + char arg2[] = "error"; + char* const argv[] = {arg0, arg1, arg2, NULL}; + exit(kyua_cli_main(count_argv(argv), argv, &mock_tester)); + } + atf_utils_wait(pid, EXIT_INTERNAL_ERROR, "", "cli_test: Not enough " + "memory\n"); +} + + +ATF_TC_WITHOUT_HEAD(list__missing_arguments); +ATF_TC_BODY(list__missing_arguments, tc) +{ + const pid_t pid = atf_utils_fork(); + if (pid == 0) { + char arg0[] = "unused-progname"; + char arg1[] = "list"; + char* const argv[] = {arg0, arg1, NULL}; + exit(kyua_cli_main(count_argv(argv), argv, &unused_tester)); + } + atf_utils_wait(pid, EXIT_USAGE_ERROR, "", "cli_test: No test program " + "provided\n"); +} + + +ATF_TC_WITHOUT_HEAD(list__too_many_arguments); +ATF_TC_BODY(list__too_many_arguments, tc) +{ + const pid_t pid = atf_utils_fork(); + if (pid == 0) { + char arg0[] = "unused-progname"; + char arg1[] = "list"; + char arg2[] = "first"; + char arg3[] = "second"; + char* const argv[] = {arg0, arg1, arg2, arg3, NULL}; + exit(kyua_cli_main(count_argv(argv), argv, &unused_tester)); + } + atf_utils_wait(pid, EXIT_USAGE_ERROR, "", "cli_test: Only one test program " + "allowed\n"); +} + + +ATF_TC_WITHOUT_HEAD(test__ok__pass); +ATF_TC_BODY(test__ok__pass, tc) +{ + const pid_t pid = atf_utils_fork(); + if (pid == 0) { + char arg0[] = "unused-progname"; + char arg1[] = "test"; + char arg2[] = "the-program"; + char arg3[] = "the-test-case"; + char arg4[] = "pass"; + char* const argv[] = {arg0, arg1, arg2, arg3, arg4, NULL}; + exit(kyua_cli_main(count_argv(argv), argv, &mock_tester)); + } + atf_utils_wait(pid, EXIT_SUCCESS, + "test_program: the-program\n" + "test_case: the-test-case\n" + "result_file: pass\n" + "timeout_seconds: 60\n" + "unprivileged_user: self\n" + "unprivileged_group: self\n", + ""); +} + + +ATF_TC_WITHOUT_HEAD(test__ok__fail); +ATF_TC_BODY(test__ok__fail, tc) +{ + const pid_t pid = atf_utils_fork(); + if (pid == 0) { + char arg0[] = "unused-progname"; + char arg1[] = "test"; + char arg2[] = "the-program"; + char arg3[] = "the-test-case"; + char arg4[] = "fail"; + char* const argv[] = {arg0, arg1, arg2, arg3, arg4, NULL}; + exit(kyua_cli_main(count_argv(argv), argv, &mock_tester)); + } + atf_utils_wait(pid, EXIT_FAILURE, + "test_program: the-program\n" + "test_case: the-test-case\n" + "result_file: fail\n" + "timeout_seconds: 60\n" + "unprivileged_user: self\n" + "unprivileged_group: self\n", + ""); +} + + +ATF_TC_WITHOUT_HEAD(test__custom_run_params); +ATF_TC_BODY(test__custom_run_params, tc) +{ + const pid_t pid = atf_utils_fork(); + if (pid == 0) { + char arg0[] = "unused-progname"; + char arg1[] = "-g987"; + char arg2[] = "-t123"; + char arg3[] = "-u45"; + char arg4[] = "test"; + char arg5[] = "the-program"; + char arg6[] = "the-test-case"; + char arg7[] = "pass"; + char* const argv[] = {arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, + NULL}; + exit(kyua_cli_main(count_argv(argv), argv, &mock_tester)); + } + atf_utils_wait(pid, EXIT_SUCCESS, + "test_program: the-program\n" + "test_case: the-test-case\n" + "result_file: pass\n" + "timeout_seconds: 123\n" + "unprivileged_user: 45\n" + "unprivileged_group: 987\n", + ""); +} + + +ATF_TC_WITHOUT_HEAD(test__config_variables); +ATF_TC_BODY(test__config_variables, tc) +{ + const pid_t pid = atf_utils_fork(); + if (pid == 0) { + char arg0[] = "unused-progname"; + char arg1[] = "test"; + char arg2[] = "-vfoo=bar"; + char arg3[] = "-va=c"; + char arg4[] = "the-program"; + char arg5[] = "the-test-case"; + char arg6[] = "pass"; + char* const argv[] = {arg0, arg1, arg2, arg3, arg4, arg5, arg6, NULL}; + exit(kyua_cli_main(count_argv(argv), argv, &mock_tester)); + } + atf_utils_wait(pid, EXIT_SUCCESS, + "test_program: the-program\n" + "test_case: the-test-case\n" + "result_file: pass\n" + "variable: foo=bar\n" + "variable: a=c\n" + "timeout_seconds: 60\n" + "unprivileged_user: self\n" + "unprivileged_group: self\n", + ""); +} + + +ATF_TC_WITHOUT_HEAD(test__error); +ATF_TC_BODY(test__error, tc) +{ + const pid_t pid = atf_utils_fork(); + if (pid == 0) { + char arg0[] = "unused-progname"; + char arg1[] = "test"; + char arg2[] = "error"; + char* const argv[] = {arg0, arg1, arg2, arg2, arg2, NULL}; + exit(kyua_cli_main(count_argv(argv), argv, &mock_tester)); + } + atf_utils_wait(pid, EXIT_INTERNAL_ERROR, "", "cli_test: Not enough " + "memory\n"); +} + + +/// Checks that the test command validates the right number of arguments. +/// +/// \param count Number of arguments to pass to the test command. +static void +check_test_invalid_arguments(const unsigned int count) +{ + printf("Checking with %d arguments\n", count); + const pid_t pid = atf_utils_fork(); + if (pid == 0) { + char arg0[] = "unused-progname"; + char arg1[] = "test"; + char argX[] = "arg"; + assert(count <= 4); + char* argv[] = {arg0, arg1, argX, argX, argX, argX, NULL}; + argv[2 + count] = NULL; + exit(kyua_cli_main(2 + count, argv, &unused_tester)); + } + atf_utils_wait(pid, EXIT_USAGE_ERROR, "", "cli_test: Must provide a test " + "program, a test case name and a result file\n"); +} + + +ATF_TC_WITHOUT_HEAD(test__invalid_arguments); +ATF_TC_BODY(test__invalid_arguments, tc) +{ + check_test_invalid_arguments(0); + check_test_invalid_arguments(1); + check_test_invalid_arguments(2); + check_test_invalid_arguments(4); +} + + +ATF_TC_WITHOUT_HEAD(test__unknown_option); +ATF_TC_BODY(test__unknown_option, tc) +{ + const pid_t pid = atf_utils_fork(); + if (pid == 0) { + char arg0[] = "unused-progname"; + char arg1[] = "test"; + char arg2[] = "-Z"; + char* const argv[] = {arg0, arg1, arg2, NULL}; + exit(kyua_cli_main(count_argv(argv), argv, &unused_tester)); + } + atf_utils_wait(pid, EXIT_USAGE_ERROR, "", "cli_test: Unknown test option " + "-Z\n"); +} + + +ATF_TC_WITHOUT_HEAD(test__missing_option_argument); +ATF_TC_BODY(test__missing_option_argument, tc) +{ + const pid_t pid = atf_utils_fork(); + if (pid == 0) { + char arg0[] = "unused-progname"; + char arg1[] = "test"; + char arg2[] = "-v"; + char* const argv[] = {arg0, arg1, arg2, NULL}; + exit(kyua_cli_main(count_argv(argv), argv, &unused_tester)); + } + atf_utils_wait(pid, EXIT_USAGE_ERROR, "", "cli_test: test's -v requires an " + "argument\n"); +} + + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, main__unknown_option); + ATF_TP_ADD_TC(tp, main__missing_option_argument); + ATF_TP_ADD_TC(tp, main__unknown_command); + ATF_TP_ADD_TC(tp, main__missing_command); + ATF_TP_ADD_TC(tp, main__gflag__not_a_number); + ATF_TP_ADD_TC(tp, main__gflag__out_of_range); + ATF_TP_ADD_TC(tp, main__tflag__not_a_number); + ATF_TP_ADD_TC(tp, main__tflag__out_of_range); + ATF_TP_ADD_TC(tp, main__uflag__not_a_number); + ATF_TP_ADD_TC(tp, main__uflag__out_of_range); + + ATF_TP_ADD_TC(tp, list__ok); + ATF_TP_ADD_TC(tp, list__custom_run_params); + ATF_TP_ADD_TC(tp, list__error); + ATF_TP_ADD_TC(tp, list__missing_arguments); + ATF_TP_ADD_TC(tp, list__too_many_arguments); + + ATF_TP_ADD_TC(tp, test__ok__pass); + ATF_TP_ADD_TC(tp, test__ok__fail); + ATF_TP_ADD_TC(tp, test__custom_run_params); + ATF_TP_ADD_TC(tp, test__config_variables); + ATF_TP_ADD_TC(tp, test__error); + ATF_TP_ADD_TC(tp, test__invalid_arguments); + ATF_TP_ADD_TC(tp, test__unknown_option); + ATF_TP_ADD_TC(tp, test__missing_option_argument); + + return atf_no_error(); +} diff --git a/external/bsd/kyua-testers/dist/common_inttest.h b/external/bsd/kyua-testers/dist/common_inttest.h new file mode 100644 index 000000000..2724b5e1a --- /dev/null +++ b/external/bsd/kyua-testers/dist/common_inttest.h @@ -0,0 +1,180 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file common_inttest.h +/// Common integration tests for the tester binaries. + +#if defined(KYUA_COMMON_INTTEST_H) +# error "common_inttest.h can only be defined once" +#endif +/// Include guard. +#define KYUA_COMMON_INTTEST_H + +#if !defined(INTERFACE) +# error "Must define INTERFACE to the name of the tester interface" +#endif + +#include +#include +#include +#include +#include + +#include + +#include "cli.h" // For the EXIT_* constants only. +#include "defs.h" + + +/// Path to the installed testers. +static const char* default_testersdir = TESTERSDIR; + + +/// Returns the name of the current tester. +#define TESTER_BIN "kyua-" INTERFACE "-tester" + + +/// Returns the path to the helpers. +/// +/// \param tc Pointer to the caller test case, to obtain the srcdir property. +/// +/// \return A dynamically-allocated string; must be released with free(3). +static char* +helpers_path(const atf_tc_t* tc) +{ + const char* srcdir = atf_tc_get_config_var(tc, "srcdir"); + const char* name = INTERFACE "_helpers"; + + const size_t length = strlen(srcdir) + 1 + strlen(name) + 1; + char* buffer = (char*)malloc(length); + (void)snprintf(buffer, length, "%s/%s", srcdir, name); + return buffer; +} + + +/// Returns the path to the tester. +/// +/// \return A dynamically-allocated string; must be released with free(3). +static char* +tester_path(void) +{ + const char* testersdir = getenv("TESTERSDIR"); + if (testersdir == NULL) + testersdir = default_testersdir; + const char* name = TESTER_BIN; + + const size_t length = strlen(testersdir) + 1 + strlen(name) + 1; + char* buffer = (char*)malloc(length); + ATF_REQUIRE(buffer != NULL); + (void)snprintf(buffer, length, "%s/%s", testersdir, name); + return buffer; +} + + +/// Initializes the test case metadata and the helpers. +/// +/// \param [in,out] tc The test case in which to set the property. +/// \param uses_helpers Whether the test uses the helpers or not. +static void +setup(atf_tc_t* tc, const bool uses_helpers) +{ + char* tester = tester_path(); + if (uses_helpers) { + char* helpers = helpers_path(tc); + atf_tc_set_md_var(tc, "require.progs", "%s %s", tester, helpers); + free(helpers); + } else { + atf_tc_set_md_var(tc, "require.progs", "%s", tester); + } + free(tester); +} + + +static void execute(va_list ap) KYUA_DEFS_NORETURN; + + +/// Executes the tester with the given set of variable arguments. +/// +/// \param ap List of arguments to the tester. +static void +execute(va_list ap) +{ + const char* args[16]; + + const char** current_arg = &args[0]; + *current_arg = TESTER_BIN; + ++current_arg; + while ((*current_arg = va_arg(ap, const char*)) != NULL) + ++current_arg; + + char* program = tester_path(); + (void)execv(program, KYUA_DEFS_UNCONST(args)); + free(program); + err(111, "Failed to execute %s", program); +} + + +/// Executes the tester and validates its output. +/// +/// \param expected_exit_status Expected exit status of the subprocess. +/// \param expected_stdout Expected contents of stdout. +/// \param expected_stderr Expected contents of stderr. +/// \param ... Arguments to the tester, not including the program name. +static void +check(const int expected_exit_status, const char* expected_stdout, + const char* expected_stderr, ...) +{ + const pid_t pid = atf_utils_fork(); + if (pid == 0) { + va_list ap; + va_start(ap, expected_stderr); + execute(ap); + va_end(ap); + } else { + atf_utils_wait(pid, expected_exit_status, expected_stdout, + expected_stderr); + } +} + + +ATF_TC(top__missing_command); +ATF_TC_HEAD(top__missing_command, tc) { setup(tc, false); } +ATF_TC_BODY(top__missing_command, tc) +{ + check(EXIT_USAGE_ERROR, "", TESTER_BIN": Must provide a command\n", + NULL); +} + + +ATF_TC(top__unknown_command); +ATF_TC_HEAD(top__unknown_command, tc) { setup(tc, false); } +ATF_TC_BODY(top__unknown_command, tc) +{ + check(EXIT_USAGE_ERROR, "", TESTER_BIN": Unknown command 'foo'\n", + "foo", NULL); +} diff --git a/external/bsd/kyua-testers/dist/env.c b/external/bsd/kyua-testers/dist/env.c new file mode 100644 index 000000000..945cdf836 --- /dev/null +++ b/external/bsd/kyua-testers/dist/env.c @@ -0,0 +1,105 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#if defined(HAVE_CONFIG_H) +# include "config.h" +#endif + +#include "env.h" + +#include +#include +#include +#include +#include + +#include "error.h" + + +/// Sets an environment variable. +/// +/// \param name Name of the environment variable to set. +/// \param value Value to be set. +/// +/// \return An error object. +kyua_error_t +kyua_env_set(const char* name, const char* value) +{ + kyua_error_t error; + +#if defined(HAVE_SETENV) + if (setenv(name, value, 1) == -1) + error = kyua_libc_error_new( + errno, "Failed to set environment variable %s to %s", name, value); + else + error = kyua_error_ok(); +#elif defined(HAVE_PUTENV) + const size_t length = strlen(name) + strlen(value) + 2; + char* buffer = (char*)malloc(length); + if (buffer == NULL) + error = kyua_oom_error_new(); + else { + const size_t printed_length = snprintf(buffer, length, "%s=%s", name, + value); + assert(length == printed_length + 1); + if (putenv(buffer) == -1) { + error = kyua_libc_error_new( + errno, "Failed to set environment variable %s to %s", + name, value); + free(buffer); + } else + error = kyua_error_ok(); + } +#else +# error "Don't know how to set an environment variable." +#endif + + return error; +} + + +/// Unsets an environment variable. +/// +/// \param name Name of the environment variable to unset. +/// +/// \return An error object. +kyua_error_t +kyua_env_unset(const char* name) +{ +#if defined(HAVE_UNSETENV) + if (unsetenv(name) == -1) + return kyua_libc_error_new( + errno, "Failed to unset environment variable %s", name); + else + return kyua_error_ok(); +#elif defined(HAVE_PUTENV) + return kyua_env_set(name, ""); +#else +# error "Don't know how to unset an environment variable." +#endif +} diff --git a/external/bsd/kyua-testers/dist/env.h b/external/bsd/kyua-testers/dist/env.h new file mode 100644 index 000000000..a993febb4 --- /dev/null +++ b/external/bsd/kyua-testers/dist/env.h @@ -0,0 +1,42 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file env.h +/// Portable environment manipulation functions. + +#if !defined(KYUA_ENV_H) +#define KYUA_ENV_H + +#include "error_fwd.h" + + +kyua_error_t kyua_env_set(const char*, const char*); +kyua_error_t kyua_env_unset(const char*); + + +#endif // !defined(KYUA_ENV_H) diff --git a/external/bsd/kyua-testers/dist/env_test.c b/external/bsd/kyua-testers/dist/env_test.c new file mode 100644 index 000000000..309ec3b79 --- /dev/null +++ b/external/bsd/kyua-testers/dist/env_test.c @@ -0,0 +1,61 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "env.h" + +#include +#include + +#include + + +ATF_TC_WITHOUT_HEAD(set); +ATF_TC_BODY(set, tc) +{ + ATF_REQUIRE(strcmp(getenv("PATH"), "new value") != 0); + kyua_env_set("PATH", "new value"); + ATF_REQUIRE(strcmp(getenv("PATH"), "new value") == 0); +} + + +ATF_TC_WITHOUT_HEAD(unset); +ATF_TC_BODY(unset, tc) +{ + ATF_REQUIRE(getenv("PATH") != NULL); + kyua_env_unset("PATH"); + ATF_REQUIRE(getenv("PATH") == NULL); +} + + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, set); + ATF_TP_ADD_TC(tp, unset); + + return atf_no_error(); +} diff --git a/external/bsd/kyua-testers/dist/error.c b/external/bsd/kyua-testers/dist/error.c new file mode 100644 index 000000000..40fe47b1a --- /dev/null +++ b/external/bsd/kyua-testers/dist/error.c @@ -0,0 +1,576 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "error.h" + +#include +#include +#include +#include +#include +#include + + +/// Generic hook to format an error that does not have a format callback. +/// +/// \param error Error for which to generate a message. +/// \param output_buffer Buffer to hold the generated message. +/// \param output_size Length of output_buffer. +static int +generic_format_callback(const kyua_error_t error, char* const output_buffer, + size_t output_size) +{ + assert(error != NULL); + return snprintf(output_buffer, output_size, "Error '%s'", error->type_name); +} + + +/// Initializes an error object. +/// +/// \param error Error for which to generate a message. +/// \param type_name Name of the error type. +/// \param data Opaque data that belongs to the error, for usage by +/// error-specific methods like format_callback. +/// \param data_size Size of the opaque data object. +/// \param format_callback Type-specific method to generate a user +/// representation of the error. +/// +/// \return True if the initialization succeeds; false otherwise. If +/// false, the error object passed in has not been modified. +static bool +error_init(kyua_error_t const error, const char* const type_name, + void* const data, const size_t data_size, + const kyua_error_format_callback format_callback) +{ + assert(data != NULL || data_size == 0); + assert(data_size != 0 || data == NULL); + + bool ok; + + if (data == NULL) { + error->data = NULL; + error->needs_free = false; + ok = true; + } else { + void* new_data = malloc(data_size); + if (new_data == NULL) { + ok = false; + } else { + memcpy(new_data, data, data_size); + error->data = new_data; + ok = true; + } + } + + if (ok) { + error->type_name = type_name; + error->format_callback = (format_callback == NULL) ? + generic_format_callback : format_callback; + } + + return ok; +} + + +/// Allocates and initializes a new error. +/// +/// \param type_name Name of the error type. +/// \param data Opaque data that belongs to the error, for usage by +/// error-specific methods like format_callback. +/// \param data_size Size of the opaque data object. +/// \param format_callback Type-specific method to generate a user +/// representation of the error. +/// +/// \return The newly initialized error, or an out of memory error. +kyua_error_t +kyua_error_new(const char* const type_name, void* const data, + const size_t data_size, + const kyua_error_format_callback format_callback) +{ + assert(data != NULL || data_size == 0); + assert(data_size != 0 || data == NULL); + + kyua_error_t error = malloc(sizeof(struct kyua_error)); + if (error == NULL) + error = kyua_oom_error_new(); + else { + if (!error_init(error, type_name, data, data_size, format_callback)) { + free(error); + error = kyua_oom_error_new(); + } else { + error->needs_free = true; + } + } + + assert(error != NULL); + return error; +} + + +/// Releases an error. +/// +/// \param error The error object to release. +void +kyua_error_free(kyua_error_t error) +{ + assert(error != NULL); + + const bool needs_free = error->needs_free; + + if (error->data != NULL) + free(error->data); + if (needs_free) + free(error); +} + + +/// Returns the "most important" of two errors. +/// +/// "Most important" is defined as: the primary error is returned if set, +/// otherwise the secondary error is returned. +/// +/// It is the responsibility of the caller to free the *resulting* error of this +/// call. The original errors passed in should not be consulted any longer, +/// because it is impossible to know which one was chosen. +/// +/// \param primary The primary error to compare. +/// \param [in,out] secondary The secondary error to compare. This is freed if +/// the primary error is set. +/// +/// \return Either primary or secondary. +kyua_error_t +kyua_error_subsume(kyua_error_t primary, kyua_error_t secondary) +{ + if (kyua_error_is_set(primary)) { + if (kyua_error_is_set(secondary)) + kyua_error_free(secondary); + return primary; + } else { + return secondary; + } +} + + +/// Constructor for a no-error condition. +/// +/// \return Opaque representation of a no-error condition. +kyua_error_t +kyua_error_ok(void) +{ + return NULL; +} + + +/// Checks if the given error object represents an error or not. +/// +/// \param error The error to check. +/// +/// \return True if the error is set. +bool +kyua_error_is_set(const kyua_error_t error) +{ + return error != NULL; +} + + +/// Checks if the given error object is of a specific type. +/// +/// \pre The error must be set. +/// +/// \param error The error to check. +/// \param type_name The type of the expected error. +/// +/// \return True if the error is of type type_name. +bool +kyua_error_is_type(const kyua_error_t error, const char* type_name) +{ + assert(error != NULL); + + return strcmp(error->type_name, type_name) == 0; +} + + +/// Returns a pointer to the error-specific data. +/// +/// \pre The error must be set. +/// +/// \param error The error to query. +/// +/// \return An opaque pointer to the error data. This should only be +/// dereferenced by the methods of the error class that created it. +const void* +kyua_error_data(const kyua_error_t error) +{ + assert(error != NULL); + + return error->data; +} + + +/// Generates a user-friendly representation of the error. +/// +/// This cannot fail, but it is possible that the generated error does not +/// fit in the provided buffer. +/// +/// \pre The error must be set. +/// +/// \param error Error for which to generate a message. +/// \param output_buffer Buffer to hold the generated message. +/// \param output_size Length of output_buffer. +/// +/// \return The number of bytes written to output_buffer, or a negative value if +/// there was an error. +int +kyua_error_format(const kyua_error_t error, char* const output_buffer, + const size_t output_size) +{ + assert(kyua_error_is_set(error)); + return error->format_callback(error, output_buffer, output_size); +} + + +/// Formats a string and appends an error code to it. +/// +/// \param error Error to append to the formatted message. +/// \param format User-specified message, as a formatting string. +/// \param ap List of arguments to the format string. +/// \param [out] output_buffer Buffer into which to write the message. +/// \param output_size Length of the output_buffer. +/// +/// \return The number of bytes written to output_buffer, or a negative value if +/// there was an error. +static int +format_user_message(const kyua_error_t error, const char* format, va_list ap, + char* const output_buffer, const size_t output_size) +{ + assert(kyua_error_is_set(error)); + + va_list ap2; + va_copy(ap2, ap); + size_t written = vsnprintf(output_buffer, output_size, format, ap2); + va_end(ap2); + if (written >= output_size) + return -1; + + written += snprintf(output_buffer + written, output_size - written, ": "); + if (written >= output_size) + return -1; + + return kyua_error_format(error, output_buffer + written, + output_size - written); +} + + +/// Version of err(3) that works with kyua_error_t objects. +/// +/// \param exit_code Error code with which to terminate the execution. +/// \param error Error to append to the output. +/// \param format User-specified message, as a formatting string. +/// \param ... Positional arguments to the format string. +/// +/// \post Execution terminates with exit_code. +void +kyua_error_err(const int exit_code, const kyua_error_t error, + const char* format, ...) +{ + char buffer[2048]; + + va_list ap; + va_start(ap, format); + (void)format_user_message(error, format, ap, buffer, sizeof(buffer)); + va_end(ap); + kyua_error_free(error); + + errx(exit_code, "%s", buffer); +} + + +/// Writes an error to a file stream. +/// +/// \param stream Stream to which to write the message. +/// \param error Error to append to the output. This is not released. +/// \param format User-specified message, as a formatting string. +/// \param ... Positional arguments to the format string. +void +kyua_error_fprintf(FILE* stream, const kyua_error_t error, + const char* format, ...) +{ + char buffer[2048]; + + va_list ap; + va_start(ap, format); + (void)format_user_message(error, format, ap, buffer, sizeof(buffer)); + va_end(ap); + + fprintf(stream, "%s", buffer); +} + + +/// Version of warn(3) that works with kyua_error_t objects. +/// +/// \param error Error to append to the output. This is not released. +/// \param format User-specified message, as a formatting string. +/// \param ... Positional arguments to the format string. +void +kyua_error_warn(const kyua_error_t error, const char* format, ...) +{ + char buffer[2048]; + + va_list ap; + va_start(ap, format); + (void)format_user_message(error, format, ap, buffer, sizeof(buffer)); + va_end(ap); + + warnx("%s", buffer); +} + + +/// Name of an generic error type. +const char* const kyua_generic_error_type = "generic"; + + +/// Generates a user-friendly representation of the error. +/// +/// \pre The error must be set. +/// +/// \param error Error for which to generate a message. +/// \param output_buffer Buffer to hold the generated message. +/// \param output_size Length of output_buffer. +/// +/// \return The number of bytes written to output_buffer, or a negative value if +/// there was an error. +static int +generic_format(const kyua_error_t error, char* const output_buffer, + const size_t output_size) +{ + assert(kyua_error_is_type(error, kyua_generic_error_type)); + + const char* message = kyua_error_data(error); + return snprintf(output_buffer, output_size, "%s", message); +} + + +/// Constructs a new generic error. +/// +/// \param message Textual description of the problem. +/// \param ... Positional arguments for the description. +/// +/// \return The generated error. +kyua_error_t +kyua_generic_error_new(const char* message, ...) +{ + char formatted[1024]; + va_list ap; + + va_start(ap, message); + (void)vsnprintf(formatted, sizeof(formatted), message, ap); + va_end(ap); + + return kyua_error_new(kyua_generic_error_type, formatted, sizeof(formatted), + generic_format); +} + + +/// Name of a libc type. +const char* const kyua_libc_error_type = "libc"; + + +/// Representation of a libc error. +struct libc_error_data { + /// Value of the errno captured during the error creation. + int original_errno; + + /// Explanation of the problem that lead to the error. + char description[4096]; +}; +/// Shorthand for a libc_error_data structure. +typedef struct libc_error_data libc_error_data_t; + + +/// Generates a user-friendly representation of the error. +/// +/// \pre The error must be set. +/// +/// \param error Error for which to generate a message. +/// \param output_buffer Buffer to hold the generated message. +/// \param output_size Length of output_buffer. +/// +/// \return The number of bytes written to output_buffer, or a negative value if +/// there was an error. +static int +libc_format(const kyua_error_t error, char* const output_buffer, + const size_t output_size) +{ + assert(kyua_error_is_type(error, kyua_libc_error_type)); + + const libc_error_data_t* data = kyua_error_data(error); + return snprintf(output_buffer, output_size, "%s: %s", data->description, + strerror(data->original_errno)); +} + + +/// Constructs a new libc error. +/// +/// \param original_errno libc error code for this error. +/// \param description Textual description of the problem. +/// \param ... Positional arguments for the description. +/// +/// \return The generated error. +kyua_error_t +kyua_libc_error_new(const int original_errno, const char* description, ...) +{ + va_list ap; + + const size_t data_size = sizeof(libc_error_data_t); + libc_error_data_t* data = (libc_error_data_t*)malloc(data_size); + if (data == NULL) + return kyua_oom_error_new(); + + data->original_errno = original_errno; + va_start(ap, description); + (void)vsnprintf(data->description, sizeof(data->description), + description, ap); + va_end(ap); + + return kyua_error_new(kyua_libc_error_type, data, data_size, libc_format); +} + + +/// Extracts the original errno of a libc error. +/// +/// \pre error must have been constructed by kyua_libc_error_new. +/// +/// \param error The error object to access. +/// +/// \return The libc error code. +int +kyua_libc_error_errno(const kyua_error_t error) +{ + assert(kyua_error_is_type(error, kyua_libc_error_type)); + + const struct libc_error_data* data = kyua_error_data(error); + return data->original_errno; +} + + +/// Name of an OOM type. +const char* const kyua_oom_error_type = "oom"; + + +/// Data of an out of memory error. +/// +/// All error types are allocated in dynamic memory. However, doing so for +/// an out of memory error is not possible because, when we are out of +/// memory, we probably cannot allocate more memory to generate an error. +/// Therefore, we just keep a single static instance of the out of memory +/// error around all the time. +static struct kyua_error oom_error; + + +/// Generates a user-friendly representation of the error. +/// +/// \pre The error must be set. +/// +/// \param error Error for which to generate a message. +/// \param output_buffer Buffer to hold the generated message. +/// \param output_size Length of output_buffer. +/// +/// \return The number of bytes written to output_buffer, or a negative value if +/// there was an error. +static int +oom_format(const kyua_error_t error, char* const output_buffer, + const size_t output_size) +{ + assert(kyua_error_is_type(error, kyua_oom_error_type)); + + return snprintf(output_buffer, output_size, "Not enough memory"); +} + + +/// Constructs a new out-of-memory error. +/// +/// This will always succeed because we just return a reference to the +/// statically-allocated oom_error. +/// +/// \return An error representing an out of memory condition. +kyua_error_t +kyua_oom_error_new(void) +{ + // This is idempotent; no need to ensure that we call it only once. + const bool ok = error_init(&oom_error, kyua_oom_error_type, NULL, 0, + oom_format); + assert(ok); + + return &oom_error; +} + + +/// Name of an usage error type. +const char* const kyua_usage_error_type = "usage"; + + +/// Generates a user-friendly representation of the error. +/// +/// \pre The error must be set. +/// +/// \param error Error for which to generate a message. +/// \param output_buffer Buffer to hold the generated message. +/// \param output_size Length of output_buffer. +/// +/// \return The number of bytes written to output_buffer, or a negative value if +/// there was an error. +static int +usage_format(const kyua_error_t error, char* const output_buffer, + const size_t output_size) +{ + assert(kyua_error_is_type(error, kyua_usage_error_type)); + + const char* message = kyua_error_data(error); + return snprintf(output_buffer, output_size, "%s", message); +} + + +/// Constructs a new usage error. +/// +/// \param message Textual description of the problem. +/// \param ... Positional arguments for the description. +/// +/// \return The generated error. +kyua_error_t +kyua_usage_error_new(const char* message, ...) +{ + char formatted[1024]; + va_list ap; + + va_start(ap, message); + (void)vsnprintf(formatted, sizeof(formatted), message, ap); + va_end(ap); + + return kyua_error_new(kyua_usage_error_type, formatted, sizeof(formatted), + usage_format); +} diff --git a/external/bsd/kyua-testers/dist/error.h b/external/bsd/kyua-testers/dist/error.h new file mode 100644 index 000000000..7713fcdba --- /dev/null +++ b/external/bsd/kyua-testers/dist/error.h @@ -0,0 +1,117 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file error.h +/// High-level representation of error conditions. +/// +/// The error module provides a mechanism to represent error conditions in an +/// efficient manner. In the case of a successful operation, an error is +/// internally represented as a NULL pointer and thus has no overhead. In the +/// case of an actual error, the representation is more complex and costly than +/// a traditional libc error number, but is also more verbose. Because errors +/// are not (or should not be!) in the critical path, this is not a concern. + +#if !defined(KYUA_ERROR_H) +#define KYUA_ERROR_H + +#include "error_fwd.h" + +#include +#include +#include + +#include "defs.h" + + +/// Type of the per-error formatting function. +/// +/// These functions take three arguments: the error to be formatted, a pointer +/// to the output buffer and the size of the output buffer. The return value +/// indicates how many bytes were written to the output buffer, or a negative +/// value in case of an error. +typedef int (*kyua_error_format_callback)( + struct kyua_error* const, char* const, const size_t); + + +/// Representation of an error. +struct kyua_error { + /// Whether the error object has to be released or not. + /// + /// Sometimes (the oom error), a kyua_error_t object may point to a + /// statically allocated error. Such object cannot be freed. + bool needs_free; + + /// Name of the type. + const char* type_name; + + /// Opaquet error-specific data. + void* data; + + /// Method to generate a textual representation of the error. + kyua_error_format_callback format_callback; +}; + + +kyua_error_t kyua_error_new(const char*, void*, size_t, + kyua_error_format_callback); +void kyua_error_free(kyua_error_t); +kyua_error_t kyua_error_subsume(kyua_error_t, kyua_error_t); + +kyua_error_t kyua_error_ok(void); +bool kyua_error_is_set(const kyua_error_t); +bool kyua_error_is_type(const kyua_error_t, const char*); + +const void* kyua_error_data(const kyua_error_t); +int kyua_error_format(const kyua_error_t, char* const, size_t); +void kyua_error_err(const int, const kyua_error_t, const char*, ...) + KYUA_DEFS_NORETURN KYUA_DEFS_FORMAT_PRINTF(3, 4); +void kyua_error_fprintf(FILE*, const kyua_error_t, const char*, ...); +void kyua_error_warn(const kyua_error_t, const char*, ...); + + +extern const char* const kyua_generic_error_type; +kyua_error_t kyua_generic_error_new(const char* , ...) + KYUA_DEFS_FORMAT_PRINTF(1, 2); + + +extern const char* const kyua_libc_error_type; +kyua_error_t kyua_libc_error_new(int, const char* , ...) + KYUA_DEFS_FORMAT_PRINTF(2, 3); +int kyua_libc_error_errno(const kyua_error_t); + + +extern const char* const kyua_oom_error_type; +kyua_error_t kyua_oom_error_new(void); + + +extern const char* const kyua_usage_error_type; +kyua_error_t kyua_usage_error_new(const char* , ...) + KYUA_DEFS_FORMAT_PRINTF(1, 2); + + +#endif // !defined(KYUA_ERROR_H) diff --git a/external/bsd/kyua-testers/dist/error_fwd.h b/external/bsd/kyua-testers/dist/error_fwd.h new file mode 100644 index 000000000..4d32f2a77 --- /dev/null +++ b/external/bsd/kyua-testers/dist/error_fwd.h @@ -0,0 +1,43 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file error_fwd.h +/// Forward declarations for the error.h header. + +#if !defined(KYUA_ERROR_FWD_H) +#define KYUA_ERROR_FWD_H + + +struct kyua_error; + + +/// Shorthand for a kyua_error structure. +typedef struct kyua_error* kyua_error_t; + + +#endif // !defined(KYUA_ERROR_FWD_H) diff --git a/external/bsd/kyua-testers/dist/error_test.c b/external/bsd/kyua-testers/dist/error_test.c new file mode 100644 index 000000000..1fc338b9d --- /dev/null +++ b/external/bsd/kyua-testers/dist/error_test.c @@ -0,0 +1,416 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "error.h" + +#include +#include +#include +#include +#include + +#include + + +ATF_TC_WITHOUT_HEAD(error_new__oom); +ATF_TC_BODY(error_new__oom, tc) +{ + void* invalid = (void*)1; + kyua_error_t error = kyua_error_new("test_error", invalid, SIZE_MAX, NULL); + ATF_REQUIRE(kyua_error_is_type(error, kyua_oom_error_type)); + ATF_REQUIRE(kyua_error_data(error) == NULL); + kyua_error_free(error); +} + + +ATF_TC_WITHOUT_HEAD(error_subsume__none); +ATF_TC_BODY(error_subsume__none, tc) +{ + kyua_error_t primary = kyua_error_ok(); + kyua_error_t secondary = kyua_error_ok(); + ATF_REQUIRE(!kyua_error_is_set(kyua_error_subsume(primary, secondary))); +} + + +ATF_TC_WITHOUT_HEAD(error_subsume__primary); +ATF_TC_BODY(error_subsume__primary, tc) +{ + kyua_error_t primary = kyua_error_new("primary_error", NULL, 0, NULL); + kyua_error_t secondary = kyua_error_new("secondary_error", NULL, 0, NULL); + kyua_error_t error = kyua_error_subsume(primary, secondary); + ATF_REQUIRE(kyua_error_is_type(error, "primary_error")); + kyua_error_free(error); +} + + +ATF_TC_WITHOUT_HEAD(error_subsume__secondary); +ATF_TC_BODY(error_subsume__secondary, tc) +{ + kyua_error_t primary = kyua_error_ok(); + kyua_error_t secondary = kyua_error_new("secondary_error", NULL, 0, NULL); + kyua_error_t error = kyua_error_subsume(primary, secondary); + ATF_REQUIRE(kyua_error_is_type(error, "secondary_error")); + kyua_error_free(error); +} + + +ATF_TC_WITHOUT_HEAD(error_is_type__match); +ATF_TC_BODY(error_is_type__match, tc) +{ + kyua_error_t error = kyua_error_new("test_error", NULL, 0, NULL); + ATF_REQUIRE(kyua_error_is_type(error, "test_error")); + kyua_error_free(error); +} + + +ATF_TC_WITHOUT_HEAD(error_is_type__not_match); +ATF_TC_BODY(error_is_type__not_match, tc) +{ + kyua_error_t error = kyua_error_new("test_error", NULL, 0, NULL); + ATF_REQUIRE(!kyua_error_is_type(error, "test_erro")); + ATF_REQUIRE(!kyua_error_is_type(error, "test_error2")); + ATF_REQUIRE(!kyua_error_is_type(error, "foo")); + kyua_error_free(error); +} + + +ATF_TC_WITHOUT_HEAD(error_data__none); +ATF_TC_BODY(error_data__none, tc) +{ + kyua_error_t error = kyua_error_new("test_error", NULL, 0, NULL); + ATF_REQUIRE(kyua_error_data(error) == NULL); + kyua_error_free(error); +} + + +ATF_TC_WITHOUT_HEAD(error_data__some); +ATF_TC_BODY(error_data__some, tc) +{ + int data = 5; + kyua_error_t error = kyua_error_new("test_data_error", &data, sizeof(data), + NULL); + ATF_REQUIRE(kyua_error_data(error) != NULL); + ATF_REQUIRE_EQ(*((const int*)kyua_error_data(error)), 5); + kyua_error_free(error); +} + + +ATF_TC_WITHOUT_HEAD(error_is_set__no); +ATF_TC_BODY(error_is_set__no, tc) +{ + kyua_error_t error = kyua_error_ok(); + ATF_REQUIRE(!kyua_error_is_set(error)); +} + + +ATF_TC_WITHOUT_HEAD(error_is_set__yes); +ATF_TC_BODY(error_is_set__yes, tc) +{ + kyua_error_t error = kyua_error_new("test_error", NULL, 0, NULL); + ATF_REQUIRE(kyua_error_is_set(error)); + kyua_error_free(error); +} + + +ATF_TC_WITHOUT_HEAD(error_format__default); +ATF_TC_BODY(error_format__default, tc) +{ + kyua_error_t error = kyua_error_new("test_error", NULL, 0, NULL); + char buffer[1024]; + kyua_error_format(error, buffer, sizeof(buffer)); + ATF_REQUIRE_STREQ("Error 'test_error'", buffer); + kyua_error_free(error); +} + + +/// Error-specific formatting function for testing purposes. +static int +test_format(const kyua_error_t error, char* const output_buffer, + const size_t output_size) +{ + ATF_REQUIRE(kyua_error_is_type(error, "test_error")); + return snprintf(output_buffer, output_size, "Test formatting function"); +} + + +ATF_TC_WITHOUT_HEAD(error_format__custom__ok); +ATF_TC_BODY(error_format__custom__ok, tc) +{ + kyua_error_t error = kyua_error_new("test_error", NULL, 0, test_format); + const char* exp_message = "Test formatting function"; + char buffer[1024]; + ATF_REQUIRE_EQ((int)strlen(exp_message), + kyua_error_format(error, buffer, sizeof(buffer))); + ATF_REQUIRE_STREQ(exp_message, buffer); + kyua_error_free(error); +} + + +ATF_TC_WITHOUT_HEAD(error_format__custom__error); +ATF_TC_BODY(error_format__custom__error, tc) +{ + kyua_error_t error = kyua_error_new("test_error", NULL, 0, test_format); + char buffer[5]; + ATF_REQUIRE(kyua_error_format(error, buffer, sizeof(buffer)) + >= (int)sizeof(buffer)); + kyua_error_free(error); +} + + +ATF_TC_WITHOUT_HEAD(err); +ATF_TC_BODY(err, tc) +{ + const pid_t pid = atf_utils_fork(); + if (pid == 0) { + kyua_error_t error = kyua_usage_error_new("A usage error"); + kyua_error_err(15, error, "The %s message", "1st"); + } + atf_utils_wait(pid, 15, "", "error_test: The 1st message: A usage error\n"); +} + + +ATF_TC_WITHOUT_HEAD(fprintf); +ATF_TC_BODY(fprintf, tc) +{ + FILE* output = fopen("output", "w"); + const kyua_error_t error = kyua_usage_error_new("A usage error"); + kyua_error_fprintf(output, error, "The %s message", "1st"); + kyua_error_free(error); + fclose(output); + + ATF_REQUIRE(atf_utils_grep_file("The 1st message: A usage error", + "output")); +} + + +ATF_TC_WITHOUT_HEAD(warn); +ATF_TC_BODY(warn, tc) +{ + const pid_t pid = atf_utils_fork(); + if (pid == 0) { + kyua_error_t error = kyua_usage_error_new("A usage error"); + kyua_error_warn(error, "The %s message", "1st"); + kyua_error_free(error); + exit(51); + } + atf_utils_wait(pid, 51, "", "error_test: The 1st message: A usage error\n"); +} + + +ATF_TC_WITHOUT_HEAD(generic_error_type); +ATF_TC_BODY(generic_error_type, tc) +{ + kyua_error_t error = kyua_generic_error_new("Nothing"); + ATF_REQUIRE(kyua_error_is_type(error, kyua_generic_error_type)); + kyua_error_free(error); +} + + +ATF_TC_WITHOUT_HEAD(generic_error_format__plain); +ATF_TC_BODY(generic_error_format__plain, tc) +{ + kyua_error_t error = kyua_generic_error_new("Test message"); + char buffer[1024]; + kyua_error_format(error, buffer, sizeof(buffer)); + ATF_REQUIRE_STREQ("Test message", buffer); + kyua_error_free(error); +} + + +ATF_TC_WITHOUT_HEAD(generic_error_format__args); +ATF_TC_BODY(generic_error_format__args, tc) +{ + kyua_error_t error = kyua_generic_error_new("%s message %d", "A", 123); + char buffer[1024]; + kyua_error_format(error, buffer, sizeof(buffer)); + ATF_REQUIRE_STREQ("A message 123", buffer); + kyua_error_free(error); +} + + +ATF_TC_WITHOUT_HEAD(libc_error_type); +ATF_TC_BODY(libc_error_type, tc) +{ + kyua_error_t error = kyua_libc_error_new(ENOMEM, "Nothing"); + ATF_REQUIRE(kyua_error_is_type(error, kyua_libc_error_type)); + kyua_error_free(error); +} + + +ATF_TC_WITHOUT_HEAD(libc_error_errno); +ATF_TC_BODY(libc_error_errno, tc) +{ + kyua_error_t error = kyua_libc_error_new(EPERM, "Doesn't matter"); + ATF_REQUIRE_EQ(EPERM, kyua_libc_error_errno(error)); + kyua_error_free(error); +} + + +ATF_TC_WITHOUT_HEAD(libc_error_format__plain); +ATF_TC_BODY(libc_error_format__plain, tc) +{ + kyua_error_t error = kyua_libc_error_new(ENOMEM, "Test message"); + char buffer[1024]; + kyua_error_format(error, buffer, sizeof(buffer)); + ATF_REQUIRE(strstr(buffer, strerror(ENOMEM)) != NULL); + ATF_REQUIRE(strstr(buffer, "Test message") != NULL); + kyua_error_free(error); +} + + +ATF_TC_WITHOUT_HEAD(libc_error_format__args); +ATF_TC_BODY(libc_error_format__args, tc) +{ + kyua_error_t error = kyua_libc_error_new(EPERM, "%s message %d", "A", 123); + char buffer[1024]; + kyua_error_format(error, buffer, sizeof(buffer)); + ATF_REQUIRE(strstr(buffer, strerror(EPERM)) != NULL); + ATF_REQUIRE(strstr(buffer, "A message 123") != NULL); + kyua_error_free(error); +} + + +ATF_TC_WITHOUT_HEAD(oom_error_type); +ATF_TC_BODY(oom_error_type, tc) +{ + kyua_error_t error = kyua_oom_error_new(); + ATF_REQUIRE(kyua_error_is_type(error, kyua_oom_error_type)); + kyua_error_free(error); +} + + +ATF_TC_WITHOUT_HEAD(oom_error_data); +ATF_TC_BODY(oom_error_data, tc) +{ + kyua_error_t error = kyua_oom_error_new(); + ATF_REQUIRE(kyua_error_data(error) == NULL); + kyua_error_free(error); +} + + +ATF_TC_WITHOUT_HEAD(oom_error_format); +ATF_TC_BODY(oom_error_format, tc) +{ + kyua_error_t error = kyua_oom_error_new(); + char buffer[1024]; + kyua_error_format(error, buffer, sizeof(buffer)); + ATF_REQUIRE_STREQ("Not enough memory", buffer); + kyua_error_free(error); +} + + +ATF_TC_WITHOUT_HEAD(oom_error_reuse); +ATF_TC_BODY(oom_error_reuse, tc) +{ + { + kyua_error_t error = kyua_oom_error_new(); + ATF_REQUIRE(kyua_error_is_type(error, kyua_oom_error_type)); + ATF_REQUIRE(kyua_error_data(error) == NULL); + kyua_error_free(error); + } + + { + kyua_error_t error = kyua_oom_error_new(); + ATF_REQUIRE(kyua_error_is_type(error, kyua_oom_error_type)); + ATF_REQUIRE(kyua_error_data(error) == NULL); + kyua_error_free(error); + } +} + + +ATF_TC_WITHOUT_HEAD(usage_error_type); +ATF_TC_BODY(usage_error_type, tc) +{ + kyua_error_t error = kyua_usage_error_new("Nothing"); + ATF_REQUIRE(kyua_error_is_type(error, kyua_usage_error_type)); + kyua_error_free(error); +} + + +ATF_TC_WITHOUT_HEAD(usage_error_format__plain); +ATF_TC_BODY(usage_error_format__plain, tc) +{ + kyua_error_t error = kyua_usage_error_new("Test message"); + char buffer[1024]; + kyua_error_format(error, buffer, sizeof(buffer)); + ATF_REQUIRE_STREQ("Test message", buffer); + kyua_error_free(error); +} + + +ATF_TC_WITHOUT_HEAD(usage_error_format__args); +ATF_TC_BODY(usage_error_format__args, tc) +{ + kyua_error_t error = kyua_usage_error_new("%s message %d", "A", 123); + char buffer[1024]; + kyua_error_format(error, buffer, sizeof(buffer)); + ATF_REQUIRE_STREQ("A message 123", buffer); + kyua_error_free(error); +} + + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, error_new__oom); + ATF_TP_ADD_TC(tp, error_subsume__none); + ATF_TP_ADD_TC(tp, error_subsume__primary); + ATF_TP_ADD_TC(tp, error_subsume__secondary); + ATF_TP_ADD_TC(tp, error_is_type__match); + ATF_TP_ADD_TC(tp, error_is_type__not_match); + ATF_TP_ADD_TC(tp, error_data__none); + ATF_TP_ADD_TC(tp, error_data__some); + ATF_TP_ADD_TC(tp, error_is_set__no); + ATF_TP_ADD_TC(tp, error_is_set__yes); + ATF_TP_ADD_TC(tp, error_format__default); + ATF_TP_ADD_TC(tp, error_format__custom__ok); + ATF_TP_ADD_TC(tp, error_format__custom__error); + + ATF_TP_ADD_TC(tp, err); + ATF_TP_ADD_TC(tp, fprintf); + ATF_TP_ADD_TC(tp, warn); + + ATF_TP_ADD_TC(tp, generic_error_type); + ATF_TP_ADD_TC(tp, generic_error_format__plain); + ATF_TP_ADD_TC(tp, generic_error_format__args); + + ATF_TP_ADD_TC(tp, libc_error_type); + ATF_TP_ADD_TC(tp, libc_error_errno); + ATF_TP_ADD_TC(tp, libc_error_format__plain); + ATF_TP_ADD_TC(tp, libc_error_format__args); + + ATF_TP_ADD_TC(tp, oom_error_type); + ATF_TP_ADD_TC(tp, oom_error_data); + ATF_TP_ADD_TC(tp, oom_error_format); + ATF_TP_ADD_TC(tp, oom_error_reuse); + + ATF_TP_ADD_TC(tp, usage_error_type); + ATF_TP_ADD_TC(tp, usage_error_format__plain); + ATF_TP_ADD_TC(tp, usage_error_format__args); + + return atf_no_error(); +} diff --git a/external/bsd/kyua-testers/dist/fs.c b/external/bsd/kyua-testers/dist/fs.c new file mode 100644 index 000000000..6294828fc --- /dev/null +++ b/external/bsd/kyua-testers/dist/fs.c @@ -0,0 +1,577 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "fs.h" + +#if defined(HAVE_CONFIG_H) +# include "config.h" +#endif + +#if defined(HAVE_UNMOUNT) +# include +# include +#endif +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "defs.h" +#include "error.h" + + +/// Specifies if a real unmount(2) is available. +/// +/// We use this as a constant instead of a macro so that we can compile both +/// versions of the unmount code unconditionally. This is a way to prevent +/// compilation bugs going unnoticed for long. +static const bool have_unmount2 = +#if defined(HAVE_UNMOUNT) + true; +#else + false; +#endif + + +#if !defined(UMOUNT) +/// Fake replacement value to the path to umount(8). +# define UMOUNT "do-not-use-this-value" +#else +# if defined(HAVE_UNMOUNT) +# error "umount(8) detected when unmount(2) is also available" +# endif +#endif + + +#if !defined(HAVE_UNMOUNT) +/// Fake unmount(2) function for systems without it. +/// +/// This is only provided to allow our code to compile in all platforms +/// regardless of whether they actually have an unmount(2) or not. +/// +/// \param unused_path The mount point to be unmounted. +/// \param unused_flags The flags to the unmount(2) call. +/// +/// \return -1 to indicate error, although this should never happen. +static int +unmount(const char* KYUA_DEFS_UNUSED_PARAM(path), + const int KYUA_DEFS_UNUSED_PARAM(flags)) +{ + assert(false); + return -1; +} +#endif + + +/// Scans a directory and executes a callback on each entry. +/// +/// \param directory The directory to scan. +/// \param callback The function to execute on each entry. +/// \param argument A cookie to pass to the callback function. +/// +/// \return True if the directory scan and the calls to the callback function +/// are all successful; false otherwise. +/// +/// \note Errors are logged to stderr and do not stop the algorithm. +static bool +try_iterate_directory(const char* directory, + bool (*callback)(const char*, const void*), + const void* argument) +{ + bool ok = true; + + DIR* dirp = opendir(directory); + if (dirp == NULL) { + warn("opendir(%s) failed", directory); + ok &= false; + } else { + struct dirent* dp; + while ((dp = readdir(dirp)) != NULL) { + const char* name = dp->d_name; + if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) + continue; + + char* subdir; + const kyua_error_t error = kyua_fs_concat(&subdir, directory, name, + NULL); + if (kyua_error_is_set(error)) { + kyua_error_free(error); + warn("path concatenation failed"); + ok &= false; + } else { + ok &= callback(subdir, argument); + free(subdir); + } + } + closedir(dirp); + } + + return ok; +} + + +/// Stats a file, without following links. +/// +/// \param path The file to stat. +/// \param [out] sb Pointer to the stat structure in which to place the result. +/// +/// \return The stat structure on success; none on failure. +/// +/// \note Errors are logged to stderr. +static bool +try_stat(const char* path, struct stat* sb) +{ + if (lstat(path, sb) == -1) { + warn("lstat(%s) failed", path); + return false; + } else + return true; +} + + +/// Removes a directory. +/// +/// \param path The directory to remove. +/// +/// \return True on success; false otherwise. +/// +/// \note Errors are logged to stderr. +static bool +try_rmdir(const char* path) +{ + if (rmdir(path) == -1) { + warn("rmdir(%s) failed", path); + return false; + } else + return true; +} + + +/// Removes a file. +/// +/// \param path The file to remove. +/// +/// \return True on success; false otherwise. +/// +/// \note Errors are logged to stderr. +static bool +try_unlink(const char* path) +{ + if (unlink(path) == -1) { + warn("unlink(%s) failed", path); + return false; + } else + return true; +} + + +/// Unmounts a mount point. +/// +/// \param path The location to unmount. +/// +/// \return True on success; false otherwise. +/// +/// \note Errors are logged to stderr. +static bool +try_unmount(const char* path) +{ + const kyua_error_t error = kyua_fs_unmount(path); + if (kyua_error_is_set(error)) { + kyua_error_warn(error, "Cannot unmount %s", path); + kyua_error_free(error); + return false; + } else + return true; +} + + +/// Attempts to weaken the permissions of a file. +/// +/// \param path The file to unprotect. +/// +/// \return True on success; false otherwise. +/// +/// \note Errors are logged to stderr. +static bool +try_unprotect(const char* path) +{ + static const mode_t new_mode = 0700; + + if (chmod(path, new_mode) == -1) { + warnx("chmod(%s, %04o) failed", path, new_mode); + return false; + } else + return true; +} + + +/// Attempts to weaken the permissions of a symbolic link. +/// +/// \param path The symbolic link to unprotect. +/// +/// \return True on success; false otherwise. +/// +/// \note Errors are logged to stderr. +static bool +try_unprotect_symlink(const char* path) +{ + static const mode_t new_mode = 0700; + +#if HAVE_WORKING_LCHMOD + if (lchmod(path, new_mode) == -1) { + warnx("lchmod(%s, %04o) failed", path, new_mode); + return false; + } else + return true; +#else + warnx("lchmod(%s, %04o) failed; system call not implemented", path, + new_mode); + return false; +#endif +} + + +/// Traverses a hierarchy unmounting any mount points in it. +/// +/// \param current_path The file or directory to traverse. +/// \param raw_parent_sb The stat structure of the enclosing directory. +/// +/// \return True on success; false otherwise. +/// +/// \note Errors are logged to stderr and do not stop the algorithm. +static bool +recursive_unmount(const char* current_path, const void* raw_parent_sb) +{ + const struct stat* parent_sb = raw_parent_sb; + + struct stat current_sb; + bool ok = try_stat(current_path, ¤t_sb); + if (ok) { + if (S_ISDIR(current_sb.st_mode)) { + assert(!S_ISLNK(current_sb.st_mode)); + ok &= try_iterate_directory(current_path, recursive_unmount, + ¤t_sb); + } + + if (current_sb.st_dev != parent_sb->st_dev) + ok &= try_unmount(current_path); + } + + return ok; +} + + +/// Traverses a hierarchy and removes all of its contents. +/// +/// This honors mount points: when a mount point is encountered, it is traversed +/// in search for other mount points, but no files within any of these are +/// removed. +/// +/// \param current_path The file or directory to traverse. +/// \param raw_parent_sb The stat structure of the enclosing directory. +/// +/// \return True on success; false otherwise. +/// +/// \note Errors are logged to stderr and do not stop the algorithm. +static bool +recursive_cleanup(const char* current_path, const void* raw_parent_sb) +{ + const struct stat* parent_sb = raw_parent_sb; + + struct stat current_sb; + bool ok = try_stat(current_path, ¤t_sb); + if (ok) { + // Weakening the protections of a file is just a best-effort operation. + // If this fails, we may still be able to do the file/directory removal + // later on, so ignore any failures from try_unprotect(). + // + // One particular case in which this fails is if try_unprotect() is run + // on a symbolic link that points to a file for which the unprotect is + // not possible, and lchmod(3) is not available. + if (S_ISLNK(current_sb.st_mode)) + try_unprotect_symlink(current_path); + else + try_unprotect(current_path); + + if (current_sb.st_dev != parent_sb->st_dev) { + ok &= recursive_unmount(current_path, parent_sb); + if (ok) + ok &= recursive_cleanup(current_path, parent_sb); + } else { + if (S_ISDIR(current_sb.st_mode)) { + assert(!S_ISLNK(current_sb.st_mode)); + ok &= try_iterate_directory(current_path, recursive_cleanup, + ¤t_sb); + ok &= try_rmdir(current_path); + } else { + ok &= try_unlink(current_path); + } + } + } + + return ok; +} + + +/// Unmounts a file system using unmount(2). +/// +/// \pre unmount(2) must be available; i.e. have_unmount2 must be true. +/// +/// \param mount_point The file system to unmount. +/// +/// \return An error object. +static kyua_error_t +unmount_with_unmount2(const char* mount_point) +{ + assert(have_unmount2); + + if (unmount(mount_point, 0) == -1) { + return kyua_libc_error_new(errno, "unmount(%s) failed", + mount_point); + } + + return kyua_error_ok(); +} + + +/// Unmounts a file system using umount(8). +/// +/// \pre umount(2) must not be available; i.e. have_unmount2 must be false. +/// +/// \param mount_point The file system to unmount. +/// +/// \return An error object. +static kyua_error_t +unmount_with_umount8(const char* mount_point) +{ + assert(!have_unmount2); + + const pid_t pid = fork(); + if (pid == -1) { + return kyua_libc_error_new(errno, "fork() failed"); + } else if (pid == 0) { + const int ret = execlp(UMOUNT, "umount", mount_point, NULL); + assert(ret == -1); + err(EXIT_FAILURE, "Failed to execute " UMOUNT); + } + + kyua_error_t error = kyua_error_ok(); + int status; + if (waitpid(pid, &status, 0) == -1) { + error = kyua_libc_error_new(errno, "waitpid(%d) failed", pid); + } else { + if (WIFEXITED(status)) { + if (WEXITSTATUS(status) == EXIT_SUCCESS) + assert(!kyua_error_is_set(error)); + else { + error = kyua_libc_error_new(EBUSY, "unmount(%s) failed", + mount_point); + } + } else + error = kyua_libc_error_new(EFAULT, "umount(8) crashed"); + } + return error; +} + + +/// Recursively removes a directory. +/// +/// \param root The directory or file to remove. Cannot be a mount point. +/// +/// \return An error object. +kyua_error_t +kyua_fs_cleanup(const char* root) +{ + struct stat current_sb; + bool ok = try_stat(root, ¤t_sb); + if (ok) + ok &= recursive_cleanup(root, ¤t_sb); + + if (!ok) { + warnx("Cleanup of '%s' failed", root); + return kyua_libc_error_new(EPERM, "Cleanup of %s failed", root); + } else + return kyua_error_ok(); +} + + +/// Concatenates a set of strings to form a path. +/// +/// \param [out] output Pointer to a dynamically-allocated string that will hold +/// the resulting path, if all goes well. +/// \param first First component of the path to concatenate. +/// \param ... All other components to concatenate. +/// +/// \return An error if there is not enough memory to fulfill the request; OK +/// otherwise. +kyua_error_t +kyua_fs_concat(char** const output, const char* first, ...) +{ + va_list ap; + const char* component; + + va_start(ap, first); + size_t length = strlen(first) + 1; + while ((component = va_arg(ap, const char*)) != NULL) { + length += 1 + strlen(component); + } + va_end(ap); + + *output = (char*)malloc(length); + if (output == NULL) + return kyua_oom_error_new(); + char* iterator = *output; + + int added_size; + added_size = snprintf(iterator, length, "%s", first); + iterator += added_size; length -= added_size; + + va_start(ap, first); + while ((component = va_arg(ap, const char*)) != NULL) { + added_size = snprintf(iterator, length, "/%s", component); + iterator += added_size; length -= added_size; + } + va_end(ap); + + return kyua_error_ok(); +} + + +/// Queries the path to the current directory. +/// +/// \param [out] out_cwd Dynamically-allocated pointer to a string holding the +/// current path. The caller must use free() to release it. +/// +/// \return An error object. +kyua_error_t +kyua_fs_current_path(char** out_cwd) +{ + char* cwd; +#if defined(HAVE_GETCWD_DYN) + cwd = getcwd(NULL, 0); +#else + { + const char* static_cwd = ::getcwd(NULL, MAXPATHLEN); + const kyua_error_t error = kyua_fs_concat(&cwd, static_cwd, NULL); + if (kyua_error_is_set(error)) + return error; + } +#endif + if (cwd == NULL) { + return kyua_libc_error_new(errno, "getcwd() failed"); + } else { + *out_cwd = cwd; + return kyua_error_ok(); + } +} + + +/// Converts a path to absolute. +/// +/// \param original The path to convert; may already be absolute. +/// \param [out] output Pointer to a dynamically-allocated string that will hold +/// the absolute path, if all goes well. +/// +/// \return An error if there is not enough memory to fulfill the request; OK +/// otherwise. +kyua_error_t +kyua_fs_make_absolute(const char* original, char** const output) +{ + if (original[0] == '/') { + *output = (char*)malloc(strlen(original) + 1); + if (output == NULL) + return kyua_oom_error_new(); + strcpy(*output, original); + return kyua_error_ok(); + } else { + char* current_path; + kyua_error_t error; + + error = kyua_fs_current_path(¤t_path); + if (kyua_error_is_set(error)) + return error; + + error = kyua_fs_concat(output, current_path, original, NULL); + free(current_path); + return error; + } +} + + +/// Unmounts a file system. +/// +/// \param mount_point The file system to unmount. +/// +/// \return An error object. +kyua_error_t +kyua_fs_unmount(const char* mount_point) +{ + kyua_error_t error; + + // FreeBSD's unmount(2) requires paths to be absolute. To err on the side + // of caution, let's make it absolute in all cases. + char* abs_mount_point; + error = kyua_fs_make_absolute(mount_point, &abs_mount_point); + if (kyua_error_is_set(error)) + goto out; + + static const int unmount_retries = 3; + static const int unmount_retry_delay_seconds = 1; + + int retries = unmount_retries; +retry: + if (have_unmount2) { + error = unmount_with_unmount2(abs_mount_point); + } else { + error = unmount_with_umount8(abs_mount_point); + } + if (kyua_error_is_set(error)) { + assert(kyua_error_is_type(error, "libc")); + if (kyua_libc_error_errno(error) == EBUSY && retries > 0) { + kyua_error_warn(error, "%s busy; unmount retries left %d", + abs_mount_point, retries); + kyua_error_free(error); + retries--; + sleep(unmount_retry_delay_seconds); + goto retry; + } + } + +out: + free(abs_mount_point); + return error; +} diff --git a/external/bsd/kyua-testers/dist/fs.h b/external/bsd/kyua-testers/dist/fs.h new file mode 100644 index 000000000..482111295 --- /dev/null +++ b/external/bsd/kyua-testers/dist/fs.h @@ -0,0 +1,45 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file fs.h +/// Routines for file system manipulation. + +#if !defined(KYUA_FS_H) +#define KYUA_FS_H + +#include "error_fwd.h" + + +kyua_error_t kyua_fs_cleanup(const char*); +kyua_error_t kyua_fs_concat(char** const, const char*, ...); +kyua_error_t kyua_fs_current_path(char**); +kyua_error_t kyua_fs_make_absolute(const char*, char**); +kyua_error_t kyua_fs_unmount(const char*); + + +#endif // !defined(KYUA_FS_H) diff --git a/external/bsd/kyua-testers/dist/fs_test.c b/external/bsd/kyua-testers/dist/fs_test.c new file mode 100644 index 000000000..4c6f6c369 --- /dev/null +++ b/external/bsd/kyua-testers/dist/fs_test.c @@ -0,0 +1,576 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "fs.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "error.h" + + +static void run_mount_tmpfs(const char*) KYUA_DEFS_NORETURN; + + +/// Operating systems recognized by the code below. +enum os_type { + os_unsupported = 0, + os_freebsd, + os_linux, + os_netbsd, + os_sunos, +}; + + +/// The current operating system. +static enum os_type current_os = +#if defined(__FreeBSD__) + os_freebsd +#elif defined(__linux__) + os_linux +#elif defined(__NetBSD__) + os_netbsd +#elif defined(__SunOS__) + os_sunos +#else + os_unsupported +#endif + ; + + +/// Checks if a directory entry exists and matches a specific type. +/// +/// \param dir The directory in which to look for the entry. +/// \param name The name of the entry to look up. +/// \param expected_type The expected type of the file as given by dir(5). +/// +/// \return True if the entry exists and matches the given type; false +/// otherwise. +static bool +lookup(const char* dir, const char* name, const int expected_type) +{ + DIR* dirp = opendir(dir); + ATF_REQUIRE(dirp != NULL); + + bool found = false; + struct dirent* dp; + while (!found && (dp = readdir(dirp)) != NULL) { + if (strcmp(dp->d_name, name) == 0 && + dp->d_type == expected_type) { + found = true; + } + } + closedir(dirp); + return found; +} + + +/// Executes 'mount -t tmpfs' (or a similar variant). +/// +/// This function must be called from a subprocess, as it never returns. +/// +/// \param mount_point Location on which to mount a tmpfs. +static void +run_mount_tmpfs(const char* mount_point) +{ + const char* mount_args[16]; + + size_t last = 0; + switch (current_os) { + case os_freebsd: + mount_args[last++] = "mdmfs"; + mount_args[last++] = "-s16m"; + mount_args[last++] = "md"; + mount_args[last++] = mount_point; + break; + + case os_linux: + mount_args[last++] = "mount"; + mount_args[last++] = "-ttmpfs"; + mount_args[last++] = "tmpfs"; + mount_args[last++] = mount_point; + break; + + case os_netbsd: + mount_args[last++] = "mount"; + mount_args[last++] = "-ttmpfs"; + mount_args[last++] = "tmpfs"; + mount_args[last++] = mount_point; + break; + + case os_sunos: + mount_args[last++] = "mount"; + mount_args[last++] = "-Ftmpfs"; + mount_args[last++] = "tmpfs"; + mount_args[last++] = mount_point; + break; + + default: + err(123, "Don't know how to mount a file system for testing " + "purposes"); + } + mount_args[last] = NULL; + + const char** arg; + printf("Mounting tmpfs onto %s with:", mount_point); + for (arg = &mount_args[0]; *arg != NULL; arg++) + printf(" %s", *arg); + printf("\n"); + + const int ret = execvp(mount_args[0], KYUA_DEFS_UNCONST(mount_args)); + assert(ret == -1); + err(EXIT_FAILURE, "Failed to exec %s", mount_args[0]); +}; + + +/// Mounts a temporary file system. +/// +/// This is only provided for testing purposes. The mounted file system +/// contains no valuable data. +/// +/// Note that the calling test case is skipped if the current operating system +/// is not supported. +/// +/// \param mount_point The path on which the file system will be mounted. +static void +mount_tmpfs(const char* mount_point) +{ + // SunOS's mount(8) requires paths to be absolute. To err on the side of + // caution, let's make it absolute in all cases. + //const fspath abs_mount_point = mount_point.is_absolute() ? + // mount_point : mount_point.to_absolute(); + + pid_t pid = fork(); + ATF_REQUIRE(pid != -1); + if (pid == 0) + run_mount_tmpfs(mount_point); + int status; + ATF_REQUIRE(waitpid(pid, &status, 0) != -1); + ATF_REQUIRE(WIFEXITED(status)); + if (WEXITSTATUS(status) == 123) + atf_tc_skip("Don't know how to mount a file system for testing " + "purposes"); + else + ATF_REQUIRE_EQ(EXIT_SUCCESS, WEXITSTATUS(status)); +} + + +static bool +lchmod_fails(void) +{ + ATF_REQUIRE(mkdir("test", 0755) != -1); + return lchmod("test", 0700) == -1 && chmod("test", 0700) != -1; +} + + +ATF_TC_WITHOUT_HEAD(cleanup__file); +ATF_TC_BODY(cleanup__file, tc) +{ + atf_utils_create_file("root", "%s", ""); + ATF_REQUIRE(lookup(".", "root", DT_REG)); + ATF_REQUIRE(!kyua_error_is_set(kyua_fs_cleanup("root"))); + ATF_REQUIRE(!lookup(".", "root", DT_REG)); +} + + +ATF_TC_WITHOUT_HEAD(cleanup__subdir__empty); +ATF_TC_BODY(cleanup__subdir__empty, tc) +{ + ATF_REQUIRE(mkdir("root", 0755) != -1); + ATF_REQUIRE(lookup(".", "root", DT_DIR)); + ATF_REQUIRE(!kyua_error_is_set(kyua_fs_cleanup("root"))); + ATF_REQUIRE(!lookup(".", "root", DT_DIR)); +} + + +ATF_TC_WITHOUT_HEAD(cleanup__subdir__files_and_directories); +ATF_TC_BODY(cleanup__subdir__files_and_directories, tc) +{ + ATF_REQUIRE(mkdir("root", 0755) != -1); + atf_utils_create_file("root/.hidden_file", "%s", ""); + ATF_REQUIRE(mkdir("root/.hidden_dir", 0755) != -1); + atf_utils_create_file("root/.hidden_dir/a", "%s", ""); + atf_utils_create_file("root/file", "%s", ""); + atf_utils_create_file("root/with spaces", "%s", ""); + ATF_REQUIRE(mkdir("root/dir1", 0755) != -1); + ATF_REQUIRE(mkdir("root/dir1/dir2", 0755) != -1); + atf_utils_create_file("root/dir1/dir2/file", "%s", ""); + ATF_REQUIRE(mkdir("root/dir1/dir3", 0755) != -1); + ATF_REQUIRE(lookup(".", "root", DT_DIR)); + ATF_REQUIRE(!kyua_error_is_set(kyua_fs_cleanup("root"))); + ATF_REQUIRE(!lookup(".", "root", DT_DIR)); +} + + +ATF_TC_WITHOUT_HEAD(cleanup__subdir__unprotect_regular); +ATF_TC_BODY(cleanup__subdir__unprotect_regular, tc) +{ + ATF_REQUIRE(mkdir("root", 0755) != -1); + ATF_REQUIRE(mkdir("root/dir1", 0755) != -1); + ATF_REQUIRE(mkdir("root/dir1/dir2", 0755) != -1); + atf_utils_create_file("root/dir1/dir2/file", "%s", ""); + ATF_REQUIRE(chmod("root/dir1/dir2/file", 0000) != -1); + ATF_REQUIRE(chmod("root/dir1/dir2", 0000) != -1); + ATF_REQUIRE(chmod("root/dir1", 0000) != -1); + ATF_REQUIRE(!kyua_error_is_set(kyua_fs_cleanup("root"))); + ATF_REQUIRE(!lookup(".", "root", DT_DIR)); +} + + +ATF_TC(cleanup__subdir__unprotect_symlink); +ATF_TC_HEAD(cleanup__subdir__unprotect_symlink, tc) +{ + atf_tc_set_md_var(tc, "require.progs", "/bin/ls"); + // We are ensuring that chmod is not run on the target of a symlink, so + // we cannot be root (nor we don't want to, to prevent unprotecting a + // system file!). + atf_tc_set_md_var(tc, "require.user", "unprivileged"); +} +ATF_TC_BODY(cleanup__subdir__unprotect_symlink, tc) +{ + ATF_REQUIRE(mkdir("root", 0755) != -1); + ATF_REQUIRE(mkdir("root/dir1", 0755) != -1); + ATF_REQUIRE(symlink("/bin/ls", "root/dir1/ls") != -1); + ATF_REQUIRE(chmod("root/dir1", 0555) != -1); + ATF_REQUIRE(!kyua_error_is_set(kyua_fs_cleanup("root"))); + ATF_REQUIRE(!lookup(".", "root", DT_DIR)); +} + + +ATF_TC_WITHOUT_HEAD(cleanup__subdir__links); +ATF_TC_BODY(cleanup__subdir__links, tc) +{ + ATF_REQUIRE(mkdir("root", 0755) != -1); + ATF_REQUIRE(mkdir("root/dir1", 0755) != -1); + ATF_REQUIRE(symlink("../../root", "root/dir1/loop") != -1); + ATF_REQUIRE(symlink("non-existent", "root/missing") != -1); + ATF_REQUIRE(lookup(".", "root", DT_DIR)); + kyua_error_t error = kyua_fs_cleanup("root"); + if (kyua_error_is_set(error)) { + if (lchmod_fails()) + atf_tc_expect_fail("lchmod(2) is not implemented in your system"); + kyua_error_free(error); + atf_tc_fail("kyua_fs_cleanup returned an error"); + } + ATF_REQUIRE(!lookup(".", "root", DT_DIR)); +} + + +ATF_TC(cleanup__mount_point__simple); +ATF_TC_HEAD(cleanup__mount_point__simple, tc) +{ + atf_tc_set_md_var(tc, "require.user", "root"); +} +ATF_TC_BODY(cleanup__mount_point__simple, tc) +{ + ATF_REQUIRE(mkdir("root", 0755) != -1); + ATF_REQUIRE(mkdir("root/dir1", 0755) != -1); + atf_utils_create_file("root/zz", "%s", ""); + mount_tmpfs("root/dir1"); + ATF_REQUIRE(!kyua_error_is_set(kyua_fs_cleanup("root"))); + ATF_REQUIRE(!lookup(".", "root", DT_DIR)); +} + + +ATF_TC(cleanup__mount_point__overlayed); +ATF_TC_HEAD(cleanup__mount_point__overlayed, tc) +{ + atf_tc_set_md_var(tc, "require.user", "root"); +} +ATF_TC_BODY(cleanup__mount_point__overlayed, tc) +{ + ATF_REQUIRE(mkdir("root", 0755) != -1); + ATF_REQUIRE(mkdir("root/dir1", 0755) != -1); + atf_utils_create_file("root/zz", "%s", ""); + mount_tmpfs("root/dir1"); + mount_tmpfs("root/dir1"); + ATF_REQUIRE(!kyua_error_is_set(kyua_fs_cleanup("root"))); + ATF_REQUIRE(!lookup(".", "root", DT_DIR)); +} + + +ATF_TC(cleanup__mount_point__nested); +ATF_TC_HEAD(cleanup__mount_point__nested, tc) +{ + atf_tc_set_md_var(tc, "require.user", "root"); +} +ATF_TC_BODY(cleanup__mount_point__nested, tc) +{ + ATF_REQUIRE(mkdir("root", 0755) != -1); + ATF_REQUIRE(mkdir("root/dir1", 0755) != -1); + ATF_REQUIRE(mkdir("root/dir1/dir2", 0755) != -1); + ATF_REQUIRE(mkdir("root/dir3", 0755) != -1); + mount_tmpfs("root/dir1/dir2"); + mount_tmpfs("root/dir3"); + ATF_REQUIRE(mkdir("root/dir1/dir2/dir4", 0755) != -1); + mount_tmpfs("root/dir1/dir2/dir4"); + ATF_REQUIRE(mkdir("root/dir1/dir2/not-mount-point", 0755) != -1); + ATF_REQUIRE(!kyua_error_is_set(kyua_fs_cleanup("root"))); + ATF_REQUIRE(!lookup(".", "root", DT_DIR)); +} + + +ATF_TC(cleanup__mount_point__links); +ATF_TC_HEAD(cleanup__mount_point__links, tc) +{ + atf_tc_set_md_var(tc, "require.user", "root"); +} +ATF_TC_BODY(cleanup__mount_point__links, tc) +{ + ATF_REQUIRE(mkdir("root", 0755) != -1); + ATF_REQUIRE(mkdir("root/dir1", 0755) != -1); + ATF_REQUIRE(mkdir("root/dir3", 0755) != -1); + mount_tmpfs("root/dir1"); + ATF_REQUIRE(symlink("../dir3", "root/dir1/link") != -1); + ATF_REQUIRE(!kyua_error_is_set(kyua_fs_cleanup("root"))); + ATF_REQUIRE(!lookup(".", "root", DT_DIR)); +} + + +ATF_TC(cleanup__mount_point__busy); +ATF_TC_HEAD(cleanup__mount_point__busy, tc) +{ + atf_tc_set_md_var(tc, "require.user", "root"); +} +ATF_TC_BODY(cleanup__mount_point__busy, tc) +{ + ATF_REQUIRE(mkdir("root", 0755) != -1); + ATF_REQUIRE(mkdir("root/dir1", 0755) != -1); + mount_tmpfs("root/dir1"); + + pid_t pid = fork(); + ATF_REQUIRE(pid != -1); + if (pid == 0) { + if (chdir("root/dir1") == -1) + abort(); + + atf_utils_create_file("dont-delete-me", "%s", ""); + atf_utils_create_file("../../done", "%s", ""); + + pause(); + exit(EXIT_SUCCESS); + } else { + fprintf(stderr, "Waiting for child to finish preparations\n"); + while (!atf_utils_file_exists("done")) {} + fprintf(stderr, "Child done; cleaning up\n"); + + ATF_REQUIRE(kyua_error_is_set(kyua_fs_cleanup("root"))); + ATF_REQUIRE(atf_utils_file_exists("root/dir1/dont-delete-me")); + + fprintf(stderr, "Killing child\n"); + ATF_REQUIRE(kill(pid, SIGKILL) != -1); + int status; + ATF_REQUIRE(waitpid(pid, &status, 0) != -1); + + ATF_REQUIRE(!kyua_error_is_set(kyua_fs_cleanup("root"))); + ATF_REQUIRE(!lookup(".", "root", DT_DIR)); + } +} + + +ATF_TC_WITHOUT_HEAD(concat__one); +ATF_TC_BODY(concat__one, tc) +{ + char* path; + ATF_REQUIRE(!kyua_error_is_set(kyua_fs_concat(&path, "foo", NULL))); + ATF_REQUIRE_STREQ("foo", path); + free(path); +} + + +ATF_TC_WITHOUT_HEAD(concat__two); +ATF_TC_BODY(concat__two, tc) +{ + char* path; + ATF_REQUIRE(!kyua_error_is_set(kyua_fs_concat(&path, "foo", "bar", NULL))); + ATF_REQUIRE_STREQ("foo/bar", path); + free(path); +} + + +ATF_TC_WITHOUT_HEAD(concat__several); +ATF_TC_BODY(concat__several, tc) +{ + char* path; + ATF_REQUIRE(!kyua_error_is_set(kyua_fs_concat(&path, "/usr", ".", "bin", + "ls", NULL))); + ATF_REQUIRE_STREQ("/usr/./bin/ls", path); + free(path); +} + + +ATF_TC_WITHOUT_HEAD(current_path__ok); +ATF_TC_BODY(current_path__ok, tc) +{ + char* previous; + ATF_REQUIRE(!kyua_error_is_set(kyua_fs_current_path(&previous))); + + ATF_REQUIRE(mkdir("root", 0755) != -1); + ATF_REQUIRE(chdir("root") != -1); + char* cwd; + ATF_REQUIRE(!kyua_error_is_set(kyua_fs_current_path(&cwd))); + + char* exp_cwd; + ATF_REQUIRE(!kyua_error_is_set(kyua_fs_concat(&exp_cwd, previous, "root", + NULL))); + ATF_REQUIRE_STREQ(exp_cwd, cwd); + + free(exp_cwd); + free(cwd); + free(previous); +} + + +ATF_TC_WITHOUT_HEAD(current_path__enoent); +ATF_TC_BODY(current_path__enoent, tc) +{ + char* previous; + ATF_REQUIRE(!kyua_error_is_set(kyua_fs_current_path(&previous))); + + ATF_REQUIRE(mkdir("root", 0755) != -1); + ATF_REQUIRE(chdir("root") != -1); + ATF_REQUIRE(rmdir("../root") != -1); + char* cwd = (char*)0xdeadbeef; + kyua_error_t error = kyua_fs_current_path(&cwd); + ATF_REQUIRE(kyua_error_is_set(error)); + ATF_REQUIRE(kyua_error_is_type(error, "libc")); + ATF_REQUIRE_EQ(ENOENT, kyua_libc_error_errno(error)); + ATF_REQUIRE_EQ((char*)0xdeadbeef, cwd); + kyua_error_free(error); + + free(previous); +} + + +ATF_TC_WITHOUT_HEAD(make_absolute__absolute); +ATF_TC_BODY(make_absolute__absolute, tc) +{ + char* absolute; + ATF_REQUIRE(!kyua_error_is_set(kyua_fs_make_absolute( + "/this/is/absolute", &absolute))); + ATF_REQUIRE_STREQ("/this/is/absolute", absolute); + free(absolute); +} + + +ATF_TC_WITHOUT_HEAD(make_absolute__relative); +ATF_TC_BODY(make_absolute__relative, tc) +{ + kyua_error_t error; + char* absolute; + + DIR* previous = opendir("."); + ATF_REQUIRE(previous != NULL); + ATF_REQUIRE(chdir("/usr") != -1); + error = kyua_fs_make_absolute("bin/foobar", &absolute); + const int previous_fd = dirfd(previous); + ATF_REQUIRE(fchdir(previous_fd) != -1); + close(previous_fd); + + ATF_REQUIRE(!kyua_error_is_set(error)); + ATF_REQUIRE_STREQ("/usr/bin/foobar", absolute); + free(absolute); +} + + +ATF_TC(unmount__ok); +ATF_TC_HEAD(unmount__ok, tc) +{ + atf_tc_set_md_var(tc, "require.user", "root"); +} +ATF_TC_BODY(unmount__ok, tc) +{ + ATF_REQUIRE(mkdir("mount_point", 0755) != -1); + + atf_utils_create_file("mount_point/test1", "%s", ""); + mount_tmpfs("mount_point"); + atf_utils_create_file("mount_point/test2", "%s", ""); + + ATF_REQUIRE(!atf_utils_file_exists("mount_point/test1")); + ATF_REQUIRE( atf_utils_file_exists("mount_point/test2")); + kyua_fs_unmount("mount_point"); + ATF_REQUIRE( atf_utils_file_exists("mount_point/test1")); + ATF_REQUIRE(!atf_utils_file_exists("mount_point/test2")); +} + + +ATF_TC(unmount__fail); +ATF_TC_HEAD(unmount__fail, tc) +{ + atf_tc_set_md_var(tc, "require.user", "root"); +} +ATF_TC_BODY(unmount__fail, tc) +{ + kyua_error_t error = kyua_fs_unmount("mount_point"); + ATF_REQUIRE(kyua_error_is_set(error)); + kyua_error_free(error); +} + + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, cleanup__file); + ATF_TP_ADD_TC(tp, cleanup__subdir__empty); + ATF_TP_ADD_TC(tp, cleanup__subdir__files_and_directories); + ATF_TP_ADD_TC(tp, cleanup__subdir__unprotect_regular); + ATF_TP_ADD_TC(tp, cleanup__subdir__unprotect_symlink); + ATF_TP_ADD_TC(tp, cleanup__subdir__links); + ATF_TP_ADD_TC(tp, cleanup__mount_point__simple); + ATF_TP_ADD_TC(tp, cleanup__mount_point__overlayed); + ATF_TP_ADD_TC(tp, cleanup__mount_point__nested); + ATF_TP_ADD_TC(tp, cleanup__mount_point__links); + ATF_TP_ADD_TC(tp, cleanup__mount_point__busy); + + ATF_TP_ADD_TC(tp, concat__one); + ATF_TP_ADD_TC(tp, concat__two); + ATF_TP_ADD_TC(tp, concat__several); + + ATF_TP_ADD_TC(tp, current_path__ok); + ATF_TP_ADD_TC(tp, current_path__enoent); + + ATF_TP_ADD_TC(tp, make_absolute__absolute); + ATF_TP_ADD_TC(tp, make_absolute__relative); + + ATF_TP_ADD_TC(tp, unmount__ok); + ATF_TP_ADD_TC(tp, unmount__fail); + + return atf_no_error(); +} diff --git a/external/bsd/kyua-testers/dist/kyua-atf-interface.7 b/external/bsd/kyua-testers/dist/kyua-atf-interface.7 new file mode 100644 index 000000000..acf541be8 --- /dev/null +++ b/external/bsd/kyua-testers/dist/kyua-atf-interface.7 @@ -0,0 +1,405 @@ +.\" Copyright 2012 Google Inc. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are +.\" met: +.\" +.\" * Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" * Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" * Neither the name of Google Inc. nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.Dd September 9, 2012 +.Dt KYUA-ATF-INTERFACE 1 +.Os +.Sh NAME +.Nm atf-interface +.Nd Description of the ATF test program interface +.Sh DESCRIPTION +The interface of ATF test programs is the interface of the test +programs linked to the +.Nm atf-c , +.Nm atf-c++ +and +.Nm atf-sh +libraries provided by ATF. +.Pp +The ATF interface can be understood as the mechanisms used by test programs +to communicate with the runtime engine as well as the assumptions that test +programs and test cases can make while running. +.Pp +A test case is the most basic part of a test suite. A test case is +supposed to reproduce one, and only one, scenario. For example: if the +item under test was a function, the test case would provide a single set of +input parameters to the function and check its output; If the item under +test was a binary, the test case would provide a single set of arguments to +the program and check its behavior. +.Ss Test case parts +Test cases have three parts: +.Bl -tag -width cleanupXX +.It Head +Programmatically defines metadata properties. The head must not perform +any other thing than defining such properties. In particular, no testing +whatsoever can happen in the head. (Ideally the definition of metadata +properties would not happen programmatically.) +.It Body +The actual test case which performs any desired testing and reports a +result. The body is executed by the runtime engine in a deterministic way; +see the isolation section below. +.It Cleanup +An optional cleanup routine. Note that the runtime engine will attempt to +clean up the work directory automatically, so this routine should only be +provided in cases where the test modifies system-wide state not known by +the runtime engine. The cleanup part is executed in the same directory as +the body. However, the body and the cleanup parts +.Em do not share the same process space ; +the only way to pass data around from the body to the cleanup is by means +of files in the work directory. +.El +.Ss Metadata properties +The following test case metadata properties must be exported in the test +case list for every test case: +.Bl -tag -width XX +.It Va ident +Single-word string. The name of the test case. Must be unique within the +test program. +.El +.Pp +The following test case metadata properties may be exported in the +test case list for every test case: +.Bl -tag -width XX +.It Va descr +Multi-word string. A textual description for the test case. Usually, +providing a descriptive identifier is better than providing a textual +description. +.It Va has.cleanup +Boolean. Whether the test case defines a cleanup routine or not. +.It Va require.arch +Whitespace separated list of the architectures required by the test case. +If defined, the test case is skipped unless the host architecture matches +any of the values defined in this property. +.It Va require.config +Whitespace separated list of configuration variable names. The list of +configuration variables that must be defined. The test is skipped if any +of these is missing. +.It Va require.files +Whitespace separated list of absolute paths to installed files. If any of +these files is not found, the test case is skipped. +.It Va require.machine +Whitespace separated list of the machine types required by the test case. +If defined, the test case is skipped unless the host machine type matches +any of the values defined in this property. +.It Va require.progs +Whitespace separated list of program names (either absolute names or base +names). If any of these programs is not found, the test case is skipped. +.It Va require.user +Either +.Sq root +or +.Sq unprivileged . +If +.Sq root , +the test case must be run as the superuser or otherwise it is skipped. If +.Sq unprivileged , +the test case must be run as an unprivileged user or else it is skipped. +.It Va timeout +Integer. The amount of seconds the test case can run for before it is +killed by the runtime engine. +.El +.Ss Configuration properties +The following properties may be defined by the runtime engine and are +propagated to the test cases: +.Bl -tag -width XX +.It Va unprivileged-user +String, optional. Specifies the name of the user under which tests that +set +.Sq require.user=unprivileged +are executed. +.El +.Ss Results +A test case must always report a result by creating the results file +specified through the +.Fl r +flag. For convenience when running test cases without the runtime engine, +this file may point to +.Pa /dev/stdout +or +.Pa /dev/stderr +in which case the file must not be created (because the creation will +fail). +.Pp +Aside from creating the results file, the process in which the test case +runs must terminate in particular ways for the test result to be considered +valid. +.Pp +If the test case fails to create the test result, if the test result is +created but contains an invalid syntax, or if the termination status of the +process does not match the requirements of the test result, the runtime +engine marks the test case as +.Sq broken . +Note that the +.Sq broken +state is decided by the runtime engine; a test case cannot report itself as +.Sq broken . +.Pp +The general syntax for the results file is as follows: +.Bd -literal -offset indent +[[(int)]: reason] +.Ed +.Pp +The following results are allowed: +.Bl -tag -width XX +.It expected_death +The process is expected to terminate either due to a clean call to +.Xr exit 3 +or due to the reception of a signal. The contents of the file are +.Sq expected_death: \\n . +Example: +.Sq expected_death: Calling libdofoo breaks due to bug xyz . +.It expected_exit +The process is expected to terminate cleanly. The contents of the file are +.Sq expected_exit: +if the exit code is irrelevant or +.Sq expected_exit(): +if the process must terminate with a given exit code. Examples: +.Sq expected_exit: Calling bar exits but it should not +or +.Sq expected_exit(123): Calling bar exits with an unexpected code . +.It expected_failure +The process must exit cleanly with an +.Va EXIT_SUCCESS +exit code. The contents of the file are +.Sq expected_failure: \\n +Example: +.Sq expected_failure: 2 + 2 = 3 . +.It expected_signal +The process is expected to terminate due to the reception of a signal. The +contents of the file are +.Sq expected_signal: +if the signal number is irrelevant or +.Sq expected_signal(): +if the process must terminate due to a particular signal. Examples: +.Sq expected_signal: Calling bar crashes +or +.Sq expected_signal(1): Calling bar kills ourselves due to unhandled SIGHUP . +.It expected_timeout +The process is expected to hang for longer than its +.Va timeout +metadata property. Only the runtime engine can control this situation +because the runtime engine is the one implementing the timeout +functionality. +.It failed +The process must exit cleanly with an +.Va EXIT_FAILURE +exit code. The contents of the file are +.Sq failed: \\n . +Example: +.Sq failed: Failed on purpose\\n . +.It passed +The process must exit cleanly with an +.Va EXIT_SUCCESS +exit code. The contents of the file are +.Sq passed\\n . +.It skipped +The process must exit cleanly with an +.Va EXIT_SUCCESS +exit code. The contents of the file are +.Sq skipped: \\n . +Example: +.Sq skipped: Skipped because the foo is not present\\n . +.El +.Ss Isolation +The runtime engine attempts to isolate test cases from other test cases in +the same test program and from the rest of the system by performing what is +called +.Em test case isolation . +.Pp +Whenever the user runs a test program binary by hand (i.e. not through +.Xr kyua 1 ) , +the test program will print a warning message stating that test case +isolation does not work and therefore the program may cause side-effects +and/or report invalid values. +.Pp +The runtime engine must set the +.Va __RUNNING_INSIDE_ATF_RUN +environment variable to the magic value +.Sq internal-yes-value +to tell the test programs that they are being run with isolation enabled. +.Pp +The test case isolation performs the following: +.Bl -tag -width XX +.It Process space +Each test case body and cleanup routines are executed in independent +processes. Corollary: the test case can do whatever it wants to the +current process (such as modifying global variables) without having to undo +such changes. +.It Process group +The test case body and cleanup are executed in their own process groups. +Should they spawn any children, such children should maintain the same +process group. This is done to allow the runtime engine to kill the whole +process subtree once the test case finishes (or if the test case hangs). +.It Work directory +The test case body and its cleanup (if any) are executed in a temporary +directory automatically created by the runtime engine. This temporary +directory is shared among the body and cleanup parts of a single test case +but is completely separate from the temporary directories of other tests. +Corollary: the test case body and cleanup routines can write to their +current directory without bothering to clean any files and/or directories +they create. The runtime engine takes care to recursively delete the +temporary directories after the execution of a test case. Any file systems +mounted within the temporary directory will be unmounted if possible. +.It Home directory +The +.Va HOME +environment variable is set to the absolute path of the work directory. +.It Umask +The value of the umask is set to 0022. +.It Environment +The +.Va LANG , +.Va LC_ALL , +.Va LC_COLLATE , +.Va LC_CTYPE , +.Va LC_MESSAGES , +.Va LC_MONETARY , +.Va LC_NUMERIC +and +.Va LC_TIME +variables are unset. The +.Va TZ +variable is set to +.Sq UTC . +.It Process limits +The maximum soft core size limit is raised to its corresponding hard limit. +This is a simple, best-effort attempt at allowing test cases to dump core +for further diagnostic purposes. +.El +.Ss Test programs +A test program is, simply put, a collection of related test cases. The +test program can be seen as a command-line dispatcher for the test cases. +A test program must provide one or more test cases. If it does not contain +any test case, the runtime system will report it as invalid. +.Pp +Test programs expose their list of test cases in a machine parseable +format. The runtime engine obtains the list of test cases to know what +tests to run and to know how to set up the environment of each test prior +execution. The test program must not do any test when asked to dump its +test case list. +.Pp +The generic syntax to obtain the list of test cases included in a test +program is: +.Bd -literal -offset indent + -l +.Ed +.Pp +The list of test cases follows the following format: +.Bd -literal -offset indent +LIST ::= HEADER NEWLINE TEST_CASES + +HEADER ::= 'Content-Type: application/X-atf-tp; version="1"' +NEWLINE ::= '\\n' +TEST_CASES ::= TEST_CASE | TEST_CASE NEWLINE TEST_CASES + +TEST_CASE ::= IDENT_PROPERTY PROPERTIES +IDENT_PROPERTY ::= 'ident' DELIM STRING NEWLINE +DELIM ::= ': ' + +PROPERTIES ::= PROPERTY | PROPERTY PROPERTIES +PROPERTY ::= PROPERTY_NAME DELIM STRING NEWLINE +PROPERTY_NAME ::= (see below) +.Ed +.Pp +An example: +.Bd -literal -offset indent +Content-Type: application/X-atf-tp; version="1" + +ident: addition +descr: Tests that the addition function works + +ident: subtraction +descr: Tests that the subtraction function works + +ident: remove +descr: Tests removing files +require.root: true +timeout: 50 +has.cleanup: true +.Ed +.Pp +The syntax to run a test case body part is: +.Bd -literal -offset indent + [-r resfile] [-s srcdir] [-v var=value]* [:body] +.Ed +.Pp +This must run the test case body +.Dq as is , +without any attempt of isolating it from the rest of the system. It is the +responsibility of the runtime engine to do such isolation. +.Pp +The runtime engine always passes the path of a nonexistent file to +.Fl r , +which must be created by the test case; and always passes an absolute path +to the +.Fl s +flag pointing to the directory containing the test program executable. +.Pp +The runtime engine shall pass any configuration variables it wants through +the +.Fl v +flag, and these can be later inspected by the test case at will. +.Pp +A note to users: if you run the test case by hand (not through +.Xr kyua 1 nor +.Xr atf-run 1 ) +from the command line, none of the isolation features described in the +isolation section apply. This means that the test case can (and probably +will) write to the current directory and leave garbage behind. Also, given +that the test case is executed without e.g. clearing the environment, the +results of the test case may differ from those obtained when running the +test case inside the runtime engine. +.Em Only use this for debugging purposes +(i.e. to run the test case code under GDB). +.Pp +The syntax to run a test case cleanup part is: +.Bd -literal -offset indent + [-s srcdir] [-v var=value]* :cleanup +.Ed +.Pp +This can only be performed if and only if the test case sets the +.Va has.cleanup +property to true. Otherwise the behavior of executing the cleanup part is +undefined. +.Pp +The same rules for +.Fl s +and +.Fl v +apply as to when running the body. +.Pp +The cleanup part must be executed in the same directory as the body but in +a separate process space. The only way for test cases to transfer state +(if any) from the body to the cleanup routine is by means of files in the +current directory. +.Pp +The cleanup part does not have to worry about deleting temporary files +created in the current directory. The runtime engine does this +automatically. +.Sh SEE ALSO +.Xr kyua-test 1 , +.Xr kyuafile 5 diff --git a/external/bsd/kyua-testers/dist/kyua-atf-tester.1.in b/external/bsd/kyua-testers/dist/kyua-atf-tester.1.in new file mode 100644 index 000000000..2c53edd09 --- /dev/null +++ b/external/bsd/kyua-testers/dist/kyua-atf-tester.1.in @@ -0,0 +1,133 @@ +.\" Copyright 2012 Google Inc. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are +.\" met: +.\" +.\" * Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" * Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" * Neither the name of Google Inc. nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.Dd December 26, 2012 +.Dt KYUA-ATF-TESTER 1 +.Os +.Sh NAME +.Nm kyua-atf-tester +.Nd Scriptable interface to interact with ATF test programs +.Sh SYNOPSIS +.Nm +.Op Ar generic_flags +.Ar subcommand +.Op Ar subcommand_flags +.Op Ar subcommand_args +.Sh DESCRIPTION +.Nm +provides a scriptable interface to interact with test programs that implement +the +.Xr kyua-atf-interface 7 +test interface. +This manual page describes the specific features that apply to this specific +tester. For the generic manual page, which describes the command-line interface +in detail, please see +.Xr kyua-tester 1 . +.Ss Results conversion +The result format outputted by +.Nm +(described in +.Xr kyua-tester-result 5 ) +is more restricted than what the ATF test case itself can output. The following +list details maps ATF test results to their generic results: +.Bl -tag -width expectedXfailureXX +.It expected_death +Maps to +.Sq expected_failure +if the death happens; +.Sq failed +otherwise. +.It expected_exit +Maps to +.Sq expected_failure +if the test exits cleanly; +.Sq failed +otherwise. +.It expected_failure +Maps to +.Sq expected_failure +if there is any failure during the execution; +.Sq failed +otherwise. +.It expected_signal +Maps to +.Sq expected_failure +if the test terminates due to a signal; +.Sq failed +otherwise. +.It expected_timeout +Maps to +.Sq expected_failure +if the test times out; +.Sq failed +otherwise. +.It failed +Maps to +.Sq failed . +.It passed +Maps to +.Sq passed . +.It skipped +Maps to +.Sq skipped . +.El +.Pp +Any of the previous test results +.Em can also map +to +.Sq broken +in those cases where there is an unexpected problem in the communcation between +the test and +.Nm . +For example, this will happen if result file created by the ATF test case does +not comply to what +.Xr kyua-atf-interface 7 +describes. +.Ss Cleanup routines +Because +.Nm +cannot keep any contextual information between the listing of test cases and +their execution, the tester cannot easily (aka cheaply) know whether a test has +or has not a cleanup routine when it is run. For this reason, the +.Sq test +subcommand of +.Nm +will assume, by default, that a test case +.Em does have +a cleanup routine. This postive assumption ensures that, if the tester is +incorrectly executed, the test will be properly cleaned up. +.Pp +However, as an optimization, the caller can pass +.Sq -v has_cleanup=false +to the +.Sq test +subcommand to tell +.Nm +that the test being run does not have a cleanup routine. +.Sh SEE ALSO +.Xr kyua-tester 1 , +.Xr kyua-atf-interface 7 diff --git a/external/bsd/kyua-testers/dist/kyua-plain-interface.7 b/external/bsd/kyua-testers/dist/kyua-plain-interface.7 new file mode 100644 index 000000000..e0b305902 --- /dev/null +++ b/external/bsd/kyua-testers/dist/kyua-plain-interface.7 @@ -0,0 +1,63 @@ +.\" Copyright 2012 Google Inc. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are +.\" met: +.\" +.\" * Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" * Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" * Neither the name of Google Inc. nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.Dd September 9, 2012 +.Dt KYUA-PLAIN-INTERFACE 1 +.Os +.Sh NAME +.Nm plain-interface +.Nd Description of the plain test program interface +.Sh DESCRIPTION +The +.Em plain test interface +is the interface of test programs that return their pass/fail status as an +exit code. While simple, this interface is what legacy test programs use +and what test programs written with many other testing libraries use too. +.Pp +Kyua supports this interface for two main reasons: first, to simplify the +incorporation of legacy test programs into a Kyua test suite; and, second, +to ensure that the Kyua run-time engine does not become tied to a +particular test interface. +.Pp +The results of a plain test are one of the following: +.Bl -tag -width passedXX +.It passed +If the test program exits with a success exit code; i.e. 0. +.It failed +If the test program exits with a failure exit code; i.e. not 0. +.It broken +If the test program exits due to any other reason (e.g. it crashes) or +if it fails to be executed. +.El +.Pp +Plain test programs are executed with the same isolation features as +ATF test programs; see +.Xr kyua-atf-interface 7 . +.Sh SEE ALSO +.Xr kyua-test 1 , +.Xr kyuafile 5 , +.Xr kyua-atf-interface 7 diff --git a/external/bsd/kyua-testers/dist/kyua-plain-tester.1.in b/external/bsd/kyua-testers/dist/kyua-plain-tester.1.in new file mode 100644 index 000000000..cab74b372 --- /dev/null +++ b/external/bsd/kyua-testers/dist/kyua-plain-tester.1.in @@ -0,0 +1,60 @@ +.\" Copyright 2012 Google Inc. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are +.\" met: +.\" +.\" * Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" * Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" * Neither the name of Google Inc. nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.Dd December 26, 2012 +.Dt KYUA-PLAIN-TESTER 1 +.Os +.Sh NAME +.Nm kyua-plain-tester +.Nd Scriptable interface to interact with plain test programs +.Sh SYNOPSIS +.Nm +.Op Ar generic_flags +.Ar subcommand +.Op Ar subcommand_flags +.Op Ar subcommand_args +.Sh DESCRIPTION +.Nm +provides a scriptable interface to interact with test programs that implement +the +.Xr kyua-plain-interface 7 +test interface. +This manual page describes the specific features that apply to this specific +tester. For the generic manual page, which describes the command-line interface +in detail, please see +.Xr kyua-tester 1 . +.Ss Test cases list +A test program that follows the plain interface can only have a single test +case. Due to this, the output of the +.Sq list +subcommand of +.Nm +will always result in one single test case. This test case represents the whole +test program. +.Sh SEE ALSO +.Xr kyua-tester 1 , +.Xr kyua-plain-interface 7 diff --git a/external/bsd/kyua-testers/dist/kyua-tester-list.5 b/external/bsd/kyua-testers/dist/kyua-tester-list.5 new file mode 100644 index 000000000..4057bb290 --- /dev/null +++ b/external/bsd/kyua-testers/dist/kyua-tester-list.5 @@ -0,0 +1,103 @@ +.\" Copyright 2012 Google Inc. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are +.\" met: +.\" +.\" * Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" * Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" * Neither the name of Google Inc. nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.Dd December 26, 2012 +.Dt KYUA-TESTER-LIST 5 +.Os +.Sh NAME +.Nm kyua-tester-list +.Nd The test cases list printed by the Kyua testers +.Sh SYNOPSIS +.Fn test_case properties_table +.Sh DESCRIPTION +The +.Sq list +subcommand of the various Kyua testers outputs the list of tests cases within a +given test program. The format of the list of test cases is a Lua script in +which every line invokes the +.Fn test_case +function to define a test case. The +.Xr kyua 1 +runtime engine reads this list in order to determine what tests can be run. +.Pp +The +.Fn test_case +function takes a table as its only argument, and the table contains the +definition of the metadata properties of the test case. A typical invocation of +this function looks like this: +.Bd -literal -indent +test_case{name='THE-NAME', ...} +.Ed +.Pp +Where +.Sq ... +denote optional metadata values attached to the test case. The supported +metadata properties are the following: +.Bl -tag -width allowedXarchitecturesXX +.It allowed_architectures +Whitespace-separated list of machine architecture names allowed by the test +case. If empty or not defined, the test case is allowed to run on any machine +architecture. +.It allowed_platforms +Whitespace-separated list of machine platform names allowed by the test case. +If empty or not defined, the test case is allowed to run on any machine +platform. +.It description +Textual description of the test case. +.It has_cleanup +If +.Sq true , +denotes that the test case has a cleanup routine. +.It required_configs +Whitespace-separated list of configuration variables that the test case requires +to be defined before it can run. +.It required_files +Whitespace-separated list of paths that the test case requires to exist before +it can run. +.It required_memory +Amount of physical memory that the test case needs to run successfully. +.It required_programs +Whitespace-separated list of basenames or absolute paths pointing to executable +binaries that the test case requires to exist before it can run. +.It required_user +If empty, the test case has no restrictions on the calling user for it to run. +If set to +.Sq unprivileged , +the test case needs to not run as root. +If set to +.Sq root , +the test case must run as root. +.It timeout +Amount of seconds that the test case is allowed to execute before being killed. +.It X-NAME +Custom variable defined by the test case, where +.Sq NAME +denotes the name of the variable. +.El +.Sh SEE ALSO +.Xr kyua-atf-tester 1 , +.Xr kyua-plain-tester 1 diff --git a/external/bsd/kyua-testers/dist/kyua-tester-result.5 b/external/bsd/kyua-testers/dist/kyua-tester-result.5 new file mode 100644 index 000000000..e8cf76257 --- /dev/null +++ b/external/bsd/kyua-testers/dist/kyua-tester-result.5 @@ -0,0 +1,66 @@ +.\" Copyright 2012 Google Inc. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are +.\" met: +.\" +.\" * Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" * Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" * Neither the name of Google Inc. nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.Dd December 26, 2012 +.Dt KYUA-TESTER-RESULT 1 +.Os +.Sh NAME +.Nm kyua-tester-result +.Nd Result files created by the Kyua testers +.Sh SYNOPSIS +.Bd -literal +result_type[: result_reason] +.Ed +.Sh DESCRIPTION +The +.Sq test +subcommand of the various Kyua testers creates a file describing the result of +the execution of a single test case. +.Pp +The result file contains the type of the result and, optionally, a textual +description explaining what caused the given result. The description is +separated from the type by a colon-space character pair. +.Pp +The result type may be any of the following: +.Bl -tag -width expectedXfailureXX +.It broken +The test case did not follow the conventions of the test interface correctly and +therefore it is considered to be broken. This includes a test case timing out. +.It expected_failure +The test case raised an error but such error was expected. The tester will +repor the test as passed. +.It failed +The test case raised an error. +.It passed +The test case passed successfully. +.It skipped +The test case was not executed because some preconditions were not met. This is +considered as a successful result. +.El +.Sh SEE ALSO +.Xr kyua-atf-tester 1 , +.Xr kyua-plain-tester 1 diff --git a/external/bsd/kyua-testers/dist/kyua-tester.1.in b/external/bsd/kyua-testers/dist/kyua-tester.1.in new file mode 100644 index 000000000..9565ef8be --- /dev/null +++ b/external/bsd/kyua-testers/dist/kyua-tester.1.in @@ -0,0 +1,205 @@ +.\" Copyright 2012 Google Inc. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions are +.\" met: +.\" +.\" * Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" * Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" * Neither the name of Google Inc. nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +.\" OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.Dd December 26, 2012 +.Dt KYUA-TESTER 1 +.Os +.Sh NAME +.Nm kyua-tester +.Nd Scriptable interface to interact with test programs +.Sh SYNOPSIS +.Nm +.Op Fl g Ar gid +.Op Fl t Ar timeout +.Op Fl u Ar uid +.Ar list +.Ar test_program +.Nm +.Op Fl g Ar gid +.Op Fl t Ar timeout +.Op Fl u Ar uid +.Ar test +.Op Fl v Ar var=value +.Ar test_program +.Ar test_case +.Ar result_file +.Sh DESCRIPTION +This generic manual page does +.Em not +correspond to any specific binary. It describes the generic command-line +interface provided by all Kyua testers shipped by the +.Sq __PACKAGE__ +package, which all have names of the form +.Nm kyua-INTERFACE-NAME-tester . +.Pp +The main goal of a +.Nm +is to provide a scriptable interface to run +.Em a single test case +of +.Em a single test program +in a generic manner. The specific implementation of how to do this is up to the +tester, as each +.Nm +binary implements a specific test interface. The following binaries are shipped +with the +.Sq __PACKAGE__ +package: +.Bl -tag -width XXXX +.It Xr kyua-atf-tester 1 +An implementation of +.Nm +that wraps tests that follow the +.Xr kyua-atf-interface 7 +interface. +.It Xr kyua-plain-tester 1 +An implementation of +.Nm +that wraps tests that follow the +.Xr kyua-plain-interface 7 +interface. +.El +.Pp +.Xr kyua 1 +uses the various +.Nm +binaries to execute tests that implement diverse interfaces, without having to +know about any of its specifics. It is possible for other packages to provide +new testers that implement other interfaces as long as the tester's command line +complies to what is described in this manual page. +.Pp +A +.Nm +implements a typical command-line interface based on subcommands. The tool +takes a set of generic options first, a subcommand name, a set of any options +accepted by such subcommand, and a set of arguments to the subcommand. +.Pp +The following options apply to all subcommands: +.Bl -tag -width XtXtimeoutXX +.It Fl g Ar gid +GID of the user to switch to before running the test case. Defaults to the +current GID. +.It Fl t Ar timeout +Seconds to allow the test program to run before killing it. Defaults to 60. +.It Fl u Ar uid +UID of the user to switch to before running the test case. Defaults to the +current UID. +.El +.Pp +Killing the tester should always be a safe operation, resulting in the +subsequent termination of the test program being run and the cleanup of any used +resources. +.Ss Workflow +The way +.Xr kyua 1 +uses the testers to interact with individual test cases is the following: +.Bl -enum +.It +For every test program listed in a +.Xr kyuafile 5 , +execute the +.Sq list +subcommand of the +.Nm +that matches the interface name in the test program description. +.It +.Xr kyua 1 +collects the test cases returned in the previous step and checks if they are +runnable according to their metadata. +.It +For every test case collected from the previous steps, execute the +.Sq test +subcommand of the same +.Nm +used in the test case listing. +.It +Reinterpret the generic test result and record it as necessary. +.El +.Ss The list subcommand +The +.Sq list +subcommand extracts the list of test cases that are part of the given test +program in a machine-parseable format. The test program should be provided as +an absolute pathname. +.Pp +The format of the output is described in +.Xr kyua-tester-list 5 . +.Ss The test subcommand +The +.Sq test +subcommand executes a single test case of a test program in a controlled manner, +which means that it is placed in its own subprocess and its own work directory +so that side-effects during execution are minimized. +.Pp +If the test is executed successfully, the +.Ar result_file +is created following the format described in +.Xr kyua-tester-result 5 . +.Pp +If the test crashes halfway through and dumps core, +.Nm +will attempt to gather a stacktrace and print it as part of the test's output. +.Pp +The following options are specific to the test command: +.Bl -tag -width XvXvar=nameXX +.It Fl v Ar var=name +Passes a configuration variable to the test case. +.El +.Pp +The following configuration variables have special meaning: +.Bl -tag -width unprivilegedXuserXX +.It unprivileged-user +The name (not UID) of an unprivileged user that the test can use for its own +purposes. +.El +.Sh ENVIRONMENT +The following variables are recognized and can be freely tuned by the end user: +.Bl -tag -width TMPDIRXX +.It Va TMPDIR +Path to the system-wide temporary directory. +.Nm +uses this location to place the work directory of test cases. +.Pp +The default value is +.Pa __TMPDIR__ . +.El +.Sh EXIT STATUS +.Nm +returns the following exit codes: +.Bl -tag -compact -width 0XX +.It 0 +The tester ran correctly and the test passed. +.It 1 +The tester ran correctly, but the test failed. +.It 2 +The tester failed. The result of the test itself is irrelevant. +.It 3 +The user invoked the tester incorrectly. +.El +.Sh SEE ALSO +.Xr kyua-atf-tester 1 , +.Xr kyua-plain-tester 1 diff --git a/external/bsd/kyua-testers/dist/kyua-testers.pc.in b/external/bsd/kyua-testers/dist/kyua-testers.pc.in new file mode 100644 index 000000000..533ddc67f --- /dev/null +++ b/external/bsd/kyua-testers/dist/kyua-testers.pc.in @@ -0,0 +1,5 @@ +testersdir=__LIBEXECDIR__ + +Name: kyua-testers +Description: Kyua - Testers +Version: __VERSION__ diff --git a/external/bsd/kyua-testers/dist/plain_helpers.c b/external/bsd/kyua-testers/dist/plain_helpers.c new file mode 100644 index 000000000..7d33cf43b --- /dev/null +++ b/external/bsd/kyua-testers/dist/plain_helpers.c @@ -0,0 +1,110 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include +#include +#include +#include +#include + +#include "defs.h" + + +/// Exit code to report internal, unexpected errors. +static const int EXIT_BOGUS = 123; + + +/// Test case that always fails. +static int +fail_helper(void) +{ + fprintf(stdout, "First line to stdout\n"); + fprintf(stderr, "First line to stderr\n"); + return 78; +} + + +/// Test case that always passes. +static int +pass_helper(void) +{ + fprintf(stdout, "First line to stdout\n"); + fprintf(stdout, "Second line to stdout\n"); + fprintf(stderr, "First line to stderr\n"); + fprintf(stderr, "Second line to stderr\n"); + return EXIT_SUCCESS; +} + + +/// Test case that always dies due to a signal and dumps core. +static int +signal_helper(void) +{ + fprintf(stderr, "About to die due to SIGABRT!\n"); + abort(); +} + + +/// Test case that sleeps for a long time. +static int +sleep_helper(void) +{ + sleep(300); + return EXIT_FAILURE; +} + + +/// Dispatcher for individual testers based on the HELPER environment variable. +/// +/// \param argc Number of arguments to the command. +/// \param unused_argv Arguments to the command. +/// +/// \return An exit code. +int +main(const int argc, char* const* const KYUA_DEFS_UNUSED_PARAM(argv)) +{ + if (argc != 1) + errx(EXIT_BOGUS, "No arguments allowed"); + + const char* helper_name = getenv("HELPER"); + if (helper_name == NULL) { + errx(EXIT_BOGUS, "Must set HELPER to the name of the desired helper"); + } + + if (strcmp(helper_name, "fail") == 0) { + return fail_helper(); + } else if (strcmp(helper_name, "pass") == 0) { + return pass_helper(); + } else if (strcmp(helper_name, "signal") == 0) { + return signal_helper(); + } else if (strcmp(helper_name, "sleep") == 0) { + return sleep_helper(); + } else { + errx(EXIT_BOGUS, "Unknown helper '%s'", helper_name); + } +} diff --git a/external/bsd/kyua-testers/dist/plain_inttest.c b/external/bsd/kyua-testers/dist/plain_inttest.c new file mode 100644 index 000000000..3dfb2f657 --- /dev/null +++ b/external/bsd/kyua-testers/dist/plain_inttest.c @@ -0,0 +1,179 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include + +#include + +#define INTERFACE "plain" +#include "common_inttest.h" + + +/// Sets up a particular helper. +/// +/// \param tc The test case calling this function. +/// \param helper_name Name of the desired helper. +/// +/// \return The return value of helpers_path(). +static char* +select_helper(const atf_tc_t* tc, const char* helper_name) +{ + ATF_REQUIRE(setenv("HELPER", helper_name, 1) != -1); + return helpers_path(tc); +} + + +ATF_TC(list__ok); +ATF_TC_HEAD(list__ok, tc) { setup(tc, false); } +ATF_TC_BODY(list__ok, tc) +{ + check(EXIT_SUCCESS, "test_case{name='main'}\n", "", + "list", "irrelevant-program", NULL); +} + + +ATF_TC(test__pass); +ATF_TC_HEAD(test__pass, tc) { setup(tc, true); } +ATF_TC_BODY(test__pass, tc) +{ + char* helpers = select_helper(tc, "pass"); + check(EXIT_SUCCESS, + "First line to stdout\nSecond line to stdout\n", + "First line to stderr\nSecond line to stderr\n", + "test", helpers, "main", "test-result", NULL); + free(helpers); + + ATF_REQUIRE(atf_utils_compare_file("test-result", "passed\n")); +} + + +ATF_TC(test__fail); +ATF_TC_HEAD(test__fail, tc) { setup(tc, true); } +ATF_TC_BODY(test__fail, tc) +{ + char* helpers = select_helper(tc, "fail"); + check(EXIT_FAILURE, "First line to stdout\n", "First line to stderr\n", + "test", helpers, "main", "test-result", NULL); + free(helpers); + + ATF_REQUIRE(atf_utils_compare_file("test-result", + "failed: Returned non-success exit status 78\n")); +} + + +ATF_TC(test__crash); +ATF_TC_HEAD(test__crash, tc) { setup(tc, true); } +ATF_TC_BODY(test__crash, tc) +{ + char* helpers = select_helper(tc, "signal"); + check(EXIT_FAILURE, "", "save:crash.err", + "test", helpers, "main", "test-result", NULL); + free(helpers); + + ATF_REQUIRE(atf_utils_compare_file("test-result", + "broken: Received signal 6\n")); + + ATF_REQUIRE(atf_utils_grep_file("About to die due to SIGABRT!", + "crash.err")); + ATF_REQUIRE(atf_utils_grep_file("attempting to gather stack trace", + "crash.err")); +} + + +ATF_TC(test__timeout); +ATF_TC_HEAD(test__timeout, tc) { setup(tc, true); } +ATF_TC_BODY(test__timeout, tc) +{ + char* helpers = select_helper(tc, "sleep"); + check(EXIT_FAILURE, "", "Subprocess timed out; sending KILL signal...\n", + "-t1", "test", helpers, "main", "test-result", NULL); + free(helpers); + + ATF_REQUIRE(atf_utils_compare_file("test-result", "broken: Test case " + "timed out\n")); +} + + +ATF_TC(test__config_ignored); +ATF_TC_HEAD(test__config_ignored, tc) { setup(tc, true); } +ATF_TC_BODY(test__config_ignored, tc) +{ + char* helpers = select_helper(tc, "pass"); + check(EXIT_SUCCESS, + "First line to stdout\nSecond line to stdout\n", + "save:stderr.txt", + "test", "-va=b", "-vfoo=a b c", helpers, "main", "test-result", NULL); + free(helpers); + + ATF_REQUIRE(atf_utils_grep_file("ignoring 'a=b'", "stderr.txt")); + ATF_REQUIRE(atf_utils_grep_file("ignoring 'foo=a b c'", "stderr.txt")); + ATF_REQUIRE(atf_utils_compare_file("test-result", "passed\n")); +} + + +ATF_TC(test__missing_test_program); +ATF_TC_HEAD(test__missing_test_program, tc) { setup(tc, false); } +ATF_TC_BODY(test__missing_test_program, tc) +{ + check(EXIT_INTERNAL_ERROR, "", + "kyua-plain-tester: execvp failed: No such file or directory\n", + "test", "./non-existent", "main", "test-result", NULL); + + ATF_REQUIRE(!atf_utils_file_exists("test-result")); +} + + +ATF_TC(test__invalid_test_case_name); +ATF_TC_HEAD(test__invalid_test_case_name, tc) { setup(tc, false); } +ATF_TC_BODY(test__invalid_test_case_name, tc) +{ + check(EXIT_INTERNAL_ERROR, "", + "kyua-plain-tester: Unknown test case 'foo'\n", + "test", "./non-existent", "foo", "test-result", NULL); + + ATF_REQUIRE(!atf_utils_file_exists("test-result")); +} + + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, top__missing_command); + ATF_TP_ADD_TC(tp, top__unknown_command); + + ATF_TP_ADD_TC(tp, list__ok); + + ATF_TP_ADD_TC(tp, test__pass); + ATF_TP_ADD_TC(tp, test__fail); + ATF_TP_ADD_TC(tp, test__crash); + ATF_TP_ADD_TC(tp, test__timeout); + ATF_TP_ADD_TC(tp, test__config_ignored); + ATF_TP_ADD_TC(tp, test__missing_test_program); + ATF_TP_ADD_TC(tp, test__invalid_test_case_name); + + return atf_no_error(); +} diff --git a/external/bsd/kyua-testers/dist/plain_main.c b/external/bsd/kyua-testers/dist/plain_main.c new file mode 100644 index 000000000..4ad42cd29 --- /dev/null +++ b/external/bsd/kyua-testers/dist/plain_main.c @@ -0,0 +1,200 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include + +#include +#include +#include +#include +#include + +#include "cli.h" +#include "defs.h" +#include "error.h" +#include "result.h" +#include "run.h" +#include "stacktrace.h" + +#if !defined(WCOREDUMP) && defined(__minix) +#define WCOREDUMP(x) ((x) & 0x80) +#endif /*!defined(WCOREDUMP) && defined(__minix) */ + + +/// Template for the creation of the temporary work directories. +#define WORKDIR_TEMPLATE "kyua.plain-tester.XXXXXX" + + +/// Name of the fake test case exposed by the program. +const char* const fake_test_case_name = "main"; + + +/// Converts the exit status of a program to a result. +/// +/// \param status Exit status of the test program, as returned by waitpid(). +/// \param timed_out Whether the test program timed out or not. +/// \param result_file Path to the result file to create. +/// \param [out] success Set to true if the test program returned with a +/// successful condition. +/// +/// \return An error if something went wrong. +static kyua_error_t +status_to_result(int status, const bool timed_out, const char* result_file, + bool* success) +{ + if (timed_out) { + *success = false; + return kyua_result_write(result_file, KYUA_RESULT_BROKEN, + "Test case timed out"); + } + + if (WIFEXITED(status)) { + if (WEXITSTATUS(status) == EXIT_SUCCESS) { + *success = true; + return kyua_result_write(result_file, KYUA_RESULT_PASSED, NULL); + } else { + *success = false; + return kyua_result_write(result_file, KYUA_RESULT_FAILED, + "Returned non-success exit status %d", + WEXITSTATUS(status)); + } + } else { + assert(WIFSIGNALED(status)); + *success = false; + return kyua_result_write(result_file, KYUA_RESULT_BROKEN, + "Received signal %d", WTERMSIG(status)); + } +} + + +/// Lists the test cases in a test program. +/// +/// \param unused_test_program Path to the test program for which to list the +/// test cases. Should be absolute. +/// \param unused_run_params Execution parameters to configure the test process. +/// +/// \return An error if the listing fails; OK otherwise. +static kyua_error_t +list_test_cases(const char* KYUA_DEFS_UNUSED_PARAM(test_program), + const kyua_run_params_t* KYUA_DEFS_UNUSED_PARAM(run_params)) +{ + printf("test_case{name='%s'}\n", fake_test_case_name); + return kyua_error_ok(); +} + + +/// Runs a single test cases of a test program. +/// +/// \param test_program Path to the test program for which to list the test +/// cases. Should be absolute. +/// \param test_case Name of the test case to run. +/// \param result_file Path to the file to which to write the result of the +/// test. Should be absolute. +/// \param user_variables Array of name=value pairs that describe the user +/// configuration variables for the test case. +/// \param run_params Execution parameters to configure the test process. +/// \param [out] success Set to true if the test case reported a valid exit +/// condition (like "passed" or "skipped"); false otherwise. This is +/// only updated if the method returns OK. +/// +/// \return An error if the listing fails; OK otherwise. +static kyua_error_t +run_test_case(const char* test_program, const char* test_case, + const char* result_file, const char* const user_variables[], + const kyua_run_params_t* run_params, + bool* success) +{ + kyua_error_t error; + + if (strcmp(test_case, fake_test_case_name) != 0) { + error = kyua_generic_error_new("Unknown test case '%s'", test_case); + goto out; + } + + const char* const* iter; + for (iter = user_variables; *iter != NULL; ++iter) { + warnx("Configuration variables not supported; ignoring '%s'", *iter); + } + + char *work_directory; + error = kyua_run_work_directory_enter(WORKDIR_TEMPLATE, + run_params->unprivileged_user, + run_params->unprivileged_group, + &work_directory); + if (kyua_error_is_set(error)) + goto out; + kyua_run_params_t real_run_params = *run_params; + real_run_params.work_directory = work_directory; + + pid_t pid; + error = kyua_run_fork(&real_run_params, &pid); + if (!kyua_error_is_set(error) && pid == 0) { + const char* const program_args[] = { test_program, NULL }; + kyua_run_exec(test_program, program_args); + } + assert(pid != -1 && pid != 0); + if (kyua_error_is_set(error)) + goto out_work_directory; + + int status; bool timed_out; + error = kyua_run_wait(pid, &status, &timed_out); + if (kyua_error_is_set(error)) + goto out_work_directory; + + if (WIFSIGNALED(status) && WCOREDUMP(status)) { + kyua_stacktrace_dump(test_program, pid, run_params, stderr); + } + + error = status_to_result(status, timed_out, result_file, success); + +out_work_directory: + error = kyua_error_subsume(error, + kyua_run_work_directory_leave(&work_directory)); +out: + return error; +} + + +/// Definition of the tester. +static kyua_cli_tester_t plain_tester = { + .list_test_cases = list_test_cases, + .run_test_case = run_test_case, +}; + + +/// Tester entry point. +/// +/// \param argc Number of command line arguments. +/// \param argv NULL-terminated array of command line arguments. +/// +/// \return An exit code. +int +main(const int argc, char* const* const argv) +{ + return kyua_cli_main(argc, argv, &plain_tester); +} diff --git a/external/bsd/kyua-testers/dist/result.c b/external/bsd/kyua-testers/dist/result.c new file mode 100644 index 000000000..dfcc53685 --- /dev/null +++ b/external/bsd/kyua-testers/dist/result.c @@ -0,0 +1,81 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "result.h" + +#include +#include +#include +#include + +#include "error.h" + + +/// Mapping of kyua_result_type_t values to their textual representation. +static const char* type_to_name[] = { + "passed", // KYUA_RESULT_PASSED + "failed", // KYUA_RESULT_FAILED + "broken", // KYUA_RESULT_BROKEN + "skipped", // KYUA_RESULT_SKIPPED + "expected_failure", // KYUA_RESULT_EXPECTED_FAILURE +}; + + +/// Creates a file with the result of the test. +/// +/// \param path Path to the file to be created. +/// \param type The type of the result. +/// \param reason Textual explanation of the reason behind the result. Must be +/// NULL with KYUA_RESULT_PASSED, or else non-NULL. +/// +/// \return An error object. +kyua_error_t +kyua_result_write(const char* path, const enum kyua_result_type_t type, + const char* reason, ...) +{ + assert(type == KYUA_RESULT_PASSED || reason != NULL); + assert(reason == NULL || type != KYUA_RESULT_PASSED); + + FILE* file = fopen(path, "w"); + if (file == NULL) + return kyua_libc_error_new(errno, "Cannot create result file '%s'", + path); + if (reason != NULL) { + char buffer[1024]; + va_list ap; + va_start(ap, reason); + (void)vsnprintf(buffer, sizeof(buffer), reason, ap); + va_end(ap); + fprintf(file, "%s: %s\n", type_to_name[type], buffer); + } else { + fprintf(file, "%s\n", type_to_name[type]); + } + fclose(file); + + return kyua_error_ok(); +} diff --git a/external/bsd/kyua-testers/dist/result.h b/external/bsd/kyua-testers/dist/result.h new file mode 100644 index 000000000..08305d772 --- /dev/null +++ b/external/bsd/kyua-testers/dist/result.h @@ -0,0 +1,53 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file result.h +/// Utilities to create test result files. + +#if !defined(KYUA_RESULT_H) +#define KYUA_RESULT_H + +#include "defs.h" +#include "error_fwd.h" + + +/// Enumeration of the different result types. +enum kyua_result_type_t { + KYUA_RESULT_PASSED = 0, + KYUA_RESULT_FAILED, + KYUA_RESULT_BROKEN, + KYUA_RESULT_SKIPPED, + KYUA_RESULT_EXPECTED_FAILURE, +}; + + +kyua_error_t kyua_result_write(const char*, const enum kyua_result_type_t, + const char*, ...) KYUA_DEFS_FORMAT_PRINTF(3, 4); + + +#endif // !defined(KYUA_RESULT_H) diff --git a/external/bsd/kyua-testers/dist/result_test.c b/external/bsd/kyua-testers/dist/result_test.c new file mode 100644 index 000000000..fe91ef0d5 --- /dev/null +++ b/external/bsd/kyua-testers/dist/result_test.c @@ -0,0 +1,119 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "result.h" + +#include + +#include + +#include "error.h" + + +ATF_TC_WITHOUT_HEAD(write__passed); +ATF_TC_BODY(write__passed, tc) +{ + const kyua_error_t error = kyua_result_write( + "test.txt", KYUA_RESULT_PASSED, NULL); + ATF_REQUIRE(!kyua_error_is_set(error)); + ATF_REQUIRE(atf_utils_compare_file("test.txt", "passed\n")); +} + + +ATF_TC_WITHOUT_HEAD(write__failed); +ATF_TC_BODY(write__failed, tc) +{ + const kyua_error_t error = kyua_result_write( + "test.txt", KYUA_RESULT_FAILED, "Some message"); + ATF_REQUIRE(!kyua_error_is_set(error)); + ATF_REQUIRE(atf_utils_compare_file("test.txt", "failed: Some message\n")); +} + + +ATF_TC_WITHOUT_HEAD(write__broken); +ATF_TC_BODY(write__broken, tc) +{ + const kyua_error_t error = kyua_result_write( + "test.txt", KYUA_RESULT_BROKEN, "Some message"); + ATF_REQUIRE(!kyua_error_is_set(error)); + ATF_REQUIRE(atf_utils_compare_file("test.txt", "broken: Some message\n")); +} + + +ATF_TC_WITHOUT_HEAD(write__skipped); +ATF_TC_BODY(write__skipped, tc) +{ + const kyua_error_t error = kyua_result_write( + "test.txt", KYUA_RESULT_SKIPPED, "Some message"); + ATF_REQUIRE(!kyua_error_is_set(error)); + ATF_REQUIRE(atf_utils_compare_file("test.txt", "skipped: Some message\n")); +} + + +ATF_TC_WITHOUT_HEAD(write__expected_failure); +ATF_TC_BODY(write__expected_failure, tc) +{ + const kyua_error_t error = kyua_result_write( + "test.txt", KYUA_RESULT_EXPECTED_FAILURE, "Some message"); + ATF_REQUIRE(!kyua_error_is_set(error)); + ATF_REQUIRE(atf_utils_compare_file("test.txt", "expected_failure: " + "Some message\n")); +} + + +ATF_TC(write__open_error); +ATF_TC_HEAD(write__open_error, tc) +{ + atf_tc_set_md_var(tc, "require.user", "unprivileged"); +} +ATF_TC_BODY(write__open_error, tc) +{ + ATF_REQUIRE(mkdir("readonly", 0555) != -1); + const kyua_error_t error = kyua_result_write( + "readonly/test.txt", KYUA_RESULT_FAILED, "Some message"); + ATF_REQUIRE(kyua_error_is_set(error)); + ATF_REQUIRE(kyua_error_is_type(error, "libc")); + char buffer[512]; + kyua_error_format(error, buffer, sizeof(buffer)); + ATF_REQUIRE(atf_utils_grep_string( + "Cannot create result file 'readonly/test.txt'", buffer)); + kyua_error_free(error); +} + + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, write__passed); + ATF_TP_ADD_TC(tp, write__failed); + ATF_TP_ADD_TC(tp, write__skipped); + ATF_TP_ADD_TC(tp, write__broken); + ATF_TP_ADD_TC(tp, write__expected_failure); + ATF_TP_ADD_TC(tp, write__open_error); + + return atf_no_error(); +} diff --git a/external/bsd/kyua-testers/dist/run.c b/external/bsd/kyua-testers/dist/run.c new file mode 100644 index 000000000..4ed1e048b --- /dev/null +++ b/external/bsd/kyua-testers/dist/run.c @@ -0,0 +1,598 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#if defined(HAVE_CONFIG_H) +# include "config.h" +#endif + +#include "run.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "defs.h" +#include "env.h" +#include "error.h" +#include "fs.h" +#include "text.h" + + +/// Path to the temporary work directory to use. +const char* kyua_run_tmpdir = KYUA_TMPDIR; +#undef KYUA_TMPDIR // We really want to use the variable, not the macro. + + +/// Whether we got a signal or not. +static volatile bool signal_fired = false; + + +/// Whether the process timed out or not. +static volatile bool process_timed_out = false; + + +/// If not -1, PID of the process to forcibly kill when we get a signal. +/// +/// Must be protected by protect() and unprotect(). +static volatile pid_t pid_to_kill = -1; + + +/// Whether we are holding signals or not. +static bool protected = false; + + +/// Magic exit code to denote an error while preparing the subprocess. +static const int exit_setup_child = 124; +/// Magic exit code to denote an error in exec(3) that we do not handle. +static const int exit_exec_unknown = 123; +/// Magic exit code to denote an EACCES error in exec(3). +static const int exit_exec_eacces = 122; +/// Magic exit code to denote an ENOENT error in exec(3). +static const int exit_exec_enoent = 121; + + +/// Area to save the original SIGHUP handler. +static struct sigaction old_sighup; +/// Area to save the original SIGINT handler. +static struct sigaction old_sigint; +/// Area to save the original SIGTERM handler. +static struct sigaction old_sigterm; +/// Area to save the original SIGALRM handler. +static struct sigaction old_sigalrm; +/// Area to save the original realtime timer. +static struct itimerval old_timer; + + +/// Masks or unmasks all the signals programmed by this module. +/// +/// \param operation One of SIG_BLOCK or SIG_UNBLOCK. +static void +mask_handlers(const int operation) +{ + sigset_t mask; + sigemptyset(&mask); + sigaddset(&mask, SIGALRM); + sigaddset(&mask, SIGINT); + sigaddset(&mask, SIGHUP); + sigaddset(&mask, SIGTERM); + const int ret = sigprocmask(operation, &mask, NULL); + assert(ret != -1); +} + + +/// Masks all signals programmed by this module. +static void +protect(void) +{ + mask_handlers(SIG_BLOCK); + protected = true; +} + + +/// Unmasks all signals programmed by this module. +static void +unprotect(void) +{ + protected = false; + mask_handlers(SIG_UNBLOCK); +} + + +/// Handler for signals that should abort execution. +/// +/// When called the first time, this handler kills any running subprocess so +/// that the cleanup routines can proceed. Calling this a second time aborts +/// execution of the program. +/// +/// \param unused_signo Number of the captured signal. +static void +cleanup_handler(const int KYUA_DEFS_UNUSED_PARAM(signo)) +{ + static const char* clean_message = "Signal caught; cleaning up...\n"; + static const char* abort_message = "Double signal caught; aborting...\n"; + + protect(); + if (!signal_fired) { + signal_fired = true; + if (write(STDERR_FILENO, clean_message, strlen(clean_message)) == -1) { + // Ignore. + } + if (pid_to_kill != -1) { + kill(pid_to_kill, SIGKILL); + pid_to_kill = -1; + } + unprotect(); + } else { + if (write(STDERR_FILENO, abort_message, strlen(abort_message)) == -1) { + // Ignore. + } + if (pid_to_kill != -1) { + kill(pid_to_kill, SIGKILL); + pid_to_kill = -1; + } + abort(); + } +} + + +/// Handler for signals that should terminate the active subprocess. +/// +/// \param unused_signo Number of the captured signal. +static void +timeout_handler(const int KYUA_DEFS_UNUSED_PARAM(signo)) +{ + static const char* message = "Subprocess timed out; sending KILL " + "signal...\n"; + + protect(); + process_timed_out = true; + if (write(STDERR_FILENO, message, strlen(message)) == -1) { + // Ignore. + } + if (pid_to_kill != -1) { + kill(pid_to_kill, SIGKILL); + pid_to_kill = -1; + } + unprotect(); +} + + +/// Installs a signal handler. +/// +/// \param signo Number of the signal to program. +/// \param handler Handler for the signal. +/// \param [out] old_sa Pointer to the sigaction structure in which to save the +/// current signal handler data. +static void +setup_signal(const int signo, void (*handler)(const int), + struct sigaction* old_sa) +{ + struct sigaction sa; + sa.sa_handler = handler; + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_RESTART; + + const int ret = sigaction(signo, &sa, old_sa); + assert(ret != -1); +} + + +/// Installs a timer. +/// +/// \param seconds Deadline for the timer. +/// \param [out] old_itimerval Pointer to the itimerval structure in which to +/// save the current timer data into. +static void +setup_timer(const int seconds, struct itimerval* old_itimerval) +{ + struct itimerval new_timer; + new_timer.it_interval.tv_sec = 0; + new_timer.it_interval.tv_usec = 0; + new_timer.it_value.tv_sec = seconds; + new_timer.it_value.tv_usec = 0; + const int ret = setitimer(ITIMER_REAL, &new_timer, old_itimerval); + assert(ret != -1); +} + + +/// Resets the environment of the process to a known state. +/// +/// \param work_directory Path to the work directory being used. +/// +/// \return An error if there is a problem configuring the environment +/// variables, or OK if successful. Note that if this returns an error, we have +/// left the environment in an inconsistent state. +static kyua_error_t +prepare_environment(const char* work_directory) +{ + kyua_error_t error; + + // TODO(jmmv): It might be better to do the opposite: just pass a good known + // set of variables to the child (aka HOME, PATH, ...). But how do we + // determine this minimum set? + + const char* to_unset[] = { "LANG", "LC_ALL", "LC_COLLATE", "LC_CTYPE", + "LC_MESSAGES", "LC_MONETARY", "LC_NUMERIC", + "LC_TIME", NULL }; + const char** iter; + for (iter = to_unset; *iter != NULL; ++iter) { + error = kyua_env_unset(*iter); + if (kyua_error_is_set(error)) + return error; + } + + error = kyua_env_set("HOME", work_directory); + if (kyua_error_is_set(error)) + return error; + + error = kyua_env_set("TZ", "UTC"); + if (kyua_error_is_set(error)) + return error; + + error = kyua_env_set("__RUNNING_INSIDE_ATF_RUN", "internal-yes-value"); + if (kyua_error_is_set(error)) + return error; + + assert(!kyua_error_is_set(error)); + return error; +} + + +/// Resets all signals to their default handlers. +static void +reset_signals(void) +{ + int signo; + + for (signo = 1; signo <= LAST_SIGNO; ++signo) { + if (signo == SIGKILL || signo == SIGSTOP) { + // Don't attempt to reset immutable signals. + continue; + } + + struct sigaction sa; + sa.sa_handler = SIG_DFL; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + (void)sigaction(signo, &sa, NULL); + } +} + + +/// Raises core size limit to its possible maximum. +/// +/// This is a best-effort operation. There is no guarantee that the operation +/// will yield a large-enough limit to generate any possible core file. +static void +unlimit_core_size(void) +{ +#if !defined(__minix) + struct rlimit rl; + { + const int ret = getrlimit(RLIMIT_CORE, &rl); + assert(ret != -1); + } + rl.rlim_cur = rl.rlim_max; + const int ret = setrlimit(RLIMIT_CORE, &rl) != -1; + assert(ret != -1); +#endif /* !defined(__minix) */ +} + + +/// Cleans up the container process to run a new child. +/// +/// If there is any error during the setup, the new process is terminated +/// with an error code. +/// +/// \param run_params End-user parameters that describe how to isolate the +/// newly-created process. +static void +setup_child(const kyua_run_params_t* run_params) +{ +#if !defined(__minix) + setpgid(getpid(), getpid()); +#endif /* !defined(__minix) */ + + if (chdir(run_params->work_directory) == -1) + err(exit_setup_child, "chdir(%s) failed", run_params->work_directory); + + unlimit_core_size(); + reset_signals(); + + const kyua_error_t error = prepare_environment(run_params->work_directory); + if (kyua_error_is_set(error)) + kyua_error_err(exit_setup_child, error, "Failed to configure the " + "environment"); + + (void)umask(0022); + + if (run_params->unprivileged_group != getgid()) { + if (setgid(run_params->unprivileged_group) == -1) + err(exit_setup_child, "setgid(%ld) failed; uid is %ld and gid " + "is %ld", (long int)run_params->unprivileged_group, + (long int)getuid(), (long int)getgid()); + } + if (run_params->unprivileged_user != getuid()) { + if (setuid(run_params->unprivileged_user) == -1) + err(exit_setup_child, "setuid(%ld) failed; uid is %ld and gid " + "is %ld", (long int)run_params->unprivileged_user, + (long int)getuid(), (long int)getgid()); + } +} + + +/// Constructs a path to a work directory based on a template. +/// +/// \param template Template of the work directory to create. Should be a +/// basename and must include the XXXXXX placeholder string. The directory +/// is created within the temporary directory specified by the TMPDIR +/// environment variable or the builtin value in kyua_run_tmpdir. +/// \param [out] work_directory Pointer to a dynamically-allocated string +/// containing the full path to the work directory. The caller is +/// responsible for releasing this string. +/// +/// \return An error if there is a problem (most likely OOM), or OK otherwise. +static kyua_error_t +build_work_directory_path(const char* template, char** work_directory) +{ + assert(strstr(template, "XXXXXX") != NULL); + + const char* tmpdir = getenv("TMPDIR"); + if (tmpdir == NULL) + return kyua_text_printf(work_directory, "%s/%s", kyua_run_tmpdir, + template); + else + return kyua_text_printf(work_directory, "%s/%s", tmpdir, template); +} + + +/// Initializes the run_params parameters with default values. +/// +/// \param [out] run_params The object to initialize. +void +kyua_run_params_init(kyua_run_params_t* run_params) +{ + run_params->timeout_seconds = 60; + run_params->unprivileged_user = getuid(); + run_params->unprivileged_group = getgid(); + run_params->work_directory = "."; +} + + +/// Executes a program and exits if there is a problem. +/// +/// This routine is supposed to be used in conjunction with kyua_run_fork and +/// kyua_run_wait so that the various return codes of the exec system call are +/// properly propagated to the parent process. +/// +/// \param program Path to the program to run. +/// \param args Arguments to the program. +void +kyua_run_exec(const char* program, const char* const* args) +{ + (void)execvp(program, KYUA_DEFS_UNCONST(args)); + switch (errno) { + case EACCES: + exit(exit_exec_eacces); + case ENOENT: + exit(exit_exec_enoent); + default: + err(exit_exec_unknown, "execvp failed"); + } +} + + +/// Forks and isolates the child process. +/// +/// The created subprocess must be waited for with kyua_run_wait(). +/// +/// \param run_params Parameters that describe how to isolate the newly-created +/// process. +/// \param [out] out_pid The PID of the child in the parent, or 0 in the child. +/// The value left here should only be accessed if this function does not +/// return an error. +/// +/// \return An error object if fork(2) fails. +kyua_error_t +kyua_run_fork(const kyua_run_params_t* run_params, pid_t* const out_pid) +{ + protect(); + pid_t pid = fork(); + if (pid == -1) { + unprotect(); + *out_pid = pid; // Not necessary, but avoid mistakes in the caller. + return kyua_libc_error_new(errno, "fork failed"); + } else if (pid == 0) { + unprotect(); + setup_child(run_params); + *out_pid = pid; + return kyua_error_ok(); + } else { + pid_to_kill = pid; + unprotect(); + + setup_signal(SIGALRM, timeout_handler, &old_sigalrm); + process_timed_out = false; + setup_timer(run_params->timeout_seconds, &old_timer); + + *out_pid = pid; + return kyua_error_ok(); + } +} + + +/// Waits for a process started via kyua_run_fork. +/// +/// \param pid The PID of the child to wait for. +/// \param [out] status The exit status of the awaited process. +/// \param [out] timed_out Whether the process timed out or not. +/// +/// \return An error if the process failed due to an problem in kyua_run_exec. +/// However, note that the wait for the process itself is expected to have been +/// successful. +kyua_error_t +kyua_run_wait(const pid_t pid, int* status, bool* timed_out) +{ + int tmp_status; + const pid_t waited_pid = waitpid(pid, &tmp_status, 0); + assert(pid == waited_pid); + + protect(); + (void)setitimer(ITIMER_REAL, &old_timer, NULL); + (void)sigaction(SIGALRM, &old_sigalrm, NULL); + pid_to_kill = -1; + unprotect(); + + killpg(pid, SIGKILL); + + if (WIFEXITED(tmp_status)) { + if (WEXITSTATUS(tmp_status) == exit_setup_child) { + return kyua_generic_error_new("Failed to isolate subprocess; " + "see stderr for details"); + } else if (WEXITSTATUS(tmp_status) == exit_exec_eacces) { + return kyua_libc_error_new(EACCES, "execvp failed"); + } else if (WEXITSTATUS(tmp_status) == exit_exec_enoent) { + return kyua_libc_error_new(ENOENT, "execvp failed"); + } else if (WEXITSTATUS(tmp_status) == exit_exec_unknown) { + return kyua_generic_error_new("execvp failed; see stderr for " + "details"); + } else { + // Fall-through. + } + } + *status = tmp_status; + *timed_out = process_timed_out; + return kyua_error_ok(); +} + + +/// Creates a temporary directory for use by a subprocess. +/// +/// The temporary directory must be deleted with kyua_run_work_directory_leave. +/// +/// \param template Template of the work directory to create. Should be a +/// basename and must include the XXXXXX placeholder string. The directory +/// is created within the temporary directory specified by the TMPDIR +/// environment variable or the builtin value. +/// \param uid User to set the owner of the directory to. +/// \param gid Group to set the owner of the directory to. +/// \param [out] out_work_directory Updated with a pointer to a dynamic string +/// holding the path to the created work directory. This must be passed as +/// is to kyua_run_work_directory_leave, which takes care of freeing the +/// memory. +/// +/// \return An error code if there is a problem creating the directory. +kyua_error_t +kyua_run_work_directory_enter(const char* template, const uid_t uid, + const gid_t gid, char** out_work_directory) +{ + kyua_error_t error = kyua_error_ok(); + + signal_fired = false; + setup_signal(SIGHUP, cleanup_handler, &old_sighup); + setup_signal(SIGINT, cleanup_handler, &old_sigint); + setup_signal(SIGTERM, cleanup_handler, &old_sigterm); + + char* work_directory; + error = build_work_directory_path(template, &work_directory); + if (kyua_error_is_set(error)) + goto err_signals; + + if (mkdtemp(work_directory) == NULL) { + error = kyua_libc_error_new(errno, "mkdtemp(%s) failed", + work_directory); + goto err_work_directory_variable; + } + + if (uid != getuid() || gid != getgid()) { + if (chown(work_directory, uid, gid) == -1) { + error = kyua_libc_error_new(errno, + "chown(%s, %ld, %ld) failed; uid is %ld and gid is %ld", + work_directory, (long int)uid, (long int)gid, + (long int)getuid(), (long int)getgid()); + goto err_work_directory_file; + } + } + + *out_work_directory = work_directory; + assert(!kyua_error_is_set(error)); + goto out; + +err_work_directory_file: + (void)rmdir(work_directory); +err_work_directory_variable: + free(work_directory); +err_signals: + (void)sigaction(SIGTERM, &old_sigterm, NULL); + (void)sigaction(SIGINT, &old_sigint, NULL); + (void)sigaction(SIGHUP, &old_sighup, NULL); +out: + return error; +} + + +/// Deletes a temporary directory created by kyua_run_work_directory_enter(). +/// +/// \param [in,out] work_directory The pointer to the work_directory string as +/// originally returned by kyua_run_work_directory_leave(). This is +/// explicitly invalidated by this function to clearly denote that this +/// performs the memory releasing. +/// +/// \return An error code if the cleanup of the directory fails. Note that any +/// intermediate errors during the cleanup are sent to stderr. +kyua_error_t +kyua_run_work_directory_leave(char** work_directory) +{ + kyua_error_t error = kyua_fs_cleanup(*work_directory); + + free(*work_directory); + *work_directory = NULL; + + (void)sigaction(SIGTERM, &old_sigterm, NULL); + (void)sigaction(SIGHUP, &old_sighup, NULL); + (void)sigaction(SIGINT, &old_sigint, NULL); + + // At this point, we have cleaned up the work directory and we could + // (should?) re-deliver the signal to ourselves so that we terminated with + // the right code. However, we just let this return and allow the caller + // code to perform any other cleanups instead. + + return error; +} diff --git a/external/bsd/kyua-testers/dist/run.h b/external/bsd/kyua-testers/dist/run.h new file mode 100644 index 000000000..0bd0272cc --- /dev/null +++ b/external/bsd/kyua-testers/dist/run.h @@ -0,0 +1,85 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file run.h +/// Structures and functions to run a program in an isolated manner. +/// +/// Pretty much all the functions of this module (ab)use global variables to +/// store their state. This means that they are not reentrant, but this is by +/// design: the whole point of implementing standalone testers is to simplify +/// the writing of this code by being able to make such assumptions. + +#if !defined(KYUA_RUN_H) +#define KYUA_RUN_H + +#include +#include + +#include "defs.h" +#include "error_fwd.h" +#include "run_fwd.h" + + +extern const char* kyua_run_tmpdir; + + +/// Parameters that indicate how to isolate a subprocess. +/// +/// In the name of simplicity, the fields of this structure can be considered +/// public. +struct kyua_run_params { + /// Execution deadline for the subprocess. + unsigned long timeout_seconds; + + /// Work directory for the subprocess to use. + const char* work_directory; + + /// UID of the user to switch to before running the subprocess. + uid_t unprivileged_user; + + /// GID of the group to switch to before running the subprocess. + gid_t unprivileged_group; +}; + + +void kyua_run_params_init(kyua_run_params_t*); + + +void kyua_run_exec(const char*, const char* const*) KYUA_DEFS_NORETURN; + + +kyua_error_t kyua_run_fork(const kyua_run_params_t*, pid_t* const); +kyua_error_t kyua_run_wait(const pid_t, int*, bool*); + + +kyua_error_t kyua_run_work_directory_enter(const char*, const uid_t, + const gid_t, char**); +kyua_error_t kyua_run_work_directory_leave(char**); + + +#endif // !defined(KYUA_RUN_H) diff --git a/external/bsd/kyua-testers/dist/run_fwd.h b/external/bsd/kyua-testers/dist/run_fwd.h new file mode 100644 index 000000000..bddbab4e8 --- /dev/null +++ b/external/bsd/kyua-testers/dist/run_fwd.h @@ -0,0 +1,43 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file run_fwd.h +/// Forward declarations for the run.h header. + +#if !defined(KYUA_RUN_FWD_H) +#define KYUA_RUN_FWD_H + + +struct kyua_run_params; + + +/// Shorthand for a kyua_run_params structure. +typedef struct kyua_run_params kyua_run_params_t; + + +#endif // !defined(KYUA_RUN_FWD_H) diff --git a/external/bsd/kyua-testers/dist/run_test.c b/external/bsd/kyua-testers/dist/run_test.c new file mode 100644 index 000000000..26ca8ef70 --- /dev/null +++ b/external/bsd/kyua-testers/dist/run_test.c @@ -0,0 +1,801 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#if defined(HAVE_CONFIG_H) +# include "config.h" +#endif + +#include "run.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "defs.h" +#include "env.h" +#include "error.h" +#include "fs.h" + +#if !defined(WCOREDUMP) && defined(__minix) +#define WCOREDUMP(x) ((x) & 0x80) +#endif /*!defined(WCOREDUMP) && defined(__minix) */ + + +/// Evalutes an expression and ensures it does not return an error. +/// +/// \param expr A expression that must evaluate to kyua_error_t. +#define RE(expr) ATF_REQUIRE(!kyua_error_is_set(expr)) + + +static void check_env(const void* KYUA_DEFS_UNUSED_PARAM(cookie)) + KYUA_DEFS_NORETURN; + + +/// Subprocess that validates the cleanliness of the environment. +/// +/// \param unused_cookie NULL. +/// +/// \post Exits with success if the environment is clean; failure otherwise. +static void +check_env(const void* KYUA_DEFS_UNUSED_PARAM(cookie)) +{ + bool failed = false; + + const char* empty[] = { "LANG", "LC_ALL", "LC_COLLATE", "LC_CTYPE", + "LC_MESSAGES", "LC_MONETARY", "LC_NUMERIC", + "LC_TIME", NULL }; + const char** iter; + for (iter = empty; *iter != NULL; ++iter) { + if (getenv(*iter) != NULL) { + failed = true; + printf("%s was not unset\n", *iter); + } + } + + if (strcmp(getenv("HOME"), ".") != 0) { + failed = true; + printf("HOME was not set to .\n"); + } + if (strcmp(getenv("TZ"), "UTC") != 0) { + failed = true; + printf("TZ was not set to UTC\n"); + } + if (strcmp(getenv("LEAVE_ME_ALONE"), "kill-some-day") != 0) { + failed = true; + printf("LEAVE_ME_ALONE was modified while it should not have been\n"); + } + + exit(failed ? EXIT_FAILURE : EXIT_SUCCESS); +} + + +static void check_process_group(const void* KYUA_DEFS_UNUSED_PARAM(cookie)) + KYUA_DEFS_NORETURN; + + +/// Subprocess that validates that it has become the leader of a process group. +/// +/// \param unused_cookie NULL. +/// +/// \post Exits with success if the process lives in its own process group; +/// failure otherwise. +static void +check_process_group(const void* KYUA_DEFS_UNUSED_PARAM(cookie)) +{ +#if defined(__minix) + // no pgid support on MINIX + exit(EXIT_FAILURE); +#else + exit(getpgid(getpid()) == getpid() ? EXIT_SUCCESS : EXIT_FAILURE); +#endif /* defined(__minix) */ +} + + +static void check_signals(const void* KYUA_DEFS_UNUSED_PARAM(cookie)) + KYUA_DEFS_NORETURN; + + +/// Subprocess that validates that signals have been reset to their defaults. +/// +/// \param unused_cookie NULL. +/// +/// \post Exits with success if the process has its signals reset to their +/// default values; failure otherwise. +static void +check_signals(const void* KYUA_DEFS_UNUSED_PARAM(cookie)) +{ + int signo; + for (signo = 1; signo <= LAST_SIGNO; signo++) { + if (signo == SIGKILL || signo == SIGSTOP) { + // Don't attempt to check immutable signals, as this results in + // an unconditional error in some systems. E.g. Mac OS X 10.8 + // reports 'Invalid argument' when querying SIGKILL. + continue; + } + + struct sigaction old_sa; + if (sigaction(signo, NULL, &old_sa) == -1) { + err(EXIT_FAILURE, "Failed to query signal information for %d", + signo); + } + if (old_sa.sa_handler != SIG_DFL) { + errx(EXIT_FAILURE, "Signal %d not reset to its default handler", + signo); + } + printf("Signal %d has its default handler set\n", signo); + } + + exit(EXIT_SUCCESS); +} + + +static void check_umask(const void* KYUA_DEFS_UNUSED_PARAM(cookie)) + KYUA_DEFS_NORETURN; + + +/// Subprocess that validates that the umask has been reset. +/// +/// \param unused_cookie NULL. +/// +/// \post Exits with success if the umask matches the expected value; failure +/// otherwise. +static void +check_umask(const void* KYUA_DEFS_UNUSED_PARAM(cookie)) +{ + exit(umask(0) == 0022 ? EXIT_SUCCESS : EXIT_FAILURE); +} + + +static void check_work_directory(const void* cookie) KYUA_DEFS_NORETURN; + + +/// Subprocess that validates that the umask has been reset. +/// +/// \param cookie The name of a file to expect in the current directory. +/// +/// \post Exits with success if the umask matches the expected value; failure +/// otherwise. +static void +check_work_directory(const void* cookie) +{ + const char* exp_file = (const char*)cookie; + exit(atf_utils_file_exists(exp_file) ? EXIT_SUCCESS : EXIT_FAILURE); +} + + +static void check_uid_not_root(const void* KYUA_DEFS_UNUSED_PARAM(cookie)) + KYUA_DEFS_NORETURN; + + +/// Subprocess that validates that the UID is not root. +/// +/// \param unused_cookie NULL. +/// +/// \post Exits with success if the UID is not root; failure otherwise. +static void +check_uid_not_root(const void* KYUA_DEFS_UNUSED_PARAM(cookie)) +{ + exit(getuid() != 0 ? EXIT_SUCCESS : EXIT_FAILURE); +} + + +static void check_gid_not_root(const void* KYUA_DEFS_UNUSED_PARAM(cookie)) + KYUA_DEFS_NORETURN; + + +/// Subprocess that validates that the GID is not root. +/// +/// \param unused_cookie NULL. +/// +/// \post Exits with success if the GID is not root; failure otherwise. +static void +check_gid_not_root(const void* KYUA_DEFS_UNUSED_PARAM(cookie)) +{ + exit(getgid() != 0 ? EXIT_SUCCESS : EXIT_FAILURE); +} + + +static void check_not_root(const void* KYUA_DEFS_UNUSED_PARAM(cookie)) + KYUA_DEFS_NORETURN; + + +/// Subprocess that validates that the UID and GID are not root. +/// +/// \param unused_cookie NULL. +/// +/// \post Exits with success if the UID and GID are not root; failure otherwise. +static void +check_not_root(const void* KYUA_DEFS_UNUSED_PARAM(cookie)) +{ + exit(getuid() != 0 && getgid() != 0 ? EXIT_SUCCESS : EXIT_FAILURE); +} + + +/// Uses kyua_fork, kyua_exec and kyua_wait to execute a subprocess. +/// +/// \param program Path to the program to run. +/// \param args Arguments to the program. +/// \param [out] exitstatus The exit status of the subprocess, if it exits +/// successfully without timing out nor receiving a signal. +/// +/// \return Returns the error code of kyua_run_wait (which should have the +/// error representation of the exec call in the subprocess). +static kyua_error_t +exec_check(const char* program, const char* const* args, int* exitstatus) +{ + kyua_run_params_t run_params; + kyua_run_params_init(&run_params); + + pid_t pid; + kyua_error_t error = kyua_run_fork(&run_params, &pid); + if (!kyua_error_is_set(error) && pid == 0) + kyua_run_exec(program, args); + ATF_REQUIRE(!kyua_error_is_set(error)); + int status; bool timed_out; + error = kyua_run_wait(pid, &status, &timed_out); + if (!kyua_error_is_set(error)) { + ATF_REQUIRE(!timed_out); + ATF_REQUIRE_MSG(WIFEXITED(status), + "Subprocess expected to exit successfully"); + *exitstatus = WEXITSTATUS(status); + } + return error; +} + + +/// Uses kyua_fork and kyua_wait to spawn a subprocess. +/// +/// \param run_params The parameters to configure the subprocess. Can be NULL +/// to indicate to use the default set of parameters. +/// \param hook Any of the check_* functions provided in this module. +/// \param cookie The data to pass to the hook. +/// +/// \return True if the subprocess exits successfully; false otherwise. +static bool +fork_check(const kyua_run_params_t* run_params, + void (*hook)(const void*), const void* cookie) +{ + kyua_run_params_t default_run_params; + if (run_params == NULL) { + kyua_run_params_init(&default_run_params); + run_params = &default_run_params; + } + + pid_t pid; + kyua_error_t error = kyua_run_fork(run_params, &pid); + if (!kyua_error_is_set(error) && pid == 0) + hook(cookie); + ATF_REQUIRE(!kyua_error_is_set(error)); + int status; bool timed_out; + error = kyua_run_wait(pid, &status, &timed_out); + if (kyua_error_is_set(error)) + atf_tc_fail("wait failed; unexpected problem during exec?"); + ATF_REQUIRE(!timed_out); + return WIFEXITED(status) && WEXITSTATUS(status) == EXIT_SUCCESS; +} + + +ATF_TC_WITHOUT_HEAD(run_params_init__defaults); +ATF_TC_BODY(run_params_init__defaults, tc) +{ + kyua_run_params_t run_params; + kyua_run_params_init(&run_params); + + ATF_REQUIRE_EQ(60, run_params.timeout_seconds); + ATF_REQUIRE_EQ(getuid(), run_params.unprivileged_user); + ATF_REQUIRE_EQ(getgid(), run_params.unprivileged_group); + ATF_REQUIRE_STREQ(".", run_params.work_directory); +} + + +ATF_TC_WITHOUT_HEAD(fork_exec_wait__ok); +ATF_TC_BODY(fork_exec_wait__ok, tc) +{ + const char* const args[] = {"sh", "-c", "exit 42", NULL}; + int exitstatus = -1; // Shut up GCC warning. + const kyua_error_t error = exec_check("/bin/sh", args, &exitstatus); + ATF_REQUIRE(!kyua_error_is_set(error)); + ATF_REQUIRE_EQ(42, exitstatus); +} + + +ATF_TC(fork_exec_wait__eacces); +ATF_TC_HEAD(fork_exec_wait__eacces, tc) +{ + atf_tc_set_md_var(tc, "require.user", "unprivileged"); +} +ATF_TC_BODY(fork_exec_wait__eacces, tc) +{ + ATF_REQUIRE(mkdir("dir", 0000) != -1); + + const char* const args[] = {"foo", NULL}; + int unused_exitstatus; + const kyua_error_t error = exec_check("./dir/foo", args, + &unused_exitstatus); + ATF_REQUIRE(kyua_error_is_set(error)); + ATF_REQUIRE(kyua_error_is_type(error, "libc")); + ATF_REQUIRE_EQ(EACCES, kyua_libc_error_errno(error)); +} + + +ATF_TC_WITHOUT_HEAD(fork_exec_wait__enoent); +ATF_TC_BODY(fork_exec_wait__enoent, tc) +{ + const char* const args[] = {"foo", NULL}; + int unused_exitstatus; + const kyua_error_t error = exec_check("./foo", args, &unused_exitstatus); + ATF_REQUIRE(kyua_error_is_set(error)); + ATF_REQUIRE(kyua_error_is_type(error, "libc")); + ATF_REQUIRE_EQ(ENOENT, kyua_libc_error_errno(error)); +} + + +ATF_TC_WITHOUT_HEAD(fork_wait__core_size); +ATF_TC_BODY(fork_wait__core_size, tc) +{ +#if !defined(__minix) + struct rlimit rl; + rl.rlim_cur = 0; + rl.rlim_max = RLIM_INFINITY; + if (setrlimit(RLIMIT_CORE, &rl) == -1) + atf_tc_skip("Failed to lower the core size limit"); +#endif /* !defined(__minix) */ + + kyua_run_params_t run_params; + kyua_run_params_init(&run_params); + + pid_t pid; + kyua_error_t error = kyua_run_fork(&run_params, &pid); + if (!kyua_error_is_set(error) && pid == 0) + abort(); + + ATF_REQUIRE(!kyua_error_is_set(error)); + int status; bool timed_out; + error = kyua_run_wait(pid, &status, &timed_out); + if (kyua_error_is_set(error)) + atf_tc_fail("wait failed; unexpected problem during exec?"); + + ATF_REQUIRE(!timed_out); + ATF_REQUIRE(WIFSIGNALED(status)); + ATF_REQUIRE_MSG(WCOREDUMP(status), "Core not dumped as expected"); +} + + +ATF_TC_WITHOUT_HEAD(fork_wait__env); +ATF_TC_BODY(fork_wait__env, tc) +{ + kyua_env_set("HOME", "/non-existent/directory"); + kyua_env_set("LANG", "C"); + kyua_env_set("LC_ALL", "C"); + kyua_env_set("LC_COLLATE", "C"); + kyua_env_set("LC_CTYPE", "C"); + kyua_env_set("LC_MESSAGES", "C"); + kyua_env_set("LC_MONETARY", "C"); + kyua_env_set("LC_NUMERIC", "C"); + kyua_env_set("LC_TIME", "C"); + kyua_env_set("LEAVE_ME_ALONE", "kill-some-day"); + kyua_env_set("TZ", "EST+5"); + + ATF_REQUIRE_MSG(fork_check(NULL, check_env, NULL), + "Unclean environment in subprocess"); +} + + +ATF_TC_WITHOUT_HEAD(fork_wait__process_group); +ATF_TC_BODY(fork_wait__process_group, tc) +{ + ATF_REQUIRE_MSG(fork_check(NULL, check_process_group, NULL), + "Subprocess not in its own process group"); +} + + +ATF_TC_WITHOUT_HEAD(fork_wait__signals); +ATF_TC_BODY(fork_wait__signals, tc) +{ + ATF_REQUIRE_MSG(LAST_SIGNO > 10, "LAST_SIGNO as detected by configure is " + "suspiciously low"); + + int signo; + for (signo = 1; signo <= LAST_SIGNO; signo++) { + if (signo == SIGKILL || signo == SIGSTOP) { + // Ignore immutable signals. + continue; + } + if (signo == SIGCHLD) { + // If we were to reset SIGCHLD to SIG_IGN (which is different than + // not touching the signal at all, leaving it at its default value), + // our child process will not become a zombie and the call to + // kyua_run_wait will fail. Avoid this. + continue; + } + + struct sigaction sa; + sa.sa_handler = SIG_IGN; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + printf("Ignoring signal %d\n", signo); + ATF_REQUIRE(sigaction(signo, &sa, NULL) != -1); + } + + ATF_REQUIRE_MSG(fork_check(NULL, check_signals, NULL), + "Signals not reset to their default state"); +} + + +ATF_TC_WITHOUT_HEAD(fork_wait__timeout); +ATF_TC_BODY(fork_wait__timeout, tc) +{ + kyua_run_params_t run_params; + kyua_run_params_init(&run_params); + run_params.timeout_seconds = 1; + + pid_t pid; + kyua_error_t error = kyua_run_fork(&run_params, &pid); + if (!kyua_error_is_set(error) && pid == 0) { + sigset_t mask; + sigemptyset(&mask); + for (;;) + sigsuspend(&mask); + } + ATF_REQUIRE(!kyua_error_is_set(error)); + int status; bool timed_out; + kyua_run_wait(pid, &status, &timed_out); + ATF_REQUIRE(timed_out); + ATF_REQUIRE(WIFSIGNALED(status)); + ATF_REQUIRE_EQ(SIGKILL, WTERMSIG(status)); +} + + +ATF_TC_WITHOUT_HEAD(fork_wait__umask); +ATF_TC_BODY(fork_wait__umask, tc) +{ + (void)umask(0222); + ATF_REQUIRE_MSG(fork_check(NULL, check_umask, NULL), + "Subprocess does not have the predetermined 0022 umask"); +} + + +ATF_TC(fork_wait__unprivileged_user); +ATF_TC_HEAD(fork_wait__unprivileged_user, tc) +{ + atf_tc_set_md_var(tc, "require.config", "unprivileged-user"); + atf_tc_set_md_var(tc, "require.user", "root"); +} +ATF_TC_BODY(fork_wait__unprivileged_user, tc) +{ + const struct passwd* pw = getpwnam(atf_tc_get_config_var( + tc, "unprivileged-user")); + ATF_REQUIRE_MSG(pw != NULL, "Cannot find unprivileged user"); + + kyua_run_params_t run_params; + kyua_run_params_init(&run_params); + run_params.unprivileged_user = pw->pw_uid; + + ATF_REQUIRE_MSG(fork_check(&run_params, check_uid_not_root, NULL), + "Subprocess is still running with UID set to root"); +} + + +ATF_TC(fork_wait__unprivileged_group); +ATF_TC_HEAD(fork_wait__unprivileged_group, tc) +{ + atf_tc_set_md_var(tc, "require.config", "unprivileged-user"); + atf_tc_set_md_var(tc, "require.user", "root"); +} +ATF_TC_BODY(fork_wait__unprivileged_group, tc) +{ + const struct passwd* pw = getpwnam(atf_tc_get_config_var( + tc, "unprivileged-user")); + ATF_REQUIRE_MSG(pw != NULL, "Cannot find unprivileged user"); + + kyua_run_params_t run_params; + kyua_run_params_init(&run_params); + run_params.unprivileged_group = pw->pw_gid; + + ATF_REQUIRE_MSG(fork_check(&run_params, check_gid_not_root, NULL), + "Subprocess is still running with GID set to root"); +} + + +ATF_TC(fork_wait__unprivileged_both); +ATF_TC_HEAD(fork_wait__unprivileged_both, tc) +{ + atf_tc_set_md_var(tc, "require.config", "unprivileged-user"); + atf_tc_set_md_var(tc, "require.user", "root"); +} +ATF_TC_BODY(fork_wait__unprivileged_both, tc) +{ + const struct passwd* pw = getpwnam(atf_tc_get_config_var( + tc, "unprivileged-user")); + ATF_REQUIRE_MSG(pw != NULL, "Cannot find unprivileged user"); + + kyua_run_params_t run_params; + kyua_run_params_init(&run_params); + run_params.unprivileged_user = pw->pw_uid; + run_params.unprivileged_group = pw->pw_gid; + + ATF_REQUIRE_MSG(fork_check(&run_params, check_not_root, NULL), + "Subprocess is still running with root privileges"); +} + + +ATF_TC_WITHOUT_HEAD(fork_wait__work_directory); +ATF_TC_BODY(fork_wait__work_directory, tc) +{ + ATF_REQUIRE(mkdir("the-work-directory", 0755) != -1); + atf_utils_create_file("the-work-directory/data-file", "%s", ""); + + kyua_run_params_t run_params; + kyua_run_params_init(&run_params); + run_params.work_directory = "./the-work-directory"; + ATF_REQUIRE_MSG(fork_check(&run_params, check_work_directory, "data-file"), + "Subprocess not in its own process group"); +} + + +ATF_TC_WITHOUT_HEAD(work_directory__builtin_tmpdir); +ATF_TC_BODY(work_directory__builtin_tmpdir, tc) +{ + char* tmpdir; + RE(kyua_fs_make_absolute("worktest", &tmpdir)); + ATF_REQUIRE(mkdir(tmpdir, 0755) != -1); + RE(kyua_env_unset("TMPDIR")); + kyua_run_tmpdir = tmpdir; + + char* work_directory; + RE(kyua_run_work_directory_enter("template.XXXXXX", getuid(), getgid(), + &work_directory)); + + { + char* template_test; + RE(kyua_fs_concat(&template_test, atf_tc_get_config_var(tc, "srcdir"), + "worktest", "template.XXXXXX", NULL)); + ATF_REQUIRE(access(template_test, X_OK) == -1); + free(template_test); + } + + ATF_REQUIRE(access(work_directory, X_OK) != -1); + + ATF_REQUIRE(rmdir(tmpdir) == -1); // Not yet empty. + RE(kyua_run_work_directory_leave(&work_directory)); + ATF_REQUIRE(rmdir(tmpdir) != -1); + free(tmpdir); +} + + +ATF_TC_WITHOUT_HEAD(work_directory__env_tmpdir); +ATF_TC_BODY(work_directory__env_tmpdir, tc) +{ + char* tmpdir; + RE(kyua_fs_make_absolute("worktest", &tmpdir)); + ATF_REQUIRE(mkdir(tmpdir, 0755) != -1); + RE(kyua_env_set("TMPDIR", tmpdir)); + + char* work_directory; + RE(kyua_run_work_directory_enter("template.XXXXXX", getuid(), getgid(), + &work_directory)); + + { + char* template_test; + RE(kyua_fs_concat(&template_test, atf_tc_get_config_var(tc, "srcdir"), + "worktest", "template.XXXXXX", NULL)); + ATF_REQUIRE(access(template_test, X_OK) == -1); + free(template_test); + } + + ATF_REQUIRE(access(work_directory, X_OK) != -1); + + ATF_REQUIRE(rmdir(tmpdir) == -1); // Not yet empty. + RE(kyua_run_work_directory_leave(&work_directory)); + ATF_REQUIRE(rmdir(tmpdir) != -1); + free(tmpdir); +} + + +ATF_TC(work_directory__permissions); +ATF_TC_HEAD(work_directory__permissions, tc) +{ + atf_tc_set_md_var(tc, "require.config", "unprivileged-user"); + atf_tc_set_md_var(tc, "require.user", "root"); +} +ATF_TC_BODY(work_directory__permissions, tc) +{ + const struct passwd* pw = getpwnam(atf_tc_get_config_var( + tc, "unprivileged-user")); + + printf("%d %d %d %d\n", getuid(), getgid(), pw->pw_uid, pw->pw_gid); + + char* work_directory; + RE(kyua_run_work_directory_enter("template.XXXXXX", pw->pw_uid, pw->pw_gid, + &work_directory)); + + struct stat sb; + ATF_REQUIRE(stat(work_directory, &sb) != -1); + ATF_REQUIRE_EQ(pw->pw_uid, sb.st_uid); + ATF_REQUIRE_EQ(pw->pw_gid, sb.st_gid); + + RE(kyua_run_work_directory_leave(&work_directory)); +} + + +ATF_TC(work_directory__mkdtemp_error); +ATF_TC_HEAD(work_directory__mkdtemp_error, tc) +{ + atf_tc_set_md_var(tc, "require.user", "unprivileged"); +} +ATF_TC_BODY(work_directory__mkdtemp_error, tc) +{ + char* tmpdir; + RE(kyua_fs_make_absolute("worktest", &tmpdir)); + ATF_REQUIRE(mkdir(tmpdir, 0555) != -1); + RE(kyua_env_set("TMPDIR", tmpdir)); + + char* work_directory; + const kyua_error_t error = kyua_run_work_directory_enter( + "template.XXXXXX", getuid(), getgid(), &work_directory); + ATF_REQUIRE(kyua_error_is_set(error)); + ATF_REQUIRE(kyua_error_is_type(error, "libc")); + ATF_REQUIRE_EQ(EACCES, kyua_libc_error_errno(error)); + kyua_error_free(error); + + ATF_REQUIRE(rmdir(tmpdir) != -1); // Empty; subdirectory not created. + free(tmpdir); +} + + +ATF_TC(work_directory__permissions_error); +ATF_TC_HEAD(work_directory__permissions_error, tc) +{ + atf_tc_set_md_var(tc, "require.user", "unprivileged"); +} +ATF_TC_BODY(work_directory__permissions_error, tc) +{ + char* tmpdir; + RE(kyua_fs_make_absolute("worktest", &tmpdir)); + ATF_REQUIRE(mkdir(tmpdir, 0755) != -1); + RE(kyua_env_set("TMPDIR", tmpdir)); + + char* work_directory; + const kyua_error_t error = kyua_run_work_directory_enter( + "template.XXXXXX", getuid() + 1, getgid(), &work_directory); + ATF_REQUIRE(kyua_error_is_set(error)); + ATF_REQUIRE(kyua_error_is_type(error, "libc")); + ATF_REQUIRE_EQ(EPERM, kyua_libc_error_errno(error)); + kyua_error_free(error); + + ATF_REQUIRE(rmdir(tmpdir) != -1); // Empty; subdirectory not created. + free(tmpdir); +} + + +/// Performs a signal delivery test to the work directory handling code. +/// +/// \param signo The signal to deliver. +static void +work_directory_signal_check(const int signo) +{ + char* tmpdir; + RE(kyua_fs_make_absolute("worktest", &tmpdir)); + ATF_REQUIRE(mkdir(tmpdir, 0755) != -1); + RE(kyua_env_set("TMPDIR", tmpdir)); + + char* work_directory; + RE(kyua_run_work_directory_enter("template.XXXXXX", getuid(), getgid(), + &work_directory)); + + kyua_run_params_t run_params; + kyua_run_params_init(&run_params); + run_params.work_directory = work_directory; + + pid_t pid; + RE(kyua_run_fork(&run_params, &pid)); + if (pid == 0) { + sleep(run_params.timeout_seconds * 2); + abort(); + } + + // This should cause the handled installed by the work_directory management + // code to terminate the subprocess so that we get a chance to run the + // cleanup code ourselves. + kill(getpid(), signo); + + int status; bool timed_out; + RE(kyua_run_wait(pid, &status, &timed_out)); + ATF_REQUIRE(!timed_out); + ATF_REQUIRE(WIFSIGNALED(status)); + ATF_REQUIRE_EQ(SIGKILL, WTERMSIG(status)); + + ATF_REQUIRE(rmdir(tmpdir) == -1); // Not yet empty. + RE(kyua_run_work_directory_leave(&work_directory)); + ATF_REQUIRE(rmdir(tmpdir) != -1); + free(tmpdir); +} + + +ATF_TC_WITHOUT_HEAD(work_directory__sighup); +ATF_TC_BODY(work_directory__sighup, tc) +{ + work_directory_signal_check(SIGHUP); +} + + +ATF_TC_WITHOUT_HEAD(work_directory__sigint); +ATF_TC_BODY(work_directory__sigint, tc) +{ + work_directory_signal_check(SIGINT); +} + + +ATF_TC_WITHOUT_HEAD(work_directory__sigterm); +ATF_TC_BODY(work_directory__sigterm, tc) +{ + work_directory_signal_check(SIGTERM); +} + + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, run_params_init__defaults); + + ATF_TP_ADD_TC(tp, fork_exec_wait__ok); + ATF_TP_ADD_TC(tp, fork_exec_wait__eacces); + ATF_TP_ADD_TC(tp, fork_exec_wait__enoent); + + ATF_TP_ADD_TC(tp, fork_wait__core_size); + ATF_TP_ADD_TC(tp, fork_wait__env); + ATF_TP_ADD_TC(tp, fork_wait__process_group); + ATF_TP_ADD_TC(tp, fork_wait__signals); + ATF_TP_ADD_TC(tp, fork_wait__timeout); + ATF_TP_ADD_TC(tp, fork_wait__umask); + ATF_TP_ADD_TC(tp, fork_wait__unprivileged_user); + ATF_TP_ADD_TC(tp, fork_wait__unprivileged_group); + ATF_TP_ADD_TC(tp, fork_wait__unprivileged_both); + ATF_TP_ADD_TC(tp, fork_wait__work_directory); + + ATF_TP_ADD_TC(tp, work_directory__builtin_tmpdir); + ATF_TP_ADD_TC(tp, work_directory__env_tmpdir); + ATF_TP_ADD_TC(tp, work_directory__permissions); + ATF_TP_ADD_TC(tp, work_directory__permissions_error); + ATF_TP_ADD_TC(tp, work_directory__mkdtemp_error); + ATF_TP_ADD_TC(tp, work_directory__sighup); + ATF_TP_ADD_TC(tp, work_directory__sigint); + ATF_TP_ADD_TC(tp, work_directory__sigterm); + + return atf_no_error(); +} diff --git a/external/bsd/kyua-testers/dist/stacktrace.c b/external/bsd/kyua-testers/dist/stacktrace.c new file mode 100644 index 000000000..c4020a1f1 --- /dev/null +++ b/external/bsd/kyua-testers/dist/stacktrace.c @@ -0,0 +1,364 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "stacktrace.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "defs.h" +#include "fs.h" +#include "env.h" +#include "error.h" +#include "run.h" +#include "text.h" + + +/// Built-in path to GDB. +/// +/// This should be an absolute path for deterministic behavior. We also accept +/// a basename to cope with any issues that might arise from an invalid +/// configure check or a manual override of the GDB constant, in which case the +/// exec call below will (try to) locate the binary in the path. +/// +/// Note that the program pointed to by this variable is not required to exist. +/// If it does not, we fail gracefully. +/// +/// Test cases can override the value of this built-in constant to unit-test the +/// behavior of the functions below. +const char* kyua_stacktrace_gdb = GDB; +#undef GDB // We really want to use the variable, not the macro. + + +/// Time to give to the external GDB process to produce a stack trace. +/// +/// Test cases can override the value of this built-in constant to unit-test the +/// behavior of the functions below. +unsigned long kyua_stacktrace_gdb_timeout = 300; + + +/// Maximum length of the core file name, if known. +/// +/// Some operating systems impose a maximum length on the basename of the core +/// file. If MAXCOMLEN is defined, then we need to truncate the program name to +/// this length before searching for the core file. If we cannot figure out +/// what this limit is, we set it to zero, which we consider later as +/// "unlimited". +#if !defined(MAXCOMLEN) +# define MAXCOMLEN 0 +#endif + + +static void run_gdb(const char* program, const char* core_name, FILE* output) + KYUA_DEFS_NORETURN; + + +/// Constructs the parameters to run GDB with. +/// +/// \param original_run_params Parameters used to run the binary that generated +/// the core dump. +/// +/// \return The run parameters with which to run GDB. +static kyua_run_params_t +gdb_run_params(const kyua_run_params_t* original_run_params) +{ + kyua_run_params_t run_params = *original_run_params; + run_params.timeout_seconds = kyua_stacktrace_gdb_timeout; + return run_params; +} + + +/// Body of a subprocess to execute GDB. +/// +/// This should be called from the child created by a kyua_run_fork() call, +/// which means that we do not have to take care of isolating the process. +/// +/// \pre The caller must have flushed stdout before spawning this process, to +/// prevent double-flushing and/or corruption of data. +/// +/// \param program Path to the program being debugged. Can be relative to +/// the given work directory. +/// \param core_name Path to the dumped core. Use find_core() to deduce +/// a valid candidate. Can be relative to the given work directory. +/// \param output Stream to which to send the output of GDB. +static void +run_gdb(const char* program, const char* core_name, FILE* output) +{ + // TODO(jmmv): Should be done by kyua_run_fork(), but doing so would change + // the semantics of the ATF interface. Need to evaluate this carefully. + const kyua_error_t error = kyua_env_unset("TERM"); + if (kyua_error_is_set(error)) { + kyua_error_warn(error, "Failed to unset TERM; GDB may misbehave"); + free(error); + } + + (void)close(STDIN_FILENO); + const int input_fd = open("/dev/null", O_RDONLY); + assert(input_fd == STDIN_FILENO); + + const int output_fd = fileno(output); + assert(output_fd != -1); // We expect a file-backed stream. + if (output_fd != STDOUT_FILENO) { + fflush(stdout); + (void)dup2(output_fd, STDOUT_FILENO); + } + if (output_fd != STDERR_FILENO) { + fflush(stderr); + (void)dup2(output_fd, STDERR_FILENO); + } + if (output_fd != STDOUT_FILENO && output_fd != STDERR_FILENO) + fclose(output); + + const char* const gdb_args[] = { + "gdb", "-batch", "-q", "-ex", "bt", program, core_name, NULL }; + kyua_run_exec(kyua_stacktrace_gdb, gdb_args); +} + + +/// Truncates a string. +/// +/// \param source The string to truncate. +/// \param [out] buffer Output buffer into which to store the truncated text. +/// \param buffer_length Size of the buffer. +/// +/// \return A pointer to the buffer. +static const char* +slice(const char* source, char* buffer, const size_t buffer_length) +{ + const size_t source_length = strlen(source); + if (source_length < buffer_length) { + strcpy(buffer, source); + } else { + memcpy(buffer, source, buffer_length - 1); + buffer[buffer_length - 1] = '\0'; + } + return buffer; +} + + +static char* try_core(const char* format, ...) KYUA_DEFS_FORMAT_PRINTF(1, 2); + + +/// Generates a path and checks if it exists. +/// +/// \param format Formatting string for the path to generate. +/// \param ... Arguments to the formatting string. +/// +/// \return A dynamically-allocated string containing the generated path if +/// there were no errors and the file pointed to by such path exists; NULL +/// otherwise. The returned string must be relesed with free() by the caller. +static char* +try_core(const char* format, ...) +{ + char* path; + va_list ap; + + va_start(ap, format); + kyua_error_t error = kyua_text_vprintf(&path, format, ap); + va_end(ap); + if (kyua_error_is_set(error)) { + // Something went really wrong (and should not have happened). Ignore + // this core file candidate. + kyua_error_free(error); + return NULL; + } + + if (access(path, F_OK) == -1) { + free(path); + return NULL; + } else { + return path; + } +} + + +/// Simple version of basename() that operates on constant strings. +/// +/// This is not 100% compatible with basename() because it may return an +/// unexpected string if the path ends with a slash. For our purposes, this +/// does not matter, so we can use this simplified trick. +/// +/// \param path Path from which to compute the basename. +/// +/// \return A pointer within the input path pointing at the last component. +static const char* +const_basename(const char* path) +{ + const char* last_slash = strrchr(path, '/'); + return last_slash == NULL ? path : last_slash + 1; +} + + +/// Looks for a core file for the given program. +/// +/// \param name The basename of the binary that generated the core. +/// \param directory The directory from which the program was run. We expect to +/// find the core file in this directory. +/// \param dead_pid PID of the process that generated the core. This is needed +/// in some platforms. +/// +/// \return The path to the core file if found; otherwise none. +char* +kyua_stacktrace_find_core(const char* name, const char* directory, + const pid_t dead_pid) +{ + char* candidate = NULL; + + // TODO(jmmv): Other than checking all these defaults, in NetBSD we should + // also inspect the value of the kern.defcorename sysctl(2) MIB and use that + // as the first candidate. + // + // In Linux, the way to determine the name is by looking at + // /proc/sys/kernel/core_{pattern,uses_pid} as described by core(5). + // Unfortunately, there does not seem to be a standard API to parse these + // files, which makes checking for core files quite difficult if the + // defaults have been modified. + + // Default NetBSD naming scheme. + if (candidate == NULL && MAXCOMLEN > 0) { + char truncated[MAXCOMLEN + 1]; + candidate = try_core("%s/%s.core", directory, + slice(name, truncated, sizeof(truncated))); + } + + // Common naming scheme without the MAXCOMLEN truncation. + if (candidate == NULL) + candidate = try_core("%s/%s.core", directory, name); + + // Common naming scheme found in Linux systems. + if (candidate == NULL) + candidate = try_core("%s/core.%d", directory, (int)dead_pid); + + // Default Mac OS X naming scheme. + if (candidate == NULL) + candidate = try_core("/cores/core.%d", (int)dead_pid); + + // Common naming scheme found in Linux systems. Attempted last due to the + // genericity of the core file name. + if (candidate == NULL) + candidate = try_core("%s/core", directory); + + if (candidate != NULL) { + char* abs_candidate; + kyua_error_t error = kyua_fs_make_absolute(candidate, &abs_candidate); + if (kyua_error_is_set(error)) { + kyua_error_free(error); + return candidate; // Return possibly-relative path as a best guess. + } else { + free(candidate); + return abs_candidate; + } + } else { + return candidate; + } +} + + +/// Gathers a stacktrace of a crashed program. +/// +/// \param program The name of the binary that crashed and dumped a core file. +/// Can be either absolute or relative. +/// \param dead_pid The PID of the process that dumped core. +/// \param original_run_params Parameters with which the original binary was +/// executed. These are reused to run GDB, but adjusted with GDB-specific +/// settings. Of special interest, the work directory is used to search for +/// the core file. +/// \param output Stream into which to dump the stack trace and any additional +/// information. +/// +/// \post If anything goes wrong, the diagnostic messages are written to the +/// output. This function returns no errors. +void +kyua_stacktrace_dump(const char* program, const pid_t dead_pid, + const kyua_run_params_t* original_run_params, FILE* output) +{ + fprintf(output, "Process with PID %d dumped core; attempting to gather " + "stack trace\n", dead_pid); + + const kyua_run_params_t run_params = gdb_run_params(original_run_params); + + kyua_error_t error = kyua_error_ok(); + + char* core_file = kyua_stacktrace_find_core(const_basename(program), + run_params.work_directory, + dead_pid); + if (core_file == NULL) { + fprintf(output, "Cannot find any core file\n"); + goto out; + } + + // We must flush the output stream right before invoking fork, so that the + // subprocess does not have any unflushed data. Failure to do so results in + // the messages above being written twice to the output. + fflush(output); + pid_t pid; + error = kyua_run_fork(&run_params, &pid); + if (!kyua_error_is_set(error) && pid == 0) { + run_gdb(program, core_file, output); + } + assert(pid != -1 && pid != 0); + if (kyua_error_is_set(error)) + goto out_core_file; + + int status; bool timed_out; + error = kyua_run_wait(pid, &status, &timed_out); + if (kyua_error_is_set(error)) + goto out_core_file; + + if (timed_out) { + fprintf(output, "GDB failed; timed out\n"); + } else { + if (WIFEXITED(status)) { + if (WEXITSTATUS(status) == EXIT_SUCCESS) + fprintf(output, "GDB exited successfully\n"); + else + fprintf(output, "GDB failed with code %d; see output above for " + "details\n", WEXITSTATUS(status)); + } else { + assert(WIFSIGNALED(status)); + fprintf(output, "GDB received signal %d; see output above for " + "details\n", WTERMSIG(status)); + } + } + +out_core_file: + free(core_file); +out: + if (kyua_error_is_set(error)) { + kyua_error_fprintf(output, error, "Failed to gather stacktrace"); + free(error); + } +} diff --git a/external/bsd/kyua-testers/dist/stacktrace.h b/external/bsd/kyua-testers/dist/stacktrace.h new file mode 100644 index 000000000..048b09316 --- /dev/null +++ b/external/bsd/kyua-testers/dist/stacktrace.h @@ -0,0 +1,50 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file stacktrace.h +/// Routines to obtain stacktraces out of core files. + +#if !defined(KYUA_STACKTRACE_H) +#define KYUA_STACKTRACE_H + +#include +#include + +#include "run_fwd.h" + + +extern const char* kyua_stacktrace_gdb; +extern unsigned long kyua_stacktrace_gdb_timeout; + +char* kyua_stacktrace_find_core(const char* name, const char* directory, + const pid_t dead_pid); +void kyua_stacktrace_dump(const char*, const pid_t, const kyua_run_params_t*, + FILE*); + + +#endif // !defined(KYUA_STACKTRACE_H) diff --git a/external/bsd/kyua-testers/dist/stacktrace_helper.c b/external/bsd/kyua-testers/dist/stacktrace_helper.c new file mode 100644 index 000000000..561a74baa --- /dev/null +++ b/external/bsd/kyua-testers/dist/stacktrace_helper.c @@ -0,0 +1,36 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include + + +int +main(void) +{ + abort(); +} diff --git a/external/bsd/kyua-testers/dist/stacktrace_test.c b/external/bsd/kyua-testers/dist/stacktrace_test.c new file mode 100644 index 000000000..2671e2c5b --- /dev/null +++ b/external/bsd/kyua-testers/dist/stacktrace_test.c @@ -0,0 +1,331 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "stacktrace.h" + +#include +#include +#include + +#include +#include +#include + +#include + +#include "env.h" +#include "error.h" +#include "fs.h" +#include "run.h" +#include "text.h" + +#if !defined(WCOREDUMP) && defined(__minix) +#define WCOREDUMP(x) ((x) & 0x80) +#endif /*!defined(WCOREDUMP) && defined(__minix) */ + + +/// Ensures that the given expression does not return a kyua_error_t. +/// +/// \param expr Expression to evaluate. +#define RE(expr) ATF_REQUIRE(!kyua_error_is_set(expr)) + + +/// Ensures that the given expression does not return a kyua_error_t. +/// +/// \param expr Expression to evaluate. +/// \param msg Failure message. +#define RE_MSG(expr, msg) ATF_REQUIRE_MSG(!kyua_error_is_set(expr), msg) + + +/// Generates a core dump. +/// +/// Due to the complexity of this interface, you should probably use +/// generate_core() instead. +/// +/// \post If this fails to generate a core file, the test case is marked as +/// skipped. The caller therefore can rely that a core dump has been created on +/// return. +/// +/// \param tc Pointer to the caller test case. +/// \param run_params Parameters for the execution of the helper. +/// \param helper_path Path to the created helper. +/// \param exec_path Name of the helper, prefixed with ./ so that it can be +/// executed from within the work directory. +/// \param helper_name Basename of the helper. +/// +/// \return The PID of the crashed binary. +static pid_t +generate_core_aux(const atf_tc_t* tc, const kyua_run_params_t* run_params, + const char* helper_path, const char* exec_path, + const char* helper_name) +{ + const char* srcdir = atf_tc_get_config_var(tc, "srcdir"); + + char* src_helper; + RE(kyua_fs_concat(&src_helper, srcdir, "stacktrace_helper", NULL)); + atf_utils_copy_file(src_helper, helper_path); + free(src_helper); + + // We use kyua_run_fork for this to better simulate the final use case of + // the stacktrace gathering, as test programs are run through these + // functions. Also, kyua_run_fork provides us with automatic unlimiting of + // resources so that core files can be generated. + + pid_t pid; + const kyua_error_t error = kyua_run_fork(run_params, &pid); + if (!kyua_error_is_set(error) && pid == 0) { + const char* const args[] = { helper_name, NULL }; + kyua_run_exec(exec_path, args); + } + RE(error); + + int status; bool timed_out; + RE_MSG(kyua_run_wait(pid, &status, &timed_out), + "wait failed; unexpected problem during exec?"); + + ATF_REQUIRE(WIFSIGNALED(status)); + if (!WCOREDUMP(status)) + atf_tc_skip("Test failed to generate core dump"); + return pid; +} + + +/// Creates a script. +/// +/// \param script Path to the script to create. +/// \param contents Contents of the script. +static void +create_script(const char* script, const char* contents) +{ + atf_utils_create_file(script, "#! /bin/sh\n\n%s\n", contents); + ATF_REQUIRE(chmod(script, 0755) != -1); +} + + +/// Generates a core file. +/// +/// \param tc Pointer to the calling test case. +/// \param work_directory Name of the directory in which to place the binary +/// that will generate the stacktrace. +/// \param program_name Basename of the binary that will crash. +/// +/// \return PID of the process that generated the core file. +static pid_t +generate_core(const atf_tc_t* tc, const char* work_directory, + const char* program_name) +{ + kyua_run_params_t run_params; + kyua_run_params_init(&run_params); + if (strcmp(work_directory, ".") != 0) { + ATF_REQUIRE(mkdir(work_directory, 0755) != -1); + run_params.work_directory = work_directory; + } + + char* copy_to; char* exec_path; + RE(kyua_text_printf(©_to, "%s/%s", work_directory, program_name)); + RE(kyua_text_printf(&exec_path, "./%s", program_name)); + const pid_t pid = generate_core_aux(tc, &run_params, copy_to, exec_path, + program_name); + free(exec_path); + free(copy_to); + return pid; +} + + +/// Prepares and runs kyua_stacktrace_dump(). +/// +/// \param tc Pointer to the calling test case. +/// \param work_directory Name of the directory in which to place the binary +/// that will generate the stacktrace. +/// \param program_name Basename of the binary that will crash. +/// \param output_name Name of the file to which to write the stacktrace. +/// \param timeout_seconds Time to give GDB to complete. +static void +do_dump(const atf_tc_t* tc, const char* work_directory, + const char* program_name, const char* output_name, + const int timeout_seconds) +{ + const pid_t pid = generate_core(tc, work_directory, program_name); + + kyua_run_params_t run_params; + kyua_run_params_init(&run_params); + run_params.timeout_seconds = timeout_seconds + 100; // Some large value. + run_params.work_directory = work_directory; // Created by generate_core. + + kyua_stacktrace_gdb_timeout = timeout_seconds; + + FILE* output = fopen(output_name, "w"); + ATF_REQUIRE(output != NULL); + kyua_stacktrace_dump(program_name, pid, &run_params, output); + fclose(output); + atf_utils_cat_file(output_name, "dump output: "); +} + + +ATF_TC_WITHOUT_HEAD(find_core__found__short); +ATF_TC_BODY(find_core__found__short, tc) +{ + const pid_t pid = generate_core(tc, "dir", "short"); + const char* core_name = kyua_stacktrace_find_core("short", "dir", pid); + if (core_name == NULL) + atf_tc_fail("Core dumped, but no candidates found"); + ATF_REQUIRE(strstr(core_name, "core") != NULL); + ATF_REQUIRE(access(core_name, F_OK) != -1); +} + + +ATF_TC_WITHOUT_HEAD(find_core__found__long); +ATF_TC_BODY(find_core__found__long, tc) +{ + const pid_t pid = generate_core( + tc, "dir", "long-name-that-may-be-truncated-in-some-systems"); + const char* core_name = kyua_stacktrace_find_core( + "long-name-that-may-be-truncated-in-some-systems", "dir", pid); + if (core_name == NULL) + atf_tc_fail("Core dumped, but no candidates found"); + ATF_REQUIRE(strstr(core_name, "core") != NULL); + ATF_REQUIRE(access(core_name, F_OK) != -1); +} + + +ATF_TC_WITHOUT_HEAD(find_core__not_found); +ATF_TC_BODY(find_core__not_found, tc) +{ + const char* core_name = kyua_stacktrace_find_core("missing", ".", 1); + if (core_name != NULL) + atf_tc_fail("Core not dumped, but candidate found: %s", core_name); +} + + +ATF_TC_WITHOUT_HEAD(dump__integration); +ATF_TC_BODY(dump__integration, tc) +{ + do_dump(tc, "dir", "short", "stacktrace", 10); + + // It is hard to validate the execution of an arbitrary GDB of which we know + // nothing anything. Just assume that the backtrace, at the very least, + // prints a frame identifier. + ATF_REQUIRE(atf_utils_grep_file("#0", "stacktrace")); +} + + +ATF_TC_WITHOUT_HEAD(dump__ok); +ATF_TC_BODY(dump__ok, tc) +{ + RE(kyua_env_set("PATH", ".")); + create_script("fake-gdb", "echo 'frame 1'; echo 'frame 2'; " + "echo 'some warning' 1>&2; exit 0"); + kyua_stacktrace_gdb = "fake-gdb"; + + do_dump(tc, ".", "short", "stacktrace", 10); + + ATF_REQUIRE(atf_utils_grep_file("dumped core; attempting to gather", + "stacktrace")); + ATF_REQUIRE(atf_utils_grep_file("frame 1", "stacktrace")); + ATF_REQUIRE(atf_utils_grep_file("frame 2", "stacktrace")); + ATF_REQUIRE(atf_utils_grep_file("some warning", "stacktrace")); + ATF_REQUIRE(atf_utils_grep_file("GDB exited successfully", "stacktrace")); +} + + +ATF_TC_WITHOUT_HEAD(dump__cannot_find_core); +ATF_TC_BODY(dump__cannot_find_core, tc) +{ + kyua_run_params_t run_params; + kyua_run_params_init(&run_params); + + FILE* output = fopen("stacktrace", "w"); + ATF_REQUIRE(output != NULL); + // This assumes that init(8) has never core dumped. + kyua_stacktrace_dump("missing", 1, &run_params, output); + fclose(output); + atf_utils_cat_file("stacktrace", "dump output: "); + + ATF_REQUIRE(atf_utils_grep_file("Cannot find any core file", "stacktrace")); +} + + +ATF_TC_WITHOUT_HEAD(dump__cannot_find_gdb); +ATF_TC_BODY(dump__cannot_find_gdb, tc) +{ + RE(kyua_env_set("PATH", ".")); + kyua_stacktrace_gdb = "missing-gdb"; + + do_dump(tc, ".", "dont-care", "stacktrace", 10); + + ATF_REQUIRE(atf_utils_grep_file("execvp failed", "stacktrace")); +} + + +ATF_TC_WITHOUT_HEAD(dump__gdb_fail); +ATF_TC_BODY(dump__gdb_fail, tc) +{ + RE(kyua_env_set("PATH", ".")); + create_script("fake-gdb", "echo 'foo'; echo 'bar' 1>&2; exit 56"); + kyua_stacktrace_gdb = "fake-gdb"; + + do_dump(tc, ".", "short", "stacktrace", 10); + + ATF_REQUIRE(atf_utils_grep_file("foo", "stacktrace")); + ATF_REQUIRE(atf_utils_grep_file("bar", "stacktrace")); + ATF_REQUIRE(atf_utils_grep_file("GDB failed with code 56; see output above " + "for details", "stacktrace")); +} + + +ATF_TC_WITHOUT_HEAD(dump__gdb_times_out); +ATF_TC_BODY(dump__gdb_times_out, tc) +{ + RE(kyua_env_set("PATH", ".")); + create_script("fake-gdb", "echo 'foo'; echo 'bar' 1>&2; " + "/bin/sleep 10; /usr/bin/sleep 10; exit 0"); + kyua_stacktrace_gdb = "fake-gdb"; + + do_dump(tc, ".", "short", "stacktrace", 1); + + ATF_REQUIRE(atf_utils_grep_file("foo", "stacktrace")); + ATF_REQUIRE(atf_utils_grep_file("bar", "stacktrace")); + ATF_REQUIRE(atf_utils_grep_file("GDB failed; timed out", "stacktrace")); +} + + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, find_core__found__short); + ATF_TP_ADD_TC(tp, find_core__found__long); + ATF_TP_ADD_TC(tp, find_core__not_found); + + ATF_TP_ADD_TC(tp, dump__integration); + ATF_TP_ADD_TC(tp, dump__ok); + ATF_TP_ADD_TC(tp, dump__cannot_find_core); + ATF_TP_ADD_TC(tp, dump__cannot_find_gdb); + ATF_TP_ADD_TC(tp, dump__gdb_fail); + ATF_TP_ADD_TC(tp, dump__gdb_times_out); + + return atf_no_error(); +} diff --git a/external/bsd/kyua-testers/dist/text.c b/external/bsd/kyua-testers/dist/text.c new file mode 100644 index 000000000..cfe64b2e9 --- /dev/null +++ b/external/bsd/kyua-testers/dist/text.c @@ -0,0 +1,117 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "text.h" + +#include +#include +#include +#include +#include + +#include "error.h" + + +/// Calculates the length of a formatting string with its replacements. +/// +/// \param format The formatting string. +/// \param ap List of arguments to apply to the formatting string. +/// +/// \return -1 if there is an error; or the final length otherwise. +static int +calculate_length(const char* format, va_list ap) +{ + va_list ap2; + + char buffer[1]; + va_copy(ap2, ap); + const int needed = vsnprintf(buffer, sizeof(buffer), format, ap); + va_end(ap2); + return needed; +} + + +/// Generates a string from a format string and its replacements. +/// +/// \param [out] output Pointer to the dynamically-allocated string with the +/// result of the operation. The caller must release this with free(). +/// \param format The formatting string. +/// \param ... Arguments to apply to the formatting string. +/// +/// \return OK if the string could be formatted; an error otherwise. +kyua_error_t +kyua_text_printf(char** output, const char* format, ...) +{ + kyua_error_t error; + va_list ap; + + va_start(ap, format); + error = kyua_text_vprintf(output, format, ap); + va_end(ap); + + return error; +} + + +/// Generates a string from a format string and its replacements. +/// +/// \param [out] output Pointer to the dynamically-allocated string with the +/// result of the operation. The caller must release this with free(). +/// \param format The formatting string. +/// \param ap List of to apply to the formatting string. +/// +/// \return OK if the string could be formatted; an error otherwise. +kyua_error_t +kyua_text_vprintf(char** output, const char* format, va_list ap) +{ + va_list ap2; + + va_copy(ap2, ap); + const int length = calculate_length(format, ap2); + va_end(ap2); + if (length < 0) + return kyua_libc_error_new(errno, "Could not calculate length of " + "string with format '%s'", format); + + char* buffer = (char*)malloc(length + 1); + if (buffer == NULL) + return kyua_oom_error_new(); + + va_copy(ap2, ap); + const int printed_length = vsnprintf(buffer, length + 1, format, ap2); + va_end(ap2); + assert(printed_length == length); + if (printed_length < 0) { + free(buffer); + return kyua_libc_error_new(errno, "Could generate string with format " + "'%s'", format); + } + + *output = buffer; + return kyua_error_ok(); +} diff --git a/external/bsd/kyua-testers/dist/text.h b/external/bsd/kyua-testers/dist/text.h new file mode 100644 index 000000000..300f99d73 --- /dev/null +++ b/external/bsd/kyua-testers/dist/text.h @@ -0,0 +1,46 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file text.h +/// Routines for file system manipulation. + +#if !defined(KYUA_TEXT_H) +#define KYUA_TEXT_H + +#include + +#include "defs.h" +#include "error_fwd.h" + + +kyua_error_t kyua_text_printf(char**, const char*, ...) + KYUA_DEFS_FORMAT_PRINTF(2, 3); +kyua_error_t kyua_text_vprintf(char**, const char*, va_list); + + +#endif // !defined(KYUA_TEXT_H) diff --git a/external/bsd/kyua-testers/dist/text_test.c b/external/bsd/kyua-testers/dist/text_test.c new file mode 100644 index 000000000..5bf9acadf --- /dev/null +++ b/external/bsd/kyua-testers/dist/text_test.c @@ -0,0 +1,112 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "text.h" + +#include +#include + +#include + +#include "error.h" + + +static kyua_error_t call_vprintf(char** output, const char* format, ...) + KYUA_DEFS_FORMAT_PRINTF(2, 3); + + +/// Invokes kyua_text_vprintf() based on a set of variable arguments. +/// +/// \param [out] output Output pointer of kyua_text_vprintf(). +/// \param format Formatting string to use. +/// \param ... Variable arguments to pack in a va_list to use. +/// +/// \return The return value of the wrapped function. +static kyua_error_t +call_vprintf(char** output, const char* format, ...) +{ + va_list ap; + va_start(ap, format); + kyua_error_t error = kyua_text_vprintf(output, format, ap); + va_end(ap); + return error; +} + + +ATF_TC_WITHOUT_HEAD(printf__empty); +ATF_TC_BODY(printf__empty, tc) +{ + char* buffer; + kyua_error_t error = kyua_text_printf(&buffer, "%s", ""); + ATF_REQUIRE(!kyua_error_is_set(error)); + ATF_REQUIRE_STREQ("", buffer); +} + + +ATF_TC_WITHOUT_HEAD(printf__some); +ATF_TC_BODY(printf__some, tc) +{ + char* buffer; + kyua_error_t error = kyua_text_printf(&buffer, "this is %d %s", 123, "foo"); + ATF_REQUIRE(!kyua_error_is_set(error)); + ATF_REQUIRE_STREQ("this is 123 foo", buffer); + free(buffer); +} + + +ATF_TC_WITHOUT_HEAD(vprintf__empty); +ATF_TC_BODY(vprintf__empty, tc) +{ + char* buffer; + kyua_error_t error = call_vprintf(&buffer, "%s", ""); + ATF_REQUIRE(!kyua_error_is_set(error)); + ATF_REQUIRE_STREQ("", buffer); +} + + +ATF_TC_WITHOUT_HEAD(vprintf__some); +ATF_TC_BODY(vprintf__some, tc) +{ + char* buffer; + kyua_error_t error = call_vprintf(&buffer, "this is %d %s", 123, "foo"); + ATF_REQUIRE(!kyua_error_is_set(error)); + ATF_REQUIRE_STREQ("this is 123 foo", buffer); + free(buffer); +} + + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, printf__empty); + ATF_TP_ADD_TC(tp, printf__some); + + ATF_TP_ADD_TC(tp, vprintf__empty); + ATF_TP_ADD_TC(tp, vprintf__some); + + return atf_no_error(); +} diff --git a/external/bsd/kyua-testers/lib/Makefile b/external/bsd/kyua-testers/lib/Makefile new file mode 100644 index 000000000..b451c505c --- /dev/null +++ b/external/bsd/kyua-testers/lib/Makefile @@ -0,0 +1,5 @@ +# $NetBSD: Makefile,v 1.1 2013/02/19 06:04:42 jmmv Exp $ + +SUBDIR= libtester libatf_tester + +.include diff --git a/external/bsd/kyua-testers/lib/libatf_tester/Makefile b/external/bsd/kyua-testers/lib/libatf_tester/Makefile new file mode 100644 index 000000000..dca48c780 --- /dev/null +++ b/external/bsd/kyua-testers/lib/libatf_tester/Makefile @@ -0,0 +1,23 @@ +# $NetBSD: Makefile,v 1.1 2013/02/19 06:04:42 jmmv Exp $ + +#NOLINT= # defined + +.include + +LIB= atf_tester +LIBISPRIVATE= yes + +SRCDIR= ${NETBSDSRCDIR}/external/bsd/kyua-testers/dist +.PATH: ${SRCDIR} + +CPPFLAGS+= -I${.CURDIR}/../libtester # For config.h and defs.h. +CPPFLAGS+= -I${SRCDIR} # For non-installed headers. + +CPPFLAGS+= -DHAVE_CONFIG_H + +WARNS?= 5 + +SRCS= atf_list.c +SRCS+= atf_result.c + +.include diff --git a/external/bsd/kyua-testers/lib/libtester/Makefile b/external/bsd/kyua-testers/lib/libtester/Makefile new file mode 100644 index 000000000..bc662fb1c --- /dev/null +++ b/external/bsd/kyua-testers/lib/libtester/Makefile @@ -0,0 +1,45 @@ +# $NetBSD: Makefile,v 1.1 2013/02/19 06:04:42 jmmv Exp $ + +#NOLINT= # defined + +.include + +LIB= tester +LIBISPRIVATE= yes + +SRCDIR= ${NETBSDSRCDIR}/external/bsd/kyua-testers/dist +.PATH: ${SRCDIR} + +CPPFLAGS+= -DGDB=\"/usr/bin/gdb\" +CPPFLAGS+= -DKYUA_TMPDIR=\"/tmp\" +CPPFLAGS+= -I${.CURDIR} # For config.h and defs.h. +CPPFLAGS+= -I${SRCDIR} # For non-installed headers. + +CPPFLAGS+= -DHAVE_CONFIG_H + +WARNS?= 3 + +SRCS= cli.c +SRCS+= env.c +SRCS+= error.c +SRCS+= fs.c +SRCS+= result.c +SRCS+= run.c +SRCS+= stacktrace.c +SRCS+= text.c + +.if ${MKSHARE} != "no" +FILES+= kyua-testers.pc +FILESDIR= /usr/lib/pkgconfig + +realall: kyua-testers.pc +kyua-testers.pc: Makefile kyua-testers.pc.in + ${TOOL_SED} \ + -e 's,__LIBEXECDIR__,/usr/libexec,g' \ + -e 's,__VERSION__,0.1,g' \ + <${SRCDIR}/kyua-testers.pc.in >kyua-testers.pc +CLEANFILES+= kyua-testers.pc +.endif + +.include +.include diff --git a/external/bsd/kyua-testers/lib/libtester/config.h b/external/bsd/kyua-testers/lib/libtester/config.h new file mode 100644 index 000000000..ec0fdba25 --- /dev/null +++ b/external/bsd/kyua-testers/lib/libtester/config.h @@ -0,0 +1,59 @@ +/* config.h. Generated from config.h.in by configure. */ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to the optind value to reset getopt processing */ +#define GETOPT_OPTIND_RESET_VALUE 1 + +/* Define to 1 if getcwd(NULL, 0) works */ +#define HAVE_GETCWD_DYN 1 + +/* Define to 1 if getopt allows a + sign for POSIX behavior */ +/* #undef HAVE_GETOPT_GNU */ + +/* Define to 1 if getopt has optreset */ +#define HAVE_GETOPT_WITH_OPTRESET 1 + +/* Define to 1 if you have the `putenv' function. */ +#define HAVE_PUTENV 1 + +/* Define to 1 if you have the `setenv' function. */ +#define HAVE_SETENV 1 + +/* Define to 1 if you have the `unmount' function. */ +/* #undef HAVE_UNMOUNT */ + +/* Define to 1 if you have the `unsetenv' function. */ +#define HAVE_UNSETENV 1 + +/* Define to 1 if your lchmod works */ +/* #undef HAVE_WORKING_LCHMOD */ + +/* Define to the last valid signal number */ +#define LAST_SIGNO 63 + +/* Name of package */ +#define PACKAGE "kyua-testers" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "kyua-discuss@googlegroups.com" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "Kyua - Testers" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "Kyua - Testers 0.1" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "kyua-testers" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "http://code.google.com/p/kyua/" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "0.1" + +/* Set to the path of umount(8) */ +/* #undef UMOUNT */ + +/* Version number of package */ +#define VERSION "0.1" diff --git a/external/bsd/kyua-testers/lib/libtester/defs.h b/external/bsd/kyua-testers/lib/libtester/defs.h new file mode 100644 index 000000000..477a6711e --- /dev/null +++ b/external/bsd/kyua-testers/lib/libtester/defs.h @@ -0,0 +1,74 @@ +// Copyright 2010 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file defs.h +/// +/// Definitions for compiler and system features autodetected at configuration +/// time. + +#if !defined(KYUA_DEFS_H) +#define KYUA_DEFS_H + + +/// Attribute to mark a function as printf-like. +/// +/// \param a Number of the format parameter. +/// \param b Number of the first positional parameter. +#define KYUA_DEFS_FORMAT_PRINTF(a, b) __attribute__((__format__(__printf__, a, b))) + + +/// Attribute to mark a function as non-returning. +#define KYUA_DEFS_NORETURN __attribute__((noreturn)) + + +/// Attribute to mark a function as pure. +#define KYUA_DEFS_PURE __attribute__((__pure__)) + + +/// Attribute to mark an entity as unused. +#define KYUA_DEFS_UNUSED __attribute__((__unused__)) + + +/// Macro to mark a parameter as unused. +/// +/// This macro has to be called on the name of a parameter during the +/// definition (not declaration) of a function. When doing so, it declares +/// the parameter as unused to silence compiler warnings and also renames +/// the parameter by prefixing "unused_" to it. This is to ensure that the +/// developer remembers to remove the call to this macro from the parameter +/// when he actually starts using it. +/// +/// \param name The name of the function parameter to mark as unused. +#define KYUA_DEFS_UNUSED_PARAM(name) unused_ ## name KYUA_DEFS_UNUSED + + +/// Unconstifies a pointer. +#define KYUA_DEFS_UNCONST(ptr) ((void*)(unsigned long)(const void*)(ptr)) + + +#endif // !defined(KYUA_DEFS_H) diff --git a/external/bsd/kyua-testers/libexec/Makefile b/external/bsd/kyua-testers/libexec/Makefile new file mode 100644 index 000000000..62a4fb81b --- /dev/null +++ b/external/bsd/kyua-testers/libexec/Makefile @@ -0,0 +1,5 @@ +# $NetBSD: Makefile,v 1.1 2013/02/19 06:04:43 jmmv Exp $ + +SUBDIR= kyua-atf-tester kyua-plain-tester + +.include diff --git a/external/bsd/kyua-testers/libexec/kyua-atf-tester/Makefile b/external/bsd/kyua-testers/libexec/kyua-atf-tester/Makefile new file mode 100644 index 000000000..04c4be2dc --- /dev/null +++ b/external/bsd/kyua-testers/libexec/kyua-atf-tester/Makefile @@ -0,0 +1,33 @@ +# $NetBSD: Makefile,v 1.1 2013/02/19 06:04:43 jmmv Exp $ + +.include + +SRCDIR= ${NETBSDSRCDIR}/external/bsd/kyua-testers/dist +.PATH: ${SRCDIR} + +BINDIR= /usr/libexec +PROG_CXX= kyua-atf-tester +SRCS= atf_main.c +MAN= kyua-atf-tester.1 +MAN+= kyua-atf-interface.7 + +PRIVATELIBDIR!= cd ${.CURDIR}/../../lib; ${PRINTOBJDIR} +LDADD+= ${PRIVATELIBDIR}/libatf_tester/libatf_tester.a +DPADD+= ${PRIVATELIBDIR}/libatf_tester/libatf_tester.a +LDADD+= ${PRIVATELIBDIR}/libtester/libtester.a +DPADD+= ${PRIVATELIBDIR}/libtester/libtester.a + +CPPFLAGS+= -DHAVE_CONFIG_H +CPPFLAGS+= -I${.CURDIR}/../../lib/libtester +CPPFLAGS+= -I${SRCDIR} + +WARNS?= 3 + +CLEANFILES+= kyua-atf-tester.1 +kyua-atf-tester.1: kyua-atf-tester.1.in + sed -e 's,__PACKAGE__,kyua-testers,g' \ + -e 's,__TMPDIR__,/tmp,g' \ + <${.ALLSRC} >${.TARGET}.tmp + mv ${.TARGET}.tmp ${.TARGET} + +.include diff --git a/external/bsd/kyua-testers/libexec/kyua-plain-tester/Makefile b/external/bsd/kyua-testers/libexec/kyua-plain-tester/Makefile new file mode 100644 index 000000000..ac13ea6fe --- /dev/null +++ b/external/bsd/kyua-testers/libexec/kyua-plain-tester/Makefile @@ -0,0 +1,31 @@ +# $NetBSD: Makefile,v 1.1 2013/02/19 06:04:43 jmmv Exp $ + +.include + +SRCDIR= ${NETBSDSRCDIR}/external/bsd/kyua-testers/dist +.PATH: ${SRCDIR} + +BINDIR= /usr/libexec +PROG_CXX= kyua-plain-tester +SRCS= plain_main.c +MAN= kyua-plain-tester.1 +MAN+= kyua-plain-interface.7 + +PRIVATELIBDIR!= cd ${.CURDIR}/../../lib; ${PRINTOBJDIR} +LDADD+= ${PRIVATELIBDIR}/libtester/libtester.a +DPADD+= ${PRIVATELIBDIR}/libtester/libtester.a + +CPPFLAGS+= -DHAVE_CONFIG_H +CPPFLAGS+= -I${.CURDIR}/../../lib/libtester +CPPFLAGS+= -I${SRCDIR} + +WARNS?= 3 + +CLEANFILES+= kyua-plain-tester.1 +kyua-plain-tester.1: kyua-plain-tester.1.in + sed -e 's,__PACKAGE__,kyua-testers,g' \ + -e 's,__TMPDIR__,/tmp,g' \ + <${.ALLSRC} >${.TARGET}.tmp + mv ${.TARGET}.tmp ${.TARGET} + +.include diff --git a/external/bsd/kyua-testers/prepare-import.sh b/external/bsd/kyua-testers/prepare-import.sh new file mode 100755 index 000000000..322401523 --- /dev/null +++ b/external/bsd/kyua-testers/prepare-import.sh @@ -0,0 +1,107 @@ +#!/bin/sh +# $NetBSD: prepare-import.sh,v 1.1 2013/02/19 06:04:42 jmmv Exp $ +# +# Use this script to recreate the 'dist' subdirectory from a newly released +# distfile. The script takes care of unpacking the distfile, removing any +# files that are not relevant to NetBSD and checking if there are any new +# files in the new release that need to be addressed. +# + +set -e + +ProgName=${0##*/} + +CLEAN_PATTERNS= +CLEAN_PATTERNS="${CLEAN_PATTERNS} *.m4" +CLEAN_PATTERNS="${CLEAN_PATTERNS} INSTALL TODO" +CLEAN_PATTERNS="${CLEAN_PATTERNS} Doxyfile*" +CLEAN_PATTERNS="${CLEAN_PATTERNS} Makefile* */Makefile*" +CLEAN_PATTERNS="${CLEAN_PATTERNS} admin" +CLEAN_PATTERNS="${CLEAN_PATTERNS} api-docs" +CLEAN_PATTERNS="${CLEAN_PATTERNS} config.h.in" +CLEAN_PATTERNS="${CLEAN_PATTERNS} configure*" +CLEAN_PATTERNS="${CLEAN_PATTERNS} defs.h*" +CLEAN_PATTERNS="${CLEAN_PATTERNS} m4" + +err() { + echo "${ProgName}:" "${@}" 1>&2 + exit 1 +} + +log() { + echo "${ProgName}:" "${@}" +} + +backup_dist() { + if [ -d dist.old ]; then + log "Removing dist; dist.old exists" + rm -rf dist + else + log "Backing up dist as dist.old" + mv dist dist.old + fi +} + +extract_distfile() { + local distfile="${1}"; shift + local distname="${1}"; shift + + log "Extracting ${distfile}" + tar -xzf "${distfile}" + [ -d "${distname}" ] || err "Distfile did not create ${distname}" + log "Renaming ${distname} to dist" + mv "${distname}" dist +} + +get_distname() { + local distfile="${1}"; shift + basename "${distfile}" | sed -e 's,\.tar.*,,' +} + +cleanup_dist() { + log "Removing unnecessary files from dist" + ( cd dist && rm -rf ${CLEAN_PATTERNS} ) +} + +diff_dirs() { + local old_dir="${1}"; shift + local new_dir="${1}"; shift + + local old_list=$(mktemp -t kyua-testers-import.XXXXXX) + local new_list=$(mktemp -t kyua-testers-import.XXXXXX) + local diff=$(mktemp -t kyua-testers-import.XXXXXX) + trap "rm -f '${old_list}' '${new_list}' '${diff}'; exit 1" \ + HUP INT QUIT TERM + + ( cd "${old_dir}" && find . | sort >>"${old_list}" ) + ( cd "${new_dir}" && find . | sort >>"${new_list}" ) + + diff -u "${old_list}" "${new_list}" | grep '^+\.' >>"${diff}" || true + if [ -s "${diff}" ]; then + log "New files found" + diff -u "${old_list}" "${new_list}" | grep '^+\.' + log "Check if any files have to be cleaned up and update" \ + "the prepare-import.sh script accordingly" + else + log "No new files; all good!" + fi + + rm -f "${old_list}" "${new_list}" "${diff}" +} + +main() { + [ ${#} -eq 1 ] || err "Must provide a distfile name" + local distfile="${1}"; shift + + [ -f Makefile -a -f prepare-import.sh ] || \ + err "Must be run from the src/external/bsd/kyua-testers subdirectory" + + local distname="$(get_distname ${distfile})" + + backup_dist + extract_distfile "${distfile}" "${distname}" + cleanup_dist + diff_dirs dist.old dist +} + +main "${@}" diff --git a/external/bsd/kyua-testers/share/Makefile b/external/bsd/kyua-testers/share/Makefile new file mode 100644 index 000000000..bc7993f5e --- /dev/null +++ b/external/bsd/kyua-testers/share/Makefile @@ -0,0 +1,5 @@ +# $NetBSD: Makefile,v 1.2 2013/02/23 14:58:12 jmmv Exp $ + +SUBDIR= doc man + +.include diff --git a/external/bsd/kyua-testers/share/doc/Makefile b/external/bsd/kyua-testers/share/doc/Makefile new file mode 100644 index 000000000..897c128d4 --- /dev/null +++ b/external/bsd/kyua-testers/share/doc/Makefile @@ -0,0 +1,5 @@ +# $NetBSD: Makefile,v 1.1 2013/02/24 03:12:59 jmmv Exp $ + +SUBDIR= kyua-testers + +.include diff --git a/external/bsd/kyua-testers/share/doc/kyua-testers/Makefile b/external/bsd/kyua-testers/share/doc/kyua-testers/Makefile new file mode 100644 index 000000000..ae17e1be1 --- /dev/null +++ b/external/bsd/kyua-testers/share/doc/kyua-testers/Makefile @@ -0,0 +1,16 @@ +# $NetBSD: Makefile,v 1.1 2013/02/24 03:12:59 jmmv Exp $ + +.include + +SRCDIR= ${NETBSDSRCDIR}/external/bsd/kyua-testers/dist +.PATH: ${SRCDIR} + +.if ${MKSHARE} != "no" +.PATH: ${SRCDIR} + +FILESDIR= /usr/share/doc/kyua-testers +FILESMODE= 444 +FILES= AUTHORS COPYING NEWS README +.endif + +.include diff --git a/external/bsd/kyua-testers/share/man/Makefile b/external/bsd/kyua-testers/share/man/Makefile new file mode 100644 index 000000000..7b6b1060f --- /dev/null +++ b/external/bsd/kyua-testers/share/man/Makefile @@ -0,0 +1,5 @@ +# $NetBSD: Makefile,v 1.1 2013/02/19 06:04:43 jmmv Exp $ + +SUBDIR= man1 man5 + +.include diff --git a/external/bsd/kyua-testers/share/man/man1/Makefile b/external/bsd/kyua-testers/share/man/man1/Makefile new file mode 100644 index 000000000..76e151fff --- /dev/null +++ b/external/bsd/kyua-testers/share/man/man1/Makefile @@ -0,0 +1,15 @@ +# $NetBSD: Makefile,v 1.1 2013/02/19 06:04:44 jmmv Exp $ + +SRCDIR= ${NETBSDSRCDIR}/external/bsd/kyua-testers/dist +.PATH: ${SRCDIR} + +MAN= kyua-tester.1 + +CLEANFILES+= kyua-tester.1 +kyua-tester.1: kyua-tester.1.in + sed -e 's,__PACKAGE__,kyua-testers,g' \ + -e 's,__TMPDIR__,/tmp,g' \ + <${.ALLSRC} >${.TARGET}.tmp + mv ${.TARGET}.tmp ${.TARGET} + +.include diff --git a/external/bsd/kyua-testers/share/man/man5/Makefile b/external/bsd/kyua-testers/share/man/man5/Makefile new file mode 100644 index 000000000..ef474aec9 --- /dev/null +++ b/external/bsd/kyua-testers/share/man/man5/Makefile @@ -0,0 +1,9 @@ +# $NetBSD: Makefile,v 1.1 2013/02/19 06:04:44 jmmv Exp $ + +SRCDIR= ${NETBSDSRCDIR}/external/bsd/kyua-testers/dist +.PATH: ${SRCDIR} + +MAN= kyua-tester-list.5 +MAN+= kyua-tester-result.5 + +.include diff --git a/external/bsd/kyua-testers/tests/Makefile b/external/bsd/kyua-testers/tests/Makefile new file mode 100644 index 000000000..5d5f75094 --- /dev/null +++ b/external/bsd/kyua-testers/tests/Makefile @@ -0,0 +1,5 @@ +# $NetBSD: Makefile,v 1.1 2013/02/19 06:04:44 jmmv Exp $ + +SUBDIR= kyua-testers + +.include diff --git a/external/bsd/kyua-testers/tests/kyua-testers/Makefile b/external/bsd/kyua-testers/tests/kyua-testers/Makefile new file mode 100644 index 000000000..ce80e201f --- /dev/null +++ b/external/bsd/kyua-testers/tests/kyua-testers/Makefile @@ -0,0 +1,48 @@ +# $NetBSD: Makefile,v 1.1 2013/02/19 06:04:44 jmmv Exp $ + +.include + +TESTSDIR= ${TESTSBASE}/kyua-testers + +SRCDIR= ${NETBSDSRCDIR}/external/bsd/kyua-testers/dist +.PATH: ${SRCDIR} + +CPPFLAGS+= -DHAVE_CONFIG_H +CPPFLAGS+= -DTESTERSDIR=\"/usr/libexec\" +CPPFLAGS+= -I${.CURDIR}/../../lib/libtester +CPPFLAGS+= -I${SRCDIR} + +PRIVATELIBDIR!= cd ${.CURDIR}/../../lib; ${PRINTOBJDIR} +.for lib in atf_tester tester +LDADD+= ${PRIVATELIBDIR}/lib${lib}/lib${lib}.a +DPADD+= ${PRIVATELIBDIR}/lib${lib}/lib${lib}.a +.endfor + +TESTS_C= atf_list_test +TESTS_C+= atf_result_test +TESTS_C+= atf_inttest +TESTS_C+= cli_test +TESTS_C+= env_test +TESTS_C+= error_test +#LSC FIXME: Requires tmpfs to work correctly, maybe a workaround +# with a ramdisk may be used. +#TESTS_C+= fs_test +TESTS_C+= plain_inttest +TESTS_C+= result_test +TESTS_C+= run_test +TESTS_C+= stacktrace_test +TESTS_C+= text_test + +PROGS= atf_helpers +BINDIR.atf_helpers= ${TESTSDIR} +MAN.atf_helpers= # empty +LDADD.atf_helpers= -latf-c++ -latf-c +DPADD.atf_helpers= ${LIBATF_CXX} ${LIBATF_C} +PROGS+= plain_helpers +BINDIR.plain_helpers= ${TESTSDIR} +MAN.plain_helpers= # empty +PROGS+= stacktrace_helper +BINDIR.stacktrace_helper= ${TESTSDIR} +MAN.stacktrace_helper= # empty + +.include diff --git a/external/bsd/lutok/Makefile b/external/bsd/lutok/Makefile new file mode 100644 index 000000000..f70faee9f --- /dev/null +++ b/external/bsd/lutok/Makefile @@ -0,0 +1,5 @@ +# $NetBSD: Makefile,v 1.1 2013/02/16 21:29:45 jmmv Exp $ + +SUBDIR= lib .WAIT share tests + +.include diff --git a/external/bsd/lutok/dist/AUTHORS b/external/bsd/lutok/dist/AUTHORS new file mode 100644 index 000000000..0f707683a --- /dev/null +++ b/external/bsd/lutok/dist/AUTHORS @@ -0,0 +1 @@ +* Julio Merino diff --git a/external/bsd/lutok/dist/Atffile b/external/bsd/lutok/dist/Atffile new file mode 100644 index 000000000..c822fdd0c --- /dev/null +++ b/external/bsd/lutok/dist/Atffile @@ -0,0 +1,11 @@ +Content-Type: application/X-atf-atffile; version="1" + +prop: test-suite = lutok + +tp: c_gate_test +tp: debug_test +tp: examples_test +tp: exceptions_test +tp: operations_test +tp: stack_cleaner_test +tp: state_test diff --git a/external/bsd/lutok/dist/COPYING b/external/bsd/lutok/dist/COPYING new file mode 100644 index 000000000..be29aafc5 --- /dev/null +++ b/external/bsd/lutok/dist/COPYING @@ -0,0 +1,27 @@ +Copyright 2011, 2012 Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +* Neither the name of Google Inc. nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/external/bsd/lutok/dist/Kyuafile b/external/bsd/lutok/dist/Kyuafile new file mode 100644 index 000000000..48c912dab --- /dev/null +++ b/external/bsd/lutok/dist/Kyuafile @@ -0,0 +1,11 @@ +syntax("kyuafile", 1) + +test_suite("lutok") + +atf_test_program{name="c_gate_test"} +atf_test_program{name="debug_test"} +atf_test_program{name="examples_test"} +atf_test_program{name="exceptions_test"} +atf_test_program{name="operations_test"} +atf_test_program{name="stack_cleaner_test"} +atf_test_program{name="state_test"} diff --git a/external/bsd/lutok/dist/NEWS b/external/bsd/lutok/dist/NEWS new file mode 100644 index 000000000..d1920e5cf --- /dev/null +++ b/external/bsd/lutok/dist/NEWS @@ -0,0 +1,19 @@ +Changes in version 0.2 +====================== + +Released on 2012/05/30. + +* New global constants: globals_index. + +* New methods added to the state class: get_metafield, get_metatable, + insert, push_value, raw_get and raw_set. + +* Acknowledged that Lua 5.2 is currently not supported. + + +Changes in version 0.1 +====================== + +Released on 2012/01/29. + +* This is the first public release of the Lutok package. diff --git a/external/bsd/lutok/dist/README b/external/bsd/lutok/dist/README new file mode 100644 index 000000000..95e23ff8c --- /dev/null +++ b/external/bsd/lutok/dist/README @@ -0,0 +1,27 @@ +Lutok is a lightweight C++ API library for Lua. + +Lutok provides thin C++ wrappers around the Lua C API to ease the +interaction between C++ and Lua. These wrappers make intensive use of +RAII to prevent resource leakage, expose C++-friendly data types, report +errors by means of exceptions and ensure that the Lua stack is always +left untouched in the face of errors. The library also provides a small +subset of miscellaneous utility functions built on top of the wrappers. + +Lutok focuses on providing a clean and safe C++ interface; the drawback +is that it is not suitable for performance-critical environments. In +order to implement error-safe C++ wrappers on top of a Lua C binary +library, Lutok adds several layers or abstraction and error checking +that go against the original spirit of the Lua C API and thus degrade +performance. + +For further information on the contents of this distribution file, +please refer to the following other documents: + +* AUTHORS: List of authors and contributors to this project. +* COPYING: License information. +* INSTALL: Compilation and installation instructions. +* NEWS: List of major changes between formal releases. + +For general project information, please visit: + + http://code.google.com/p/lutok/ diff --git a/external/bsd/lutok/dist/c_gate.cpp b/external/bsd/lutok/dist/c_gate.cpp new file mode 100644 index 000000000..dde366e2d --- /dev/null +++ b/external/bsd/lutok/dist/c_gate.cpp @@ -0,0 +1,76 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "c_gate.hpp" +#include "state.ipp" + + +/// Creates a new gateway to an existing C++ Lua state. +/// +/// \param state_ The state to connect to. This object must remain alive while +/// the newly-constructed state_c_gate is alive. +lutok::state_c_gate::state_c_gate(state& state_) : + _state(state_) +{ +} + + +/// Destructor. +/// +/// Destroying this object has no implications on the life cycle of the Lua +/// state. Only the corresponding state object controls when the Lua state is +/// closed. +lutok::state_c_gate::~state_c_gate(void) +{ +} + + +/// Creates a C++ state for a C Lua state. +/// +/// \warning The created state object does NOT own the C state. You must take +/// care to properly destroy the input lua_State when you are done with it to +/// not leak resources. +/// +/// \param raw_state The raw state to wrap temporarily. +/// +/// \return The wrapped state without strong ownership on the input state. +lutok::state +lutok::state_c_gate::connect(lua_State* raw_state) +{ + return state(static_cast< void* >(raw_state)); +} + + +/// Returns the C native Lua state. +/// +/// \return A native lua_State object holding the Lua C API state. +lua_State* +lutok::state_c_gate::c_state(void) +{ + return static_cast< lua_State* >(_state.raw_state()); +} diff --git a/external/bsd/lutok/dist/c_gate.hpp b/external/bsd/lutok/dist/c_gate.hpp new file mode 100644 index 000000000..36bc9c228 --- /dev/null +++ b/external/bsd/lutok/dist/c_gate.hpp @@ -0,0 +1,71 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file c_gate.hpp +/// Provides direct access to the C state of the Lua wrappers. + +#if !defined(LUTOK_C_GATE_HPP) +#define LUTOK_C_GATE_HPP + +#include + +namespace lutok { + + +class state; + + +/// Gateway to the raw C state of Lua. +/// +/// This class provides a mechanism to muck with the internals of the state +/// wrapper class. Client code may wish to do so if Lutok is missing some +/// features of the performance of Lutok in a particular situation is not +/// reasonable. +/// +/// \warning The use of this class is discouraged. By using this class, you are +/// entering the world of unsafety. Anything you do through the objects exposed +/// through this class will not be controlled by RAII patterns not validated in +/// any other way, so you can end up corrupting the Lua state and later get +/// crashes on otherwise perfectly-valid C++ code. +class state_c_gate { + /// The C++ state that this class wraps. + state& _state; + +public: + state_c_gate(state&); + ~state_c_gate(void); + + static state connect(lua_State*); + + lua_State* c_state(void); +}; + + +} // namespace lutok + +#endif // !defined(LUTOK_C_GATE_HPP) diff --git a/external/bsd/lutok/dist/c_gate_test.cpp b/external/bsd/lutok/dist/c_gate_test.cpp new file mode 100644 index 000000000..59115534b --- /dev/null +++ b/external/bsd/lutok/dist/c_gate_test.cpp @@ -0,0 +1,74 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "c_gate.hpp" + +#include +#include + +#include "state.ipp" +#include "test_utils.hpp" + + +ATF_TEST_CASE_WITHOUT_HEAD(connect); +ATF_TEST_CASE_BODY(connect) +{ + lua_State* raw_state = lua_open(); + ATF_REQUIRE(raw_state != NULL); + + { + lutok::state state = lutok::state_c_gate::connect(raw_state); + lua_pushinteger(raw(state), 123); + } + // If the wrapper object had closed the Lua state, we could very well crash + // here. + ATF_REQUIRE_EQ(123, lua_tointeger(raw_state, -1)); + + lua_close(raw_state); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(c_state); +ATF_TEST_CASE_BODY(c_state) +{ + lutok::state state; + state.push_integer(5); + { + lutok::state_c_gate gate(state); + lua_State* raw_state = gate.c_state(); + ATF_REQUIRE_EQ(5, lua_tointeger(raw_state, -1)); + } + state.pop(1); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, c_state); + ATF_ADD_TEST_CASE(tcs, connect); +} diff --git a/external/bsd/lutok/dist/debug.cpp b/external/bsd/lutok/dist/debug.cpp new file mode 100644 index 000000000..e0a0b5eb2 --- /dev/null +++ b/external/bsd/lutok/dist/debug.cpp @@ -0,0 +1,192 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include + +#include + +#include +#include +#include +#include + + +/// Internal implementation for lutok::debug. +struct lutok::debug::impl { + /// The Lua internal debug state. + lua_Debug lua_debug; +}; + + +/// Constructor for an empty debug structure. +lutok::debug::debug(void) : + _pimpl(new impl()) +{ +} + + +/// Destructor. +lutok::debug::~debug(void) +{ +} + + +/// Wrapper around lua_getinfo. +/// +/// \param s The Lua state. +/// \param what_ The second parameter to lua_getinfo. +/// +/// \warning Terminates execution if there is not enough memory to manipulate +/// the Lua stack. +void +lutok::debug::get_info(state& s, const std::string& what_) +{ + lua_State* raw_state = state_c_gate(s).c_state(); + + if (lua_getinfo(raw_state, what_.c_str(), &_pimpl->lua_debug) == 0) + throw lutok::api_error::from_stack(s, "lua_getinfo"); +} + + +/// Wrapper around lua_getstack. +/// +/// \param s The Lua state. +/// \param level The second parameter to lua_getstack. +void +lutok::debug::get_stack(state& s, const int level) +{ + lua_State* raw_state = state_c_gate(s).c_state(); + + lua_getstack(raw_state, level, &_pimpl->lua_debug); +} + + +/// Accessor for the 'event' field of lua_Debug. +/// +/// \return Returns the 'event' field of the internal lua_Debug structure. +int +lutok::debug::event(void) const +{ + return _pimpl->lua_debug.event; +} + + +/// Accessor for the 'name' field of lua_Debug. +/// +/// \return Returns the 'name' field of the internal lua_Debug structure. +std::string +lutok::debug::name(void) const +{ + assert(_pimpl->lua_debug.name != NULL); + return _pimpl->lua_debug.name; +} + + +/// Accessor for the 'namewhat' field of lua_Debug. +/// +/// \return Returns the 'namewhat' field of the internal lua_Debug structure. +std::string +lutok::debug::name_what(void) const +{ + assert(_pimpl->lua_debug.namewhat != NULL); + return _pimpl->lua_debug.namewhat; +} + + +/// Accessor for the 'what' field of lua_Debug. +/// +/// \return Returns the 'what' field of the internal lua_Debug structure. +std::string +lutok::debug::what(void) const +{ + assert(_pimpl->lua_debug.what != NULL); + return _pimpl->lua_debug.what; +} + + +/// Accessor for the 'source' field of lua_Debug. +/// +/// \return Returns the 'source' field of the internal lua_Debug structure. +std::string +lutok::debug::source(void) const +{ + assert(_pimpl->lua_debug.source != NULL); + return _pimpl->lua_debug.source; +} + + +/// Accessor for the 'currentline' field of lua_Debug. +/// +/// \return Returns the 'currentline' field of the internal lua_Debug structure. +int +lutok::debug::current_line(void) const +{ + return _pimpl->lua_debug.currentline; +} + + +/// Accessor for the 'nups' field of lua_Debug. +/// +/// \return Returns the 'nups' field of the internal lua_Debug structure. +int +lutok::debug::n_ups(void) const +{ + return _pimpl->lua_debug.nups; +} + + +/// Accessor for the 'linedefined' field of lua_Debug. +/// +/// \return Returns the 'linedefined' field of the internal lua_Debug structure. +int +lutok::debug::line_defined(void) const +{ + return _pimpl->lua_debug.linedefined; +} + + +/// Accessor for the 'lastlinedefined' field of lua_Debug. +/// +/// \return Returns the 'lastlinedefined' field of the internal lua_Debug +/// structure. +int +lutok::debug::last_line_defined(void) const +{ + return _pimpl->lua_debug.lastlinedefined; +} + + +/// Accessor for the 'short_src' field of lua_Debug. +/// +/// \return Returns the 'short_src' field of the internal lua_Debug structure. +std::string +lutok::debug::short_src(void) const +{ + assert(_pimpl->lua_debug.short_src != NULL); + return _pimpl->lua_debug.short_src; +} diff --git a/external/bsd/lutok/dist/debug.hpp b/external/bsd/lutok/dist/debug.hpp new file mode 100644 index 000000000..d566032c5 --- /dev/null +++ b/external/bsd/lutok/dist/debug.hpp @@ -0,0 +1,83 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file debug.hpp +/// Provides the debug wrapper class for the Lua C debug state. + +#if !defined(LUTOK_DEBUG_HPP) +#define LUTOK_DEBUG_HPP + +#include +#include + + +namespace lutok { + + +class state; + + +/// A model for the Lua debug state. +/// +/// This extremely-simple class provides a mechanism to hide the internals of +/// the C native lua_Debug type, exposing its internal fields using friendlier +/// C++ types. +/// +/// This class also acts as a complement to the state class by exposing any +/// state-related functions as methods of this function. For example, while it +/// might seem that get_info() belongs in state, we expose it from here because +/// its result is really mutating a debug object, not the state object. +class debug { + struct impl; + + /// Pointer to the shared internal implementation. + std::tr1::shared_ptr< impl > _pimpl; + +public: + debug(void); + ~debug(void); + + void get_info(state&, const std::string&); + void get_stack(state&, const int); + + int event(void) const; + std::string name(void) const; + std::string name_what(void) const; + std::string what(void) const; + std::string source(void) const; + int current_line(void) const; + int n_ups(void) const; + int line_defined(void) const; + int last_line_defined(void) const; + std::string short_src(void) const; +}; + + +} // namespace lutok + +#endif // !defined(LUTOK_DEBUG_HPP) diff --git a/external/bsd/lutok/dist/debug_test.cpp b/external/bsd/lutok/dist/debug_test.cpp new file mode 100644 index 000000000..a88b892d0 --- /dev/null +++ b/external/bsd/lutok/dist/debug_test.cpp @@ -0,0 +1,68 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "debug.hpp" + +#include +#include + +#include "state.ipp" +#include "test_utils.hpp" + + +ATF_TEST_CASE_WITHOUT_HEAD(get_info); +ATF_TEST_CASE_BODY(get_info) +{ + lutok::state state; + ATF_REQUIRE(luaL_dostring(raw(state), "\n\nfunction hello() end\n" + "return hello") == 0); + lutok::debug debug; + debug.get_info(state, ">S"); + ATF_REQUIRE_EQ(3, debug.line_defined()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(get_stack); +ATF_TEST_CASE_BODY(get_stack) +{ + lutok::state state; + ATF_REQUIRE(luaL_dostring(raw(state), "error('Hello')") == 1); + lutok::debug debug; + debug.get_stack(state, 0); + lua_pop(raw(state), 1); + // Not sure if we can actually validate anything here, other than we did not + // crash... (because get_stack only is supposed to update internal values of + // the debug structure). +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, get_info); + ATF_ADD_TEST_CASE(tcs, get_stack); +} diff --git a/external/bsd/lutok/dist/examples/bindings.cpp b/external/bsd/lutok/dist/examples/bindings.cpp new file mode 100644 index 000000000..5ebf373f3 --- /dev/null +++ b/external/bsd/lutok/dist/examples/bindings.cpp @@ -0,0 +1,133 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file examples/bindings.cpp +/// Showcases how to define Lua functions from C++ code. +/// +/// A major selling point of Lua is that it is very easy too hook native C and +/// C++ functions into the runtime environment so that Lua can call them. The +/// purpose of this example program is to show how this is done by using Lutok. + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + +/// Calculates the factorial of a given number. +/// +/// \param i The postivie number to calculate the factorial of. +/// +/// \return The factorial of i. +static int +factorial(const int i) +{ + assert(i >= 0); + + if (i == 0) + return 1; + else + return i * factorial(i - 1); +} + + +/// A custom factorial function for Lua. +/// +/// \pre stack(-1) contains the number to calculate the factorial of. +/// \post stack(-1) contains the result of the operation. +/// +/// \param state The Lua state from which to get the function arguments and into +/// which to push the results. +/// +/// \return The number of results pushed onto the stack, i.e. 1. +/// +/// \throw std::runtime_error If the input parameters are invalid. Note that +/// Lutok will convert this exception to lutok::error. +static int +lua_factorial(lutok::state& state) +{ + if (!state.is_number()) + throw std::runtime_error("Argument to factorial must be an integer"); + const int i = state.to_integer(); + if (i < 0) + throw std::runtime_error("Argument to factorial must be positive"); + state.push_integer(factorial(i)); + return 1; +} + + +/// Program's entry point. +/// +/// \param argc Length of argv. Must be 2. +/// \param argv Command-line arguments to the program. The first argument to +/// the tool has to be a number. +/// +/// \return A system exit code. +int +main(int argc, char** argv) +{ + if (argc != 2) { + std::cerr << "Usage: bindings \n"; + return EXIT_FAILURE; + } + + // Create a new Lua session and load the print() function. + lutok::state state; + state.open_base(); + + // Construct a 'module' that contains an entry point to our native factorial + // function. A module is just a Lua table that contains a mapping of names + // to functions. Instead of creating a module by using our create_module() + // helper function, we could have used push_cxx_function on the state to + // define the function ourselves. + std::map< std::string, lutok::cxx_function > module; + module["factorial"] = lua_factorial; + lutok::create_module(state, "native", module); + + // Use a little Lua script to call our native factorial function providing + // it the first argument passed to the program. Note that this will error + // out in a controlled manner if the passed argument is not an integer. The + // important thing to notice is that the exception comes from our own C++ + // binding and that it has been converted to a lutok::error. + std::ostringstream script; + script << "print(native.factorial(" << argv[1] << "))"; + try { + lutok::do_string(state, script.str()); + return EXIT_SUCCESS; + } catch (const lutok::error& e) { + std::cerr << "ERROR: " << e.what() << '\n'; + return EXIT_FAILURE; + } +} diff --git a/external/bsd/lutok/dist/examples/hello.cpp b/external/bsd/lutok/dist/examples/hello.cpp new file mode 100644 index 000000000..40afdd572 --- /dev/null +++ b/external/bsd/lutok/dist/examples/hello.cpp @@ -0,0 +1,58 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file examples/hello.cpp +/// Minimal example using Lua code to print a traditional hello-world message. + +#include + +#include + + +/// Program's entry point. +/// +/// \return A system exit code. +int +main(void) +{ + // Initializes a new Lua state. Every Lua state is independent from each + // other. + lutok::state state; + + // Loads the standard library into the Lua state. Among many other + // functions, this gives us access to print(), which is used below. + state.open_base(); + + // Pushes the print() function into the Lua stack, then its only argument, + // and then proceeds to execute it within the Lua state. + state.get_global("print"); + state.push_string("Hello, world!"); + state.pcall(1, 0, 0); + + return EXIT_SUCCESS; +} diff --git a/external/bsd/lutok/dist/examples/interpreter.cpp b/external/bsd/lutok/dist/examples/interpreter.cpp new file mode 100644 index 000000000..00383f23c --- /dev/null +++ b/external/bsd/lutok/dist/examples/interpreter.cpp @@ -0,0 +1,83 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file examples/interpreter.cpp +/// Implementation of a basic command-line Lua interpreter. + +#include +#include +#include + +#include +#include +#include + + +/// Executes a Lua statement provided by the user with error checking. +/// +/// \param state The Lua state in which to process the statement. +/// \param line The textual statement provided by the user. +static void +run_statement(lutok::state& state, const std::string& line) +{ + try { + // This utility function allows us to feed a given piece of Lua code to + // the interpreter and process it. The piece of code can include + // multiple statements separated by a semicolon or by a newline + // character. + lutok::do_string(state, line); + } catch (const lutok::error& error) { + std::cerr << "ERROR: " << error.what() << '\n'; + } +} + + +/// Program's entry point. +/// +/// \return A system exit code. +int +main(void) +{ + // Create a new session and load some standard libraries. + lutok::state state; + state.open_base(); + state.open_string(); + state.open_table(); + + for (;;) { + std::cout << "lua> "; + std::cout.flush(); + + std::string line; + if (!std::getline(std::cin, line).good()) + break; + run_statement(state, line); + } + + return EXIT_SUCCESS; +} diff --git a/external/bsd/lutok/dist/examples/raii.cpp b/external/bsd/lutok/dist/examples/raii.cpp new file mode 100644 index 000000000..6b8fca9c7 --- /dev/null +++ b/external/bsd/lutok/dist/examples/raii.cpp @@ -0,0 +1,125 @@ +// Copyright 2012 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file examples/raii.cpp +/// Demonstrates how RAII helps in keeping the Lua state consistent. +/// +/// One of the major complains that is raised against the Lua C API is that it +/// is very hard to ensure it remains consistent during the execution of the +/// program. In the case of native C code, there exist many tools that help the +/// developer catch memory leaks, access to uninitialized variables, etc. +/// However, when using the Lua C API, none of these tools can validate that, +/// for example, the Lua stack remains balanced across calls. +/// +/// Enter RAII. The RAII pattern, intensively applied by Lutok, helps the +/// developer in maintaining the Lua state consistent at all times in a +/// transparent manner. This example program attempts to illustrate this. + +#include +#include +#include +#include + +#include +#include +#include + + +/// Prints the string-typed field of a table. +/// +/// If the field contains a string, this function prints its value. If the +/// field contains any other type, this prints an error message. +/// +/// \pre The top of the Lua stack in 'state' references a table. +/// +/// \param state The Lua state. +/// \param field The name of the string-typed field. +static void +print_table_field(lutok::state& state, const std::string& field) +{ + assert(state.is_table()); + + // Bring in some RAII magic: the stack_cleaner object captures the current + // height of the Lua stack at this point. Whenever the object goes out of + // scope, it will pop as many entries from the stack as necessary to restore + // the stack to its previous level. + // + // This ensures that, no matter how we exit the function, we do not leak + // objects in the stack. + lutok::stack_cleaner cleaner(state); + + // Stack contents: -1: table. + state.push_string(field); + // Stack contents: -2: table, -1: field name. + state.get_table(); + // Stack contents: -2: table, -1: field value. + + if (!state.is_string()) { + std::cout << "The field " << field << " does not contain a string\n"; + // Stack contents: -2: table, -1: field value. + // + // This is different than when we started! We should pop our extra + // value from the stack at this point. However, it is extremely common + // for software to have bugs (in this case, leaks) in error paths, + // mostly because such code paths are rarely exercised. + // + // By using the stack_cleaner object, we can be confident that the Lua + // stack will be cleared for us at this point, no matter what happened + // earlier on the stack nor how we exit the function. + return; + } + + std::cout << "String in field " << field << ": " << state.to_string() + << '\n'; + // A well-behaved program explicitly pops anything extra from the stack to + // return it to its original state. Mostly for clarity. + state.pop(1); + + // Stack contents: -1: table. Same as when we started. +} + + +/// Program's entry point. +/// +/// \return A system exit code. +int +main(void) +{ + lutok::state state; + state.open_base(); + + lutok::do_string(state, "example = {foo='hello', bar=123, baz='bye'}"); + + state.get_global("example"); + print_table_field(state, "foo"); + print_table_field(state, "bar"); + print_table_field(state, "baz"); + state.pop(1); + + return EXIT_SUCCESS; +} diff --git a/external/bsd/lutok/dist/examples_test.sh b/external/bsd/lutok/dist/examples_test.sh new file mode 100644 index 000000000..d638abf09 --- /dev/null +++ b/external/bsd/lutok/dist/examples_test.sh @@ -0,0 +1,114 @@ +#! __ATF_SH__ +# Copyright 2012 Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Google Inc. nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +ExamplesDir="__EXAMPLESDIR__" +LibDir="__LIBDIR__" + + +make_example() { + cp "${ExamplesDir}/Makefile" "${ExamplesDir}/${1}.cpp" . + make "${1}" + + # Ensure that the binary we just built can find liblutok. This is + # needed because the lutok.pc file (which the Makefile used above + # queries) does not provide rpaths to the installed library and + # therefore the binary may not be able to locate it. Hardcoding the + # rpath flags into lutok.pc is non-trivial because we simply don't + # have any knowledge about what the correct flag to set an rpath is. + # + # Additionally, setting rpaths is not always the right thing to do. + # For example, pkgsrc will automatically change lutok.pc to add the + # missing rpath, in which case this is unnecessary. But in the case + # of Fedora, adding rpaths goes against the packaging guidelines. + if [ -n "${LD_LIBRARY_PATH}" ]; then + export LD_LIBRARY_PATH="${LibDir}:${LD_LIBRARY_PATH}" + else + export LD_LIBRARY_PATH="${LibDir}" + fi +} + + +example_test_case() { + local name="${1}"; shift + + atf_test_case "${name}" + eval "${name}_head() { \ + atf_set 'require.files' '${ExamplesDir}/${name}.cpp'; \ + atf_set 'require.progs' 'make pkg-config'; \ + }" + eval "${name}_body() { \ + make_example '${name}'; \ + ${name}_validate; \ + }" +} + + +example_test_case bindings +bindings_validate() { + atf_check -s exit:0 -o inline:'120\n' ./bindings 5 + atf_check -s exit:1 -e match:'Argument.*must be an integer' ./bindings foo + atf_check -s exit:1 -e match:'Argument.*must be positive' ./bindings -5 +} + + +example_test_case hello +hello_validate() { + atf_check -s exit:0 -o inline:'Hello, world!\n' ./hello +} + + +example_test_case interpreter +interpreter_validate() { + cat >script.lua <expout < + +#include + +#include "c_gate.hpp" +#include "exceptions.hpp" +#include "state.ipp" + + +/// Constructs a new error with a plain-text message. +/// +/// \param message The plain-text error message. +lutok::error::error(const std::string& message) : + std::runtime_error(message) +{ +} + + +/// Destructor for the error. +lutok::error::~error(void) throw() +{ +} + + +/// Constructs a new error. +/// +/// \param api_function_ The name of the API function that caused the error. +/// \param message The plain-text error message provided by Lua. +lutok::api_error::api_error(const std::string& api_function_, + const std::string& message) : + error(message), + _api_function(api_function_) +{ +} + + +/// Destructor for the error. +lutok::api_error::~api_error(void) throw() +{ +} + + +/// Constructs a new api_error with the message on the top of the Lua stack. +/// +/// \pre There is an error message on the top of the stack. +/// \post The error message is popped from the stack. +/// +/// \param state_ The Lua state. +/// \param api_function_ The name of the Lua API function that caused the error. +/// +/// \return A new api_error with the popped message. +lutok::api_error +lutok::api_error::from_stack(state& state_, const std::string& api_function_) +{ + lua_State* raw_state = lutok::state_c_gate(state_).c_state(); + + assert(lua_isstring(raw_state, -1)); + const std::string message = lua_tostring(raw_state, -1); + lua_pop(raw_state, 1); + return lutok::api_error(api_function_, message); +} + + +/// Gets the name of the Lua API function that caused this error. +/// +/// \return The name of the function. +const std::string& +lutok::api_error::api_function(void) const +{ + return _api_function; +} + + +/// Constructs a new error. +/// +/// \param filename_ The file that count not be found. +lutok::file_not_found_error::file_not_found_error( + const std::string& filename_) : + error("File '" + filename_ + "' not found"), + _filename(filename_) +{ +} + + +/// Destructor for the error. +lutok::file_not_found_error::~file_not_found_error(void) throw() +{ +} + + +/// Gets the name of the file that could not be found. +/// +/// \return The name of the file. +const std::string& +lutok::file_not_found_error::filename(void) const +{ + return _filename; +} diff --git a/external/bsd/lutok/dist/exceptions.hpp b/external/bsd/lutok/dist/exceptions.hpp new file mode 100644 index 000000000..93a794873 --- /dev/null +++ b/external/bsd/lutok/dist/exceptions.hpp @@ -0,0 +1,83 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file exceptions.hpp +/// Exception types raised by lutok. + +#if !defined(LUTOK_EXCEPTIONS_HPP) +#define LUTOK_EXCEPTIONS_HPP + +#include +#include + +namespace lutok { + + +class state; + + +/// Base exception for lua errors. +class error : public std::runtime_error { +public: + explicit error(const std::string&); + virtual ~error(void) throw(); +}; + + +/// Exception for errors raised by the Lua API library. +class api_error : public error { + /// Name of the Lua C API function that caused the error. + std::string _api_function; + +public: + explicit api_error(const std::string&, const std::string&); + virtual ~api_error(void) throw(); + + static api_error from_stack(state&, const std::string&); + + const std::string& api_function(void) const; +}; + + +/// File not found error. +class file_not_found_error : public error { + /// Name of the not-found file. + std::string _filename; + +public: + explicit file_not_found_error(const std::string&); + virtual ~file_not_found_error(void) throw(); + + const std::string& filename(void) const; +}; + + +} // namespace lutok + + +#endif // !defined(LUTOK_EXCEPTIONS_HPP) diff --git a/external/bsd/lutok/dist/exceptions_test.cpp b/external/bsd/lutok/dist/exceptions_test.cpp new file mode 100644 index 000000000..807127cf4 --- /dev/null +++ b/external/bsd/lutok/dist/exceptions_test.cpp @@ -0,0 +1,88 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "exceptions.hpp" + +#include + +#include + +#include "state.ipp" + + +ATF_TEST_CASE_WITHOUT_HEAD(error); +ATF_TEST_CASE_BODY(error) +{ + const lutok::error e("Some text"); + ATF_REQUIRE(std::strcmp("Some text", e.what()) == 0); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(api_error__explicit); +ATF_TEST_CASE_BODY(api_error__explicit) +{ + const lutok::api_error e("some_function", "Some text"); + ATF_REQUIRE(std::strcmp("Some text", e.what()) == 0); + ATF_REQUIRE_EQ("some_function", e.api_function()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(api_error__from_stack); +ATF_TEST_CASE_BODY(api_error__from_stack) +{ + lutok::state state; + state.push_integer(123); + state.push_string("The error message"); + const lutok::api_error e = lutok::api_error::from_stack(state, + "the_function"); + ATF_REQUIRE_EQ(1, state.get_top()); + ATF_REQUIRE_EQ(123, state.to_integer()); + state.pop(1); + ATF_REQUIRE(std::strcmp("The error message", e.what()) == 0); + ATF_REQUIRE_EQ("the_function", e.api_function()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(file_not_found_error); +ATF_TEST_CASE_BODY(file_not_found_error) +{ + const lutok::file_not_found_error e("missing-file"); + ATF_REQUIRE(std::strcmp("File 'missing-file' not found", e.what()) == 0); + ATF_REQUIRE_EQ("missing-file", e.filename()); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, error); + + ATF_ADD_TEST_CASE(tcs, api_error__explicit); + ATF_ADD_TEST_CASE(tcs, api_error__from_stack); + + ATF_ADD_TEST_CASE(tcs, file_not_found_error); +} diff --git a/external/bsd/lutok/dist/lutok.pc.in b/external/bsd/lutok/dist/lutok.pc.in new file mode 100644 index 000000000..2886dfc3e --- /dev/null +++ b/external/bsd/lutok/dist/lutok.pc.in @@ -0,0 +1,8 @@ +includedir=__INCLUDEDIR__ +libdir=__LIBDIR__ + +Name: lutok +Description: Lightweight C++ API for Lua +Version: __VERSION__ +Cflags: __LUA_CFLAGS__ -I${includedir} +Libs: __LUA_LIBS__ -L${libdir} -llutok diff --git a/external/bsd/lutok/dist/operations.cpp b/external/bsd/lutok/dist/operations.cpp new file mode 100644 index 000000000..b47d4a22e --- /dev/null +++ b/external/bsd/lutok/dist/operations.cpp @@ -0,0 +1,143 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include + +#include + +#include "exceptions.hpp" +#include "operations.hpp" +#include "stack_cleaner.hpp" +#include "state.hpp" + + +/// Creates a module: i.e. a table with a set of methods in it. +/// +/// \param s The Lua state. +/// \param name The name of the module to create. +/// \param members The list of member functions to add to the module. +void +lutok::create_module(state& s, const std::string& name, + const std::map< std::string, cxx_function >& members) +{ + stack_cleaner cleaner(s); + s.new_table(); + for (std::map< std::string, cxx_function >::const_iterator + iter = members.begin(); iter != members.end(); iter++) { + s.push_string((*iter).first); + s.push_cxx_function((*iter).second); + s.set_table(-3); + } + s.set_global(name); +} + + +/// Loads and processes a Lua file. +/// +/// This is a replacement for luaL_dofile but with proper error reporting +/// and stack control. +/// +/// \param s The Lua state. +/// \param file The file to load. +/// \param nresults The number of results to expect; -1 for any. +/// +/// \return The number of results left on the stack. +/// +/// \throw error If there is a problem processing the file. +unsigned int +lutok::do_file(state& s, const std::string& file, const int nresults) +{ + assert(nresults >= -1); + const int height = s.get_top(); + + stack_cleaner cleaner(s); + try { + s.load_file(file); + s.pcall(0, nresults == -1 ? LUA_MULTRET : nresults, 0); + } catch (const lutok::api_error& e) { + throw lutok::error("Failed to load Lua file '" + file + "': " + + e.what()); + } + cleaner.forget(); + + const int actual_results = s.get_top() - height; + assert(nresults == -1 || actual_results == nresults); + assert(actual_results >= 0); + return static_cast< unsigned int >(actual_results); +} + + +/// Processes a Lua script. +/// +/// This is a replacement for luaL_dostring but with proper error reporting +/// and stack control. +/// +/// \param s The Lua state. +/// \param str The string to process. +/// \param nresults The number of results to expect; -1 for any. +/// +/// \return The number of results left on the stack. +/// +/// \throw error If there is a problem processing the string. +unsigned int +lutok::do_string(state& s, const std::string& str, const int nresults) +{ + assert(nresults >= -1); + const int height = s.get_top(); + + stack_cleaner cleaner(s); + try { + s.load_string(str); + s.pcall(0, nresults == -1 ? LUA_MULTRET : nresults, 0); + } catch (const lutok::api_error& e) { + throw lutok::error("Failed to process Lua string '" + str + "': " + + e.what()); + } + cleaner.forget(); + + const int actual_results = s.get_top() - height; + assert(nresults == -1 || actual_results == nresults); + assert(actual_results >= 0); + return static_cast< unsigned int >(actual_results); +} + + +/// Convenience function to evaluate a Lua expression. +/// +/// \param s The Lua state. +/// \param expression The textual expression to evaluate. +/// \param nresults The number of results to leave on the stack. Must be +/// positive. +/// +/// \throw api_error If there is a problem evaluating the expression. +void +lutok::eval(state& s, const std::string& expression, const int nresults) +{ + assert(nresults > 0); + do_string(s, "return " + expression, nresults); +} diff --git a/external/bsd/lutok/dist/operations.hpp b/external/bsd/lutok/dist/operations.hpp new file mode 100644 index 000000000..d99832a10 --- /dev/null +++ b/external/bsd/lutok/dist/operations.hpp @@ -0,0 +1,53 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file operations.hpp +/// Extra generic functions to interact with Lua. + +#if !defined(LUTOK_OPERATIONS_HPP) +#define LUTOK_OPERATIONS_HPP + +#include +#include +#include + +#include + +namespace lutok { + + +void create_module(state&, const std::string&, + const std::map< std::string, cxx_function >&); +unsigned int do_file(state&, const std::string&, const int = 0); +unsigned int do_string(state&, const std::string&, const int = 0); +void eval(state&, const std::string&, const int = 1); + + +} // namespace lutok + +#endif // !defined(LUTOK_OPERATIONS_HPP) diff --git a/external/bsd/lutok/dist/operations_test.cpp b/external/bsd/lutok/dist/operations_test.cpp new file mode 100644 index 000000000..5363054ec --- /dev/null +++ b/external/bsd/lutok/dist/operations_test.cpp @@ -0,0 +1,296 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "operations.hpp" + +#include + +#include + +#include "exceptions.hpp" +#include "state.ipp" +#include "test_utils.hpp" + + +namespace { + + +/// Addition function for injection into Lua. +/// +/// \pre stack(-2) The first summand. +/// \pre stack(-1) The second summand. +/// \post stack(-1) The result of the sum. +/// +/// \param state The Lua state. +/// +/// \return The number of results (1). +static int +hook_add(lutok::state& state) +{ + state.push_integer(state.to_integer(-1) + state.to_integer(-2)); + return 1; +} + + +/// Multiplication function for injection into Lua. +/// +/// \pre stack(-2) The first factor. +/// \pre stack(-1) The second factor. +/// \post stack(-1) The product. +/// +/// \param state The Lua state. +/// +/// \return The number of results (1). +static int +hook_multiply(lutok::state& state) +{ + state.push_integer(state.to_integer(-1) * state.to_integer(-2)); + return 1; +} + + +} // anonymous namespace + + +ATF_TEST_CASE_WITHOUT_HEAD(create_module__empty); +ATF_TEST_CASE_BODY(create_module__empty) +{ + lutok::state state; + std::map< std::string, lutok::cxx_function > members; + lutok::create_module(state, "my_math", members); + + state.open_base(); + lutok::do_string(state, "return next(my_math) == nil", 1); + ATF_REQUIRE(state.to_boolean()); + state.pop(1); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(create_module__one); +ATF_TEST_CASE_BODY(create_module__one) +{ + lutok::state state; + std::map< std::string, lutok::cxx_function > members; + members["add"] = hook_add; + lutok::create_module(state, "my_math", members); + + lutok::do_string(state, "return my_math.add(10, 20)", 1); + ATF_REQUIRE_EQ(30, state.to_integer()); + state.pop(1); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(create_module__many); +ATF_TEST_CASE_BODY(create_module__many) +{ + lutok::state state; + std::map< std::string, lutok::cxx_function > members; + members["add"] = hook_add; + members["multiply"] = hook_multiply; + members["add2"] = hook_add; + lutok::create_module(state, "my_math", members); + + lutok::do_string(state, "return my_math.add(10, 20)", 1); + ATF_REQUIRE_EQ(30, state.to_integer()); + lutok::do_string(state, "return my_math.multiply(10, 20)", 1); + ATF_REQUIRE_EQ(200, state.to_integer()); + lutok::do_string(state, "return my_math.add2(20, 30)", 1); + ATF_REQUIRE_EQ(50, state.to_integer()); + state.pop(3); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(do_file__any_results); +ATF_TEST_CASE_BODY(do_file__any_results) +{ + std::ofstream output("test.lua"); + output << "return 10, 20, 30\n"; + output.close(); + + lutok::state state; + ATF_REQUIRE_EQ(3, lutok::do_file(state, "test.lua", -1)); + ATF_REQUIRE_EQ(3, state.get_top()); + ATF_REQUIRE_EQ(10, state.to_integer(-3)); + ATF_REQUIRE_EQ(20, state.to_integer(-2)); + ATF_REQUIRE_EQ(30, state.to_integer(-1)); + state.pop(3); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(do_file__no_results); +ATF_TEST_CASE_BODY(do_file__no_results) +{ + std::ofstream output("test.lua"); + output << "return 10, 20, 30\n"; + output.close(); + + lutok::state state; + ATF_REQUIRE_EQ(0, lutok::do_file(state, "test.lua")); + ATF_REQUIRE_EQ(0, state.get_top()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(do_file__many_results); +ATF_TEST_CASE_BODY(do_file__many_results) +{ + std::ofstream output("test.lua"); + output << "return 10, 20, 30\n"; + output.close(); + + lutok::state state; + ATF_REQUIRE_EQ(2, lutok::do_file(state, "test.lua", 2)); + ATF_REQUIRE_EQ(2, state.get_top()); + ATF_REQUIRE_EQ(10, state.to_integer(-2)); + ATF_REQUIRE_EQ(20, state.to_integer(-1)); + state.pop(2); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(do_file__not_found); +ATF_TEST_CASE_BODY(do_file__not_found) +{ + lutok::state state; + stack_balance_checker checker(state); + ATF_REQUIRE_THROW_RE(lutok::file_not_found_error, "missing.lua", + lutok::do_file(state, "missing.lua")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(do_file__error); +ATF_TEST_CASE_BODY(do_file__error) +{ + std::ofstream output("test.lua"); + output << "a b c\n"; + output.close(); + + lutok::state state; + stack_balance_checker checker(state); + ATF_REQUIRE_THROW_RE(lutok::error, "Failed to load Lua file 'test.lua'", + lutok::do_file(state, "test.lua")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(do_string__any_results); +ATF_TEST_CASE_BODY(do_string__any_results) +{ + lutok::state state; + ATF_REQUIRE_EQ(3, lutok::do_string(state, "return 10, 20, 30", -1)); + ATF_REQUIRE_EQ(3, state.get_top()); + ATF_REQUIRE_EQ(10, state.to_integer(-3)); + ATF_REQUIRE_EQ(20, state.to_integer(-2)); + ATF_REQUIRE_EQ(30, state.to_integer(-1)); + state.pop(3); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(do_string__no_results); +ATF_TEST_CASE_BODY(do_string__no_results) +{ + lutok::state state; + ATF_REQUIRE_EQ(0, lutok::do_string(state, "return 10, 20, 30")); + ATF_REQUIRE_EQ(0, state.get_top()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(do_string__many_results); +ATF_TEST_CASE_BODY(do_string__many_results) +{ + lutok::state state; + ATF_REQUIRE_EQ(2, lutok::do_string(state, "return 10, 20, 30", 2)); + ATF_REQUIRE_EQ(2, state.get_top()); + ATF_REQUIRE_EQ(10, state.to_integer(-2)); + ATF_REQUIRE_EQ(20, state.to_integer(-1)); + state.pop(2); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(do_string__error); +ATF_TEST_CASE_BODY(do_string__error) +{ + lutok::state state; + stack_balance_checker checker(state); + ATF_REQUIRE_THROW_RE(lutok::error, "Failed to process Lua string 'a b c'", + lutok::do_string(state, "a b c")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(eval__one_result); +ATF_TEST_CASE_BODY(eval__one_result) +{ + lutok::state state; + stack_balance_checker checker(state); + lutok::eval(state, "3 + 10"); + ATF_REQUIRE_EQ(13, state.to_integer()); + state.pop(1); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(eval__many_results); +ATF_TEST_CASE_BODY(eval__many_results) +{ + lutok::state state; + stack_balance_checker checker(state); + lutok::eval(state, "5, 8, 10", 3); + ATF_REQUIRE_EQ(5, state.to_integer(-3)); + ATF_REQUIRE_EQ(8, state.to_integer(-2)); + ATF_REQUIRE_EQ(10, state.to_integer(-1)); + state.pop(3); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(eval__error); +ATF_TEST_CASE_BODY(eval__error) +{ + lutok::state state; + stack_balance_checker checker(state); + ATF_REQUIRE_THROW(lutok::error, + lutok::eval(state, "non_existent.method()")); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, create_module__empty); + ATF_ADD_TEST_CASE(tcs, create_module__one); + ATF_ADD_TEST_CASE(tcs, create_module__many); + + ATF_ADD_TEST_CASE(tcs, do_file__any_results); + ATF_ADD_TEST_CASE(tcs, do_file__no_results); + ATF_ADD_TEST_CASE(tcs, do_file__many_results); + ATF_ADD_TEST_CASE(tcs, do_file__not_found); + ATF_ADD_TEST_CASE(tcs, do_file__error); + + ATF_ADD_TEST_CASE(tcs, do_string__any_results); + ATF_ADD_TEST_CASE(tcs, do_string__no_results); + ATF_ADD_TEST_CASE(tcs, do_string__many_results); + ATF_ADD_TEST_CASE(tcs, do_string__error); + + ATF_ADD_TEST_CASE(tcs, eval__one_result); + ATF_ADD_TEST_CASE(tcs, eval__many_results); + ATF_ADD_TEST_CASE(tcs, eval__error); +} diff --git a/external/bsd/lutok/dist/stack_cleaner.cpp b/external/bsd/lutok/dist/stack_cleaner.cpp new file mode 100644 index 000000000..419e55a12 --- /dev/null +++ b/external/bsd/lutok/dist/stack_cleaner.cpp @@ -0,0 +1,91 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include +#include + +#include "stack_cleaner.hpp" +#include "state.ipp" + + +/// Internal implementation for lutok::stack_cleaner. +struct lutok::stack_cleaner::impl { + /// Reference to the Lua state this stack_cleaner refers to. + state& state_ref; + + /// The depth of the Lua stack to be restored. + unsigned int original_depth; + + /// Constructor. + /// + /// \param state_ref_ Reference to the Lua state. + /// \param original_depth_ The depth of the Lua stack. + impl(state& state_ref_, const unsigned int original_depth_) : + state_ref(state_ref_), + original_depth(original_depth_) + { + } +}; + + +/// Creates a new stack cleaner. +/// +/// This gathers the current height of the stack so that extra elements can be +/// popped during destruction. +/// +/// \param state_ The Lua state. +lutok::stack_cleaner::stack_cleaner(state& state_) : + _pimpl(new impl(state_, state_.get_top())) +{ +} + + +/// Pops any values from the stack not known at construction time. +/// +/// \pre The current height of the stack must be equal or greater to the height +/// of the stack when this object was instantiated. +lutok::stack_cleaner::~stack_cleaner(void) +{ + const unsigned int current_depth = _pimpl->state_ref.get_top(); + assert(current_depth >= _pimpl->original_depth); + const unsigned int diff = current_depth - _pimpl->original_depth; + if (diff > 0) + _pimpl->state_ref.pop(diff); +} + + +/// Forgets about any elements currently in the stack. +/// +/// This allows a function to return values on the stack because all the +/// elements that are currently in the stack will not be touched during +/// destruction when the function is called. +void +lutok::stack_cleaner::forget(void) +{ + _pimpl->original_depth = _pimpl->state_ref.get_top(); +} diff --git a/external/bsd/lutok/dist/stack_cleaner.hpp b/external/bsd/lutok/dist/stack_cleaner.hpp new file mode 100644 index 000000000..cd3e14686 --- /dev/null +++ b/external/bsd/lutok/dist/stack_cleaner.hpp @@ -0,0 +1,93 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file stack_cleaner.hpp +/// Provides the stack_cleaner class. + +#if !defined(LUTOK_STACK_CLEANER_HPP) +#define LUTOK_STACK_CLEANER_HPP + +#include + +#include + +namespace lutok { + + +/// A RAII model for values on the Lua stack. +/// +/// At creation time, the object records the current depth of the Lua stack and, +/// during destruction, restores the recorded depth by popping as many stack +/// entries as required. As a corollary, the stack can only grow during the +/// lifetime of a stack_cleaner object (or shrink, but cannot become shorter +/// than the depth recorded at creation time). +/// +/// Use this class as follows: +/// +/// state s; +/// { +/// stack_cleaner cleaner1(s); +/// s.push_integer(3); +/// s.push_integer(5); +/// ... do stuff here ... +/// for (...) { +/// stack_cleaner cleaner2(s); +/// s.load_string("..."); +/// s.pcall(0, 1, 0); +/// ... do stuff here ... +/// } +/// // cleaner2 destroyed; the result of pcall is gone. +/// } +/// // cleaner1 destroyed; the integers 3 and 5 are gone. +/// +/// You must give a name to the instantiated objects even if they cannot be +/// accessed later. Otherwise, the instance will be destroyed right away and +/// will not have the desired effect. +class stack_cleaner { + struct impl; + + /// Pointer to the shared internal implementation. + std::auto_ptr< impl > _pimpl; + + /// Disallow copies. + stack_cleaner(const stack_cleaner&); + + /// Disallow assignment. + stack_cleaner& operator=(const stack_cleaner&); + +public: + stack_cleaner(state&); + ~stack_cleaner(void); + + void forget(void); +}; + + +} // namespace lutok + +#endif // !defined(LUTOK_STACK_CLEANER_HPP) diff --git a/external/bsd/lutok/dist/stack_cleaner_test.cpp b/external/bsd/lutok/dist/stack_cleaner_test.cpp new file mode 100644 index 000000000..c378ba398 --- /dev/null +++ b/external/bsd/lutok/dist/stack_cleaner_test.cpp @@ -0,0 +1,108 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "stack_cleaner.hpp" + +#include + + +ATF_TEST_CASE_WITHOUT_HEAD(empty); +ATF_TEST_CASE_BODY(empty) +{ + lutok::state state; + { + lutok::stack_cleaner cleaner(state); + ATF_REQUIRE_EQ(0, state.get_top()); + } + ATF_REQUIRE_EQ(0, state.get_top()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(some); +ATF_TEST_CASE_BODY(some) +{ + lutok::state state; + { + lutok::stack_cleaner cleaner(state); + state.push_integer(15); + ATF_REQUIRE_EQ(1, state.get_top()); + state.push_integer(30); + ATF_REQUIRE_EQ(2, state.get_top()); + } + ATF_REQUIRE_EQ(0, state.get_top()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(nested); +ATF_TEST_CASE_BODY(nested) +{ + lutok::state state; + { + lutok::stack_cleaner cleaner1(state); + state.push_integer(10); + ATF_REQUIRE_EQ(1, state.get_top()); + ATF_REQUIRE_EQ(10, state.to_integer()); + { + lutok::stack_cleaner cleaner2(state); + state.push_integer(20); + ATF_REQUIRE_EQ(2, state.get_top()); + ATF_REQUIRE_EQ(20, state.to_integer(-1)); + ATF_REQUIRE_EQ(10, state.to_integer(-2)); + } + ATF_REQUIRE_EQ(1, state.get_top()); + ATF_REQUIRE_EQ(10, state.to_integer()); + } + ATF_REQUIRE_EQ(0, state.get_top()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(forget); +ATF_TEST_CASE_BODY(forget) +{ + lutok::state state; + { + lutok::stack_cleaner cleaner(state); + state.push_integer(15); + state.push_integer(30); + cleaner.forget(); + state.push_integer(60); + ATF_REQUIRE_EQ(3, state.get_top()); + } + ATF_REQUIRE_EQ(2, state.get_top()); + ATF_REQUIRE_EQ(30, state.to_integer()); + state.pop(2); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, empty); + ATF_ADD_TEST_CASE(tcs, some); + ATF_ADD_TEST_CASE(tcs, nested); + ATF_ADD_TEST_CASE(tcs, forget); +} diff --git a/external/bsd/lutok/dist/state.cpp b/external/bsd/lutok/dist/state.cpp new file mode 100644 index 000000000..a7d095208 --- /dev/null +++ b/external/bsd/lutok/dist/state.cpp @@ -0,0 +1,862 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +extern "C" { +#include +} + +#include +#include + +#include "c_gate.hpp" +#include "exceptions.hpp" +#include "state.ipp" + + +namespace { + + +/// Wrapper around lua_getglobal to run in a protected environment. +/// +/// \pre stack(-1) is the name of the global to get. +/// \post stack(-1) is the value of the global. +/// +/// \param state The Lua C API state. +/// +/// \return The number of return values pushed onto the stack. +static int +protected_getglobal(lua_State* state) +{ + lua_getglobal(state, lua_tostring(state, -1)); + return 1; +} + + +/// Wrapper around lua_gettable to run in a protected environment. +/// +/// \pre stack(-2) is the table to get the element from. +/// \pre stack(-1) is the table index. +/// \post stack(-1) is the value of stack(-2)[stack(-1)]. +/// +/// \param state The Lua C API state. +/// +/// \return The number of return values pushed onto the stack. +static int +protected_gettable(lua_State* state) +{ + lua_gettable(state, -2); + return 1; +} + + +/// Wrapper around lua_next to run in a protected environment. +/// +/// \pre stack(-2) is the table to get the next element from. +/// \pre stack(-1) is the last processed key. +/// \post stack(-1) is the value of next(stack(-2), stack(-1)). +/// +/// \param state The Lua C API state. +/// +/// \return The number of return values pushed onto the stack. +static int +protected_next(lua_State* state) +{ + const int more = lua_next(state, -2) != 0; + lua_pushboolean(state, more); + return more ? 3 : 1; +} + + +/// Wrapper around lua_setglobal to run in a protected environment. +/// +/// \pre stack(-2) is the name of the global to set. +/// \pre stack(-1) is the value to set the global to. +/// +/// \param state The Lua C API state. +/// +/// \return The number of return values pushed onto the stack. +static int +protected_setglobal(lua_State* state) +{ + lua_setglobal(state, lua_tostring(state, -2)); + return 0; +} + + +/// Wrapper around lua_settable to run in a protected environment. +/// +/// \pre stack(-3) is the table to set the element into. +/// \pre stack(-2) is the table index. +/// \pre stack(-1) is the value to set. +/// +/// \param state The Lua C API state. +/// +/// \return The number of return values pushed onto the stack. +static int +protected_settable(lua_State* state) +{ + lua_settable(state, -3); + return 0; +} + + +/// Calls a C++ Lua function from a C calling environment. +/// +/// Any errors reported by the C++ function are caught and reported to the +/// caller as Lua errors. +/// +/// \param function The C++ function to call. +/// \param raw_state The raw Lua state. +/// +/// \return The number of return values pushed onto the Lua stack by the +/// function. +static int +call_cxx_function_from_c(lutok::cxx_function function, + lua_State* raw_state) throw() +{ + char error_buf[1024]; + + try { + lutok::state state = lutok::state_c_gate::connect(raw_state); + return function(state); + } catch (const std::exception& e) { + std::strncpy(error_buf, e.what(), sizeof(error_buf)); + } catch (...) { + std::strncpy(error_buf, "Unhandled exception in Lua C++ hook", + sizeof(error_buf)); + } + error_buf[sizeof(error_buf) - 1] = '\0'; + // We raise the Lua error from outside the try/catch context and we use + // a stack-based buffer to hold the message to ensure that we do not leak + // any C++ objects (and, as a likely result, memory) when Lua performs its + // longjmp. + return luaL_error(raw_state, "%s", error_buf); +} + + +/// Lua glue to call a C++ closure. +/// +/// This Lua binding is actually a closure that we have constructed from the +/// state.push_cxx_closure() method. The closure contains the same upvalues +/// provided by the user plus an extra upvalue that contains the address of the +/// C++ function we have to call. All we do here is safely delegate the +/// execution to the wrapped C++ closure. +/// +/// \param raw_state The Lua C API state. +/// +/// \return The number of return values of the called closure. +static int +cxx_closure_trampoline(lua_State* raw_state) +{ + lutok::state state = lutok::state_c_gate::connect(raw_state); + + int nupvalues; + { + lua_Debug debug; + lua_getstack(raw_state, 0, &debug); + lua_getinfo(raw_state, "u", &debug); + nupvalues = debug.nups; + } + + lutok::cxx_function* function = state.to_userdata< lutok::cxx_function >( + state.upvalue_index(nupvalues)); + return call_cxx_function_from_c(*function, raw_state); +} + + +/// Lua glue to call a C++ function. +/// +/// This Lua binding is actually a closure that we have constructed from the +/// state.push_cxx_function() method. The closure has a single upvalue that +/// contains the address of the C++ function we have to call. All we do here is +/// safely delegate the execution to the wrapped C++ function. +/// +/// \param raw_state The Lua C API state. +/// +/// \return The number of return values of the called function. +static int +cxx_function_trampoline(lua_State* raw_state) +{ + lutok::state state = lutok::state_c_gate::connect(raw_state); + lutok::cxx_function* function = state.to_userdata< lutok::cxx_function >( + state.upvalue_index(1)); + return call_cxx_function_from_c(*function, raw_state); +} + + +} // anonymous namespace + + +const int lutok::globals_index = LUA_GLOBALSINDEX; + + +/// Internal implementation for lutok::state. +struct lutok::state::impl { + /// The Lua internal state. + lua_State* lua_state; + + /// Whether we own the state or not (to decide if we close it). + bool owned; + + /// Constructor. + /// + /// \param lua_ The Lua internal state. + /// \param owned_ Whether we own the state or not. + impl(lua_State* lua_, bool owned_) : + lua_state(lua_), + owned(owned_) + { + } +}; + + +/// Initializes the Lua state. +/// +/// You must share the same state object alongside the lifetime of your Lua +/// session. As soon as the object is destroyed, the session is terminated. +lutok::state::state(void) +{ + lua_State* lua = lua_open(); + if (lua == NULL) + throw lutok::error("lua open failed"); + _pimpl.reset(new impl(lua, true)); +} + + +/// Initializes the Lua state from an existing raw state. +/// +/// Instances constructed using this method do NOT own the raw state. This +/// means that, on exit, the state will not be destroyed. +/// +/// \param raw_state_ The raw Lua state to wrap. +lutok::state::state(void* raw_state_) : + _pimpl(new impl(reinterpret_cast< lua_State* >(raw_state_), false)) +{ +} + + +/// Destructor for the Lua state. +/// +/// Closes the session unless it has already been closed by calling the +/// close() method. It is recommended to explicitly close the session in the +/// code. +lutok::state::~state(void) +{ + if (_pimpl->owned && _pimpl->lua_state != NULL) + close(); +} + + +/// Terminates this Lua session. +/// +/// It is recommended to call this instead of relying on the destructor to do +/// the cleanup, but it is not a requirement to use close(). +/// +/// \pre close() has not yet been called. +/// \pre The Lua stack is empty. This is not truly necessary but ensures that +/// our code is consistent and clears the stack explicitly. +void +lutok::state::close(void) +{ + assert(_pimpl->lua_state != NULL); + assert(lua_gettop(_pimpl->lua_state) == 0); + lua_close(_pimpl->lua_state); + _pimpl->lua_state = NULL; +} + + +/// Wrapper around lua_getglobal. +/// +/// \param name The second parameter to lua_getglobal. +/// +/// \throw api_error If lua_getglobal fails. +/// +/// \warning Terminates execution if there is not enough memory to manipulate +/// the Lua stack. +void +lutok::state::get_global(const std::string& name) +{ + lua_pushcfunction(_pimpl->lua_state, protected_getglobal); + lua_pushstring(_pimpl->lua_state, name.c_str()); + if (lua_pcall(_pimpl->lua_state, 1, 1, 0) != 0) + throw lutok::api_error::from_stack(*this, "lua_getglobal"); +} + + +/// Wrapper around luaL_getmetafield. +/// +/// \param index The second parameter to luaL_getmetafield. +/// \param name The third parameter to luaL_getmetafield. +/// +/// \return The return value of luaL_getmetafield. +/// +/// \warning Terminates execution if there is not enough memory to manipulate +/// the Lua stack. +bool +lutok::state::get_metafield(const int index, const std::string& name) +{ + return luaL_getmetafield(_pimpl->lua_state, index, name.c_str()) != 0; +} + + +/// Wrapper around lua_getmetatable. +/// +/// \param index The second parameter to lua_getmetatable. +/// +/// \return The return value of lua_getmetatable. +bool +lutok::state::get_metatable(const int index) +{ + return lua_getmetatable(_pimpl->lua_state, index) != 0; +} + + +/// Wrapper around lua_gettable. +/// +/// \param index The second parameter to lua_gettable. +/// +/// \throw api_error If lua_gettable fails. +/// +/// \warning Terminates execution if there is not enough memory to manipulate +/// the Lua stack. +void +lutok::state::get_table(const int index) +{ + assert(lua_gettop(_pimpl->lua_state) >= 2); + lua_pushcfunction(_pimpl->lua_state, protected_gettable); + lua_pushvalue(_pimpl->lua_state, index < 0 ? index - 1 : index); + lua_pushvalue(_pimpl->lua_state, -3); + if (lua_pcall(_pimpl->lua_state, 2, 1, 0) != 0) + throw lutok::api_error::from_stack(*this, "lua_gettable"); + lua_remove(_pimpl->lua_state, -2); +} + + +/// Wrapper around lua_gettop. +/// +/// \return The return value of lua_gettop. +int +lutok::state::get_top(void) +{ + return lua_gettop(_pimpl->lua_state); +} + + +/// Wrapper around lua_insert. +/// +/// \param index The second parameter to lua_insert. +void +lutok::state::insert(const int index) +{ + lua_insert(_pimpl->lua_state, index); +} + + +/// Wrapper around lua_isboolean. +/// +/// \param index The second parameter to lua_isboolean. +/// +/// \return The return value of lua_isboolean. +bool +lutok::state::is_boolean(const int index) +{ + return lua_isboolean(_pimpl->lua_state, index); +} + + +/// Wrapper around lua_isfunction. +/// +/// \param index The second parameter to lua_isfunction. +/// +/// \return The return value of lua_isfunction. +bool +lutok::state::is_function(const int index) +{ + return lua_isfunction(_pimpl->lua_state, index); +} + + +/// Wrapper around lua_isnil. +/// +/// \param index The second parameter to lua_isnil. +/// +/// \return The return value of lua_isnil. +bool +lutok::state::is_nil(const int index) +{ + return lua_isnil(_pimpl->lua_state, index); +} + + +/// Wrapper around lua_isnumber. +/// +/// \param index The second parameter to lua_isnumber. +/// +/// \return The return value of lua_isnumber. +bool +lutok::state::is_number(const int index) +{ + return lua_isnumber(_pimpl->lua_state, index); +} + + +/// Wrapper around lua_isstring. +/// +/// \param index The second parameter to lua_isstring. +/// +/// \return The return value of lua_isstring. +bool +lutok::state::is_string(const int index) +{ + return lua_isstring(_pimpl->lua_state, index); +} + + +/// Wrapper around lua_istable. +/// +/// \param index The second parameter to lua_istable. +/// +/// \return The return value of lua_istable. +bool +lutok::state::is_table(const int index) +{ + return lua_istable(_pimpl->lua_state, index); +} + + +/// Wrapper around lua_isuserdata. +/// +/// \param index The second parameter to lua_isuserdata. +/// +/// \return The return value of lua_isuserdata. +bool +lutok::state::is_userdata(const int index) +{ + return lua_isuserdata(_pimpl->lua_state, index); +} + + +/// Wrapper around luaL_loadfile. +/// +/// \param file The second parameter to luaL_loadfile. +/// +/// \throw api_error If luaL_loadfile returns an error. +/// \throw file_not_found_error If the file cannot be accessed. +/// +/// \warning Terminates execution if there is not enough memory. +void +lutok::state::load_file(const std::string& file) +{ + if (!::access(file.c_str(), R_OK) == 0) + throw lutok::file_not_found_error(file); + if (luaL_loadfile(_pimpl->lua_state, file.c_str()) != 0) + throw lutok::api_error::from_stack(*this, "luaL_loadfile"); +} + + +/// Wrapper around luaL_loadstring. +/// +/// \param str The second parameter to luaL_loadstring. +/// +/// \throw api_error If luaL_loadstring returns an error. +/// +/// \warning Terminates execution if there is not enough memory. +void +lutok::state::load_string(const std::string& str) +{ + if (luaL_loadstring(_pimpl->lua_state, str.c_str()) != 0) + throw lutok::api_error::from_stack(*this, "luaL_loadstring"); +} + + +/// Wrapper around lua_newtable. +/// +/// \warning Terminates execution if there is not enough memory. +void +lutok::state::new_table(void) +{ + lua_newtable(_pimpl->lua_state); +} + + +/// Wrapper around lua_newuserdata. +/// +/// This is internal. The public type-safe interface of this method should be +/// used instead. +/// +/// \param size The second parameter to lua_newuserdata. +/// +/// \return The return value of lua_newuserdata. +/// +/// \warning Terminates execution if there is not enough memory. +void* +lutok::state::new_userdata_voidp(const size_t size) +{ + return lua_newuserdata(_pimpl->lua_state, size); +} + + +/// Wrapper around lua_next. +/// +/// \param index The second parameter to lua_next. +/// +/// \return True if there are more elements to process; false otherwise. +/// +/// \warning Terminates execution if there is not enough memory. +bool +lutok::state::next(const int index) +{ + assert(lua_istable(_pimpl->lua_state, index)); + assert(lua_gettop(_pimpl->lua_state) >= 1); + lua_pushcfunction(_pimpl->lua_state, protected_next); + lua_pushvalue(_pimpl->lua_state, index < 0 ? index - 1 : index); + lua_pushvalue(_pimpl->lua_state, -3); + if (lua_pcall(_pimpl->lua_state, 2, LUA_MULTRET, 0) != 0) + throw lutok::api_error::from_stack(*this, "lua_next"); + const bool more = lua_toboolean(_pimpl->lua_state, -1); + lua_pop(_pimpl->lua_state, 1); + if (more) + lua_remove(_pimpl->lua_state, -3); + else + lua_pop(_pimpl->lua_state, 1); + return more; +} + + +/// Wrapper around luaopen_base. +/// +/// \throw api_error If luaopen_base fails. +/// +/// \warning Terminates execution if there is not enough memory. +void +lutok::state::open_base(void) +{ + lua_pushcfunction(_pimpl->lua_state, luaopen_base); + if (lua_pcall(_pimpl->lua_state, 0, 0, 0) != 0) + throw lutok::api_error::from_stack(*this, "luaopen_base"); +} + + +/// Wrapper around luaopen_string. +/// +/// \throw api_error If luaopen_string fails. +/// +/// \warning Terminates execution if there is not enough memory. +void +lutok::state::open_string(void) +{ + lua_pushcfunction(_pimpl->lua_state, luaopen_string); + if (lua_pcall(_pimpl->lua_state, 0, 0, 0) != 0) + throw lutok::api_error::from_stack(*this, "luaopen_string"); +} + + +/// Wrapper around luaopen_table. +/// +/// \throw api_error If luaopen_table fails. +/// +/// \warning Terminates execution if there is not enough memory. +void +lutok::state::open_table(void) +{ + lua_pushcfunction(_pimpl->lua_state, luaopen_table); + if (lua_pcall(_pimpl->lua_state, 0, 0, 0) != 0) + throw lutok::api_error::from_stack(*this, "luaopen_table"); +} + + +/// Wrapper around lua_pcall. +/// +/// \param nargs The second parameter to lua_pcall. +/// \param nresults The third parameter to lua_pcall. +/// \param errfunc The fourth parameter to lua_pcall. +/// +/// \throw api_error If lua_pcall returns an error. +void +lutok::state::pcall(const int nargs, const int nresults, const int errfunc) +{ + if (lua_pcall(_pimpl->lua_state, nargs, nresults, errfunc) != 0) + throw lutok::api_error::from_stack(*this, "lua_pcall"); +} + + +/// Wrapper around lua_pop. +/// +/// \param count The second parameter to lua_pop. +void +lutok::state::pop(const int count) +{ + assert(count <= lua_gettop(_pimpl->lua_state)); + lua_pop(_pimpl->lua_state, count); + assert(lua_gettop(_pimpl->lua_state) >= 0); +} + + +/// Wrapper around lua_pushboolean. +/// +/// \param value The second parameter to lua_pushboolean. +void +lutok::state::push_boolean(const bool value) +{ + lua_pushboolean(_pimpl->lua_state, value ? 1 : 0); +} + + +/// Wrapper around lua_pushcclosure. +/// +/// This is not a pure wrapper around lua_pushcclosure because this has to do +/// extra magic to allow passing C++ functions instead of plain C functions. +/// +/// \param function The C++ function to be pushed as a closure. +/// \param nvalues The number of upvalues that the function receives. +void +lutok::state::push_cxx_closure(cxx_function function, const int nvalues) +{ + cxx_function *data = static_cast< cxx_function* >( + lua_newuserdata(_pimpl->lua_state, sizeof(cxx_function))); + *data = function; + lua_pushcclosure(_pimpl->lua_state, cxx_closure_trampoline, nvalues + 1); +} + + +/// Wrapper around lua_pushcfunction. +/// +/// This is not a pure wrapper around lua_pushcfunction because this has to do +/// extra magic to allow passing C++ functions instead of plain C functions. +/// +/// \param function The C++ function to be pushed. +void +lutok::state::push_cxx_function(cxx_function function) +{ + cxx_function *data = static_cast< cxx_function* >( + lua_newuserdata(_pimpl->lua_state, sizeof(cxx_function))); + *data = function; + lua_pushcclosure(_pimpl->lua_state, cxx_function_trampoline, 1); +} + + +/// Wrapper around lua_pushinteger. +/// +/// \param value The second parameter to lua_pushinteger. +void +lutok::state::push_integer(const int value) +{ + lua_pushinteger(_pimpl->lua_state, value); +} + + +/// Wrapper around lua_pushnil. +void +lutok::state::push_nil(void) +{ + lua_pushnil(_pimpl->lua_state); +} + + +/// Wrapper around lua_pushstring. +/// +/// \param str The second parameter to lua_pushstring. +/// +/// \warning Terminates execution if there is not enough memory. +void +lutok::state::push_string(const std::string& str) +{ + lua_pushstring(_pimpl->lua_state, str.c_str()); +} + + +/// Wrapper around lua_pushvalue. +/// +/// \param index The second parameter to lua_pushvalue. +void +lutok::state::push_value(const int index) +{ + lua_pushvalue(_pimpl->lua_state, index); +} + + +/// Wrapper around lua_rawget. +/// +/// \param index The second parameter to lua_rawget. +void +lutok::state::raw_get(const int index) +{ + lua_rawget(_pimpl->lua_state, index); +} + + +/// Wrapper around lua_rawset. +/// +/// \param index The second parameter to lua_rawset. +/// +/// \warning Terminates execution if there is not enough memory to manipulate +/// the Lua stack. +void +lutok::state::raw_set(const int index) +{ + lua_rawset(_pimpl->lua_state, index); +} + + +/// Wrapper around lua_setglobal. +/// +/// \param name The second parameter to lua_setglobal. +/// +/// \throw api_error If lua_setglobal fails. +/// +/// \warning Terminates execution if there is not enough memory to manipulate +/// the Lua stack. +void +lutok::state::set_global(const std::string& name) +{ + lua_pushcfunction(_pimpl->lua_state, protected_setglobal); + lua_pushstring(_pimpl->lua_state, name.c_str()); + lua_pushvalue(_pimpl->lua_state, -3); + if (lua_pcall(_pimpl->lua_state, 2, 0, 0) != 0) + throw lutok::api_error::from_stack(*this, "lua_setglobal"); + lua_pop(_pimpl->lua_state, 1); +} + + +/// Wrapper around lua_setmetatable. +/// +/// \param index The second parameter to lua_setmetatable. +void +lutok::state::set_metatable(const int index) +{ + lua_setmetatable(_pimpl->lua_state, index); +} + + +/// Wrapper around lua_settable. +/// +/// \param index The second parameter to lua_settable. +/// +/// \throw api_error If lua_settable fails. +/// +/// \warning Terminates execution if there is not enough memory to manipulate +/// the Lua stack. +void +lutok::state::set_table(const int index) +{ + lua_pushcfunction(_pimpl->lua_state, protected_settable); + lua_pushvalue(_pimpl->lua_state, index < 0 ? index - 1 : index); + lua_pushvalue(_pimpl->lua_state, -4); + lua_pushvalue(_pimpl->lua_state, -4); + if (lua_pcall(_pimpl->lua_state, 3, 0, 0) != 0) + throw lutok::api_error::from_stack(*this, "lua_settable"); + lua_pop(_pimpl->lua_state, 2); +} + + +/// Wrapper around lua_toboolean. +/// +/// \param index The second parameter to lua_toboolean. +/// +/// \return The return value of lua_toboolean. +bool +lutok::state::to_boolean(const int index) +{ + assert(is_boolean(index)); + return lua_toboolean(_pimpl->lua_state, index); +} + + +/// Wrapper around lua_tointeger. +/// +/// \param index The second parameter to lua_tointeger. +/// +/// \return The return value of lua_tointeger. +long +lutok::state::to_integer(const int index) +{ + assert(is_number(index)); + return lua_tointeger(_pimpl->lua_state, index); +} + + +/// Wrapper around lua_touserdata. +/// +/// This is internal. The public type-safe interface of this method should be +/// used instead. +/// +/// \param index The second parameter to lua_touserdata. +/// +/// \return The return value of lua_touserdata. +/// +/// \warning Terminates execution if there is not enough memory. +void* +lutok::state::to_userdata_voidp(const int index) +{ + return lua_touserdata(_pimpl->lua_state, index); +} + + + +/// Wrapper around lua_tostring. +/// +/// \param index The second parameter to lua_tostring. +/// +/// \return The return value of lua_tostring. +/// +/// \warning Terminates execution if there is not enough memory. +std::string +lutok::state::to_string(const int index) +{ + assert(is_string(index)); + const char *raw_string = lua_tostring(_pimpl->lua_state, index); + // Note that the creation of a string object below (explicit for clarity) + // implies that the raw string is duplicated and, henceforth, the string is + // safe even if the corresponding element is popped from the Lua stack. + return std::string(raw_string); +} + + +/// Wrapper around lua_upvalueindex. +/// +/// \param index The first parameter to lua_upvalueindex. +/// +/// \return The return value of lua_upvalueindex. +int +lutok::state::upvalue_index(const int index) +{ + return lua_upvalueindex(index); +} + + +/// Gets the internal lua_State object. +/// +/// \return The raw Lua state. This is returned as a void pointer to prevent +/// including the lua.hpp header file from our public interface. The only way +/// to call this method is by using the c_gate module, and c_gate takes care of +/// casting this object to the appropriate type. +void* +lutok::state::raw_state(void) +{ + return _pimpl->lua_state; +} diff --git a/external/bsd/lutok/dist/state.hpp b/external/bsd/lutok/dist/state.hpp new file mode 100644 index 000000000..9dd610ae9 --- /dev/null +++ b/external/bsd/lutok/dist/state.hpp @@ -0,0 +1,134 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file state.hpp +/// Provides the state wrapper class for the Lua C state. + +#if !defined(LUTOK_STATE_HPP) +#define LUTOK_STATE_HPP + +#include +#include + +namespace lutok { + + +class debug; +class state; + + +/// The type of a C++ function that can be bound into Lua. +/// +/// Functions of this type are free to raise exceptions. These will not +/// propagate into the Lua C API. However, any such exceptions will be reported +/// as a Lua error and their type will be lost. +typedef int (*cxx_function)(state&); + + +/// Stack index constant pointing to the globals table (_G). +extern const int globals_index; + + +/// A RAII model for the Lua state. +/// +/// This class holds the state of the Lua interpreter during its existence and +/// provides wrappers around several Lua library functions that operate on such +/// state. +/// +/// These wrapper functions differ from the C versions in that they use the +/// implicit state hold by the class, they use C++ types where appropriate and +/// they use exceptions to report errors. +/// +/// The wrappers intend to be as lightweight as possible but, in some +/// situations, they are pretty complex because they need to do extra work to +/// capture the errors reported by the Lua C API. We prefer having fine-grained +/// error control rather than efficiency, so this is OK. +class state { + struct impl; + + /// Pointer to the shared internal implementation. + std::tr1::shared_ptr< impl > _pimpl; + + void* new_userdata_voidp(const size_t); + void* to_userdata_voidp(const int); + + friend class state_c_gate; + explicit state(void*); + void* raw_state(void); + +public: + state(void); + ~state(void); + + void close(void); + void get_global(const std::string&); + bool get_metafield(const int, const std::string&); + bool get_metatable(const int = -1); + void get_table(const int = -2); + int get_top(void); + void insert(const int); + bool is_boolean(const int = -1); + bool is_function(const int = -1); + bool is_nil(const int = -1); + bool is_number(const int = -1); + bool is_string(const int = -1); + bool is_table(const int = -1); + bool is_userdata(const int = -1); + void load_file(const std::string&); + void load_string(const std::string&); + void new_table(void); + template< typename Type > Type* new_userdata(void); + bool next(const int = -2); + void open_base(void); + void open_string(void); + void open_table(void); + void pcall(const int, const int, const int); + void pop(const int); + void push_boolean(const bool); + void push_cxx_closure(cxx_function, const int); + void push_cxx_function(cxx_function); + void push_integer(const int); + void push_nil(void); + void push_string(const std::string&); + void push_value(const int = -1); + void raw_get(const int = -2); + void raw_set(const int = -3); + void set_global(const std::string&); + void set_metatable(const int = -2); + void set_table(const int = -3); + bool to_boolean(const int = -1); + long to_integer(const int = -1); + template< typename Type > Type* to_userdata(const int = -1); + std::string to_string(const int = -1); + int upvalue_index(const int); +}; + + +} // namespace lutok + +#endif // !defined(LUTOK_STATE_HPP) diff --git a/external/bsd/lutok/dist/state.ipp b/external/bsd/lutok/dist/state.ipp new file mode 100644 index 000000000..76f47a643 --- /dev/null +++ b/external/bsd/lutok/dist/state.ipp @@ -0,0 +1,67 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#if !defined(LUTOK_STATE_IPP) +#define LUTOK_STATE_IPP + +#include + +namespace lutok { + + +/// Wrapper around lua_newuserdata. +/// +/// This allocates an object as big as the size of the provided Type. +/// +/// \return The pointer to the allocated userdata object. +/// +/// \warning Terminates execution if there is not enough memory. +template< typename Type > +Type* +state::new_userdata(void) +{ + return static_cast< Type* >(new_userdata_voidp(sizeof(Type))); +} + + +/// Wrapper around lua_touserdata. +/// +/// \param index The second parameter to lua_touserdata. +/// +/// \return The return value of lua_touserdata. +template< typename Type > +Type* +state::to_userdata(const int index) +{ + return static_cast< Type* >(to_userdata_voidp(index)); +} + + +} // namespace lutok + +#endif // !defined(LUTOK_STATE_IPP) diff --git a/external/bsd/lutok/dist/state_test.cpp b/external/bsd/lutok/dist/state_test.cpp new file mode 100644 index 000000000..269de81f3 --- /dev/null +++ b/external/bsd/lutok/dist/state_test.cpp @@ -0,0 +1,1404 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "state.ipp" + +#include +#include +#include +#include + +#include +#include + +#include "c_gate.hpp" +#include "exceptions.hpp" +#include "test_utils.hpp" + + +// A note about the lutok::state tests. +// +// The methods of lutok::state are, in general, thin wrappers around the +// corresponding Lua C API methods. The tests below are simple unit tests that +// ensure that these functions just delegate the calls to the Lua library. We +// do not intend to test the validity of the methods themselves (that's the +// job of the Lua authors). That said, we test those conditions we rely on, +// such as the reporting of errors and the default values to the API. +// +// Lastly, for every test case that stresses a single lutok::state method, we +// only call that method directly. All other Lua state manipulation operations +// are performed by means of direct calls to the Lua C API. This is to ensure +// that the wrapped methods are really talking to Lua. + + +namespace { + + +/// Checks if a symbol is available. +/// +/// \param state The Lua state. +/// \param symbol The symbol to check for. +/// +/// \return True if the symbol is defined, false otherwise. +static bool +is_available(lutok::state& state, const char* symbol) +{ + luaL_loadstring(raw(state), (std::string("return ") + symbol).c_str()); + const bool ok = (lua_pcall(raw(state), 0, 1, 0) == 0 && + !lua_isnil(raw(state), -1)); + lua_pop(raw(state), 1); + std::cout << "Symbol " << symbol << (ok ? " found\n" : " not found\n"); + return ok; +} + + +/// Checks that no modules are present or that only one has been loaded. +/// +/// \post The test case terminates if there is any module present when expected +/// is empty or if there two modules loaded when expected is defined. +/// +/// \param state The Lua state. +/// \param expected The module to expect. Empty if no modules are allowed. +static void +check_modules(lutok::state& state, const std::string& expected) +{ + std::cout << "Checking loaded modules" << + (expected.empty() ? "" : (" (" + expected + " expected)")) << "\n"; + ATF_REQUIRE(!((expected == "base") ^ (is_available(state, "assert")))); + ATF_REQUIRE(!((expected == "string") ^ + (is_available(state, "string.byte")))); + ATF_REQUIRE(!((expected == "table") ^ + (is_available(state, "table.concat")))); +} + + +/// A C closure that returns its two integral upvalues. +/// +/// \post stack(-2) contains the first upvalue. +/// \post stack(-1) contains the second upvalue. +/// +/// \param raw_state The raw Lua state. +/// +/// \return The number of result values, i.e. 2. +static int +c_get_upvalues(lua_State* raw_state) +{ + lutok::state state = lutok::state_c_gate::connect(raw_state); + const int i1 = lua_tointeger(raw_state, state.upvalue_index(1)); + const int i2 = lua_tointeger(raw_state, state.upvalue_index(2)); + lua_pushinteger(raw_state, i1); + lua_pushinteger(raw_state, i2); + return 2; +} + + +/// A custom C++ multiply function with one of its factors on its closure. +/// +/// \pre stack(-1) contains the second factor. +/// \post stack(-1) contains the product of the two input factors. +/// +/// \param state The Lua state. +/// +/// \return The number of result values, i.e. 1. +static int +cxx_multiply_closure(lutok::state& state) +{ + const int f1 = lua_tointeger(raw(state), lua_upvalueindex(1)); + const int f2 = lua_tointeger(raw(state), -1); + lua_pushinteger(raw(state), f1 * f2); + return 1; +} + + +/// A custom C++ integral division function for Lua. +/// +/// \pre stack(-2) contains the dividend. +/// \pre stack(-1) contains the divisor. +/// \post stack(-2) contains the quotient of the division. +/// \post stack(-1) contains the remainder of the division. +/// +/// \param state The Lua state. +/// +/// \return The number of result values, i.e. 1. +/// +/// \throw std::runtime_error If the divisor is zero. +/// \throw std::string If the dividend or the divisor are negative. This is an +/// exception not derived from std::exception on purpose to ensure that the +/// C++ wrapping correctly captures any exception regardless of its type. +static int +cxx_divide(lutok::state& state) +{ + const int dividend = state.to_integer(-2); + const int divisor = state.to_integer(-1); + if (divisor == 0) + throw std::runtime_error("Divisor is 0"); + if (dividend < 0 || divisor < 0) + throw std::string("Cannot divide negative numbers"); + state.push_integer(dividend / divisor); + state.push_integer(dividend % divisor); + return 2; +} + + +/// A Lua function that raises a very long error message. +/// +/// \pre stack(-1) contains the length of the message to construct. +/// +/// \param state The Lua state. +/// +/// \return Never returns. +/// +/// \throw std::runtime_error Unconditionally, with an error message formed by +/// the repetition of 'A' as many times as requested. +static int +raise_long_error(lutok::state& state) +{ + const int length = state.to_integer(); + throw std::runtime_error(std::string(length, 'A').c_str()); +} + + +} // anonymous namespace + + +ATF_TEST_CASE_WITHOUT_HEAD(close); +ATF_TEST_CASE_BODY(close) +{ + lutok::state state; + state.close(); + // The destructor for state will run now. If it does a second close, we may + // crash, so let's see if we don't. +} + + +ATF_TEST_CASE_WITHOUT_HEAD(get_global__ok); +ATF_TEST_CASE_BODY(get_global__ok) +{ + lutok::state state; + ATF_REQUIRE(luaL_dostring(raw(state), "test_variable = 3") == 0); + state.get_global("test_variable"); + ATF_REQUIRE(lua_isnumber(raw(state), -1)); + lua_pop(raw(state), 1); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(get_global__fail); +ATF_TEST_CASE_BODY(get_global__fail) +{ + lutok::state state; + lua_pushinteger(raw(state), 3); + lua_replace(raw(state), LUA_GLOBALSINDEX); + REQUIRE_API_ERROR("lua_getglobal", state.get_global("test_variable")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(get_global__undefined); +ATF_TEST_CASE_BODY(get_global__undefined) +{ + lutok::state state; + state.get_global("test_variable"); + ATF_REQUIRE(lua_isnil(raw(state), -1)); + lua_pop(raw(state), 1); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(get_metafield__ok); +ATF_TEST_CASE_BODY(get_metafield__ok) +{ + lutok::state state; + luaL_openlibs(raw(state)); + ATF_REQUIRE(luaL_dostring(raw(state), "meta = { foo = 567 }; " + "t = {}; setmetatable(t, meta)") == 0); + lua_getglobal(raw(state), "t"); + ATF_REQUIRE(state.get_metafield(-1, "foo")); + ATF_REQUIRE(lua_isnumber(raw(state), -1)); + ATF_REQUIRE_EQ(567, lua_tointeger(raw(state), -1)); + lua_pop(raw(state), 2); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(get_metafield__undefined); +ATF_TEST_CASE_BODY(get_metafield__undefined) +{ + lutok::state state; + luaL_openlibs(raw(state)); + ATF_REQUIRE(luaL_dostring(raw(state), "meta = { foo = 567 }; " + "t = {}; setmetatable(t, meta)") == 0); + lua_getglobal(raw(state), "t"); + ATF_REQUIRE(!state.get_metafield(-1, "bar")); + lua_pop(raw(state), 1); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(get_metatable__top); +ATF_TEST_CASE_BODY(get_metatable__top) +{ + lutok::state state; + luaL_openlibs(raw(state)); + ATF_REQUIRE(luaL_dostring(raw(state), "meta = { foo = 567 }; " + "t = {}; setmetatable(t, meta)") == 0); + lua_getglobal(raw(state), "t"); + ATF_REQUIRE(state.get_metatable()); + ATF_REQUIRE(lua_istable(raw(state), -1)); + lua_pushstring(raw(state), "foo"); + lua_gettable(raw(state), -2); + ATF_REQUIRE(lua_isnumber(raw(state), -1)); + ATF_REQUIRE_EQ(567, lua_tointeger(raw(state), -1)); + lua_pop(raw(state), 3); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(get_metatable__explicit); +ATF_TEST_CASE_BODY(get_metatable__explicit) +{ + lutok::state state; + luaL_openlibs(raw(state)); + ATF_REQUIRE(luaL_dostring(raw(state), "meta = { foo = 567 }; " + "t = {}; setmetatable(t, meta)") == 0); + lua_getglobal(raw(state), "t"); + lua_pushinteger(raw(state), 5555); + ATF_REQUIRE(state.get_metatable(-2)); + ATF_REQUIRE(lua_istable(raw(state), -1)); + lua_pushstring(raw(state), "foo"); + lua_gettable(raw(state), -2); + ATF_REQUIRE(lua_isnumber(raw(state), -1)); + ATF_REQUIRE_EQ(567, lua_tointeger(raw(state), -1)); + lua_pop(raw(state), 4); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(get_metatable__undefined); +ATF_TEST_CASE_BODY(get_metatable__undefined) +{ + lutok::state state; + ATF_REQUIRE(luaL_dostring(raw(state), "t = {}") == 0); + lua_getglobal(raw(state), "t"); + ATF_REQUIRE(!state.get_metatable(-1)); + lua_pop(raw(state), 1); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(get_table__ok); +ATF_TEST_CASE_BODY(get_table__ok) +{ + lutok::state state; + ATF_REQUIRE(luaL_dostring(raw(state), "t = { a = 1, bar = 234 }") == 0); + lua_getglobal(raw(state), "t"); + lua_pushstring(raw(state), "bar"); + state.get_table(); + ATF_REQUIRE(lua_isnumber(raw(state), -1)); + ATF_REQUIRE_EQ(234, lua_tointeger(raw(state), -1)); + lua_pop(raw(state), 2); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(get_table__nil); +ATF_TEST_CASE_BODY(get_table__nil) +{ + lutok::state state; + lua_pushnil(raw(state)); + lua_pushinteger(raw(state), 1); + REQUIRE_API_ERROR("lua_gettable", state.get_table()); + ATF_REQUIRE_EQ(2, lua_gettop(raw(state))); + lua_pop(raw(state), 2); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(get_table__unknown_index); +ATF_TEST_CASE_BODY(get_table__unknown_index) +{ + lutok::state state; + ATF_REQUIRE(luaL_dostring(raw(state), + "the_table = { foo = 1, bar = 2 }") == 0); + lua_getglobal(raw(state), "the_table"); + lua_pushstring(raw(state), "baz"); + state.get_table(); + ATF_REQUIRE(lua_isnil(raw(state), -1)); + lua_pop(raw(state), 2); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(get_top); +ATF_TEST_CASE_BODY(get_top) +{ + lutok::state state; + ATF_REQUIRE_EQ(0, state.get_top()); + lua_pushinteger(raw(state), 3); + ATF_REQUIRE_EQ(1, state.get_top()); + lua_pushinteger(raw(state), 3); + ATF_REQUIRE_EQ(2, state.get_top()); + lua_pop(raw(state), 2); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(globals_index); +ATF_TEST_CASE_BODY(globals_index) +{ + lutok::state state; + ATF_REQUIRE(luaL_dostring(raw(state), "global_variable = 'hello'") == 0); + lua_pushvalue(raw(state), lutok::globals_index); + lua_pushstring(raw(state), "global_variable"); + lua_gettable(raw(state), -2); + ATF_REQUIRE(lua_isstring(raw(state), -1)); + ATF_REQUIRE(std::strcmp("hello", lua_tostring(raw(state), -1)) == 0); + lua_pop(raw(state), 2); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(insert); +ATF_TEST_CASE_BODY(insert) +{ + lutok::state state; + lua_pushinteger(raw(state), 1); + lua_pushinteger(raw(state), 2); + lua_pushinteger(raw(state), 3); + lua_pushinteger(raw(state), 4); + state.insert(-3); + ATF_REQUIRE_EQ(3, lua_tointeger(raw(state), -1)); + ATF_REQUIRE_EQ(2, lua_tointeger(raw(state), -2)); + ATF_REQUIRE_EQ(4, lua_tointeger(raw(state), -3)); + ATF_REQUIRE_EQ(1, lua_tointeger(raw(state), -4)); + lua_pop(raw(state), 4); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(is_boolean__empty); +ATF_TEST_CASE_BODY(is_boolean__empty) +{ + lutok::state state; + ATF_REQUIRE(!state.is_boolean()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(is_boolean__top); +ATF_TEST_CASE_BODY(is_boolean__top) +{ + lutok::state state; + lua_pushnil(raw(state)); + ATF_REQUIRE(!state.is_boolean()); + lua_pushboolean(raw(state), 1); + ATF_REQUIRE(state.is_boolean()); + lua_pop(raw(state), 2); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(is_boolean__explicit); +ATF_TEST_CASE_BODY(is_boolean__explicit) +{ + lutok::state state; + lua_pushboolean(raw(state), 1); + ATF_REQUIRE(state.is_boolean(-1)); + lua_pushinteger(raw(state), 5); + ATF_REQUIRE(!state.is_boolean(-1)); + ATF_REQUIRE(state.is_boolean(-2)); + lua_pop(raw(state), 2); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(is_function__empty); +ATF_TEST_CASE_BODY(is_function__empty) +{ + lutok::state state; + ATF_REQUIRE(!state.is_function()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(is_function__top); +ATF_TEST_CASE_BODY(is_function__top) +{ + lutok::state state; + luaL_dostring(raw(state), "function my_func(a, b) return a + b; end"); + + lua_pushnil(raw(state)); + ATF_REQUIRE(!state.is_function()); + lua_getglobal(raw(state), "my_func"); + ATF_REQUIRE(state.is_function()); + lua_pop(raw(state), 2); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(is_function__explicit); +ATF_TEST_CASE_BODY(is_function__explicit) +{ + lutok::state state; + luaL_dostring(raw(state), "function my_func(a, b) return a + b; end"); + + lua_getglobal(raw(state), "my_func"); + ATF_REQUIRE(state.is_function(-1)); + lua_pushinteger(raw(state), 5); + ATF_REQUIRE(!state.is_function(-1)); + ATF_REQUIRE(state.is_function(-2)); + lua_pop(raw(state), 2); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(is_nil__empty); +ATF_TEST_CASE_BODY(is_nil__empty) +{ + lutok::state state; + ATF_REQUIRE(state.is_nil()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(is_nil__top); +ATF_TEST_CASE_BODY(is_nil__top) +{ + lutok::state state; + lua_pushnil(raw(state)); + ATF_REQUIRE(state.is_nil()); + lua_pushinteger(raw(state), 5); + ATF_REQUIRE(!state.is_nil()); + lua_pop(raw(state), 2); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(is_nil__explicit); +ATF_TEST_CASE_BODY(is_nil__explicit) +{ + lutok::state state; + lua_pushnil(raw(state)); + ATF_REQUIRE(state.is_nil(-1)); + lua_pushinteger(raw(state), 5); + ATF_REQUIRE(!state.is_nil(-1)); + ATF_REQUIRE(state.is_nil(-2)); + lua_pop(raw(state), 2); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(is_number__empty); +ATF_TEST_CASE_BODY(is_number__empty) +{ + lutok::state state; + ATF_REQUIRE(!state.is_number()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(is_number__top); +ATF_TEST_CASE_BODY(is_number__top) +{ + lutok::state state; + lua_pushnil(raw(state)); + ATF_REQUIRE(!state.is_number()); + lua_pushinteger(raw(state), 5); + ATF_REQUIRE(state.is_number()); + lua_pop(raw(state), 2); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(is_number__explicit); +ATF_TEST_CASE_BODY(is_number__explicit) +{ + lutok::state state; + lua_pushnil(raw(state)); + ATF_REQUIRE(!state.is_number(-1)); + lua_pushinteger(raw(state), 5); + ATF_REQUIRE(state.is_number(-1)); + ATF_REQUIRE(!state.is_number(-2)); + lua_pop(raw(state), 2); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(is_string__empty); +ATF_TEST_CASE_BODY(is_string__empty) +{ + lutok::state state; + ATF_REQUIRE(!state.is_string()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(is_string__top); +ATF_TEST_CASE_BODY(is_string__top) +{ + lutok::state state; + lua_pushnil(raw(state)); + ATF_REQUIRE(!state.is_string()); + lua_pushinteger(raw(state), 3); + ATF_REQUIRE(state.is_string()); + lua_pushstring(raw(state), "foo"); + ATF_REQUIRE(state.is_string()); + lua_pop(raw(state), 3); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(is_string__explicit); +ATF_TEST_CASE_BODY(is_string__explicit) +{ + lutok::state state; + lua_pushinteger(raw(state), 3); + ATF_REQUIRE(state.is_string(-1)); + lua_pushnil(raw(state)); + ATF_REQUIRE(!state.is_string(-1)); + ATF_REQUIRE(state.is_string(-2)); + lua_pushstring(raw(state), "foo"); + ATF_REQUIRE(state.is_string(-1)); + ATF_REQUIRE(!state.is_string(-2)); + ATF_REQUIRE(state.is_string(-3)); + lua_pop(raw(state), 3); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(is_table__empty); +ATF_TEST_CASE_BODY(is_table__empty) +{ + lutok::state state; + ATF_REQUIRE(!state.is_table()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(is_table__top); +ATF_TEST_CASE_BODY(is_table__top) +{ + lutok::state state; + luaL_dostring(raw(state), "t = {3, 4, 5}"); + + lua_pushstring(raw(state), "foo"); + ATF_REQUIRE(!state.is_table()); + lua_getglobal(raw(state), "t"); + ATF_REQUIRE(state.is_table()); + lua_pop(raw(state), 2); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(is_table__explicit); +ATF_TEST_CASE_BODY(is_table__explicit) +{ + lutok::state state; + luaL_dostring(raw(state), "t = {3, 4, 5}"); + + lua_pushstring(raw(state), "foo"); + ATF_REQUIRE(!state.is_table(-1)); + lua_getglobal(raw(state), "t"); + ATF_REQUIRE(state.is_table(-1)); + ATF_REQUIRE(!state.is_table(-2)); + lua_pop(raw(state), 2); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(is_userdata__empty); +ATF_TEST_CASE_BODY(is_userdata__empty) +{ + lutok::state state; + ATF_REQUIRE(!state.is_userdata()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(is_userdata__top); +ATF_TEST_CASE_BODY(is_userdata__top) +{ + lutok::state state; + + lua_pushstring(raw(state), "foo"); + ATF_REQUIRE(!state.is_userdata()); + lua_newuserdata(raw(state), 1234); + ATF_REQUIRE(state.is_userdata()); + lua_pop(raw(state), 2); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(is_userdata__explicit); +ATF_TEST_CASE_BODY(is_userdata__explicit) +{ + lutok::state state; + + lua_pushstring(raw(state), "foo"); + ATF_REQUIRE(!state.is_userdata(-1)); + lua_newuserdata(raw(state), 543); + ATF_REQUIRE(state.is_userdata(-1)); + ATF_REQUIRE(!state.is_userdata(-2)); + lua_pop(raw(state), 2); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(load_file__ok); +ATF_TEST_CASE_BODY(load_file__ok) +{ + std::ofstream output("test.lua"); + output << "in_the_file = \"oh yes\"\n"; + output.close(); + + lutok::state state; + state.load_file("test.lua"); + ATF_REQUIRE(lua_pcall(raw(state), 0, 0, 0) == 0); + lua_getglobal(raw(state), "in_the_file"); + ATF_REQUIRE(std::strcmp("oh yes", lua_tostring(raw(state), -1)) == 0); + lua_pop(raw(state), 1); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(load_file__api_error); +ATF_TEST_CASE_BODY(load_file__api_error) +{ + std::ofstream output("test.lua"); + output << "I have a bad syntax! Wohoo!\n"; + output.close(); + + lutok::state state; + REQUIRE_API_ERROR("luaL_loadfile", state.load_file("test.lua")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(load_file__file_not_found_error); +ATF_TEST_CASE_BODY(load_file__file_not_found_error) +{ + lutok::state state; + ATF_REQUIRE_THROW_RE(lutok::file_not_found_error, "missing.lua", + state.load_file("missing.lua")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(load_string__ok); +ATF_TEST_CASE_BODY(load_string__ok) +{ + lutok::state state; + state.load_string("return 2 + 3"); + ATF_REQUIRE(lua_pcall(raw(state), 0, 1, 0) == 0); + ATF_REQUIRE_EQ(5, lua_tointeger(raw(state), -1)); + lua_pop(raw(state), 1); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(load_string__fail); +ATF_TEST_CASE_BODY(load_string__fail) +{ + lutok::state state; + REQUIRE_API_ERROR("luaL_loadstring", state.load_string("-")); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(new_table); +ATF_TEST_CASE_BODY(new_table) +{ + lutok::state state; + state.new_table(); + ATF_REQUIRE_EQ(1, lua_gettop(raw(state))); + ATF_REQUIRE(lua_istable(raw(state), -1)); + lua_pop(raw(state), 1); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(new_userdata); +ATF_TEST_CASE_BODY(new_userdata) +{ + lutok::state state; + int* pointer = state.new_userdata< int >(); + *pointer = 1234; + ATF_REQUIRE_EQ(1, lua_gettop(raw(state))); + ATF_REQUIRE(lua_isuserdata(raw(state), -1)); + lua_pop(raw(state), 1); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(next__empty); +ATF_TEST_CASE_BODY(next__empty) +{ + lutok::state state; + luaL_dostring(raw(state), "t = {}"); + + lua_getglobal(raw(state), "t"); + lua_pushstring(raw(state), "this is a dummy value"); + lua_pushnil(raw(state)); + ATF_REQUIRE(!state.next(-3)); + lua_pop(raw(state), 2); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(next__many); +ATF_TEST_CASE_BODY(next__many) +{ + lutok::state state; + luaL_dostring(raw(state), "t = {}; t[1] = 100; t[2] = 200"); + + lua_getglobal(raw(state), "t"); + lua_pushnil(raw(state)); + + ATF_REQUIRE(state.next()); + ATF_REQUIRE_EQ(3, lua_gettop(raw(state))); + ATF_REQUIRE(lua_isnumber(raw(state), -2)); + ATF_REQUIRE_EQ(1, lua_tointeger(raw(state), -2)); + ATF_REQUIRE(lua_isnumber(raw(state), -1)); + ATF_REQUIRE_EQ(100, lua_tointeger(raw(state), -1)); + lua_pop(raw(state), 1); + + ATF_REQUIRE(state.next()); + ATF_REQUIRE_EQ(3, lua_gettop(raw(state))); + ATF_REQUIRE(lua_isnumber(raw(state), -2)); + ATF_REQUIRE_EQ(2, lua_tointeger(raw(state), -2)); + ATF_REQUIRE(lua_isnumber(raw(state), -1)); + ATF_REQUIRE_EQ(200, lua_tointeger(raw(state), -1)); + lua_pop(raw(state), 1); + + ATF_REQUIRE(!state.next()); + lua_pop(raw(state), 1); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(open_base); +ATF_TEST_CASE_BODY(open_base) +{ + lutok::state state; + check_modules(state, ""); + state.open_base(); + check_modules(state, "base"); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(open_string); +ATF_TEST_CASE_BODY(open_string) +{ + lutok::state state; + check_modules(state, ""); + state.open_string(); + check_modules(state, "string"); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(open_table); +ATF_TEST_CASE_BODY(open_table) +{ + lutok::state state; + check_modules(state, ""); + state.open_table(); + check_modules(state, "table"); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(pcall__ok); +ATF_TEST_CASE_BODY(pcall__ok) +{ + lutok::state state; + luaL_loadstring(raw(state), "function mul(a, b) return a * b; end"); + state.pcall(0, 0, 0); + lua_getfield(raw(state), LUA_GLOBALSINDEX, "mul"); + lua_pushinteger(raw(state), 3); + lua_pushinteger(raw(state), 5); + state.pcall(2, 1, 0); + ATF_REQUIRE_EQ(15, lua_tointeger(raw(state), -1)); + lua_pop(raw(state), 1); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(pcall__fail); +ATF_TEST_CASE_BODY(pcall__fail) +{ + lutok::state state; + lua_pushnil(raw(state)); + REQUIRE_API_ERROR("lua_pcall", state.pcall(0, 0, 0)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(pop__one); +ATF_TEST_CASE_BODY(pop__one) +{ + lutok::state state; + lua_pushinteger(raw(state), 10); + lua_pushinteger(raw(state), 20); + lua_pushinteger(raw(state), 30); + state.pop(1); + ATF_REQUIRE_EQ(2, lua_gettop(raw(state))); + ATF_REQUIRE_EQ(20, lua_tointeger(raw(state), -1)); + lua_pop(raw(state), 2); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(pop__many); +ATF_TEST_CASE_BODY(pop__many) +{ + lutok::state state; + lua_pushinteger(raw(state), 10); + lua_pushinteger(raw(state), 20); + lua_pushinteger(raw(state), 30); + state.pop(2); + ATF_REQUIRE_EQ(1, lua_gettop(raw(state))); + ATF_REQUIRE_EQ(10, lua_tointeger(raw(state), -1)); + lua_pop(raw(state), 1); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(push_boolean); +ATF_TEST_CASE_BODY(push_boolean) +{ + lutok::state state; + state.push_boolean(true); + ATF_REQUIRE_EQ(1, lua_gettop(raw(state))); + ATF_REQUIRE(lua_toboolean(raw(state), -1)); + state.push_boolean(false); + ATF_REQUIRE_EQ(2, lua_gettop(raw(state))); + ATF_REQUIRE(!lua_toboolean(raw(state), -1)); + ATF_REQUIRE(lua_toboolean(raw(state), -2)); + lua_pop(raw(state), 2); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(push_cxx_closure); +ATF_TEST_CASE_BODY(push_cxx_closure) +{ + lutok::state state; + state.push_integer(15); + state.push_cxx_closure(cxx_multiply_closure, 1); + lua_setglobal(raw(state), "cxx_multiply_closure"); + + ATF_REQUIRE(luaL_dostring(raw(state), + "return cxx_multiply_closure(10)") == 0); + ATF_REQUIRE_EQ(150, lua_tointeger(raw(state), -1)); + lua_pop(raw(state), 1); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(push_cxx_function__ok); +ATF_TEST_CASE_BODY(push_cxx_function__ok) +{ + lutok::state state; + state.push_cxx_function(cxx_divide); + lua_setglobal(raw(state), "cxx_divide"); + + ATF_REQUIRE(luaL_dostring(raw(state), "return cxx_divide(17, 3)") == 0); + ATF_REQUIRE_EQ(5, lua_tointeger(raw(state), -2)); + ATF_REQUIRE_EQ(2, lua_tointeger(raw(state), -1)); + lua_pop(raw(state), 2); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(push_cxx_function__fail_exception); +ATF_TEST_CASE_BODY(push_cxx_function__fail_exception) +{ + lutok::state state; + state.push_cxx_function(cxx_divide); + lua_setglobal(raw(state), "cxx_divide"); + + ATF_REQUIRE(luaL_dostring(raw(state), "return cxx_divide(15, 0)") != 0); + ATF_REQUIRE_MATCH("Divisor is 0", lua_tostring(raw(state), -1)); + lua_pop(raw(state), 1); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(push_cxx_function__fail_anything); +ATF_TEST_CASE_BODY(push_cxx_function__fail_anything) +{ + lutok::state state; + state.push_cxx_function(cxx_divide); + lua_setglobal(raw(state), "cxx_divide"); + + ATF_REQUIRE(luaL_dostring(raw(state), "return cxx_divide(-3, -1)") != 0); + ATF_REQUIRE_MATCH("Unhandled exception", lua_tostring(raw(state), -1)); + lua_pop(raw(state), 1); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(push_cxx_function__fail_overflow); +ATF_TEST_CASE_BODY(push_cxx_function__fail_overflow) +{ + lutok::state state; + state.push_cxx_function(raise_long_error); + lua_setglobal(raw(state), "fail"); + + ATF_REQUIRE(luaL_dostring(raw(state), "return fail(900)") != 0); + ATF_REQUIRE_MATCH(std::string(900, 'A'), lua_tostring(raw(state), -1)); + lua_pop(raw(state), 1); + + ATF_REQUIRE(luaL_dostring(raw(state), "return fail(8192)") != 0); + ATF_REQUIRE_MATCH(std::string(900, 'A'), lua_tostring(raw(state), -1)); + lua_pop(raw(state), 1); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(push_integer); +ATF_TEST_CASE_BODY(push_integer) +{ + lutok::state state; + state.push_integer(12); + ATF_REQUIRE_EQ(1, lua_gettop(raw(state))); + ATF_REQUIRE_EQ(12, lua_tointeger(raw(state), -1)); + state.push_integer(34); + ATF_REQUIRE_EQ(2, lua_gettop(raw(state))); + ATF_REQUIRE_EQ(34, lua_tointeger(raw(state), -1)); + ATF_REQUIRE_EQ(12, lua_tointeger(raw(state), -2)); + lua_pop(raw(state), 2); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(push_nil); +ATF_TEST_CASE_BODY(push_nil) +{ + lutok::state state; + state.push_nil(); + ATF_REQUIRE_EQ(1, lua_gettop(raw(state))); + ATF_REQUIRE(lua_isnil(raw(state), -1)); + state.push_integer(34); + ATF_REQUIRE_EQ(2, lua_gettop(raw(state))); + ATF_REQUIRE(!lua_isnil(raw(state), -1)); + ATF_REQUIRE(lua_isnil(raw(state), -2)); + lua_pop(raw(state), 2); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(push_string); +ATF_TEST_CASE_BODY(push_string) +{ + lutok::state state; + + { + std::string str = "first"; + state.push_string(str); + ATF_REQUIRE_EQ(1, lua_gettop(raw(state))); + ATF_REQUIRE_EQ(std::string("first"), lua_tostring(raw(state), -1)); + str = "second"; + state.push_string(str); + } + ATF_REQUIRE_EQ(2, lua_gettop(raw(state))); + ATF_REQUIRE_EQ(std::string("second"), lua_tostring(raw(state), -1)); + ATF_REQUIRE_EQ(std::string("first"), lua_tostring(raw(state), -2)); + lua_pop(raw(state), 2); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(push_value__top); +ATF_TEST_CASE_BODY(push_value__top) +{ + lutok::state state; + + lua_pushinteger(raw(state), 10); + lua_pushinteger(raw(state), 20); + state.push_value(); + ATF_REQUIRE_EQ(3, lua_gettop(raw(state))); + ATF_REQUIRE_EQ(20, lua_tointeger(raw(state), -1)); + ATF_REQUIRE_EQ(20, lua_tointeger(raw(state), -2)); + ATF_REQUIRE_EQ(10, lua_tointeger(raw(state), -3)); + lua_pop(raw(state), 3); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(push_value__explicit); +ATF_TEST_CASE_BODY(push_value__explicit) +{ + lutok::state state; + + lua_pushinteger(raw(state), 10); + lua_pushinteger(raw(state), 20); + state.push_value(-2); + ATF_REQUIRE_EQ(3, lua_gettop(raw(state))); + ATF_REQUIRE_EQ(10, lua_tointeger(raw(state), -1)); + ATF_REQUIRE_EQ(20, lua_tointeger(raw(state), -2)); + ATF_REQUIRE_EQ(10, lua_tointeger(raw(state), -3)); + lua_pop(raw(state), 3); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(raw_get__top); +ATF_TEST_CASE_BODY(raw_get__top) +{ + lutok::state state; + + luaL_openlibs(raw(state)); + ATF_REQUIRE(luaL_dostring( + raw(state), "t = {foo=123} ; setmetatable(t, {__index=1})") == 0); + lua_getglobal(raw(state), "t"); + lua_pushstring(raw(state), "foo"); + state.raw_get(); + ATF_REQUIRE(lua_isnumber(raw(state), -1)); + ATF_REQUIRE_EQ(123, lua_tointeger(raw(state), -1)); + lua_pop(raw(state), 2); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(raw_get__explicit); +ATF_TEST_CASE_BODY(raw_get__explicit) +{ + lutok::state state; + + luaL_openlibs(raw(state)); + ATF_REQUIRE(luaL_dostring( + raw(state), "t = {foo=123} ; setmetatable(t, {__index=1})") == 0); + lua_getglobal(raw(state), "t"); + lua_pushinteger(raw(state), 9876); + lua_pushstring(raw(state), "foo"); + state.raw_get(-3); + ATF_REQUIRE(lua_isnumber(raw(state), -1)); + ATF_REQUIRE_EQ(123, lua_tointeger(raw(state), -1)); + ATF_REQUIRE_EQ(9876, lua_tointeger(raw(state), -2)); + lua_pop(raw(state), 3); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(raw_set__top); +ATF_TEST_CASE_BODY(raw_set__top) +{ + lutok::state state; + + luaL_openlibs(raw(state)); + ATF_REQUIRE(luaL_dostring( + raw(state), "t = {} ; setmetatable(t, {__newindex=1})") == 0); + lua_getglobal(raw(state), "t"); + lua_pushstring(raw(state), "foo"); + lua_pushinteger(raw(state), 345); + state.raw_set(); + ATF_REQUIRE(luaL_dostring(raw(state), "return t.foo") == 0); + ATF_REQUIRE(lua_isnumber(raw(state), -1)); + ATF_REQUIRE_EQ(345, lua_tointeger(raw(state), -1)); + lua_pop(raw(state), 2); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(raw_set__explicit); +ATF_TEST_CASE_BODY(raw_set__explicit) +{ + lutok::state state; + + luaL_openlibs(raw(state)); + ATF_REQUIRE(luaL_dostring( + raw(state), "t = {} ; setmetatable(t, {__newindex=1})") == 0); + lua_getglobal(raw(state), "t"); + lua_pushinteger(raw(state), 876); + lua_pushstring(raw(state), "foo"); + lua_pushinteger(raw(state), 345); + state.raw_set(-4); + ATF_REQUIRE(luaL_dostring(raw(state), "return t.foo") == 0); + ATF_REQUIRE(lua_isnumber(raw(state), -1)); + ATF_REQUIRE_EQ(345, lua_tointeger(raw(state), -1)); + ATF_REQUIRE_EQ(876, lua_tointeger(raw(state), -2)); + lua_pop(raw(state), 3); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(set_global__ok); +ATF_TEST_CASE_BODY(set_global__ok) +{ + lutok::state state; + lua_pushinteger(raw(state), 3); + state.set_global("test_variable"); + ATF_REQUIRE(luaL_dostring(raw(state), "return test_variable + 1") == 0); + ATF_REQUIRE(lua_isnumber(raw(state), -1)); + ATF_REQUIRE_EQ(4, lua_tointeger(raw(state), -1)); + lua_pop(raw(state), 1); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(set_global__fail); +ATF_TEST_CASE_BODY(set_global__fail) +{ + lutok::state state; + lua_pushinteger(raw(state), 3); + lua_replace(raw(state), LUA_GLOBALSINDEX); + lua_pushinteger(raw(state), 4); + REQUIRE_API_ERROR("lua_setglobal", state.set_global("test_variable")); + lua_pop(raw(state), 1); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(set_metatable__top); +ATF_TEST_CASE_BODY(set_metatable__top) +{ + lutok::state state; + ATF_REQUIRE(luaL_dostring( + raw(state), + "mt = {}\n" + "mt.__add = function(a, b) return a[1] + b end\n" + "numbers = {}\n" + "numbers[1] = 5\n") == 0); + + lua_getglobal(raw(state), "numbers"); + lua_getglobal(raw(state), "mt"); + state.set_metatable(); + lua_pop(raw(state), 1); + + ATF_REQUIRE(luaL_dostring(raw(state), "return numbers + 2") == 0); + ATF_REQUIRE(lua_isnumber(raw(state), -1)); + ATF_REQUIRE_EQ(7, lua_tointeger(raw(state), -1)); + lua_pop(raw(state), 1); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(set_metatable__explicit); +ATF_TEST_CASE_BODY(set_metatable__explicit) +{ + lutok::state state; + ATF_REQUIRE(luaL_dostring( + raw(state), + "mt = {}\n" + "mt.__add = function(a, b) return a[1] + b end\n" + "numbers = {}\n" + "numbers[1] = 5\n") == 0); + + lua_getglobal(raw(state), "numbers"); + lua_pushinteger(raw(state), 1234); + lua_getglobal(raw(state), "mt"); + state.set_metatable(-3); + lua_pop(raw(state), 2); + + ATF_REQUIRE(luaL_dostring(raw(state), "return numbers + 2") == 0); + ATF_REQUIRE(lua_isnumber(raw(state), -1)); + ATF_REQUIRE_EQ(7, lua_tointeger(raw(state), -1)); + lua_pop(raw(state), 1); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(set_table__ok); +ATF_TEST_CASE_BODY(set_table__ok) +{ + lutok::state state; + ATF_REQUIRE(luaL_dostring(raw(state), "t = { a = 1, bar = 234 }") == 0); + lua_getglobal(raw(state), "t"); + + lua_pushstring(raw(state), "bar"); + lua_pushstring(raw(state), "baz"); + state.set_table(); + ATF_REQUIRE_EQ(1, lua_gettop(raw(state))); + + lua_pushstring(raw(state), "a"); + lua_gettable(raw(state), -2); + ATF_REQUIRE(lua_isnumber(raw(state), -1)); + ATF_REQUIRE_EQ(1, lua_tointeger(raw(state), -1)); + lua_pop(raw(state), 1); + + lua_pushstring(raw(state), "bar"); + lua_gettable(raw(state), -2); + ATF_REQUIRE(lua_isstring(raw(state), -1)); + ATF_REQUIRE_EQ(std::string("baz"), lua_tostring(raw(state), -1)); + lua_pop(raw(state), 1); + + lua_pop(raw(state), 1); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(set_table__nil); +ATF_TEST_CASE_BODY(set_table__nil) +{ + lutok::state state; + lua_pushnil(raw(state)); + lua_pushinteger(raw(state), 1); + lua_pushinteger(raw(state), 2); + REQUIRE_API_ERROR("lua_settable", state.set_table(-3)); + lua_pop(raw(state), 3); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(to_boolean__top); +ATF_TEST_CASE_BODY(to_boolean__top) +{ + lutok::state state; + lua_pushboolean(raw(state), 1); + ATF_REQUIRE(state.to_boolean()); + lua_pushboolean(raw(state), 0); + ATF_REQUIRE(!state.to_boolean()); + lua_pop(raw(state), 2); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(to_boolean__explicit); +ATF_TEST_CASE_BODY(to_boolean__explicit) +{ + lutok::state state; + lua_pushboolean(raw(state), 0); + lua_pushboolean(raw(state), 1); + ATF_REQUIRE(!state.to_boolean(-2)); + ATF_REQUIRE(state.to_boolean(-1)); + lua_pop(raw(state), 2); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(to_integer__top); +ATF_TEST_CASE_BODY(to_integer__top) +{ + lutok::state state; + lua_pushstring(raw(state), "34"); + ATF_REQUIRE_EQ(34, state.to_integer()); + lua_pushinteger(raw(state), 12); + ATF_REQUIRE_EQ(12, state.to_integer()); + lua_pop(raw(state), 2); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(to_integer__explicit); +ATF_TEST_CASE_BODY(to_integer__explicit) +{ + lutok::state state; + lua_pushinteger(raw(state), 12); + lua_pushstring(raw(state), "foobar"); + ATF_REQUIRE_EQ(12, state.to_integer(-2)); + lua_pop(raw(state), 2); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(to_string__top); +ATF_TEST_CASE_BODY(to_string__top) +{ + lutok::state state; + lua_pushstring(raw(state), "foobar"); + ATF_REQUIRE_EQ("foobar", state.to_string()); + lua_pushinteger(raw(state), 12); + ATF_REQUIRE_EQ("12", state.to_string()); + lua_pop(raw(state), 2); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(to_string__explicit); +ATF_TEST_CASE_BODY(to_string__explicit) +{ + lutok::state state; + lua_pushstring(raw(state), "foobar"); + lua_pushinteger(raw(state), 12); + ATF_REQUIRE_EQ("foobar", state.to_string(-2)); + ATF_REQUIRE_EQ("12", state.to_string(-1)); + lua_pop(raw(state), 2); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(to_userdata__top); +ATF_TEST_CASE_BODY(to_userdata__top) +{ + lutok::state state; + { + int* pointer = static_cast< int* >( + lua_newuserdata(raw(state), sizeof(int))); + *pointer = 987; + } + + int* pointer = state.to_userdata< int >(); + ATF_REQUIRE_EQ(987, *pointer); + lua_pop(raw(state), 1); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(to_userdata__explicit); +ATF_TEST_CASE_BODY(to_userdata__explicit) +{ + lutok::state state; + { + int* pointer = static_cast< int* >( + lua_newuserdata(raw(state), sizeof(int))); + *pointer = 987; + } + + lua_pushinteger(raw(state), 3); + int* pointer = state.to_userdata< int >(-2); + ATF_REQUIRE_EQ(987, *pointer); + lua_pop(raw(state), 2); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(upvalue_index); +ATF_TEST_CASE_BODY(upvalue_index) +{ + lutok::state state; + lua_pushinteger(raw(state), 25); + lua_pushinteger(raw(state), 30); + lua_pushcclosure(raw(state), c_get_upvalues, 2); + lua_setglobal(raw(state), "c_get_upvalues"); + + ATF_REQUIRE(luaL_dostring(raw(state), + "return c_get_upvalues()") == 0); + ATF_REQUIRE_EQ(25, lua_tointeger(raw(state), -2)); + ATF_REQUIRE_EQ(30, lua_tointeger(raw(state), -1)); + lua_pop(raw(state), 2); +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, close); + ATF_ADD_TEST_CASE(tcs, get_global__ok); + ATF_ADD_TEST_CASE(tcs, get_global__fail); + ATF_ADD_TEST_CASE(tcs, get_global__undefined); + ATF_ADD_TEST_CASE(tcs, get_metafield__ok); + ATF_ADD_TEST_CASE(tcs, get_metafield__undefined); + ATF_ADD_TEST_CASE(tcs, get_metatable__top); + ATF_ADD_TEST_CASE(tcs, get_metatable__explicit); + ATF_ADD_TEST_CASE(tcs, get_metatable__undefined); + ATF_ADD_TEST_CASE(tcs, get_table__ok); + ATF_ADD_TEST_CASE(tcs, get_table__nil); + ATF_ADD_TEST_CASE(tcs, get_table__unknown_index); + ATF_ADD_TEST_CASE(tcs, get_top); + ATF_ADD_TEST_CASE(tcs, globals_index); + ATF_ADD_TEST_CASE(tcs, insert); + ATF_ADD_TEST_CASE(tcs, is_boolean__empty); + ATF_ADD_TEST_CASE(tcs, is_boolean__top); + ATF_ADD_TEST_CASE(tcs, is_boolean__explicit); + ATF_ADD_TEST_CASE(tcs, is_function__empty); + ATF_ADD_TEST_CASE(tcs, is_function__top); + ATF_ADD_TEST_CASE(tcs, is_function__explicit); + ATF_ADD_TEST_CASE(tcs, is_nil__empty); + ATF_ADD_TEST_CASE(tcs, is_nil__top); + ATF_ADD_TEST_CASE(tcs, is_nil__explicit); + ATF_ADD_TEST_CASE(tcs, is_number__empty); + ATF_ADD_TEST_CASE(tcs, is_number__top); + ATF_ADD_TEST_CASE(tcs, is_number__explicit); + ATF_ADD_TEST_CASE(tcs, is_string__empty); + ATF_ADD_TEST_CASE(tcs, is_string__top); + ATF_ADD_TEST_CASE(tcs, is_string__explicit); + ATF_ADD_TEST_CASE(tcs, is_table__empty); + ATF_ADD_TEST_CASE(tcs, is_table__top); + ATF_ADD_TEST_CASE(tcs, is_table__explicit); + ATF_ADD_TEST_CASE(tcs, is_userdata__empty); + ATF_ADD_TEST_CASE(tcs, is_userdata__top); + ATF_ADD_TEST_CASE(tcs, is_userdata__explicit); + ATF_ADD_TEST_CASE(tcs, load_file__ok); + ATF_ADD_TEST_CASE(tcs, load_file__api_error); + ATF_ADD_TEST_CASE(tcs, load_file__file_not_found_error); + ATF_ADD_TEST_CASE(tcs, load_string__ok); + ATF_ADD_TEST_CASE(tcs, load_string__fail); + ATF_ADD_TEST_CASE(tcs, new_table); + ATF_ADD_TEST_CASE(tcs, new_userdata); + ATF_ADD_TEST_CASE(tcs, next__empty); + ATF_ADD_TEST_CASE(tcs, next__many); + ATF_ADD_TEST_CASE(tcs, open_base); + ATF_ADD_TEST_CASE(tcs, open_string); + ATF_ADD_TEST_CASE(tcs, open_table); + ATF_ADD_TEST_CASE(tcs, pcall__ok); + ATF_ADD_TEST_CASE(tcs, pcall__fail); + ATF_ADD_TEST_CASE(tcs, pop__one); + ATF_ADD_TEST_CASE(tcs, pop__many); + ATF_ADD_TEST_CASE(tcs, push_boolean); + ATF_ADD_TEST_CASE(tcs, push_cxx_closure); + ATF_ADD_TEST_CASE(tcs, push_cxx_function__ok); + ATF_ADD_TEST_CASE(tcs, push_cxx_function__fail_exception); + ATF_ADD_TEST_CASE(tcs, push_cxx_function__fail_anything); + ATF_ADD_TEST_CASE(tcs, push_cxx_function__fail_overflow); + ATF_ADD_TEST_CASE(tcs, push_integer); + ATF_ADD_TEST_CASE(tcs, push_nil); + ATF_ADD_TEST_CASE(tcs, push_string); + ATF_ADD_TEST_CASE(tcs, push_value__top); + ATF_ADD_TEST_CASE(tcs, push_value__explicit); + ATF_ADD_TEST_CASE(tcs, raw_get__top); + ATF_ADD_TEST_CASE(tcs, raw_get__explicit); + ATF_ADD_TEST_CASE(tcs, raw_set__top); + ATF_ADD_TEST_CASE(tcs, raw_set__explicit); + ATF_ADD_TEST_CASE(tcs, set_global__ok); + ATF_ADD_TEST_CASE(tcs, set_global__fail); + ATF_ADD_TEST_CASE(tcs, set_metatable__top); + ATF_ADD_TEST_CASE(tcs, set_metatable__explicit); + ATF_ADD_TEST_CASE(tcs, set_table__ok); + ATF_ADD_TEST_CASE(tcs, set_table__nil); + ATF_ADD_TEST_CASE(tcs, to_boolean__top); + ATF_ADD_TEST_CASE(tcs, to_boolean__explicit); + ATF_ADD_TEST_CASE(tcs, to_integer__top); + ATF_ADD_TEST_CASE(tcs, to_integer__explicit); + ATF_ADD_TEST_CASE(tcs, to_string__top); + ATF_ADD_TEST_CASE(tcs, to_string__explicit); + ATF_ADD_TEST_CASE(tcs, to_userdata__top); + ATF_ADD_TEST_CASE(tcs, to_userdata__explicit); + ATF_ADD_TEST_CASE(tcs, upvalue_index); +} diff --git a/external/bsd/lutok/dist/test_utils.hpp b/external/bsd/lutok/dist/test_utils.hpp new file mode 100644 index 000000000..9077f18f0 --- /dev/null +++ b/external/bsd/lutok/dist/test_utils.hpp @@ -0,0 +1,141 @@ +// Copyright 2011 Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/// \file test_utils.hpp +/// Utilities for tests of the lua modules. +/// +/// This file is intended to be included once, and only once, for every test +/// program that needs it. All the code is herein contained to simplify the +/// dependency chain in the build rules. + +#if !defined(LUTOK_TEST_UTILS_HPP) +# define LUTOK_TEST_UTILS_HPP +#else +# error "test_utils.hpp can only be included once" +#endif + +#include + +#include "c_gate.hpp" +#include "exceptions.hpp" +#include "state.hpp" + + +namespace { + + +/// Checks that a given expression raises a particular lutok::api_error. +/// +/// We cannot make any assumptions regarding the error text provided by Lua, so +/// we resort to checking only which API function raised the error (because our +/// code is the one hardcoding these strings). +/// +/// \param exp_api_function The name of the Lua C API function that causes the +/// error. +/// \param statement The statement to execute. +#define REQUIRE_API_ERROR(exp_api_function, statement) \ + do { \ + try { \ + statement; \ + ATF_FAIL("api_error not raised by " #statement); \ + } catch (const lutok::api_error& api_error) { \ + ATF_REQUIRE_EQ(exp_api_function, api_error.api_function()); \ + } \ + } while (0) + + +/// Gets the pointer to the internal lua_State of a state object. +/// +/// This is pure syntactic sugar to simplify typing in the test cases. +/// +/// \param state The Lua state. +/// +/// \return The internal lua_State of the input Lua state. +static inline lua_State* +raw(lutok::state& state) +{ + return lutok::state_c_gate(state).c_state(); +} + + +/// Ensures that the Lua stack maintains its original height upon exit. +/// +/// Use an instance of this class to check that a piece of code does not have +/// side-effects on the Lua stack. +/// +/// To be used within a test case only. +class stack_balance_checker { + /// The Lua state. + lutok::state& _state; + + /// Whether to install a sentinel on the stack for balance enforcement. + bool _with_sentinel; + + /// The height of the stack on creation. + unsigned int _old_count; + +public: + /// Constructs a new stack balance checker. + /// + /// \param state_ The Lua state to validate. + /// \param with_sentinel_ If true, insert a sentinel item into the stack and + /// validate upon exit that the item is still there. This is an attempt + /// to ensure that already-existing items are not removed from the stack + /// by the code under test. + stack_balance_checker(lutok::state& state_, + const bool with_sentinel_ = true) : + _state(state_), + _with_sentinel(with_sentinel_), + _old_count(_state.get_top()) + { + if (_with_sentinel) + _state.push_integer(987654321); + } + + /// Destructor for the object. + /// + /// If the stack height does not match the height when the instance was + /// created, this fails the test case. + ~stack_balance_checker(void) + { + if (_with_sentinel) { + if (!_state.is_number() || _state.to_integer() != 987654321) + ATF_FAIL("Stack corrupted: sentinel not found"); + _state.pop(1); + } + + unsigned int new_count = _state.get_top(); + if (_old_count != new_count) + //ATF_FAIL(F("Stack not balanced: before %d, after %d") % + // _old_count % new_count); + ATF_FAIL("Stack not balanced"); + } +}; + + +} // anonymous namespace diff --git a/external/bsd/lutok/lib/Makefile b/external/bsd/lutok/lib/Makefile new file mode 100644 index 000000000..681733915 --- /dev/null +++ b/external/bsd/lutok/lib/Makefile @@ -0,0 +1,5 @@ +# $NetBSD: Makefile,v 1.1 2013/02/16 21:29:46 jmmv Exp $ + +SUBDIR= liblutok + +.include diff --git a/external/bsd/lutok/lib/liblutok/Makefile b/external/bsd/lutok/lib/liblutok/Makefile new file mode 100644 index 000000000..b5beed995 --- /dev/null +++ b/external/bsd/lutok/lib/liblutok/Makefile @@ -0,0 +1,61 @@ +# $NetBSD: Makefile,v 1.2 2013/02/22 15:14:31 jmmv Exp $ + +#NOLINT= # defined + +.include + +LIB= lutok +LIBISCXX= yes + +LIBDPLIBS+= lua ${.CURDIR}/../../../../mit/lua/lib/liblua +.if ${HAVE_GCC} == 4 +LIBDPLIBS+= stdc++ ${.CURDIR}/../../../../../gnu/lib/libstdc++-v3_4 +.else +LIBDPLIBS+= stdc++ ${.CURDIR}/../../../../../external/gpl3/gcc/lib/libstdc++-v3 +.endif +LIBDPLIBS+= m ${.CURDIR}/../../../../../lib/libm + +SRCDIR= ${NETBSDSRCDIR}/external/bsd/lutok/dist +.PATH: ${SRCDIR} + +CPPFLAGS+= -I${.CURDIR} +CPPFLAGS+= -I. + +CPPFLAGS+= -DHAVE_CONFIG_H + +WARNS?= 4 + +SRCS= c_gate.cpp \ + debug.cpp \ + exceptions.cpp \ + operations.cpp \ + stack_cleaner.cpp \ + state.cpp + +INCS= c_gate.hpp \ + debug.hpp \ + exceptions.hpp \ + operations.hpp \ + stack_cleaner.hpp \ + state.hpp \ + state.ipp \ + test_utils.hpp +INCSDIR= /usr/include/lutok + +.if ${MKSHARE} != "no" +FILES+= lutok.pc +FILESDIR= /usr/lib/pkgconfig + +realall: lutok.pc +lutok.pc: Makefile lutok.pc.in + ${TOOL_SED} \ + -e 's,__INCLUDEDIR__,/usr/include,g' \ + -e 's,__LIBDIR__,/usr/lib,g' \ + -e 's,__LUA_CFLAGS__,-I/usr/include,g' \ + -e 's,__LUA_LIBS,-llua,g' \ + -e 's,__VERSION__,0.2,g' \ + <${SRCDIR}/lutok.pc.in >lutok.pc +CLEANFILES+= lutok.pc +.endif + +.include diff --git a/external/bsd/lutok/lib/liblutok/config.h b/external/bsd/lutok/lib/liblutok/config.h new file mode 100644 index 000000000..f718a3a73 --- /dev/null +++ b/external/bsd/lutok/lib/liblutok/config.h @@ -0,0 +1,63 @@ +/* config.h. Generated from config.h.in by configure. */ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#define LT_OBJDIR ".libs/" + +/* Name of package */ +#define PACKAGE "lutok" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "lutok-discuss@googlegroups.com" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "Lutok" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "Lutok 0.2" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "lutok" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "http://code.google.com/p/lutok/" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "0.2" + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Version number of package */ +#define VERSION "0.2" diff --git a/external/bsd/lutok/lib/liblutok/shlib_version b/external/bsd/lutok/lib/liblutok/shlib_version new file mode 100644 index 000000000..fec6b6631 --- /dev/null +++ b/external/bsd/lutok/lib/liblutok/shlib_version @@ -0,0 +1,3 @@ +# $NetBSD: shlib_version,v 1.1 2013/02/16 21:29:47 jmmv Exp $ +major=1 +minor=0 diff --git a/external/bsd/lutok/prepare-import.sh b/external/bsd/lutok/prepare-import.sh new file mode 100755 index 000000000..b157fc214 --- /dev/null +++ b/external/bsd/lutok/prepare-import.sh @@ -0,0 +1,107 @@ +#!/bin/sh +# $NetBSD: prepare-import.sh,v 1.1 2013/02/16 21:29:45 jmmv Exp $ +# +# Use this script to recreate the 'dist' subdirectory from a newly released +# distfile. The script takes care of unpacking the distfile, removing any +# files that are not relevant to NetBSD and checking if there are any new +# files in the new release that need to be addressed. +# + +set -e + +ProgName=${0##*/} + +CLEAN_PATTERNS= +CLEAN_PATTERNS="${CLEAN_PATTERNS} *.m4" +CLEAN_PATTERNS="${CLEAN_PATTERNS} INSTALL TODO" +CLEAN_PATTERNS="${CLEAN_PATTERNS} Doxyfile*" +CLEAN_PATTERNS="${CLEAN_PATTERNS} Makefile* */Makefile* */*/Makefile*" +CLEAN_PATTERNS="${CLEAN_PATTERNS} admin" +CLEAN_PATTERNS="${CLEAN_PATTERNS} api-docs" +CLEAN_PATTERNS="${CLEAN_PATTERNS} config.h.in" +CLEAN_PATTERNS="${CLEAN_PATTERNS} configure*" +CLEAN_PATTERNS="${CLEAN_PATTERNS} include" +CLEAN_PATTERNS="${CLEAN_PATTERNS} m4" + +err() { + echo "${ProgName}:" "${@}" 1>&2 + exit 1 +} + +log() { + echo "${ProgName}:" "${@}" +} + +backup_dist() { + if [ -d dist.old ]; then + log "Removing dist; dist.old exists" + rm -rf dist + else + log "Backing up dist as dist.old" + mv dist dist.old + fi +} + +extract_distfile() { + local distfile="${1}"; shift + local distname="${1}"; shift + + log "Extracting ${distfile}" + tar -xzf "${distfile}" + [ -d "${distname}" ] || err "Distfile did not create ${distname}" + log "Renaming ${distname} to dist" + mv "${distname}" dist +} + +get_distname() { + local distfile="${1}"; shift + basename "${distfile}" | sed -e 's,\.tar.*,,' +} + +cleanup_dist() { + log "Removing unnecessary files from dist" + ( cd dist && rm -rf ${CLEAN_PATTERNS} ) +} + +diff_dirs() { + local old_dir="${1}"; shift + local new_dir="${1}"; shift + + local old_list=$(mktemp -t lutok-import.XXXXXX) + local new_list=$(mktemp -t lutok-import.XXXXXX) + local diff=$(mktemp -t lutok-import.XXXXXX) + trap "rm -f '${old_list}' '${new_list}' '${diff}'; exit 1" \ + HUP INT QUIT TERM + + ( cd "${old_dir}" && find . | sort >>"${old_list}" ) + ( cd "${new_dir}" && find . | sort >>"${new_list}" ) + + diff -u "${old_list}" "${new_list}" | grep '^+\.' >>"${diff}" || true + if [ -s "${diff}" ]; then + log "New files found" + diff -u "${old_list}" "${new_list}" | grep '^+\.' + log "Check if any files have to be cleaned up and update" \ + "the prepare-import.sh script accordingly" + else + log "No new files; all good!" + fi + + rm -f "${old_list}" "${new_list}" "${diff}" +} + +main() { + [ ${#} -eq 1 ] || err "Must provide a distfile name" + local distfile="${1}"; shift + + [ -f Makefile -a -f prepare-import.sh ] || \ + err "Must be run from the src/external/bsd/lutok subdirectory" + + local distname="$(get_distname ${distfile})" + + backup_dist + extract_distfile "${distfile}" "${distname}" + cleanup_dist + diff_dirs dist.old dist +} + +main "${@}" diff --git a/external/bsd/lutok/share/Makefile b/external/bsd/lutok/share/Makefile new file mode 100644 index 000000000..244eac4be --- /dev/null +++ b/external/bsd/lutok/share/Makefile @@ -0,0 +1,10 @@ +# $NetBSD: Makefile,v 1.1 2013/02/16 21:29:48 jmmv Exp $ + +.include + +.if ${MKSHARE} != "no" || \ + make(clean) || make(cleandir) || make(distclean) || make(obj) +SUBDIR= examples +.endif + +.include diff --git a/external/bsd/lutok/share/examples/Makefile b/external/bsd/lutok/share/examples/Makefile new file mode 100644 index 000000000..3ab359a1a --- /dev/null +++ b/external/bsd/lutok/share/examples/Makefile @@ -0,0 +1,5 @@ +# $NetBSD: Makefile,v 1.1 2013/02/16 21:29:48 jmmv Exp $ + +SUBDIR= lutok + +.include diff --git a/external/bsd/lutok/share/examples/lutok/Makefile b/external/bsd/lutok/share/examples/lutok/Makefile new file mode 100644 index 000000000..1beb9dfc2 --- /dev/null +++ b/external/bsd/lutok/share/examples/lutok/Makefile @@ -0,0 +1,15 @@ +# $NetBSD: Makefile,v 1.1 2013/02/16 21:29:48 jmmv Exp $ + +.include + +SRCDIR= ${NETBSDSRCDIR}/external/bsd/lutok/dist +.PATH: ${SRCDIR}/examples + +FILESDIR= /usr/share/examples/lutok +FILESMODE= 444 +FILES= bindings.cpp \ + hello.cpp \ + interpreter.cpp \ + raii.cpp + +.include diff --git a/external/bsd/lutok/tests/Makefile b/external/bsd/lutok/tests/Makefile new file mode 100644 index 000000000..adf0158b6 --- /dev/null +++ b/external/bsd/lutok/tests/Makefile @@ -0,0 +1,5 @@ +# $NetBSD: Makefile,v 1.1 2013/02/16 21:29:49 jmmv Exp $ + +SUBDIR= lib share + +.include diff --git a/external/bsd/lutok/tests/lib/Makefile b/external/bsd/lutok/tests/lib/Makefile new file mode 100644 index 000000000..341b852a5 --- /dev/null +++ b/external/bsd/lutok/tests/lib/Makefile @@ -0,0 +1,5 @@ +# $NetBSD: Makefile,v 1.1 2013/02/16 21:29:49 jmmv Exp $ + +SUBDIR= liblutok + +.include diff --git a/external/bsd/lutok/tests/lib/liblutok/Makefile b/external/bsd/lutok/tests/lib/liblutok/Makefile new file mode 100644 index 000000000..29a2f4fe2 --- /dev/null +++ b/external/bsd/lutok/tests/lib/liblutok/Makefile @@ -0,0 +1,32 @@ +# $NetBSD: Makefile,v 1.1 2013/02/16 21:29:50 jmmv Exp $ + +.include + +TESTSDIR= ${TESTSBASE}/lib/liblutok + +SRCDIR= ${NETBSDSRCDIR}/external/bsd/lutok/dist +.PATH: ${SRCDIR} + +CPPFLAGS+= -DHAVE_CONFIG_H +CPPFLAGS+= -I${NETBSDSRCDIR}/lib/liblutok + +FILESDIR= ${TESTSDIR} + +TESTS_CXX= c_gate_test \ + debug_test \ + exceptions_test \ + operations_test \ + stack_cleaner_test \ + state_test + +LDADD+= -llutok +DPADD+= ${LIBLUTOK} + +.if defined(__MINIX) +LDADD+= -llua +DPADD+= ${LIBLUA} +#LSC FIXME: We should fix this double definition problem of aeabi symbols +LDFLAGS+= -Wl,--allow-multiple-definition +.endif # defined(__MINIX) + +.include diff --git a/external/bsd/lutok/tests/share/Makefile b/external/bsd/lutok/tests/share/Makefile new file mode 100644 index 000000000..3c64dde9c --- /dev/null +++ b/external/bsd/lutok/tests/share/Makefile @@ -0,0 +1,10 @@ +# $NetBSD: Makefile,v 1.1 2013/02/16 21:29:50 jmmv Exp $ + +.include + +.if ${MKSHARE} != "no" || \ + make(clean) || make(cleandir) || make(distclean) || make(obj) +SUBDIR= lutok +.endif + +.include diff --git a/external/bsd/lutok/tests/share/lutok/Makefile b/external/bsd/lutok/tests/share/lutok/Makefile new file mode 100644 index 000000000..349f25ddf --- /dev/null +++ b/external/bsd/lutok/tests/share/lutok/Makefile @@ -0,0 +1,23 @@ +# $NetBSD: Makefile,v 1.1 2013/02/16 21:29:51 jmmv Exp $ + +.include + +TESTSDIR= ${TESTSBASE}/share/examples/lutok + +SRCDIR= ${NETBSDSRCDIR}/external/bsd/lutok/dist +.PATH: ${SRCDIR} + +FILESDIR= ${TESTSDIR} + +TESTS_SH= examples_test +TESTS_SH_SRC_examples_test= examples_test.patched + +examples_test.patched: examples_test.sh + ${TOOL_SED} \ + -e 's,__ATF_SH__,/bin/sh,g' \ + -e 's,__EXAMPLESDIR__,/usr/share/examples/lutok,g' \ + -e 's,__LIBDIR__,/usr/lib,g' \ + <${SRCDIR}/examples_test.sh >examples_test.patched +CLEANFILES+= examples_test.patched + +.include diff --git a/external/mit/Makefile b/external/mit/Makefile new file mode 100644 index 000000000..b661c408f --- /dev/null +++ b/external/mit/Makefile @@ -0,0 +1,5 @@ +# $NetBSD: Makefile,v 1.2 2012/02/29 20:07:55 tron Exp $ + +SUBDIR+= lua + +.include diff --git a/external/mit/lua/Makefile b/external/mit/lua/Makefile new file mode 100644 index 000000000..6852920e7 --- /dev/null +++ b/external/mit/lua/Makefile @@ -0,0 +1,5 @@ +# $NetBSD: Makefile,v 1.3 2010/10/31 11:26:01 mbalmer Exp $ + +SUBDIR+= usr.bin + +.include diff --git a/external/mit/lua/dist/COPYRIGHT b/external/mit/lua/dist/COPYRIGHT new file mode 100644 index 000000000..a86026803 --- /dev/null +++ b/external/mit/lua/dist/COPYRIGHT @@ -0,0 +1,34 @@ +Lua License +----------- + +Lua is licensed under the terms of the MIT license reproduced below. +This means that Lua is free software and can be used for both academic +and commercial purposes at absolutely no cost. + +For details and rationale, see http://www.lua.org/license.html . + +=============================================================================== + +Copyright (C) 1994-2012 Lua.org, PUC-Rio. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +=============================================================================== + +(end of COPYRIGHT) diff --git a/external/mit/lua/dist/HISTORY b/external/mit/lua/dist/HISTORY new file mode 100644 index 000000000..ce0c95bc6 --- /dev/null +++ b/external/mit/lua/dist/HISTORY @@ -0,0 +1,183 @@ +HISTORY for Lua 5.1 + +* Changes from version 5.0 to 5.1 + ------------------------------- + Language: + + new module system. + + new semantics for control variables of fors. + + new semantics for setn/getn. + + new syntax/semantics for varargs. + + new long strings and comments. + + new `mod' operator (`%') + + new length operator #t + + metatables for all types + API: + + new functions: lua_createtable, lua_get(set)field, lua_push(to)integer. + + user supplies memory allocator (lua_open becomes lua_newstate). + + luaopen_* functions must be called through Lua. + Implementation: + + new configuration scheme via luaconf.h. + + incremental garbage collection. + + better handling of end-of-line in the lexer. + + fully reentrant parser (new Lua function `load') + + better support for 64-bit machines. + + native loadlib support for Mac OS X. + + standard distribution in only one library (lualib.a merged into lua.a) + +* Changes from version 4.0 to 5.0 + ------------------------------- + Language: + + lexical scoping. + + Lua coroutines. + + standard libraries now packaged in tables. + + tags replaced by metatables and tag methods replaced by metamethods, + stored in metatables. + + proper tail calls. + + each function can have its own global table, which can be shared. + + new __newindex metamethod, called when we insert a new key into a table. + + new block comments: --[[ ... ]]. + + new generic for. + + new weak tables. + + new boolean type. + + new syntax "local function". + + (f()) returns the first value returned by f. + + {f()} fills a table with all values returned by f. + + \n ignored in [[\n . + + fixed and-or priorities. + + more general syntax for function definition (e.g. function a.x.y:f()...end). + + more general syntax for function calls (e.g. (print or write)(9)). + + new functions (time/date, tmpfile, unpack, require, load*, etc.). + API: + + chunks are loaded by using lua_load; new luaL_loadfile and luaL_loadbuffer. + + introduced lightweight userdata, a simple "void*" without a metatable. + + new error handling protocol: the core no longer prints error messages; + all errors are reported to the caller on the stack. + + new lua_atpanic for host cleanup. + + new, signal-safe, hook scheme. + Implementation: + + new license: MIT. + + new, faster, register-based virtual machine. + + support for external multithreading and coroutines. + + new and consistent error message format. + + the core no longer needs "stdio.h" for anything (except for a single + use of sprintf to convert numbers to strings). + + lua.c now runs the environment variable LUA_INIT, if present. It can + be "@filename", to run a file, or the chunk itself. + + support for user extensions in lua.c. + sample implementation given for command line editing. + + new dynamic loading library, active by default on several platforms. + + safe garbage-collector metamethods. + + precompiled bytecodes checked for integrity (secure binary dostring). + + strings are fully aligned. + + position capture in string.find. + + read('*l') can read lines with embedded zeros. + +* Changes from version 3.2 to 4.0 + ------------------------------- + Language: + + new "break" and "for" statements (both numerical and for tables). + + uniform treatment of globals: globals are now stored in a Lua table. + + improved error messages. + + no more '$debug': full speed *and* full debug information. + + new read form: read(N) for next N bytes. + + general read patterns now deprecated. + (still available with -DCOMPAT_READPATTERNS.) + + all return values are passed as arguments for the last function + (old semantics still available with -DLUA_COMPAT_ARGRET) + + garbage collection tag methods for tables now deprecated. + + there is now only one tag method for order. + API: + + New API: fully re-entrant, simpler, and more efficient. + + New debug API. + Implementation: + + faster than ever: cleaner virtual machine and new hashing algorithm. + + non-recursive garbage-collector algorithm. + + reduced memory usage for programs with many strings. + + improved treatment for memory allocation errors. + + improved support for 16-bit machines (we hope). + + code now compiles unmodified as both ANSI C and C++. + + numbers in bases other than 10 are converted using strtoul. + + new -f option in Lua to support #! scripts. + + luac can now combine text and binaries. + +* Changes from version 3.1 to 3.2 + ------------------------------- + + redirected all output in Lua's core to _ERRORMESSAGE and _ALERT. + + increased limit on the number of constants and globals per function + (from 2^16 to 2^24). + + debugging info (lua_debug and hooks) moved into lua_state and new API + functions provided to get and set this info. + + new debug lib gives full debugging access within Lua. + + new table functions "foreachi", "sort", "tinsert", "tremove", "getn". + + new io functions "flush", "seek". + +* Changes from version 3.0 to 3.1 + ------------------------------- + + NEW FEATURE: anonymous functions with closures (via "upvalues"). + + new syntax: + - local variables in chunks. + - better scope control with DO block END. + - constructors can now be also written: { record-part; list-part }. + - more general syntax for function calls and lvalues, e.g.: + f(x).y=1 + o:f(x,y):g(z) + f"string" is sugar for f("string") + + strings may now contain arbitrary binary data (e.g., embedded zeros). + + major code re-organization and clean-up; reduced module interdependecies. + + no arbitrary limits on the total number of constants and globals. + + support for multiple global contexts. + + better syntax error messages. + + new traversal functions "foreach" and "foreachvar". + + the default for numbers is now double. + changing it to use floats or longs is easy. + + complete debug information stored in pre-compiled chunks. + + sample interpreter now prompts user when run interactively, and also + handles control-C interruptions gracefully. + +* Changes from version 2.5 to 3.0 + ------------------------------- + + NEW CONCEPT: "tag methods". + Tag methods replace fallbacks as the meta-mechanism for extending the + semantics of Lua. Whereas fallbacks had a global nature, tag methods + work on objects having the same tag (e.g., groups of tables). + Existing code that uses fallbacks should work without change. + + new, general syntax for constructors {[exp] = exp, ... }. + + support for handling variable number of arguments in functions (varargs). + + support for conditional compilation ($if ... $else ... $end). + + cleaner semantics in API simplifies host code. + + better support for writing libraries (auxlib.h). + + better type checking and error messages in the standard library. + + luac can now also undump. + +* Changes from version 2.4 to 2.5 + ------------------------------- + + io and string libraries are now based on pattern matching; + the old libraries are still available for compatibility + + dofile and dostring can now return values (via return statement) + + better support for 16- and 64-bit machines + + expanded documentation, with more examples + +* Changes from version 2.2 to 2.4 + ------------------------------- + + external compiler creates portable binary files that can be loaded faster + + interface for debugging and profiling + + new "getglobal" fallback + + new functions for handling references to Lua objects + + new functions in standard lib + + only one copy of each string is stored + + expanded documentation, with more examples + +* Changes from version 2.1 to 2.2 + ------------------------------- + + functions now may be declared with any "lvalue" as a name + + garbage collection of functions + + support for pipes + +* Changes from version 1.1 to 2.1 + ------------------------------- + + object-oriented support + + fallbacks + + simplified syntax for tables + + many internal improvements + +(end of HISTORY) diff --git a/external/mit/lua/dist/INSTALL b/external/mit/lua/dist/INSTALL new file mode 100644 index 000000000..17eb8aee8 --- /dev/null +++ b/external/mit/lua/dist/INSTALL @@ -0,0 +1,99 @@ +INSTALL for Lua 5.1 + +* Building Lua + ------------ + Lua is built in the src directory, but the build process can be + controlled from the top-level Makefile. + + Building Lua on Unix systems should be very easy. First do "make" and + see if your platform is listed. If so, just do "make xxx", where xxx + is your platform name. The platforms currently supported are: + aix ansi bsd freebsd generic linux macosx mingw posix solaris + + If your platform is not listed, try the closest one or posix, generic, + ansi, in this order. + + See below for customization instructions and for instructions on how + to build with other Windows compilers. + + If you want to check that Lua has been built correctly, do "make test" + after building Lua. Also, have a look at the example programs in test. + +* Installing Lua + -------------- + Once you have built Lua, you may want to install it in an official + place in your system. In this case, do "make install". The official + place and the way to install files are defined in Makefile. You must + have the right permissions to install files. + + If you want to build and install Lua in one step, do "make xxx install", + where xxx is your platform name. + + If you want to install Lua locally, then do "make local". This will + create directories bin, include, lib, man, and install Lua there as + follows: + + bin: lua luac + include: lua.h luaconf.h lualib.h lauxlib.h lua.hpp + lib: liblua.a + man/man1: lua.1 luac.1 + + These are the only directories you need for development. + + There are man pages for lua and luac, in both nroff and html, and a + reference manual in html in doc, some sample code in test, and some + useful stuff in etc. You don't need these directories for development. + + If you want to install Lua locally, but in some other directory, do + "make install INSTALL_TOP=xxx", where xxx is your chosen directory. + + See below for instructions for Windows and other systems. + +* Customization + ------------- + Three things can be customized by editing a file: + - Where and how to install Lua -- edit Makefile. + - How to build Lua -- edit src/Makefile. + - Lua features -- edit src/luaconf.h. + + You don't actually need to edit the Makefiles because you may set the + relevant variables when invoking make. + + On the other hand, if you need to select some Lua features, you'll need + to edit src/luaconf.h. The edited file will be the one installed, and + it will be used by any Lua clients that you build, to ensure consistency. + + We strongly recommend that you enable dynamic loading. This is done + automatically for all platforms listed above that have this feature + (and also Windows). See src/luaconf.h and also src/Makefile. + +* Building Lua on Windows and other systems + ----------------------------------------- + If you're not using the usual Unix tools, then the instructions for + building Lua depend on the compiler you use. You'll need to create + projects (or whatever your compiler uses) for building the library, + the interpreter, and the compiler, as follows: + + library: lapi.c lcode.c ldebug.c ldo.c ldump.c lfunc.c lgc.c llex.c + lmem.c lobject.c lopcodes.c lparser.c lstate.c lstring.c + ltable.c ltm.c lundump.c lvm.c lzio.c + lauxlib.c lbaselib.c ldblib.c liolib.c lmathlib.c loslib.c + ltablib.c lstrlib.c loadlib.c linit.c + + interpreter: library, lua.c + + compiler: library, luac.c print.c + + If you use Visual Studio .NET, you can use etc/luavs.bat in its + "Command Prompt". + + If all you want is to build the Lua interpreter, you may put all .c files + in a single project, except for luac.c and print.c. Or just use etc/all.c. + + To use Lua as a library in your own programs, you'll need to know how to + create and use libraries with your compiler. + + As mentioned above, you may edit luaconf.h to select some features before + building Lua. + +(end of INSTALL) diff --git a/external/mit/lua/dist/Makefile b/external/mit/lua/dist/Makefile new file mode 100644 index 000000000..209a13244 --- /dev/null +++ b/external/mit/lua/dist/Makefile @@ -0,0 +1,128 @@ +# makefile for installing Lua +# see INSTALL for installation instructions +# see src/Makefile and src/luaconf.h for further customization + +# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT ======================= + +# Your platform. See PLATS for possible values. +PLAT= none + +# Where to install. The installation starts in the src and doc directories, +# so take care if INSTALL_TOP is not an absolute path. +INSTALL_TOP= /usr/local +INSTALL_BIN= $(INSTALL_TOP)/bin +INSTALL_INC= $(INSTALL_TOP)/include +INSTALL_LIB= $(INSTALL_TOP)/lib +INSTALL_MAN= $(INSTALL_TOP)/man/man1 +# +# You probably want to make INSTALL_LMOD and INSTALL_CMOD consistent with +# LUA_ROOT, LUA_LDIR, and LUA_CDIR in luaconf.h (and also with etc/lua.pc). +INSTALL_LMOD= $(INSTALL_TOP)/share/lua/$V +INSTALL_CMOD= $(INSTALL_TOP)/lib/lua/$V + +# How to install. If your install program does not support "-p", then you +# may have to run ranlib on the installed liblua.a (do "make ranlib"). +INSTALL= install -p +INSTALL_EXEC= $(INSTALL) -m 0755 +INSTALL_DATA= $(INSTALL) -m 0644 +# +# If you don't have install you can use cp instead. +# INSTALL= cp -p +# INSTALL_EXEC= $(INSTALL) +# INSTALL_DATA= $(INSTALL) + +# Utilities. +MKDIR= mkdir -p +RANLIB= ranlib + +# == END OF USER SETTINGS. NO NEED TO CHANGE ANYTHING BELOW THIS LINE ========= + +# Convenience platforms targets. +PLATS= aix ansi bsd freebsd generic linux macosx mingw posix solaris + +# What to install. +TO_BIN= lua luac +TO_INC= lua.h luaconf.h lualib.h lauxlib.h ../etc/lua.hpp +TO_LIB= liblua.a +TO_MAN= lua.1 luac.1 + +# Lua version and release. +V= 5.1 +R= 5.1.5 + +all: $(PLAT) + +$(PLATS) clean: + cd src && $(MAKE) $@ + +test: dummy + src/lua test/hello.lua + +install: dummy + cd src && $(MKDIR) $(INSTALL_BIN) $(INSTALL_INC) $(INSTALL_LIB) $(INSTALL_MAN) $(INSTALL_LMOD) $(INSTALL_CMOD) + cd src && $(INSTALL_EXEC) $(TO_BIN) $(INSTALL_BIN) + cd src && $(INSTALL_DATA) $(TO_INC) $(INSTALL_INC) + cd src && $(INSTALL_DATA) $(TO_LIB) $(INSTALL_LIB) + cd doc && $(INSTALL_DATA) $(TO_MAN) $(INSTALL_MAN) + +ranlib: + cd src && cd $(INSTALL_LIB) && $(RANLIB) $(TO_LIB) + +local: + $(MAKE) install INSTALL_TOP=.. + +none: + @echo "Please do" + @echo " make PLATFORM" + @echo "where PLATFORM is one of these:" + @echo " $(PLATS)" + @echo "See INSTALL for complete instructions." + +# make may get confused with test/ and INSTALL in a case-insensitive OS +dummy: + +# echo config parameters +echo: + @echo "" + @echo "These are the parameters currently set in src/Makefile to build Lua $R:" + @echo "" + @cd src && $(MAKE) -s echo + @echo "" + @echo "These are the parameters currently set in Makefile to install Lua $R:" + @echo "" + @echo "PLAT = $(PLAT)" + @echo "INSTALL_TOP = $(INSTALL_TOP)" + @echo "INSTALL_BIN = $(INSTALL_BIN)" + @echo "INSTALL_INC = $(INSTALL_INC)" + @echo "INSTALL_LIB = $(INSTALL_LIB)" + @echo "INSTALL_MAN = $(INSTALL_MAN)" + @echo "INSTALL_LMOD = $(INSTALL_LMOD)" + @echo "INSTALL_CMOD = $(INSTALL_CMOD)" + @echo "INSTALL_EXEC = $(INSTALL_EXEC)" + @echo "INSTALL_DATA = $(INSTALL_DATA)" + @echo "" + @echo "See also src/luaconf.h ." + @echo "" + +# echo private config parameters +pecho: + @echo "V = $(V)" + @echo "R = $(R)" + @echo "TO_BIN = $(TO_BIN)" + @echo "TO_INC = $(TO_INC)" + @echo "TO_LIB = $(TO_LIB)" + @echo "TO_MAN = $(TO_MAN)" + +# echo config parameters as Lua code +# uncomment the last sed expression if you want nil instead of empty strings +lecho: + @echo "-- installation parameters for Lua $R" + @echo "VERSION = '$V'" + @echo "RELEASE = '$R'" + @$(MAKE) echo | grep = | sed -e 's/= /= "/' -e 's/$$/"/' #-e 's/""/nil/' + @echo "-- EOF" + +# list targets that do not create files (but not all makes understand .PHONY) +.PHONY: all $(PLATS) clean test install local none dummy echo pecho lecho + +# (end of Makefile) diff --git a/external/mit/lua/dist/README b/external/mit/lua/dist/README new file mode 100644 index 000000000..11b4dff70 --- /dev/null +++ b/external/mit/lua/dist/README @@ -0,0 +1,37 @@ +README for Lua 5.1 + +See INSTALL for installation instructions. +See HISTORY for a summary of changes since the last released version. + +* What is Lua? + ------------ + Lua is a powerful, light-weight programming language designed for extending + applications. Lua is also frequently used as a general-purpose, stand-alone + language. Lua is free software. + + For complete information, visit Lua's web site at http://www.lua.org/ . + For an executive summary, see http://www.lua.org/about.html . + + Lua has been used in many different projects around the world. + For a short list, see http://www.lua.org/uses.html . + +* Availability + ------------ + Lua is freely available for both academic and commercial purposes. + See COPYRIGHT and http://www.lua.org/license.html for details. + Lua can be downloaded at http://www.lua.org/download.html . + +* Installation + ------------ + Lua is implemented in pure ANSI C, and compiles unmodified in all known + platforms that have an ANSI C compiler. In most Unix-like platforms, simply + do "make" with a suitable target. See INSTALL for detailed instructions. + +* Origin + ------ + Lua is developed at Lua.org, a laboratory of the Department of Computer + Science of PUC-Rio (the Pontifical Catholic University of Rio de Janeiro + in Brazil). + For more information about the authors, see http://www.lua.org/authors.html . + +(end of README) diff --git a/external/mit/lua/dist/doc/contents.html b/external/mit/lua/dist/doc/contents.html new file mode 100644 index 000000000..3d83da98a --- /dev/null +++ b/external/mit/lua/dist/doc/contents.html @@ -0,0 +1,497 @@ + + + +Lua 5.1 Reference Manual - contents + + + + + + + +
    +

    + +Lua 5.1 Reference Manual +

    + +

    +The reference manual is the official definition of the Lua language. +For a complete introduction to Lua programming, see the book +Programming in Lua. + +

    +This manual is also available as a book: +

    + + + +Lua 5.1 Reference Manual +
    by R. Ierusalimschy, L. H. de Figueiredo, W. Celes +
    Lua.org, August 2006 +
    ISBN 85-903798-3-3 +
    +
    + +

    +Buy a copy +of this book and +help to support +the Lua project. + +

    +start +· +contents +· +index +· +other versions +


    + +Copyright © 2006–2012 Lua.org, PUC-Rio. +Freely available under the terms of the +Lua license. + + +

    Contents

    + + +

    Index

    + + + + + + + +
    +

    Lua functions

    +_G
    +_VERSION
    +

    + +assert
    +collectgarbage
    +dofile
    +error
    +getfenv
    +getmetatable
    +ipairs
    +load
    +loadfile
    +loadstring
    +module
    +next
    +pairs
    +pcall
    +print
    +rawequal
    +rawget
    +rawset
    +require
    +select
    +setfenv
    +setmetatable
    +tonumber
    +tostring
    +type
    +unpack
    +xpcall
    +

    + +coroutine.create
    +coroutine.resume
    +coroutine.running
    +coroutine.status
    +coroutine.wrap
    +coroutine.yield
    +

    + +debug.debug
    +debug.getfenv
    +debug.gethook
    +debug.getinfo
    +debug.getlocal
    +debug.getmetatable
    +debug.getregistry
    +debug.getupvalue
    +debug.setfenv
    +debug.sethook
    +debug.setlocal
    +debug.setmetatable
    +debug.setupvalue
    +debug.traceback
    + +

    +

     

    +file:close
    +file:flush
    +file:lines
    +file:read
    +file:seek
    +file:setvbuf
    +file:write
    +

    + +io.close
    +io.flush
    +io.input
    +io.lines
    +io.open
    +io.output
    +io.popen
    +io.read
    +io.stderr
    +io.stdin
    +io.stdout
    +io.tmpfile
    +io.type
    +io.write
    +

    + +math.abs
    +math.acos
    +math.asin
    +math.atan
    +math.atan2
    +math.ceil
    +math.cos
    +math.cosh
    +math.deg
    +math.exp
    +math.floor
    +math.fmod
    +math.frexp
    +math.huge
    +math.ldexp
    +math.log
    +math.log10
    +math.max
    +math.min
    +math.modf
    +math.pi
    +math.pow
    +math.rad
    +math.random
    +math.randomseed
    +math.sin
    +math.sinh
    +math.sqrt
    +math.tan
    +math.tanh
    +

    + +os.clock
    +os.date
    +os.difftime
    +os.execute
    +os.exit
    +os.getenv
    +os.remove
    +os.rename
    +os.setlocale
    +os.time
    +os.tmpname
    +

    + +package.cpath
    +package.loaded
    +package.loaders
    +package.loadlib
    +package.path
    +package.preload
    +package.seeall
    +

    + +string.byte
    +string.char
    +string.dump
    +string.find
    +string.format
    +string.gmatch
    +string.gsub
    +string.len
    +string.lower
    +string.match
    +string.rep
    +string.reverse
    +string.sub
    +string.upper
    +

    + +table.concat
    +table.insert
    +table.maxn
    +table.remove
    +table.sort
    + +

    +

    C API

    +lua_Alloc
    +lua_CFunction
    +lua_Debug
    +lua_Hook
    +lua_Integer
    +lua_Number
    +lua_Reader
    +lua_State
    +lua_Writer
    +

    + +lua_atpanic
    +lua_call
    +lua_checkstack
    +lua_close
    +lua_concat
    +lua_cpcall
    +lua_createtable
    +lua_dump
    +lua_equal
    +lua_error
    +lua_gc
    +lua_getallocf
    +lua_getfenv
    +lua_getfield
    +lua_getglobal
    +lua_gethook
    +lua_gethookcount
    +lua_gethookmask
    +lua_getinfo
    +lua_getlocal
    +lua_getmetatable
    +lua_getstack
    +lua_gettable
    +lua_gettop
    +lua_getupvalue
    +lua_insert
    +lua_isboolean
    +lua_iscfunction
    +lua_isfunction
    +lua_islightuserdata
    +lua_isnil
    +lua_isnone
    +lua_isnoneornil
    +lua_isnumber
    +lua_isstring
    +lua_istable
    +lua_isthread
    +lua_isuserdata
    +lua_lessthan
    +lua_load
    +lua_newstate
    +lua_newtable
    +lua_newthread
    +lua_newuserdata
    +lua_next
    +lua_objlen
    +lua_pcall
    +lua_pop
    +lua_pushboolean
    +lua_pushcclosure
    +lua_pushcfunction
    +lua_pushfstring
    +lua_pushinteger
    +lua_pushlightuserdata
    +lua_pushliteral
    +lua_pushlstring
    +lua_pushnil
    +lua_pushnumber
    +lua_pushstring
    +lua_pushthread
    +lua_pushvalue
    +lua_pushvfstring
    +lua_rawequal
    +lua_rawget
    +lua_rawgeti
    +lua_rawset
    +lua_rawseti
    +lua_register
    +lua_remove
    +lua_replace
    +lua_resume
    +lua_setallocf
    +lua_setfenv
    +lua_setfield
    +lua_setglobal
    +lua_sethook
    +lua_setlocal
    +lua_setmetatable
    +lua_settable
    +lua_settop
    +lua_setupvalue
    +lua_status
    +lua_toboolean
    +lua_tocfunction
    +lua_tointeger
    +lua_tolstring
    +lua_tonumber
    +lua_topointer
    +lua_tostring
    +lua_tothread
    +lua_touserdata
    +lua_type
    +lua_typename
    +lua_upvalueindex
    +lua_xmove
    +lua_yield
    + +

    +

    auxiliary library

    +luaL_Buffer
    +luaL_Reg
    +

    + +luaL_addchar
    +luaL_addlstring
    +luaL_addsize
    +luaL_addstring
    +luaL_addvalue
    +luaL_argcheck
    +luaL_argerror
    +luaL_buffinit
    +luaL_callmeta
    +luaL_checkany
    +luaL_checkint
    +luaL_checkinteger
    +luaL_checklong
    +luaL_checklstring
    +luaL_checknumber
    +luaL_checkoption
    +luaL_checkstack
    +luaL_checkstring
    +luaL_checktype
    +luaL_checkudata
    +luaL_dofile
    +luaL_dostring
    +luaL_error
    +luaL_getmetafield
    +luaL_getmetatable
    +luaL_gsub
    +luaL_loadbuffer
    +luaL_loadfile
    +luaL_loadstring
    +luaL_newmetatable
    +luaL_newstate
    +luaL_openlibs
    +luaL_optint
    +luaL_optinteger
    +luaL_optlong
    +luaL_optlstring
    +luaL_optnumber
    +luaL_optstring
    +luaL_prepbuffer
    +luaL_pushresult
    +luaL_ref
    +luaL_register
    +luaL_typename
    +luaL_typerror
    +luaL_unref
    +luaL_where
    + +

    +

    + +


    + +Last update: +Mon Feb 13 18:53:32 BRST 2012 + + + + + diff --git a/external/mit/lua/dist/doc/cover.png b/external/mit/lua/dist/doc/cover.png new file mode 100644 index 000000000..2dbb19812 Binary files /dev/null and b/external/mit/lua/dist/doc/cover.png differ diff --git a/external/mit/lua/dist/doc/logo.gif b/external/mit/lua/dist/doc/logo.gif new file mode 100644 index 000000000..2f5e4ac2e Binary files /dev/null and b/external/mit/lua/dist/doc/logo.gif differ diff --git a/external/mit/lua/dist/doc/lua.1 b/external/mit/lua/dist/doc/lua.1 new file mode 100644 index 000000000..b14bef56f --- /dev/null +++ b/external/mit/lua/dist/doc/lua.1 @@ -0,0 +1,165 @@ +.\" $NetBSD: lua.1,v 1.1.1.2 2012/03/15 00:08:15 alnsn Exp $ +.\" +.\" $Id: lua.1,v 1.1.1.2 2012/03/15 00:08:15 alnsn Exp $ +.TH LUA 1 "$Date: 2012/03/15 00:08:15 $" +.SH NAME +lua \- Lua interpreter +.SH SYNOPSIS +.B lua +[ +.I options +] +[ +.I script +[ +.I args +] +] +.SH DESCRIPTION +.B lua +is the stand-alone Lua interpreter. +It loads and executes Lua programs, +either in textual source form or +in precompiled binary form. +(Precompiled binaries are output by +.BR luac , +the Lua compiler.) +.B lua +can be used as a batch interpreter and also interactively. +.LP +The given +.I options +(see below) +are executed and then +the Lua program in file +.I script +is loaded and executed. +The given +.I args +are available to +.I script +as strings in a global table named +.BR arg . +If these arguments contain spaces or other characters special to the shell, +then they should be quoted +(but note that the quotes will be removed by the shell). +The arguments in +.B arg +start at 0, +which contains the string +.RI ' script '. +The index of the last argument is stored in +.BR arg.n . +The arguments given in the command line before +.IR script , +including the name of the interpreter, +are available in negative indices in +.BR arg . +.LP +At the very start, +before even handling the command line, +.B lua +executes the contents of the environment variable +.BR LUA_INIT , +if it is defined. +If the value of +.B LUA_INIT +is of the form +.RI '@ filename ', +then +.I filename +is executed. +Otherwise, the string is assumed to be a Lua statement and is executed. +.LP +Options start with +.B '\-' +and are described below. +You can use +.B "'\--'" +to signal the end of options. +.LP +If no arguments are given, +then +.B "\-v \-i" +is assumed when the standard input is a terminal; +otherwise, +.B "\-" +is assumed. +.LP +In interactive mode, +.B lua +prompts the user, +reads lines from the standard input, +and executes them as they are read. +If a line does not contain a complete statement, +then a secondary prompt is displayed and +lines are read until a complete statement is formed or +a syntax error is found. +So, one way to interrupt the reading of an incomplete statement is +to force a syntax error: +adding a +.B ';' +in the middle of a statement is a sure way of forcing a syntax error +(except inside multiline strings and comments; these must be closed explicitly). +If a line starts with +.BR '=' , +then +.B lua +displays the values of all the expressions in the remainder of the +line. The expressions must be separated by commas. +The primary prompt is the value of the global variable +.BR _PROMPT , +if this value is a string; +otherwise, the default prompt is used. +Similarly, the secondary prompt is the value of the global variable +.BR _PROMPT2 . +So, +to change the prompts, +set the corresponding variable to a string of your choice. +You can do that after calling the interpreter +or on the command line +(but in this case you have to be careful with quotes +if the prompt string contains a space; otherwise you may confuse the shell.) +The default prompts are "> " and ">> ". +.SH OPTIONS +.TP +.B \- +load and execute the standard input as a file, +that is, +not interactively, +even when the standard input is a terminal. +.TP +.BI \-e " stat" +execute statement +.IR stat . +You need to quote +.I stat +if it contains spaces, quotes, +or other characters special to the shell. +.TP +.B \-i +enter interactive mode after +.I script +is executed. +.TP +.BI \-l " name" +call +.BI require(' name ') +before executing +.IR script . +Typically used to load libraries. +.TP +.B \-v +show version information. +.SH "SEE ALSO" +.BR luac (1) +.br +http://www.lua.org/ +.SH DIAGNOSTICS +Error messages should be self explanatory. +.SH AUTHORS +R. Ierusalimschy, +L. H. de Figueiredo, +and +W. Celes +.\" EOF diff --git a/external/mit/lua/dist/doc/lua.css b/external/mit/lua/dist/doc/lua.css new file mode 100644 index 000000000..7fafbb1bb --- /dev/null +++ b/external/mit/lua/dist/doc/lua.css @@ -0,0 +1,83 @@ +body { + color: #000000 ; + background-color: #FFFFFF ; + font-family: Helvetica, Arial, sans-serif ; + text-align: justify ; + margin-right: 30px ; + margin-left: 30px ; +} + +h1, h2, h3, h4 { + font-family: Verdana, Geneva, sans-serif ; + font-weight: normal ; + font-style: italic ; +} + +h2 { + padding-top: 0.4em ; + padding-bottom: 0.4em ; + padding-left: 30px ; + padding-right: 30px ; + margin-left: -30px ; + background-color: #E0E0FF ; +} + +h3 { + padding-left: 0.5em ; + border-left: solid #E0E0FF 1em ; +} + +table h3 { + padding-left: 0px ; + border-left: none ; +} + +a:link { + color: #000080 ; + background-color: inherit ; + text-decoration: none ; +} + +a:visited { + background-color: inherit ; + text-decoration: none ; +} + +a:link:hover, a:visited:hover { + color: #000080 ; + background-color: #E0E0FF ; +} + +a:link:active, a:visited:active { + color: #FF0000 ; +} + +hr { + border: 0 ; + height: 1px ; + color: #a0a0a0 ; + background-color: #a0a0a0 ; +} + +:target { + background-color: #F8F8F8 ; + padding: 8px ; + border: solid #a0a0a0 2px ; +} + +.footer { + color: gray ; + font-size: small ; +} + +input[type=text] { + border: solid #a0a0a0 2px ; + border-radius: 2em ; + -moz-border-radius: 2em ; + background-image: url('images/search.png') ; + background-repeat: no-repeat; + background-position: 4px center ; + padding-left: 20px ; + height: 2em ; +} + diff --git a/external/mit/lua/dist/doc/lua.html b/external/mit/lua/dist/doc/lua.html new file mode 100644 index 000000000..96b52a9a5 --- /dev/null +++ b/external/mit/lua/dist/doc/lua.html @@ -0,0 +1,172 @@ + + + +LUA man page + + + + + +

    NAME

    +lua - Lua interpreter +

    SYNOPSIS

    +lua +[ +options +] +[ +script +[ +args +] +] +

    DESCRIPTION

    +lua +is the stand-alone Lua interpreter. +It loads and executes Lua programs, +either in textual source form or +in precompiled binary form. +(Precompiled binaries are output by +luac, +the Lua compiler.) +lua +can be used as a batch interpreter and also interactively. +

    +The given +options +(see below) +are executed and then +the Lua program in file +script +is loaded and executed. +The given +args +are available to +script +as strings in a global table named +arg. +If these arguments contain spaces or other characters special to the shell, +then they should be quoted +(but note that the quotes will be removed by the shell). +The arguments in +arg +start at 0, +which contains the string +'script'. +The index of the last argument is stored in +arg.n. +The arguments given in the command line before +script, +including the name of the interpreter, +are available in negative indices in +arg. +

    +At the very start, +before even handling the command line, +lua +executes the contents of the environment variable +LUA_INIT, +if it is defined. +If the value of +LUA_INIT +is of the form +'@filename', +then +filename +is executed. +Otherwise, the string is assumed to be a Lua statement and is executed. +

    +Options start with +'-' +and are described below. +You can use +'--' +to signal the end of options. +

    +If no arguments are given, +then +"-v -i" +is assumed when the standard input is a terminal; +otherwise, +"-" +is assumed. +

    +In interactive mode, +lua +prompts the user, +reads lines from the standard input, +and executes them as they are read. +If a line does not contain a complete statement, +then a secondary prompt is displayed and +lines are read until a complete statement is formed or +a syntax error is found. +So, one way to interrupt the reading of an incomplete statement is +to force a syntax error: +adding a +';' +in the middle of a statement is a sure way of forcing a syntax error +(except inside multiline strings and comments; these must be closed explicitly). +If a line starts with +'=', +then +lua +displays the values of all the expressions in the remainder of the +line. The expressions must be separated by commas. +The primary prompt is the value of the global variable +_PROMPT, +if this value is a string; +otherwise, the default prompt is used. +Similarly, the secondary prompt is the value of the global variable +_PROMPT2. +So, +to change the prompts, +set the corresponding variable to a string of your choice. +You can do that after calling the interpreter +or on the command line +(but in this case you have to be careful with quotes +if the prompt string contains a space; otherwise you may confuse the shell.) +The default prompts are "> " and ">> ". +

    OPTIONS

    +

    +- +load and execute the standard input as a file, +that is, +not interactively, +even when the standard input is a terminal. +

    +-e stat +execute statement +stat. +You need to quote +stat +if it contains spaces, quotes, +or other characters special to the shell. +

    +-i +enter interactive mode after +script +is executed. +

    +-l name +call +require('name') +before executing +script. +Typically used to load libraries. +

    +-v +show version information. +

    SEE ALSO

    +luac(1) +
    +http://www.lua.org/ +

    DIAGNOSTICS

    +Error messages should be self explanatory. +

    AUTHORS

    +R. Ierusalimschy, +L. H. de Figueiredo, +and +W. Celes + + + diff --git a/external/mit/lua/dist/doc/luac.1 b/external/mit/lua/dist/doc/luac.1 new file mode 100644 index 000000000..783b2c696 --- /dev/null +++ b/external/mit/lua/dist/doc/luac.1 @@ -0,0 +1,138 @@ +.\" $NetBSD: luac.1,v 1.1.1.2 2012/03/15 00:08:21 alnsn Exp $ +.\" +.\" $Id: luac.1,v 1.1.1.2 2012/03/15 00:08:21 alnsn Exp $ +.TH LUAC 1 "$Date: 2012/03/15 00:08:21 $" +.SH NAME +luac \- Lua compiler +.SH SYNOPSIS +.B luac +[ +.I options +] [ +.I filenames +] +.SH DESCRIPTION +.B luac +is the Lua compiler. +It translates programs written in the Lua programming language +into binary files that can be later loaded and executed. +.LP +The main advantages of precompiling chunks are: +faster loading, +protecting source code from accidental user changes, +and +off-line syntax checking. +.LP +Pre-compiling does not imply faster execution +because in Lua chunks are always compiled into bytecodes before being executed. +.B luac +simply allows those bytecodes to be saved in a file for later execution. +.LP +Pre-compiled chunks are not necessarily smaller than the corresponding source. +The main goal in pre-compiling is faster loading. +.LP +The binary files created by +.B luac +are portable only among architectures with the same word size and byte order. +.LP +.B luac +produces a single output file containing the bytecodes +for all source files given. +By default, +the output file is named +.BR luac.out , +but you can change this with the +.B \-o +option. +.LP +In the command line, +you can mix +text files containing Lua source and +binary files containing precompiled chunks. +This is useful to combine several precompiled chunks, +even from different (but compatible) platforms, +into a single precompiled chunk. +.LP +You can use +.B "'\-'" +to indicate the standard input as a source file +and +.B "'\--'" +to signal the end of options +(that is, +all remaining arguments will be treated as files even if they start with +.BR "'\-'" ). +.LP +The internal format of the binary files produced by +.B luac +is likely to change when a new version of Lua is released. +So, +save the source files of all Lua programs that you precompile. +.LP +.SH OPTIONS +Options must be separate. +.TP +.B \-l +produce a listing of the compiled bytecode for Lua's virtual machine. +Listing bytecodes is useful to learn about Lua's virtual machine. +If no files are given, then +.B luac +loads +.B luac.out +and lists its contents. +.TP +.BI \-o " file" +output to +.IR file , +instead of the default +.BR luac.out . +(You can use +.B "'\-'" +for standard output, +but not on platforms that open standard output in text mode.) +The output file may be a source file because +all files are loaded before the output file is written. +Be careful not to overwrite precious files. +.TP +.B \-p +load files but do not generate any output file. +Used mainly for syntax checking and for testing precompiled chunks: +corrupted files will probably generate errors when loaded. +Lua always performs a thorough integrity test on precompiled chunks. +Bytecode that passes this test is completely safe, +in the sense that it will not break the interpreter. +However, +there is no guarantee that such code does anything sensible. +(None can be given, because the halting problem is unsolvable.) +If no files are given, then +.B luac +loads +.B luac.out +and tests its contents. +No messages are displayed if the file passes the integrity test. +.TP +.B \-s +strip debug information before writing the output file. +This saves some space in very large chunks, +but if errors occur when running a stripped chunk, +then the error messages may not contain the full information they usually do. +For instance, +line numbers and names of local variables are lost. +.TP +.B \-v +show version information. +.SH FILES +.TP 15 +.B luac.out +default output file +.SH "SEE ALSO" +.BR lua (1) +.br +http://www.lua.org/ +.SH DIAGNOSTICS +Error messages should be self explanatory. +.SH AUTHORS +L. H. de Figueiredo, +R. Ierusalimschy and +W. Celes +.\" EOF diff --git a/external/mit/lua/dist/doc/luac.html b/external/mit/lua/dist/doc/luac.html new file mode 100644 index 000000000..be4e80aab --- /dev/null +++ b/external/mit/lua/dist/doc/luac.html @@ -0,0 +1,145 @@ + + + +LUAC man page + + + + + +

    NAME

    +luac - Lua compiler +

    SYNOPSIS

    +luac +[ +options +] [ +filenames +] +

    DESCRIPTION

    +luac +is the Lua compiler. +It translates programs written in the Lua programming language +into binary files that can be later loaded and executed. +

    +The main advantages of precompiling chunks are: +faster loading, +protecting source code from accidental user changes, +and +off-line syntax checking. +

    +Precompiling does not imply faster execution +because in Lua chunks are always compiled into bytecodes before being executed. +luac +simply allows those bytecodes to be saved in a file for later execution. +

    +Precompiled chunks are not necessarily smaller than the corresponding source. +The main goal in precompiling is faster loading. +

    +The binary files created by +luac +are portable only among architectures with the same word size and byte order. +

    +luac +produces a single output file containing the bytecodes +for all source files given. +By default, +the output file is named +luac.out, +but you can change this with the +-o +option. +

    +In the command line, +you can mix +text files containing Lua source and +binary files containing precompiled chunks. +This is useful because several precompiled chunks, +even from different (but compatible) platforms, +can be combined into a single precompiled chunk. +

    +You can use +'-' +to indicate the standard input as a source file +and +'--' +to signal the end of options +(that is, +all remaining arguments will be treated as files even if they start with +'-'). +

    +The internal format of the binary files produced by +luac +is likely to change when a new version of Lua is released. +So, +save the source files of all Lua programs that you precompile. +

    +

    OPTIONS

    +Options must be separate. +

    +-l +produce a listing of the compiled bytecode for Lua's virtual machine. +Listing bytecodes is useful to learn about Lua's virtual machine. +If no files are given, then +luac +loads +luac.out +and lists its contents. +

    +-o file +output to +file, +instead of the default +luac.out. +(You can use +'-' +for standard output, +but not on platforms that open standard output in text mode.) +The output file may be a source file because +all files are loaded before the output file is written. +Be careful not to overwrite precious files. +

    +-p +load files but do not generate any output file. +Used mainly for syntax checking and for testing precompiled chunks: +corrupted files will probably generate errors when loaded. +Lua always performs a thorough integrity test on precompiled chunks. +Bytecode that passes this test is completely safe, +in the sense that it will not break the interpreter. +However, +there is no guarantee that such code does anything sensible. +(None can be given, because the halting problem is unsolvable.) +If no files are given, then +luac +loads +luac.out +and tests its contents. +No messages are displayed if the file passes the integrity test. +

    +-s +strip debug information before writing the output file. +This saves some space in very large chunks, +but if errors occur when running a stripped chunk, +then the error messages may not contain the full information they usually do. +For instance, +line numbers and names of local variables are lost. +

    +-v +show version information. +

    FILES

    +

    +luac.out +default output file +

    SEE ALSO

    +lua(1) +
    +http://www.lua.org/ +

    DIAGNOSTICS

    +Error messages should be self explanatory. +

    AUTHORS

    +L. H. de Figueiredo, +R. Ierusalimschy and +W. Celes + + + diff --git a/external/mit/lua/dist/doc/manual.css b/external/mit/lua/dist/doc/manual.css new file mode 100644 index 000000000..b49b36293 --- /dev/null +++ b/external/mit/lua/dist/doc/manual.css @@ -0,0 +1,24 @@ +h3 code { + font-family: inherit ; + font-size: inherit ; +} + +pre, code { + font-size: 12pt ; +} + +span.apii { + float: right ; + font-family: inherit ; + font-style: normal ; + font-size: small ; + color: gray ; +} + +p+h1, ul+h1 { + padding-top: 0.4em ; + padding-bottom: 0.4em ; + padding-left: 30px ; + margin-left: -30px ; + background-color: #E0E0FF ; +} diff --git a/external/mit/lua/dist/doc/manual.html b/external/mit/lua/dist/doc/manual.html new file mode 100644 index 000000000..a8c88c412 --- /dev/null +++ b/external/mit/lua/dist/doc/manual.html @@ -0,0 +1,8804 @@ + + + + +Lua 5.1 Reference Manual + + + + + + + +
    +

    + +Lua 5.1 Reference Manual +

    + +by Roberto Ierusalimschy, Luiz Henrique de Figueiredo, Waldemar Celes +

    + +Copyright © 2006–2012 Lua.org, PUC-Rio. +Freely available under the terms of the +Lua license. + +


    +

    + +contents +· +index +· +other versions + + +

    + + + + + + +

    1 - Introduction

    + +

    +Lua is an extension programming language designed to support +general procedural programming with data description +facilities. +It also offers good support for object-oriented programming, +functional programming, and data-driven programming. +Lua is intended to be used as a powerful, light-weight +scripting language for any program that needs one. +Lua is implemented as a library, written in clean C +(that is, in the common subset of ANSI C and C++). + + +

    +Being an extension language, Lua has no notion of a "main" program: +it only works embedded in a host client, +called the embedding program or simply the host. +This host program can invoke functions to execute a piece of Lua code, +can write and read Lua variables, +and can register C functions to be called by Lua code. +Through the use of C functions, Lua can be augmented to cope with +a wide range of different domains, +thus creating customized programming languages sharing a syntactical framework. +The Lua distribution includes a sample host program called lua, +which uses the Lua library to offer a complete, stand-alone Lua interpreter. + + +

    +Lua is free software, +and is provided as usual with no guarantees, +as stated in its license. +The implementation described in this manual is available +at Lua's official web site, www.lua.org. + + +

    +Like any other reference manual, +this document is dry in places. +For a discussion of the decisions behind the design of Lua, +see the technical papers available at Lua's web site. +For a detailed introduction to programming in Lua, +see Roberto's book, Programming in Lua (Second Edition). + + + +

    2 - The Language

    + +

    +This section describes the lexis, the syntax, and the semantics of Lua. +In other words, +this section describes +which tokens are valid, +how they can be combined, +and what their combinations mean. + + +

    +The language constructs will be explained using the usual extended BNF notation, +in which +{a} means 0 or more a's, and +[a] means an optional a. +Non-terminals are shown like non-terminal, +keywords are shown like kword, +and other terminal symbols are shown like `=´. +The complete syntax of Lua can be found in §8 +at the end of this manual. + + + +

    2.1 - Lexical Conventions

    + +

    +Names +(also called identifiers) +in Lua can be any string of letters, +digits, and underscores, +not beginning with a digit. +This coincides with the definition of names in most languages. +(The definition of letter depends on the current locale: +any character considered alphabetic by the current locale +can be used in an identifier.) +Identifiers are used to name variables and table fields. + + +

    +The following keywords are reserved +and cannot be used as names: + + +

    +     and       break     do        else      elseif
    +     end       false     for       function  if
    +     in        local     nil       not       or
    +     repeat    return    then      true      until     while
    +
    + +

    +Lua is a case-sensitive language: +and is a reserved word, but And and AND +are two different, valid names. +As a convention, names starting with an underscore followed by +uppercase letters (such as _VERSION) +are reserved for internal global variables used by Lua. + + +

    +The following strings denote other tokens: + +

    +     +     -     *     /     %     ^     #
    +     ==    ~=    <=    >=    <     >     =
    +     (     )     {     }     [     ]
    +     ;     :     ,     .     ..    ...
    +
    + +

    +Literal strings +can be delimited by matching single or double quotes, +and can contain the following C-like escape sequences: +'\a' (bell), +'\b' (backspace), +'\f' (form feed), +'\n' (newline), +'\r' (carriage return), +'\t' (horizontal tab), +'\v' (vertical tab), +'\\' (backslash), +'\"' (quotation mark [double quote]), +and '\'' (apostrophe [single quote]). +Moreover, a backslash followed by a real newline +results in a newline in the string. +A character in a string can also be specified by its numerical value +using the escape sequence \ddd, +where ddd is a sequence of up to three decimal digits. +(Note that if a numerical escape is to be followed by a digit, +it must be expressed using exactly three digits.) +Strings in Lua can contain any 8-bit value, including embedded zeros, +which can be specified as '\0'. + + +

    +Literal strings can also be defined using a long format +enclosed by long brackets. +We define an opening long bracket of level n as an opening +square bracket followed by n equal signs followed by another +opening square bracket. +So, an opening long bracket of level 0 is written as [[, +an opening long bracket of level 1 is written as [=[, +and so on. +A closing long bracket is defined similarly; +for instance, a closing long bracket of level 4 is written as ]====]. +A long string starts with an opening long bracket of any level and +ends at the first closing long bracket of the same level. +Literals in this bracketed form can run for several lines, +do not interpret any escape sequences, +and ignore long brackets of any other level. +They can contain anything except a closing bracket of the proper level. + + +

    +For convenience, +when the opening long bracket is immediately followed by a newline, +the newline is not included in the string. +As an example, in a system using ASCII +(in which 'a' is coded as 97, +newline is coded as 10, and '1' is coded as 49), +the five literal strings below denote the same string: + +

    +     a = 'alo\n123"'
    +     a = "alo\n123\""
    +     a = '\97lo\10\04923"'
    +     a = [[alo
    +     123"]]
    +     a = [==[
    +     alo
    +     123"]==]
    +
    + +

    +A numerical constant can be written with an optional decimal part +and an optional decimal exponent. +Lua also accepts integer hexadecimal constants, +by prefixing them with 0x. +Examples of valid numerical constants are + +

    +     3   3.0   3.1416   314.16e-2   0.31416E1   0xff   0x56
    +
    + +

    +A comment starts with a double hyphen (--) +anywhere outside a string. +If the text immediately after -- is not an opening long bracket, +the comment is a short comment, +which runs until the end of the line. +Otherwise, it is a long comment, +which runs until the corresponding closing long bracket. +Long comments are frequently used to disable code temporarily. + + + + + +

    2.2 - Values and Types

    + +

    +Lua is a dynamically typed language. +This means that +variables do not have types; only values do. +There are no type definitions in the language. +All values carry their own type. + + +

    +All values in Lua are first-class values. +This means that all values can be stored in variables, +passed as arguments to other functions, and returned as results. + + +

    +There are eight basic types in Lua: +nil, boolean, number, +string, function, userdata, +thread, and table. +Nil is the type of the value nil, +whose main property is to be different from any other value; +it usually represents the absence of a useful value. +Boolean is the type of the values false and true. +Both nil and false make a condition false; +any other value makes it true. +Number represents real (double-precision floating-point) numbers. +(It is easy to build Lua interpreters that use other +internal representations for numbers, +such as single-precision float or long integers; +see file luaconf.h.) +String represents arrays of characters. + +Lua is 8-bit clean: +strings can contain any 8-bit character, +including embedded zeros ('\0') (see §2.1). + + +

    +Lua can call (and manipulate) functions written in Lua and +functions written in C +(see §2.5.8). + + +

    +The type userdata is provided to allow arbitrary C data to +be stored in Lua variables. +This type corresponds to a block of raw memory +and has no pre-defined operations in Lua, +except assignment and identity test. +However, by using metatables, +the programmer can define operations for userdata values +(see §2.8). +Userdata values cannot be created or modified in Lua, +only through the C API. +This guarantees the integrity of data owned by the host program. + + +

    +The type thread represents independent threads of execution +and it is used to implement coroutines (see §2.11). +Do not confuse Lua threads with operating-system threads. +Lua supports coroutines on all systems, +even those that do not support threads. + + +

    +The type table implements associative arrays, +that is, arrays that can be indexed not only with numbers, +but with any value (except nil). +Tables can be heterogeneous; +that is, they can contain values of all types (except nil). +Tables are the sole data structuring mechanism in Lua; +they can be used to represent ordinary arrays, +symbol tables, sets, records, graphs, trees, etc. +To represent records, Lua uses the field name as an index. +The language supports this representation by +providing a.name as syntactic sugar for a["name"]. +There are several convenient ways to create tables in Lua +(see §2.5.7). + + +

    +Like indices, +the value of a table field can be of any type (except nil). +In particular, +because functions are first-class values, +table fields can contain functions. +Thus tables can also carry methods (see §2.5.9). + + +

    +Tables, functions, threads, and (full) userdata values are objects: +variables do not actually contain these values, +only references to them. +Assignment, parameter passing, and function returns +always manipulate references to such values; +these operations do not imply any kind of copy. + + +

    +The library function type returns a string describing the type +of a given value. + + + +

    2.2.1 - Coercion

    + +

    +Lua provides automatic conversion between +string and number values at run time. +Any arithmetic operation applied to a string tries to convert +this string to a number, following the usual conversion rules. +Conversely, whenever a number is used where a string is expected, +the number is converted to a string, in a reasonable format. +For complete control over how numbers are converted to strings, +use the format function from the string library +(see string.format). + + + + + + + +

    2.3 - Variables

    + +

    +Variables are places that store values. + +There are three kinds of variables in Lua: +global variables, local variables, and table fields. + + +

    +A single name can denote a global variable or a local variable +(or a function's formal parameter, +which is a particular kind of local variable): + +

    +	var ::= Name
    +

    +Name denotes identifiers, as defined in §2.1. + + +

    +Any variable is assumed to be global unless explicitly declared +as a local (see §2.4.7). +Local variables are lexically scoped: +local variables can be freely accessed by functions +defined inside their scope (see §2.6). + + +

    +Before the first assignment to a variable, its value is nil. + + +

    +Square brackets are used to index a table: + +

    +	var ::= prefixexp `[´ exp `]´
    +

    +The meaning of accesses to global variables +and table fields can be changed via metatables. +An access to an indexed variable t[i] is equivalent to +a call gettable_event(t,i). +(See §2.8 for a complete description of the +gettable_event function. +This function is not defined or callable in Lua. +We use it here only for explanatory purposes.) + + +

    +The syntax var.Name is just syntactic sugar for +var["Name"]: + +

    +	var ::= prefixexp `.´ Name
    +
    + +

    +All global variables live as fields in ordinary Lua tables, +called environment tables or simply +environments (see §2.9). +Each function has its own reference to an environment, +so that all global variables in this function +will refer to this environment table. +When a function is created, +it inherits the environment from the function that created it. +To get the environment table of a Lua function, +you call getfenv. +To replace it, +you call setfenv. +(You can only manipulate the environment of C functions +through the debug library; (see §5.9).) + + +

    +An access to a global variable x +is equivalent to _env.x, +which in turn is equivalent to + +

    +     gettable_event(_env, "x")
    +

    +where _env is the environment of the running function. +(See §2.8 for a complete description of the +gettable_event function. +This function is not defined or callable in Lua. +Similarly, the _env variable is not defined in Lua. +We use them here only for explanatory purposes.) + + + + + +

    2.4 - Statements

    + +

    +Lua supports an almost conventional set of statements, +similar to those in Pascal or C. +This set includes +assignments, control structures, function calls, +and variable declarations. + + + +

    2.4.1 - Chunks

    + +

    +The unit of execution of Lua is called a chunk. +A chunk is simply a sequence of statements, +which are executed sequentially. +Each statement can be optionally followed by a semicolon: + +

    +	chunk ::= {stat [`;´]}
    +

    +There are no empty statements and thus ';;' is not legal. + + +

    +Lua handles a chunk as the body of an anonymous function +with a variable number of arguments +(see §2.5.9). +As such, chunks can define local variables, +receive arguments, and return values. + + +

    +A chunk can be stored in a file or in a string inside the host program. +To execute a chunk, +Lua first pre-compiles the chunk into instructions for a virtual machine, +and then it executes the compiled code +with an interpreter for the virtual machine. + + +

    +Chunks can also be pre-compiled into binary form; +see program luac for details. +Programs in source and compiled forms are interchangeable; +Lua automatically detects the file type and acts accordingly. + + + + + + +

    2.4.2 - Blocks

    +A block is a list of statements; +syntactically, a block is the same as a chunk: + +

    +	block ::= chunk
    +
    + +

    +A block can be explicitly delimited to produce a single statement: + +

    +	stat ::= do block end
    +

    +Explicit blocks are useful +to control the scope of variable declarations. +Explicit blocks are also sometimes used to +add a return or break statement in the middle +of another block (see §2.4.4). + + + + + +

    2.4.3 - Assignment

    + +

    +Lua allows multiple assignments. +Therefore, the syntax for assignment +defines a list of variables on the left side +and a list of expressions on the right side. +The elements in both lists are separated by commas: + +

    +	stat ::= varlist `=´ explist
    +	varlist ::= var {`,´ var}
    +	explist ::= exp {`,´ exp}
    +

    +Expressions are discussed in §2.5. + + +

    +Before the assignment, +the list of values is adjusted to the length of +the list of variables. +If there are more values than needed, +the excess values are thrown away. +If there are fewer values than needed, +the list is extended with as many nil's as needed. +If the list of expressions ends with a function call, +then all values returned by that call enter the list of values, +before the adjustment +(except when the call is enclosed in parentheses; see §2.5). + + +

    +The assignment statement first evaluates all its expressions +and only then are the assignments performed. +Thus the code + +

    +     i = 3
    +     i, a[i] = i+1, 20
    +

    +sets a[3] to 20, without affecting a[4] +because the i in a[i] is evaluated (to 3) +before it is assigned 4. +Similarly, the line + +

    +     x, y = y, x
    +

    +exchanges the values of x and y, +and + +

    +     x, y, z = y, z, x
    +

    +cyclically permutes the values of x, y, and z. + + +

    +The meaning of assignments to global variables +and table fields can be changed via metatables. +An assignment to an indexed variable t[i] = val is equivalent to +settable_event(t,i,val). +(See §2.8 for a complete description of the +settable_event function. +This function is not defined or callable in Lua. +We use it here only for explanatory purposes.) + + +

    +An assignment to a global variable x = val +is equivalent to the assignment +_env.x = val, +which in turn is equivalent to + +

    +     settable_event(_env, "x", val)
    +

    +where _env is the environment of the running function. +(The _env variable is not defined in Lua. +We use it here only for explanatory purposes.) + + + + + +

    2.4.4 - Control Structures

    +The control structures +if, while, and repeat have the usual meaning and +familiar syntax: + + + + +

    +	stat ::= while exp do block end
    +	stat ::= repeat block until exp
    +	stat ::= if exp then block {elseif exp then block} [else block] end
    +

    +Lua also has a for statement, in two flavors (see §2.4.5). + + +

    +The condition expression of a +control structure can return any value. +Both false and nil are considered false. +All values different from nil and false are considered true +(in particular, the number 0 and the empty string are also true). + + +

    +In the repeatuntil loop, +the inner block does not end at the until keyword, +but only after the condition. +So, the condition can refer to local variables +declared inside the loop block. + + +

    +The return statement is used to return values +from a function or a chunk (which is just a function). + +Functions and chunks can return more than one value, +and so the syntax for the return statement is + +

    +	stat ::= return [explist]
    +
    + +

    +The break statement is used to terminate the execution of a +while, repeat, or for loop, +skipping to the next statement after the loop: + + +

    +	stat ::= break
    +

    +A break ends the innermost enclosing loop. + + +

    +The return and break +statements can only be written as the last statement of a block. +If it is really necessary to return or break in the +middle of a block, +then an explicit inner block can be used, +as in the idioms +do return end and do break end, +because now return and break are the last statements in +their (inner) blocks. + + + + + +

    2.4.5 - For Statement

    + +

    + +The for statement has two forms: +one numeric and one generic. + + +

    +The numeric for loop repeats a block of code while a +control variable runs through an arithmetic progression. +It has the following syntax: + +

    +	stat ::= for Name `=´ exp `,´ exp [`,´ exp] do block end
    +

    +The block is repeated for name starting at the value of +the first exp, until it passes the second exp by steps of the +third exp. +More precisely, a for statement like + +

    +     for v = e1, e2, e3 do block end
    +

    +is equivalent to the code: + +

    +     do
    +       local var, limit, step = tonumber(e1), tonumber(e2), tonumber(e3)
    +       if not (var and limit and step) then error() end
    +       while (step > 0 and var <= limit) or (step <= 0 and var >= limit) do
    +         local v = var
    +         block
    +         var = var + step
    +       end
    +     end
    +

    +Note the following: + +

      + +
    • +All three control expressions are evaluated only once, +before the loop starts. +They must all result in numbers. +
    • + +
    • +var, limit, and step are invisible variables. +The names shown here are for explanatory purposes only. +
    • + +
    • +If the third expression (the step) is absent, +then a step of 1 is used. +
    • + +
    • +You can use break to exit a for loop. +
    • + +
    • +The loop variable v is local to the loop; +you cannot use its value after the for ends or is broken. +If you need this value, +assign it to another variable before breaking or exiting the loop. +
    • + +
    + +

    +The generic for statement works over functions, +called iterators. +On each iteration, the iterator function is called to produce a new value, +stopping when this new value is nil. +The generic for loop has the following syntax: + +

    +	stat ::= for namelist in explist do block end
    +	namelist ::= Name {`,´ Name}
    +

    +A for statement like + +

    +     for var_1, ···, var_n in explist do block end
    +

    +is equivalent to the code: + +

    +     do
    +       local f, s, var = explist
    +       while true do
    +         local var_1, ···, var_n = f(s, var)
    +         var = var_1
    +         if var == nil then break end
    +         block
    +       end
    +     end
    +

    +Note the following: + +

      + +
    • +explist is evaluated only once. +Its results are an iterator function, +a state, +and an initial value for the first iterator variable. +
    • + +
    • +f, s, and var are invisible variables. +The names are here for explanatory purposes only. +
    • + +
    • +You can use break to exit a for loop. +
    • + +
    • +The loop variables var_i are local to the loop; +you cannot use their values after the for ends. +If you need these values, +then assign them to other variables before breaking or exiting the loop. +
    • + +
    + + + + +

    2.4.6 - Function Calls as Statements

    +To allow possible side-effects, +function calls can be executed as statements: + +

    +	stat ::= functioncall
    +

    +In this case, all returned values are thrown away. +Function calls are explained in §2.5.8. + + + + + +

    2.4.7 - Local Declarations

    +Local variables can be declared anywhere inside a block. +The declaration can include an initial assignment: + +

    +	stat ::= local namelist [`=´ explist]
    +

    +If present, an initial assignment has the same semantics +of a multiple assignment (see §2.4.3). +Otherwise, all variables are initialized with nil. + + +

    +A chunk is also a block (see §2.4.1), +and so local variables can be declared in a chunk outside any explicit block. +The scope of such local variables extends until the end of the chunk. + + +

    +The visibility rules for local variables are explained in §2.6. + + + + + + + +

    2.5 - Expressions

    + +

    +The basic expressions in Lua are the following: + +

    +	exp ::= prefixexp
    +	exp ::= nil | false | true
    +	exp ::= Number
    +	exp ::= String
    +	exp ::= function
    +	exp ::= tableconstructor
    +	exp ::= `...´
    +	exp ::= exp binop exp
    +	exp ::= unop exp
    +	prefixexp ::= var | functioncall | `(´ exp `)´
    +
    + +

    +Numbers and literal strings are explained in §2.1; +variables are explained in §2.3; +function definitions are explained in §2.5.9; +function calls are explained in §2.5.8; +table constructors are explained in §2.5.7. +Vararg expressions, +denoted by three dots ('...'), can only be used when +directly inside a vararg function; +they are explained in §2.5.9. + + +

    +Binary operators comprise arithmetic operators (see §2.5.1), +relational operators (see §2.5.2), logical operators (see §2.5.3), +and the concatenation operator (see §2.5.4). +Unary operators comprise the unary minus (see §2.5.1), +the unary not (see §2.5.3), +and the unary length operator (see §2.5.5). + + +

    +Both function calls and vararg expressions can result in multiple values. +If an expression is used as a statement +(only possible for function calls (see §2.4.6)), +then its return list is adjusted to zero elements, +thus discarding all returned values. +If an expression is used as the last (or the only) element +of a list of expressions, +then no adjustment is made +(unless the call is enclosed in parentheses). +In all other contexts, +Lua adjusts the result list to one element, +discarding all values except the first one. + + +

    +Here are some examples: + +

    +     f()                -- adjusted to 0 results
    +     g(f(), x)          -- f() is adjusted to 1 result
    +     g(x, f())          -- g gets x plus all results from f()
    +     a,b,c = f(), x     -- f() is adjusted to 1 result (c gets nil)
    +     a,b = ...          -- a gets the first vararg parameter, b gets
    +                        -- the second (both a and b can get nil if there
    +                        -- is no corresponding vararg parameter)
    +     
    +     a,b,c = x, f()     -- f() is adjusted to 2 results
    +     a,b,c = f()        -- f() is adjusted to 3 results
    +     return f()         -- returns all results from f()
    +     return ...         -- returns all received vararg parameters
    +     return x,y,f()     -- returns x, y, and all results from f()
    +     {f()}              -- creates a list with all results from f()
    +     {...}              -- creates a list with all vararg parameters
    +     {f(), nil}         -- f() is adjusted to 1 result
    +
    + +

    +Any expression enclosed in parentheses always results in only one value. +Thus, +(f(x,y,z)) is always a single value, +even if f returns several values. +(The value of (f(x,y,z)) is the first value returned by f +or nil if f does not return any values.) + + + +

    2.5.1 - Arithmetic Operators

    +Lua supports the usual arithmetic operators: +the binary + (addition), +- (subtraction), * (multiplication), +/ (division), % (modulo), and ^ (exponentiation); +and unary - (negation). +If the operands are numbers, or strings that can be converted to +numbers (see §2.2.1), +then all operations have the usual meaning. +Exponentiation works for any exponent. +For instance, x^(-0.5) computes the inverse of the square root of x. +Modulo is defined as + +

    +     a % b == a - math.floor(a/b)*b
    +

    +That is, it is the remainder of a division that rounds +the quotient towards minus infinity. + + + + + +

    2.5.2 - Relational Operators

    +The relational operators in Lua are + +

    +     ==    ~=    <     >     <=    >=
    +

    +These operators always result in false or true. + + +

    +Equality (==) first compares the type of its operands. +If the types are different, then the result is false. +Otherwise, the values of the operands are compared. +Numbers and strings are compared in the usual way. +Objects (tables, userdata, threads, and functions) +are compared by reference: +two objects are considered equal only if they are the same object. +Every time you create a new object +(a table, userdata, thread, or function), +this new object is different from any previously existing object. + + +

    +You can change the way that Lua compares tables and userdata +by using the "eq" metamethod (see §2.8). + + +

    +The conversion rules of §2.2.1 +do not apply to equality comparisons. +Thus, "0"==0 evaluates to false, +and t[0] and t["0"] denote different +entries in a table. + + +

    +The operator ~= is exactly the negation of equality (==). + + +

    +The order operators work as follows. +If both arguments are numbers, then they are compared as such. +Otherwise, if both arguments are strings, +then their values are compared according to the current locale. +Otherwise, Lua tries to call the "lt" or the "le" +metamethod (see §2.8). +A comparison a > b is translated to b < a +and a >= b is translated to b <= a. + + + + + +

    2.5.3 - Logical Operators

    +The logical operators in Lua are +and, or, and not. +Like the control structures (see §2.4.4), +all logical operators consider both false and nil as false +and anything else as true. + + +

    +The negation operator not always returns false or true. +The conjunction operator and returns its first argument +if this value is false or nil; +otherwise, and returns its second argument. +The disjunction operator or returns its first argument +if this value is different from nil and false; +otherwise, or returns its second argument. +Both and and or use short-cut evaluation; +that is, +the second operand is evaluated only if necessary. +Here are some examples: + +

    +     10 or 20            --> 10
    +     10 or error()       --> 10
    +     nil or "a"          --> "a"
    +     nil and 10          --> nil
    +     false and error()   --> false
    +     false and nil       --> false
    +     false or nil        --> nil
    +     10 and 20           --> 20
    +

    +(In this manual, +--> indicates the result of the preceding expression.) + + + + + +

    2.5.4 - Concatenation

    +The string concatenation operator in Lua is +denoted by two dots ('..'). +If both operands are strings or numbers, then they are converted to +strings according to the rules mentioned in §2.2.1. +Otherwise, the "concat" metamethod is called (see §2.8). + + + + + +

    2.5.5 - The Length Operator

    + +

    +The length operator is denoted by the unary operator #. +The length of a string is its number of bytes +(that is, the usual meaning of string length when each +character is one byte). + + +

    +The length of a table t is defined to be any +integer index n +such that t[n] is not nil and t[n+1] is nil; +moreover, if t[1] is nil, n can be zero. +For a regular array, with non-nil values from 1 to a given n, +its length is exactly that n, +the index of its last value. +If the array has "holes" +(that is, nil values between other non-nil values), +then #t can be any of the indices that +directly precedes a nil value +(that is, it may consider any such nil value as the end of +the array). + + + + + +

    2.5.6 - Precedence

    +Operator precedence in Lua follows the table below, +from lower to higher priority: + +

    +     or
    +     and
    +     <     >     <=    >=    ~=    ==
    +     ..
    +     +     -
    +     *     /     %
    +     not   #     - (unary)
    +     ^
    +

    +As usual, +you can use parentheses to change the precedences of an expression. +The concatenation ('..') and exponentiation ('^') +operators are right associative. +All other binary operators are left associative. + + + + + +

    2.5.7 - Table Constructors

    +Table constructors are expressions that create tables. +Every time a constructor is evaluated, a new table is created. +A constructor can be used to create an empty table +or to create a table and initialize some of its fields. +The general syntax for constructors is + +

    +	tableconstructor ::= `{´ [fieldlist] `}´
    +	fieldlist ::= field {fieldsep field} [fieldsep]
    +	field ::= `[´ exp `]´ `=´ exp | Name `=´ exp | exp
    +	fieldsep ::= `,´ | `;´
    +
    + +

    +Each field of the form [exp1] = exp2 adds to the new table an entry +with key exp1 and value exp2. +A field of the form name = exp is equivalent to +["name"] = exp. +Finally, fields of the form exp are equivalent to +[i] = exp, where i are consecutive numerical integers, +starting with 1. +Fields in the other formats do not affect this counting. +For example, + +

    +     a = { [f(1)] = g; "x", "y"; x = 1, f(x), [30] = 23; 45 }
    +

    +is equivalent to + +

    +     do
    +       local t = {}
    +       t[f(1)] = g
    +       t[1] = "x"         -- 1st exp
    +       t[2] = "y"         -- 2nd exp
    +       t.x = 1            -- t["x"] = 1
    +       t[3] = f(x)        -- 3rd exp
    +       t[30] = 23
    +       t[4] = 45          -- 4th exp
    +       a = t
    +     end
    +
    + +

    +If the last field in the list has the form exp +and the expression is a function call or a vararg expression, +then all values returned by this expression enter the list consecutively +(see §2.5.8). +To avoid this, +enclose the function call or the vararg expression +in parentheses (see §2.5). + + +

    +The field list can have an optional trailing separator, +as a convenience for machine-generated code. + + + + + +

    2.5.8 - Function Calls

    +A function call in Lua has the following syntax: + +

    +	functioncall ::= prefixexp args
    +

    +In a function call, +first prefixexp and args are evaluated. +If the value of prefixexp has type function, +then this function is called +with the given arguments. +Otherwise, the prefixexp "call" metamethod is called, +having as first parameter the value of prefixexp, +followed by the original call arguments +(see §2.8). + + +

    +The form + +

    +	functioncall ::= prefixexp `:´ Name args
    +

    +can be used to call "methods". +A call v:name(args) +is syntactic sugar for v.name(v,args), +except that v is evaluated only once. + + +

    +Arguments have the following syntax: + +

    +	args ::= `(´ [explist] `)´
    +	args ::= tableconstructor
    +	args ::= String
    +

    +All argument expressions are evaluated before the call. +A call of the form f{fields} is +syntactic sugar for f({fields}); +that is, the argument list is a single new table. +A call of the form f'string' +(or f"string" or f[[string]]) +is syntactic sugar for f('string'); +that is, the argument list is a single literal string. + + +

    +As an exception to the free-format syntax of Lua, +you cannot put a line break before the '(' in a function call. +This restriction avoids some ambiguities in the language. +If you write + +

    +     a = f
    +     (g).x(a)
    +

    +Lua would see that as a single statement, a = f(g).x(a). +So, if you want two statements, you must add a semi-colon between them. +If you actually want to call f, +you must remove the line break before (g). + + +

    +A call of the form return functioncall is called +a tail call. +Lua implements proper tail calls +(or proper tail recursion): +in a tail call, +the called function reuses the stack entry of the calling function. +Therefore, there is no limit on the number of nested tail calls that +a program can execute. +However, a tail call erases any debug information about the +calling function. +Note that a tail call only happens with a particular syntax, +where the return has one single function call as argument; +this syntax makes the calling function return exactly +the returns of the called function. +So, none of the following examples are tail calls: + +

    +     return (f(x))        -- results adjusted to 1
    +     return 2 * f(x)
    +     return x, f(x)       -- additional results
    +     f(x); return         -- results discarded
    +     return x or f(x)     -- results adjusted to 1
    +
    + + + + +

    2.5.9 - Function Definitions

    + +

    +The syntax for function definition is + +

    +	function ::= function funcbody
    +	funcbody ::= `(´ [parlist] `)´ block end
    +
    + +

    +The following syntactic sugar simplifies function definitions: + +

    +	stat ::= function funcname funcbody
    +	stat ::= local function Name funcbody
    +	funcname ::= Name {`.´ Name} [`:´ Name]
    +

    +The statement + +

    +     function f () body end
    +

    +translates to + +

    +     f = function () body end
    +

    +The statement + +

    +     function t.a.b.c.f () body end
    +

    +translates to + +

    +     t.a.b.c.f = function () body end
    +

    +The statement + +

    +     local function f () body end
    +

    +translates to + +

    +     local f; f = function () body end
    +

    +not to + +

    +     local f = function () body end
    +

    +(This only makes a difference when the body of the function +contains references to f.) + + +

    +A function definition is an executable expression, +whose value has type function. +When Lua pre-compiles a chunk, +all its function bodies are pre-compiled too. +Then, whenever Lua executes the function definition, +the function is instantiated (or closed). +This function instance (or closure) +is the final value of the expression. +Different instances of the same function +can refer to different external local variables +and can have different environment tables. + + +

    +Parameters act as local variables that are +initialized with the argument values: + +

    +	parlist ::= namelist [`,´ `...´] | `...´
    +

    +When a function is called, +the list of arguments is adjusted to +the length of the list of parameters, +unless the function is a variadic or vararg function, +which is +indicated by three dots ('...') at the end of its parameter list. +A vararg function does not adjust its argument list; +instead, it collects all extra arguments and supplies them +to the function through a vararg expression, +which is also written as three dots. +The value of this expression is a list of all actual extra arguments, +similar to a function with multiple results. +If a vararg expression is used inside another expression +or in the middle of a list of expressions, +then its return list is adjusted to one element. +If the expression is used as the last element of a list of expressions, +then no adjustment is made +(unless that last expression is enclosed in parentheses). + + +

    +As an example, consider the following definitions: + +

    +     function f(a, b) end
    +     function g(a, b, ...) end
    +     function r() return 1,2,3 end
    +

    +Then, we have the following mapping from arguments to parameters and +to the vararg expression: + +

    +     CALL            PARAMETERS
    +     
    +     f(3)             a=3, b=nil
    +     f(3, 4)          a=3, b=4
    +     f(3, 4, 5)       a=3, b=4
    +     f(r(), 10)       a=1, b=10
    +     f(r())           a=1, b=2
    +     
    +     g(3)             a=3, b=nil, ... -->  (nothing)
    +     g(3, 4)          a=3, b=4,   ... -->  (nothing)
    +     g(3, 4, 5, 8)    a=3, b=4,   ... -->  5  8
    +     g(5, r())        a=5, b=1,   ... -->  2  3
    +
    + +

    +Results are returned using the return statement (see §2.4.4). +If control reaches the end of a function +without encountering a return statement, +then the function returns with no results. + + +

    +The colon syntax +is used for defining methods, +that is, functions that have an implicit extra parameter self. +Thus, the statement + +

    +     function t.a.b.c:f (params) body end
    +

    +is syntactic sugar for + +

    +     t.a.b.c.f = function (self, params) body end
    +
    + + + + + + +

    2.6 - Visibility Rules

    + +

    + +Lua is a lexically scoped language. +The scope of variables begins at the first statement after +their declaration and lasts until the end of the innermost block that +includes the declaration. +Consider the following example: + +

    +     x = 10                -- global variable
    +     do                    -- new block
    +       local x = x         -- new 'x', with value 10
    +       print(x)            --> 10
    +       x = x+1
    +       do                  -- another block
    +         local x = x+1     -- another 'x'
    +         print(x)          --> 12
    +       end
    +       print(x)            --> 11
    +     end
    +     print(x)              --> 10  (the global one)
    +
    + +

    +Notice that, in a declaration like local x = x, +the new x being declared is not in scope yet, +and so the second x refers to the outside variable. + + +

    +Because of the lexical scoping rules, +local variables can be freely accessed by functions +defined inside their scope. +A local variable used by an inner function is called +an upvalue, or external local variable, +inside the inner function. + + +

    +Notice that each execution of a local statement +defines new local variables. +Consider the following example: + +

    +     a = {}
    +     local x = 20
    +     for i=1,10 do
    +       local y = 0
    +       a[i] = function () y=y+1; return x+y end
    +     end
    +

    +The loop creates ten closures +(that is, ten instances of the anonymous function). +Each of these closures uses a different y variable, +while all of them share the same x. + + + + + +

    2.7 - Error Handling

    + +

    +Because Lua is an embedded extension language, +all Lua actions start from C code in the host program +calling a function from the Lua library (see lua_pcall). +Whenever an error occurs during Lua compilation or execution, +control returns to C, +which can take appropriate measures +(such as printing an error message). + + +

    +Lua code can explicitly generate an error by calling the +error function. +If you need to catch errors in Lua, +you can use the pcall function. + + + + + +

    2.8 - Metatables

    + +

    +Every value in Lua can have a metatable. +This metatable is an ordinary Lua table +that defines the behavior of the original value +under certain special operations. +You can change several aspects of the behavior +of operations over a value by setting specific fields in its metatable. +For instance, when a non-numeric value is the operand of an addition, +Lua checks for a function in the field "__add" in its metatable. +If it finds one, +Lua calls this function to perform the addition. + + +

    +We call the keys in a metatable events +and the values metamethods. +In the previous example, the event is "add" +and the metamethod is the function that performs the addition. + + +

    +You can query the metatable of any value +through the getmetatable function. + + +

    +You can replace the metatable of tables +through the setmetatable +function. +You cannot change the metatable of other types from Lua +(except by using the debug library); +you must use the C API for that. + + +

    +Tables and full userdata have individual metatables +(although multiple tables and userdata can share their metatables). +Values of all other types share one single metatable per type; +that is, there is one single metatable for all numbers, +one for all strings, etc. + + +

    +A metatable controls how an object behaves in arithmetic operations, +order comparisons, concatenation, length operation, and indexing. +A metatable also can define a function to be called when a userdata +is garbage collected. +For each of these operations Lua associates a specific key +called an event. +When Lua performs one of these operations over a value, +it checks whether this value has a metatable with the corresponding event. +If so, the value associated with that key (the metamethod) +controls how Lua will perform the operation. + + +

    +Metatables control the operations listed next. +Each operation is identified by its corresponding name. +The key for each operation is a string with its name prefixed by +two underscores, '__'; +for instance, the key for operation "add" is the +string "__add". +The semantics of these operations is better explained by a Lua function +describing how the interpreter executes the operation. + + +

    +The code shown here in Lua is only illustrative; +the real behavior is hard coded in the interpreter +and it is much more efficient than this simulation. +All functions used in these descriptions +(rawget, tonumber, etc.) +are described in §5.1. +In particular, to retrieve the metamethod of a given object, +we use the expression + +

    +     metatable(obj)[event]
    +

    +This should be read as + +

    +     rawget(getmetatable(obj) or {}, event)
    +

    + +That is, the access to a metamethod does not invoke other metamethods, +and the access to objects with no metatables does not fail +(it simply results in nil). + + + +

      + +
    • "add": +the + operation. + + + +

      +The function getbinhandler below defines how Lua chooses a handler +for a binary operation. +First, Lua tries the first operand. +If its type does not define a handler for the operation, +then Lua tries the second operand. + +

      +     function getbinhandler (op1, op2, event)
      +       return metatable(op1)[event] or metatable(op2)[event]
      +     end
      +

      +By using this function, +the behavior of the op1 + op2 is + +

      +     function add_event (op1, op2)
      +       local o1, o2 = tonumber(op1), tonumber(op2)
      +       if o1 and o2 then  -- both operands are numeric?
      +         return o1 + o2   -- '+' here is the primitive 'add'
      +       else  -- at least one of the operands is not numeric
      +         local h = getbinhandler(op1, op2, "__add")
      +         if h then
      +           -- call the handler with both operands
      +           return (h(op1, op2))
      +         else  -- no handler available: default behavior
      +           error(···)
      +         end
      +       end
      +     end
      +

      +

    • + +
    • "sub": +the - operation. + +Behavior similar to the "add" operation. +
    • + +
    • "mul": +the * operation. + +Behavior similar to the "add" operation. +
    • + +
    • "div": +the / operation. + +Behavior similar to the "add" operation. +
    • + +
    • "mod": +the % operation. + +Behavior similar to the "add" operation, +with the operation +o1 - floor(o1/o2)*o2 as the primitive operation. +
    • + +
    • "pow": +the ^ (exponentiation) operation. + +Behavior similar to the "add" operation, +with the function pow (from the C math library) +as the primitive operation. +
    • + +
    • "unm": +the unary - operation. + + +
      +     function unm_event (op)
      +       local o = tonumber(op)
      +       if o then  -- operand is numeric?
      +         return -o  -- '-' here is the primitive 'unm'
      +       else  -- the operand is not numeric.
      +         -- Try to get a handler from the operand
      +         local h = metatable(op).__unm
      +         if h then
      +           -- call the handler with the operand
      +           return (h(op))
      +         else  -- no handler available: default behavior
      +           error(···)
      +         end
      +       end
      +     end
      +

      +

    • + +
    • "concat": +the .. (concatenation) operation. + + +
      +     function concat_event (op1, op2)
      +       if (type(op1) == "string" or type(op1) == "number") and
      +          (type(op2) == "string" or type(op2) == "number") then
      +         return op1 .. op2  -- primitive string concatenation
      +       else
      +         local h = getbinhandler(op1, op2, "__concat")
      +         if h then
      +           return (h(op1, op2))
      +         else
      +           error(···)
      +         end
      +       end
      +     end
      +

      +

    • + +
    • "len": +the # operation. + + +
      +     function len_event (op)
      +       if type(op) == "string" then
      +         return strlen(op)         -- primitive string length
      +       elseif type(op) == "table" then
      +         return #op                -- primitive table length
      +       else
      +         local h = metatable(op).__len
      +         if h then
      +           -- call the handler with the operand
      +           return (h(op))
      +         else  -- no handler available: default behavior
      +           error(···)
      +         end
      +       end
      +     end
      +

      +See §2.5.5 for a description of the length of a table. +

    • + +
    • "eq": +the == operation. + +The function getcomphandler defines how Lua chooses a metamethod +for comparison operators. +A metamethod only is selected when both objects +being compared have the same type +and the same metamethod for the selected operation. + +
      +     function getcomphandler (op1, op2, event)
      +       if type(op1) ~= type(op2) then return nil end
      +       local mm1 = metatable(op1)[event]
      +       local mm2 = metatable(op2)[event]
      +       if mm1 == mm2 then return mm1 else return nil end
      +     end
      +

      +The "eq" event is defined as follows: + +

      +     function eq_event (op1, op2)
      +       if type(op1) ~= type(op2) then  -- different types?
      +         return false   -- different objects
      +       end
      +       if op1 == op2 then   -- primitive equal?
      +         return true   -- objects are equal
      +       end
      +       -- try metamethod
      +       local h = getcomphandler(op1, op2, "__eq")
      +       if h then
      +         return (h(op1, op2))
      +       else
      +         return false
      +       end
      +     end
      +

      +a ~= b is equivalent to not (a == b). +

    • + +
    • "lt": +the < operation. + + +
      +     function lt_event (op1, op2)
      +       if type(op1) == "number" and type(op2) == "number" then
      +         return op1 < op2   -- numeric comparison
      +       elseif type(op1) == "string" and type(op2) == "string" then
      +         return op1 < op2   -- lexicographic comparison
      +       else
      +         local h = getcomphandler(op1, op2, "__lt")
      +         if h then
      +           return (h(op1, op2))
      +         else
      +           error(···)
      +         end
      +       end
      +     end
      +

      +a > b is equivalent to b < a. +

    • + +
    • "le": +the <= operation. + + +
      +     function le_event (op1, op2)
      +       if type(op1) == "number" and type(op2) == "number" then
      +         return op1 <= op2   -- numeric comparison
      +       elseif type(op1) == "string" and type(op2) == "string" then
      +         return op1 <= op2   -- lexicographic comparison
      +       else
      +         local h = getcomphandler(op1, op2, "__le")
      +         if h then
      +           return (h(op1, op2))
      +         else
      +           h = getcomphandler(op1, op2, "__lt")
      +           if h then
      +             return not h(op2, op1)
      +           else
      +             error(···)
      +           end
      +         end
      +       end
      +     end
      +

      +a >= b is equivalent to b <= a. +Note that, in the absence of a "le" metamethod, +Lua tries the "lt", assuming that a <= b is +equivalent to not (b < a). +

    • + +
    • "index": +The indexing access table[key]. + + +
      +     function gettable_event (table, key)
      +       local h
      +       if type(table) == "table" then
      +         local v = rawget(table, key)
      +         if v ~= nil then return v end
      +         h = metatable(table).__index
      +         if h == nil then return nil end
      +       else
      +         h = metatable(table).__index
      +         if h == nil then
      +           error(···)
      +         end
      +       end
      +       if type(h) == "function" then
      +         return (h(table, key))     -- call the handler
      +       else return h[key]           -- or repeat operation on it
      +       end
      +     end
      +

      +

    • + +
    • "newindex": +The indexing assignment table[key] = value. + + +
      +     function settable_event (table, key, value)
      +       local h
      +       if type(table) == "table" then
      +         local v = rawget(table, key)
      +         if v ~= nil then rawset(table, key, value); return end
      +         h = metatable(table).__newindex
      +         if h == nil then rawset(table, key, value); return end
      +       else
      +         h = metatable(table).__newindex
      +         if h == nil then
      +           error(···)
      +         end
      +       end
      +       if type(h) == "function" then
      +         h(table, key,value)           -- call the handler
      +       else h[key] = value             -- or repeat operation on it
      +       end
      +     end
      +

      +

    • + +
    • "call": +called when Lua calls a value. + + +
      +     function function_event (func, ...)
      +       if type(func) == "function" then
      +         return func(...)   -- primitive call
      +       else
      +         local h = metatable(func).__call
      +         if h then
      +           return h(func, ...)
      +         else
      +           error(···)
      +         end
      +       end
      +     end
      +

      +

    • + +
    + + + + +

    2.9 - Environments

    + +

    +Besides metatables, +objects of types thread, function, and userdata +have another table associated with them, +called their environment. +Like metatables, environments are regular tables and +multiple objects can share the same environment. + + +

    +Threads are created sharing the environment of the creating thread. +Userdata and C functions are created sharing the environment +of the creating C function. +Non-nested Lua functions +(created by loadfile, loadstring or load) +are created sharing the environment of the creating thread. +Nested Lua functions are created sharing the environment of +the creating Lua function. + + +

    +Environments associated with userdata have no meaning for Lua. +It is only a convenience feature for programmers to associate a table to +a userdata. + + +

    +Environments associated with threads are called +global environments. +They are used as the default environment for threads and +non-nested Lua functions created by the thread +and can be directly accessed by C code (see §3.3). + + +

    +The environment associated with a C function can be directly +accessed by C code (see §3.3). +It is used as the default environment for other C functions +and userdata created by the function. + + +

    +Environments associated with Lua functions are used to resolve +all accesses to global variables within the function (see §2.3). +They are used as the default environment for nested Lua functions +created by the function. + + +

    +You can change the environment of a Lua function or the +running thread by calling setfenv. +You can get the environment of a Lua function or the running thread +by calling getfenv. +To manipulate the environment of other objects +(userdata, C functions, other threads) you must +use the C API. + + + + + +

    2.10 - Garbage Collection

    + +

    +Lua performs automatic memory management. +This means that +you have to worry neither about allocating memory for new objects +nor about freeing it when the objects are no longer needed. +Lua manages memory automatically by running +a garbage collector from time to time +to collect all dead objects +(that is, objects that are no longer accessible from Lua). +All memory used by Lua is subject to automatic management: +tables, userdata, functions, threads, strings, etc. + + +

    +Lua implements an incremental mark-and-sweep collector. +It uses two numbers to control its garbage-collection cycles: +the garbage-collector pause and +the garbage-collector step multiplier. +Both use percentage points as units +(so that a value of 100 means an internal value of 1). + + +

    +The garbage-collector pause +controls how long the collector waits before starting a new cycle. +Larger values make the collector less aggressive. +Values smaller than 100 mean the collector will not wait to +start a new cycle. +A value of 200 means that the collector waits for the total memory in use +to double before starting a new cycle. + + +

    +The step multiplier +controls the relative speed of the collector relative to +memory allocation. +Larger values make the collector more aggressive but also increase +the size of each incremental step. +Values smaller than 100 make the collector too slow and +can result in the collector never finishing a cycle. +The default, 200, means that the collector runs at "twice" +the speed of memory allocation. + + +

    +You can change these numbers by calling lua_gc in C +or collectgarbage in Lua. +With these functions you can also control +the collector directly (e.g., stop and restart it). + + + +

    2.10.1 - Garbage-Collection Metamethods

    + +

    +Using the C API, +you can set garbage-collector metamethods for userdata (see §2.8). +These metamethods are also called finalizers. +Finalizers allow you to coordinate Lua's garbage collection +with external resource management +(such as closing files, network or database connections, +or freeing your own memory). + + +

    +Garbage userdata with a field __gc in their metatables are not +collected immediately by the garbage collector. +Instead, Lua puts them in a list. +After the collection, +Lua does the equivalent of the following function +for each userdata in that list: + +

    +     function gc_event (udata)
    +       local h = metatable(udata).__gc
    +       if h then
    +         h(udata)
    +       end
    +     end
    +
    + +

    +At the end of each garbage-collection cycle, +the finalizers for userdata are called in reverse +order of their creation, +among those collected in that cycle. +That is, the first finalizer to be called is the one associated +with the userdata created last in the program. +The userdata itself is freed only in the next garbage-collection cycle. + + + + + +

    2.10.2 - Weak Tables

    + +

    +A weak table is a table whose elements are +weak references. +A weak reference is ignored by the garbage collector. +In other words, +if the only references to an object are weak references, +then the garbage collector will collect this object. + + +

    +A weak table can have weak keys, weak values, or both. +A table with weak keys allows the collection of its keys, +but prevents the collection of its values. +A table with both weak keys and weak values allows the collection of +both keys and values. +In any case, if either the key or the value is collected, +the whole pair is removed from the table. +The weakness of a table is controlled by the +__mode field of its metatable. +If the __mode field is a string containing the character 'k', +the keys in the table are weak. +If __mode contains 'v', +the values in the table are weak. + + +

    +After you use a table as a metatable, +you should not change the value of its __mode field. +Otherwise, the weak behavior of the tables controlled by this +metatable is undefined. + + + + + + + +

    2.11 - Coroutines

    + +

    +Lua supports coroutines, +also called collaborative multithreading. +A coroutine in Lua represents an independent thread of execution. +Unlike threads in multithread systems, however, +a coroutine only suspends its execution by explicitly calling +a yield function. + + +

    +You create a coroutine with a call to coroutine.create. +Its sole argument is a function +that is the main function of the coroutine. +The create function only creates a new coroutine and +returns a handle to it (an object of type thread); +it does not start the coroutine execution. + + +

    +When you first call coroutine.resume, +passing as its first argument +a thread returned by coroutine.create, +the coroutine starts its execution, +at the first line of its main function. +Extra arguments passed to coroutine.resume are passed on +to the coroutine main function. +After the coroutine starts running, +it runs until it terminates or yields. + + +

    +A coroutine can terminate its execution in two ways: +normally, when its main function returns +(explicitly or implicitly, after the last instruction); +and abnormally, if there is an unprotected error. +In the first case, coroutine.resume returns true, +plus any values returned by the coroutine main function. +In case of errors, coroutine.resume returns false +plus an error message. + + +

    +A coroutine yields by calling coroutine.yield. +When a coroutine yields, +the corresponding coroutine.resume returns immediately, +even if the yield happens inside nested function calls +(that is, not in the main function, +but in a function directly or indirectly called by the main function). +In the case of a yield, coroutine.resume also returns true, +plus any values passed to coroutine.yield. +The next time you resume the same coroutine, +it continues its execution from the point where it yielded, +with the call to coroutine.yield returning any extra +arguments passed to coroutine.resume. + + +

    +Like coroutine.create, +the coroutine.wrap function also creates a coroutine, +but instead of returning the coroutine itself, +it returns a function that, when called, resumes the coroutine. +Any arguments passed to this function +go as extra arguments to coroutine.resume. +coroutine.wrap returns all the values returned by coroutine.resume, +except the first one (the boolean error code). +Unlike coroutine.resume, +coroutine.wrap does not catch errors; +any error is propagated to the caller. + + +

    +As an example, +consider the following code: + +

    +     function foo (a)
    +       print("foo", a)
    +       return coroutine.yield(2*a)
    +     end
    +     
    +     co = coroutine.create(function (a,b)
    +           print("co-body", a, b)
    +           local r = foo(a+1)
    +           print("co-body", r)
    +           local r, s = coroutine.yield(a+b, a-b)
    +           print("co-body", r, s)
    +           return b, "end"
    +     end)
    +            
    +     print("main", coroutine.resume(co, 1, 10))
    +     print("main", coroutine.resume(co, "r"))
    +     print("main", coroutine.resume(co, "x", "y"))
    +     print("main", coroutine.resume(co, "x", "y"))
    +

    +When you run it, it produces the following output: + +

    +     co-body 1       10
    +     foo     2
    +     
    +     main    true    4
    +     co-body r
    +     main    true    11      -9
    +     co-body x       y
    +     main    true    10      end
    +     main    false   cannot resume dead coroutine
    +
    + + + + +

    3 - The Application Program Interface

    + +

    + +This section describes the C API for Lua, that is, +the set of C functions available to the host program to communicate +with Lua. +All API functions and related types and constants +are declared in the header file lua.h. + + +

    +Even when we use the term "function", +any facility in the API may be provided as a macro instead. +All such macros use each of their arguments exactly once +(except for the first argument, which is always a Lua state), +and so do not generate any hidden side-effects. + + +

    +As in most C libraries, +the Lua API functions do not check their arguments for validity or consistency. +However, you can change this behavior by compiling Lua +with a proper definition for the macro luai_apicheck, +in file luaconf.h. + + + +

    3.1 - The Stack

    + +

    +Lua uses a virtual stack to pass values to and from C. +Each element in this stack represents a Lua value +(nil, number, string, etc.). + + +

    +Whenever Lua calls C, the called function gets a new stack, +which is independent of previous stacks and of stacks of +C functions that are still active. +This stack initially contains any arguments to the C function +and it is where the C function pushes its results +to be returned to the caller (see lua_CFunction). + + +

    +For convenience, +most query operations in the API do not follow a strict stack discipline. +Instead, they can refer to any element in the stack +by using an index: +A positive index represents an absolute stack position +(starting at 1); +a negative index represents an offset relative to the top of the stack. +More specifically, if the stack has n elements, +then index 1 represents the first element +(that is, the element that was pushed onto the stack first) +and +index n represents the last element; +index -1 also represents the last element +(that is, the element at the top) +and index -n represents the first element. +We say that an index is valid +if it lies between 1 and the stack top +(that is, if 1 ≤ abs(index) ≤ top). + + + + + + +

    3.2 - Stack Size

    + +

    +When you interact with Lua API, +you are responsible for ensuring consistency. +In particular, +you are responsible for controlling stack overflow. +You can use the function lua_checkstack +to grow the stack size. + + +

    +Whenever Lua calls C, +it ensures that at least LUA_MINSTACK stack positions are available. +LUA_MINSTACK is defined as 20, +so that usually you do not have to worry about stack space +unless your code has loops pushing elements onto the stack. + + +

    +Most query functions accept as indices any value inside the +available stack space, that is, indices up to the maximum stack size +you have set through lua_checkstack. +Such indices are called acceptable indices. +More formally, we define an acceptable index +as follows: + +

    +     (index < 0 && abs(index) <= top) ||
    +     (index > 0 && index <= stackspace)
    +

    +Note that 0 is never an acceptable index. + + + + + +

    3.3 - Pseudo-Indices

    + +

    +Unless otherwise noted, +any function that accepts valid indices can also be called with +pseudo-indices, +which represent some Lua values that are accessible to C code +but which are not in the stack. +Pseudo-indices are used to access the thread environment, +the function environment, +the registry, +and the upvalues of a C function (see §3.4). + + +

    +The thread environment (where global variables live) is +always at pseudo-index LUA_GLOBALSINDEX. +The environment of the running C function is always +at pseudo-index LUA_ENVIRONINDEX. + + +

    +To access and change the value of global variables, +you can use regular table operations over an environment table. +For instance, to access the value of a global variable, do + +

    +     lua_getfield(L, LUA_GLOBALSINDEX, varname);
    +
    + + + + +

    3.4 - C Closures

    + +

    +When a C function is created, +it is possible to associate some values with it, +thus creating a C closure; +these values are called upvalues and are +accessible to the function whenever it is called +(see lua_pushcclosure). + + +

    +Whenever a C function is called, +its upvalues are located at specific pseudo-indices. +These pseudo-indices are produced by the macro +lua_upvalueindex. +The first value associated with a function is at position +lua_upvalueindex(1), and so on. +Any access to lua_upvalueindex(n), +where n is greater than the number of upvalues of the +current function (but not greater than 256), +produces an acceptable (but invalid) index. + + + + + +

    3.5 - Registry

    + +

    +Lua provides a registry, +a pre-defined table that can be used by any C code to +store whatever Lua value it needs to store. +This table is always located at pseudo-index +LUA_REGISTRYINDEX. +Any C library can store data into this table, +but it should take care to choose keys different from those used +by other libraries, to avoid collisions. +Typically, you should use as key a string containing your library name +or a light userdata with the address of a C object in your code. + + +

    +The integer keys in the registry are used by the reference mechanism, +implemented by the auxiliary library, +and therefore should not be used for other purposes. + + + + + +

    3.6 - Error Handling in C

    + +

    +Internally, Lua uses the C longjmp facility to handle errors. +(You can also choose to use exceptions if you use C++; +see file luaconf.h.) +When Lua faces any error +(such as memory allocation errors, type errors, syntax errors, +and runtime errors) +it raises an error; +that is, it does a long jump. +A protected environment uses setjmp +to set a recover point; +any error jumps to the most recent active recover point. + + +

    +Most functions in the API can throw an error, +for instance due to a memory allocation error. +The documentation for each function indicates whether +it can throw errors. + + +

    +Inside a C function you can throw an error by calling lua_error. + + + + + +

    3.7 - Functions and Types

    + +

    +Here we list all functions and types from the C API in +alphabetical order. +Each function has an indicator like this: +[-o, +p, x] + + +

    +The first field, o, +is how many elements the function pops from the stack. +The second field, p, +is how many elements the function pushes onto the stack. +(Any function always pushes its results after popping its arguments.) +A field in the form x|y means the function can push (or pop) +x or y elements, +depending on the situation; +an interrogation mark '?' means that +we cannot know how many elements the function pops/pushes +by looking only at its arguments +(e.g., they may depend on what is on the stack). +The third field, x, +tells whether the function may throw errors: +'-' means the function never throws any error; +'m' means the function may throw an error +only due to not enough memory; +'e' means the function may throw other kinds of errors; +'v' means the function may throw an error on purpose. + + + +


    lua_Alloc

    +
    typedef void * (*lua_Alloc) (void *ud,
    +                             void *ptr,
    +                             size_t osize,
    +                             size_t nsize);
    + +

    +The type of the memory-allocation function used by Lua states. +The allocator function must provide a +functionality similar to realloc, +but not exactly the same. +Its arguments are +ud, an opaque pointer passed to lua_newstate; +ptr, a pointer to the block being allocated/reallocated/freed; +osize, the original size of the block; +nsize, the new size of the block. +ptr is NULL if and only if osize is zero. +When nsize is zero, the allocator must return NULL; +if osize is not zero, +it should free the block pointed to by ptr. +When nsize is not zero, the allocator returns NULL +if and only if it cannot fill the request. +When nsize is not zero and osize is zero, +the allocator should behave like malloc. +When nsize and osize are not zero, +the allocator behaves like realloc. +Lua assumes that the allocator never fails when +osize >= nsize. + + +

    +Here is a simple implementation for the allocator function. +It is used in the auxiliary library by luaL_newstate. + +

    +     static void *l_alloc (void *ud, void *ptr, size_t osize,
    +                                                size_t nsize) {
    +       (void)ud;  (void)osize;  /* not used */
    +       if (nsize == 0) {
    +         free(ptr);
    +         return NULL;
    +       }
    +       else
    +         return realloc(ptr, nsize);
    +     }
    +

    +This code assumes +that free(NULL) has no effect and that +realloc(NULL, size) is equivalent to malloc(size). +ANSI C ensures both behaviors. + + + + + +


    lua_atpanic

    +[-0, +0, -] +

    lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf);
    + +

    +Sets a new panic function and returns the old one. + + +

    +If an error happens outside any protected environment, +Lua calls a panic function +and then calls exit(EXIT_FAILURE), +thus exiting the host application. +Your panic function can avoid this exit by +never returning (e.g., doing a long jump). + + +

    +The panic function can access the error message at the top of the stack. + + + + + +


    lua_call

    +[-(nargs + 1), +nresults, e] +

    void lua_call (lua_State *L, int nargs, int nresults);
    + +

    +Calls a function. + + +

    +To call a function you must use the following protocol: +first, the function to be called is pushed onto the stack; +then, the arguments to the function are pushed +in direct order; +that is, the first argument is pushed first. +Finally you call lua_call; +nargs is the number of arguments that you pushed onto the stack. +All arguments and the function value are popped from the stack +when the function is called. +The function results are pushed onto the stack when the function returns. +The number of results is adjusted to nresults, +unless nresults is LUA_MULTRET. +In this case, all results from the function are pushed. +Lua takes care that the returned values fit into the stack space. +The function results are pushed onto the stack in direct order +(the first result is pushed first), +so that after the call the last result is on the top of the stack. + + +

    +Any error inside the called function is propagated upwards +(with a longjmp). + + +

    +The following example shows how the host program can do the +equivalent to this Lua code: + +

    +     a = f("how", t.x, 14)
    +

    +Here it is in C: + +

    +     lua_getfield(L, LUA_GLOBALSINDEX, "f"); /* function to be called */
    +     lua_pushstring(L, "how");                        /* 1st argument */
    +     lua_getfield(L, LUA_GLOBALSINDEX, "t");   /* table to be indexed */
    +     lua_getfield(L, -1, "x");        /* push result of t.x (2nd arg) */
    +     lua_remove(L, -2);                  /* remove 't' from the stack */
    +     lua_pushinteger(L, 14);                          /* 3rd argument */
    +     lua_call(L, 3, 1);     /* call 'f' with 3 arguments and 1 result */
    +     lua_setfield(L, LUA_GLOBALSINDEX, "a");        /* set global 'a' */
    +

    +Note that the code above is "balanced": +at its end, the stack is back to its original configuration. +This is considered good programming practice. + + + + + +


    lua_CFunction

    +
    typedef int (*lua_CFunction) (lua_State *L);
    + +

    +Type for C functions. + + +

    +In order to communicate properly with Lua, +a C function must use the following protocol, +which defines the way parameters and results are passed: +a C function receives its arguments from Lua in its stack +in direct order (the first argument is pushed first). +So, when the function starts, +lua_gettop(L) returns the number of arguments received by the function. +The first argument (if any) is at index 1 +and its last argument is at index lua_gettop(L). +To return values to Lua, a C function just pushes them onto the stack, +in direct order (the first result is pushed first), +and returns the number of results. +Any other value in the stack below the results will be properly +discarded by Lua. +Like a Lua function, a C function called by Lua can also return +many results. + + +

    +As an example, the following function receives a variable number +of numerical arguments and returns their average and sum: + +

    +     static int foo (lua_State *L) {
    +       int n = lua_gettop(L);    /* number of arguments */
    +       lua_Number sum = 0;
    +       int i;
    +       for (i = 1; i <= n; i++) {
    +         if (!lua_isnumber(L, i)) {
    +           lua_pushstring(L, "incorrect argument");
    +           lua_error(L);
    +         }
    +         sum += lua_tonumber(L, i);
    +       }
    +       lua_pushnumber(L, sum/n);        /* first result */
    +       lua_pushnumber(L, sum);         /* second result */
    +       return 2;                   /* number of results */
    +     }
    +
    + + + + +

    lua_checkstack

    +[-0, +0, m] +

    int lua_checkstack (lua_State *L, int extra);
    + +

    +Ensures that there are at least extra free stack slots in the stack. +It returns false if it cannot grow the stack to that size. +This function never shrinks the stack; +if the stack is already larger than the new size, +it is left unchanged. + + + + + +


    lua_close

    +[-0, +0, -] +

    void lua_close (lua_State *L);
    + +

    +Destroys all objects in the given Lua state +(calling the corresponding garbage-collection metamethods, if any) +and frees all dynamic memory used by this state. +On several platforms, you may not need to call this function, +because all resources are naturally released when the host program ends. +On the other hand, long-running programs, +such as a daemon or a web server, +might need to release states as soon as they are not needed, +to avoid growing too large. + + + + + +


    lua_concat

    +[-n, +1, e] +

    void lua_concat (lua_State *L, int n);
    + +

    +Concatenates the n values at the top of the stack, +pops them, and leaves the result at the top. +If n is 1, the result is the single value on the stack +(that is, the function does nothing); +if n is 0, the result is the empty string. +Concatenation is performed following the usual semantics of Lua +(see §2.5.4). + + + + + +


    lua_cpcall

    +[-0, +(0|1), -] +

    int lua_cpcall (lua_State *L, lua_CFunction func, void *ud);
    + +

    +Calls the C function func in protected mode. +func starts with only one element in its stack, +a light userdata containing ud. +In case of errors, +lua_cpcall returns the same error codes as lua_pcall, +plus the error object on the top of the stack; +otherwise, it returns zero, and does not change the stack. +All values returned by func are discarded. + + + + + +


    lua_createtable

    +[-0, +1, m] +

    void lua_createtable (lua_State *L, int narr, int nrec);
    + +

    +Creates a new empty table and pushes it onto the stack. +The new table has space pre-allocated +for narr array elements and nrec non-array elements. +This pre-allocation is useful when you know exactly how many elements +the table will have. +Otherwise you can use the function lua_newtable. + + + + + +


    lua_dump

    +[-0, +0, m] +

    int lua_dump (lua_State *L, lua_Writer writer, void *data);
    + +

    +Dumps a function as a binary chunk. +Receives a Lua function on the top of the stack +and produces a binary chunk that, +if loaded again, +results in a function equivalent to the one dumped. +As it produces parts of the chunk, +lua_dump calls function writer (see lua_Writer) +with the given data +to write them. + + +

    +The value returned is the error code returned by the last +call to the writer; +0 means no errors. + + +

    +This function does not pop the Lua function from the stack. + + + + + +


    lua_equal

    +[-0, +0, e] +

    int lua_equal (lua_State *L, int index1, int index2);
    + +

    +Returns 1 if the two values in acceptable indices index1 and +index2 are equal, +following the semantics of the Lua == operator +(that is, may call metamethods). +Otherwise returns 0. +Also returns 0 if any of the indices is non valid. + + + + + +


    lua_error

    +[-1, +0, v] +

    int lua_error (lua_State *L);
    + +

    +Generates a Lua error. +The error message (which can actually be a Lua value of any type) +must be on the stack top. +This function does a long jump, +and therefore never returns. +(see luaL_error). + + + + + +


    lua_gc

    +[-0, +0, e] +

    int lua_gc (lua_State *L, int what, int data);
    + +

    +Controls the garbage collector. + + +

    +This function performs several tasks, +according to the value of the parameter what: + +

      + +
    • LUA_GCSTOP: +stops the garbage collector. +
    • + +
    • LUA_GCRESTART: +restarts the garbage collector. +
    • + +
    • LUA_GCCOLLECT: +performs a full garbage-collection cycle. +
    • + +
    • LUA_GCCOUNT: +returns the current amount of memory (in Kbytes) in use by Lua. +
    • + +
    • LUA_GCCOUNTB: +returns the remainder of dividing the current amount of bytes of +memory in use by Lua by 1024. +
    • + +
    • LUA_GCSTEP: +performs an incremental step of garbage collection. +The step "size" is controlled by data +(larger values mean more steps) in a non-specified way. +If you want to control the step size +you must experimentally tune the value of data. +The function returns 1 if the step finished a +garbage-collection cycle. +
    • + +
    • LUA_GCSETPAUSE: +sets data as the new value +for the pause of the collector (see §2.10). +The function returns the previous value of the pause. +
    • + +
    • LUA_GCSETSTEPMUL: +sets data as the new value for the step multiplier of +the collector (see §2.10). +The function returns the previous value of the step multiplier. +
    • + +
    + + + + +

    lua_getallocf

    +[-0, +0, -] +

    lua_Alloc lua_getallocf (lua_State *L, void **ud);
    + +

    +Returns the memory-allocation function of a given state. +If ud is not NULL, Lua stores in *ud the +opaque pointer passed to lua_newstate. + + + + + +


    lua_getfenv

    +[-0, +1, -] +

    void lua_getfenv (lua_State *L, int index);
    + +

    +Pushes onto the stack the environment table of +the value at the given index. + + + + + +


    lua_getfield

    +[-0, +1, e] +

    void lua_getfield (lua_State *L, int index, const char *k);
    + +

    +Pushes onto the stack the value t[k], +where t is the value at the given valid index. +As in Lua, this function may trigger a metamethod +for the "index" event (see §2.8). + + + + + +


    lua_getglobal

    +[-0, +1, e] +

    void lua_getglobal (lua_State *L, const char *name);
    + +

    +Pushes onto the stack the value of the global name. +It is defined as a macro: + +

    +     #define lua_getglobal(L,s)  lua_getfield(L, LUA_GLOBALSINDEX, s)
    +
    + + + + +

    lua_getmetatable

    +[-0, +(0|1), -] +

    int lua_getmetatable (lua_State *L, int index);
    + +

    +Pushes onto the stack the metatable of the value at the given +acceptable index. +If the index is not valid, +or if the value does not have a metatable, +the function returns 0 and pushes nothing on the stack. + + + + + +


    lua_gettable

    +[-1, +1, e] +

    void lua_gettable (lua_State *L, int index);
    + +

    +Pushes onto the stack the value t[k], +where t is the value at the given valid index +and k is the value at the top of the stack. + + +

    +This function pops the key from the stack +(putting the resulting value in its place). +As in Lua, this function may trigger a metamethod +for the "index" event (see §2.8). + + + + + +


    lua_gettop

    +[-0, +0, -] +

    int lua_gettop (lua_State *L);
    + +

    +Returns the index of the top element in the stack. +Because indices start at 1, +this result is equal to the number of elements in the stack +(and so 0 means an empty stack). + + + + + +


    lua_insert

    +[-1, +1, -] +

    void lua_insert (lua_State *L, int index);
    + +

    +Moves the top element into the given valid index, +shifting up the elements above this index to open space. +Cannot be called with a pseudo-index, +because a pseudo-index is not an actual stack position. + + + + + +


    lua_Integer

    +
    typedef ptrdiff_t lua_Integer;
    + +

    +The type used by the Lua API to represent integral values. + + +

    +By default it is a ptrdiff_t, +which is usually the largest signed integral type the machine handles +"comfortably". + + + + + +


    lua_isboolean

    +[-0, +0, -] +

    int lua_isboolean (lua_State *L, int index);
    + +

    +Returns 1 if the value at the given acceptable index has type boolean, +and 0 otherwise. + + + + + +


    lua_iscfunction

    +[-0, +0, -] +

    int lua_iscfunction (lua_State *L, int index);
    + +

    +Returns 1 if the value at the given acceptable index is a C function, +and 0 otherwise. + + + + + +


    lua_isfunction

    +[-0, +0, -] +

    int lua_isfunction (lua_State *L, int index);
    + +

    +Returns 1 if the value at the given acceptable index is a function +(either C or Lua), and 0 otherwise. + + + + + +


    lua_islightuserdata

    +[-0, +0, -] +

    int lua_islightuserdata (lua_State *L, int index);
    + +

    +Returns 1 if the value at the given acceptable index is a light userdata, +and 0 otherwise. + + + + + +


    lua_isnil

    +[-0, +0, -] +

    int lua_isnil (lua_State *L, int index);
    + +

    +Returns 1 if the value at the given acceptable index is nil, +and 0 otherwise. + + + + + +


    lua_isnone

    +[-0, +0, -] +

    int lua_isnone (lua_State *L, int index);
    + +

    +Returns 1 if the given acceptable index is not valid +(that is, it refers to an element outside the current stack), +and 0 otherwise. + + + + + +


    lua_isnoneornil

    +[-0, +0, -] +

    int lua_isnoneornil (lua_State *L, int index);
    + +

    +Returns 1 if the given acceptable index is not valid +(that is, it refers to an element outside the current stack) +or if the value at this index is nil, +and 0 otherwise. + + + + + +


    lua_isnumber

    +[-0, +0, -] +

    int lua_isnumber (lua_State *L, int index);
    + +

    +Returns 1 if the value at the given acceptable index is a number +or a string convertible to a number, +and 0 otherwise. + + + + + +


    lua_isstring

    +[-0, +0, -] +

    int lua_isstring (lua_State *L, int index);
    + +

    +Returns 1 if the value at the given acceptable index is a string +or a number (which is always convertible to a string), +and 0 otherwise. + + + + + +


    lua_istable

    +[-0, +0, -] +

    int lua_istable (lua_State *L, int index);
    + +

    +Returns 1 if the value at the given acceptable index is a table, +and 0 otherwise. + + + + + +


    lua_isthread

    +[-0, +0, -] +

    int lua_isthread (lua_State *L, int index);
    + +

    +Returns 1 if the value at the given acceptable index is a thread, +and 0 otherwise. + + + + + +


    lua_isuserdata

    +[-0, +0, -] +

    int lua_isuserdata (lua_State *L, int index);
    + +

    +Returns 1 if the value at the given acceptable index is a userdata +(either full or light), and 0 otherwise. + + + + + +


    lua_lessthan

    +[-0, +0, e] +

    int lua_lessthan (lua_State *L, int index1, int index2);
    + +

    +Returns 1 if the value at acceptable index index1 is smaller +than the value at acceptable index index2, +following the semantics of the Lua < operator +(that is, may call metamethods). +Otherwise returns 0. +Also returns 0 if any of the indices is non valid. + + + + + +


    lua_load

    +[-0, +1, -] +

    int lua_load (lua_State *L,
    +              lua_Reader reader,
    +              void *data,
    +              const char *chunkname);
    + +

    +Loads a Lua chunk. +If there are no errors, +lua_load pushes the compiled chunk as a Lua +function on top of the stack. +Otherwise, it pushes an error message. +The return values of lua_load are: + +

      + +
    • 0: no errors;
    • + +
    • LUA_ERRSYNTAX: +syntax error during pre-compilation;
    • + +
    • LUA_ERRMEM: +memory allocation error.
    • + +
    + +

    +This function only loads a chunk; +it does not run it. + + +

    +lua_load automatically detects whether the chunk is text or binary, +and loads it accordingly (see program luac). + + +

    +The lua_load function uses a user-supplied reader function +to read the chunk (see lua_Reader). +The data argument is an opaque value passed to the reader function. + + +

    +The chunkname argument gives a name to the chunk, +which is used for error messages and in debug information (see §3.8). + + + + + +


    lua_newstate

    +[-0, +0, -] +

    lua_State *lua_newstate (lua_Alloc f, void *ud);
    + +

    +Creates a new, independent state. +Returns NULL if cannot create the state +(due to lack of memory). +The argument f is the allocator function; +Lua does all memory allocation for this state through this function. +The second argument, ud, is an opaque pointer that Lua +simply passes to the allocator in every call. + + + + + +


    lua_newtable

    +[-0, +1, m] +

    void lua_newtable (lua_State *L);
    + +

    +Creates a new empty table and pushes it onto the stack. +It is equivalent to lua_createtable(L, 0, 0). + + + + + +


    lua_newthread

    +[-0, +1, m] +

    lua_State *lua_newthread (lua_State *L);
    + +

    +Creates a new thread, pushes it on the stack, +and returns a pointer to a lua_State that represents this new thread. +The new state returned by this function shares with the original state +all global objects (such as tables), +but has an independent execution stack. + + +

    +There is no explicit function to close or to destroy a thread. +Threads are subject to garbage collection, +like any Lua object. + + + + + +


    lua_newuserdata

    +[-0, +1, m] +

    void *lua_newuserdata (lua_State *L, size_t size);
    + +

    +This function allocates a new block of memory with the given size, +pushes onto the stack a new full userdata with the block address, +and returns this address. + + +

    +Userdata represent C values in Lua. +A full userdata represents a block of memory. +It is an object (like a table): +you must create it, it can have its own metatable, +and you can detect when it is being collected. +A full userdata is only equal to itself (under raw equality). + + +

    +When Lua collects a full userdata with a gc metamethod, +Lua calls the metamethod and marks the userdata as finalized. +When this userdata is collected again then +Lua frees its corresponding memory. + + + + + +


    lua_next

    +[-1, +(2|0), e] +

    int lua_next (lua_State *L, int index);
    + +

    +Pops a key from the stack, +and pushes a key-value pair from the table at the given index +(the "next" pair after the given key). +If there are no more elements in the table, +then lua_next returns 0 (and pushes nothing). + + +

    +A typical traversal looks like this: + +

    +     /* table is in the stack at index 't' */
    +     lua_pushnil(L);  /* first key */
    +     while (lua_next(L, t) != 0) {
    +       /* uses 'key' (at index -2) and 'value' (at index -1) */
    +       printf("%s - %s\n",
    +              lua_typename(L, lua_type(L, -2)),
    +              lua_typename(L, lua_type(L, -1)));
    +       /* removes 'value'; keeps 'key' for next iteration */
    +       lua_pop(L, 1);
    +     }
    +
    + +

    +While traversing a table, +do not call lua_tolstring directly on a key, +unless you know that the key is actually a string. +Recall that lua_tolstring changes +the value at the given index; +this confuses the next call to lua_next. + + + + + +


    lua_Number

    +
    typedef double lua_Number;
    + +

    +The type of numbers in Lua. +By default, it is double, but that can be changed in luaconf.h. + + +

    +Through the configuration file you can change +Lua to operate with another type for numbers (e.g., float or long). + + + + + +


    lua_objlen

    +[-0, +0, -] +

    size_t lua_objlen (lua_State *L, int index);
    + +

    +Returns the "length" of the value at the given acceptable index: +for strings, this is the string length; +for tables, this is the result of the length operator ('#'); +for userdata, this is the size of the block of memory allocated +for the userdata; +for other values, it is 0. + + + + + +


    lua_pcall

    +[-(nargs + 1), +(nresults|1), -] +

    int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc);
    + +

    +Calls a function in protected mode. + + +

    +Both nargs and nresults have the same meaning as +in lua_call. +If there are no errors during the call, +lua_pcall behaves exactly like lua_call. +However, if there is any error, +lua_pcall catches it, +pushes a single value on the stack (the error message), +and returns an error code. +Like lua_call, +lua_pcall always removes the function +and its arguments from the stack. + + +

    +If errfunc is 0, +then the error message returned on the stack +is exactly the original error message. +Otherwise, errfunc is the stack index of an +error handler function. +(In the current implementation, this index cannot be a pseudo-index.) +In case of runtime errors, +this function will be called with the error message +and its return value will be the message returned on the stack by lua_pcall. + + +

    +Typically, the error handler function is used to add more debug +information to the error message, such as a stack traceback. +Such information cannot be gathered after the return of lua_pcall, +since by then the stack has unwound. + + +

    +The lua_pcall function returns 0 in case of success +or one of the following error codes +(defined in lua.h): + +

      + +
    • LUA_ERRRUN: +a runtime error. +
    • + +
    • LUA_ERRMEM: +memory allocation error. +For such errors, Lua does not call the error handler function. +
    • + +
    • LUA_ERRERR: +error while running the error handler function. +
    • + +
    + + + + +

    lua_pop

    +[-n, +0, -] +

    void lua_pop (lua_State *L, int n);
    + +

    +Pops n elements from the stack. + + + + + +


    lua_pushboolean

    +[-0, +1, -] +

    void lua_pushboolean (lua_State *L, int b);
    + +

    +Pushes a boolean value with value b onto the stack. + + + + + +


    lua_pushcclosure

    +[-n, +1, m] +

    void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n);
    + +

    +Pushes a new C closure onto the stack. + + +

    +When a C function is created, +it is possible to associate some values with it, +thus creating a C closure (see §3.4); +these values are then accessible to the function whenever it is called. +To associate values with a C function, +first these values should be pushed onto the stack +(when there are multiple values, the first value is pushed first). +Then lua_pushcclosure +is called to create and push the C function onto the stack, +with the argument n telling how many values should be +associated with the function. +lua_pushcclosure also pops these values from the stack. + + +

    +The maximum value for n is 255. + + + + + +


    lua_pushcfunction

    +[-0, +1, m] +

    void lua_pushcfunction (lua_State *L, lua_CFunction f);
    + +

    +Pushes a C function onto the stack. +This function receives a pointer to a C function +and pushes onto the stack a Lua value of type function that, +when called, invokes the corresponding C function. + + +

    +Any function to be registered in Lua must +follow the correct protocol to receive its parameters +and return its results (see lua_CFunction). + + +

    +lua_pushcfunction is defined as a macro: + +

    +     #define lua_pushcfunction(L,f)  lua_pushcclosure(L,f,0)
    +
    + + + + +

    lua_pushfstring

    +[-0, +1, m] +

    const char *lua_pushfstring (lua_State *L, const char *fmt, ...);
    + +

    +Pushes onto the stack a formatted string +and returns a pointer to this string. +It is similar to the C function sprintf, +but has some important differences: + +

      + +
    • +You do not have to allocate space for the result: +the result is a Lua string and Lua takes care of memory allocation +(and deallocation, through garbage collection). +
    • + +
    • +The conversion specifiers are quite restricted. +There are no flags, widths, or precisions. +The conversion specifiers can only be +'%%' (inserts a '%' in the string), +'%s' (inserts a zero-terminated string, with no size restrictions), +'%f' (inserts a lua_Number), +'%p' (inserts a pointer as a hexadecimal numeral), +'%d' (inserts an int), and +'%c' (inserts an int as a character). +
    • + +
    + + + + +

    lua_pushinteger

    +[-0, +1, -] +

    void lua_pushinteger (lua_State *L, lua_Integer n);
    + +

    +Pushes a number with value n onto the stack. + + + + + +


    lua_pushlightuserdata

    +[-0, +1, -] +

    void lua_pushlightuserdata (lua_State *L, void *p);
    + +

    +Pushes a light userdata onto the stack. + + +

    +Userdata represent C values in Lua. +A light userdata represents a pointer. +It is a value (like a number): +you do not create it, it has no individual metatable, +and it is not collected (as it was never created). +A light userdata is equal to "any" +light userdata with the same C address. + + + + + +


    lua_pushliteral

    +[-0, +1, m] +

    void lua_pushliteral (lua_State *L, const char *s);
    + +

    +This macro is equivalent to lua_pushlstring, +but can be used only when s is a literal string. +In these cases, it automatically provides the string length. + + + + + +


    lua_pushlstring

    +[-0, +1, m] +

    void lua_pushlstring (lua_State *L, const char *s, size_t len);
    + +

    +Pushes the string pointed to by s with size len +onto the stack. +Lua makes (or reuses) an internal copy of the given string, +so the memory at s can be freed or reused immediately after +the function returns. +The string can contain embedded zeros. + + + + + +


    lua_pushnil

    +[-0, +1, -] +

    void lua_pushnil (lua_State *L);
    + +

    +Pushes a nil value onto the stack. + + + + + +


    lua_pushnumber

    +[-0, +1, -] +

    void lua_pushnumber (lua_State *L, lua_Number n);
    + +

    +Pushes a number with value n onto the stack. + + + + + +


    lua_pushstring

    +[-0, +1, m] +

    void lua_pushstring (lua_State *L, const char *s);
    + +

    +Pushes the zero-terminated string pointed to by s +onto the stack. +Lua makes (or reuses) an internal copy of the given string, +so the memory at s can be freed or reused immediately after +the function returns. +The string cannot contain embedded zeros; +it is assumed to end at the first zero. + + + + + +


    lua_pushthread

    +[-0, +1, -] +

    int lua_pushthread (lua_State *L);
    + +

    +Pushes the thread represented by L onto the stack. +Returns 1 if this thread is the main thread of its state. + + + + + +


    lua_pushvalue

    +[-0, +1, -] +

    void lua_pushvalue (lua_State *L, int index);
    + +

    +Pushes a copy of the element at the given valid index +onto the stack. + + + + + +


    lua_pushvfstring

    +[-0, +1, m] +

    const char *lua_pushvfstring (lua_State *L,
    +                              const char *fmt,
    +                              va_list argp);
    + +

    +Equivalent to lua_pushfstring, except that it receives a va_list +instead of a variable number of arguments. + + + + + +


    lua_rawequal

    +[-0, +0, -] +

    int lua_rawequal (lua_State *L, int index1, int index2);
    + +

    +Returns 1 if the two values in acceptable indices index1 and +index2 are primitively equal +(that is, without calling metamethods). +Otherwise returns 0. +Also returns 0 if any of the indices are non valid. + + + + + +


    lua_rawget

    +[-1, +1, -] +

    void lua_rawget (lua_State *L, int index);
    + +

    +Similar to lua_gettable, but does a raw access +(i.e., without metamethods). + + + + + +


    lua_rawgeti

    +[-0, +1, -] +

    void lua_rawgeti (lua_State *L, int index, int n);
    + +

    +Pushes onto the stack the value t[n], +where t is the value at the given valid index. +The access is raw; +that is, it does not invoke metamethods. + + + + + +


    lua_rawset

    +[-2, +0, m] +

    void lua_rawset (lua_State *L, int index);
    + +

    +Similar to lua_settable, but does a raw assignment +(i.e., without metamethods). + + + + + +


    lua_rawseti

    +[-1, +0, m] +

    void lua_rawseti (lua_State *L, int index, int n);
    + +

    +Does the equivalent of t[n] = v, +where t is the value at the given valid index +and v is the value at the top of the stack. + + +

    +This function pops the value from the stack. +The assignment is raw; +that is, it does not invoke metamethods. + + + + + +


    lua_Reader

    +
    typedef const char * (*lua_Reader) (lua_State *L,
    +                                    void *data,
    +                                    size_t *size);
    + +

    +The reader function used by lua_load. +Every time it needs another piece of the chunk, +lua_load calls the reader, +passing along its data parameter. +The reader must return a pointer to a block of memory +with a new piece of the chunk +and set size to the block size. +The block must exist until the reader function is called again. +To signal the end of the chunk, +the reader must return NULL or set size to zero. +The reader function may return pieces of any size greater than zero. + + + + + +


    lua_register

    +[-0, +0, e] +

    void lua_register (lua_State *L,
    +                   const char *name,
    +                   lua_CFunction f);
    + +

    +Sets the C function f as the new value of global name. +It is defined as a macro: + +

    +     #define lua_register(L,n,f) \
    +            (lua_pushcfunction(L, f), lua_setglobal(L, n))
    +
    + + + + +

    lua_remove

    +[-1, +0, -] +

    void lua_remove (lua_State *L, int index);
    + +

    +Removes the element at the given valid index, +shifting down the elements above this index to fill the gap. +Cannot be called with a pseudo-index, +because a pseudo-index is not an actual stack position. + + + + + +


    lua_replace

    +[-1, +0, -] +

    void lua_replace (lua_State *L, int index);
    + +

    +Moves the top element into the given position (and pops it), +without shifting any element +(therefore replacing the value at the given position). + + + + + +


    lua_resume

    +[-?, +?, -] +

    int lua_resume (lua_State *L, int narg);
    + +

    +Starts and resumes a coroutine in a given thread. + + +

    +To start a coroutine, you first create a new thread +(see lua_newthread); +then you push onto its stack the main function plus any arguments; +then you call lua_resume, +with narg being the number of arguments. +This call returns when the coroutine suspends or finishes its execution. +When it returns, the stack contains all values passed to lua_yield, +or all values returned by the body function. +lua_resume returns +LUA_YIELD if the coroutine yields, +0 if the coroutine finishes its execution +without errors, +or an error code in case of errors (see lua_pcall). +In case of errors, +the stack is not unwound, +so you can use the debug API over it. +The error message is on the top of the stack. +To restart a coroutine, you put on its stack only the values to +be passed as results from yield, +and then call lua_resume. + + + + + +


    lua_setallocf

    +[-0, +0, -] +

    void lua_setallocf (lua_State *L, lua_Alloc f, void *ud);
    + +

    +Changes the allocator function of a given state to f +with user data ud. + + + + + +


    lua_setfenv

    +[-1, +0, -] +

    int lua_setfenv (lua_State *L, int index);
    + +

    +Pops a table from the stack and sets it as +the new environment for the value at the given index. +If the value at the given index is +neither a function nor a thread nor a userdata, +lua_setfenv returns 0. +Otherwise it returns 1. + + + + + +


    lua_setfield

    +[-1, +0, e] +

    void lua_setfield (lua_State *L, int index, const char *k);
    + +

    +Does the equivalent to t[k] = v, +where t is the value at the given valid index +and v is the value at the top of the stack. + + +

    +This function pops the value from the stack. +As in Lua, this function may trigger a metamethod +for the "newindex" event (see §2.8). + + + + + +


    lua_setglobal

    +[-1, +0, e] +

    void lua_setglobal (lua_State *L, const char *name);
    + +

    +Pops a value from the stack and +sets it as the new value of global name. +It is defined as a macro: + +

    +     #define lua_setglobal(L,s)   lua_setfield(L, LUA_GLOBALSINDEX, s)
    +
    + + + + +

    lua_setmetatable

    +[-1, +0, -] +

    int lua_setmetatable (lua_State *L, int index);
    + +

    +Pops a table from the stack and +sets it as the new metatable for the value at the given +acceptable index. + + + + + +


    lua_settable

    +[-2, +0, e] +

    void lua_settable (lua_State *L, int index);
    + +

    +Does the equivalent to t[k] = v, +where t is the value at the given valid index, +v is the value at the top of the stack, +and k is the value just below the top. + + +

    +This function pops both the key and the value from the stack. +As in Lua, this function may trigger a metamethod +for the "newindex" event (see §2.8). + + + + + +


    lua_settop

    +[-?, +?, -] +

    void lua_settop (lua_State *L, int index);
    + +

    +Accepts any acceptable index, or 0, +and sets the stack top to this index. +If the new top is larger than the old one, +then the new elements are filled with nil. +If index is 0, then all stack elements are removed. + + + + + +


    lua_State

    +
    typedef struct lua_State lua_State;
    + +

    +Opaque structure that keeps the whole state of a Lua interpreter. +The Lua library is fully reentrant: +it has no global variables. +All information about a state is kept in this structure. + + +

    +A pointer to this state must be passed as the first argument to +every function in the library, except to lua_newstate, +which creates a Lua state from scratch. + + + + + +


    lua_status

    +[-0, +0, -] +

    int lua_status (lua_State *L);
    + +

    +Returns the status of the thread L. + + +

    +The status can be 0 for a normal thread, +an error code if the thread finished its execution with an error, +or LUA_YIELD if the thread is suspended. + + + + + +


    lua_toboolean

    +[-0, +0, -] +

    int lua_toboolean (lua_State *L, int index);
    + +

    +Converts the Lua value at the given acceptable index to a C boolean +value (0 or 1). +Like all tests in Lua, +lua_toboolean returns 1 for any Lua value +different from false and nil; +otherwise it returns 0. +It also returns 0 when called with a non-valid index. +(If you want to accept only actual boolean values, +use lua_isboolean to test the value's type.) + + + + + +


    lua_tocfunction

    +[-0, +0, -] +

    lua_CFunction lua_tocfunction (lua_State *L, int index);
    + +

    +Converts a value at the given acceptable index to a C function. +That value must be a C function; +otherwise, returns NULL. + + + + + +


    lua_tointeger

    +[-0, +0, -] +

    lua_Integer lua_tointeger (lua_State *L, int index);
    + +

    +Converts the Lua value at the given acceptable index +to the signed integral type lua_Integer. +The Lua value must be a number or a string convertible to a number +(see §2.2.1); +otherwise, lua_tointeger returns 0. + + +

    +If the number is not an integer, +it is truncated in some non-specified way. + + + + + +


    lua_tolstring

    +[-0, +0, m] +

    const char *lua_tolstring (lua_State *L, int index, size_t *len);
    + +

    +Converts the Lua value at the given acceptable index to a C string. +If len is not NULL, +it also sets *len with the string length. +The Lua value must be a string or a number; +otherwise, the function returns NULL. +If the value is a number, +then lua_tolstring also +changes the actual value in the stack to a string. +(This change confuses lua_next +when lua_tolstring is applied to keys during a table traversal.) + + +

    +lua_tolstring returns a fully aligned pointer +to a string inside the Lua state. +This string always has a zero ('\0') +after its last character (as in C), +but can contain other zeros in its body. +Because Lua has garbage collection, +there is no guarantee that the pointer returned by lua_tolstring +will be valid after the corresponding value is removed from the stack. + + + + + +


    lua_tonumber

    +[-0, +0, -] +

    lua_Number lua_tonumber (lua_State *L, int index);
    + +

    +Converts the Lua value at the given acceptable index +to the C type lua_Number (see lua_Number). +The Lua value must be a number or a string convertible to a number +(see §2.2.1); +otherwise, lua_tonumber returns 0. + + + + + +


    lua_topointer

    +[-0, +0, -] +

    const void *lua_topointer (lua_State *L, int index);
    + +

    +Converts the value at the given acceptable index to a generic +C pointer (void*). +The value can be a userdata, a table, a thread, or a function; +otherwise, lua_topointer returns NULL. +Different objects will give different pointers. +There is no way to convert the pointer back to its original value. + + +

    +Typically this function is used only for debug information. + + + + + +


    lua_tostring

    +[-0, +0, m] +

    const char *lua_tostring (lua_State *L, int index);
    + +

    +Equivalent to lua_tolstring with len equal to NULL. + + + + + +


    lua_tothread

    +[-0, +0, -] +

    lua_State *lua_tothread (lua_State *L, int index);
    + +

    +Converts the value at the given acceptable index to a Lua thread +(represented as lua_State*). +This value must be a thread; +otherwise, the function returns NULL. + + + + + +


    lua_touserdata

    +[-0, +0, -] +

    void *lua_touserdata (lua_State *L, int index);
    + +

    +If the value at the given acceptable index is a full userdata, +returns its block address. +If the value is a light userdata, +returns its pointer. +Otherwise, returns NULL. + + + + + +


    lua_type

    +[-0, +0, -] +

    int lua_type (lua_State *L, int index);
    + +

    +Returns the type of the value in the given acceptable index, +or LUA_TNONE for a non-valid index +(that is, an index to an "empty" stack position). +The types returned by lua_type are coded by the following constants +defined in lua.h: +LUA_TNIL, +LUA_TNUMBER, +LUA_TBOOLEAN, +LUA_TSTRING, +LUA_TTABLE, +LUA_TFUNCTION, +LUA_TUSERDATA, +LUA_TTHREAD, +and +LUA_TLIGHTUSERDATA. + + + + + +


    lua_typename

    +[-0, +0, -] +

    const char *lua_typename  (lua_State *L, int tp);
    + +

    +Returns the name of the type encoded by the value tp, +which must be one the values returned by lua_type. + + + + + +


    lua_Writer

    +
    typedef int (*lua_Writer) (lua_State *L,
    +                           const void* p,
    +                           size_t sz,
    +                           void* ud);
    + +

    +The type of the writer function used by lua_dump. +Every time it produces another piece of chunk, +lua_dump calls the writer, +passing along the buffer to be written (p), +its size (sz), +and the data parameter supplied to lua_dump. + + +

    +The writer returns an error code: +0 means no errors; +any other value means an error and stops lua_dump from +calling the writer again. + + + + + +


    lua_xmove

    +[-?, +?, -] +

    void lua_xmove (lua_State *from, lua_State *to, int n);
    + +

    +Exchange values between different threads of the same global state. + + +

    +This function pops n values from the stack from, +and pushes them onto the stack to. + + + + + +


    lua_yield

    +[-?, +?, -] +

    int lua_yield  (lua_State *L, int nresults);
    + +

    +Yields a coroutine. + + +

    +This function should only be called as the +return expression of a C function, as follows: + +

    +     return lua_yield (L, nresults);
    +

    +When a C function calls lua_yield in that way, +the running coroutine suspends its execution, +and the call to lua_resume that started this coroutine returns. +The parameter nresults is the number of values from the stack +that are passed as results to lua_resume. + + + + + + + +

    3.8 - The Debug Interface

    + +

    +Lua has no built-in debugging facilities. +Instead, it offers a special interface +by means of functions and hooks. +This interface allows the construction of different +kinds of debuggers, profilers, and other tools +that need "inside information" from the interpreter. + + + +


    lua_Debug

    +
    typedef struct lua_Debug {
    +  int event;
    +  const char *name;           /* (n) */
    +  const char *namewhat;       /* (n) */
    +  const char *what;           /* (S) */
    +  const char *source;         /* (S) */
    +  int currentline;            /* (l) */
    +  int nups;                   /* (u) number of upvalues */
    +  int linedefined;            /* (S) */
    +  int lastlinedefined;        /* (S) */
    +  char short_src[LUA_IDSIZE]; /* (S) */
    +  /* private part */
    +  other fields
    +} lua_Debug;
    + +

    +A structure used to carry different pieces of +information about an active function. +lua_getstack fills only the private part +of this structure, for later use. +To fill the other fields of lua_Debug with useful information, +call lua_getinfo. + + +

    +The fields of lua_Debug have the following meaning: + +

      + +
    • source: +If the function was defined in a string, +then source is that string. +If the function was defined in a file, +then source starts with a '@' followed by the file name. +
    • + +
    • short_src: +a "printable" version of source, to be used in error messages. +
    • + +
    • linedefined: +the line number where the definition of the function starts. +
    • + +
    • lastlinedefined: +the line number where the definition of the function ends. +
    • + +
    • what: +the string "Lua" if the function is a Lua function, +"C" if it is a C function, +"main" if it is the main part of a chunk, +and "tail" if it was a function that did a tail call. +In the latter case, +Lua has no other information about the function. +
    • + +
    • currentline: +the current line where the given function is executing. +When no line information is available, +currentline is set to -1. +
    • + +
    • name: +a reasonable name for the given function. +Because functions in Lua are first-class values, +they do not have a fixed name: +some functions can be the value of multiple global variables, +while others can be stored only in a table field. +The lua_getinfo function checks how the function was +called to find a suitable name. +If it cannot find a name, +then name is set to NULL. +
    • + +
    • namewhat: +explains the name field. +The value of namewhat can be +"global", "local", "method", +"field", "upvalue", or "" (the empty string), +according to how the function was called. +(Lua uses the empty string when no other option seems to apply.) +
    • + +
    • nups: +the number of upvalues of the function. +
    • + +
    + + + + +

    lua_gethook

    +[-0, +0, -] +

    lua_Hook lua_gethook (lua_State *L);
    + +

    +Returns the current hook function. + + + + + +


    lua_gethookcount

    +[-0, +0, -] +

    int lua_gethookcount (lua_State *L);
    + +

    +Returns the current hook count. + + + + + +


    lua_gethookmask

    +[-0, +0, -] +

    int lua_gethookmask (lua_State *L);
    + +

    +Returns the current hook mask. + + + + + +


    lua_getinfo

    +[-(0|1), +(0|1|2), m] +

    int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar);
    + +

    +Returns information about a specific function or function invocation. + + +

    +To get information about a function invocation, +the parameter ar must be a valid activation record that was +filled by a previous call to lua_getstack or +given as argument to a hook (see lua_Hook). + + +

    +To get information about a function you push it onto the stack +and start the what string with the character '>'. +(In that case, +lua_getinfo pops the function in the top of the stack.) +For instance, to know in which line a function f was defined, +you can write the following code: + +

    +     lua_Debug ar;
    +     lua_getfield(L, LUA_GLOBALSINDEX, "f");  /* get global 'f' */
    +     lua_getinfo(L, ">S", &ar);
    +     printf("%d\n", ar.linedefined);
    +
    + +

    +Each character in the string what +selects some fields of the structure ar to be filled or +a value to be pushed on the stack: + +

      + +
    • 'n': fills in the field name and namewhat; +
    • + +
    • 'S': +fills in the fields source, short_src, +linedefined, lastlinedefined, and what; +
    • + +
    • 'l': fills in the field currentline; +
    • + +
    • 'u': fills in the field nups; +
    • + +
    • 'f': +pushes onto the stack the function that is +running at the given level; +
    • + +
    • 'L': +pushes onto the stack a table whose indices are the +numbers of the lines that are valid on the function. +(A valid line is a line with some associated code, +that is, a line where you can put a break point. +Non-valid lines include empty lines and comments.) +
    • + +
    + +

    +This function returns 0 on error +(for instance, an invalid option in what). + + + + + +


    lua_getlocal

    +[-0, +(0|1), -] +

    const char *lua_getlocal (lua_State *L, lua_Debug *ar, int n);
    + +

    +Gets information about a local variable of a given activation record. +The parameter ar must be a valid activation record that was +filled by a previous call to lua_getstack or +given as argument to a hook (see lua_Hook). +The index n selects which local variable to inspect +(1 is the first parameter or active local variable, and so on, +until the last active local variable). +lua_getlocal pushes the variable's value onto the stack +and returns its name. + + +

    +Variable names starting with '(' (open parentheses) +represent internal variables +(loop control variables, temporaries, and C function locals). + + +

    +Returns NULL (and pushes nothing) +when the index is greater than +the number of active local variables. + + + + + +


    lua_getstack

    +[-0, +0, -] +

    int lua_getstack (lua_State *L, int level, lua_Debug *ar);
    + +

    +Get information about the interpreter runtime stack. + + +

    +This function fills parts of a lua_Debug structure with +an identification of the activation record +of the function executing at a given level. +Level 0 is the current running function, +whereas level n+1 is the function that has called level n. +When there are no errors, lua_getstack returns 1; +when called with a level greater than the stack depth, +it returns 0. + + + + + +


    lua_getupvalue

    +[-0, +(0|1), -] +

    const char *lua_getupvalue (lua_State *L, int funcindex, int n);
    + +

    +Gets information about a closure's upvalue. +(For Lua functions, +upvalues are the external local variables that the function uses, +and that are consequently included in its closure.) +lua_getupvalue gets the index n of an upvalue, +pushes the upvalue's value onto the stack, +and returns its name. +funcindex points to the closure in the stack. +(Upvalues have no particular order, +as they are active through the whole function. +So, they are numbered in an arbitrary order.) + + +

    +Returns NULL (and pushes nothing) +when the index is greater than the number of upvalues. +For C functions, this function uses the empty string "" +as a name for all upvalues. + + + + + +


    lua_Hook

    +
    typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar);
    + +

    +Type for debugging hook functions. + + +

    +Whenever a hook is called, its ar argument has its field +event set to the specific event that triggered the hook. +Lua identifies these events with the following constants: +LUA_HOOKCALL, LUA_HOOKRET, +LUA_HOOKTAILRET, LUA_HOOKLINE, +and LUA_HOOKCOUNT. +Moreover, for line events, the field currentline is also set. +To get the value of any other field in ar, +the hook must call lua_getinfo. +For return events, event can be LUA_HOOKRET, +the normal value, or LUA_HOOKTAILRET. +In the latter case, Lua is simulating a return from +a function that did a tail call; +in this case, it is useless to call lua_getinfo. + + +

    +While Lua is running a hook, it disables other calls to hooks. +Therefore, if a hook calls back Lua to execute a function or a chunk, +this execution occurs without any calls to hooks. + + + + + +


    lua_sethook

    +[-0, +0, -] +

    int lua_sethook (lua_State *L, lua_Hook f, int mask, int count);
    + +

    +Sets the debugging hook function. + + +

    +Argument f is the hook function. +mask specifies on which events the hook will be called: +it is formed by a bitwise or of the constants +LUA_MASKCALL, +LUA_MASKRET, +LUA_MASKLINE, +and LUA_MASKCOUNT. +The count argument is only meaningful when the mask +includes LUA_MASKCOUNT. +For each event, the hook is called as explained below: + +

      + +
    • The call hook: is called when the interpreter calls a function. +The hook is called just after Lua enters the new function, +before the function gets its arguments. +
    • + +
    • The return hook: is called when the interpreter returns from a function. +The hook is called just before Lua leaves the function. +You have no access to the values to be returned by the function. +
    • + +
    • The line hook: is called when the interpreter is about to +start the execution of a new line of code, +or when it jumps back in the code (even to the same line). +(This event only happens while Lua is executing a Lua function.) +
    • + +
    • The count hook: is called after the interpreter executes every +count instructions. +(This event only happens while Lua is executing a Lua function.) +
    • + +
    + +

    +A hook is disabled by setting mask to zero. + + + + + +


    lua_setlocal

    +[-(0|1), +0, -] +

    const char *lua_setlocal (lua_State *L, lua_Debug *ar, int n);
    + +

    +Sets the value of a local variable of a given activation record. +Parameters ar and n are as in lua_getlocal +(see lua_getlocal). +lua_setlocal assigns the value at the top of the stack +to the variable and returns its name. +It also pops the value from the stack. + + +

    +Returns NULL (and pops nothing) +when the index is greater than +the number of active local variables. + + + + + +


    lua_setupvalue

    +[-(0|1), +0, -] +

    const char *lua_setupvalue (lua_State *L, int funcindex, int n);
    + +

    +Sets the value of a closure's upvalue. +It assigns the value at the top of the stack +to the upvalue and returns its name. +It also pops the value from the stack. +Parameters funcindex and n are as in the lua_getupvalue +(see lua_getupvalue). + + +

    +Returns NULL (and pops nothing) +when the index is greater than the number of upvalues. + + + + + + + +

    4 - The Auxiliary Library

    + +

    + +The auxiliary library provides several convenient functions +to interface C with Lua. +While the basic API provides the primitive functions for all +interactions between C and Lua, +the auxiliary library provides higher-level functions for some +common tasks. + + +

    +All functions from the auxiliary library +are defined in header file lauxlib.h and +have a prefix luaL_. + + +

    +All functions in the auxiliary library are built on +top of the basic API, +and so they provide nothing that cannot be done with this API. + + +

    +Several functions in the auxiliary library are used to +check C function arguments. +Their names are always luaL_check* or luaL_opt*. +All of these functions throw an error if the check is not satisfied. +Because the error message is formatted for arguments +(e.g., "bad argument #1"), +you should not use these functions for other stack values. + + + +

    4.1 - Functions and Types

    + +

    +Here we list all functions and types from the auxiliary library +in alphabetical order. + + + +


    luaL_addchar

    +[-0, +0, m] +

    void luaL_addchar (luaL_Buffer *B, char c);
    + +

    +Adds the character c to the buffer B +(see luaL_Buffer). + + + + + +


    luaL_addlstring

    +[-0, +0, m] +

    void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l);
    + +

    +Adds the string pointed to by s with length l to +the buffer B +(see luaL_Buffer). +The string may contain embedded zeros. + + + + + +


    luaL_addsize

    +[-0, +0, m] +

    void luaL_addsize (luaL_Buffer *B, size_t n);
    + +

    +Adds to the buffer B (see luaL_Buffer) +a string of length n previously copied to the +buffer area (see luaL_prepbuffer). + + + + + +


    luaL_addstring

    +[-0, +0, m] +

    void luaL_addstring (luaL_Buffer *B, const char *s);
    + +

    +Adds the zero-terminated string pointed to by s +to the buffer B +(see luaL_Buffer). +The string may not contain embedded zeros. + + + + + +


    luaL_addvalue

    +[-1, +0, m] +

    void luaL_addvalue (luaL_Buffer *B);
    + +

    +Adds the value at the top of the stack +to the buffer B +(see luaL_Buffer). +Pops the value. + + +

    +This is the only function on string buffers that can (and must) +be called with an extra element on the stack, +which is the value to be added to the buffer. + + + + + +


    luaL_argcheck

    +[-0, +0, v] +

    void luaL_argcheck (lua_State *L,
    +                    int cond,
    +                    int narg,
    +                    const char *extramsg);
    + +

    +Checks whether cond is true. +If not, raises an error with the following message, +where func is retrieved from the call stack: + +

    +     bad argument #<narg> to <func> (<extramsg>)
    +
    + + + + +

    luaL_argerror

    +[-0, +0, v] +

    int luaL_argerror (lua_State *L, int narg, const char *extramsg);
    + +

    +Raises an error with the following message, +where func is retrieved from the call stack: + +

    +     bad argument #<narg> to <func> (<extramsg>)
    +
    + +

    +This function never returns, +but it is an idiom to use it in C functions +as return luaL_argerror(args). + + + + + +


    luaL_Buffer

    +
    typedef struct luaL_Buffer luaL_Buffer;
    + +

    +Type for a string buffer. + + +

    +A string buffer allows C code to build Lua strings piecemeal. +Its pattern of use is as follows: + +

      + +
    • First you declare a variable b of type luaL_Buffer.
    • + +
    • Then you initialize it with a call luaL_buffinit(L, &b).
    • + +
    • +Then you add string pieces to the buffer calling any of +the luaL_add* functions. +
    • + +
    • +You finish by calling luaL_pushresult(&b). +This call leaves the final string on the top of the stack. +
    • + +
    + +

    +During its normal operation, +a string buffer uses a variable number of stack slots. +So, while using a buffer, you cannot assume that you know where +the top of the stack is. +You can use the stack between successive calls to buffer operations +as long as that use is balanced; +that is, +when you call a buffer operation, +the stack is at the same level +it was immediately after the previous buffer operation. +(The only exception to this rule is luaL_addvalue.) +After calling luaL_pushresult the stack is back to its +level when the buffer was initialized, +plus the final string on its top. + + + + + +


    luaL_buffinit

    +[-0, +0, -] +

    void luaL_buffinit (lua_State *L, luaL_Buffer *B);
    + +

    +Initializes a buffer B. +This function does not allocate any space; +the buffer must be declared as a variable +(see luaL_Buffer). + + + + + +


    luaL_callmeta

    +[-0, +(0|1), e] +

    int luaL_callmeta (lua_State *L, int obj, const char *e);
    + +

    +Calls a metamethod. + + +

    +If the object at index obj has a metatable and this +metatable has a field e, +this function calls this field and passes the object as its only argument. +In this case this function returns 1 and pushes onto the +stack the value returned by the call. +If there is no metatable or no metamethod, +this function returns 0 (without pushing any value on the stack). + + + + + +


    luaL_checkany

    +[-0, +0, v] +

    void luaL_checkany (lua_State *L, int narg);
    + +

    +Checks whether the function has an argument +of any type (including nil) at position narg. + + + + + +


    luaL_checkint

    +[-0, +0, v] +

    int luaL_checkint (lua_State *L, int narg);
    + +

    +Checks whether the function argument narg is a number +and returns this number cast to an int. + + + + + +


    luaL_checkinteger

    +[-0, +0, v] +

    lua_Integer luaL_checkinteger (lua_State *L, int narg);
    + +

    +Checks whether the function argument narg is a number +and returns this number cast to a lua_Integer. + + + + + +


    luaL_checklong

    +[-0, +0, v] +

    long luaL_checklong (lua_State *L, int narg);
    + +

    +Checks whether the function argument narg is a number +and returns this number cast to a long. + + + + + +


    luaL_checklstring

    +[-0, +0, v] +

    const char *luaL_checklstring (lua_State *L, int narg, size_t *l);
    + +

    +Checks whether the function argument narg is a string +and returns this string; +if l is not NULL fills *l +with the string's length. + + +

    +This function uses lua_tolstring to get its result, +so all conversions and caveats of that function apply here. + + + + + +


    luaL_checknumber

    +[-0, +0, v] +

    lua_Number luaL_checknumber (lua_State *L, int narg);
    + +

    +Checks whether the function argument narg is a number +and returns this number. + + + + + +


    luaL_checkoption

    +[-0, +0, v] +

    int luaL_checkoption (lua_State *L,
    +                      int narg,
    +                      const char *def,
    +                      const char *const lst[]);
    + +

    +Checks whether the function argument narg is a string and +searches for this string in the array lst +(which must be NULL-terminated). +Returns the index in the array where the string was found. +Raises an error if the argument is not a string or +if the string cannot be found. + + +

    +If def is not NULL, +the function uses def as a default value when +there is no argument narg or if this argument is nil. + + +

    +This is a useful function for mapping strings to C enums. +(The usual convention in Lua libraries is +to use strings instead of numbers to select options.) + + + + + +


    luaL_checkstack

    +[-0, +0, v] +

    void luaL_checkstack (lua_State *L, int sz, const char *msg);
    + +

    +Grows the stack size to top + sz elements, +raising an error if the stack cannot grow to that size. +msg is an additional text to go into the error message. + + + + + +


    luaL_checkstring

    +[-0, +0, v] +

    const char *luaL_checkstring (lua_State *L, int narg);
    + +

    +Checks whether the function argument narg is a string +and returns this string. + + +

    +This function uses lua_tolstring to get its result, +so all conversions and caveats of that function apply here. + + + + + +


    luaL_checktype

    +[-0, +0, v] +

    void luaL_checktype (lua_State *L, int narg, int t);
    + +

    +Checks whether the function argument narg has type t. +See lua_type for the encoding of types for t. + + + + + +


    luaL_checkudata

    +[-0, +0, v] +

    void *luaL_checkudata (lua_State *L, int narg, const char *tname);
    + +

    +Checks whether the function argument narg is a userdata +of the type tname (see luaL_newmetatable). + + + + + +


    luaL_dofile

    +[-0, +?, m] +

    int luaL_dofile (lua_State *L, const char *filename);
    + +

    +Loads and runs the given file. +It is defined as the following macro: + +

    +     (luaL_loadfile(L, filename) || lua_pcall(L, 0, LUA_MULTRET, 0))
    +

    +It returns 0 if there are no errors +or 1 in case of errors. + + + + + +


    luaL_dostring

    +[-0, +?, m] +

    int luaL_dostring (lua_State *L, const char *str);
    + +

    +Loads and runs the given string. +It is defined as the following macro: + +

    +     (luaL_loadstring(L, str) || lua_pcall(L, 0, LUA_MULTRET, 0))
    +

    +It returns 0 if there are no errors +or 1 in case of errors. + + + + + +


    luaL_error

    +[-0, +0, v] +

    int luaL_error (lua_State *L, const char *fmt, ...);
    + +

    +Raises an error. +The error message format is given by fmt +plus any extra arguments, +following the same rules of lua_pushfstring. +It also adds at the beginning of the message the file name and +the line number where the error occurred, +if this information is available. + + +

    +This function never returns, +but it is an idiom to use it in C functions +as return luaL_error(args). + + + + + +


    luaL_getmetafield

    +[-0, +(0|1), m] +

    int luaL_getmetafield (lua_State *L, int obj, const char *e);
    + +

    +Pushes onto the stack the field e from the metatable +of the object at index obj. +If the object does not have a metatable, +or if the metatable does not have this field, +returns 0 and pushes nothing. + + + + + +


    luaL_getmetatable

    +[-0, +1, -] +

    void luaL_getmetatable (lua_State *L, const char *tname);
    + +

    +Pushes onto the stack the metatable associated with name tname +in the registry (see luaL_newmetatable). + + + + + +


    luaL_gsub

    +[-0, +1, m] +

    const char *luaL_gsub (lua_State *L,
    +                       const char *s,
    +                       const char *p,
    +                       const char *r);
    + +

    +Creates a copy of string s by replacing +any occurrence of the string p +with the string r. +Pushes the resulting string on the stack and returns it. + + + + + +


    luaL_loadbuffer

    +[-0, +1, m] +

    int luaL_loadbuffer (lua_State *L,
    +                     const char *buff,
    +                     size_t sz,
    +                     const char *name);
    + +

    +Loads a buffer as a Lua chunk. +This function uses lua_load to load the chunk in the +buffer pointed to by buff with size sz. + + +

    +This function returns the same results as lua_load. +name is the chunk name, +used for debug information and error messages. + + + + + +


    luaL_loadfile

    +[-0, +1, m] +

    int luaL_loadfile (lua_State *L, const char *filename);
    + +

    +Loads a file as a Lua chunk. +This function uses lua_load to load the chunk in the file +named filename. +If filename is NULL, +then it loads from the standard input. +The first line in the file is ignored if it starts with a #. + + +

    +This function returns the same results as lua_load, +but it has an extra error code LUA_ERRFILE +if it cannot open/read the file. + + +

    +As lua_load, this function only loads the chunk; +it does not run it. + + + + + +


    luaL_loadstring

    +[-0, +1, m] +

    int luaL_loadstring (lua_State *L, const char *s);
    + +

    +Loads a string as a Lua chunk. +This function uses lua_load to load the chunk in +the zero-terminated string s. + + +

    +This function returns the same results as lua_load. + + +

    +Also as lua_load, this function only loads the chunk; +it does not run it. + + + + + +


    luaL_newmetatable

    +[-0, +1, m] +

    int luaL_newmetatable (lua_State *L, const char *tname);
    + +

    +If the registry already has the key tname, +returns 0. +Otherwise, +creates a new table to be used as a metatable for userdata, +adds it to the registry with key tname, +and returns 1. + + +

    +In both cases pushes onto the stack the final value associated +with tname in the registry. + + + + + +


    luaL_newstate

    +[-0, +0, -] +

    lua_State *luaL_newstate (void);
    + +

    +Creates a new Lua state. +It calls lua_newstate with an +allocator based on the standard C realloc function +and then sets a panic function (see lua_atpanic) that prints +an error message to the standard error output in case of fatal +errors. + + +

    +Returns the new state, +or NULL if there is a memory allocation error. + + + + + +


    luaL_openlibs

    +[-0, +0, m] +

    void luaL_openlibs (lua_State *L);
    + +

    +Opens all standard Lua libraries into the given state. + + + + + +


    luaL_optint

    +[-0, +0, v] +

    int luaL_optint (lua_State *L, int narg, int d);
    + +

    +If the function argument narg is a number, +returns this number cast to an int. +If this argument is absent or is nil, +returns d. +Otherwise, raises an error. + + + + + +


    luaL_optinteger

    +[-0, +0, v] +

    lua_Integer luaL_optinteger (lua_State *L,
    +                             int narg,
    +                             lua_Integer d);
    + +

    +If the function argument narg is a number, +returns this number cast to a lua_Integer. +If this argument is absent or is nil, +returns d. +Otherwise, raises an error. + + + + + +


    luaL_optlong

    +[-0, +0, v] +

    long luaL_optlong (lua_State *L, int narg, long d);
    + +

    +If the function argument narg is a number, +returns this number cast to a long. +If this argument is absent or is nil, +returns d. +Otherwise, raises an error. + + + + + +


    luaL_optlstring

    +[-0, +0, v] +

    const char *luaL_optlstring (lua_State *L,
    +                             int narg,
    +                             const char *d,
    +                             size_t *l);
    + +

    +If the function argument narg is a string, +returns this string. +If this argument is absent or is nil, +returns d. +Otherwise, raises an error. + + +

    +If l is not NULL, +fills the position *l with the results's length. + + + + + +


    luaL_optnumber

    +[-0, +0, v] +

    lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number d);
    + +

    +If the function argument narg is a number, +returns this number. +If this argument is absent or is nil, +returns d. +Otherwise, raises an error. + + + + + +


    luaL_optstring

    +[-0, +0, v] +

    const char *luaL_optstring (lua_State *L,
    +                            int narg,
    +                            const char *d);
    + +

    +If the function argument narg is a string, +returns this string. +If this argument is absent or is nil, +returns d. +Otherwise, raises an error. + + + + + +


    luaL_prepbuffer

    +[-0, +0, -] +

    char *luaL_prepbuffer (luaL_Buffer *B);
    + +

    +Returns an address to a space of size LUAL_BUFFERSIZE +where you can copy a string to be added to buffer B +(see luaL_Buffer). +After copying the string into this space you must call +luaL_addsize with the size of the string to actually add +it to the buffer. + + + + + +


    luaL_pushresult

    +[-?, +1, m] +

    void luaL_pushresult (luaL_Buffer *B);
    + +

    +Finishes the use of buffer B leaving the final string on +the top of the stack. + + + + + +


    luaL_ref

    +[-1, +0, m] +

    int luaL_ref (lua_State *L, int t);
    + +

    +Creates and returns a reference, +in the table at index t, +for the object at the top of the stack (and pops the object). + + +

    +A reference is a unique integer key. +As long as you do not manually add integer keys into table t, +luaL_ref ensures the uniqueness of the key it returns. +You can retrieve an object referred by reference r +by calling lua_rawgeti(L, t, r). +Function luaL_unref frees a reference and its associated object. + + +

    +If the object at the top of the stack is nil, +luaL_ref returns the constant LUA_REFNIL. +The constant LUA_NOREF is guaranteed to be different +from any reference returned by luaL_ref. + + + + + +


    luaL_Reg

    +
    typedef struct luaL_Reg {
    +  const char *name;
    +  lua_CFunction func;
    +} luaL_Reg;
    + +

    +Type for arrays of functions to be registered by +luaL_register. +name is the function name and func is a pointer to +the function. +Any array of luaL_Reg must end with an sentinel entry +in which both name and func are NULL. + + + + + +


    luaL_register

    +[-(0|1), +1, m] +

    void luaL_register (lua_State *L,
    +                    const char *libname,
    +                    const luaL_Reg *l);
    + +

    +Opens a library. + + +

    +When called with libname equal to NULL, +it simply registers all functions in the list l +(see luaL_Reg) into the table on the top of the stack. + + +

    +When called with a non-null libname, +luaL_register creates a new table t, +sets it as the value of the global variable libname, +sets it as the value of package.loaded[libname], +and registers on it all functions in the list l. +If there is a table in package.loaded[libname] or in +variable libname, +reuses this table instead of creating a new one. + + +

    +In any case the function leaves the table +on the top of the stack. + + + + + +


    luaL_typename

    +[-0, +0, -] +

    const char *luaL_typename (lua_State *L, int index);
    + +

    +Returns the name of the type of the value at the given index. + + + + + +


    luaL_typerror

    +[-0, +0, v] +

    int luaL_typerror (lua_State *L, int narg, const char *tname);
    + +

    +Generates an error with a message like the following: + +

    +     location: bad argument narg to 'func' (tname expected, got rt)
    +

    +where location is produced by luaL_where, +func is the name of the current function, +and rt is the type name of the actual argument. + + + + + +


    luaL_unref

    +[-0, +0, -] +

    void luaL_unref (lua_State *L, int t, int ref);
    + +

    +Releases reference ref from the table at index t +(see luaL_ref). +The entry is removed from the table, +so that the referred object can be collected. +The reference ref is also freed to be used again. + + +

    +If ref is LUA_NOREF or LUA_REFNIL, +luaL_unref does nothing. + + + + + +


    luaL_where

    +[-0, +1, m] +

    void luaL_where (lua_State *L, int lvl);
    + +

    +Pushes onto the stack a string identifying the current position +of the control at level lvl in the call stack. +Typically this string has the following format: + +

    +     chunkname:currentline:
    +

    +Level 0 is the running function, +level 1 is the function that called the running function, +etc. + + +

    +This function is used to build a prefix for error messages. + + + + + + + +

    5 - Standard Libraries

    + +

    +The standard Lua libraries provide useful functions +that are implemented directly through the C API. +Some of these functions provide essential services to the language +(e.g., type and getmetatable); +others provide access to "outside" services (e.g., I/O); +and others could be implemented in Lua itself, +but are quite useful or have critical performance requirements that +deserve an implementation in C (e.g., table.sort). + + +

    +All libraries are implemented through the official C API +and are provided as separate C modules. +Currently, Lua has the following standard libraries: + +

      + +
    • basic library, which includes the coroutine sub-library;
    • + +
    • package library;
    • + +
    • string manipulation;
    • + +
    • table manipulation;
    • + +
    • mathematical functions (sin, log, etc.);
    • + +
    • input and output;
    • + +
    • operating system facilities;
    • + +
    • debug facilities.
    • + +

    +Except for the basic and package libraries, +each library provides all its functions as fields of a global table +or as methods of its objects. + + +

    +To have access to these libraries, +the C host program should call the luaL_openlibs function, +which opens all standard libraries. +Alternatively, +it can open them individually by calling +luaopen_base (for the basic library), +luaopen_package (for the package library), +luaopen_string (for the string library), +luaopen_table (for the table library), +luaopen_math (for the mathematical library), +luaopen_io (for the I/O library), +luaopen_os (for the Operating System library), +and luaopen_debug (for the debug library). +These functions are declared in lualib.h +and should not be called directly: +you must call them like any other Lua C function, +e.g., by using lua_call. + + + +

    5.1 - Basic Functions

    + +

    +The basic library provides some core functions to Lua. +If you do not include this library in your application, +you should check carefully whether you need to provide +implementations for some of its facilities. + + +

    +


    assert (v [, message])

    +Issues an error when +the value of its argument v is false (i.e., nil or false); +otherwise, returns all its arguments. +message is an error message; +when absent, it defaults to "assertion failed!" + + + + +

    +


    collectgarbage ([opt [, arg]])

    + + +

    +This function is a generic interface to the garbage collector. +It performs different functions according to its first argument, opt: + +

      + +
    • "collect": +performs a full garbage-collection cycle. +This is the default option. +
    • + +
    • "stop": +stops the garbage collector. +
    • + +
    • "restart": +restarts the garbage collector. +
    • + +
    • "count": +returns the total memory in use by Lua (in Kbytes). +
    • + +
    • "step": +performs a garbage-collection step. +The step "size" is controlled by arg +(larger values mean more steps) in a non-specified way. +If you want to control the step size +you must experimentally tune the value of arg. +Returns true if the step finished a collection cycle. +
    • + +
    • "setpause": +sets arg as the new value for the pause of +the collector (see §2.10). +Returns the previous value for pause. +
    • + +
    • "setstepmul": +sets arg as the new value for the step multiplier of +the collector (see §2.10). +Returns the previous value for step. +
    • + +
    + + + +

    +


    dofile ([filename])

    +Opens the named file and executes its contents as a Lua chunk. +When called without arguments, +dofile executes the contents of the standard input (stdin). +Returns all values returned by the chunk. +In case of errors, dofile propagates the error +to its caller (that is, dofile does not run in protected mode). + + + + +

    +


    error (message [, level])

    +Terminates the last protected function called +and returns message as the error message. +Function error never returns. + + +

    +Usually, error adds some information about the error position +at the beginning of the message. +The level argument specifies how to get the error position. +With level 1 (the default), the error position is where the +error function was called. +Level 2 points the error to where the function +that called error was called; and so on. +Passing a level 0 avoids the addition of error position information +to the message. + + + + +

    +


    _G

    +A global variable (not a function) that +holds the global environment (that is, _G._G = _G). +Lua itself does not use this variable; +changing its value does not affect any environment, +nor vice-versa. +(Use setfenv to change environments.) + + + + +

    +


    getfenv ([f])

    +Returns the current environment in use by the function. +f can be a Lua function or a number +that specifies the function at that stack level: +Level 1 is the function calling getfenv. +If the given function is not a Lua function, +or if f is 0, +getfenv returns the global environment. +The default for f is 1. + + + + +

    +


    getmetatable (object)

    + + +

    +If object does not have a metatable, returns nil. +Otherwise, +if the object's metatable has a "__metatable" field, +returns the associated value. +Otherwise, returns the metatable of the given object. + + + + +

    +


    ipairs (t)

    + + +

    +Returns three values: an iterator function, the table t, and 0, +so that the construction + +

    +     for i,v in ipairs(t) do body end
    +

    +will iterate over the pairs (1,t[1]), (2,t[2]), ···, +up to the first integer key absent from the table. + + + + +

    +


    load (func [, chunkname])

    + + +

    +Loads a chunk using function func to get its pieces. +Each call to func must return a string that concatenates +with previous results. +A return of an empty string, nil, or no value signals the end of the chunk. + + +

    +If there are no errors, +returns the compiled chunk as a function; +otherwise, returns nil plus the error message. +The environment of the returned function is the global environment. + + +

    +chunkname is used as the chunk name for error messages +and debug information. +When absent, +it defaults to "=(load)". + + + + +

    +


    loadfile ([filename])

    + + +

    +Similar to load, +but gets the chunk from file filename +or from the standard input, +if no file name is given. + + + + +

    +


    loadstring (string [, chunkname])

    + + +

    +Similar to load, +but gets the chunk from the given string. + + +

    +To load and run a given string, use the idiom + +

    +     assert(loadstring(s))()
    +
    + +

    +When absent, +chunkname defaults to the given string. + + + + +

    +


    next (table [, index])

    + + +

    +Allows a program to traverse all fields of a table. +Its first argument is a table and its second argument +is an index in this table. +next returns the next index of the table +and its associated value. +When called with nil as its second argument, +next returns an initial index +and its associated value. +When called with the last index, +or with nil in an empty table, +next returns nil. +If the second argument is absent, then it is interpreted as nil. +In particular, +you can use next(t) to check whether a table is empty. + + +

    +The order in which the indices are enumerated is not specified, +even for numeric indices. +(To traverse a table in numeric order, +use a numerical for or the ipairs function.) + + +

    +The behavior of next is undefined if, +during the traversal, +you assign any value to a non-existent field in the table. +You may however modify existing fields. +In particular, you may clear existing fields. + + + + +

    +


    pairs (t)

    + + +

    +Returns three values: the next function, the table t, and nil, +so that the construction + +

    +     for k,v in pairs(t) do body end
    +

    +will iterate over all key–value pairs of table t. + + +

    +See function next for the caveats of modifying +the table during its traversal. + + + + +

    +


    pcall (f, arg1, ···)

    + + +

    +Calls function f with +the given arguments in protected mode. +This means that any error inside f is not propagated; +instead, pcall catches the error +and returns a status code. +Its first result is the status code (a boolean), +which is true if the call succeeds without errors. +In such case, pcall also returns all results from the call, +after this first result. +In case of any error, pcall returns false plus the error message. + + + + +

    +


    print (···)

    +Receives any number of arguments, +and prints their values to stdout, +using the tostring function to convert them to strings. +print is not intended for formatted output, +but only as a quick way to show a value, +typically for debugging. +For formatted output, use string.format. + + + + +

    +


    rawequal (v1, v2)

    +Checks whether v1 is equal to v2, +without invoking any metamethod. +Returns a boolean. + + + + +

    +


    rawget (table, index)

    +Gets the real value of table[index], +without invoking any metamethod. +table must be a table; +index may be any value. + + + + +

    +


    rawset (table, index, value)

    +Sets the real value of table[index] to value, +without invoking any metamethod. +table must be a table, +index any value different from nil, +and value any Lua value. + + +

    +This function returns table. + + + + +

    +


    select (index, ···)

    + + +

    +If index is a number, +returns all arguments after argument number index. +Otherwise, index must be the string "#", +and select returns the total number of extra arguments it received. + + + + +

    +


    setfenv (f, table)

    + + +

    +Sets the environment to be used by the given function. +f can be a Lua function or a number +that specifies the function at that stack level: +Level 1 is the function calling setfenv. +setfenv returns the given function. + + +

    +As a special case, when f is 0 setfenv changes +the environment of the running thread. +In this case, setfenv returns no values. + + + + +

    +


    setmetatable (table, metatable)

    + + +

    +Sets the metatable for the given table. +(You cannot change the metatable of other types from Lua, only from C.) +If metatable is nil, +removes the metatable of the given table. +If the original metatable has a "__metatable" field, +raises an error. + + +

    +This function returns table. + + + + +

    +


    tonumber (e [, base])

    +Tries to convert its argument to a number. +If the argument is already a number or a string convertible +to a number, then tonumber returns this number; +otherwise, it returns nil. + + +

    +An optional argument specifies the base to interpret the numeral. +The base may be any integer between 2 and 36, inclusive. +In bases above 10, the letter 'A' (in either upper or lower case) +represents 10, 'B' represents 11, and so forth, +with 'Z' representing 35. +In base 10 (the default), the number can have a decimal part, +as well as an optional exponent part (see §2.1). +In other bases, only unsigned integers are accepted. + + + + +

    +


    tostring (e)

    +Receives an argument of any type and +converts it to a string in a reasonable format. +For complete control of how numbers are converted, +use string.format. + + +

    +If the metatable of e has a "__tostring" field, +then tostring calls the corresponding value +with e as argument, +and uses the result of the call as its result. + + + + +

    +


    type (v)

    +Returns the type of its only argument, coded as a string. +The possible results of this function are +"nil" (a string, not the value nil), +"number", +"string", +"boolean", +"table", +"function", +"thread", +and "userdata". + + + + +

    +


    unpack (list [, i [, j]])

    +Returns the elements from the given table. +This function is equivalent to + +
    +     return list[i], list[i+1], ···, list[j]
    +

    +except that the above code can be written only for a fixed number +of elements. +By default, i is 1 and j is the length of the list, +as defined by the length operator (see §2.5.5). + + + + +

    +


    _VERSION

    +A global variable (not a function) that +holds a string containing the current interpreter version. +The current contents of this variable is "Lua 5.1". + + + + +

    +


    xpcall (f, err)

    + + +

    +This function is similar to pcall, +except that you can set a new error handler. + + +

    +xpcall calls function f in protected mode, +using err as the error handler. +Any error inside f is not propagated; +instead, xpcall catches the error, +calls the err function with the original error object, +and returns a status code. +Its first result is the status code (a boolean), +which is true if the call succeeds without errors. +In this case, xpcall also returns all results from the call, +after this first result. +In case of any error, +xpcall returns false plus the result from err. + + + + + + + +

    5.2 - Coroutine Manipulation

    + +

    +The operations related to coroutines comprise a sub-library of +the basic library and come inside the table coroutine. +See §2.11 for a general description of coroutines. + + +

    +


    coroutine.create (f)

    + + +

    +Creates a new coroutine, with body f. +f must be a Lua function. +Returns this new coroutine, +an object with type "thread". + + + + +

    +


    coroutine.resume (co [, val1, ···])

    + + +

    +Starts or continues the execution of coroutine co. +The first time you resume a coroutine, +it starts running its body. +The values val1, ··· are passed +as the arguments to the body function. +If the coroutine has yielded, +resume restarts it; +the values val1, ··· are passed +as the results from the yield. + + +

    +If the coroutine runs without any errors, +resume returns true plus any values passed to yield +(if the coroutine yields) or any values returned by the body function +(if the coroutine terminates). +If there is any error, +resume returns false plus the error message. + + + + +

    +


    coroutine.running ()

    + + +

    +Returns the running coroutine, +or nil when called by the main thread. + + + + +

    +


    coroutine.status (co)

    + + +

    +Returns the status of coroutine co, as a string: +"running", +if the coroutine is running (that is, it called status); +"suspended", if the coroutine is suspended in a call to yield, +or if it has not started running yet; +"normal" if the coroutine is active but not running +(that is, it has resumed another coroutine); +and "dead" if the coroutine has finished its body function, +or if it has stopped with an error. + + + + +

    +


    coroutine.wrap (f)

    + + +

    +Creates a new coroutine, with body f. +f must be a Lua function. +Returns a function that resumes the coroutine each time it is called. +Any arguments passed to the function behave as the +extra arguments to resume. +Returns the same values returned by resume, +except the first boolean. +In case of error, propagates the error. + + + + +

    +


    coroutine.yield (···)

    + + +

    +Suspends the execution of the calling coroutine. +The coroutine cannot be running a C function, +a metamethod, or an iterator. +Any arguments to yield are passed as extra results to resume. + + + + + + + +

    5.3 - Modules

    + +

    +The package library provides basic +facilities for loading and building modules in Lua. +It exports two of its functions directly in the global environment: +require and module. +Everything else is exported in a table package. + + +

    +


    module (name [, ···])

    + + +

    +Creates a module. +If there is a table in package.loaded[name], +this table is the module. +Otherwise, if there is a global table t with the given name, +this table is the module. +Otherwise creates a new table t and +sets it as the value of the global name and +the value of package.loaded[name]. +This function also initializes t._NAME with the given name, +t._M with the module (t itself), +and t._PACKAGE with the package name +(the full module name minus last component; see below). +Finally, module sets t as the new environment +of the current function and the new value of package.loaded[name], +so that require returns t. + + +

    +If name is a compound name +(that is, one with components separated by dots), +module creates (or reuses, if they already exist) +tables for each component. +For instance, if name is a.b.c, +then module stores the module table in field c of +field b of global a. + + +

    +This function can receive optional options after +the module name, +where each option is a function to be applied over the module. + + + + +

    +


    require (modname)

    + + +

    +Loads the given module. +The function starts by looking into the package.loaded table +to determine whether modname is already loaded. +If it is, then require returns the value stored +at package.loaded[modname]. +Otherwise, it tries to find a loader for the module. + + +

    +To find a loader, +require is guided by the package.loaders array. +By changing this array, +we can change how require looks for a module. +The following explanation is based on the default configuration +for package.loaders. + + +

    +First require queries package.preload[modname]. +If it has a value, +this value (which should be a function) is the loader. +Otherwise require searches for a Lua loader using the +path stored in package.path. +If that also fails, it searches for a C loader using the +path stored in package.cpath. +If that also fails, +it tries an all-in-one loader (see package.loaders). + + +

    +Once a loader is found, +require calls the loader with a single argument, modname. +If the loader returns any value, +require assigns the returned value to package.loaded[modname]. +If the loader returns no value and +has not assigned any value to package.loaded[modname], +then require assigns true to this entry. +In any case, require returns the +final value of package.loaded[modname]. + + +

    +If there is any error loading or running the module, +or if it cannot find any loader for the module, +then require signals an error. + + + + +

    +


    package.cpath

    + + +

    +The path used by require to search for a C loader. + + +

    +Lua initializes the C path package.cpath in the same way +it initializes the Lua path package.path, +using the environment variable LUA_CPATH +or a default path defined in luaconf.h. + + + + +

    + +


    package.loaded

    + + +

    +A table used by require to control which +modules are already loaded. +When you require a module modname and +package.loaded[modname] is not false, +require simply returns the value stored there. + + + + +

    +


    package.loaders

    + + +

    +A table used by require to control how to load modules. + + +

    +Each entry in this table is a searcher function. +When looking for a module, +require calls each of these searchers in ascending order, +with the module name (the argument given to require) as its +sole parameter. +The function can return another function (the module loader) +or a string explaining why it did not find that module +(or nil if it has nothing to say). +Lua initializes this table with four functions. + + +

    +The first searcher simply looks for a loader in the +package.preload table. + + +

    +The second searcher looks for a loader as a Lua library, +using the path stored at package.path. +A path is a sequence of templates separated by semicolons. +For each template, +the searcher will change each interrogation +mark in the template by filename, +which is the module name with each dot replaced by a +"directory separator" (such as "/" in Unix); +then it will try to open the resulting file name. +So, for instance, if the Lua path is the string + +

    +     "./?.lua;./?.lc;/usr/local/?/init.lua"
    +

    +the search for a Lua file for module foo +will try to open the files +./foo.lua, ./foo.lc, and +/usr/local/foo/init.lua, in that order. + + +

    +The third searcher looks for a loader as a C library, +using the path given by the variable package.cpath. +For instance, +if the C path is the string + +

    +     "./?.so;./?.dll;/usr/local/?/init.so"
    +

    +the searcher for module foo +will try to open the files ./foo.so, ./foo.dll, +and /usr/local/foo/init.so, in that order. +Once it finds a C library, +this searcher first uses a dynamic link facility to link the +application with the library. +Then it tries to find a C function inside the library to +be used as the loader. +The name of this C function is the string "luaopen_" +concatenated with a copy of the module name where each dot +is replaced by an underscore. +Moreover, if the module name has a hyphen, +its prefix up to (and including) the first hyphen is removed. +For instance, if the module name is a.v1-b.c, +the function name will be luaopen_b_c. + + +

    +The fourth searcher tries an all-in-one loader. +It searches the C path for a library for +the root name of the given module. +For instance, when requiring a.b.c, +it will search for a C library for a. +If found, it looks into it for an open function for +the submodule; +in our example, that would be luaopen_a_b_c. +With this facility, a package can pack several C submodules +into one single library, +with each submodule keeping its original open function. + + + + +

    +


    package.loadlib (libname, funcname)

    + + +

    +Dynamically links the host program with the C library libname. +Inside this library, looks for a function funcname +and returns this function as a C function. +(So, funcname must follow the protocol (see lua_CFunction)). + + +

    +This is a low-level function. +It completely bypasses the package and module system. +Unlike require, +it does not perform any path searching and +does not automatically adds extensions. +libname must be the complete file name of the C library, +including if necessary a path and extension. +funcname must be the exact name exported by the C library +(which may depend on the C compiler and linker used). + + +

    +This function is not supported by ANSI C. +As such, it is only available on some platforms +(Windows, Linux, Mac OS X, Solaris, BSD, +plus other Unix systems that support the dlfcn standard). + + + + +

    +


    package.path

    + + +

    +The path used by require to search for a Lua loader. + + +

    +At start-up, Lua initializes this variable with +the value of the environment variable LUA_PATH or +with a default path defined in luaconf.h, +if the environment variable is not defined. +Any ";;" in the value of the environment variable +is replaced by the default path. + + + + +

    +


    package.preload

    + + +

    +A table to store loaders for specific modules +(see require). + + + + +

    +


    package.seeall (module)

    + + +

    +Sets a metatable for module with +its __index field referring to the global environment, +so that this module inherits values +from the global environment. +To be used as an option to function module. + + + + + + + +

    5.4 - String Manipulation

    + +

    +This library provides generic functions for string manipulation, +such as finding and extracting substrings, and pattern matching. +When indexing a string in Lua, the first character is at position 1 +(not at 0, as in C). +Indices are allowed to be negative and are interpreted as indexing backwards, +from the end of the string. +Thus, the last character is at position -1, and so on. + + +

    +The string library provides all its functions inside the table +string. +It also sets a metatable for strings +where the __index field points to the string table. +Therefore, you can use the string functions in object-oriented style. +For instance, string.byte(s, i) +can be written as s:byte(i). + + +

    +The string library assumes one-byte character encodings. + + +

    +


    string.byte (s [, i [, j]])

    +Returns the internal numerical codes of the characters s[i], +s[i+1], ···, s[j]. +The default value for i is 1; +the default value for j is i. + + +

    +Note that numerical codes are not necessarily portable across platforms. + + + + +

    +


    string.char (···)

    +Receives zero or more integers. +Returns a string with length equal to the number of arguments, +in which each character has the internal numerical code equal +to its corresponding argument. + + +

    +Note that numerical codes are not necessarily portable across platforms. + + + + +

    +


    string.dump (function)

    + + +

    +Returns a string containing a binary representation of the given function, +so that a later loadstring on this string returns +a copy of the function. +function must be a Lua function without upvalues. + + + + +

    +


    string.find (s, pattern [, init [, plain]])

    +Looks for the first match of +pattern in the string s. +If it finds a match, then find returns the indices of s +where this occurrence starts and ends; +otherwise, it returns nil. +A third, optional numerical argument init specifies +where to start the search; +its default value is 1 and can be negative. +A value of true as a fourth, optional argument plain +turns off the pattern matching facilities, +so the function does a plain "find substring" operation, +with no characters in pattern being considered "magic". +Note that if plain is given, then init must be given as well. + + +

    +If the pattern has captures, +then in a successful match +the captured values are also returned, +after the two indices. + + + + +

    +


    string.format (formatstring, ···)

    +Returns a formatted version of its variable number of arguments +following the description given in its first argument (which must be a string). +The format string follows the same rules as the printf family of +standard C functions. +The only differences are that the options/modifiers +*, l, L, n, p, +and h are not supported +and that there is an extra option, q. +The q option formats a string in a form suitable to be safely read +back by the Lua interpreter: +the string is written between double quotes, +and all double quotes, newlines, embedded zeros, +and backslashes in the string +are correctly escaped when written. +For instance, the call + +
    +     string.format('%q', 'a string with "quotes" and \n new line')
    +

    +will produce the string: + +

    +     "a string with \"quotes\" and \
    +      new line"
    +
    + +

    +The options c, d, E, e, f, +g, G, i, o, u, X, and x all +expect a number as argument, +whereas q and s expect a string. + + +

    +This function does not accept string values +containing embedded zeros, +except as arguments to the q option. + + + + +

    +


    string.gmatch (s, pattern)

    +Returns an iterator function that, +each time it is called, +returns the next captures from pattern over string s. +If pattern specifies no captures, +then the whole match is produced in each call. + + +

    +As an example, the following loop + +

    +     s = "hello world from Lua"
    +     for w in string.gmatch(s, "%a+") do
    +       print(w)
    +     end
    +

    +will iterate over all the words from string s, +printing one per line. +The next example collects all pairs key=value from the +given string into a table: + +

    +     t = {}
    +     s = "from=world, to=Lua"
    +     for k, v in string.gmatch(s, "(%w+)=(%w+)") do
    +       t[k] = v
    +     end
    +
    + +

    +For this function, a '^' at the start of a pattern does not +work as an anchor, as this would prevent the iteration. + + + + +

    +


    string.gsub (s, pattern, repl [, n])

    +Returns a copy of s +in which all (or the first n, if given) +occurrences of the pattern have been +replaced by a replacement string specified by repl, +which can be a string, a table, or a function. +gsub also returns, as its second value, +the total number of matches that occurred. + + +

    +If repl is a string, then its value is used for replacement. +The character % works as an escape character: +any sequence in repl of the form %n, +with n between 1 and 9, +stands for the value of the n-th captured substring (see below). +The sequence %0 stands for the whole match. +The sequence %% stands for a single %. + + +

    +If repl is a table, then the table is queried for every match, +using the first capture as the key; +if the pattern specifies no captures, +then the whole match is used as the key. + + +

    +If repl is a function, then this function is called every time a +match occurs, with all captured substrings passed as arguments, +in order; +if the pattern specifies no captures, +then the whole match is passed as a sole argument. + + +

    +If the value returned by the table query or by the function call +is a string or a number, +then it is used as the replacement string; +otherwise, if it is false or nil, +then there is no replacement +(that is, the original match is kept in the string). + + +

    +Here are some examples: + +

    +     x = string.gsub("hello world", "(%w+)", "%1 %1")
    +     --> x="hello hello world world"
    +     
    +     x = string.gsub("hello world", "%w+", "%0 %0", 1)
    +     --> x="hello hello world"
    +     
    +     x = string.gsub("hello world from Lua", "(%w+)%s*(%w+)", "%2 %1")
    +     --> x="world hello Lua from"
    +     
    +     x = string.gsub("home = $HOME, user = $USER", "%$(%w+)", os.getenv)
    +     --> x="home = /home/roberto, user = roberto"
    +     
    +     x = string.gsub("4+5 = $return 4+5$", "%$(.-)%$", function (s)
    +           return loadstring(s)()
    +         end)
    +     --> x="4+5 = 9"
    +     
    +     local t = {name="lua", version="5.1"}
    +     x = string.gsub("$name-$version.tar.gz", "%$(%w+)", t)
    +     --> x="lua-5.1.tar.gz"
    +
    + + + +

    +


    string.len (s)

    +Receives a string and returns its length. +The empty string "" has length 0. +Embedded zeros are counted, +so "a\000bc\000" has length 5. + + + + +

    +


    string.lower (s)

    +Receives a string and returns a copy of this string with all +uppercase letters changed to lowercase. +All other characters are left unchanged. +The definition of what an uppercase letter is depends on the current locale. + + + + +

    +


    string.match (s, pattern [, init])

    +Looks for the first match of +pattern in the string s. +If it finds one, then match returns +the captures from the pattern; +otherwise it returns nil. +If pattern specifies no captures, +then the whole match is returned. +A third, optional numerical argument init specifies +where to start the search; +its default value is 1 and can be negative. + + + + +

    +


    string.rep (s, n)

    +Returns a string that is the concatenation of n copies of +the string s. + + + + +

    +


    string.reverse (s)

    +Returns a string that is the string s reversed. + + + + +

    +


    string.sub (s, i [, j])

    +Returns the substring of s that +starts at i and continues until j; +i and j can be negative. +If j is absent, then it is assumed to be equal to -1 +(which is the same as the string length). +In particular, +the call string.sub(s,1,j) returns a prefix of s +with length j, +and string.sub(s, -i) returns a suffix of s +with length i. + + + + +

    +


    string.upper (s)

    +Receives a string and returns a copy of this string with all +lowercase letters changed to uppercase. +All other characters are left unchanged. +The definition of what a lowercase letter is depends on the current locale. + + + +

    5.4.1 - Patterns

    + + +

    Character Class:

    +A character class is used to represent a set of characters. +The following combinations are allowed in describing a character class: + +

      + +
    • x: +(where x is not one of the magic characters +^$()%.[]*+-?) +represents the character x itself. +
    • + +
    • .: (a dot) represents all characters.
    • + +
    • %a: represents all letters.
    • + +
    • %c: represents all control characters.
    • + +
    • %d: represents all digits.
    • + +
    • %l: represents all lowercase letters.
    • + +
    • %p: represents all punctuation characters.
    • + +
    • %s: represents all space characters.
    • + +
    • %u: represents all uppercase letters.
    • + +
    • %w: represents all alphanumeric characters.
    • + +
    • %x: represents all hexadecimal digits.
    • + +
    • %z: represents the character with representation 0.
    • + +
    • %x: (where x is any non-alphanumeric character) +represents the character x. +This is the standard way to escape the magic characters. +Any punctuation character (even the non magic) +can be preceded by a '%' +when used to represent itself in a pattern. +
    • + +
    • [set]: +represents the class which is the union of all +characters in set. +A range of characters can be specified by +separating the end characters of the range with a '-'. +All classes %x described above can also be used as +components in set. +All other characters in set represent themselves. +For example, [%w_] (or [_%w]) +represents all alphanumeric characters plus the underscore, +[0-7] represents the octal digits, +and [0-7%l%-] represents the octal digits plus +the lowercase letters plus the '-' character. + + +

      +The interaction between ranges and classes is not defined. +Therefore, patterns like [%a-z] or [a-%%] +have no meaning. +

    • + +
    • [^set]: +represents the complement of set, +where set is interpreted as above. +
    • + +

    +For all classes represented by single letters (%a, %c, etc.), +the corresponding uppercase letter represents the complement of the class. +For instance, %S represents all non-space characters. + + +

    +The definitions of letter, space, and other character groups +depend on the current locale. +In particular, the class [a-z] may not be equivalent to %l. + + + + + +

    Pattern Item:

    +A pattern item can be + +

      + +
    • +a single character class, +which matches any single character in the class; +
    • + +
    • +a single character class followed by '*', +which matches 0 or more repetitions of characters in the class. +These repetition items will always match the longest possible sequence; +
    • + +
    • +a single character class followed by '+', +which matches 1 or more repetitions of characters in the class. +These repetition items will always match the longest possible sequence; +
    • + +
    • +a single character class followed by '-', +which also matches 0 or more repetitions of characters in the class. +Unlike '*', +these repetition items will always match the shortest possible sequence; +
    • + +
    • +a single character class followed by '?', +which matches 0 or 1 occurrence of a character in the class; +
    • + +
    • +%n, for n between 1 and 9; +such item matches a substring equal to the n-th captured string +(see below); +
    • + +
    • +%bxy, where x and y are two distinct characters; +such item matches strings that start with x, end with y, +and where the x and y are balanced. +This means that, if one reads the string from left to right, +counting +1 for an x and -1 for a y, +the ending y is the first y where the count reaches 0. +For instance, the item %b() matches expressions with +balanced parentheses. +
    • + +
    + + + + +

    Pattern:

    +A pattern is a sequence of pattern items. +A '^' at the beginning of a pattern anchors the match at the +beginning of the subject string. +A '$' at the end of a pattern anchors the match at the +end of the subject string. +At other positions, +'^' and '$' have no special meaning and represent themselves. + + + + + +

    Captures:

    +A pattern can contain sub-patterns enclosed in parentheses; +they describe captures. +When a match succeeds, the substrings of the subject string +that match captures are stored (captured) for future use. +Captures are numbered according to their left parentheses. +For instance, in the pattern "(a*(.)%w(%s*))", +the part of the string matching "a*(.)%w(%s*)" is +stored as the first capture (and therefore has number 1); +the character matching "." is captured with number 2, +and the part matching "%s*" has number 3. + + +

    +As a special case, the empty capture () captures +the current string position (a number). +For instance, if we apply the pattern "()aa()" on the +string "flaaap", there will be two captures: 3 and 5. + + +

    +A pattern cannot contain embedded zeros. Use %z instead. + + + + + + + + + + + +

    5.5 - Table Manipulation

    +This library provides generic functions for table manipulation. +It provides all its functions inside the table table. + + +

    +Most functions in the table library assume that the table +represents an array or a list. +For these functions, when we talk about the "length" of a table +we mean the result of the length operator. + + +

    +


    table.concat (table [, sep [, i [, j]]])

    +Given an array where all elements are strings or numbers, +returns table[i]..sep..table[i+1] ··· sep..table[j]. +The default value for sep is the empty string, +the default for i is 1, +and the default for j is the length of the table. +If i is greater than j, returns the empty string. + + + + +

    +


    table.insert (table, [pos,] value)

    + + +

    +Inserts element value at position pos in table, +shifting up other elements to open space, if necessary. +The default value for pos is n+1, +where n is the length of the table (see §2.5.5), +so that a call table.insert(t,x) inserts x at the end +of table t. + + + + +

    +


    table.maxn (table)

    + + +

    +Returns the largest positive numerical index of the given table, +or zero if the table has no positive numerical indices. +(To do its job this function does a linear traversal of +the whole table.) + + + + +

    +


    table.remove (table [, pos])

    + + +

    +Removes from table the element at position pos, +shifting down other elements to close the space, if necessary. +Returns the value of the removed element. +The default value for pos is n, +where n is the length of the table, +so that a call table.remove(t) removes the last element +of table t. + + + + +

    +


    table.sort (table [, comp])

    +Sorts table elements in a given order, in-place, +from table[1] to table[n], +where n is the length of the table. +If comp is given, +then it must be a function that receives two table elements, +and returns true +when the first is less than the second +(so that not comp(a[i+1],a[i]) will be true after the sort). +If comp is not given, +then the standard Lua operator < is used instead. + + +

    +The sort algorithm is not stable; +that is, elements considered equal by the given order +may have their relative positions changed by the sort. + + + + + + + +

    5.6 - Mathematical Functions

    + +

    +This library is an interface to the standard C math library. +It provides all its functions inside the table math. + + +

    +


    math.abs (x)

    + + +

    +Returns the absolute value of x. + + + + +

    +


    math.acos (x)

    + + +

    +Returns the arc cosine of x (in radians). + + + + +

    +


    math.asin (x)

    + + +

    +Returns the arc sine of x (in radians). + + + + +

    +


    math.atan (x)

    + + +

    +Returns the arc tangent of x (in radians). + + + + +

    +


    math.atan2 (y, x)

    + + +

    +Returns the arc tangent of y/x (in radians), +but uses the signs of both parameters to find the +quadrant of the result. +(It also handles correctly the case of x being zero.) + + + + +

    +


    math.ceil (x)

    + + +

    +Returns the smallest integer larger than or equal to x. + + + + +

    +


    math.cos (x)

    + + +

    +Returns the cosine of x (assumed to be in radians). + + + + +

    +


    math.cosh (x)

    + + +

    +Returns the hyperbolic cosine of x. + + + + +

    +


    math.deg (x)

    + + +

    +Returns the angle x (given in radians) in degrees. + + + + +

    +


    math.exp (x)

    + + +

    +Returns the value ex. + + + + +

    +


    math.floor (x)

    + + +

    +Returns the largest integer smaller than or equal to x. + + + + +

    +


    math.fmod (x, y)

    + + +

    +Returns the remainder of the division of x by y +that rounds the quotient towards zero. + + + + +

    +


    math.frexp (x)

    + + +

    +Returns m and e such that x = m2e, +e is an integer and the absolute value of m is +in the range [0.5, 1) +(or zero when x is zero). + + + + +

    +


    math.huge

    + + +

    +The value HUGE_VAL, +a value larger than or equal to any other numerical value. + + + + +

    +


    math.ldexp (m, e)

    + + +

    +Returns m2e (e should be an integer). + + + + +

    +


    math.log (x)

    + + +

    +Returns the natural logarithm of x. + + + + +

    +


    math.log10 (x)

    + + +

    +Returns the base-10 logarithm of x. + + + + +

    +


    math.max (x, ···)

    + + +

    +Returns the maximum value among its arguments. + + + + +

    +


    math.min (x, ···)

    + + +

    +Returns the minimum value among its arguments. + + + + +

    +


    math.modf (x)

    + + +

    +Returns two numbers, +the integral part of x and the fractional part of x. + + + + +

    +


    math.pi

    + + +

    +The value of pi. + + + + +

    +


    math.pow (x, y)

    + + +

    +Returns xy. +(You can also use the expression x^y to compute this value.) + + + + +

    +


    math.rad (x)

    + + +

    +Returns the angle x (given in degrees) in radians. + + + + +

    +


    math.random ([m [, n]])

    + + +

    +This function is an interface to the simple +pseudo-random generator function rand provided by ANSI C. +(No guarantees can be given for its statistical properties.) + + +

    +When called without arguments, +returns a uniform pseudo-random real number +in the range [0,1). +When called with an integer number m, +math.random returns +a uniform pseudo-random integer in the range [1, m]. +When called with two integer numbers m and n, +math.random returns a uniform pseudo-random +integer in the range [m, n]. + + + + +

    +


    math.randomseed (x)

    + + +

    +Sets x as the "seed" +for the pseudo-random generator: +equal seeds produce equal sequences of numbers. + + + + +

    +


    math.sin (x)

    + + +

    +Returns the sine of x (assumed to be in radians). + + + + +

    +


    math.sinh (x)

    + + +

    +Returns the hyperbolic sine of x. + + + + +

    +


    math.sqrt (x)

    + + +

    +Returns the square root of x. +(You can also use the expression x^0.5 to compute this value.) + + + + +

    +


    math.tan (x)

    + + +

    +Returns the tangent of x (assumed to be in radians). + + + + +

    +


    math.tanh (x)

    + + +

    +Returns the hyperbolic tangent of x. + + + + + + + +

    5.7 - Input and Output Facilities

    + +

    +The I/O library provides two different styles for file manipulation. +The first one uses implicit file descriptors; +that is, there are operations to set a default input file and a +default output file, +and all input/output operations are over these default files. +The second style uses explicit file descriptors. + + +

    +When using implicit file descriptors, +all operations are supplied by table io. +When using explicit file descriptors, +the operation io.open returns a file descriptor +and then all operations are supplied as methods of the file descriptor. + + +

    +The table io also provides +three predefined file descriptors with their usual meanings from C: +io.stdin, io.stdout, and io.stderr. +The I/O library never closes these files. + + +

    +Unless otherwise stated, +all I/O functions return nil on failure +(plus an error message as a second result and +a system-dependent error code as a third result) +and some value different from nil on success. + + +

    +


    io.close ([file])

    + + +

    +Equivalent to file:close(). +Without a file, closes the default output file. + + + + +

    +


    io.flush ()

    + + +

    +Equivalent to file:flush over the default output file. + + + + +

    +


    io.input ([file])

    + + +

    +When called with a file name, it opens the named file (in text mode), +and sets its handle as the default input file. +When called with a file handle, +it simply sets this file handle as the default input file. +When called without parameters, +it returns the current default input file. + + +

    +In case of errors this function raises the error, +instead of returning an error code. + + + + +

    +


    io.lines ([filename])

    + + +

    +Opens the given file name in read mode +and returns an iterator function that, +each time it is called, +returns a new line from the file. +Therefore, the construction + +

    +     for line in io.lines(filename) do body end
    +

    +will iterate over all lines of the file. +When the iterator function detects the end of file, +it returns nil (to finish the loop) and automatically closes the file. + + +

    +The call io.lines() (with no file name) is equivalent +to io.input():lines(); +that is, it iterates over the lines of the default input file. +In this case it does not close the file when the loop ends. + + + + +

    +


    io.open (filename [, mode])

    + + +

    +This function opens a file, +in the mode specified in the string mode. +It returns a new file handle, +or, in case of errors, nil plus an error message. + + +

    +The mode string can be any of the following: + +

      +
    • "r": read mode (the default);
    • +
    • "w": write mode;
    • +
    • "a": append mode;
    • +
    • "r+": update mode, all previous data is preserved;
    • +
    • "w+": update mode, all previous data is erased;
    • +
    • "a+": append update mode, previous data is preserved, + writing is only allowed at the end of file.
    • +

    +The mode string can also have a 'b' at the end, +which is needed in some systems to open the file in binary mode. +This string is exactly what is used in the +standard C function fopen. + + + + +

    +


    io.output ([file])

    + + +

    +Similar to io.input, but operates over the default output file. + + + + +

    +


    io.popen (prog [, mode])

    + + +

    +Starts program prog in a separated process and returns +a file handle that you can use to read data from this program +(if mode is "r", the default) +or to write data to this program +(if mode is "w"). + + +

    +This function is system dependent and is not available +on all platforms. + + + + +

    +


    io.read (···)

    + + +

    +Equivalent to io.input():read. + + + + +

    +


    io.tmpfile ()

    + + +

    +Returns a handle for a temporary file. +This file is opened in update mode +and it is automatically removed when the program ends. + + + + +

    +


    io.type (obj)

    + + +

    +Checks whether obj is a valid file handle. +Returns the string "file" if obj is an open file handle, +"closed file" if obj is a closed file handle, +or nil if obj is not a file handle. + + + + +

    +


    io.write (···)

    + + +

    +Equivalent to io.output():write. + + + + +

    +


    file:close ()

    + + +

    +Closes file. +Note that files are automatically closed when +their handles are garbage collected, +but that takes an unpredictable amount of time to happen. + + + + +

    +


    file:flush ()

    + + +

    +Saves any written data to file. + + + + +

    +


    file:lines ()

    + + +

    +Returns an iterator function that, +each time it is called, +returns a new line from the file. +Therefore, the construction + +

    +     for line in file:lines() do body end
    +

    +will iterate over all lines of the file. +(Unlike io.lines, this function does not close the file +when the loop ends.) + + + + +

    +


    file:read (···)

    + + +

    +Reads the file file, +according to the given formats, which specify what to read. +For each format, +the function returns a string (or a number) with the characters read, +or nil if it cannot read data with the specified format. +When called without formats, +it uses a default format that reads the entire next line +(see below). + + +

    +The available formats are + +

      + +
    • "*n": +reads a number; +this is the only format that returns a number instead of a string. +
    • + +
    • "*a": +reads the whole file, starting at the current position. +On end of file, it returns the empty string. +
    • + +
    • "*l": +reads the next line (skipping the end of line), +returning nil on end of file. +This is the default format. +
    • + +
    • number: +reads a string with up to this number of characters, +returning nil on end of file. +If number is zero, +it reads nothing and returns an empty string, +or nil on end of file. +
    • + +
    + + + +

    +


    file:seek ([whence] [, offset])

    + + +

    +Sets and gets the file position, +measured from the beginning of the file, +to the position given by offset plus a base +specified by the string whence, as follows: + +

      +
    • "set": base is position 0 (beginning of the file);
    • +
    • "cur": base is current position;
    • +
    • "end": base is end of file;
    • +

    +In case of success, function seek returns the final file position, +measured in bytes from the beginning of the file. +If this function fails, it returns nil, +plus a string describing the error. + + +

    +The default value for whence is "cur", +and for offset is 0. +Therefore, the call file:seek() returns the current +file position, without changing it; +the call file:seek("set") sets the position to the +beginning of the file (and returns 0); +and the call file:seek("end") sets the position to the +end of the file, and returns its size. + + + + +

    +


    file:setvbuf (mode [, size])

    + + +

    +Sets the buffering mode for an output file. +There are three available modes: + +

      + +
    • "no": +no buffering; the result of any output operation appears immediately. +
    • + +
    • "full": +full buffering; output operation is performed only +when the buffer is full (or when you explicitly flush the file +(see io.flush)). +
    • + +
    • "line": +line buffering; output is buffered until a newline is output +or there is any input from some special files +(such as a terminal device). +
    • + +

    +For the last two cases, size +specifies the size of the buffer, in bytes. +The default is an appropriate size. + + + + +

    +


    file:write (···)

    + + +

    +Writes the value of each of its arguments to +the file. +The arguments must be strings or numbers. +To write other values, +use tostring or string.format before write. + + + + + + + +

    5.8 - Operating System Facilities

    + +

    +This library is implemented through table os. + + +

    +


    os.clock ()

    + + +

    +Returns an approximation of the amount in seconds of CPU time +used by the program. + + + + +

    +


    os.date ([format [, time]])

    + + +

    +Returns a string or a table containing date and time, +formatted according to the given string format. + + +

    +If the time argument is present, +this is the time to be formatted +(see the os.time function for a description of this value). +Otherwise, date formats the current time. + + +

    +If format starts with '!', +then the date is formatted in Coordinated Universal Time. +After this optional character, +if format is the string "*t", +then date returns a table with the following fields: +year (four digits), month (1--12), day (1--31), +hour (0--23), min (0--59), sec (0--61), +wday (weekday, Sunday is 1), +yday (day of the year), +and isdst (daylight saving flag, a boolean). + + +

    +If format is not "*t", +then date returns the date as a string, +formatted according to the same rules as the C function strftime. + + +

    +When called without arguments, +date returns a reasonable date and time representation that depends on +the host system and on the current locale +(that is, os.date() is equivalent to os.date("%c")). + + + + +

    +


    os.difftime (t2, t1)

    + + +

    +Returns the number of seconds from time t1 to time t2. +In POSIX, Windows, and some other systems, +this value is exactly t2-t1. + + + + +

    +


    os.execute ([command])

    + + +

    +This function is equivalent to the C function system. +It passes command to be executed by an operating system shell. +It returns a status code, which is system-dependent. +If command is absent, then it returns nonzero if a shell is available +and zero otherwise. + + + + +

    +


    os.exit ([code])

    + + +

    +Calls the C function exit, +with an optional code, +to terminate the host program. +The default value for code is the success code. + + + + +

    +


    os.getenv (varname)

    + + +

    +Returns the value of the process environment variable varname, +or nil if the variable is not defined. + + + + +

    +


    os.remove (filename)

    + + +

    +Deletes the file or directory with the given name. +Directories must be empty to be removed. +If this function fails, it returns nil, +plus a string describing the error. + + + + +

    +


    os.rename (oldname, newname)

    + + +

    +Renames file or directory named oldname to newname. +If this function fails, it returns nil, +plus a string describing the error. + + + + +

    +


    os.setlocale (locale [, category])

    + + +

    +Sets the current locale of the program. +locale is a string specifying a locale; +category is an optional string describing which category to change: +"all", "collate", "ctype", +"monetary", "numeric", or "time"; +the default category is "all". +The function returns the name of the new locale, +or nil if the request cannot be honored. + + +

    +If locale is the empty string, +the current locale is set to an implementation-defined native locale. +If locale is the string "C", +the current locale is set to the standard C locale. + + +

    +When called with nil as the first argument, +this function only returns the name of the current locale +for the given category. + + + + +

    +


    os.time ([table])

    + + +

    +Returns the current time when called without arguments, +or a time representing the date and time specified by the given table. +This table must have fields year, month, and day, +and may have fields hour, min, sec, and isdst +(for a description of these fields, see the os.date function). + + +

    +The returned value is a number, whose meaning depends on your system. +In POSIX, Windows, and some other systems, this number counts the number +of seconds since some given start time (the "epoch"). +In other systems, the meaning is not specified, +and the number returned by time can be used only as an argument to +date and difftime. + + + + +

    +


    os.tmpname ()

    + + +

    +Returns a string with a file name that can +be used for a temporary file. +The file must be explicitly opened before its use +and explicitly removed when no longer needed. + + +

    +On some systems (POSIX), +this function also creates a file with that name, +to avoid security risks. +(Someone else might create the file with wrong permissions +in the time between getting the name and creating the file.) +You still have to open the file to use it +and to remove it (even if you do not use it). + + +

    +When possible, +you may prefer to use io.tmpfile, +which automatically removes the file when the program ends. + + + + + + + +

    5.9 - The Debug Library

    + +

    +This library provides +the functionality of the debug interface to Lua programs. +You should exert care when using this library. +The functions provided here should be used exclusively for debugging +and similar tasks, such as profiling. +Please resist the temptation to use them as a +usual programming tool: +they can be very slow. +Moreover, several of these functions +violate some assumptions about Lua code +(e.g., that variables local to a function +cannot be accessed from outside or +that userdata metatables cannot be changed by Lua code) +and therefore can compromise otherwise secure code. + + +

    +All functions in this library are provided +inside the debug table. +All functions that operate over a thread +have an optional first argument which is the +thread to operate over. +The default is always the current thread. + + +

    +


    debug.debug ()

    + + +

    +Enters an interactive mode with the user, +running each string that the user enters. +Using simple commands and other debug facilities, +the user can inspect global and local variables, +change their values, evaluate expressions, and so on. +A line containing only the word cont finishes this function, +so that the caller continues its execution. + + +

    +Note that commands for debug.debug are not lexically nested +within any function, and so have no direct access to local variables. + + + + +

    +


    debug.getfenv (o)

    +Returns the environment of object o. + + + + +

    +


    debug.gethook ([thread])

    + + +

    +Returns the current hook settings of the thread, as three values: +the current hook function, the current hook mask, +and the current hook count +(as set by the debug.sethook function). + + + + +

    +


    debug.getinfo ([thread,] function [, what])

    + + +

    +Returns a table with information about a function. +You can give the function directly, +or you can give a number as the value of function, +which means the function running at level function of the call stack +of the given thread: +level 0 is the current function (getinfo itself); +level 1 is the function that called getinfo; +and so on. +If function is a number larger than the number of active functions, +then getinfo returns nil. + + +

    +The returned table can contain all the fields returned by lua_getinfo, +with the string what describing which fields to fill in. +The default for what is to get all information available, +except the table of valid lines. +If present, +the option 'f' +adds a field named func with the function itself. +If present, +the option 'L' +adds a field named activelines with the table of +valid lines. + + +

    +For instance, the expression debug.getinfo(1,"n").name returns +a table with a name for the current function, +if a reasonable name can be found, +and the expression debug.getinfo(print) +returns a table with all available information +about the print function. + + + + +

    +


    debug.getlocal ([thread,] level, local)

    + + +

    +This function returns the name and the value of the local variable +with index local of the function at level level of the stack. +(The first parameter or local variable has index 1, and so on, +until the last active local variable.) +The function returns nil if there is no local +variable with the given index, +and raises an error when called with a level out of range. +(You can call debug.getinfo to check whether the level is valid.) + + +

    +Variable names starting with '(' (open parentheses) +represent internal variables +(loop control variables, temporaries, and C function locals). + + + + +

    +


    debug.getmetatable (object)

    + + +

    +Returns the metatable of the given object +or nil if it does not have a metatable. + + + + +

    +


    debug.getregistry ()

    + + +

    +Returns the registry table (see §3.5). + + + + +

    +


    debug.getupvalue (func, up)

    + + +

    +This function returns the name and the value of the upvalue +with index up of the function func. +The function returns nil if there is no upvalue with the given index. + + + + +

    +


    debug.setfenv (object, table)

    + + +

    +Sets the environment of the given object to the given table. +Returns object. + + + + +

    +


    debug.sethook ([thread,] hook, mask [, count])

    + + +

    +Sets the given function as a hook. +The string mask and the number count describe +when the hook will be called. +The string mask may have the following characters, +with the given meaning: + +

      +
    • "c": the hook is called every time Lua calls a function;
    • +
    • "r": the hook is called every time Lua returns from a function;
    • +
    • "l": the hook is called every time Lua enters a new line of code.
    • +

    +With a count different from zero, +the hook is called after every count instructions. + + +

    +When called without arguments, +debug.sethook turns off the hook. + + +

    +When the hook is called, its first parameter is a string +describing the event that has triggered its call: +"call", "return" (or "tail return", +when simulating a return from a tail call), +"line", and "count". +For line events, +the hook also gets the new line number as its second parameter. +Inside a hook, +you can call getinfo with level 2 to get more information about +the running function +(level 0 is the getinfo function, +and level 1 is the hook function), +unless the event is "tail return". +In this case, Lua is only simulating the return, +and a call to getinfo will return invalid data. + + + + +

    +


    debug.setlocal ([thread,] level, local, value)

    + + +

    +This function assigns the value value to the local variable +with index local of the function at level level of the stack. +The function returns nil if there is no local +variable with the given index, +and raises an error when called with a level out of range. +(You can call getinfo to check whether the level is valid.) +Otherwise, it returns the name of the local variable. + + + + +

    +


    debug.setmetatable (object, table)

    + + +

    +Sets the metatable for the given object to the given table +(which can be nil). + + + + +

    +


    debug.setupvalue (func, up, value)

    + + +

    +This function assigns the value value to the upvalue +with index up of the function func. +The function returns nil if there is no upvalue +with the given index. +Otherwise, it returns the name of the upvalue. + + + + +

    +


    debug.traceback ([thread,] [message [, level]])

    + + +

    +Returns a string with a traceback of the call stack. +An optional message string is appended +at the beginning of the traceback. +An optional level number tells at which level +to start the traceback +(default is 1, the function calling traceback). + + + + + + + +

    6 - Lua Stand-alone

    + +

    +Although Lua has been designed as an extension language, +to be embedded in a host C program, +it is also frequently used as a stand-alone language. +An interpreter for Lua as a stand-alone language, +called simply lua, +is provided with the standard distribution. +The stand-alone interpreter includes +all standard libraries, including the debug library. +Its usage is: + +

    +     lua [options] [script [args]]
    +

    +The options are: + +

      +
    • -e stat: executes string stat;
    • +
    • -l mod: "requires" mod;
    • +
    • -i: enters interactive mode after running script;
    • +
    • -v: prints version information;
    • +
    • --: stops handling options;
    • +
    • -: executes stdin as a file and stops handling options.
    • +

    +After handling its options, lua runs the given script, +passing to it the given args as string arguments. +When called without arguments, +lua behaves as lua -v -i +when the standard input (stdin) is a terminal, +and as lua - otherwise. + + +

    +Before running any argument, +the interpreter checks for an environment variable LUA_INIT. +If its format is @filename, +then lua executes the file. +Otherwise, lua executes the string itself. + + +

    +All options are handled in order, except -i. +For instance, an invocation like + +

    +     $ lua -e'a=1' -e 'print(a)' script.lua
    +

    +will first set a to 1, then print the value of a (which is '1'), +and finally run the file script.lua with no arguments. +(Here $ is the shell prompt. Your prompt may be different.) + + +

    +Before starting to run the script, +lua collects all arguments in the command line +in a global table called arg. +The script name is stored at index 0, +the first argument after the script name goes to index 1, +and so on. +Any arguments before the script name +(that is, the interpreter name plus the options) +go to negative indices. +For instance, in the call + +

    +     $ lua -la b.lua t1 t2
    +

    +the interpreter first runs the file a.lua, +then creates a table + +

    +     arg = { [-2] = "lua", [-1] = "-la",
    +             [0] = "b.lua",
    +             [1] = "t1", [2] = "t2" }
    +

    +and finally runs the file b.lua. +The script is called with arg[1], arg[2], ··· +as arguments; +it can also access these arguments with the vararg expression '...'. + + +

    +In interactive mode, +if you write an incomplete statement, +the interpreter waits for its completion +by issuing a different prompt. + + +

    +If the global variable _PROMPT contains a string, +then its value is used as the prompt. +Similarly, if the global variable _PROMPT2 contains a string, +its value is used as the secondary prompt +(issued during incomplete statements). +Therefore, both prompts can be changed directly on the command line +or in any Lua programs by assigning to _PROMPT. +See the next example: + +

    +     $ lua -e"_PROMPT='myprompt> '" -i
    +

    +(The outer pair of quotes is for the shell, +the inner pair is for Lua.) +Note the use of -i to enter interactive mode; +otherwise, +the program would just end silently +right after the assignment to _PROMPT. + + +

    +To allow the use of Lua as a +script interpreter in Unix systems, +the stand-alone interpreter skips +the first line of a chunk if it starts with #. +Therefore, Lua scripts can be made into executable programs +by using chmod +x and the #! form, +as in + +

    +     #!/usr/local/bin/lua
    +

    +(Of course, +the location of the Lua interpreter may be different in your machine. +If lua is in your PATH, +then + +

    +     #!/usr/bin/env lua
    +

    +is a more portable solution.) + + + +

    7 - Incompatibilities with the Previous Version

    + +

    +Here we list the incompatibilities that you may find when moving a program +from Lua 5.0 to Lua 5.1. +You can avoid most of the incompatibilities compiling Lua with +appropriate options (see file luaconf.h). +However, +all these compatibility options will be removed in the next version of Lua. + + + +

    7.1 - Changes in the Language

    +
      + +
    • +The vararg system changed from the pseudo-argument arg with a +table with the extra arguments to the vararg expression. +(See compile-time option LUA_COMPAT_VARARG in luaconf.h.) +
    • + +
    • +There was a subtle change in the scope of the implicit +variables of the for statement and for the repeat statement. +
    • + +
    • +The long string/long comment syntax ([[string]]) +does not allow nesting. +You can use the new syntax ([=[string]=]) in these cases. +(See compile-time option LUA_COMPAT_LSTR in luaconf.h.) +
    • + +
    + + + + +

    7.2 - Changes in the Libraries

    +
      + +
    • +Function string.gfind was renamed string.gmatch. +(See compile-time option LUA_COMPAT_GFIND in luaconf.h.) +
    • + +
    • +When string.gsub is called with a function as its +third argument, +whenever this function returns nil or false the +replacement string is the whole match, +instead of the empty string. +
    • + +
    • +Function table.setn was deprecated. +Function table.getn corresponds +to the new length operator (#); +use the operator instead of the function. +(See compile-time option LUA_COMPAT_GETN in luaconf.h.) +
    • + +
    • +Function loadlib was renamed package.loadlib. +(See compile-time option LUA_COMPAT_LOADLIB in luaconf.h.) +
    • + +
    • +Function math.mod was renamed math.fmod. +(See compile-time option LUA_COMPAT_MOD in luaconf.h.) +
    • + +
    • +Functions table.foreach and table.foreachi are deprecated. +You can use a for loop with pairs or ipairs instead. +
    • + +
    • +There were substantial changes in function require due to +the new module system. +However, the new behavior is mostly compatible with the old, +but require gets the path from package.path instead +of from LUA_PATH. +
    • + +
    • +Function collectgarbage has different arguments. +Function gcinfo is deprecated; +use collectgarbage("count") instead. +
    • + +
    + + + + +

    7.3 - Changes in the API

    +
      + +
    • +The luaopen_* functions (to open libraries) +cannot be called directly, +like a regular C function. +They must be called through Lua, +like a Lua function. +
    • + +
    • +Function lua_open was replaced by lua_newstate to +allow the user to set a memory-allocation function. +You can use luaL_newstate from the standard library to +create a state with a standard allocation function +(based on realloc). +
    • + +
    • +Functions luaL_getn and luaL_setn +(from the auxiliary library) are deprecated. +Use lua_objlen instead of luaL_getn +and nothing instead of luaL_setn. +
    • + +
    • +Function luaL_openlib was replaced by luaL_register. +
    • + +
    • +Function luaL_checkudata now throws an error when the given value +is not a userdata of the expected type. +(In Lua 5.0 it returned NULL.) +
    • + +
    + + + + +

    8 - The Complete Syntax of Lua

    + +

    +Here is the complete syntax of Lua in extended BNF. +(It does not describe operator precedences.) + + + + +

    +
    +	chunk ::= {stat [`;´]} [laststat [`;´]]
    +
    +	block ::= chunk
    +
    +	stat ::=  varlist `=´ explist | 
    +		 functioncall | 
    +		 do block end | 
    +		 while exp do block end | 
    +		 repeat block until exp | 
    +		 if exp then block {elseif exp then block} [else block] end | 
    +		 for Name `=´ exp `,´ exp [`,´ exp] do block end | 
    +		 for namelist in explist do block end | 
    +		 function funcname funcbody | 
    +		 local function Name funcbody | 
    +		 local namelist [`=´ explist] 
    +
    +	laststat ::= return [explist] | break
    +
    +	funcname ::= Name {`.´ Name} [`:´ Name]
    +
    +	varlist ::= var {`,´ var}
    +
    +	var ::=  Name | prefixexp `[´ exp `]´ | prefixexp `.´ Name 
    +
    +	namelist ::= Name {`,´ Name}
    +
    +	explist ::= {exp `,´} exp
    +
    +	exp ::=  nil | false | true | Number | String | `...´ | function | 
    +		 prefixexp | tableconstructor | exp binop exp | unop exp 
    +
    +	prefixexp ::= var | functioncall | `(´ exp `)´
    +
    +	functioncall ::=  prefixexp args | prefixexp `:´ Name args 
    +
    +	args ::=  `(´ [explist] `)´ | tableconstructor | String 
    +
    +	function ::= function funcbody
    +
    +	funcbody ::= `(´ [parlist] `)´ block end
    +
    +	parlist ::= namelist [`,´ `...´] | `...´
    +
    +	tableconstructor ::= `{´ [fieldlist] `}´
    +
    +	fieldlist ::= field {fieldsep field} [fieldsep]
    +
    +	field ::= `[´ exp `]´ `=´ exp | Name `=´ exp | exp
    +
    +	fieldsep ::= `,´ | `;´
    +
    +	binop ::= `+´ | `-´ | `*´ | `/´ | `^´ | `%´ | `..´ | 
    +		 `<´ | `<=´ | `>´ | `>=´ | `==´ | `~=´ | 
    +		 and | or
    +
    +	unop ::= `-´ | not | `#´
    +
    +
    + +

    + + + + + + + +


    + +Last update: +Mon Feb 13 18:54:19 BRST 2012 + + + + + diff --git a/external/mit/lua/dist/doc/readme.html b/external/mit/lua/dist/doc/readme.html new file mode 100644 index 000000000..3ed6a8189 --- /dev/null +++ b/external/mit/lua/dist/doc/readme.html @@ -0,0 +1,40 @@ + + +Lua documentation + + + + + +
    +

    +Lua +Documentation +

    + +This is the documentation included in the source distribution of Lua 5.1.5. + + + +Lua's +official web site +contains updated documentation, +especially the +reference manual. +

    + +


    + +Last update: +Fri Feb 3 09:44:42 BRST 2012 + + + + diff --git a/external/mit/lua/dist/etc/Makefile b/external/mit/lua/dist/etc/Makefile new file mode 100644 index 000000000..6d00008d9 --- /dev/null +++ b/external/mit/lua/dist/etc/Makefile @@ -0,0 +1,44 @@ +# makefile for Lua etc + +TOP= .. +LIB= $(TOP)/src +INC= $(TOP)/src +BIN= $(TOP)/src +SRC= $(TOP)/src +TST= $(TOP)/test + +CC= gcc +CFLAGS= -O2 -Wall -I$(INC) $(MYCFLAGS) +MYCFLAGS= +MYLDFLAGS= -Wl,-E +MYLIBS= -lm +#MYLIBS= -lm -Wl,-E -ldl -lreadline -lhistory -lncurses +RM= rm -f + +default: + @echo 'Please choose a target: min noparser one strict clean' + +min: min.c + $(CC) $(CFLAGS) $@.c -L$(LIB) -llua $(MYLIBS) + echo 'print"Hello there!"' | ./a.out + +noparser: noparser.o + $(CC) noparser.o $(SRC)/lua.o -L$(LIB) -llua $(MYLIBS) + $(BIN)/luac $(TST)/hello.lua + -./a.out luac.out + -./a.out -e'a=1' + +one: + $(CC) $(CFLAGS) all.c $(MYLIBS) + ./a.out $(TST)/hello.lua + +strict: + -$(BIN)/lua -e 'print(a);b=2' + -$(BIN)/lua -lstrict -e 'print(a)' + -$(BIN)/lua -e 'function f() b=2 end f()' + -$(BIN)/lua -lstrict -e 'function f() b=2 end f()' + +clean: + $(RM) a.out core core.* *.o luac.out + +.PHONY: default min noparser one strict clean diff --git a/external/mit/lua/dist/etc/README b/external/mit/lua/dist/etc/README new file mode 100644 index 000000000..5149fc91d --- /dev/null +++ b/external/mit/lua/dist/etc/README @@ -0,0 +1,37 @@ +This directory contains some useful files and code. +Unlike the code in ../src, everything here is in the public domain. + +If any of the makes fail, you're probably not using the same libraries +used to build Lua. Set MYLIBS in Makefile accordingly. + +all.c + Full Lua interpreter in a single file. + Do "make one" for a demo. + +lua.hpp + Lua header files for C++ using 'extern "C"'. + +lua.ico + A Lua icon for Windows (and web sites: save as favicon.ico). + Drawn by hand by Markus Gritsch . + +lua.pc + pkg-config data for Lua + +luavs.bat + Script to build Lua under "Visual Studio .NET Command Prompt". + Run it from the toplevel as etc\luavs.bat. + +min.c + A minimal Lua interpreter. + Good for learning and for starting your own. + Do "make min" for a demo. + +noparser.c + Linking with noparser.o avoids loading the parsing modules in lualib.a. + Do "make noparser" for a demo. + +strict.lua + Traps uses of undeclared global variables. + Do "make strict" for a demo. + diff --git a/external/mit/lua/dist/etc/all.c b/external/mit/lua/dist/etc/all.c new file mode 100644 index 000000000..c853dbc32 --- /dev/null +++ b/external/mit/lua/dist/etc/all.c @@ -0,0 +1,40 @@ +/* $NetBSD: all.c,v 1.1.1.2 2012/03/15 00:08:14 alnsn Exp $ */ + +/* +* all.c -- Lua core, libraries and interpreter in a single file +*/ + +#define luaall_c + +#include "lapi.c" +#include "lcode.c" +#include "ldebug.c" +#include "ldo.c" +#include "ldump.c" +#include "lfunc.c" +#include "lgc.c" +#include "llex.c" +#include "lmem.c" +#include "lobject.c" +#include "lopcodes.c" +#include "lparser.c" +#include "lstate.c" +#include "lstring.c" +#include "ltable.c" +#include "ltm.c" +#include "lundump.c" +#include "lvm.c" +#include "lzio.c" + +#include "lauxlib.c" +#include "lbaselib.c" +#include "ldblib.c" +#include "liolib.c" +#include "linit.c" +#include "lmathlib.c" +#include "loadlib.c" +#include "loslib.c" +#include "lstrlib.c" +#include "ltablib.c" + +#include "lua.c" diff --git a/external/mit/lua/dist/etc/lua.hpp b/external/mit/lua/dist/etc/lua.hpp new file mode 100644 index 000000000..ec417f594 --- /dev/null +++ b/external/mit/lua/dist/etc/lua.hpp @@ -0,0 +1,9 @@ +// lua.hpp +// Lua header files for C++ +// <> not supplied automatically because Lua also compiles as C++ + +extern "C" { +#include "lua.h" +#include "lualib.h" +#include "lauxlib.h" +} diff --git a/external/mit/lua/dist/etc/lua.ico b/external/mit/lua/dist/etc/lua.ico new file mode 100644 index 000000000..ccbabc4e2 Binary files /dev/null and b/external/mit/lua/dist/etc/lua.ico differ diff --git a/external/mit/lua/dist/etc/lua.pc b/external/mit/lua/dist/etc/lua.pc new file mode 100644 index 000000000..07e2852b0 --- /dev/null +++ b/external/mit/lua/dist/etc/lua.pc @@ -0,0 +1,31 @@ +# lua.pc -- pkg-config data for Lua + +# vars from install Makefile + +# grep '^V=' ../Makefile +V= 5.1 +# grep '^R=' ../Makefile +R= 5.1.5 + +# grep '^INSTALL_.*=' ../Makefile | sed 's/INSTALL_TOP/prefix/' +prefix= /usr/local +INSTALL_BIN= ${prefix}/bin +INSTALL_INC= ${prefix}/include +INSTALL_LIB= ${prefix}/lib +INSTALL_MAN= ${prefix}/man/man1 +INSTALL_LMOD= ${prefix}/share/lua/${V} +INSTALL_CMOD= ${prefix}/lib/lua/${V} + +# canonical vars +exec_prefix=${prefix} +libdir=${exec_prefix}/lib +includedir=${prefix}/include + +Name: Lua +Description: An Extensible Extension Language +Version: ${R} +Requires: +Libs: -L${libdir} -llua -lm +Cflags: -I${includedir} + +# (end of lua.pc) diff --git a/external/mit/lua/dist/etc/luavs.bat b/external/mit/lua/dist/etc/luavs.bat new file mode 100644 index 000000000..08c2beddf --- /dev/null +++ b/external/mit/lua/dist/etc/luavs.bat @@ -0,0 +1,28 @@ +@rem Script to build Lua under "Visual Studio .NET Command Prompt". +@rem Do not run from this directory; run it from the toplevel: etc\luavs.bat . +@rem It creates lua51.dll, lua51.lib, lua.exe, and luac.exe in src. +@rem (contributed by David Manura and Mike Pall) + +@setlocal +@set MYCOMPILE=cl /nologo /MD /O2 /W3 /c /D_CRT_SECURE_NO_DEPRECATE +@set MYLINK=link /nologo +@set MYMT=mt /nologo + +cd src +%MYCOMPILE% /DLUA_BUILD_AS_DLL l*.c +del lua.obj luac.obj +%MYLINK% /DLL /out:lua51.dll l*.obj +if exist lua51.dll.manifest^ + %MYMT% -manifest lua51.dll.manifest -outputresource:lua51.dll;2 +%MYCOMPILE% /DLUA_BUILD_AS_DLL lua.c +%MYLINK% /out:lua.exe lua.obj lua51.lib +if exist lua.exe.manifest^ + %MYMT% -manifest lua.exe.manifest -outputresource:lua.exe +%MYCOMPILE% l*.c print.c +del lua.obj linit.obj lbaselib.obj ldblib.obj liolib.obj lmathlib.obj^ + loslib.obj ltablib.obj lstrlib.obj loadlib.obj +%MYLINK% /out:luac.exe *.obj +if exist luac.exe.manifest^ + %MYMT% -manifest luac.exe.manifest -outputresource:luac.exe +del *.obj *.manifest +cd .. diff --git a/external/mit/lua/dist/etc/min.c b/external/mit/lua/dist/etc/min.c new file mode 100644 index 000000000..99f6dde5c --- /dev/null +++ b/external/mit/lua/dist/etc/min.c @@ -0,0 +1,41 @@ +/* $NetBSD: min.c,v 1.1.1.2 2012/03/15 00:08:14 alnsn Exp $ */ + +/* +* min.c -- a minimal Lua interpreter +* loads stdin only with minimal error handling. +* no interaction, and no standard library, only a "print" function. +*/ + +#include + +#include "lua.h" +#include "lauxlib.h" + +static int print(lua_State *L) +{ + int n=lua_gettop(L); + int i; + for (i=1; i<=n; i++) + { + if (i>1) printf("\t"); + if (lua_isstring(L,i)) + printf("%s",lua_tostring(L,i)); + else if (lua_isnil(L,i)) + printf("%s","nil"); + else if (lua_isboolean(L,i)) + printf("%s",lua_toboolean(L,i) ? "true" : "false"); + else + printf("%s:%p",luaL_typename(L,i),lua_topointer(L,i)); + } + printf("\n"); + return 0; +} + +int main(void) +{ + lua_State *L=lua_open(); + lua_register(L,"print",print); + if (luaL_dofile(L,NULL)!=0) fprintf(stderr,"%s\n",lua_tostring(L,-1)); + lua_close(L); + return 0; +} diff --git a/external/mit/lua/dist/etc/noparser.c b/external/mit/lua/dist/etc/noparser.c new file mode 100644 index 000000000..75f2f4fc0 --- /dev/null +++ b/external/mit/lua/dist/etc/noparser.c @@ -0,0 +1,52 @@ +/* $NetBSD: noparser.c,v 1.1.1.2 2012/03/15 00:08:14 alnsn Exp $ */ + +/* +* The code below can be used to make a Lua core that does not contain the +* parsing modules (lcode, llex, lparser), which represent 35% of the total core. +* You'll only be able to load binary files and strings, precompiled with luac. +* (Of course, you'll have to build luac with the original parsing modules!) +* +* To use this module, simply compile it ("make noparser" does that) and list +* its object file before the Lua libraries. The linker should then not load +* the parsing modules. To try it, do "make luab". +* +* If you also want to avoid the dump module (ldump.o), define NODUMP. +* #define NODUMP +*/ + +#define LUA_CORE + +#include "llex.h" +#include "lparser.h" +#include "lzio.h" + +LUAI_FUNC void luaX_init (lua_State *L) { + UNUSED(L); +} + +LUAI_FUNC Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) { + UNUSED(z); + UNUSED(buff); + UNUSED(name); + lua_pushliteral(L,"parser not loaded"); + lua_error(L); + return NULL; +} + +#ifdef NODUMP +#include "lundump.h" + +LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip) { + UNUSED(f); + UNUSED(w); + UNUSED(data); + UNUSED(strip); +#if 1 + UNUSED(L); + return 0; +#else + lua_pushliteral(L,"dumper not loaded"); + lua_error(L); +#endif +} +#endif diff --git a/external/mit/lua/dist/etc/strict.lua b/external/mit/lua/dist/etc/strict.lua new file mode 100644 index 000000000..604619dd2 --- /dev/null +++ b/external/mit/lua/dist/etc/strict.lua @@ -0,0 +1,41 @@ +-- +-- strict.lua +-- checks uses of undeclared global variables +-- All global variables must be 'declared' through a regular assignment +-- (even assigning nil will do) in a main chunk before being used +-- anywhere or assigned to inside a function. +-- + +local getinfo, error, rawset, rawget = debug.getinfo, error, rawset, rawget + +local mt = getmetatable(_G) +if mt == nil then + mt = {} + setmetatable(_G, mt) +end + +mt.__declared = {} + +local function what () + local d = getinfo(3, "S") + return d and d.what or "C" +end + +mt.__newindex = function (t, n, v) + if not mt.__declared[n] then + local w = what() + if w ~= "main" and w ~= "C" then + error("assign to undeclared variable '"..n.."'", 2) + end + mt.__declared[n] = true + end + rawset(t, n, v) +end + +mt.__index = function (t, n) + if not mt.__declared[n] and what() ~= "C" then + error("variable '"..n.."' is not declared", 2) + end + return rawget(t, n) +end + diff --git a/external/mit/lua/dist/lua2netbsd b/external/mit/lua/dist/lua2netbsd new file mode 100755 index 000000000..95cc088dc --- /dev/null +++ b/external/mit/lua/dist/lua2netbsd @@ -0,0 +1,56 @@ +#! /bin/sh +# +# $NetBSD: lua2netbsd,v 1.2 2011/10/08 19:28:40 christos Exp $ +# adapted from dist/ipf/ipf2netbsd: +# NetBSD: ipf2netbsd,v 1.23 2010/04/17 22:05:53 darrenr Exp $ +# +# Copyright (c) 1999 The NetBSD Foundation, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +# lua2netbsd: prepare a Lua source tree for NeBSD. + +### Remove the $'s around various RCSIDs +cleantags src doc + +### Add our NetBSD RCS Id +find src -type f -name '*.[ch]' -print | while read c; do + sed 1q < $c | grep -q '\$NetBSD' || ( +echo "/* \$NetBSD\$ */" >/tmp/lua2n$$ +echo "" >>/tmp/lua2n$$ +cat $c >> /tmp/lua2n$$ +mv /tmp/lua2n$$ $c && echo added RCS tag to $c + ) +done + +find doc -type f -name '*.[0-9]' -print | while read m; do + sed 1q < $m | grep -q '\$NetBSD' || ( +echo ".\\\" \$NetBSD\$" >/tmp/lua2m$$ +echo ".\\\"" >>/tmp/lua2m$$ + cat $m >> /tmp/lua2m$$ + mv /tmp/lua2m$$ $m && echo added RCS tag to $m + ) +done + +echo done +exit 0 diff --git a/external/mit/lua/dist/src/Makefile b/external/mit/lua/dist/src/Makefile new file mode 100644 index 000000000..e0d4c9fa6 --- /dev/null +++ b/external/mit/lua/dist/src/Makefile @@ -0,0 +1,182 @@ +# makefile for building Lua +# see ../INSTALL for installation instructions +# see ../Makefile and luaconf.h for further customization + +# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT ======================= + +# Your platform. See PLATS for possible values. +PLAT= none + +CC= gcc +CFLAGS= -O2 -Wall $(MYCFLAGS) +AR= ar rcu +RANLIB= ranlib +RM= rm -f +LIBS= -lm $(MYLIBS) + +MYCFLAGS= +MYLDFLAGS= +MYLIBS= + +# == END OF USER SETTINGS. NO NEED TO CHANGE ANYTHING BELOW THIS LINE ========= + +PLATS= aix ansi bsd freebsd generic linux macosx mingw posix solaris + +LUA_A= liblua.a +CORE_O= lapi.o lcode.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o \ + lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o \ + lundump.o lvm.o lzio.o +LIB_O= lauxlib.o lbaselib.o ldblib.o liolib.o lmathlib.o loslib.o ltablib.o \ + lstrlib.o loadlib.o linit.o + +LUA_T= lua +LUA_O= lua.o + +LUAC_T= luac +LUAC_O= luac.o print.o + +ALL_O= $(CORE_O) $(LIB_O) $(LUA_O) $(LUAC_O) +ALL_T= $(LUA_A) $(LUA_T) $(LUAC_T) +ALL_A= $(LUA_A) + +default: $(PLAT) + +all: $(ALL_T) + +o: $(ALL_O) + +a: $(ALL_A) + +$(LUA_A): $(CORE_O) $(LIB_O) + $(AR) $@ $(CORE_O) $(LIB_O) # DLL needs all object files + $(RANLIB) $@ + +$(LUA_T): $(LUA_O) $(LUA_A) + $(CC) -o $@ $(MYLDFLAGS) $(LUA_O) $(LUA_A) $(LIBS) + +$(LUAC_T): $(LUAC_O) $(LUA_A) + $(CC) -o $@ $(MYLDFLAGS) $(LUAC_O) $(LUA_A) $(LIBS) + +clean: + $(RM) $(ALL_T) $(ALL_O) + +depend: + @$(CC) $(CFLAGS) -MM l*.c print.c + +echo: + @echo "PLAT = $(PLAT)" + @echo "CC = $(CC)" + @echo "CFLAGS = $(CFLAGS)" + @echo "AR = $(AR)" + @echo "RANLIB = $(RANLIB)" + @echo "RM = $(RM)" + @echo "MYCFLAGS = $(MYCFLAGS)" + @echo "MYLDFLAGS = $(MYLDFLAGS)" + @echo "MYLIBS = $(MYLIBS)" + +# convenience targets for popular platforms + +none: + @echo "Please choose a platform:" + @echo " $(PLATS)" + +aix: + $(MAKE) all CC="xlc" CFLAGS="-O2 -DLUA_USE_POSIX -DLUA_USE_DLOPEN" MYLIBS="-ldl" MYLDFLAGS="-brtl -bexpall" + +ansi: + $(MAKE) all MYCFLAGS=-DLUA_ANSI + +bsd: + $(MAKE) all MYCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" MYLIBS="-Wl,-E" + +freebsd: + $(MAKE) all MYCFLAGS="-DLUA_USE_LINUX" MYLIBS="-Wl,-E -lreadline" + +generic: + $(MAKE) all MYCFLAGS= + +linux: + $(MAKE) all MYCFLAGS=-DLUA_USE_LINUX MYLIBS="-Wl,-E -ldl -lreadline -lhistory -lncurses" + +macosx: + $(MAKE) all MYCFLAGS=-DLUA_USE_LINUX MYLIBS="-lreadline" +# use this on Mac OS X 10.3- +# $(MAKE) all MYCFLAGS=-DLUA_USE_MACOSX + +mingw: + $(MAKE) "LUA_A=lua51.dll" "LUA_T=lua.exe" \ + "AR=$(CC) -shared -o" "RANLIB=strip --strip-unneeded" \ + "MYCFLAGS=-DLUA_BUILD_AS_DLL" "MYLIBS=" "MYLDFLAGS=-s" lua.exe + $(MAKE) "LUAC_T=luac.exe" luac.exe + +posix: + $(MAKE) all MYCFLAGS=-DLUA_USE_POSIX + +solaris: + $(MAKE) all MYCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" MYLIBS="-ldl" + +# list targets that do not create files (but not all makes understand .PHONY) +.PHONY: all $(PLATS) default o a clean depend echo none + +# DO NOT DELETE + +lapi.o: lapi.c lua.h luaconf.h lapi.h lobject.h llimits.h ldebug.h \ + lstate.h ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h lstring.h ltable.h \ + lundump.h lvm.h +lauxlib.o: lauxlib.c lua.h luaconf.h lauxlib.h +lbaselib.o: lbaselib.c lua.h luaconf.h lauxlib.h lualib.h +lcode.o: lcode.c lua.h luaconf.h lcode.h llex.h lobject.h llimits.h \ + lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h ldo.h lgc.h \ + ltable.h +ldblib.o: ldblib.c lua.h luaconf.h lauxlib.h lualib.h +ldebug.o: ldebug.c lua.h luaconf.h lapi.h lobject.h llimits.h lcode.h \ + llex.h lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h ldo.h \ + lfunc.h lstring.h lgc.h ltable.h lvm.h +ldo.o: ldo.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h ltm.h \ + lzio.h lmem.h ldo.h lfunc.h lgc.h lopcodes.h lparser.h lstring.h \ + ltable.h lundump.h lvm.h +ldump.o: ldump.c lua.h luaconf.h lobject.h llimits.h lstate.h ltm.h \ + lzio.h lmem.h lundump.h +lfunc.o: lfunc.c lua.h luaconf.h lfunc.h lobject.h llimits.h lgc.h lmem.h \ + lstate.h ltm.h lzio.h +lgc.o: lgc.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h ltm.h \ + lzio.h lmem.h ldo.h lfunc.h lgc.h lstring.h ltable.h +linit.o: linit.c lua.h luaconf.h lualib.h lauxlib.h +liolib.o: liolib.c lua.h luaconf.h lauxlib.h lualib.h +llex.o: llex.c lua.h luaconf.h ldo.h lobject.h llimits.h lstate.h ltm.h \ + lzio.h lmem.h llex.h lparser.h lstring.h lgc.h ltable.h +lmathlib.o: lmathlib.c lua.h luaconf.h lauxlib.h lualib.h +lmem.o: lmem.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \ + ltm.h lzio.h lmem.h ldo.h +loadlib.o: loadlib.c lua.h luaconf.h lauxlib.h lualib.h +lobject.o: lobject.c lua.h luaconf.h ldo.h lobject.h llimits.h lstate.h \ + ltm.h lzio.h lmem.h lstring.h lgc.h lvm.h +lopcodes.o: lopcodes.c lopcodes.h llimits.h lua.h luaconf.h +loslib.o: loslib.c lua.h luaconf.h lauxlib.h lualib.h +lparser.o: lparser.c lua.h luaconf.h lcode.h llex.h lobject.h llimits.h \ + lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h ldo.h \ + lfunc.h lstring.h lgc.h ltable.h +lstate.o: lstate.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \ + ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h llex.h lstring.h ltable.h +lstring.o: lstring.c lua.h luaconf.h lmem.h llimits.h lobject.h lstate.h \ + ltm.h lzio.h lstring.h lgc.h +lstrlib.o: lstrlib.c lua.h luaconf.h lauxlib.h lualib.h +ltable.o: ltable.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \ + ltm.h lzio.h lmem.h ldo.h lgc.h ltable.h +ltablib.o: ltablib.c lua.h luaconf.h lauxlib.h lualib.h +ltm.o: ltm.c lua.h luaconf.h lobject.h llimits.h lstate.h ltm.h lzio.h \ + lmem.h lstring.h lgc.h ltable.h +lua.o: lua.c lua.h luaconf.h lauxlib.h lualib.h +luac.o: luac.c lua.h luaconf.h lauxlib.h ldo.h lobject.h llimits.h \ + lstate.h ltm.h lzio.h lmem.h lfunc.h lopcodes.h lstring.h lgc.h \ + lundump.h +lundump.o: lundump.c lua.h luaconf.h ldebug.h lstate.h lobject.h \ + llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lstring.h lgc.h lundump.h +lvm.o: lvm.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h ltm.h \ + lzio.h lmem.h ldo.h lfunc.h lgc.h lopcodes.h lstring.h ltable.h lvm.h +lzio.o: lzio.c lua.h luaconf.h llimits.h lmem.h lstate.h lobject.h ltm.h \ + lzio.h +print.o: print.c ldebug.h lstate.h lua.h luaconf.h lobject.h llimits.h \ + ltm.h lzio.h lmem.h lopcodes.h lundump.h + +# (end of Makefile) diff --git a/external/mit/lua/dist/src/lapi.c b/external/mit/lua/dist/src/lapi.c new file mode 100644 index 000000000..82dbf8bba --- /dev/null +++ b/external/mit/lua/dist/src/lapi.c @@ -0,0 +1,1089 @@ +/* $NetBSD: lapi.c,v 1.1.1.2 2012/03/15 00:08:10 alnsn Exp $ */ + +/* +** $Id: lapi.c,v 1.1.1.2 2012/03/15 00:08:10 alnsn Exp $ +** Lua API +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include +#include + +#define lapi_c +#define LUA_CORE + +#include "lua.h" + +#include "lapi.h" +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lgc.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" +#include "lundump.h" +#include "lvm.h" + + + +const char lua_ident[] = + "$Lua: " LUA_RELEASE " " LUA_COPYRIGHT " $\n" + "$Authors: " LUA_AUTHORS " $\n" + "$URL: www.lua.org $\n"; + + + +#define api_checknelems(L, n) api_check(L, (n) <= (L->top - L->base)) + +#define api_checkvalidindex(L, i) api_check(L, (i) != luaO_nilobject) + +#define api_incr_top(L) {api_check(L, L->top < L->ci->top); L->top++;} + + + +static TValue *index2adr (lua_State *L, int idx) { + if (idx > 0) { + TValue *o = L->base + (idx - 1); + api_check(L, idx <= L->ci->top - L->base); + if (o >= L->top) return cast(TValue *, luaO_nilobject); + else return o; + } + else if (idx > LUA_REGISTRYINDEX) { + api_check(L, idx != 0 && -idx <= L->top - L->base); + return L->top + idx; + } + else switch (idx) { /* pseudo-indices */ + case LUA_REGISTRYINDEX: return registry(L); + case LUA_ENVIRONINDEX: { + Closure *func = curr_func(L); + sethvalue(L, &L->env, func->c.env); + return &L->env; + } + case LUA_GLOBALSINDEX: return gt(L); + default: { + Closure *func = curr_func(L); + idx = LUA_GLOBALSINDEX - idx; + return (idx <= func->c.nupvalues) + ? &func->c.upvalue[idx-1] + : cast(TValue *, luaO_nilobject); + } + } +} + + +static Table *getcurrenv (lua_State *L) { + if (L->ci == L->base_ci) /* no enclosing function? */ + return hvalue(gt(L)); /* use global table as environment */ + else { + Closure *func = curr_func(L); + return func->c.env; + } +} + + +void luaA_pushobject (lua_State *L, const TValue *o) { + setobj2s(L, L->top, o); + api_incr_top(L); +} + + +LUA_API int lua_checkstack (lua_State *L, int size) { + int res = 1; + lua_lock(L); + if (size > LUAI_MAXCSTACK || (L->top - L->base + size) > LUAI_MAXCSTACK) + res = 0; /* stack overflow */ + else if (size > 0) { + luaD_checkstack(L, size); + if (L->ci->top < L->top + size) + L->ci->top = L->top + size; + } + lua_unlock(L); + return res; +} + + +LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) { + int i; + if (from == to) return; + lua_lock(to); + api_checknelems(from, n); + api_check(from, G(from) == G(to)); + api_check(from, to->ci->top - to->top >= n); + from->top -= n; + for (i = 0; i < n; i++) { + setobj2s(to, to->top++, from->top + i); + } + lua_unlock(to); +} + + +LUA_API void lua_setlevel (lua_State *from, lua_State *to) { + to->nCcalls = from->nCcalls; +} + + +LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) { + lua_CFunction old; + lua_lock(L); + old = G(L)->panic; + G(L)->panic = panicf; + lua_unlock(L); + return old; +} + + +LUA_API lua_State *lua_newthread (lua_State *L) { + lua_State *L1; + lua_lock(L); + luaC_checkGC(L); + L1 = luaE_newthread(L); + setthvalue(L, L->top, L1); + api_incr_top(L); + lua_unlock(L); + luai_userstatethread(L, L1); + return L1; +} + + + +/* +** basic stack manipulation +*/ + + +LUA_API int lua_gettop (lua_State *L) { + return cast_int(L->top - L->base); +} + + +LUA_API void lua_settop (lua_State *L, int idx) { + lua_lock(L); + if (idx >= 0) { + api_check(L, idx <= L->stack_last - L->base); + while (L->top < L->base + idx) + setnilvalue(L->top++); + L->top = L->base + idx; + } + else { + api_check(L, -(idx+1) <= (L->top - L->base)); + L->top += idx+1; /* `subtract' index (index is negative) */ + } + lua_unlock(L); +} + + +LUA_API void lua_remove (lua_State *L, int idx) { + StkId p; + lua_lock(L); + p = index2adr(L, idx); + api_checkvalidindex(L, p); + while (++p < L->top) setobjs2s(L, p-1, p); + L->top--; + lua_unlock(L); +} + + +LUA_API void lua_insert (lua_State *L, int idx) { + StkId p; + StkId q; + lua_lock(L); + p = index2adr(L, idx); + api_checkvalidindex(L, p); + for (q = L->top; q>p; q--) setobjs2s(L, q, q-1); + setobjs2s(L, p, L->top); + lua_unlock(L); +} + + +LUA_API void lua_replace (lua_State *L, int idx) { + StkId o; + lua_lock(L); + /* explicit test for incompatible code */ + if (idx == LUA_ENVIRONINDEX && L->ci == L->base_ci) + luaG_runerror(L, "no calling environment"); + api_checknelems(L, 1); + o = index2adr(L, idx); + api_checkvalidindex(L, o); + if (idx == LUA_ENVIRONINDEX) { + Closure *func = curr_func(L); + api_check(L, ttistable(L->top - 1)); + func->c.env = hvalue(L->top - 1); + luaC_barrier(L, func, L->top - 1); + } + else { + setobj(L, o, L->top - 1); + if (idx < LUA_GLOBALSINDEX) /* function upvalue? */ + luaC_barrier(L, curr_func(L), L->top - 1); + } + L->top--; + lua_unlock(L); +} + + +LUA_API void lua_pushvalue (lua_State *L, int idx) { + lua_lock(L); + setobj2s(L, L->top, index2adr(L, idx)); + api_incr_top(L); + lua_unlock(L); +} + + + +/* +** access functions (stack -> C) +*/ + + +LUA_API int lua_type (lua_State *L, int idx) { + StkId o = index2adr(L, idx); + return (o == luaO_nilobject) ? LUA_TNONE : ttype(o); +} + + +LUA_API const char *lua_typename (lua_State *L, int t) { + UNUSED(L); + return (t == LUA_TNONE) ? "no value" : luaT_typenames[t]; +} + + +LUA_API int lua_iscfunction (lua_State *L, int idx) { + StkId o = index2adr(L, idx); + return iscfunction(o); +} + + +LUA_API int lua_isnumber (lua_State *L, int idx) { + TValue n; + const TValue *o = index2adr(L, idx); + return tonumber(o, &n); +} + + +LUA_API int lua_isstring (lua_State *L, int idx) { + int t = lua_type(L, idx); + return (t == LUA_TSTRING || t == LUA_TNUMBER); +} + + +LUA_API int lua_isuserdata (lua_State *L, int idx) { + const TValue *o = index2adr(L, idx); + return (ttisuserdata(o) || ttislightuserdata(o)); +} + + +LUA_API int lua_rawequal (lua_State *L, int index1, int index2) { + StkId o1 = index2adr(L, index1); + StkId o2 = index2adr(L, index2); + return (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 + : luaO_rawequalObj(o1, o2); +} + + +LUA_API int lua_equal (lua_State *L, int index1, int index2) { + StkId o1, o2; + int i; + lua_lock(L); /* may call tag method */ + o1 = index2adr(L, index1); + o2 = index2adr(L, index2); + i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 : equalobj(L, o1, o2); + lua_unlock(L); + return i; +} + + +LUA_API int lua_lessthan (lua_State *L, int index1, int index2) { + StkId o1, o2; + int i; + lua_lock(L); /* may call tag method */ + o1 = index2adr(L, index1); + o2 = index2adr(L, index2); + i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 + : luaV_lessthan(L, o1, o2); + lua_unlock(L); + return i; +} + + + +LUA_API lua_Number lua_tonumber (lua_State *L, int idx) { + TValue n; + const TValue *o = index2adr(L, idx); + if (tonumber(o, &n)) + return nvalue(o); + else + return 0; +} + + +LUA_API lua_Integer lua_tointeger (lua_State *L, int idx) { + TValue n; + const TValue *o = index2adr(L, idx); + if (tonumber(o, &n)) { + lua_Integer res; + lua_Number num = nvalue(o); + lua_number2integer(res, num); + return res; + } + else + return 0; +} + + +LUA_API int lua_toboolean (lua_State *L, int idx) { + const TValue *o = index2adr(L, idx); + return !l_isfalse(o); +} + + +LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) { + StkId o = index2adr(L, idx); + if (!ttisstring(o)) { + lua_lock(L); /* `luaV_tostring' may create a new string */ + if (!luaV_tostring(L, o)) { /* conversion failed? */ + if (len != NULL) *len = 0; + lua_unlock(L); + return NULL; + } + luaC_checkGC(L); + o = index2adr(L, idx); /* previous call may reallocate the stack */ + lua_unlock(L); + } + if (len != NULL) *len = tsvalue(o)->len; + return svalue(o); +} + + +LUA_API size_t lua_objlen (lua_State *L, int idx) { + StkId o = index2adr(L, idx); + switch (ttype(o)) { + case LUA_TSTRING: return tsvalue(o)->len; + case LUA_TUSERDATA: return uvalue(o)->len; + case LUA_TTABLE: return luaH_getn(hvalue(o)); + case LUA_TNUMBER: { + size_t l; + lua_lock(L); /* `luaV_tostring' may create a new string */ + l = (luaV_tostring(L, o) ? tsvalue(o)->len : 0); + lua_unlock(L); + return l; + } + default: return 0; + } +} + + +LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) { + StkId o = index2adr(L, idx); + return (!iscfunction(o)) ? NULL : clvalue(o)->c.f; +} + + +LUA_API void *lua_touserdata (lua_State *L, int idx) { + StkId o = index2adr(L, idx); + switch (ttype(o)) { + case LUA_TUSERDATA: return (rawuvalue(o) + 1); + case LUA_TLIGHTUSERDATA: return pvalue(o); + default: return NULL; + } +} + + +LUA_API lua_State *lua_tothread (lua_State *L, int idx) { + StkId o = index2adr(L, idx); + return (!ttisthread(o)) ? NULL : thvalue(o); +} + + +LUA_API const void *lua_topointer (lua_State *L, int idx) { + StkId o = index2adr(L, idx); + switch (ttype(o)) { + case LUA_TTABLE: return hvalue(o); + case LUA_TFUNCTION: return clvalue(o); + case LUA_TTHREAD: return thvalue(o); + case LUA_TUSERDATA: + case LUA_TLIGHTUSERDATA: + return lua_touserdata(L, idx); + default: return NULL; + } +} + + + +/* +** push functions (C -> stack) +*/ + + +LUA_API void lua_pushnil (lua_State *L) { + lua_lock(L); + setnilvalue(L->top); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_pushnumber (lua_State *L, lua_Number n) { + lua_lock(L); + setnvalue(L->top, n); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) { + lua_lock(L); + setnvalue(L->top, cast_num(n)); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len) { + lua_lock(L); + luaC_checkGC(L); + setsvalue2s(L, L->top, luaS_newlstr(L, s, len)); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_pushstring (lua_State *L, const char *s) { + if (s == NULL) + lua_pushnil(L); + else + lua_pushlstring(L, s, strlen(s)); +} + + +LUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt, + va_list argp) { + const char *ret; + lua_lock(L); + luaC_checkGC(L); + ret = luaO_pushvfstring(L, fmt, argp); + lua_unlock(L); + return ret; +} + + +LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) { + const char *ret; + va_list argp; + lua_lock(L); + luaC_checkGC(L); + va_start(argp, fmt); + ret = luaO_pushvfstring(L, fmt, argp); + va_end(argp); + lua_unlock(L); + return ret; +} + + +LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { + Closure *cl; + lua_lock(L); + luaC_checkGC(L); + api_checknelems(L, n); + cl = luaF_newCclosure(L, n, getcurrenv(L)); + cl->c.f = fn; + L->top -= n; + while (n--) + setobj2n(L, &cl->c.upvalue[n], L->top+n); + setclvalue(L, L->top, cl); + lua_assert(iswhite(obj2gco(cl))); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_pushboolean (lua_State *L, int b) { + lua_lock(L); + setbvalue(L->top, (b != 0)); /* ensure that true is 1 */ + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_pushlightuserdata (lua_State *L, void *p) { + lua_lock(L); + setpvalue(L->top, p); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API int lua_pushthread (lua_State *L) { + lua_lock(L); + setthvalue(L, L->top, L); + api_incr_top(L); + lua_unlock(L); + return (G(L)->mainthread == L); +} + + + +/* +** get functions (Lua -> stack) +*/ + + +LUA_API void lua_gettable (lua_State *L, int idx) { + StkId t; + lua_lock(L); + t = index2adr(L, idx); + api_checkvalidindex(L, t); + luaV_gettable(L, t, L->top - 1, L->top - 1); + lua_unlock(L); +} + + +LUA_API void lua_getfield (lua_State *L, int idx, const char *k) { + StkId t; + TValue key; + lua_lock(L); + t = index2adr(L, idx); + api_checkvalidindex(L, t); + setsvalue(L, &key, luaS_new(L, k)); + luaV_gettable(L, t, &key, L->top); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_rawget (lua_State *L, int idx) { + StkId t; + lua_lock(L); + t = index2adr(L, idx); + api_check(L, ttistable(t)); + setobj2s(L, L->top - 1, luaH_get(hvalue(t), L->top - 1)); + lua_unlock(L); +} + + +LUA_API void lua_rawgeti (lua_State *L, int idx, int n) { + StkId o; + lua_lock(L); + o = index2adr(L, idx); + api_check(L, ttistable(o)); + setobj2s(L, L->top, luaH_getnum(hvalue(o), n)); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_createtable (lua_State *L, int narray, int nrec) { + lua_lock(L); + luaC_checkGC(L); + sethvalue(L, L->top, luaH_new(L, narray, nrec)); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API int lua_getmetatable (lua_State *L, int objindex) { + const TValue *obj; + Table *mt = NULL; + int res; + lua_lock(L); + obj = index2adr(L, objindex); + switch (ttype(obj)) { + case LUA_TTABLE: + mt = hvalue(obj)->metatable; + break; + case LUA_TUSERDATA: + mt = uvalue(obj)->metatable; + break; + default: + mt = G(L)->mt[ttype(obj)]; + break; + } + if (mt == NULL) + res = 0; + else { + sethvalue(L, L->top, mt); + api_incr_top(L); + res = 1; + } + lua_unlock(L); + return res; +} + + +LUA_API void lua_getfenv (lua_State *L, int idx) { + StkId o; + lua_lock(L); + o = index2adr(L, idx); + api_checkvalidindex(L, o); + switch (ttype(o)) { + case LUA_TFUNCTION: + sethvalue(L, L->top, clvalue(o)->c.env); + break; + case LUA_TUSERDATA: + sethvalue(L, L->top, uvalue(o)->env); + break; + case LUA_TTHREAD: + setobj2s(L, L->top, gt(thvalue(o))); + break; + default: + setnilvalue(L->top); + break; + } + api_incr_top(L); + lua_unlock(L); +} + + +/* +** set functions (stack -> Lua) +*/ + + +LUA_API void lua_settable (lua_State *L, int idx) { + StkId t; + lua_lock(L); + api_checknelems(L, 2); + t = index2adr(L, idx); + api_checkvalidindex(L, t); + luaV_settable(L, t, L->top - 2, L->top - 1); + L->top -= 2; /* pop index and value */ + lua_unlock(L); +} + + +LUA_API void lua_setfield (lua_State *L, int idx, const char *k) { + StkId t; + TValue key; + lua_lock(L); + api_checknelems(L, 1); + t = index2adr(L, idx); + api_checkvalidindex(L, t); + setsvalue(L, &key, luaS_new(L, k)); + luaV_settable(L, t, &key, L->top - 1); + L->top--; /* pop value */ + lua_unlock(L); +} + + +LUA_API void lua_rawset (lua_State *L, int idx) { + StkId t; + lua_lock(L); + api_checknelems(L, 2); + t = index2adr(L, idx); + api_check(L, ttistable(t)); + setobj2t(L, luaH_set(L, hvalue(t), L->top-2), L->top-1); + luaC_barriert(L, hvalue(t), L->top-1); + L->top -= 2; + lua_unlock(L); +} + + +LUA_API void lua_rawseti (lua_State *L, int idx, int n) { + StkId o; + lua_lock(L); + api_checknelems(L, 1); + o = index2adr(L, idx); + api_check(L, ttistable(o)); + setobj2t(L, luaH_setnum(L, hvalue(o), n), L->top-1); + luaC_barriert(L, hvalue(o), L->top-1); + L->top--; + lua_unlock(L); +} + + +LUA_API int lua_setmetatable (lua_State *L, int objindex) { + TValue *obj; + Table *mt; + lua_lock(L); + api_checknelems(L, 1); + obj = index2adr(L, objindex); + api_checkvalidindex(L, obj); + if (ttisnil(L->top - 1)) + mt = NULL; + else { + api_check(L, ttistable(L->top - 1)); + mt = hvalue(L->top - 1); + } + switch (ttype(obj)) { + case LUA_TTABLE: { + hvalue(obj)->metatable = mt; + if (mt) + luaC_objbarriert(L, hvalue(obj), mt); + break; + } + case LUA_TUSERDATA: { + uvalue(obj)->metatable = mt; + if (mt) + luaC_objbarrier(L, rawuvalue(obj), mt); + break; + } + default: { + G(L)->mt[ttype(obj)] = mt; + break; + } + } + L->top--; + lua_unlock(L); + return 1; +} + + +LUA_API int lua_setfenv (lua_State *L, int idx) { + StkId o; + int res = 1; + lua_lock(L); + api_checknelems(L, 1); + o = index2adr(L, idx); + api_checkvalidindex(L, o); + api_check(L, ttistable(L->top - 1)); + switch (ttype(o)) { + case LUA_TFUNCTION: + clvalue(o)->c.env = hvalue(L->top - 1); + break; + case LUA_TUSERDATA: + uvalue(o)->env = hvalue(L->top - 1); + break; + case LUA_TTHREAD: + sethvalue(L, gt(thvalue(o)), hvalue(L->top - 1)); + break; + default: + res = 0; + break; + } + if (res) luaC_objbarrier(L, gcvalue(o), hvalue(L->top - 1)); + L->top--; + lua_unlock(L); + return res; +} + + +/* +** `load' and `call' functions (run Lua code) +*/ + + +#define adjustresults(L,nres) \ + { if (nres == LUA_MULTRET && L->top >= L->ci->top) L->ci->top = L->top; } + + +#define checkresults(L,na,nr) \ + api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na))) + + +LUA_API void lua_call (lua_State *L, int nargs, int nresults) { + StkId func; + lua_lock(L); + api_checknelems(L, nargs+1); + checkresults(L, nargs, nresults); + func = L->top - (nargs+1); + luaD_call(L, func, nresults); + adjustresults(L, nresults); + lua_unlock(L); +} + + + +/* +** Execute a protected call. +*/ +struct CallS { /* data to `f_call' */ + StkId func; + int nresults; +}; + + +static void f_call (lua_State *L, void *ud) { + struct CallS *c = cast(struct CallS *, ud); + luaD_call(L, c->func, c->nresults); +} + + + +LUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc) { + struct CallS c; + int status; + ptrdiff_t func; + lua_lock(L); + api_checknelems(L, nargs+1); + checkresults(L, nargs, nresults); + if (errfunc == 0) + func = 0; + else { + StkId o = index2adr(L, errfunc); + api_checkvalidindex(L, o); + func = savestack(L, o); + } + c.func = L->top - (nargs+1); /* function to be called */ + c.nresults = nresults; + status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func); + adjustresults(L, nresults); + lua_unlock(L); + return status; +} + + +/* +** Execute a protected C call. +*/ +struct CCallS { /* data to `f_Ccall' */ + lua_CFunction func; + void *ud; +}; + + +static void f_Ccall (lua_State *L, void *ud) { + struct CCallS *c = cast(struct CCallS *, ud); + Closure *cl; + cl = luaF_newCclosure(L, 0, getcurrenv(L)); + cl->c.f = c->func; + setclvalue(L, L->top, cl); /* push function */ + api_incr_top(L); + setpvalue(L->top, c->ud); /* push only argument */ + api_incr_top(L); + luaD_call(L, L->top - 2, 0); +} + + +LUA_API int lua_cpcall (lua_State *L, lua_CFunction func, void *ud) { + struct CCallS c; + int status; + lua_lock(L); + c.func = func; + c.ud = ud; + status = luaD_pcall(L, f_Ccall, &c, savestack(L, L->top), 0); + lua_unlock(L); + return status; +} + + +LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data, + const char *chunkname) { + ZIO z; + int status; + lua_lock(L); + if (!chunkname) chunkname = "?"; + luaZ_init(L, &z, reader, data); + status = luaD_protectedparser(L, &z, chunkname); + lua_unlock(L); + return status; +} + + +LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data) { + int status; + TValue *o; + lua_lock(L); + api_checknelems(L, 1); + o = L->top - 1; + if (isLfunction(o)) + status = luaU_dump(L, clvalue(o)->l.p, writer, data, 0); + else + status = 1; + lua_unlock(L); + return status; +} + + +LUA_API int lua_status (lua_State *L) { + return L->status; +} + + +/* +** Garbage-collection function +*/ + +LUA_API int lua_gc (lua_State *L, int what, int data) { + int res = 0; + global_State *g; + lua_lock(L); + g = G(L); + switch (what) { + case LUA_GCSTOP: { + g->GCthreshold = MAX_LUMEM; + break; + } + case LUA_GCRESTART: { + g->GCthreshold = g->totalbytes; + break; + } + case LUA_GCCOLLECT: { + luaC_fullgc(L); + break; + } + case LUA_GCCOUNT: { + /* GC values are expressed in Kbytes: #bytes/2^10 */ + res = cast_int(g->totalbytes >> 10); + break; + } + case LUA_GCCOUNTB: { + res = cast_int(g->totalbytes & 0x3ff); + break; + } + case LUA_GCSTEP: { + lu_mem a = (cast(lu_mem, data) << 10); + if (a <= g->totalbytes) + g->GCthreshold = g->totalbytes - a; + else + g->GCthreshold = 0; + while (g->GCthreshold <= g->totalbytes) { + luaC_step(L); + if (g->gcstate == GCSpause) { /* end of cycle? */ + res = 1; /* signal it */ + break; + } + } + break; + } + case LUA_GCSETPAUSE: { + res = g->gcpause; + g->gcpause = data; + break; + } + case LUA_GCSETSTEPMUL: { + res = g->gcstepmul; + g->gcstepmul = data; + break; + } + default: res = -1; /* invalid option */ + } + lua_unlock(L); + return res; +} + + + +/* +** miscellaneous functions +*/ + + +LUA_API int lua_error (lua_State *L) { + lua_lock(L); + api_checknelems(L, 1); + luaG_errormsg(L); + lua_unlock(L); + return 0; /* to avoid warnings */ +} + + +LUA_API int lua_next (lua_State *L, int idx) { + StkId t; + int more; + lua_lock(L); + t = index2adr(L, idx); + api_check(L, ttistable(t)); + more = luaH_next(L, hvalue(t), L->top - 1); + if (more) { + api_incr_top(L); + } + else /* no more elements */ + L->top -= 1; /* remove key */ + lua_unlock(L); + return more; +} + + +LUA_API void lua_concat (lua_State *L, int n) { + lua_lock(L); + api_checknelems(L, n); + if (n >= 2) { + luaC_checkGC(L); + luaV_concat(L, n, cast_int(L->top - L->base) - 1); + L->top -= (n-1); + } + else if (n == 0) { /* push empty string */ + setsvalue2s(L, L->top, luaS_newlstr(L, "", 0)); + api_incr_top(L); + } + /* else n == 1; nothing to do */ + lua_unlock(L); +} + + +LUA_API lua_Alloc lua_getallocf (lua_State *L, void **ud) { + lua_Alloc f; + lua_lock(L); + if (ud) *ud = G(L)->ud; + f = G(L)->frealloc; + lua_unlock(L); + return f; +} + + +LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud) { + lua_lock(L); + G(L)->ud = ud; + G(L)->frealloc = f; + lua_unlock(L); +} + + +LUA_API void *lua_newuserdata (lua_State *L, size_t size) { + Udata *u; + lua_lock(L); + luaC_checkGC(L); + u = luaS_newudata(L, size, getcurrenv(L)); + setuvalue(L, L->top, u); + api_incr_top(L); + lua_unlock(L); + return u + 1; +} + + + + +static const char *aux_upvalue (StkId fi, int n, TValue **val) { + Closure *f; + if (!ttisfunction(fi)) return NULL; + f = clvalue(fi); + if (f->c.isC) { + if (!(1 <= n && n <= f->c.nupvalues)) return NULL; + *val = &f->c.upvalue[n-1]; + return ""; + } + else { + Proto *p = f->l.p; + if (!(1 <= n && n <= p->sizeupvalues)) return NULL; + *val = f->l.upvals[n-1]->v; + return getstr(p->upvalues[n-1]); + } +} + + +LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) { + const char *name; + TValue *val; + lua_lock(L); + name = aux_upvalue(index2adr(L, funcindex), n, &val); + if (name) { + setobj2s(L, L->top, val); + api_incr_top(L); + } + lua_unlock(L); + return name; +} + + +LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { + const char *name; + TValue *val; + StkId fi; + lua_lock(L); + fi = index2adr(L, funcindex); + api_checknelems(L, 1); + name = aux_upvalue(fi, n, &val); + if (name) { + L->top--; + setobj(L, val, L->top); + luaC_barrier(L, clvalue(fi), L->top); + } + lua_unlock(L); + return name; +} + diff --git a/external/mit/lua/dist/src/lapi.h b/external/mit/lua/dist/src/lapi.h new file mode 100644 index 000000000..7a2f2ab14 --- /dev/null +++ b/external/mit/lua/dist/src/lapi.h @@ -0,0 +1,18 @@ +/* $NetBSD: lapi.h,v 1.1.1.2 2012/03/15 00:08:13 alnsn Exp $ */ + +/* +** $Id: lapi.h,v 1.1.1.2 2012/03/15 00:08:13 alnsn Exp $ +** Auxiliary functions from Lua API +** See Copyright Notice in lua.h +*/ + +#ifndef lapi_h +#define lapi_h + + +#include "lobject.h" + + +LUAI_FUNC void luaA_pushobject (lua_State *L, const TValue *o); + +#endif diff --git a/external/mit/lua/dist/src/lauxlib.c b/external/mit/lua/dist/src/lauxlib.c new file mode 100644 index 000000000..c971e9954 --- /dev/null +++ b/external/mit/lua/dist/src/lauxlib.c @@ -0,0 +1,654 @@ +/* $NetBSD: lauxlib.c,v 1.1.1.2 2012/03/15 00:08:09 alnsn Exp $ */ + +/* +** $Id: lauxlib.c,v 1.1.1.2 2012/03/15 00:08:09 alnsn Exp $ +** Auxiliary functions for building Lua libraries +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include +#include +#include +#include + + +/* This file uses only the official API of Lua. +** Any function declared here could be written as an application function. +*/ + +#define lauxlib_c +#define LUA_LIB + +#include "lua.h" + +#include "lauxlib.h" + + +#define FREELIST_REF 0 /* free list of references */ + + +/* convert a stack index to positive */ +#define abs_index(L, i) ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : \ + lua_gettop(L) + (i) + 1) + + +/* +** {====================================================== +** Error-report functions +** ======================================================= +*/ + + +LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) { + lua_Debug ar; + if (!lua_getstack(L, 0, &ar)) /* no stack frame? */ + return luaL_error(L, "bad argument #%d (%s)", narg, extramsg); + lua_getinfo(L, "n", &ar); + if (strcmp(ar.namewhat, "method") == 0) { + narg--; /* do not count `self' */ + if (narg == 0) /* error is in the self argument itself? */ + return luaL_error(L, "calling " LUA_QS " on bad self (%s)", + ar.name, extramsg); + } + if (ar.name == NULL) + ar.name = "?"; + return luaL_error(L, "bad argument #%d to " LUA_QS " (%s)", + narg, ar.name, extramsg); +} + + +LUALIB_API int luaL_typerror (lua_State *L, int narg, const char *tname) { + const char *msg = lua_pushfstring(L, "%s expected, got %s", + tname, luaL_typename(L, narg)); + return luaL_argerror(L, narg, msg); +} + + +static void tag_error (lua_State *L, int narg, int tag) { + luaL_typerror(L, narg, lua_typename(L, tag)); +} + + +LUALIB_API void luaL_where (lua_State *L, int level) { + lua_Debug ar; + if (lua_getstack(L, level, &ar)) { /* check function at level */ + lua_getinfo(L, "Sl", &ar); /* get info about it */ + if (ar.currentline > 0) { /* is there info? */ + lua_pushfstring(L, "%s:%d: ", ar.short_src, ar.currentline); + return; + } + } + lua_pushliteral(L, ""); /* else, no information available... */ +} + + +LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) { + va_list argp; + va_start(argp, fmt); + luaL_where(L, 1); + lua_pushvfstring(L, fmt, argp); + va_end(argp); + lua_concat(L, 2); + return lua_error(L); +} + +/* }====================================================== */ + + +LUALIB_API int luaL_checkoption (lua_State *L, int narg, const char *def, + const char *const lst[]) { + const char *name = (def) ? luaL_optstring(L, narg, def) : + luaL_checkstring(L, narg); + int i; + for (i=0; lst[i]; i++) + if (strcmp(lst[i], name) == 0) + return i; + return luaL_argerror(L, narg, + lua_pushfstring(L, "invalid option " LUA_QS, name)); +} + + +LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) { + lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get registry.name */ + if (!lua_isnil(L, -1)) /* name already in use? */ + return 0; /* leave previous value on top, but return 0 */ + lua_pop(L, 1); + lua_newtable(L); /* create metatable */ + lua_pushvalue(L, -1); + lua_setfield(L, LUA_REGISTRYINDEX, tname); /* registry.name = metatable */ + return 1; +} + + +LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) { + void *p = lua_touserdata(L, ud); + if (p != NULL) { /* value is a userdata? */ + if (lua_getmetatable(L, ud)) { /* does it have a metatable? */ + lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get correct metatable */ + if (lua_rawequal(L, -1, -2)) { /* does it have the correct mt? */ + lua_pop(L, 2); /* remove both metatables */ + return p; + } + } + } + luaL_typerror(L, ud, tname); /* else error */ + return NULL; /* to avoid warnings */ +} + + +LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *mes) { + if (!lua_checkstack(L, space)) + luaL_error(L, "stack overflow (%s)", mes); +} + + +LUALIB_API void luaL_checktype (lua_State *L, int narg, int t) { + if (lua_type(L, narg) != t) + tag_error(L, narg, t); +} + + +LUALIB_API void luaL_checkany (lua_State *L, int narg) { + if (lua_type(L, narg) == LUA_TNONE) + luaL_argerror(L, narg, "value expected"); +} + + +LUALIB_API const char *luaL_checklstring (lua_State *L, int narg, size_t *len) { + const char *s = lua_tolstring(L, narg, len); + if (!s) tag_error(L, narg, LUA_TSTRING); + return s; +} + + +LUALIB_API const char *luaL_optlstring (lua_State *L, int narg, + const char *def, size_t *len) { + if (lua_isnoneornil(L, narg)) { + if (len) + *len = (def ? strlen(def) : 0); + return def; + } + else return luaL_checklstring(L, narg, len); +} + + +LUALIB_API lua_Number luaL_checknumber (lua_State *L, int narg) { + lua_Number d = lua_tonumber(L, narg); + if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */ + tag_error(L, narg, LUA_TNUMBER); + return d; +} + + +LUALIB_API lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number def) { + return luaL_opt(L, luaL_checknumber, narg, def); +} + + +LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int narg) { + lua_Integer d = lua_tointeger(L, narg); + if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */ + tag_error(L, narg, LUA_TNUMBER); + return d; +} + + +LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int narg, + lua_Integer def) { + return luaL_opt(L, luaL_checkinteger, narg, def); +} + + +LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) { + if (!lua_getmetatable(L, obj)) /* no metatable? */ + return 0; + lua_pushstring(L, event); + lua_rawget(L, -2); + if (lua_isnil(L, -1)) { + lua_pop(L, 2); /* remove metatable and metafield */ + return 0; + } + else { + lua_remove(L, -2); /* remove only metatable */ + return 1; + } +} + + +LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) { + obj = abs_index(L, obj); + if (!luaL_getmetafield(L, obj, event)) /* no metafield? */ + return 0; + lua_pushvalue(L, obj); + lua_call(L, 1, 1); + return 1; +} + + +LUALIB_API void (luaL_register) (lua_State *L, const char *libname, + const luaL_Reg *l) { + luaI_openlib(L, libname, l, 0); +} + + +static int libsize (const luaL_Reg *l) { + int size = 0; + for (; l->name; l++) size++; + return size; +} + + +LUALIB_API void luaI_openlib (lua_State *L, const char *libname, + const luaL_Reg *l, int nup) { + if (libname) { + int size = libsize(l); + /* check whether lib already exists */ + luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 1); + lua_getfield(L, -1, libname); /* get _LOADED[libname] */ + if (!lua_istable(L, -1)) { /* not found? */ + lua_pop(L, 1); /* remove previous result */ + /* try global variable (and create one if it does not exist) */ + if (luaL_findtable(L, LUA_GLOBALSINDEX, libname, size) != NULL) + luaL_error(L, "name conflict for module " LUA_QS, libname); + lua_pushvalue(L, -1); + lua_setfield(L, -3, libname); /* _LOADED[libname] = new table */ + } + lua_remove(L, -2); /* remove _LOADED table */ + lua_insert(L, -(nup+1)); /* move library table to below upvalues */ + } + for (; l->name; l++) { + int i; + for (i=0; ifunc, nup); + lua_setfield(L, -(nup+2), l->name); + } + lua_pop(L, nup); /* remove upvalues */ +} + + + +/* +** {====================================================== +** getn-setn: size for arrays +** ======================================================= +*/ + +#if defined(LUA_COMPAT_GETN) + +static int checkint (lua_State *L, int topop) { + int n = (lua_type(L, -1) == LUA_TNUMBER) ? lua_tointeger(L, -1) : -1; + lua_pop(L, topop); + return n; +} + + +static void getsizes (lua_State *L) { + lua_getfield(L, LUA_REGISTRYINDEX, "LUA_SIZES"); + if (lua_isnil(L, -1)) { /* no `size' table? */ + lua_pop(L, 1); /* remove nil */ + lua_newtable(L); /* create it */ + lua_pushvalue(L, -1); /* `size' will be its own metatable */ + lua_setmetatable(L, -2); + lua_pushliteral(L, "kv"); + lua_setfield(L, -2, "__mode"); /* metatable(N).__mode = "kv" */ + lua_pushvalue(L, -1); + lua_setfield(L, LUA_REGISTRYINDEX, "LUA_SIZES"); /* store in register */ + } +} + + +LUALIB_API void luaL_setn (lua_State *L, int t, int n) { + t = abs_index(L, t); + lua_pushliteral(L, "n"); + lua_rawget(L, t); + if (checkint(L, 1) >= 0) { /* is there a numeric field `n'? */ + lua_pushliteral(L, "n"); /* use it */ + lua_pushinteger(L, n); + lua_rawset(L, t); + } + else { /* use `sizes' */ + getsizes(L); + lua_pushvalue(L, t); + lua_pushinteger(L, n); + lua_rawset(L, -3); /* sizes[t] = n */ + lua_pop(L, 1); /* remove `sizes' */ + } +} + + +LUALIB_API int luaL_getn (lua_State *L, int t) { + int n; + t = abs_index(L, t); + lua_pushliteral(L, "n"); /* try t.n */ + lua_rawget(L, t); + if ((n = checkint(L, 1)) >= 0) return n; + getsizes(L); /* else try sizes[t] */ + lua_pushvalue(L, t); + lua_rawget(L, -2); + if ((n = checkint(L, 2)) >= 0) return n; + return (int)lua_objlen(L, t); +} + +#endif + +/* }====================================================== */ + + + +LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p, + const char *r) { + const char *wild; + size_t l = strlen(p); + luaL_Buffer b; + luaL_buffinit(L, &b); + while ((wild = strstr(s, p)) != NULL) { + luaL_addlstring(&b, s, wild - s); /* push prefix */ + luaL_addstring(&b, r); /* push replacement in place of pattern */ + s = wild + l; /* continue after `p' */ + } + luaL_addstring(&b, s); /* push last suffix */ + luaL_pushresult(&b); + return lua_tostring(L, -1); +} + + +LUALIB_API const char *luaL_findtable (lua_State *L, int idx, + const char *fname, int szhint) { + const char *e; + lua_pushvalue(L, idx); + do { + e = strchr(fname, '.'); + if (e == NULL) e = fname + strlen(fname); + lua_pushlstring(L, fname, e - fname); + lua_rawget(L, -2); + if (lua_isnil(L, -1)) { /* no such field? */ + lua_pop(L, 1); /* remove this nil */ + lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */ + lua_pushlstring(L, fname, e - fname); + lua_pushvalue(L, -2); + lua_settable(L, -4); /* set new table into field */ + } + else if (!lua_istable(L, -1)) { /* field has a non-table value? */ + lua_pop(L, 2); /* remove table and value */ + return fname; /* return problematic part of the name */ + } + lua_remove(L, -2); /* remove previous table */ + fname = e + 1; + } while (*e == '.'); + return NULL; +} + + + +/* +** {====================================================== +** Generic Buffer manipulation +** ======================================================= +*/ + + +#define bufflen(B) ((B)->p - (B)->buffer) +#define bufffree(B) ((size_t)(LUAL_BUFFERSIZE - bufflen(B))) + +#define LIMIT (LUA_MINSTACK/2) + + +static int emptybuffer (luaL_Buffer *B) { + size_t l = bufflen(B); + if (l == 0) return 0; /* put nothing on stack */ + else { + lua_pushlstring(B->L, B->buffer, l); + B->p = B->buffer; + B->lvl++; + return 1; + } +} + + +static void adjuststack (luaL_Buffer *B) { + if (B->lvl > 1) { + lua_State *L = B->L; + int toget = 1; /* number of levels to concat */ + size_t toplen = lua_strlen(L, -1); + do { + size_t l = lua_strlen(L, -(toget+1)); + if (B->lvl - toget + 1 >= LIMIT || toplen > l) { + toplen += l; + toget++; + } + else break; + } while (toget < B->lvl); + lua_concat(L, toget); + B->lvl = B->lvl - toget + 1; + } +} + + +LUALIB_API char *luaL_prepbuffer (luaL_Buffer *B) { + if (emptybuffer(B)) + adjuststack(B); + return B->buffer; +} + + +LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) { + while (l--) + luaL_addchar(B, *s++); +} + + +LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) { + luaL_addlstring(B, s, strlen(s)); +} + + +LUALIB_API void luaL_pushresult (luaL_Buffer *B) { + emptybuffer(B); + lua_concat(B->L, B->lvl); + B->lvl = 1; +} + + +LUALIB_API void luaL_addvalue (luaL_Buffer *B) { + lua_State *L = B->L; + size_t vl; + const char *s = lua_tolstring(L, -1, &vl); + if (vl <= bufffree(B)) { /* fit into buffer? */ + memcpy(B->p, s, vl); /* put it there */ + B->p += vl; + lua_pop(L, 1); /* remove from stack */ + } + else { + if (emptybuffer(B)) + lua_insert(L, -2); /* put buffer before new value */ + B->lvl++; /* add new value into B stack */ + adjuststack(B); + } +} + + +LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) { + B->L = L; + B->p = B->buffer; + B->lvl = 0; +} + +/* }====================================================== */ + + +LUALIB_API int luaL_ref (lua_State *L, int t) { + int ref; + t = abs_index(L, t); + if (lua_isnil(L, -1)) { + lua_pop(L, 1); /* remove from stack */ + return LUA_REFNIL; /* `nil' has a unique fixed reference */ + } + lua_rawgeti(L, t, FREELIST_REF); /* get first free element */ + ref = (int)lua_tointeger(L, -1); /* ref = t[FREELIST_REF] */ + lua_pop(L, 1); /* remove it from stack */ + if (ref != 0) { /* any free element? */ + lua_rawgeti(L, t, ref); /* remove it from list */ + lua_rawseti(L, t, FREELIST_REF); /* (t[FREELIST_REF] = t[ref]) */ + } + else { /* no free elements */ + ref = (int)lua_objlen(L, t); + ref++; /* create new reference */ + } + lua_rawseti(L, t, ref); + return ref; +} + + +LUALIB_API void luaL_unref (lua_State *L, int t, int ref) { + if (ref >= 0) { + t = abs_index(L, t); + lua_rawgeti(L, t, FREELIST_REF); + lua_rawseti(L, t, ref); /* t[ref] = t[FREELIST_REF] */ + lua_pushinteger(L, ref); + lua_rawseti(L, t, FREELIST_REF); /* t[FREELIST_REF] = ref */ + } +} + + + +/* +** {====================================================== +** Load functions +** ======================================================= +*/ + +typedef struct LoadF { + int extraline; + FILE *f; + char buff[LUAL_BUFFERSIZE]; +} LoadF; + + +static const char *getF (lua_State *L, void *ud, size_t *size) { + LoadF *lf = (LoadF *)ud; + (void)L; + if (lf->extraline) { + lf->extraline = 0; + *size = 1; + return "\n"; + } + if (feof(lf->f)) return NULL; + *size = fread(lf->buff, 1, sizeof(lf->buff), lf->f); + return (*size > 0) ? lf->buff : NULL; +} + + +static int errfile (lua_State *L, const char *what, int fnameindex) { + const char *serr = strerror(errno); + const char *filename = lua_tostring(L, fnameindex) + 1; + lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr); + lua_remove(L, fnameindex); + return LUA_ERRFILE; +} + + +LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) { + LoadF lf; + int status, readstatus; + int c; + int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */ + lf.extraline = 0; + if (filename == NULL) { + lua_pushliteral(L, "=stdin"); + lf.f = stdin; + } + else { + lua_pushfstring(L, "@%s", filename); + lf.f = fopen(filename, "r"); + if (lf.f == NULL) return errfile(L, "open", fnameindex); + } + c = getc(lf.f); + if (c == '#') { /* Unix exec. file? */ + lf.extraline = 1; + while ((c = getc(lf.f)) != EOF && c != '\n') ; /* skip first line */ + if (c == '\n') c = getc(lf.f); + } + if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */ + lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */ + if (lf.f == NULL) return errfile(L, "reopen", fnameindex); + /* skip eventual `#!...' */ + while ((c = getc(lf.f)) != EOF && c != LUA_SIGNATURE[0]) ; + lf.extraline = 0; + } + ungetc(c, lf.f); + status = lua_load(L, getF, &lf, lua_tostring(L, -1)); + readstatus = ferror(lf.f); + if (filename) fclose(lf.f); /* close file (even in case of errors) */ + if (readstatus) { + lua_settop(L, fnameindex); /* ignore results from `lua_load' */ + return errfile(L, "read", fnameindex); + } + lua_remove(L, fnameindex); + return status; +} + + +typedef struct LoadS { + const char *s; + size_t size; +} LoadS; + + +static const char *getS (lua_State *L, void *ud, size_t *size) { + LoadS *ls = (LoadS *)ud; + (void)L; + if (ls->size == 0) return NULL; + *size = ls->size; + ls->size = 0; + return ls->s; +} + + +LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size, + const char *name) { + LoadS ls; + ls.s = buff; + ls.size = size; + return lua_load(L, getS, &ls, name); +} + + +LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s) { + return luaL_loadbuffer(L, s, strlen(s), s); +} + + + +/* }====================================================== */ + + +static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { + (void)ud; + (void)osize; + if (nsize == 0) { + free(ptr); + return NULL; + } + else + return realloc(ptr, nsize); +} + + +static int panic (lua_State *L) { + (void)L; /* to avoid warnings */ + fprintf(stderr, "PANIC: unprotected error in call to Lua API (%s)\n", + lua_tostring(L, -1)); + return 0; +} + + +LUALIB_API lua_State *luaL_newstate (void) { + lua_State *L = lua_newstate(l_alloc, NULL); + if (L) lua_atpanic(L, &panic); + return L; +} + diff --git a/external/mit/lua/dist/src/lauxlib.h b/external/mit/lua/dist/src/lauxlib.h new file mode 100644 index 000000000..fefc622aa --- /dev/null +++ b/external/mit/lua/dist/src/lauxlib.h @@ -0,0 +1,176 @@ +/* $NetBSD: lauxlib.h,v 1.1.1.2 2012/03/15 00:08:08 alnsn Exp $ */ + +/* +** $Id: lauxlib.h,v 1.1.1.2 2012/03/15 00:08:08 alnsn Exp $ +** Auxiliary functions for building Lua libraries +** See Copyright Notice in lua.h +*/ + + +#ifndef lauxlib_h +#define lauxlib_h + + +#include +#include + +#include "lua.h" + + +#if defined(LUA_COMPAT_GETN) +LUALIB_API int (luaL_getn) (lua_State *L, int t); +LUALIB_API void (luaL_setn) (lua_State *L, int t, int n); +#else +#define luaL_getn(L,i) ((int)lua_objlen(L, i)) +#define luaL_setn(L,i,j) ((void)0) /* no op! */ +#endif + +#if defined(LUA_COMPAT_OPENLIB) +#define luaI_openlib luaL_openlib +#endif + + +/* extra error code for `luaL_load' */ +#define LUA_ERRFILE (LUA_ERRERR+1) + + +typedef struct luaL_Reg { + const char *name; + lua_CFunction func; +} luaL_Reg; + + + +LUALIB_API void (luaI_openlib) (lua_State *L, const char *libname, + const luaL_Reg *l, int nup); +LUALIB_API void (luaL_register) (lua_State *L, const char *libname, + const luaL_Reg *l); +LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e); +LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e); +LUALIB_API int (luaL_typerror) (lua_State *L, int narg, const char *tname); +LUALIB_API int (luaL_argerror) (lua_State *L, int numarg, const char *extramsg); +LUALIB_API const char *(luaL_checklstring) (lua_State *L, int numArg, + size_t *l); +LUALIB_API const char *(luaL_optlstring) (lua_State *L, int numArg, + const char *def, size_t *l); +LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int numArg); +LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int nArg, lua_Number def); + +LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg); +LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg, + lua_Integer def); + +LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg); +LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t); +LUALIB_API void (luaL_checkany) (lua_State *L, int narg); + +LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname); +LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname); + +LUALIB_API void (luaL_where) (lua_State *L, int lvl); +LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...); + +LUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def, + const char *const lst[]); + +LUALIB_API int (luaL_ref) (lua_State *L, int t); +LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref); + +LUALIB_API int (luaL_loadfile) (lua_State *L, const char *filename); +LUALIB_API int (luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz, + const char *name); +LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s); + +LUALIB_API lua_State *(luaL_newstate) (void); + + +LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p, + const char *r); + +LUALIB_API const char *(luaL_findtable) (lua_State *L, int idx, + const char *fname, int szhint); + + + + +/* +** =============================================================== +** some useful macros +** =============================================================== +*/ + +#define luaL_argcheck(L, cond,numarg,extramsg) \ + ((void)((cond) || luaL_argerror(L, (numarg), (extramsg)))) +#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL)) +#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL)) +#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n))) +#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d))) +#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n))) +#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d))) + +#define luaL_typename(L,i) lua_typename(L, lua_type(L,(i))) + +#define luaL_dofile(L, fn) \ + (luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0)) + +#define luaL_dostring(L, s) \ + (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0)) + +#define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n))) + +#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n))) + +/* +** {====================================================== +** Generic Buffer manipulation +** ======================================================= +*/ + + + +typedef struct luaL_Buffer { + char *p; /* current position in buffer */ + int lvl; /* number of strings in the stack (level) */ + lua_State *L; + char buffer[LUAL_BUFFERSIZE]; +} luaL_Buffer; + +#define luaL_addchar(B,c) \ + ((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \ + (*(B)->p++ = (char)(c))) + +/* compatibility only */ +#define luaL_putchar(B,c) luaL_addchar(B,c) + +#define luaL_addsize(B,n) ((B)->p += (n)) + +LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B); +LUALIB_API char *(luaL_prepbuffer) (luaL_Buffer *B); +LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l); +LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s); +LUALIB_API void (luaL_addvalue) (luaL_Buffer *B); +LUALIB_API void (luaL_pushresult) (luaL_Buffer *B); + + +/* }====================================================== */ + + +/* compatibility with ref system */ + +/* pre-defined references */ +#define LUA_NOREF (-2) +#define LUA_REFNIL (-1) + +#define lua_ref(L,lock) ((lock) ? luaL_ref(L, LUA_REGISTRYINDEX) : \ + (lua_pushstring(L, "unlocked references are obsolete"), lua_error(L), 0)) + +#define lua_unref(L,ref) luaL_unref(L, LUA_REGISTRYINDEX, (ref)) + +#define lua_getref(L,ref) lua_rawgeti(L, LUA_REGISTRYINDEX, (ref)) + + +#define luaL_reg luaL_Reg + +#endif + + diff --git a/external/mit/lua/dist/src/lbaselib.c b/external/mit/lua/dist/src/lbaselib.c new file mode 100644 index 000000000..db9f75efb --- /dev/null +++ b/external/mit/lua/dist/src/lbaselib.c @@ -0,0 +1,655 @@ +/* $NetBSD: lbaselib.c,v 1.1.1.2 2012/03/15 00:08:06 alnsn Exp $ */ + +/* +** $Id: lbaselib.c,v 1.1.1.2 2012/03/15 00:08:06 alnsn Exp $ +** Basic library +** See Copyright Notice in lua.h +*/ + + + +#include +#include +#include +#include + +#define lbaselib_c +#define LUA_LIB + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + + + +/* +** If your system does not support `stdout', you can just remove this function. +** If you need, you can define your own `print' function, following this +** model but changing `fputs' to put the strings at a proper place +** (a console window or a log file, for instance). +*/ +static int luaB_print (lua_State *L) { + int n = lua_gettop(L); /* number of arguments */ + int i; + lua_getglobal(L, "tostring"); + for (i=1; i<=n; i++) { + const char *s; + lua_pushvalue(L, -1); /* function to be called */ + lua_pushvalue(L, i); /* value to print */ + lua_call(L, 1, 1); + s = lua_tostring(L, -1); /* get result */ + if (s == NULL) + return luaL_error(L, LUA_QL("tostring") " must return a string to " + LUA_QL("print")); + if (i>1) fputs("\t", stdout); + fputs(s, stdout); + lua_pop(L, 1); /* pop result */ + } + fputs("\n", stdout); + return 0; +} + + +static int luaB_tonumber (lua_State *L) { + int base = luaL_optint(L, 2, 10); + if (base == 10) { /* standard conversion */ + luaL_checkany(L, 1); + if (lua_isnumber(L, 1)) { + lua_pushnumber(L, lua_tonumber(L, 1)); + return 1; + } + } + else { + const char *s1 = luaL_checkstring(L, 1); + char *s2; + unsigned long n; + luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range"); + n = strtoul(s1, &s2, base); + if (s1 != s2) { /* at least one valid digit? */ + while (isspace((unsigned char)(*s2))) s2++; /* skip trailing spaces */ + if (*s2 == '\0') { /* no invalid trailing characters? */ + lua_pushnumber(L, (lua_Number)n); + return 1; + } + } + } + lua_pushnil(L); /* else not a number */ + return 1; +} + + +static int luaB_error (lua_State *L) { + int level = luaL_optint(L, 2, 1); + lua_settop(L, 1); + if (lua_isstring(L, 1) && level > 0) { /* add extra information? */ + luaL_where(L, level); + lua_pushvalue(L, 1); + lua_concat(L, 2); + } + return lua_error(L); +} + + +static int luaB_getmetatable (lua_State *L) { + luaL_checkany(L, 1); + if (!lua_getmetatable(L, 1)) { + lua_pushnil(L); + return 1; /* no metatable */ + } + luaL_getmetafield(L, 1, "__metatable"); + return 1; /* returns either __metatable field (if present) or metatable */ +} + + +static int luaB_setmetatable (lua_State *L) { + int t = lua_type(L, 2); + luaL_checktype(L, 1, LUA_TTABLE); + luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2, + "nil or table expected"); + if (luaL_getmetafield(L, 1, "__metatable")) + luaL_error(L, "cannot change a protected metatable"); + lua_settop(L, 2); + lua_setmetatable(L, 1); + return 1; +} + + +static void getfunc (lua_State *L, int opt) { + if (lua_isfunction(L, 1)) lua_pushvalue(L, 1); + else { + lua_Debug ar; + int level = opt ? luaL_optint(L, 1, 1) : luaL_checkint(L, 1); + luaL_argcheck(L, level >= 0, 1, "level must be non-negative"); + if (lua_getstack(L, level, &ar) == 0) + luaL_argerror(L, 1, "invalid level"); + lua_getinfo(L, "f", &ar); + if (lua_isnil(L, -1)) + luaL_error(L, "no function environment for tail call at level %d", + level); + } +} + + +static int luaB_getfenv (lua_State *L) { + getfunc(L, 1); + if (lua_iscfunction(L, -1)) /* is a C function? */ + lua_pushvalue(L, LUA_GLOBALSINDEX); /* return the thread's global env. */ + else + lua_getfenv(L, -1); + return 1; +} + + +static int luaB_setfenv (lua_State *L) { + luaL_checktype(L, 2, LUA_TTABLE); + getfunc(L, 0); + lua_pushvalue(L, 2); + if (lua_isnumber(L, 1) && lua_tonumber(L, 1) == 0) { + /* change environment of current thread */ + lua_pushthread(L); + lua_insert(L, -2); + lua_setfenv(L, -2); + return 0; + } + else if (lua_iscfunction(L, -2) || lua_setfenv(L, -2) == 0) + luaL_error(L, + LUA_QL("setfenv") " cannot change environment of given object"); + return 1; +} + + +static int luaB_rawequal (lua_State *L) { + luaL_checkany(L, 1); + luaL_checkany(L, 2); + lua_pushboolean(L, lua_rawequal(L, 1, 2)); + return 1; +} + + +static int luaB_rawget (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + luaL_checkany(L, 2); + lua_settop(L, 2); + lua_rawget(L, 1); + return 1; +} + +static int luaB_rawset (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + luaL_checkany(L, 2); + luaL_checkany(L, 3); + lua_settop(L, 3); + lua_rawset(L, 1); + return 1; +} + + +static int luaB_gcinfo (lua_State *L) { + lua_pushinteger(L, lua_getgccount(L)); + return 1; +} + + +static int luaB_collectgarbage (lua_State *L) { + static const char *const opts[] = {"stop", "restart", "collect", + "count", "step", "setpause", "setstepmul", NULL}; + static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT, + LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL}; + int o = luaL_checkoption(L, 1, "collect", opts); + int ex = luaL_optint(L, 2, 0); + int res = lua_gc(L, optsnum[o], ex); + switch (optsnum[o]) { + case LUA_GCCOUNT: { + int b = lua_gc(L, LUA_GCCOUNTB, 0); + lua_pushnumber(L, res + ((lua_Number)b/1024)); + return 1; + } + case LUA_GCSTEP: { + lua_pushboolean(L, res); + return 1; + } + default: { + lua_pushnumber(L, res); + return 1; + } + } +} + + +static int luaB_type (lua_State *L) { + luaL_checkany(L, 1); + lua_pushstring(L, luaL_typename(L, 1)); + return 1; +} + + +static int luaB_next (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + lua_settop(L, 2); /* create a 2nd argument if there isn't one */ + if (lua_next(L, 1)) + return 2; + else { + lua_pushnil(L); + return 1; + } +} + + +static int luaB_pairs (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + lua_pushvalue(L, lua_upvalueindex(1)); /* return generator, */ + lua_pushvalue(L, 1); /* state, */ + lua_pushnil(L); /* and initial value */ + return 3; +} + + +static int ipairsaux (lua_State *L) { + int i = luaL_checkint(L, 2); + luaL_checktype(L, 1, LUA_TTABLE); + i++; /* next value */ + lua_pushinteger(L, i); + lua_rawgeti(L, 1, i); + return (lua_isnil(L, -1)) ? 0 : 2; +} + + +static int luaB_ipairs (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + lua_pushvalue(L, lua_upvalueindex(1)); /* return generator, */ + lua_pushvalue(L, 1); /* state, */ + lua_pushinteger(L, 0); /* and initial value */ + return 3; +} + + +static int load_aux (lua_State *L, int status) { + if (status == 0) /* OK? */ + return 1; + else { + lua_pushnil(L); + lua_insert(L, -2); /* put before error message */ + return 2; /* return nil plus error message */ + } +} + + +static int luaB_loadstring (lua_State *L) { + size_t l; + const char *s = luaL_checklstring(L, 1, &l); + const char *chunkname = luaL_optstring(L, 2, s); + return load_aux(L, luaL_loadbuffer(L, s, l, chunkname)); +} + + +static int luaB_loadfile (lua_State *L) { + const char *fname = luaL_optstring(L, 1, NULL); + return load_aux(L, luaL_loadfile(L, fname)); +} + + +/* +** Reader for generic `load' function: `lua_load' uses the +** stack for internal stuff, so the reader cannot change the +** stack top. Instead, it keeps its resulting string in a +** reserved slot inside the stack. +*/ +static const char *generic_reader (lua_State *L, void *ud, size_t *size) { + (void)ud; /* to avoid warnings */ + luaL_checkstack(L, 2, "too many nested functions"); + lua_pushvalue(L, 1); /* get function */ + lua_call(L, 0, 1); /* call it */ + if (lua_isnil(L, -1)) { + *size = 0; + return NULL; + } + else if (lua_isstring(L, -1)) { + lua_replace(L, 3); /* save string in a reserved stack slot */ + return lua_tolstring(L, 3, size); + } + else luaL_error(L, "reader function must return a string"); + return NULL; /* to avoid warnings */ +} + + +static int luaB_load (lua_State *L) { + int status; + const char *cname = luaL_optstring(L, 2, "=(load)"); + luaL_checktype(L, 1, LUA_TFUNCTION); + lua_settop(L, 3); /* function, eventual name, plus one reserved slot */ + status = lua_load(L, generic_reader, NULL, cname); + return load_aux(L, status); +} + + +static int luaB_dofile (lua_State *L) { + const char *fname = luaL_optstring(L, 1, NULL); + int n = lua_gettop(L); + if (luaL_loadfile(L, fname) != 0) lua_error(L); + lua_call(L, 0, LUA_MULTRET); + return lua_gettop(L) - n; +} + + +static int luaB_assert (lua_State *L) { + luaL_checkany(L, 1); + if (!lua_toboolean(L, 1)) + return luaL_error(L, "%s", luaL_optstring(L, 2, "assertion failed!")); + return lua_gettop(L); +} + + +static int luaB_unpack (lua_State *L) { + int i, e, n; + luaL_checktype(L, 1, LUA_TTABLE); + i = luaL_optint(L, 2, 1); + e = luaL_opt(L, luaL_checkint, 3, luaL_getn(L, 1)); + if (i > e) return 0; /* empty range */ + n = e - i + 1; /* number of elements */ + if (n <= 0 || !lua_checkstack(L, n)) /* n <= 0 means arith. overflow */ + return luaL_error(L, "too many results to unpack"); + lua_rawgeti(L, 1, i); /* push arg[i] (avoiding overflow problems) */ + while (i++ < e) /* push arg[i + 1...e] */ + lua_rawgeti(L, 1, i); + return n; +} + + +static int luaB_select (lua_State *L) { + int n = lua_gettop(L); + if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') { + lua_pushinteger(L, n-1); + return 1; + } + else { + int i = luaL_checkint(L, 1); + if (i < 0) i = n + i; + else if (i > n) i = n; + luaL_argcheck(L, 1 <= i, 1, "index out of range"); + return n - i; + } +} + + +static int luaB_pcall (lua_State *L) { + int status; + luaL_checkany(L, 1); + status = lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0); + lua_pushboolean(L, (status == 0)); + lua_insert(L, 1); + return lua_gettop(L); /* return status + all results */ +} + + +static int luaB_xpcall (lua_State *L) { + int status; + luaL_checkany(L, 2); + lua_settop(L, 2); + lua_insert(L, 1); /* put error function under function to be called */ + status = lua_pcall(L, 0, LUA_MULTRET, 1); + lua_pushboolean(L, (status == 0)); + lua_replace(L, 1); + return lua_gettop(L); /* return status + all results */ +} + + +static int luaB_tostring (lua_State *L) { + luaL_checkany(L, 1); + if (luaL_callmeta(L, 1, "__tostring")) /* is there a metafield? */ + return 1; /* use its value */ + switch (lua_type(L, 1)) { + case LUA_TNUMBER: + lua_pushstring(L, lua_tostring(L, 1)); + break; + case LUA_TSTRING: + lua_pushvalue(L, 1); + break; + case LUA_TBOOLEAN: + lua_pushstring(L, (lua_toboolean(L, 1) ? "true" : "false")); + break; + case LUA_TNIL: + lua_pushliteral(L, "nil"); + break; + default: + lua_pushfstring(L, "%s: %p", luaL_typename(L, 1), lua_topointer(L, 1)); + break; + } + return 1; +} + + +static int luaB_newproxy (lua_State *L) { + lua_settop(L, 1); + lua_newuserdata(L, 0); /* create proxy */ + if (lua_toboolean(L, 1) == 0) + return 1; /* no metatable */ + else if (lua_isboolean(L, 1)) { + lua_newtable(L); /* create a new metatable `m' ... */ + lua_pushvalue(L, -1); /* ... and mark `m' as a valid metatable */ + lua_pushboolean(L, 1); + lua_rawset(L, lua_upvalueindex(1)); /* weaktable[m] = true */ + } + else { + int validproxy = 0; /* to check if weaktable[metatable(u)] == true */ + if (lua_getmetatable(L, 1)) { + lua_rawget(L, lua_upvalueindex(1)); + validproxy = lua_toboolean(L, -1); + lua_pop(L, 1); /* remove value */ + } + luaL_argcheck(L, validproxy, 1, "boolean or proxy expected"); + lua_getmetatable(L, 1); /* metatable is valid; get it */ + } + lua_setmetatable(L, 2); + return 1; +} + + +static const luaL_Reg base_funcs[] = { + {"assert", luaB_assert}, + {"collectgarbage", luaB_collectgarbage}, + {"dofile", luaB_dofile}, + {"error", luaB_error}, + {"gcinfo", luaB_gcinfo}, + {"getfenv", luaB_getfenv}, + {"getmetatable", luaB_getmetatable}, + {"loadfile", luaB_loadfile}, + {"load", luaB_load}, + {"loadstring", luaB_loadstring}, + {"next", luaB_next}, + {"pcall", luaB_pcall}, + {"print", luaB_print}, + {"rawequal", luaB_rawequal}, + {"rawget", luaB_rawget}, + {"rawset", luaB_rawset}, + {"select", luaB_select}, + {"setfenv", luaB_setfenv}, + {"setmetatable", luaB_setmetatable}, + {"tonumber", luaB_tonumber}, + {"tostring", luaB_tostring}, + {"type", luaB_type}, + {"unpack", luaB_unpack}, + {"xpcall", luaB_xpcall}, + {NULL, NULL} +}; + + +/* +** {====================================================== +** Coroutine library +** ======================================================= +*/ + +#define CO_RUN 0 /* running */ +#define CO_SUS 1 /* suspended */ +#define CO_NOR 2 /* 'normal' (it resumed another coroutine) */ +#define CO_DEAD 3 + +static const char *const statnames[] = + {"running", "suspended", "normal", "dead"}; + +static int costatus (lua_State *L, lua_State *co) { + if (L == co) return CO_RUN; + switch (lua_status(co)) { + case LUA_YIELD: + return CO_SUS; + case 0: { + lua_Debug ar; + if (lua_getstack(co, 0, &ar) > 0) /* does it have frames? */ + return CO_NOR; /* it is running */ + else if (lua_gettop(co) == 0) + return CO_DEAD; + else + return CO_SUS; /* initial state */ + } + default: /* some error occured */ + return CO_DEAD; + } +} + + +static int luaB_costatus (lua_State *L) { + lua_State *co = lua_tothread(L, 1); + luaL_argcheck(L, co, 1, "coroutine expected"); + lua_pushstring(L, statnames[costatus(L, co)]); + return 1; +} + + +static int auxresume (lua_State *L, lua_State *co, int narg) { + int status = costatus(L, co); + if (!lua_checkstack(co, narg)) + luaL_error(L, "too many arguments to resume"); + if (status != CO_SUS) { + lua_pushfstring(L, "cannot resume %s coroutine", statnames[status]); + return -1; /* error flag */ + } + lua_xmove(L, co, narg); + lua_setlevel(L, co); + status = lua_resume(co, narg); + if (status == 0 || status == LUA_YIELD) { + int nres = lua_gettop(co); + if (!lua_checkstack(L, nres + 1)) + luaL_error(L, "too many results to resume"); + lua_xmove(co, L, nres); /* move yielded values */ + return nres; + } + else { + lua_xmove(co, L, 1); /* move error message */ + return -1; /* error flag */ + } +} + + +static int luaB_coresume (lua_State *L) { + lua_State *co = lua_tothread(L, 1); + int r; + luaL_argcheck(L, co, 1, "coroutine expected"); + r = auxresume(L, co, lua_gettop(L) - 1); + if (r < 0) { + lua_pushboolean(L, 0); + lua_insert(L, -2); + return 2; /* return false + error message */ + } + else { + lua_pushboolean(L, 1); + lua_insert(L, -(r + 1)); + return r + 1; /* return true + `resume' returns */ + } +} + + +static int luaB_auxwrap (lua_State *L) { + lua_State *co = lua_tothread(L, lua_upvalueindex(1)); + int r = auxresume(L, co, lua_gettop(L)); + if (r < 0) { + if (lua_isstring(L, -1)) { /* error object is a string? */ + luaL_where(L, 1); /* add extra info */ + lua_insert(L, -2); + lua_concat(L, 2); + } + lua_error(L); /* propagate error */ + } + return r; +} + + +static int luaB_cocreate (lua_State *L) { + lua_State *NL = lua_newthread(L); + luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1, + "Lua function expected"); + lua_pushvalue(L, 1); /* move function to top */ + lua_xmove(L, NL, 1); /* move function from L to NL */ + return 1; +} + + +static int luaB_cowrap (lua_State *L) { + luaB_cocreate(L); + lua_pushcclosure(L, luaB_auxwrap, 1); + return 1; +} + + +static int luaB_yield (lua_State *L) { + return lua_yield(L, lua_gettop(L)); +} + + +static int luaB_corunning (lua_State *L) { + if (lua_pushthread(L)) + lua_pushnil(L); /* main thread is not a coroutine */ + return 1; +} + + +static const luaL_Reg co_funcs[] = { + {"create", luaB_cocreate}, + {"resume", luaB_coresume}, + {"running", luaB_corunning}, + {"status", luaB_costatus}, + {"wrap", luaB_cowrap}, + {"yield", luaB_yield}, + {NULL, NULL} +}; + +/* }====================================================== */ + + +static void auxopen (lua_State *L, const char *name, + lua_CFunction f, lua_CFunction u) { + lua_pushcfunction(L, u); + lua_pushcclosure(L, f, 1); + lua_setfield(L, -2, name); +} + + +static void base_open (lua_State *L) { + /* set global _G */ + lua_pushvalue(L, LUA_GLOBALSINDEX); + lua_setglobal(L, "_G"); + /* open lib into global table */ + luaL_register(L, "_G", base_funcs); + lua_pushliteral(L, LUA_VERSION); + lua_setglobal(L, "_VERSION"); /* set global _VERSION */ + /* `ipairs' and `pairs' need auxiliary functions as upvalues */ + auxopen(L, "ipairs", luaB_ipairs, ipairsaux); + auxopen(L, "pairs", luaB_pairs, luaB_next); + /* `newproxy' needs a weaktable as upvalue */ + lua_createtable(L, 0, 1); /* new table `w' */ + lua_pushvalue(L, -1); /* `w' will be its own metatable */ + lua_setmetatable(L, -2); + lua_pushliteral(L, "kv"); + lua_setfield(L, -2, "__mode"); /* metatable(w).__mode = "kv" */ + lua_pushcclosure(L, luaB_newproxy, 1); + lua_setglobal(L, "newproxy"); /* set global `newproxy' */ +} + + +LUALIB_API int luaopen_base (lua_State *L) { + base_open(L); + luaL_register(L, LUA_COLIBNAME, co_funcs); + return 2; +} + diff --git a/external/mit/lua/dist/src/lcode.c b/external/mit/lua/dist/src/lcode.c new file mode 100644 index 000000000..e697e60be --- /dev/null +++ b/external/mit/lua/dist/src/lcode.c @@ -0,0 +1,833 @@ +/* $NetBSD: lcode.c,v 1.1.1.2 2012/03/15 00:08:11 alnsn Exp $ */ + +/* +** $Id: lcode.c,v 1.1.1.2 2012/03/15 00:08:11 alnsn Exp $ +** Code generator for Lua +** See Copyright Notice in lua.h +*/ + + +#include + +#define lcode_c +#define LUA_CORE + +#include "lua.h" + +#include "lcode.h" +#include "ldebug.h" +#include "ldo.h" +#include "lgc.h" +#include "llex.h" +#include "lmem.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lparser.h" +#include "ltable.h" + + +#define hasjumps(e) ((e)->t != (e)->f) + + +static int isnumeral(expdesc *e) { + return (e->k == VKNUM && e->t == NO_JUMP && e->f == NO_JUMP); +} + + +void luaK_nil (FuncState *fs, int from, int n) { + Instruction *previous; + if (fs->pc > fs->lasttarget) { /* no jumps to current position? */ + if (fs->pc == 0) { /* function start? */ + if (from >= fs->nactvar) + return; /* positions are already clean */ + } + else { + previous = &fs->f->code[fs->pc-1]; + if (GET_OPCODE(*previous) == OP_LOADNIL) { + int pfrom = GETARG_A(*previous); + int pto = GETARG_B(*previous); + if (pfrom <= from && from <= pto+1) { /* can connect both? */ + if (from+n-1 > pto) + SETARG_B(*previous, from+n-1); + return; + } + } + } + } + luaK_codeABC(fs, OP_LOADNIL, from, from+n-1, 0); /* else no optimization */ +} + + +int luaK_jump (FuncState *fs) { + int jpc = fs->jpc; /* save list of jumps to here */ + int j; + fs->jpc = NO_JUMP; + j = luaK_codeAsBx(fs, OP_JMP, 0, NO_JUMP); + luaK_concat(fs, &j, jpc); /* keep them on hold */ + return j; +} + + +void luaK_ret (FuncState *fs, int first, int nret) { + luaK_codeABC(fs, OP_RETURN, first, nret+1, 0); +} + + +static int condjump (FuncState *fs, OpCode op, int A, int B, int C) { + luaK_codeABC(fs, op, A, B, C); + return luaK_jump(fs); +} + + +static void fixjump (FuncState *fs, int pc, int dest) { + Instruction *jmp = &fs->f->code[pc]; + int offset = dest-(pc+1); + lua_assert(dest != NO_JUMP); + if (abs(offset) > MAXARG_sBx) + luaX_syntaxerror(fs->ls, "control structure too long"); + SETARG_sBx(*jmp, offset); +} + + +/* +** returns current `pc' and marks it as a jump target (to avoid wrong +** optimizations with consecutive instructions not in the same basic block). +*/ +int luaK_getlabel (FuncState *fs) { + fs->lasttarget = fs->pc; + return fs->pc; +} + + +static int getjump (FuncState *fs, int pc) { + int offset = GETARG_sBx(fs->f->code[pc]); + if (offset == NO_JUMP) /* point to itself represents end of list */ + return NO_JUMP; /* end of list */ + else + return (pc+1)+offset; /* turn offset into absolute position */ +} + + +static Instruction *getjumpcontrol (FuncState *fs, int pc) { + Instruction *pi = &fs->f->code[pc]; + if (pc >= 1 && testTMode(GET_OPCODE(*(pi-1)))) + return pi-1; + else + return pi; +} + + +/* +** check whether list has any jump that do not produce a value +** (or produce an inverted value) +*/ +static int need_value (FuncState *fs, int list) { + for (; list != NO_JUMP; list = getjump(fs, list)) { + Instruction i = *getjumpcontrol(fs, list); + if (GET_OPCODE(i) != OP_TESTSET) return 1; + } + return 0; /* not found */ +} + + +static int patchtestreg (FuncState *fs, int node, int reg) { + Instruction *i = getjumpcontrol(fs, node); + if (GET_OPCODE(*i) != OP_TESTSET) + return 0; /* cannot patch other instructions */ + if (reg != NO_REG && reg != GETARG_B(*i)) + SETARG_A(*i, reg); + else /* no register to put value or register already has the value */ + *i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i)); + + return 1; +} + + +static void removevalues (FuncState *fs, int list) { + for (; list != NO_JUMP; list = getjump(fs, list)) + patchtestreg(fs, list, NO_REG); +} + + +static void patchlistaux (FuncState *fs, int list, int vtarget, int reg, + int dtarget) { + while (list != NO_JUMP) { + int next = getjump(fs, list); + if (patchtestreg(fs, list, reg)) + fixjump(fs, list, vtarget); + else + fixjump(fs, list, dtarget); /* jump to default target */ + list = next; + } +} + + +static void dischargejpc (FuncState *fs) { + patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc); + fs->jpc = NO_JUMP; +} + + +void luaK_patchlist (FuncState *fs, int list, int target) { + if (target == fs->pc) + luaK_patchtohere(fs, list); + else { + lua_assert(target < fs->pc); + patchlistaux(fs, list, target, NO_REG, target); + } +} + + +void luaK_patchtohere (FuncState *fs, int list) { + luaK_getlabel(fs); + luaK_concat(fs, &fs->jpc, list); +} + + +void luaK_concat (FuncState *fs, int *l1, int l2) { + if (l2 == NO_JUMP) return; + else if (*l1 == NO_JUMP) + *l1 = l2; + else { + int list = *l1; + int next; + while ((next = getjump(fs, list)) != NO_JUMP) /* find last element */ + list = next; + fixjump(fs, list, l2); + } +} + + +void luaK_checkstack (FuncState *fs, int n) { + int newstack = fs->freereg + n; + if (newstack > fs->f->maxstacksize) { + if (newstack >= MAXSTACK) + luaX_syntaxerror(fs->ls, "function or expression too complex"); + fs->f->maxstacksize = cast_byte(newstack); + } +} + + +void luaK_reserveregs (FuncState *fs, int n) { + luaK_checkstack(fs, n); + fs->freereg += n; +} + + +static void freereg (FuncState *fs, int reg) { + if (!ISK(reg) && reg >= fs->nactvar) { + fs->freereg--; + lua_assert(reg == fs->freereg); + } +} + + +static void freeexp (FuncState *fs, expdesc *e) { + if (e->k == VNONRELOC) + freereg(fs, e->u.s.info); +} + + +static int addk (FuncState *fs, TValue *k, TValue *v) { + lua_State *L = fs->L; + TValue *idx = luaH_set(L, fs->h, k); + Proto *f = fs->f; + int oldsize = f->sizek; + if (ttisnumber(idx)) { + lua_assert(luaO_rawequalObj(&fs->f->k[cast_int(nvalue(idx))], v)); + return cast_int(nvalue(idx)); + } + else { /* constant not found; create a new entry */ + setnvalue(idx, cast_num(fs->nk)); + luaM_growvector(L, f->k, fs->nk, f->sizek, TValue, + MAXARG_Bx, "constant table overflow"); + while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); + setobj(L, &f->k[fs->nk], v); + luaC_barrier(L, f, v); + return fs->nk++; + } +} + + +int luaK_stringK (FuncState *fs, TString *s) { + TValue o; + setsvalue(fs->L, &o, s); + return addk(fs, &o, &o); +} + + +int luaK_numberK (FuncState *fs, lua_Number r) { + TValue o; + setnvalue(&o, r); + return addk(fs, &o, &o); +} + + +static int boolK (FuncState *fs, int b) { + TValue o; + setbvalue(&o, b); + return addk(fs, &o, &o); +} + + +static int nilK (FuncState *fs) { + TValue k, v; + setnilvalue(&v); + /* cannot use nil as key; instead use table itself to represent nil */ + sethvalue(fs->L, &k, fs->h); + return addk(fs, &k, &v); +} + + +void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) { + if (e->k == VCALL) { /* expression is an open function call? */ + SETARG_C(getcode(fs, e), nresults+1); + } + else if (e->k == VVARARG) { + SETARG_B(getcode(fs, e), nresults+1); + SETARG_A(getcode(fs, e), fs->freereg); + luaK_reserveregs(fs, 1); + } +} + + +void luaK_setoneret (FuncState *fs, expdesc *e) { + if (e->k == VCALL) { /* expression is an open function call? */ + e->k = VNONRELOC; + e->u.s.info = GETARG_A(getcode(fs, e)); + } + else if (e->k == VVARARG) { + SETARG_B(getcode(fs, e), 2); + e->k = VRELOCABLE; /* can relocate its simple result */ + } +} + + +void luaK_dischargevars (FuncState *fs, expdesc *e) { + switch (e->k) { + case VLOCAL: { + e->k = VNONRELOC; + break; + } + case VUPVAL: { + e->u.s.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.s.info, 0); + e->k = VRELOCABLE; + break; + } + case VGLOBAL: { + e->u.s.info = luaK_codeABx(fs, OP_GETGLOBAL, 0, e->u.s.info); + e->k = VRELOCABLE; + break; + } + case VINDEXED: { + freereg(fs, e->u.s.aux); + freereg(fs, e->u.s.info); + e->u.s.info = luaK_codeABC(fs, OP_GETTABLE, 0, e->u.s.info, e->u.s.aux); + e->k = VRELOCABLE; + break; + } + case VVARARG: + case VCALL: { + luaK_setoneret(fs, e); + break; + } + default: break; /* there is one value available (somewhere) */ + } +} + + +static int code_label (FuncState *fs, int A, int b, int jump) { + luaK_getlabel(fs); /* those instructions may be jump targets */ + return luaK_codeABC(fs, OP_LOADBOOL, A, b, jump); +} + + +static void discharge2reg (FuncState *fs, expdesc *e, int reg) { + luaK_dischargevars(fs, e); + switch (e->k) { + case VNIL: { + luaK_nil(fs, reg, 1); + break; + } + case VFALSE: case VTRUE: { + luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0); + break; + } + case VK: { + luaK_codeABx(fs, OP_LOADK, reg, e->u.s.info); + break; + } + case VKNUM: { + luaK_codeABx(fs, OP_LOADK, reg, luaK_numberK(fs, e->u.nval)); + break; + } + case VRELOCABLE: { + Instruction *pc = &getcode(fs, e); + SETARG_A(*pc, reg); + break; + } + case VNONRELOC: { + if (reg != e->u.s.info) + luaK_codeABC(fs, OP_MOVE, reg, e->u.s.info, 0); + break; + } + default: { + lua_assert(e->k == VVOID || e->k == VJMP); + return; /* nothing to do... */ + } + } + e->u.s.info = reg; + e->k = VNONRELOC; +} + + +static void discharge2anyreg (FuncState *fs, expdesc *e) { + if (e->k != VNONRELOC) { + luaK_reserveregs(fs, 1); + discharge2reg(fs, e, fs->freereg-1); + } +} + + +static void exp2reg (FuncState *fs, expdesc *e, int reg) { + discharge2reg(fs, e, reg); + if (e->k == VJMP) + luaK_concat(fs, &e->t, e->u.s.info); /* put this jump in `t' list */ + if (hasjumps(e)) { + int final; /* position after whole expression */ + int p_f = NO_JUMP; /* position of an eventual LOAD false */ + int p_t = NO_JUMP; /* position of an eventual LOAD true */ + if (need_value(fs, e->t) || need_value(fs, e->f)) { + int fj = (e->k == VJMP) ? NO_JUMP : luaK_jump(fs); + p_f = code_label(fs, reg, 0, 1); + p_t = code_label(fs, reg, 1, 0); + luaK_patchtohere(fs, fj); + } + final = luaK_getlabel(fs); + patchlistaux(fs, e->f, final, reg, p_f); + patchlistaux(fs, e->t, final, reg, p_t); + } + e->f = e->t = NO_JUMP; + e->u.s.info = reg; + e->k = VNONRELOC; +} + + +void luaK_exp2nextreg (FuncState *fs, expdesc *e) { + luaK_dischargevars(fs, e); + freeexp(fs, e); + luaK_reserveregs(fs, 1); + exp2reg(fs, e, fs->freereg - 1); +} + + +int luaK_exp2anyreg (FuncState *fs, expdesc *e) { + luaK_dischargevars(fs, e); + if (e->k == VNONRELOC) { + if (!hasjumps(e)) return e->u.s.info; /* exp is already in a register */ + if (e->u.s.info >= fs->nactvar) { /* reg. is not a local? */ + exp2reg(fs, e, e->u.s.info); /* put value on it */ + return e->u.s.info; + } + } + luaK_exp2nextreg(fs, e); /* default */ + return e->u.s.info; +} + + +void luaK_exp2val (FuncState *fs, expdesc *e) { + if (hasjumps(e)) + luaK_exp2anyreg(fs, e); + else + luaK_dischargevars(fs, e); +} + + +int luaK_exp2RK (FuncState *fs, expdesc *e) { + luaK_exp2val(fs, e); + switch (e->k) { + case VKNUM: + case VTRUE: + case VFALSE: + case VNIL: { + if (fs->nk <= MAXINDEXRK) { /* constant fit in RK operand? */ + e->u.s.info = (e->k == VNIL) ? nilK(fs) : + (e->k == VKNUM) ? luaK_numberK(fs, e->u.nval) : + boolK(fs, (e->k == VTRUE)); + e->k = VK; + return RKASK(e->u.s.info); + } + else break; + } + case VK: { + if (e->u.s.info <= MAXINDEXRK) /* constant fit in argC? */ + return RKASK(e->u.s.info); + else break; + } + default: break; + } + /* not a constant in the right range: put it in a register */ + return luaK_exp2anyreg(fs, e); +} + + +void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) { + switch (var->k) { + case VLOCAL: { + freeexp(fs, ex); + exp2reg(fs, ex, var->u.s.info); + return; + } + case VUPVAL: { + int e = luaK_exp2anyreg(fs, ex); + luaK_codeABC(fs, OP_SETUPVAL, e, var->u.s.info, 0); + break; + } + case VGLOBAL: { + int e = luaK_exp2anyreg(fs, ex); + luaK_codeABx(fs, OP_SETGLOBAL, e, var->u.s.info); + break; + } + case VINDEXED: { + int e = luaK_exp2RK(fs, ex); + luaK_codeABC(fs, OP_SETTABLE, var->u.s.info, var->u.s.aux, e); + break; + } + default: { + lua_assert(0); /* invalid var kind to store */ + break; + } + } + freeexp(fs, ex); +} + + +void luaK_self (FuncState *fs, expdesc *e, expdesc *key) { + int func; + luaK_exp2anyreg(fs, e); + freeexp(fs, e); + func = fs->freereg; + luaK_reserveregs(fs, 2); + luaK_codeABC(fs, OP_SELF, func, e->u.s.info, luaK_exp2RK(fs, key)); + freeexp(fs, key); + e->u.s.info = func; + e->k = VNONRELOC; +} + + +static void invertjump (FuncState *fs, expdesc *e) { + Instruction *pc = getjumpcontrol(fs, e->u.s.info); + lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET && + GET_OPCODE(*pc) != OP_TEST); + SETARG_A(*pc, !(GETARG_A(*pc))); +} + + +static int jumponcond (FuncState *fs, expdesc *e, int cond) { + if (e->k == VRELOCABLE) { + Instruction ie = getcode(fs, e); + if (GET_OPCODE(ie) == OP_NOT) { + fs->pc--; /* remove previous OP_NOT */ + return condjump(fs, OP_TEST, GETARG_B(ie), 0, !cond); + } + /* else go through */ + } + discharge2anyreg(fs, e); + freeexp(fs, e); + return condjump(fs, OP_TESTSET, NO_REG, e->u.s.info, cond); +} + + +void luaK_goiftrue (FuncState *fs, expdesc *e) { + int pc; /* pc of last jump */ + luaK_dischargevars(fs, e); + switch (e->k) { + case VK: case VKNUM: case VTRUE: { + pc = NO_JUMP; /* always true; do nothing */ + break; + } + case VJMP: { + invertjump(fs, e); + pc = e->u.s.info; + break; + } + default: { + pc = jumponcond(fs, e, 0); + break; + } + } + luaK_concat(fs, &e->f, pc); /* insert last jump in `f' list */ + luaK_patchtohere(fs, e->t); + e->t = NO_JUMP; +} + + +static void luaK_goiffalse (FuncState *fs, expdesc *e) { + int pc; /* pc of last jump */ + luaK_dischargevars(fs, e); + switch (e->k) { + case VNIL: case VFALSE: { + pc = NO_JUMP; /* always false; do nothing */ + break; + } + case VJMP: { + pc = e->u.s.info; + break; + } + default: { + pc = jumponcond(fs, e, 1); + break; + } + } + luaK_concat(fs, &e->t, pc); /* insert last jump in `t' list */ + luaK_patchtohere(fs, e->f); + e->f = NO_JUMP; +} + + +static void codenot (FuncState *fs, expdesc *e) { + luaK_dischargevars(fs, e); + switch (e->k) { + case VNIL: case VFALSE: { + e->k = VTRUE; + break; + } + case VK: case VKNUM: case VTRUE: { + e->k = VFALSE; + break; + } + case VJMP: { + invertjump(fs, e); + break; + } + case VRELOCABLE: + case VNONRELOC: { + discharge2anyreg(fs, e); + freeexp(fs, e); + e->u.s.info = luaK_codeABC(fs, OP_NOT, 0, e->u.s.info, 0); + e->k = VRELOCABLE; + break; + } + default: { + lua_assert(0); /* cannot happen */ + break; + } + } + /* interchange true and false lists */ + { int temp = e->f; e->f = e->t; e->t = temp; } + removevalues(fs, e->f); + removevalues(fs, e->t); +} + + +void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { + t->u.s.aux = luaK_exp2RK(fs, k); + t->k = VINDEXED; +} + + +static int constfolding (OpCode op, expdesc *e1, expdesc *e2) { + lua_Number v1, v2, r; + if (!isnumeral(e1) || !isnumeral(e2)) return 0; + v1 = e1->u.nval; + v2 = e2->u.nval; + switch (op) { + case OP_ADD: r = luai_numadd(v1, v2); break; + case OP_SUB: r = luai_numsub(v1, v2); break; + case OP_MUL: r = luai_nummul(v1, v2); break; + case OP_DIV: + if (v2 == 0) return 0; /* do not attempt to divide by 0 */ + r = luai_numdiv(v1, v2); break; + case OP_MOD: + if (v2 == 0) return 0; /* do not attempt to divide by 0 */ + r = luai_nummod(v1, v2); break; + case OP_POW: r = luai_numpow(v1, v2); break; + case OP_UNM: r = luai_numunm(v1); break; + case OP_LEN: return 0; /* no constant folding for 'len' */ + default: lua_assert(0); r = 0; break; + } + if (luai_numisnan(r)) return 0; /* do not attempt to produce NaN */ + e1->u.nval = r; + return 1; +} + + +static void codearith (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) { + if (constfolding(op, e1, e2)) + return; + else { + int o2 = (op != OP_UNM && op != OP_LEN) ? luaK_exp2RK(fs, e2) : 0; + int o1 = luaK_exp2RK(fs, e1); + if (o1 > o2) { + freeexp(fs, e1); + freeexp(fs, e2); + } + else { + freeexp(fs, e2); + freeexp(fs, e1); + } + e1->u.s.info = luaK_codeABC(fs, op, 0, o1, o2); + e1->k = VRELOCABLE; + } +} + + +static void codecomp (FuncState *fs, OpCode op, int cond, expdesc *e1, + expdesc *e2) { + int o1 = luaK_exp2RK(fs, e1); + int o2 = luaK_exp2RK(fs, e2); + freeexp(fs, e2); + freeexp(fs, e1); + if (cond == 0 && op != OP_EQ) { + int temp; /* exchange args to replace by `<' or `<=' */ + temp = o1; o1 = o2; o2 = temp; /* o1 <==> o2 */ + cond = 1; + } + e1->u.s.info = condjump(fs, op, cond, o1, o2); + e1->k = VJMP; +} + + +void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) { + expdesc e2; + e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0; + switch (op) { + case OPR_MINUS: { + if (!isnumeral(e)) + luaK_exp2anyreg(fs, e); /* cannot operate on non-numeric constants */ + codearith(fs, OP_UNM, e, &e2); + break; + } + case OPR_NOT: codenot(fs, e); break; + case OPR_LEN: { + luaK_exp2anyreg(fs, e); /* cannot operate on constants */ + codearith(fs, OP_LEN, e, &e2); + break; + } + default: lua_assert(0); + } +} + + +void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { + switch (op) { + case OPR_AND: { + luaK_goiftrue(fs, v); + break; + } + case OPR_OR: { + luaK_goiffalse(fs, v); + break; + } + case OPR_CONCAT: { + luaK_exp2nextreg(fs, v); /* operand must be on the `stack' */ + break; + } + case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV: + case OPR_MOD: case OPR_POW: { + if (!isnumeral(v)) luaK_exp2RK(fs, v); + break; + } + default: { + luaK_exp2RK(fs, v); + break; + } + } +} + + +void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) { + switch (op) { + case OPR_AND: { + lua_assert(e1->t == NO_JUMP); /* list must be closed */ + luaK_dischargevars(fs, e2); + luaK_concat(fs, &e2->f, e1->f); + *e1 = *e2; + break; + } + case OPR_OR: { + lua_assert(e1->f == NO_JUMP); /* list must be closed */ + luaK_dischargevars(fs, e2); + luaK_concat(fs, &e2->t, e1->t); + *e1 = *e2; + break; + } + case OPR_CONCAT: { + luaK_exp2val(fs, e2); + if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) { + lua_assert(e1->u.s.info == GETARG_B(getcode(fs, e2))-1); + freeexp(fs, e1); + SETARG_B(getcode(fs, e2), e1->u.s.info); + e1->k = VRELOCABLE; e1->u.s.info = e2->u.s.info; + } + else { + luaK_exp2nextreg(fs, e2); /* operand must be on the 'stack' */ + codearith(fs, OP_CONCAT, e1, e2); + } + break; + } + case OPR_ADD: codearith(fs, OP_ADD, e1, e2); break; + case OPR_SUB: codearith(fs, OP_SUB, e1, e2); break; + case OPR_MUL: codearith(fs, OP_MUL, e1, e2); break; + case OPR_DIV: codearith(fs, OP_DIV, e1, e2); break; + case OPR_MOD: codearith(fs, OP_MOD, e1, e2); break; + case OPR_POW: codearith(fs, OP_POW, e1, e2); break; + case OPR_EQ: codecomp(fs, OP_EQ, 1, e1, e2); break; + case OPR_NE: codecomp(fs, OP_EQ, 0, e1, e2); break; + case OPR_LT: codecomp(fs, OP_LT, 1, e1, e2); break; + case OPR_LE: codecomp(fs, OP_LE, 1, e1, e2); break; + case OPR_GT: codecomp(fs, OP_LT, 0, e1, e2); break; + case OPR_GE: codecomp(fs, OP_LE, 0, e1, e2); break; + default: lua_assert(0); + } +} + + +void luaK_fixline (FuncState *fs, int line) { + fs->f->lineinfo[fs->pc - 1] = line; +} + + +static int luaK_code (FuncState *fs, Instruction i, int line) { + Proto *f = fs->f; + dischargejpc(fs); /* `pc' will change */ + /* put new instruction in code array */ + luaM_growvector(fs->L, f->code, fs->pc, f->sizecode, Instruction, + MAX_INT, "code size overflow"); + f->code[fs->pc] = i; + /* save corresponding line information */ + luaM_growvector(fs->L, f->lineinfo, fs->pc, f->sizelineinfo, int, + MAX_INT, "code size overflow"); + f->lineinfo[fs->pc] = line; + return fs->pc++; +} + + +int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) { + lua_assert(getOpMode(o) == iABC); + lua_assert(getBMode(o) != OpArgN || b == 0); + lua_assert(getCMode(o) != OpArgN || c == 0); + return luaK_code(fs, CREATE_ABC(o, a, b, c), fs->ls->lastline); +} + + +int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) { + lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx); + lua_assert(getCMode(o) == OpArgN); + return luaK_code(fs, CREATE_ABx(o, a, bc), fs->ls->lastline); +} + + +void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) { + int c = (nelems - 1)/LFIELDS_PER_FLUSH + 1; + int b = (tostore == LUA_MULTRET) ? 0 : tostore; + lua_assert(tostore != 0); + if (c <= MAXARG_C) + luaK_codeABC(fs, OP_SETLIST, base, b, c); + else { + luaK_codeABC(fs, OP_SETLIST, base, b, 0); + luaK_code(fs, cast(Instruction, c), fs->ls->lastline); + } + fs->freereg = base + 1; /* free registers with list values */ +} + diff --git a/external/mit/lua/dist/src/lcode.h b/external/mit/lua/dist/src/lcode.h new file mode 100644 index 000000000..267cd5a7e --- /dev/null +++ b/external/mit/lua/dist/src/lcode.h @@ -0,0 +1,78 @@ +/* $NetBSD: lcode.h,v 1.1.1.2 2012/03/15 00:08:04 alnsn Exp $ */ + +/* +** $Id: lcode.h,v 1.1.1.2 2012/03/15 00:08:04 alnsn Exp $ +** Code generator for Lua +** See Copyright Notice in lua.h +*/ + +#ifndef lcode_h +#define lcode_h + +#include "llex.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lparser.h" + + +/* +** Marks the end of a patch list. It is an invalid value both as an absolute +** address, and as a list link (would link an element to itself). +*/ +#define NO_JUMP (-1) + + +/* +** grep "ORDER OPR" if you change these enums +*/ +typedef enum BinOpr { + OPR_ADD, OPR_SUB, OPR_MUL, OPR_DIV, OPR_MOD, OPR_POW, + OPR_CONCAT, + OPR_NE, OPR_EQ, + OPR_LT, OPR_LE, OPR_GT, OPR_GE, + OPR_AND, OPR_OR, + OPR_NOBINOPR +} BinOpr; + + +typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr; + + +#define getcode(fs,e) ((fs)->f->code[(e)->u.s.info]) + +#define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx) + +#define luaK_setmultret(fs,e) luaK_setreturns(fs, e, LUA_MULTRET) + +LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx); +LUAI_FUNC int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C); +LUAI_FUNC void luaK_fixline (FuncState *fs, int line); +LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n); +LUAI_FUNC void luaK_reserveregs (FuncState *fs, int n); +LUAI_FUNC void luaK_checkstack (FuncState *fs, int n); +LUAI_FUNC int luaK_stringK (FuncState *fs, TString *s); +LUAI_FUNC int luaK_numberK (FuncState *fs, lua_Number r); +LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e); +LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e); +LUAI_FUNC void luaK_exp2nextreg (FuncState *fs, expdesc *e); +LUAI_FUNC void luaK_exp2val (FuncState *fs, expdesc *e); +LUAI_FUNC int luaK_exp2RK (FuncState *fs, expdesc *e); +LUAI_FUNC void luaK_self (FuncState *fs, expdesc *e, expdesc *key); +LUAI_FUNC void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k); +LUAI_FUNC void luaK_goiftrue (FuncState *fs, expdesc *e); +LUAI_FUNC void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e); +LUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults); +LUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e); +LUAI_FUNC int luaK_jump (FuncState *fs); +LUAI_FUNC void luaK_ret (FuncState *fs, int first, int nret); +LUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target); +LUAI_FUNC void luaK_patchtohere (FuncState *fs, int list); +LUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2); +LUAI_FUNC int luaK_getlabel (FuncState *fs); +LUAI_FUNC void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v); +LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v); +LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, expdesc *v2); +LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore); + + +#endif diff --git a/external/mit/lua/dist/src/ldblib.c b/external/mit/lua/dist/src/ldblib.c new file mode 100644 index 000000000..d4aff2ede --- /dev/null +++ b/external/mit/lua/dist/src/ldblib.c @@ -0,0 +1,400 @@ +/* $NetBSD: ldblib.c,v 1.1.1.2 2012/03/15 00:08:10 alnsn Exp $ */ + +/* +** $Id: ldblib.c,v 1.1.1.2 2012/03/15 00:08:10 alnsn Exp $ +** Interface from Lua to its debug API +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include + +#define ldblib_c +#define LUA_LIB + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + + +static int db_getregistry (lua_State *L) { + lua_pushvalue(L, LUA_REGISTRYINDEX); + return 1; +} + + +static int db_getmetatable (lua_State *L) { + luaL_checkany(L, 1); + if (!lua_getmetatable(L, 1)) { + lua_pushnil(L); /* no metatable */ + } + return 1; +} + + +static int db_setmetatable (lua_State *L) { + int t = lua_type(L, 2); + luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2, + "nil or table expected"); + lua_settop(L, 2); + lua_pushboolean(L, lua_setmetatable(L, 1)); + return 1; +} + + +static int db_getfenv (lua_State *L) { + luaL_checkany(L, 1); + lua_getfenv(L, 1); + return 1; +} + + +static int db_setfenv (lua_State *L) { + luaL_checktype(L, 2, LUA_TTABLE); + lua_settop(L, 2); + if (lua_setfenv(L, 1) == 0) + luaL_error(L, LUA_QL("setfenv") + " cannot change environment of given object"); + return 1; +} + + +static void settabss (lua_State *L, const char *i, const char *v) { + lua_pushstring(L, v); + lua_setfield(L, -2, i); +} + + +static void settabsi (lua_State *L, const char *i, int v) { + lua_pushinteger(L, v); + lua_setfield(L, -2, i); +} + + +static lua_State *getthread (lua_State *L, int *arg) { + if (lua_isthread(L, 1)) { + *arg = 1; + return lua_tothread(L, 1); + } + else { + *arg = 0; + return L; + } +} + + +static void treatstackoption (lua_State *L, lua_State *L1, const char *fname) { + if (L == L1) { + lua_pushvalue(L, -2); + lua_remove(L, -3); + } + else + lua_xmove(L1, L, 1); + lua_setfield(L, -2, fname); +} + + +static int db_getinfo (lua_State *L) { + lua_Debug ar; + int arg; + lua_State *L1 = getthread(L, &arg); + const char *options = luaL_optstring(L, arg+2, "flnSu"); + if (lua_isnumber(L, arg+1)) { + if (!lua_getstack(L1, (int)lua_tointeger(L, arg+1), &ar)) { + lua_pushnil(L); /* level out of range */ + return 1; + } + } + else if (lua_isfunction(L, arg+1)) { + lua_pushfstring(L, ">%s", options); + options = lua_tostring(L, -1); + lua_pushvalue(L, arg+1); + lua_xmove(L, L1, 1); + } + else + return luaL_argerror(L, arg+1, "function or level expected"); + if (!lua_getinfo(L1, options, &ar)) + return luaL_argerror(L, arg+2, "invalid option"); + lua_createtable(L, 0, 2); + if (strchr(options, 'S')) { + settabss(L, "source", ar.source); + settabss(L, "short_src", ar.short_src); + settabsi(L, "linedefined", ar.linedefined); + settabsi(L, "lastlinedefined", ar.lastlinedefined); + settabss(L, "what", ar.what); + } + if (strchr(options, 'l')) + settabsi(L, "currentline", ar.currentline); + if (strchr(options, 'u')) + settabsi(L, "nups", ar.nups); + if (strchr(options, 'n')) { + settabss(L, "name", ar.name); + settabss(L, "namewhat", ar.namewhat); + } + if (strchr(options, 'L')) + treatstackoption(L, L1, "activelines"); + if (strchr(options, 'f')) + treatstackoption(L, L1, "func"); + return 1; /* return table */ +} + + +static int db_getlocal (lua_State *L) { + int arg; + lua_State *L1 = getthread(L, &arg); + lua_Debug ar; + const char *name; + if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */ + return luaL_argerror(L, arg+1, "level out of range"); + name = lua_getlocal(L1, &ar, luaL_checkint(L, arg+2)); + if (name) { + lua_xmove(L1, L, 1); + lua_pushstring(L, name); + lua_pushvalue(L, -2); + return 2; + } + else { + lua_pushnil(L); + return 1; + } +} + + +static int db_setlocal (lua_State *L) { + int arg; + lua_State *L1 = getthread(L, &arg); + lua_Debug ar; + if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */ + return luaL_argerror(L, arg+1, "level out of range"); + luaL_checkany(L, arg+3); + lua_settop(L, arg+3); + lua_xmove(L, L1, 1); + lua_pushstring(L, lua_setlocal(L1, &ar, luaL_checkint(L, arg+2))); + return 1; +} + + +static int auxupvalue (lua_State *L, int get) { + const char *name; + int n = luaL_checkint(L, 2); + luaL_checktype(L, 1, LUA_TFUNCTION); + if (lua_iscfunction(L, 1)) return 0; /* cannot touch C upvalues from Lua */ + name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n); + if (name == NULL) return 0; + lua_pushstring(L, name); + lua_insert(L, -(get+1)); + return get + 1; +} + + +static int db_getupvalue (lua_State *L) { + return auxupvalue(L, 1); +} + + +static int db_setupvalue (lua_State *L) { + luaL_checkany(L, 3); + return auxupvalue(L, 0); +} + + + +static const char KEY_HOOK = 'h'; + + +static void hookf (lua_State *L, lua_Debug *ar) { + static const char *const hooknames[] = + {"call", "return", "line", "count", "tail return"}; + lua_pushlightuserdata(L, (void *)&KEY_HOOK); + lua_rawget(L, LUA_REGISTRYINDEX); + lua_pushlightuserdata(L, L); + lua_rawget(L, -2); + if (lua_isfunction(L, -1)) { + lua_pushstring(L, hooknames[(int)ar->event]); + if (ar->currentline >= 0) + lua_pushinteger(L, ar->currentline); + else lua_pushnil(L); + lua_assert(lua_getinfo(L, "lS", ar)); + lua_call(L, 2, 0); + } +} + + +static int makemask (const char *smask, int count) { + int mask = 0; + if (strchr(smask, 'c')) mask |= LUA_MASKCALL; + if (strchr(smask, 'r')) mask |= LUA_MASKRET; + if (strchr(smask, 'l')) mask |= LUA_MASKLINE; + if (count > 0) mask |= LUA_MASKCOUNT; + return mask; +} + + +static char *unmakemask (int mask, char *smask) { + int i = 0; + if (mask & LUA_MASKCALL) smask[i++] = 'c'; + if (mask & LUA_MASKRET) smask[i++] = 'r'; + if (mask & LUA_MASKLINE) smask[i++] = 'l'; + smask[i] = '\0'; + return smask; +} + + +static void gethooktable (lua_State *L) { + lua_pushlightuserdata(L, (void *)&KEY_HOOK); + lua_rawget(L, LUA_REGISTRYINDEX); + if (!lua_istable(L, -1)) { + lua_pop(L, 1); + lua_createtable(L, 0, 1); + lua_pushlightuserdata(L, (void *)&KEY_HOOK); + lua_pushvalue(L, -2); + lua_rawset(L, LUA_REGISTRYINDEX); + } +} + + +static int db_sethook (lua_State *L) { + int arg, mask, count; + lua_Hook func; + lua_State *L1 = getthread(L, &arg); + if (lua_isnoneornil(L, arg+1)) { + lua_settop(L, arg+1); + func = NULL; mask = 0; count = 0; /* turn off hooks */ + } + else { + const char *smask = luaL_checkstring(L, arg+2); + luaL_checktype(L, arg+1, LUA_TFUNCTION); + count = luaL_optint(L, arg+3, 0); + func = hookf; mask = makemask(smask, count); + } + gethooktable(L); + lua_pushlightuserdata(L, L1); + lua_pushvalue(L, arg+1); + lua_rawset(L, -3); /* set new hook */ + lua_pop(L, 1); /* remove hook table */ + lua_sethook(L1, func, mask, count); /* set hooks */ + return 0; +} + + +static int db_gethook (lua_State *L) { + int arg; + lua_State *L1 = getthread(L, &arg); + char buff[5]; + int mask = lua_gethookmask(L1); + lua_Hook hook = lua_gethook(L1); + if (hook != NULL && hook != hookf) /* external hook? */ + lua_pushliteral(L, "external hook"); + else { + gethooktable(L); + lua_pushlightuserdata(L, L1); + lua_rawget(L, -2); /* get hook */ + lua_remove(L, -2); /* remove hook table */ + } + lua_pushstring(L, unmakemask(mask, buff)); + lua_pushinteger(L, lua_gethookcount(L1)); + return 3; +} + + +static int db_debug (lua_State *L) { + for (;;) { + char buffer[250]; + fputs("lua_debug> ", stderr); + if (fgets(buffer, sizeof(buffer), stdin) == 0 || + strcmp(buffer, "cont\n") == 0) + return 0; + if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") || + lua_pcall(L, 0, 0, 0)) { + fputs(lua_tostring(L, -1), stderr); + fputs("\n", stderr); + } + lua_settop(L, 0); /* remove eventual returns */ + } +} + + +#define LEVELS1 12 /* size of the first part of the stack */ +#define LEVELS2 10 /* size of the second part of the stack */ + +static int db_errorfb (lua_State *L) { + int level; + int firstpart = 1; /* still before eventual `...' */ + int arg; + lua_State *L1 = getthread(L, &arg); + lua_Debug ar; + if (lua_isnumber(L, arg+2)) { + level = (int)lua_tointeger(L, arg+2); + lua_pop(L, 1); + } + else + level = (L == L1) ? 1 : 0; /* level 0 may be this own function */ + if (lua_gettop(L) == arg) + lua_pushliteral(L, ""); + else if (!lua_isstring(L, arg+1)) return 1; /* message is not a string */ + else lua_pushliteral(L, "\n"); + lua_pushliteral(L, "stack traceback:"); + while (lua_getstack(L1, level++, &ar)) { + if (level > LEVELS1 && firstpart) { + /* no more than `LEVELS2' more levels? */ + if (!lua_getstack(L1, level+LEVELS2, &ar)) + level--; /* keep going */ + else { + lua_pushliteral(L, "\n\t..."); /* too many levels */ + while (lua_getstack(L1, level+LEVELS2, &ar)) /* find last levels */ + level++; + } + firstpart = 0; + continue; + } + lua_pushliteral(L, "\n\t"); + lua_getinfo(L1, "Snl", &ar); + lua_pushfstring(L, "%s:", ar.short_src); + if (ar.currentline > 0) + lua_pushfstring(L, "%d:", ar.currentline); + if (*ar.namewhat != '\0') /* is there a name? */ + lua_pushfstring(L, " in function " LUA_QS, ar.name); + else { + if (*ar.what == 'm') /* main? */ + lua_pushfstring(L, " in main chunk"); + else if (*ar.what == 'C' || *ar.what == 't') + lua_pushliteral(L, " ?"); /* C function or tail call */ + else + lua_pushfstring(L, " in function <%s:%d>", + ar.short_src, ar.linedefined); + } + lua_concat(L, lua_gettop(L) - arg); + } + lua_concat(L, lua_gettop(L) - arg); + return 1; +} + + +static const luaL_Reg dblib[] = { + {"debug", db_debug}, + {"getfenv", db_getfenv}, + {"gethook", db_gethook}, + {"getinfo", db_getinfo}, + {"getlocal", db_getlocal}, + {"getregistry", db_getregistry}, + {"getmetatable", db_getmetatable}, + {"getupvalue", db_getupvalue}, + {"setfenv", db_setfenv}, + {"sethook", db_sethook}, + {"setlocal", db_setlocal}, + {"setmetatable", db_setmetatable}, + {"setupvalue", db_setupvalue}, + {"traceback", db_errorfb}, + {NULL, NULL} +}; + + +LUALIB_API int luaopen_debug (lua_State *L) { + luaL_register(L, LUA_DBLIBNAME, dblib); + return 1; +} + diff --git a/external/mit/lua/dist/src/ldebug.c b/external/mit/lua/dist/src/ldebug.c new file mode 100644 index 000000000..24eff2f20 --- /dev/null +++ b/external/mit/lua/dist/src/ldebug.c @@ -0,0 +1,640 @@ +/* $NetBSD: ldebug.c,v 1.1.1.2 2012/03/15 00:08:08 alnsn Exp $ */ + +/* +** $Id: ldebug.c,v 1.1.1.2 2012/03/15 00:08:08 alnsn Exp $ +** Debug Interface +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include + + +#define ldebug_c +#define LUA_CORE + +#include "lua.h" + +#include "lapi.h" +#include "lcode.h" +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" +#include "lvm.h" + + + +static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name); + + +static int currentpc (lua_State *L, CallInfo *ci) { + if (!isLua(ci)) return -1; /* function is not a Lua function? */ + if (ci == L->ci) + ci->savedpc = L->savedpc; + return pcRel(ci->savedpc, ci_func(ci)->l.p); +} + + +static int currentline (lua_State *L, CallInfo *ci) { + int pc = currentpc(L, ci); + if (pc < 0) + return -1; /* only active lua functions have current-line information */ + else + return getline(ci_func(ci)->l.p, pc); +} + + +/* +** this function can be called asynchronous (e.g. during a signal) +*/ +LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count) { + if (func == NULL || mask == 0) { /* turn off hooks? */ + mask = 0; + func = NULL; + } + L->hook = func; + L->basehookcount = count; + resethookcount(L); + L->hookmask = cast_byte(mask); + return 1; +} + + +LUA_API lua_Hook lua_gethook (lua_State *L) { + return L->hook; +} + + +LUA_API int lua_gethookmask (lua_State *L) { + return L->hookmask; +} + + +LUA_API int lua_gethookcount (lua_State *L) { + return L->basehookcount; +} + + +LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) { + int status; + CallInfo *ci; + lua_lock(L); + for (ci = L->ci; level > 0 && ci > L->base_ci; ci--) { + level--; + if (f_isLua(ci)) /* Lua function? */ + level -= ci->tailcalls; /* skip lost tail calls */ + } + if (level == 0 && ci > L->base_ci) { /* level found? */ + status = 1; + ar->i_ci = cast_int(ci - L->base_ci); + } + else if (level < 0) { /* level is of a lost tail call? */ + status = 1; + ar->i_ci = 0; + } + else status = 0; /* no such level */ + lua_unlock(L); + return status; +} + + +static Proto *getluaproto (CallInfo *ci) { + return (isLua(ci) ? ci_func(ci)->l.p : NULL); +} + + +static const char *findlocal (lua_State *L, CallInfo *ci, int n) { + const char *name; + Proto *fp = getluaproto(ci); + if (fp && (name = luaF_getlocalname(fp, n, currentpc(L, ci))) != NULL) + return name; /* is a local variable in a Lua function */ + else { + StkId limit = (ci == L->ci) ? L->top : (ci+1)->func; + if (limit - ci->base >= n && n > 0) /* is 'n' inside 'ci' stack? */ + return "(*temporary)"; + else + return NULL; + } +} + + +LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) { + CallInfo *ci = L->base_ci + ar->i_ci; + const char *name = findlocal(L, ci, n); + lua_lock(L); + if (name) + luaA_pushobject(L, ci->base + (n - 1)); + lua_unlock(L); + return name; +} + + +LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) { + CallInfo *ci = L->base_ci + ar->i_ci; + const char *name = findlocal(L, ci, n); + lua_lock(L); + if (name) + setobjs2s(L, ci->base + (n - 1), L->top - 1); + L->top--; /* pop value */ + lua_unlock(L); + return name; +} + + +static void funcinfo (lua_Debug *ar, Closure *cl) { + if (cl->c.isC) { + ar->source = "=[C]"; + ar->linedefined = -1; + ar->lastlinedefined = -1; + ar->what = "C"; + } + else { + ar->source = getstr(cl->l.p->source); + ar->linedefined = cl->l.p->linedefined; + ar->lastlinedefined = cl->l.p->lastlinedefined; + ar->what = (ar->linedefined == 0) ? "main" : "Lua"; + } + luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE); +} + + +static void info_tailcall (lua_Debug *ar) { + ar->name = ar->namewhat = ""; + ar->what = "tail"; + ar->lastlinedefined = ar->linedefined = ar->currentline = -1; + ar->source = "=(tail call)"; + luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE); + ar->nups = 0; +} + + +static void collectvalidlines (lua_State *L, Closure *f) { + if (f == NULL || f->c.isC) { + setnilvalue(L->top); + } + else { + Table *t = luaH_new(L, 0, 0); + int *lineinfo = f->l.p->lineinfo; + int i; + for (i=0; il.p->sizelineinfo; i++) + setbvalue(luaH_setnum(L, t, lineinfo[i]), 1); + sethvalue(L, L->top, t); + } + incr_top(L); +} + + +static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, + Closure *f, CallInfo *ci) { + int status = 1; + if (f == NULL) { + info_tailcall(ar); + return status; + } + for (; *what; what++) { + switch (*what) { + case 'S': { + funcinfo(ar, f); + break; + } + case 'l': { + ar->currentline = (ci) ? currentline(L, ci) : -1; + break; + } + case 'u': { + ar->nups = f->c.nupvalues; + break; + } + case 'n': { + ar->namewhat = (ci) ? getfuncname(L, ci, &ar->name) : NULL; + if (ar->namewhat == NULL) { + ar->namewhat = ""; /* not found */ + ar->name = NULL; + } + break; + } + case 'L': + case 'f': /* handled by lua_getinfo */ + break; + default: status = 0; /* invalid option */ + } + } + return status; +} + + +LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { + int status; + Closure *f = NULL; + CallInfo *ci = NULL; + lua_lock(L); + if (*what == '>') { + StkId func = L->top - 1; + luai_apicheck(L, ttisfunction(func)); + what++; /* skip the '>' */ + f = clvalue(func); + L->top--; /* pop function */ + } + else if (ar->i_ci != 0) { /* no tail call? */ + ci = L->base_ci + ar->i_ci; + lua_assert(ttisfunction(ci->func)); + f = clvalue(ci->func); + } + status = auxgetinfo(L, what, ar, f, ci); + if (strchr(what, 'f')) { + if (f == NULL) setnilvalue(L->top); + else setclvalue(L, L->top, f); + incr_top(L); + } + if (strchr(what, 'L')) + collectvalidlines(L, f); + lua_unlock(L); + return status; +} + + +/* +** {====================================================== +** Symbolic Execution and code checker +** ======================================================= +*/ + +#define check(x) if (!(x)) return 0; + +#define checkjump(pt,pc) check(0 <= pc && pc < pt->sizecode) + +#define checkreg(pt,reg) check((reg) < (pt)->maxstacksize) + + + +static int precheck (const Proto *pt) { + check(pt->maxstacksize <= MAXSTACK); + check(pt->numparams+(pt->is_vararg & VARARG_HASARG) <= pt->maxstacksize); + check(!(pt->is_vararg & VARARG_NEEDSARG) || + (pt->is_vararg & VARARG_HASARG)); + check(pt->sizeupvalues <= pt->nups); + check(pt->sizelineinfo == pt->sizecode || pt->sizelineinfo == 0); + check(pt->sizecode > 0 && GET_OPCODE(pt->code[pt->sizecode-1]) == OP_RETURN); + return 1; +} + + +#define checkopenop(pt,pc) luaG_checkopenop((pt)->code[(pc)+1]) + +int luaG_checkopenop (Instruction i) { + switch (GET_OPCODE(i)) { + case OP_CALL: + case OP_TAILCALL: + case OP_RETURN: + case OP_SETLIST: { + check(GETARG_B(i) == 0); + return 1; + } + default: return 0; /* invalid instruction after an open call */ + } +} + + +static int checkArgMode (const Proto *pt, int r, enum OpArgMask mode) { + switch (mode) { + case OpArgN: check(r == 0); break; + case OpArgU: break; + case OpArgR: checkreg(pt, r); break; + case OpArgK: + check(ISK(r) ? INDEXK(r) < pt->sizek : r < pt->maxstacksize); + break; + } + return 1; +} + + +static Instruction symbexec (const Proto *pt, int lastpc, int reg) { + int pc; + int last; /* stores position of last instruction that changed `reg' */ + last = pt->sizecode-1; /* points to final return (a `neutral' instruction) */ + check(precheck(pt)); + for (pc = 0; pc < lastpc; pc++) { + Instruction i = pt->code[pc]; + OpCode op = GET_OPCODE(i); + int a = GETARG_A(i); + int b = 0; + int c = 0; + check(op < NUM_OPCODES); + checkreg(pt, a); + switch (getOpMode(op)) { + case iABC: { + b = GETARG_B(i); + c = GETARG_C(i); + check(checkArgMode(pt, b, getBMode(op))); + check(checkArgMode(pt, c, getCMode(op))); + break; + } + case iABx: { + b = GETARG_Bx(i); + if (getBMode(op) == OpArgK) check(b < pt->sizek); + break; + } + case iAsBx: { + b = GETARG_sBx(i); + if (getBMode(op) == OpArgR) { + int dest = pc+1+b; + check(0 <= dest && dest < pt->sizecode); + if (dest > 0) { + int j; + /* check that it does not jump to a setlist count; this + is tricky, because the count from a previous setlist may + have the same value of an invalid setlist; so, we must + go all the way back to the first of them (if any) */ + for (j = 0; j < dest; j++) { + Instruction d = pt->code[dest-1-j]; + if (!(GET_OPCODE(d) == OP_SETLIST && GETARG_C(d) == 0)) break; + } + /* if 'j' is even, previous value is not a setlist (even if + it looks like one) */ + check((j&1) == 0); + } + } + break; + } + } + if (testAMode(op)) { + if (a == reg) last = pc; /* change register `a' */ + } + if (testTMode(op)) { + check(pc+2 < pt->sizecode); /* check skip */ + check(GET_OPCODE(pt->code[pc+1]) == OP_JMP); + } + switch (op) { + case OP_LOADBOOL: { + if (c == 1) { /* does it jump? */ + check(pc+2 < pt->sizecode); /* check its jump */ + check(GET_OPCODE(pt->code[pc+1]) != OP_SETLIST || + GETARG_C(pt->code[pc+1]) != 0); + } + break; + } + case OP_LOADNIL: { + if (a <= reg && reg <= b) + last = pc; /* set registers from `a' to `b' */ + break; + } + case OP_GETUPVAL: + case OP_SETUPVAL: { + check(b < pt->nups); + break; + } + case OP_GETGLOBAL: + case OP_SETGLOBAL: { + check(ttisstring(&pt->k[b])); + break; + } + case OP_SELF: { + checkreg(pt, a+1); + if (reg == a+1) last = pc; + break; + } + case OP_CONCAT: { + check(b < c); /* at least two operands */ + break; + } + case OP_TFORLOOP: { + check(c >= 1); /* at least one result (control variable) */ + checkreg(pt, a+2+c); /* space for results */ + if (reg >= a+2) last = pc; /* affect all regs above its base */ + break; + } + case OP_FORLOOP: + case OP_FORPREP: + checkreg(pt, a+3); + /* go through */ + case OP_JMP: { + int dest = pc+1+b; + /* not full check and jump is forward and do not skip `lastpc'? */ + if (reg != NO_REG && pc < dest && dest <= lastpc) + pc += b; /* do the jump */ + break; + } + case OP_CALL: + case OP_TAILCALL: { + if (b != 0) { + checkreg(pt, a+b-1); + } + c--; /* c = num. returns */ + if (c == LUA_MULTRET) { + check(checkopenop(pt, pc)); + } + else if (c != 0) + checkreg(pt, a+c-1); + if (reg >= a) last = pc; /* affect all registers above base */ + break; + } + case OP_RETURN: { + b--; /* b = num. returns */ + if (b > 0) checkreg(pt, a+b-1); + break; + } + case OP_SETLIST: { + if (b > 0) checkreg(pt, a + b); + if (c == 0) { + pc++; + check(pc < pt->sizecode - 1); + } + break; + } + case OP_CLOSURE: { + int nup, j; + check(b < pt->sizep); + nup = pt->p[b]->nups; + check(pc + nup < pt->sizecode); + for (j = 1; j <= nup; j++) { + OpCode op1 = GET_OPCODE(pt->code[pc + j]); + check(op1 == OP_GETUPVAL || op1 == OP_MOVE); + } + if (reg != NO_REG) /* tracing? */ + pc += nup; /* do not 'execute' these pseudo-instructions */ + break; + } + case OP_VARARG: { + check((pt->is_vararg & VARARG_ISVARARG) && + !(pt->is_vararg & VARARG_NEEDSARG)); + b--; + if (b == LUA_MULTRET) check(checkopenop(pt, pc)); + checkreg(pt, a+b-1); + break; + } + default: break; + } + } + return pt->code[last]; +} + +#undef check +#undef checkjump +#undef checkreg + +/* }====================================================== */ + + +int luaG_checkcode (const Proto *pt) { + return (symbexec(pt, pt->sizecode, NO_REG) != 0); +} + + +static const char *kname (Proto *p, int c) { + if (ISK(c) && ttisstring(&p->k[INDEXK(c)])) + return svalue(&p->k[INDEXK(c)]); + else + return "?"; +} + + +static const char *getobjname (lua_State *L, CallInfo *ci, int stackpos, + const char **name) { + if (isLua(ci)) { /* a Lua function? */ + Proto *p = ci_func(ci)->l.p; + int pc = currentpc(L, ci); + Instruction i; + *name = luaF_getlocalname(p, stackpos+1, pc); + if (*name) /* is a local? */ + return "local"; + i = symbexec(p, pc, stackpos); /* try symbolic execution */ + lua_assert(pc != -1); + switch (GET_OPCODE(i)) { + case OP_GETGLOBAL: { + int g = GETARG_Bx(i); /* global index */ + lua_assert(ttisstring(&p->k[g])); + *name = svalue(&p->k[g]); + return "global"; + } + case OP_MOVE: { + int a = GETARG_A(i); + int b = GETARG_B(i); /* move from `b' to `a' */ + if (b < a) + return getobjname(L, ci, b, name); /* get name for `b' */ + break; + } + case OP_GETTABLE: { + int k = GETARG_C(i); /* key index */ + *name = kname(p, k); + return "field"; + } + case OP_GETUPVAL: { + int u = GETARG_B(i); /* upvalue index */ + *name = p->upvalues ? getstr(p->upvalues[u]) : "?"; + return "upvalue"; + } + case OP_SELF: { + int k = GETARG_C(i); /* key index */ + *name = kname(p, k); + return "method"; + } + default: break; + } + } + return NULL; /* no useful name found */ +} + + +static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) { + Instruction i; + if ((isLua(ci) && ci->tailcalls > 0) || !isLua(ci - 1)) + return NULL; /* calling function is not Lua (or is unknown) */ + ci--; /* calling function */ + i = ci_func(ci)->l.p->code[currentpc(L, ci)]; + if (GET_OPCODE(i) == OP_CALL || GET_OPCODE(i) == OP_TAILCALL || + GET_OPCODE(i) == OP_TFORLOOP) + return getobjname(L, ci, GETARG_A(i), name); + else + return NULL; /* no useful name can be found */ +} + + +/* only ANSI way to check whether a pointer points to an array */ +static int isinstack (CallInfo *ci, const TValue *o) { + StkId p; + for (p = ci->base; p < ci->top; p++) + if (o == p) return 1; + return 0; +} + + +void luaG_typeerror (lua_State *L, const TValue *o, const char *op) { + const char *name = NULL; + const char *t = luaT_typenames[ttype(o)]; + const char *kind = (isinstack(L->ci, o)) ? + getobjname(L, L->ci, cast_int(o - L->base), &name) : + NULL; + if (kind) + luaG_runerror(L, "attempt to %s %s " LUA_QS " (a %s value)", + op, kind, name, t); + else + luaG_runerror(L, "attempt to %s a %s value", op, t); +} + + +void luaG_concaterror (lua_State *L, StkId p1, StkId p2) { + if (ttisstring(p1) || ttisnumber(p1)) p1 = p2; + lua_assert(!ttisstring(p1) && !ttisnumber(p1)); + luaG_typeerror(L, p1, "concatenate"); +} + + +void luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2) { + TValue temp; + if (luaV_tonumber(p1, &temp) == NULL) + p2 = p1; /* first operand is wrong */ + luaG_typeerror(L, p2, "perform arithmetic on"); +} + + +int luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) { + const char *t1 = luaT_typenames[ttype(p1)]; + const char *t2 = luaT_typenames[ttype(p2)]; + if (t1[2] == t2[2]) + luaG_runerror(L, "attempt to compare two %s values", t1); + else + luaG_runerror(L, "attempt to compare %s with %s", t1, t2); + return 0; +} + + +static void addinfo (lua_State *L, const char *msg) { + CallInfo *ci = L->ci; + if (isLua(ci)) { /* is Lua code? */ + char buff[LUA_IDSIZE]; /* add file:line information */ + int line = currentline(L, ci); + luaO_chunkid(buff, getstr(getluaproto(ci)->source), LUA_IDSIZE); + luaO_pushfstring(L, "%s:%d: %s", buff, line, msg); + } +} + + +void luaG_errormsg (lua_State *L) { + if (L->errfunc != 0) { /* is there an error handling function? */ + StkId errfunc = restorestack(L, L->errfunc); + if (!ttisfunction(errfunc)) luaD_throw(L, LUA_ERRERR); + setobjs2s(L, L->top, L->top - 1); /* move argument */ + setobjs2s(L, L->top - 1, errfunc); /* push function */ + incr_top(L); + luaD_call(L, L->top - 2, 1); /* call it */ + } + luaD_throw(L, LUA_ERRRUN); +} + + +void luaG_runerror (lua_State *L, const char *fmt, ...) { + va_list argp; + va_start(argp, fmt); + addinfo(L, luaO_pushvfstring(L, fmt, argp)); + va_end(argp); + luaG_errormsg(L); +} + diff --git a/external/mit/lua/dist/src/ldebug.h b/external/mit/lua/dist/src/ldebug.h new file mode 100644 index 000000000..6446fb20b --- /dev/null +++ b/external/mit/lua/dist/src/ldebug.h @@ -0,0 +1,35 @@ +/* $NetBSD: ldebug.h,v 1.1.1.2 2012/03/15 00:08:14 alnsn Exp $ */ + +/* +** $Id: ldebug.h,v 1.1.1.2 2012/03/15 00:08:14 alnsn Exp $ +** Auxiliary functions from Debug Interface module +** See Copyright Notice in lua.h +*/ + +#ifndef ldebug_h +#define ldebug_h + + +#include "lstate.h" + + +#define pcRel(pc, p) (cast(int, (pc) - (p)->code) - 1) + +#define getline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : 0) + +#define resethookcount(L) (L->hookcount = L->basehookcount) + + +LUAI_FUNC void luaG_typeerror (lua_State *L, const TValue *o, + const char *opname); +LUAI_FUNC void luaG_concaterror (lua_State *L, StkId p1, StkId p2); +LUAI_FUNC void luaG_aritherror (lua_State *L, const TValue *p1, + const TValue *p2); +LUAI_FUNC int luaG_ordererror (lua_State *L, const TValue *p1, + const TValue *p2); +LUAI_FUNC void luaG_runerror (lua_State *L, const char *fmt, ...); +LUAI_FUNC void luaG_errormsg (lua_State *L); +LUAI_FUNC int luaG_checkcode (const Proto *pt); +LUAI_FUNC int luaG_checkopenop (Instruction i); + +#endif diff --git a/external/mit/lua/dist/src/ldo.c b/external/mit/lua/dist/src/ldo.c new file mode 100644 index 000000000..e25bea9aa --- /dev/null +++ b/external/mit/lua/dist/src/ldo.c @@ -0,0 +1,521 @@ +/* $NetBSD: ldo.c,v 1.1.1.2 2012/03/15 00:08:09 alnsn Exp $ */ + +/* +** $Id: ldo.c,v 1.1.1.2 2012/03/15 00:08:09 alnsn Exp $ +** Stack and Call structure of Lua +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include + +#define ldo_c +#define LUA_CORE + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lgc.h" +#include "lmem.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lparser.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" +#include "lundump.h" +#include "lvm.h" +#include "lzio.h" + + + + +/* +** {====================================================== +** Error-recovery functions +** ======================================================= +*/ + + +/* chain list of long jump buffers */ +struct lua_longjmp { + struct lua_longjmp *previous; + luai_jmpbuf b; + volatile int status; /* error code */ +}; + + +void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) { + switch (errcode) { + case LUA_ERRMEM: { + setsvalue2s(L, oldtop, luaS_newliteral(L, MEMERRMSG)); + break; + } + case LUA_ERRERR: { + setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling")); + break; + } + case LUA_ERRSYNTAX: + case LUA_ERRRUN: { + setobjs2s(L, oldtop, L->top - 1); /* error message on current top */ + break; + } + } + L->top = oldtop + 1; +} + + +static void restore_stack_limit (lua_State *L) { + lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1); + if (L->size_ci > LUAI_MAXCALLS) { /* there was an overflow? */ + int inuse = cast_int(L->ci - L->base_ci); + if (inuse + 1 < LUAI_MAXCALLS) /* can `undo' overflow? */ + luaD_reallocCI(L, LUAI_MAXCALLS); + } +} + + +static void resetstack (lua_State *L, int status) { + L->ci = L->base_ci; + L->base = L->ci->base; + luaF_close(L, L->base); /* close eventual pending closures */ + luaD_seterrorobj(L, status, L->base); + L->nCcalls = L->baseCcalls; + L->allowhook = 1; + restore_stack_limit(L); + L->errfunc = 0; + L->errorJmp = NULL; +} + + +void luaD_throw (lua_State *L, int errcode) { + if (L->errorJmp) { + L->errorJmp->status = errcode; + LUAI_THROW(L, L->errorJmp); + } + else { + L->status = cast_byte(errcode); + if (G(L)->panic) { + resetstack(L, errcode); + lua_unlock(L); + G(L)->panic(L); + } + exit(EXIT_FAILURE); + } +} + + +int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { + struct lua_longjmp lj; + lj.status = 0; + lj.previous = L->errorJmp; /* chain new error handler */ + L->errorJmp = &lj; + LUAI_TRY(L, &lj, + (*f)(L, ud); + ); + L->errorJmp = lj.previous; /* restore old error handler */ + return lj.status; +} + +/* }====================================================== */ + + +static void correctstack (lua_State *L, TValue *oldstack) { + CallInfo *ci; + GCObject *up; + L->top = (L->top - oldstack) + L->stack; + for (up = L->openupval; up != NULL; up = up->gch.next) + gco2uv(up)->v = (gco2uv(up)->v - oldstack) + L->stack; + for (ci = L->base_ci; ci <= L->ci; ci++) { + ci->top = (ci->top - oldstack) + L->stack; + ci->base = (ci->base - oldstack) + L->stack; + ci->func = (ci->func - oldstack) + L->stack; + } + L->base = (L->base - oldstack) + L->stack; +} + + +void luaD_reallocstack (lua_State *L, int newsize) { + TValue *oldstack = L->stack; + int realsize = newsize + 1 + EXTRA_STACK; + lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1); + luaM_reallocvector(L, L->stack, L->stacksize, realsize, TValue); + L->stacksize = realsize; + L->stack_last = L->stack+newsize; + correctstack(L, oldstack); +} + + +void luaD_reallocCI (lua_State *L, int newsize) { + CallInfo *oldci = L->base_ci; + luaM_reallocvector(L, L->base_ci, L->size_ci, newsize, CallInfo); + L->size_ci = newsize; + L->ci = (L->ci - oldci) + L->base_ci; + L->end_ci = L->base_ci + L->size_ci - 1; +} + + +void luaD_growstack (lua_State *L, int n) { + if (n <= L->stacksize) /* double size is enough? */ + luaD_reallocstack(L, 2*L->stacksize); + else + luaD_reallocstack(L, L->stacksize + n); +} + + +static CallInfo *growCI (lua_State *L) { + if (L->size_ci > LUAI_MAXCALLS) /* overflow while handling overflow? */ + luaD_throw(L, LUA_ERRERR); + else { + luaD_reallocCI(L, 2*L->size_ci); + if (L->size_ci > LUAI_MAXCALLS) + luaG_runerror(L, "stack overflow"); + } + return ++L->ci; +} + + +void luaD_callhook (lua_State *L, int event, int line) { + lua_Hook hook = L->hook; + if (hook && L->allowhook) { + ptrdiff_t top = savestack(L, L->top); + ptrdiff_t ci_top = savestack(L, L->ci->top); + lua_Debug ar; + ar.event = event; + ar.currentline = line; + if (event == LUA_HOOKTAILRET) + ar.i_ci = 0; /* tail call; no debug information about it */ + else + ar.i_ci = cast_int(L->ci - L->base_ci); + luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ + L->ci->top = L->top + LUA_MINSTACK; + lua_assert(L->ci->top <= L->stack_last); + L->allowhook = 0; /* cannot call hooks inside a hook */ + lua_unlock(L); + (*hook)(L, &ar); + lua_lock(L); + lua_assert(!L->allowhook); + L->allowhook = 1; + L->ci->top = restorestack(L, ci_top); + L->top = restorestack(L, top); + } +} + + +static StkId adjust_varargs (lua_State *L, Proto *p, int actual) { + int i; + int nfixargs = p->numparams; + Table *htab = NULL; + StkId base, fixed; + for (; actual < nfixargs; ++actual) + setnilvalue(L->top++); +#if defined(LUA_COMPAT_VARARG) + if (p->is_vararg & VARARG_NEEDSARG) { /* compat. with old-style vararg? */ + int nvar = actual - nfixargs; /* number of extra arguments */ + lua_assert(p->is_vararg & VARARG_HASARG); + luaC_checkGC(L); + luaD_checkstack(L, p->maxstacksize); + htab = luaH_new(L, nvar, 1); /* create `arg' table */ + for (i=0; itop - nvar + i); + /* store counter in field `n' */ + setnvalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")), cast_num(nvar)); + } +#endif + /* move fixed parameters to final position */ + fixed = L->top - actual; /* first fixed argument */ + base = L->top; /* final position of first argument */ + for (i=0; itop++, fixed+i); + setnilvalue(fixed+i); + } + /* add `arg' parameter */ + if (htab) { + sethvalue(L, L->top++, htab); + lua_assert(iswhite(obj2gco(htab))); + } + return base; +} + + +static StkId tryfuncTM (lua_State *L, StkId func) { + const TValue *tm = luaT_gettmbyobj(L, func, TM_CALL); + StkId p; + ptrdiff_t funcr = savestack(L, func); + if (!ttisfunction(tm)) + luaG_typeerror(L, func, "call"); + /* Open a hole inside the stack at `func' */ + for (p = L->top; p > func; p--) setobjs2s(L, p, p-1); + incr_top(L); + func = restorestack(L, funcr); /* previous call may change stack */ + setobj2s(L, func, tm); /* tag method is the new function to be called */ + return func; +} + + + +#define inc_ci(L) \ + ((L->ci == L->end_ci) ? growCI(L) : \ + (condhardstacktests(luaD_reallocCI(L, L->size_ci)), ++L->ci)) + + +int luaD_precall (lua_State *L, StkId func, int nresults) { + LClosure *cl; + ptrdiff_t funcr; + if (!ttisfunction(func)) /* `func' is not a function? */ + func = tryfuncTM(L, func); /* check the `function' tag method */ + funcr = savestack(L, func); + cl = &clvalue(func)->l; + L->ci->savedpc = L->savedpc; + if (!cl->isC) { /* Lua function? prepare its call */ + CallInfo *ci; + StkId st, base; + Proto *p = cl->p; + luaD_checkstack(L, p->maxstacksize); + func = restorestack(L, funcr); + if (!p->is_vararg) { /* no varargs? */ + base = func + 1; + if (L->top > base + p->numparams) + L->top = base + p->numparams; + } + else { /* vararg function */ + int nargs = cast_int(L->top - func) - 1; + base = adjust_varargs(L, p, nargs); + func = restorestack(L, funcr); /* previous call may change the stack */ + } + ci = inc_ci(L); /* now `enter' new function */ + ci->func = func; + L->base = ci->base = base; + ci->top = L->base + p->maxstacksize; + lua_assert(ci->top <= L->stack_last); + L->savedpc = p->code; /* starting point */ + ci->tailcalls = 0; + ci->nresults = nresults; + for (st = L->top; st < ci->top; st++) + setnilvalue(st); + L->top = ci->top; + if (L->hookmask & LUA_MASKCALL) { + L->savedpc++; /* hooks assume 'pc' is already incremented */ + luaD_callhook(L, LUA_HOOKCALL, -1); + L->savedpc--; /* correct 'pc' */ + } + return PCRLUA; + } + else { /* if is a C function, call it */ + CallInfo *ci; + int n; + luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ + ci = inc_ci(L); /* now `enter' new function */ + ci->func = restorestack(L, funcr); + L->base = ci->base = ci->func + 1; + ci->top = L->top + LUA_MINSTACK; + lua_assert(ci->top <= L->stack_last); + ci->nresults = nresults; + if (L->hookmask & LUA_MASKCALL) + luaD_callhook(L, LUA_HOOKCALL, -1); + lua_unlock(L); + n = (*curr_func(L)->c.f)(L); /* do the actual call */ + lua_lock(L); + if (n < 0) /* yielding? */ + return PCRYIELD; + else { + luaD_poscall(L, L->top - n); + return PCRC; + } + } +} + + +static StkId callrethooks (lua_State *L, StkId firstResult) { + ptrdiff_t fr = savestack(L, firstResult); /* next call may change stack */ + luaD_callhook(L, LUA_HOOKRET, -1); + if (f_isLua(L->ci)) { /* Lua function? */ + while ((L->hookmask & LUA_MASKRET) && L->ci->tailcalls--) /* tail calls */ + luaD_callhook(L, LUA_HOOKTAILRET, -1); + } + return restorestack(L, fr); +} + + +int luaD_poscall (lua_State *L, StkId firstResult) { + StkId res; + int wanted, i; + CallInfo *ci; + if (L->hookmask & LUA_MASKRET) + firstResult = callrethooks(L, firstResult); + ci = L->ci--; + res = ci->func; /* res == final position of 1st result */ + wanted = ci->nresults; + L->base = (ci - 1)->base; /* restore base */ + L->savedpc = (ci - 1)->savedpc; /* restore savedpc */ + /* move results to correct place */ + for (i = wanted; i != 0 && firstResult < L->top; i--) + setobjs2s(L, res++, firstResult++); + while (i-- > 0) + setnilvalue(res++); + L->top = res; + return (wanted - LUA_MULTRET); /* 0 iff wanted == LUA_MULTRET */ +} + + +/* +** Call a function (C or Lua). The function to be called is at *func. +** The arguments are on the stack, right after the function. +** When returns, all the results are on the stack, starting at the original +** function position. +*/ +void luaD_call (lua_State *L, StkId func, int nResults) { + if (++L->nCcalls >= LUAI_MAXCCALLS) { + if (L->nCcalls == LUAI_MAXCCALLS) + luaG_runerror(L, "C stack overflow"); + else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3))) + luaD_throw(L, LUA_ERRERR); /* error while handing stack error */ + } + if (luaD_precall(L, func, nResults) == PCRLUA) /* is a Lua function? */ + luaV_execute(L, 1); /* call it */ + L->nCcalls--; + luaC_checkGC(L); +} + + +static void resume (lua_State *L, void *ud) { + StkId firstArg = cast(StkId, ud); + CallInfo *ci = L->ci; + if (L->status == 0) { /* start coroutine? */ + lua_assert(ci == L->base_ci && firstArg > L->base); + if (luaD_precall(L, firstArg - 1, LUA_MULTRET) != PCRLUA) + return; + } + else { /* resuming from previous yield */ + lua_assert(L->status == LUA_YIELD); + L->status = 0; + if (!f_isLua(ci)) { /* `common' yield? */ + /* finish interrupted execution of `OP_CALL' */ + lua_assert(GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_CALL || + GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_TAILCALL); + if (luaD_poscall(L, firstArg)) /* complete it... */ + L->top = L->ci->top; /* and correct top if not multiple results */ + } + else /* yielded inside a hook: just continue its execution */ + L->base = L->ci->base; + } + luaV_execute(L, cast_int(L->ci - L->base_ci)); +} + + +static int resume_error (lua_State *L, const char *msg) { + L->top = L->ci->base; + setsvalue2s(L, L->top, luaS_new(L, msg)); + incr_top(L); + lua_unlock(L); + return LUA_ERRRUN; +} + + +LUA_API int lua_resume (lua_State *L, int nargs) { + int status; + lua_lock(L); + if (L->status != LUA_YIELD && (L->status != 0 || L->ci != L->base_ci)) + return resume_error(L, "cannot resume non-suspended coroutine"); + if (L->nCcalls >= LUAI_MAXCCALLS) + return resume_error(L, "C stack overflow"); + luai_userstateresume(L, nargs); + lua_assert(L->errfunc == 0); + L->baseCcalls = ++L->nCcalls; + status = luaD_rawrunprotected(L, resume, L->top - nargs); + if (status != 0) { /* error? */ + L->status = cast_byte(status); /* mark thread as `dead' */ + luaD_seterrorobj(L, status, L->top); + L->ci->top = L->top; + } + else { + lua_assert(L->nCcalls == L->baseCcalls); + status = L->status; + } + --L->nCcalls; + lua_unlock(L); + return status; +} + + +LUA_API int lua_yield (lua_State *L, int nresults) { + luai_userstateyield(L, nresults); + lua_lock(L); + if (L->nCcalls > L->baseCcalls) + luaG_runerror(L, "attempt to yield across metamethod/C-call boundary"); + L->base = L->top - nresults; /* protect stack slots below */ + L->status = LUA_YIELD; + lua_unlock(L); + return -1; +} + + +int luaD_pcall (lua_State *L, Pfunc func, void *u, + ptrdiff_t old_top, ptrdiff_t ef) { + int status; + unsigned short oldnCcalls = L->nCcalls; + ptrdiff_t old_ci = saveci(L, L->ci); + lu_byte old_allowhooks = L->allowhook; + ptrdiff_t old_errfunc = L->errfunc; + L->errfunc = ef; + status = luaD_rawrunprotected(L, func, u); + if (status != 0) { /* an error occurred? */ + StkId oldtop = restorestack(L, old_top); + luaF_close(L, oldtop); /* close eventual pending closures */ + luaD_seterrorobj(L, status, oldtop); + L->nCcalls = oldnCcalls; + L->ci = restoreci(L, old_ci); + L->base = L->ci->base; + L->savedpc = L->ci->savedpc; + L->allowhook = old_allowhooks; + restore_stack_limit(L); + } + L->errfunc = old_errfunc; + return status; +} + + + +/* +** Execute a protected parser. +*/ +struct SParser { /* data to `f_parser' */ + ZIO *z; + Mbuffer buff; /* buffer to be used by the scanner */ + const char *name; +}; + +static void f_parser (lua_State *L, void *ud) { + int i; + Proto *tf; + Closure *cl; + struct SParser *p = cast(struct SParser *, ud); + int c = luaZ_lookahead(p->z); + luaC_checkGC(L); + tf = ((c == LUA_SIGNATURE[0]) ? luaU_undump : luaY_parser)(L, p->z, + &p->buff, p->name); + cl = luaF_newLclosure(L, tf->nups, hvalue(gt(L))); + cl->l.p = tf; + for (i = 0; i < tf->nups; i++) /* initialize eventual upvalues */ + cl->l.upvals[i] = luaF_newupval(L); + setclvalue(L, L->top, cl); + incr_top(L); +} + + +int luaD_protectedparser (lua_State *L, ZIO *z, const char *name) { + struct SParser p; + int status; + p.z = z; p.name = name; + luaZ_initbuffer(L, &p.buff); + status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc); + luaZ_freebuffer(L, &p.buff); + return status; +} + + diff --git a/external/mit/lua/dist/src/ldo.h b/external/mit/lua/dist/src/ldo.h new file mode 100644 index 000000000..37f2af42e --- /dev/null +++ b/external/mit/lua/dist/src/ldo.h @@ -0,0 +1,59 @@ +/* $NetBSD: ldo.h,v 1.1.1.2 2012/03/15 00:08:09 alnsn Exp $ */ + +/* +** $Id: ldo.h,v 1.1.1.2 2012/03/15 00:08:09 alnsn Exp $ +** Stack and Call structure of Lua +** See Copyright Notice in lua.h +*/ + +#ifndef ldo_h +#define ldo_h + + +#include "lobject.h" +#include "lstate.h" +#include "lzio.h" + + +#define luaD_checkstack(L,n) \ + if ((char *)L->stack_last - (char *)L->top <= (n)*(int)sizeof(TValue)) \ + luaD_growstack(L, n); \ + else condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); + + +#define incr_top(L) {luaD_checkstack(L,1); L->top++;} + +#define savestack(L,p) ((char *)(p) - (char *)L->stack) +#define restorestack(L,n) ((TValue *)((char *)L->stack + (n))) + +#define saveci(L,p) ((char *)(p) - (char *)L->base_ci) +#define restoreci(L,n) ((CallInfo *)((char *)L->base_ci + (n))) + + +/* results from luaD_precall */ +#define PCRLUA 0 /* initiated a call to a Lua function */ +#define PCRC 1 /* did a call to a C function */ +#define PCRYIELD 2 /* C funtion yielded */ + + +/* type of protected functions, to be ran by `runprotected' */ +typedef void (*Pfunc) (lua_State *L, void *ud); + +LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name); +LUAI_FUNC void luaD_callhook (lua_State *L, int event, int line); +LUAI_FUNC int luaD_precall (lua_State *L, StkId func, int nresults); +LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults); +LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u, + ptrdiff_t oldtop, ptrdiff_t ef); +LUAI_FUNC int luaD_poscall (lua_State *L, StkId firstResult); +LUAI_FUNC void luaD_reallocCI (lua_State *L, int newsize); +LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize); +LUAI_FUNC void luaD_growstack (lua_State *L, int n); + +LUAI_FUNC void luaD_throw (lua_State *L, int errcode); +LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud); + +LUAI_FUNC void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop); + +#endif + diff --git a/external/mit/lua/dist/src/ldump.c b/external/mit/lua/dist/src/ldump.c new file mode 100644 index 000000000..eefb6e43f --- /dev/null +++ b/external/mit/lua/dist/src/ldump.c @@ -0,0 +1,166 @@ +/* $NetBSD: ldump.c,v 1.1.1.2 2012/03/15 00:08:12 alnsn Exp $ */ + +/* +** $Id: ldump.c,v 1.1.1.2 2012/03/15 00:08:12 alnsn Exp $ +** save precompiled Lua chunks +** See Copyright Notice in lua.h +*/ + +#include + +#define ldump_c +#define LUA_CORE + +#include "lua.h" + +#include "lobject.h" +#include "lstate.h" +#include "lundump.h" + +typedef struct { + lua_State* L; + lua_Writer writer; + void* data; + int strip; + int status; +} DumpState; + +#define DumpMem(b,n,size,D) DumpBlock(b,(n)*(size),D) +#define DumpVar(x,D) DumpMem(&x,1,sizeof(x),D) + +static void DumpBlock(const void* b, size_t size, DumpState* D) +{ + if (D->status==0) + { + lua_unlock(D->L); + D->status=(*D->writer)(D->L,b,size,D->data); + lua_lock(D->L); + } +} + +static void DumpChar(int y, DumpState* D) +{ + char x=(char)y; + DumpVar(x,D); +} + +static void DumpInt(int x, DumpState* D) +{ + DumpVar(x,D); +} + +static void DumpNumber(lua_Number x, DumpState* D) +{ + DumpVar(x,D); +} + +static void DumpVector(const void* b, int n, size_t size, DumpState* D) +{ + DumpInt(n,D); + DumpMem(b,n,size,D); +} + +static void DumpString(const TString* s, DumpState* D) +{ + if (s==NULL || getstr(s)==NULL) + { + size_t size=0; + DumpVar(size,D); + } + else + { + size_t size=s->tsv.len+1; /* include trailing '\0' */ + DumpVar(size,D); + DumpBlock(getstr(s),size,D); + } +} + +#define DumpCode(f,D) DumpVector(f->code,f->sizecode,sizeof(Instruction),D) + +static void DumpFunction(const Proto* f, const TString* p, DumpState* D); + +static void DumpConstants(const Proto* f, DumpState* D) +{ + int i,n=f->sizek; + DumpInt(n,D); + for (i=0; ik[i]; + DumpChar(ttype(o),D); + switch (ttype(o)) + { + case LUA_TNIL: + break; + case LUA_TBOOLEAN: + DumpChar(bvalue(o),D); + break; + case LUA_TNUMBER: + DumpNumber(nvalue(o),D); + break; + case LUA_TSTRING: + DumpString(rawtsvalue(o),D); + break; + default: + lua_assert(0); /* cannot happen */ + break; + } + } + n=f->sizep; + DumpInt(n,D); + for (i=0; ip[i],f->source,D); +} + +static void DumpDebug(const Proto* f, DumpState* D) +{ + int i,n; + n= (D->strip) ? 0 : f->sizelineinfo; + DumpVector(f->lineinfo,n,sizeof(int),D); + n= (D->strip) ? 0 : f->sizelocvars; + DumpInt(n,D); + for (i=0; ilocvars[i].varname,D); + DumpInt(f->locvars[i].startpc,D); + DumpInt(f->locvars[i].endpc,D); + } + n= (D->strip) ? 0 : f->sizeupvalues; + DumpInt(n,D); + for (i=0; iupvalues[i],D); +} + +static void DumpFunction(const Proto* f, const TString* p, DumpState* D) +{ + DumpString((f->source==p || D->strip) ? NULL : f->source,D); + DumpInt(f->linedefined,D); + DumpInt(f->lastlinedefined,D); + DumpChar(f->nups,D); + DumpChar(f->numparams,D); + DumpChar(f->is_vararg,D); + DumpChar(f->maxstacksize,D); + DumpCode(f,D); + DumpConstants(f,D); + DumpDebug(f,D); +} + +static void DumpHeader(DumpState* D) +{ + char h[LUAC_HEADERSIZE]; + luaU_header(h); + DumpBlock(h,LUAC_HEADERSIZE,D); +} + +/* +** dump Lua function as precompiled chunk +*/ +int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip) +{ + DumpState D; + D.L=L; + D.writer=w; + D.data=data; + D.strip=strip; + D.status=0; + DumpHeader(&D); + DumpFunction(f,NULL,&D); + return D.status; +} diff --git a/external/mit/lua/dist/src/lfunc.c b/external/mit/lua/dist/src/lfunc.c new file mode 100644 index 000000000..4a44e6e55 --- /dev/null +++ b/external/mit/lua/dist/src/lfunc.c @@ -0,0 +1,176 @@ +/* $NetBSD: lfunc.c,v 1.1.1.2 2012/03/15 00:08:10 alnsn Exp $ */ + +/* +** $Id: lfunc.c,v 1.1.1.2 2012/03/15 00:08:10 alnsn Exp $ +** Auxiliary functions to manipulate prototypes and closures +** See Copyright Notice in lua.h +*/ + + +#include + +#define lfunc_c +#define LUA_CORE + +#include "lua.h" + +#include "lfunc.h" +#include "lgc.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" + + + +Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e) { + Closure *c = cast(Closure *, luaM_malloc(L, sizeCclosure(nelems))); + luaC_link(L, obj2gco(c), LUA_TFUNCTION); + c->c.isC = 1; + c->c.env = e; + c->c.nupvalues = cast_byte(nelems); + return c; +} + + +Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e) { + Closure *c = cast(Closure *, luaM_malloc(L, sizeLclosure(nelems))); + luaC_link(L, obj2gco(c), LUA_TFUNCTION); + c->l.isC = 0; + c->l.env = e; + c->l.nupvalues = cast_byte(nelems); + while (nelems--) c->l.upvals[nelems] = NULL; + return c; +} + + +UpVal *luaF_newupval (lua_State *L) { + UpVal *uv = luaM_new(L, UpVal); + luaC_link(L, obj2gco(uv), LUA_TUPVAL); + uv->v = &uv->u.value; + setnilvalue(uv->v); + return uv; +} + + +UpVal *luaF_findupval (lua_State *L, StkId level) { + global_State *g = G(L); + GCObject **pp = &L->openupval; + UpVal *p; + UpVal *uv; + while (*pp != NULL && (p = ngcotouv(*pp))->v >= level) { + lua_assert(p->v != &p->u.value); + if (p->v == level) { /* found a corresponding upvalue? */ + if (isdead(g, obj2gco(p))) /* is it dead? */ + changewhite(obj2gco(p)); /* ressurect it */ + return p; + } + pp = &p->next; + } + uv = luaM_new(L, UpVal); /* not found: create a new one */ + uv->tt = LUA_TUPVAL; + uv->marked = luaC_white(g); + uv->v = level; /* current value lives in the stack */ + uv->next = *pp; /* chain it in the proper position */ + *pp = obj2gco(uv); + uv->u.l.prev = &g->uvhead; /* double link it in `uvhead' list */ + uv->u.l.next = g->uvhead.u.l.next; + uv->u.l.next->u.l.prev = uv; + g->uvhead.u.l.next = uv; + lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); + return uv; +} + + +static void unlinkupval (UpVal *uv) { + lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); + uv->u.l.next->u.l.prev = uv->u.l.prev; /* remove from `uvhead' list */ + uv->u.l.prev->u.l.next = uv->u.l.next; +} + + +void luaF_freeupval (lua_State *L, UpVal *uv) { + if (uv->v != &uv->u.value) /* is it open? */ + unlinkupval(uv); /* remove from open list */ + luaM_free(L, uv); /* free upvalue */ +} + + +void luaF_close (lua_State *L, StkId level) { + UpVal *uv; + global_State *g = G(L); + while (L->openupval != NULL && (uv = ngcotouv(L->openupval))->v >= level) { + GCObject *o = obj2gco(uv); + lua_assert(!isblack(o) && uv->v != &uv->u.value); + L->openupval = uv->next; /* remove from `open' list */ + if (isdead(g, o)) + luaF_freeupval(L, uv); /* free upvalue */ + else { + unlinkupval(uv); + setobj(L, &uv->u.value, uv->v); + uv->v = &uv->u.value; /* now current value lives here */ + luaC_linkupval(L, uv); /* link upvalue into `gcroot' list */ + } + } +} + + +Proto *luaF_newproto (lua_State *L) { + Proto *f = luaM_new(L, Proto); + luaC_link(L, obj2gco(f), LUA_TPROTO); + f->k = NULL; + f->sizek = 0; + f->p = NULL; + f->sizep = 0; + f->code = NULL; + f->sizecode = 0; + f->sizelineinfo = 0; + f->sizeupvalues = 0; + f->nups = 0; + f->upvalues = NULL; + f->numparams = 0; + f->is_vararg = 0; + f->maxstacksize = 0; + f->lineinfo = NULL; + f->sizelocvars = 0; + f->locvars = NULL; + f->linedefined = 0; + f->lastlinedefined = 0; + f->source = NULL; + return f; +} + + +void luaF_freeproto (lua_State *L, Proto *f) { + luaM_freearray(L, f->code, f->sizecode, Instruction); + luaM_freearray(L, f->p, f->sizep, Proto *); + luaM_freearray(L, f->k, f->sizek, TValue); + luaM_freearray(L, f->lineinfo, f->sizelineinfo, int); + luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar); + luaM_freearray(L, f->upvalues, f->sizeupvalues, TString *); + luaM_free(L, f); +} + + +void luaF_freeclosure (lua_State *L, Closure *c) { + int size = (c->c.isC) ? sizeCclosure(c->c.nupvalues) : + sizeLclosure(c->l.nupvalues); + luaM_freemem(L, c, size); +} + + +/* +** Look for n-th local variable at line `line' in function `func'. +** Returns NULL if not found. +*/ +const char *luaF_getlocalname (const Proto *f, int local_number, int pc) { + int i; + for (i = 0; isizelocvars && f->locvars[i].startpc <= pc; i++) { + if (pc < f->locvars[i].endpc) { /* is variable active? */ + local_number--; + if (local_number == 0) + return getstr(f->locvars[i].varname); + } + } + return NULL; /* not found */ +} + diff --git a/external/mit/lua/dist/src/lfunc.h b/external/mit/lua/dist/src/lfunc.h new file mode 100644 index 000000000..ccbf349bc --- /dev/null +++ b/external/mit/lua/dist/src/lfunc.h @@ -0,0 +1,36 @@ +/* $NetBSD: lfunc.h,v 1.1.1.2 2012/03/15 00:08:04 alnsn Exp $ */ + +/* +** $Id: lfunc.h,v 1.1.1.2 2012/03/15 00:08:04 alnsn Exp $ +** Auxiliary functions to manipulate prototypes and closures +** See Copyright Notice in lua.h +*/ + +#ifndef lfunc_h +#define lfunc_h + + +#include "lobject.h" + + +#define sizeCclosure(n) (cast(int, sizeof(CClosure)) + \ + cast(int, sizeof(TValue)*((n)-1))) + +#define sizeLclosure(n) (cast(int, sizeof(LClosure)) + \ + cast(int, sizeof(TValue *)*((n)-1))) + + +LUAI_FUNC Proto *luaF_newproto (lua_State *L); +LUAI_FUNC Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e); +LUAI_FUNC Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e); +LUAI_FUNC UpVal *luaF_newupval (lua_State *L); +LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level); +LUAI_FUNC void luaF_close (lua_State *L, StkId level); +LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f); +LUAI_FUNC void luaF_freeclosure (lua_State *L, Closure *c); +LUAI_FUNC void luaF_freeupval (lua_State *L, UpVal *uv); +LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number, + int pc); + + +#endif diff --git a/external/mit/lua/dist/src/lgc.c b/external/mit/lua/dist/src/lgc.c new file mode 100644 index 000000000..d62f781ca --- /dev/null +++ b/external/mit/lua/dist/src/lgc.c @@ -0,0 +1,712 @@ +/* $NetBSD: lgc.c,v 1.1.1.2 2012/03/15 00:08:13 alnsn Exp $ */ + +/* +** $Id: lgc.c,v 1.1.1.2 2012/03/15 00:08:13 alnsn Exp $ +** Garbage Collector +** See Copyright Notice in lua.h +*/ + +#include + +#define lgc_c +#define LUA_CORE + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lgc.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" + + +#define GCSTEPSIZE 1024u +#define GCSWEEPMAX 40 +#define GCSWEEPCOST 10 +#define GCFINALIZECOST 100 + + +#define maskmarks cast_byte(~(bitmask(BLACKBIT)|WHITEBITS)) + +#define makewhite(g,x) \ + ((x)->gch.marked = cast_byte(((x)->gch.marked & maskmarks) | luaC_white(g))) + +#define white2gray(x) reset2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT) +#define black2gray(x) resetbit((x)->gch.marked, BLACKBIT) + +#define stringmark(s) reset2bits((s)->tsv.marked, WHITE0BIT, WHITE1BIT) + + +#define isfinalized(u) testbit((u)->marked, FINALIZEDBIT) +#define markfinalized(u) l_setbit((u)->marked, FINALIZEDBIT) + + +#define KEYWEAK bitmask(KEYWEAKBIT) +#define VALUEWEAK bitmask(VALUEWEAKBIT) + + + +#define markvalue(g,o) { checkconsistency(o); \ + if (iscollectable(o) && iswhite(gcvalue(o))) reallymarkobject(g,gcvalue(o)); } + +#define markobject(g,t) { if (iswhite(obj2gco(t))) \ + reallymarkobject(g, obj2gco(t)); } + + +#define setthreshold(g) (g->GCthreshold = (g->estimate/100) * g->gcpause) + + +static void removeentry (Node *n) { + lua_assert(ttisnil(gval(n))); + if (iscollectable(gkey(n))) + setttype(gkey(n), LUA_TDEADKEY); /* dead key; remove it */ +} + + +static void reallymarkobject (global_State *g, GCObject *o) { + lua_assert(iswhite(o) && !isdead(g, o)); + white2gray(o); + switch (o->gch.tt) { + case LUA_TSTRING: { + return; + } + case LUA_TUSERDATA: { + Table *mt = gco2u(o)->metatable; + gray2black(o); /* udata are never gray */ + if (mt) markobject(g, mt); + markobject(g, gco2u(o)->env); + return; + } + case LUA_TUPVAL: { + UpVal *uv = gco2uv(o); + markvalue(g, uv->v); + if (uv->v == &uv->u.value) /* closed? */ + gray2black(o); /* open upvalues are never black */ + return; + } + case LUA_TFUNCTION: { + gco2cl(o)->c.gclist = g->gray; + g->gray = o; + break; + } + case LUA_TTABLE: { + gco2h(o)->gclist = g->gray; + g->gray = o; + break; + } + case LUA_TTHREAD: { + gco2th(o)->gclist = g->gray; + g->gray = o; + break; + } + case LUA_TPROTO: { + gco2p(o)->gclist = g->gray; + g->gray = o; + break; + } + default: lua_assert(0); + } +} + + +static void marktmu (global_State *g) { + GCObject *u = g->tmudata; + if (u) { + do { + u = u->gch.next; + makewhite(g, u); /* may be marked, if left from previous GC */ + reallymarkobject(g, u); + } while (u != g->tmudata); + } +} + + +/* move `dead' udata that need finalization to list `tmudata' */ +size_t luaC_separateudata (lua_State *L, int all) { + global_State *g = G(L); + size_t deadmem = 0; + GCObject **p = &g->mainthread->next; + GCObject *curr; + while ((curr = *p) != NULL) { + if (!(iswhite(curr) || all) || isfinalized(gco2u(curr))) + p = &curr->gch.next; /* don't bother with them */ + else if (fasttm(L, gco2u(curr)->metatable, TM_GC) == NULL) { + markfinalized(gco2u(curr)); /* don't need finalization */ + p = &curr->gch.next; + } + else { /* must call its gc method */ + deadmem += sizeudata(gco2u(curr)); + markfinalized(gco2u(curr)); + *p = curr->gch.next; + /* link `curr' at the end of `tmudata' list */ + if (g->tmudata == NULL) /* list is empty? */ + g->tmudata = curr->gch.next = curr; /* creates a circular list */ + else { + curr->gch.next = g->tmudata->gch.next; + g->tmudata->gch.next = curr; + g->tmudata = curr; + } + } + } + return deadmem; +} + + +static int traversetable (global_State *g, Table *h) { + int i; + int weakkey = 0; + int weakvalue = 0; + const TValue *mode; + if (h->metatable) + markobject(g, h->metatable); + mode = gfasttm(g, h->metatable, TM_MODE); + if (mode && ttisstring(mode)) { /* is there a weak mode? */ + weakkey = (strchr(svalue(mode), 'k') != NULL); + weakvalue = (strchr(svalue(mode), 'v') != NULL); + if (weakkey || weakvalue) { /* is really weak? */ + h->marked &= ~(KEYWEAK | VALUEWEAK); /* clear bits */ + h->marked |= cast_byte((weakkey << KEYWEAKBIT) | + (weakvalue << VALUEWEAKBIT)); + h->gclist = g->weak; /* must be cleared after GC, ... */ + g->weak = obj2gco(h); /* ... so put in the appropriate list */ + } + } + if (weakkey && weakvalue) return 1; + if (!weakvalue) { + i = h->sizearray; + while (i--) + markvalue(g, &h->array[i]); + } + i = sizenode(h); + while (i--) { + Node *n = gnode(h, i); + lua_assert(ttype(gkey(n)) != LUA_TDEADKEY || ttisnil(gval(n))); + if (ttisnil(gval(n))) + removeentry(n); /* remove empty entries */ + else { + lua_assert(!ttisnil(gkey(n))); + if (!weakkey) markvalue(g, gkey(n)); + if (!weakvalue) markvalue(g, gval(n)); + } + } + return weakkey || weakvalue; +} + + +/* +** All marks are conditional because a GC may happen while the +** prototype is still being created +*/ +static void traverseproto (global_State *g, Proto *f) { + int i; + if (f->source) stringmark(f->source); + for (i=0; isizek; i++) /* mark literals */ + markvalue(g, &f->k[i]); + for (i=0; isizeupvalues; i++) { /* mark upvalue names */ + if (f->upvalues[i]) + stringmark(f->upvalues[i]); + } + for (i=0; isizep; i++) { /* mark nested protos */ + if (f->p[i]) + markobject(g, f->p[i]); + } + for (i=0; isizelocvars; i++) { /* mark local-variable names */ + if (f->locvars[i].varname) + stringmark(f->locvars[i].varname); + } +} + + + +static void traverseclosure (global_State *g, Closure *cl) { + markobject(g, cl->c.env); + if (cl->c.isC) { + int i; + for (i=0; ic.nupvalues; i++) /* mark its upvalues */ + markvalue(g, &cl->c.upvalue[i]); + } + else { + int i; + lua_assert(cl->l.nupvalues == cl->l.p->nups); + markobject(g, cl->l.p); + for (i=0; il.nupvalues; i++) /* mark its upvalues */ + markobject(g, cl->l.upvals[i]); + } +} + + +static void checkstacksizes (lua_State *L, StkId max) { + int ci_used = cast_int(L->ci - L->base_ci); /* number of `ci' in use */ + int s_used = cast_int(max - L->stack); /* part of stack in use */ + if (L->size_ci > LUAI_MAXCALLS) /* handling overflow? */ + return; /* do not touch the stacks */ + if (4*ci_used < L->size_ci && 2*BASIC_CI_SIZE < L->size_ci) + luaD_reallocCI(L, L->size_ci/2); /* still big enough... */ + condhardstacktests(luaD_reallocCI(L, ci_used + 1)); + if (4*s_used < L->stacksize && + 2*(BASIC_STACK_SIZE+EXTRA_STACK) < L->stacksize) + luaD_reallocstack(L, L->stacksize/2); /* still big enough... */ + condhardstacktests(luaD_reallocstack(L, s_used)); +} + + +static void traversestack (global_State *g, lua_State *l) { + StkId o, lim; + CallInfo *ci; + markvalue(g, gt(l)); + lim = l->top; + for (ci = l->base_ci; ci <= l->ci; ci++) { + lua_assert(ci->top <= l->stack_last); + if (lim < ci->top) lim = ci->top; + } + for (o = l->stack; o < l->top; o++) + markvalue(g, o); + for (; o <= lim; o++) + setnilvalue(o); + checkstacksizes(l, lim); +} + + +/* +** traverse one gray object, turning it to black. +** Returns `quantity' traversed. +*/ +static l_mem propagatemark (global_State *g) { + GCObject *o = g->gray; + lua_assert(isgray(o)); + gray2black(o); + switch (o->gch.tt) { + case LUA_TTABLE: { + Table *h = gco2h(o); + g->gray = h->gclist; + if (traversetable(g, h)) /* table is weak? */ + black2gray(o); /* keep it gray */ + return sizeof(Table) + sizeof(TValue) * h->sizearray + + sizeof(Node) * sizenode(h); + } + case LUA_TFUNCTION: { + Closure *cl = gco2cl(o); + g->gray = cl->c.gclist; + traverseclosure(g, cl); + return (cl->c.isC) ? sizeCclosure(cl->c.nupvalues) : + sizeLclosure(cl->l.nupvalues); + } + case LUA_TTHREAD: { + lua_State *th = gco2th(o); + g->gray = th->gclist; + th->gclist = g->grayagain; + g->grayagain = o; + black2gray(o); + traversestack(g, th); + return sizeof(lua_State) + sizeof(TValue) * th->stacksize + + sizeof(CallInfo) * th->size_ci; + } + case LUA_TPROTO: { + Proto *p = gco2p(o); + g->gray = p->gclist; + traverseproto(g, p); + return sizeof(Proto) + sizeof(Instruction) * p->sizecode + + sizeof(Proto *) * p->sizep + + sizeof(TValue) * p->sizek + + sizeof(int) * p->sizelineinfo + + sizeof(LocVar) * p->sizelocvars + + sizeof(TString *) * p->sizeupvalues; + } + default: lua_assert(0); return 0; + } +} + + +static size_t propagateall (global_State *g) { + size_t m = 0; + while (g->gray) m += propagatemark(g); + return m; +} + + +/* +** The next function tells whether a key or value can be cleared from +** a weak table. Non-collectable objects are never removed from weak +** tables. Strings behave as `values', so are never removed too. for +** other objects: if really collected, cannot keep them; for userdata +** being finalized, keep them in keys, but not in values +*/ +static int iscleared (const TValue *o, int iskey) { + if (!iscollectable(o)) return 0; + if (ttisstring(o)) { + stringmark(rawtsvalue(o)); /* strings are `values', so are never weak */ + return 0; + } + return iswhite(gcvalue(o)) || + (ttisuserdata(o) && (!iskey && isfinalized(uvalue(o)))); +} + + +/* +** clear collected entries from weaktables +*/ +static void cleartable (GCObject *l) { + while (l) { + Table *h = gco2h(l); + int i = h->sizearray; + lua_assert(testbit(h->marked, VALUEWEAKBIT) || + testbit(h->marked, KEYWEAKBIT)); + if (testbit(h->marked, VALUEWEAKBIT)) { + while (i--) { + TValue *o = &h->array[i]; + if (iscleared(o, 0)) /* value was collected? */ + setnilvalue(o); /* remove value */ + } + } + i = sizenode(h); + while (i--) { + Node *n = gnode(h, i); + if (!ttisnil(gval(n)) && /* non-empty entry? */ + (iscleared(key2tval(n), 1) || iscleared(gval(n), 0))) { + setnilvalue(gval(n)); /* remove value ... */ + removeentry(n); /* remove entry from table */ + } + } + l = h->gclist; + } +} + + +static void freeobj (lua_State *L, GCObject *o) { + switch (o->gch.tt) { + case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break; + case LUA_TFUNCTION: luaF_freeclosure(L, gco2cl(o)); break; + case LUA_TUPVAL: luaF_freeupval(L, gco2uv(o)); break; + case LUA_TTABLE: luaH_free(L, gco2h(o)); break; + case LUA_TTHREAD: { + lua_assert(gco2th(o) != L && gco2th(o) != G(L)->mainthread); + luaE_freethread(L, gco2th(o)); + break; + } + case LUA_TSTRING: { + G(L)->strt.nuse--; + luaM_freemem(L, o, sizestring(gco2ts(o))); + break; + } + case LUA_TUSERDATA: { + luaM_freemem(L, o, sizeudata(gco2u(o))); + break; + } + default: lua_assert(0); + } +} + + + +#define sweepwholelist(L,p) sweeplist(L,p,MAX_LUMEM) + + +static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { + GCObject *curr; + global_State *g = G(L); + int deadmask = otherwhite(g); + while ((curr = *p) != NULL && count-- > 0) { + if (curr->gch.tt == LUA_TTHREAD) /* sweep open upvalues of each thread */ + sweepwholelist(L, &gco2th(curr)->openupval); + if ((curr->gch.marked ^ WHITEBITS) & deadmask) { /* not dead? */ + lua_assert(!isdead(g, curr) || testbit(curr->gch.marked, FIXEDBIT)); + makewhite(g, curr); /* make it white (for next cycle) */ + p = &curr->gch.next; + } + else { /* must erase `curr' */ + lua_assert(isdead(g, curr) || deadmask == bitmask(SFIXEDBIT)); + *p = curr->gch.next; + if (curr == g->rootgc) /* is the first element of the list? */ + g->rootgc = curr->gch.next; /* adjust first */ + freeobj(L, curr); + } + } + return p; +} + + +static void checkSizes (lua_State *L) { + global_State *g = G(L); + /* check size of string hash */ + if (g->strt.nuse < cast(lu_int32, g->strt.size/4) && + g->strt.size > MINSTRTABSIZE*2) + luaS_resize(L, g->strt.size/2); /* table is too big */ + /* check size of buffer */ + if (luaZ_sizebuffer(&g->buff) > LUA_MINBUFFER*2) { /* buffer too big? */ + size_t newsize = luaZ_sizebuffer(&g->buff) / 2; + luaZ_resizebuffer(L, &g->buff, newsize); + } +} + + +static void GCTM (lua_State *L) { + global_State *g = G(L); + GCObject *o = g->tmudata->gch.next; /* get first element */ + Udata *udata = rawgco2u(o); + const TValue *tm; + /* remove udata from `tmudata' */ + if (o == g->tmudata) /* last element? */ + g->tmudata = NULL; + else + g->tmudata->gch.next = udata->uv.next; + udata->uv.next = g->mainthread->next; /* return it to `root' list */ + g->mainthread->next = o; + makewhite(g, o); + tm = fasttm(L, udata->uv.metatable, TM_GC); + if (tm != NULL) { + lu_byte oldah = L->allowhook; + lu_mem oldt = g->GCthreshold; + L->allowhook = 0; /* stop debug hooks during GC tag method */ + g->GCthreshold = 2*g->totalbytes; /* avoid GC steps */ + setobj2s(L, L->top, tm); + setuvalue(L, L->top+1, udata); + L->top += 2; + luaD_call(L, L->top - 2, 0); + L->allowhook = oldah; /* restore hooks */ + g->GCthreshold = oldt; /* restore threshold */ + } +} + + +/* +** Call all GC tag methods +*/ +void luaC_callGCTM (lua_State *L) { + while (G(L)->tmudata) + GCTM(L); +} + + +void luaC_freeall (lua_State *L) { + global_State *g = G(L); + int i; + g->currentwhite = WHITEBITS | bitmask(SFIXEDBIT); /* mask to collect all elements */ + sweepwholelist(L, &g->rootgc); + for (i = 0; i < g->strt.size; i++) /* free all string lists */ + sweepwholelist(L, &g->strt.hash[i]); +} + + +static void markmt (global_State *g) { + int i; + for (i=0; imt[i]) markobject(g, g->mt[i]); +} + + +/* mark root set */ +static void markroot (lua_State *L) { + global_State *g = G(L); + g->gray = NULL; + g->grayagain = NULL; + g->weak = NULL; + markobject(g, g->mainthread); + /* make global table be traversed before main stack */ + markvalue(g, gt(g->mainthread)); + markvalue(g, registry(L)); + markmt(g); + g->gcstate = GCSpropagate; +} + + +static void remarkupvals (global_State *g) { + UpVal *uv; + for (uv = g->uvhead.u.l.next; uv != &g->uvhead; uv = uv->u.l.next) { + lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); + if (isgray(obj2gco(uv))) + markvalue(g, uv->v); + } +} + + +static void atomic (lua_State *L) { + global_State *g = G(L); + size_t udsize; /* total size of userdata to be finalized */ + /* remark occasional upvalues of (maybe) dead threads */ + remarkupvals(g); + /* traverse objects cautch by write barrier and by 'remarkupvals' */ + propagateall(g); + /* remark weak tables */ + g->gray = g->weak; + g->weak = NULL; + lua_assert(!iswhite(obj2gco(g->mainthread))); + markobject(g, L); /* mark running thread */ + markmt(g); /* mark basic metatables (again) */ + propagateall(g); + /* remark gray again */ + g->gray = g->grayagain; + g->grayagain = NULL; + propagateall(g); + udsize = luaC_separateudata(L, 0); /* separate userdata to be finalized */ + marktmu(g); /* mark `preserved' userdata */ + udsize += propagateall(g); /* remark, to propagate `preserveness' */ + cleartable(g->weak); /* remove collected objects from weak tables */ + /* flip current white */ + g->currentwhite = cast_byte(otherwhite(g)); + g->sweepstrgc = 0; + g->sweepgc = &g->rootgc; + g->gcstate = GCSsweepstring; + g->estimate = g->totalbytes - udsize; /* first estimate */ +} + + +static l_mem singlestep (lua_State *L) { + global_State *g = G(L); + /*lua_checkmemory(L);*/ + switch (g->gcstate) { + case GCSpause: { + markroot(L); /* start a new collection */ + return 0; + } + case GCSpropagate: { + if (g->gray) + return propagatemark(g); + else { /* no more `gray' objects */ + atomic(L); /* finish mark phase */ + return 0; + } + } + case GCSsweepstring: { + lu_mem old = g->totalbytes; + sweepwholelist(L, &g->strt.hash[g->sweepstrgc++]); + if (g->sweepstrgc >= g->strt.size) /* nothing more to sweep? */ + g->gcstate = GCSsweep; /* end sweep-string phase */ + lua_assert(old >= g->totalbytes); + g->estimate -= old - g->totalbytes; + return GCSWEEPCOST; + } + case GCSsweep: { + lu_mem old = g->totalbytes; + g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX); + if (*g->sweepgc == NULL) { /* nothing more to sweep? */ + checkSizes(L); + g->gcstate = GCSfinalize; /* end sweep phase */ + } + lua_assert(old >= g->totalbytes); + g->estimate -= old - g->totalbytes; + return GCSWEEPMAX*GCSWEEPCOST; + } + case GCSfinalize: { + if (g->tmudata) { + GCTM(L); + if (g->estimate > GCFINALIZECOST) + g->estimate -= GCFINALIZECOST; + return GCFINALIZECOST; + } + else { + g->gcstate = GCSpause; /* end collection */ + g->gcdept = 0; + return 0; + } + } + default: lua_assert(0); return 0; + } +} + + +void luaC_step (lua_State *L) { + global_State *g = G(L); + l_mem lim = (GCSTEPSIZE/100) * g->gcstepmul; + if (lim == 0) + lim = (MAX_LUMEM-1)/2; /* no limit */ + g->gcdept += g->totalbytes - g->GCthreshold; + do { + lim -= singlestep(L); + if (g->gcstate == GCSpause) + break; + } while (lim > 0); + if (g->gcstate != GCSpause) { + if (g->gcdept < GCSTEPSIZE) + g->GCthreshold = g->totalbytes + GCSTEPSIZE; /* - lim/g->gcstepmul;*/ + else { + g->gcdept -= GCSTEPSIZE; + g->GCthreshold = g->totalbytes; + } + } + else { + setthreshold(g); + } +} + + +void luaC_fullgc (lua_State *L) { + global_State *g = G(L); + if (g->gcstate <= GCSpropagate) { + /* reset sweep marks to sweep all elements (returning them to white) */ + g->sweepstrgc = 0; + g->sweepgc = &g->rootgc; + /* reset other collector lists */ + g->gray = NULL; + g->grayagain = NULL; + g->weak = NULL; + g->gcstate = GCSsweepstring; + } + lua_assert(g->gcstate != GCSpause && g->gcstate != GCSpropagate); + /* finish any pending sweep phase */ + while (g->gcstate != GCSfinalize) { + lua_assert(g->gcstate == GCSsweepstring || g->gcstate == GCSsweep); + singlestep(L); + } + markroot(L); + while (g->gcstate != GCSpause) { + singlestep(L); + } + setthreshold(g); +} + + +void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) { + global_State *g = G(L); + lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); + lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause); + lua_assert(ttype(&o->gch) != LUA_TTABLE); + /* must keep invariant? */ + if (g->gcstate == GCSpropagate) + reallymarkobject(g, v); /* restore invariant */ + else /* don't mind */ + makewhite(g, o); /* mark as white just to avoid other barriers */ +} + + +void luaC_barrierback (lua_State *L, Table *t) { + global_State *g = G(L); + GCObject *o = obj2gco(t); + lua_assert(isblack(o) && !isdead(g, o)); + lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause); + black2gray(o); /* make table gray (again) */ + t->gclist = g->grayagain; + g->grayagain = o; +} + + +void luaC_link (lua_State *L, GCObject *o, lu_byte tt) { + global_State *g = G(L); + o->gch.next = g->rootgc; + g->rootgc = o; + o->gch.marked = luaC_white(g); + o->gch.tt = tt; +} + + +void luaC_linkupval (lua_State *L, UpVal *uv) { + global_State *g = G(L); + GCObject *o = obj2gco(uv); + o->gch.next = g->rootgc; /* link upvalue into `rootgc' list */ + g->rootgc = o; + if (isgray(o)) { + if (g->gcstate == GCSpropagate) { + gray2black(o); /* closed upvalues need barrier */ + luaC_barrier(L, uv, uv->v); + } + else { /* sweep phase: sweep it (turning it into white) */ + makewhite(g, o); + lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause); + } + } +} + diff --git a/external/mit/lua/dist/src/lgc.h b/external/mit/lua/dist/src/lgc.h new file mode 100644 index 000000000..212e1f202 --- /dev/null +++ b/external/mit/lua/dist/src/lgc.h @@ -0,0 +1,112 @@ +/* $NetBSD: lgc.h,v 1.1.1.2 2012/03/15 00:08:10 alnsn Exp $ */ + +/* +** $Id: lgc.h,v 1.1.1.2 2012/03/15 00:08:10 alnsn Exp $ +** Garbage Collector +** See Copyright Notice in lua.h +*/ + +#ifndef lgc_h +#define lgc_h + + +#include "lobject.h" + + +/* +** Possible states of the Garbage Collector +*/ +#define GCSpause 0 +#define GCSpropagate 1 +#define GCSsweepstring 2 +#define GCSsweep 3 +#define GCSfinalize 4 + + +/* +** some userful bit tricks +*/ +#define resetbits(x,m) ((x) &= cast(lu_byte, ~(m))) +#define setbits(x,m) ((x) |= (m)) +#define testbits(x,m) ((x) & (m)) +#define bitmask(b) (1<<(b)) +#define bit2mask(b1,b2) (bitmask(b1) | bitmask(b2)) +#define l_setbit(x,b) setbits(x, bitmask(b)) +#define resetbit(x,b) resetbits(x, bitmask(b)) +#define testbit(x,b) testbits(x, bitmask(b)) +#define set2bits(x,b1,b2) setbits(x, (bit2mask(b1, b2))) +#define reset2bits(x,b1,b2) resetbits(x, (bit2mask(b1, b2))) +#define test2bits(x,b1,b2) testbits(x, (bit2mask(b1, b2))) + + + +/* +** Layout for bit use in `marked' field: +** bit 0 - object is white (type 0) +** bit 1 - object is white (type 1) +** bit 2 - object is black +** bit 3 - for userdata: has been finalized +** bit 3 - for tables: has weak keys +** bit 4 - for tables: has weak values +** bit 5 - object is fixed (should not be collected) +** bit 6 - object is "super" fixed (only the main thread) +*/ + + +#define WHITE0BIT 0 +#define WHITE1BIT 1 +#define BLACKBIT 2 +#define FINALIZEDBIT 3 +#define KEYWEAKBIT 3 +#define VALUEWEAKBIT 4 +#define FIXEDBIT 5 +#define SFIXEDBIT 6 +#define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) + + +#define iswhite(x) test2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT) +#define isblack(x) testbit((x)->gch.marked, BLACKBIT) +#define isgray(x) (!isblack(x) && !iswhite(x)) + +#define otherwhite(g) (g->currentwhite ^ WHITEBITS) +#define isdead(g,v) ((v)->gch.marked & otherwhite(g) & WHITEBITS) + +#define changewhite(x) ((x)->gch.marked ^= WHITEBITS) +#define gray2black(x) l_setbit((x)->gch.marked, BLACKBIT) + +#define valiswhite(x) (iscollectable(x) && iswhite(gcvalue(x))) + +#define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS) + + +#define luaC_checkGC(L) { \ + condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); \ + if (G(L)->totalbytes >= G(L)->GCthreshold) \ + luaC_step(L); } + + +#define luaC_barrier(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p))) \ + luaC_barrierf(L,obj2gco(p),gcvalue(v)); } + +#define luaC_barriert(L,t,v) { if (valiswhite(v) && isblack(obj2gco(t))) \ + luaC_barrierback(L,t); } + +#define luaC_objbarrier(L,p,o) \ + { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) \ + luaC_barrierf(L,obj2gco(p),obj2gco(o)); } + +#define luaC_objbarriert(L,t,o) \ + { if (iswhite(obj2gco(o)) && isblack(obj2gco(t))) luaC_barrierback(L,t); } + +LUAI_FUNC size_t luaC_separateudata (lua_State *L, int all); +LUAI_FUNC void luaC_callGCTM (lua_State *L); +LUAI_FUNC void luaC_freeall (lua_State *L); +LUAI_FUNC void luaC_step (lua_State *L); +LUAI_FUNC void luaC_fullgc (lua_State *L); +LUAI_FUNC void luaC_link (lua_State *L, GCObject *o, lu_byte tt); +LUAI_FUNC void luaC_linkupval (lua_State *L, UpVal *uv); +LUAI_FUNC void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v); +LUAI_FUNC void luaC_barrierback (lua_State *L, Table *t); + + +#endif diff --git a/external/mit/lua/dist/src/linit.c b/external/mit/lua/dist/src/linit.c new file mode 100644 index 000000000..e80ebd852 --- /dev/null +++ b/external/mit/lua/dist/src/linit.c @@ -0,0 +1,40 @@ +/* $NetBSD: linit.c,v 1.1.1.2 2012/03/15 00:08:04 alnsn Exp $ */ + +/* +** $Id: linit.c,v 1.1.1.2 2012/03/15 00:08:04 alnsn Exp $ +** Initialization of libraries for lua.c +** See Copyright Notice in lua.h +*/ + + +#define linit_c +#define LUA_LIB + +#include "lua.h" + +#include "lualib.h" +#include "lauxlib.h" + + +static const luaL_Reg lualibs[] = { + {"", luaopen_base}, + {LUA_LOADLIBNAME, luaopen_package}, + {LUA_TABLIBNAME, luaopen_table}, + {LUA_IOLIBNAME, luaopen_io}, + {LUA_OSLIBNAME, luaopen_os}, + {LUA_STRLIBNAME, luaopen_string}, + {LUA_MATHLIBNAME, luaopen_math}, + {LUA_DBLIBNAME, luaopen_debug}, + {NULL, NULL} +}; + + +LUALIB_API void luaL_openlibs (lua_State *L) { + const luaL_Reg *lib = lualibs; + for (; lib->func; lib++) { + lua_pushcfunction(L, lib->func); + lua_pushstring(L, lib->name); + lua_call(L, 1, 0); + } +} + diff --git a/external/mit/lua/dist/src/liolib.c b/external/mit/lua/dist/src/liolib.c new file mode 100644 index 000000000..6a7413f52 --- /dev/null +++ b/external/mit/lua/dist/src/liolib.c @@ -0,0 +1,558 @@ +/* $NetBSD: liolib.c,v 1.1.1.2 2012/03/15 00:08:04 alnsn Exp $ */ + +/* +** $Id: liolib.c,v 1.1.1.2 2012/03/15 00:08:04 alnsn Exp $ +** Standard I/O (and system) library +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include +#include + +#define liolib_c +#define LUA_LIB + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + + +#define IO_INPUT 1 +#define IO_OUTPUT 2 + + +static const char *const fnames[] = {"input", "output"}; + + +static int pushresult (lua_State *L, int i, const char *filename) { + int en = errno; /* calls to Lua API may change this value */ + if (i) { + lua_pushboolean(L, 1); + return 1; + } + else { + lua_pushnil(L); + if (filename) + lua_pushfstring(L, "%s: %s", filename, strerror(en)); + else + lua_pushfstring(L, "%s", strerror(en)); + lua_pushinteger(L, en); + return 3; + } +} + + +static void fileerror (lua_State *L, int arg, const char *filename) { + lua_pushfstring(L, "%s: %s", filename, strerror(errno)); + luaL_argerror(L, arg, lua_tostring(L, -1)); +} + + +#define tofilep(L) ((FILE **)luaL_checkudata(L, 1, LUA_FILEHANDLE)) + + +static int io_type (lua_State *L) { + void *ud; + luaL_checkany(L, 1); + ud = lua_touserdata(L, 1); + lua_getfield(L, LUA_REGISTRYINDEX, LUA_FILEHANDLE); + if (ud == NULL || !lua_getmetatable(L, 1) || !lua_rawequal(L, -2, -1)) + lua_pushnil(L); /* not a file */ + else if (*((FILE **)ud) == NULL) + lua_pushliteral(L, "closed file"); + else + lua_pushliteral(L, "file"); + return 1; +} + + +static FILE *tofile (lua_State *L) { + FILE **f = tofilep(L); + if (*f == NULL) + luaL_error(L, "attempt to use a closed file"); + return *f; +} + + + +/* +** When creating file handles, always creates a `closed' file handle +** before opening the actual file; so, if there is a memory error, the +** file is not left opened. +*/ +static FILE **newfile (lua_State *L) { + FILE **pf = (FILE **)lua_newuserdata(L, sizeof(FILE *)); + *pf = NULL; /* file handle is currently `closed' */ + luaL_getmetatable(L, LUA_FILEHANDLE); + lua_setmetatable(L, -2); + return pf; +} + + +/* +** function to (not) close the standard files stdin, stdout, and stderr +*/ +static int io_noclose (lua_State *L) { + lua_pushnil(L); + lua_pushliteral(L, "cannot close standard file"); + return 2; +} + + +/* +** function to close 'popen' files +*/ +static int io_pclose (lua_State *L) { + FILE **p = tofilep(L); + int ok = lua_pclose(L, *p); + *p = NULL; + return pushresult(L, ok, NULL); +} + + +/* +** function to close regular files +*/ +static int io_fclose (lua_State *L) { + FILE **p = tofilep(L); + int ok = (fclose(*p) == 0); + *p = NULL; + return pushresult(L, ok, NULL); +} + + +static int aux_close (lua_State *L) { + lua_getfenv(L, 1); + lua_getfield(L, -1, "__close"); + return (lua_tocfunction(L, -1))(L); +} + + +static int io_close (lua_State *L) { + if (lua_isnone(L, 1)) + lua_rawgeti(L, LUA_ENVIRONINDEX, IO_OUTPUT); + tofile(L); /* make sure argument is a file */ + return aux_close(L); +} + + +static int io_gc (lua_State *L) { + FILE *f = *tofilep(L); + /* ignore closed files */ + if (f != NULL) + aux_close(L); + return 0; +} + + +static int io_tostring (lua_State *L) { + FILE *f = *tofilep(L); + if (f == NULL) + lua_pushliteral(L, "file (closed)"); + else + lua_pushfstring(L, "file (%p)", f); + return 1; +} + + +static int io_open (lua_State *L) { + const char *filename = luaL_checkstring(L, 1); + const char *mode = luaL_optstring(L, 2, "r"); + FILE **pf = newfile(L); + *pf = fopen(filename, mode); + return (*pf == NULL) ? pushresult(L, 0, filename) : 1; +} + + +/* +** this function has a separated environment, which defines the +** correct __close for 'popen' files +*/ +static int io_popen (lua_State *L) { + const char *filename = luaL_checkstring(L, 1); + const char *mode = luaL_optstring(L, 2, "r"); + FILE **pf = newfile(L); + *pf = lua_popen(L, filename, mode); + return (*pf == NULL) ? pushresult(L, 0, filename) : 1; +} + + +static int io_tmpfile (lua_State *L) { + FILE **pf = newfile(L); + *pf = tmpfile(); + return (*pf == NULL) ? pushresult(L, 0, NULL) : 1; +} + + +static FILE *getiofile (lua_State *L, int findex) { + FILE *f; + lua_rawgeti(L, LUA_ENVIRONINDEX, findex); + f = *(FILE **)lua_touserdata(L, -1); + if (f == NULL) + luaL_error(L, "standard %s file is closed", fnames[findex - 1]); + return f; +} + + +static int g_iofile (lua_State *L, int f, const char *mode) { + if (!lua_isnoneornil(L, 1)) { + const char *filename = lua_tostring(L, 1); + if (filename) { + FILE **pf = newfile(L); + *pf = fopen(filename, mode); + if (*pf == NULL) + fileerror(L, 1, filename); + } + else { + tofile(L); /* check that it's a valid file handle */ + lua_pushvalue(L, 1); + } + lua_rawseti(L, LUA_ENVIRONINDEX, f); + } + /* return current value */ + lua_rawgeti(L, LUA_ENVIRONINDEX, f); + return 1; +} + + +static int io_input (lua_State *L) { + return g_iofile(L, IO_INPUT, "r"); +} + + +static int io_output (lua_State *L) { + return g_iofile(L, IO_OUTPUT, "w"); +} + + +static int io_readline (lua_State *L); + + +static void aux_lines (lua_State *L, int idx, int toclose) { + lua_pushvalue(L, idx); + lua_pushboolean(L, toclose); /* close/not close file when finished */ + lua_pushcclosure(L, io_readline, 2); +} + + +static int f_lines (lua_State *L) { + tofile(L); /* check that it's a valid file handle */ + aux_lines(L, 1, 0); + return 1; +} + + +static int io_lines (lua_State *L) { + if (lua_isnoneornil(L, 1)) { /* no arguments? */ + /* will iterate over default input */ + lua_rawgeti(L, LUA_ENVIRONINDEX, IO_INPUT); + return f_lines(L); + } + else { + const char *filename = luaL_checkstring(L, 1); + FILE **pf = newfile(L); + *pf = fopen(filename, "r"); + if (*pf == NULL) + fileerror(L, 1, filename); + aux_lines(L, lua_gettop(L), 1); + return 1; + } +} + + +/* +** {====================================================== +** READ +** ======================================================= +*/ + + +static int read_number (lua_State *L, FILE *f) { + lua_Number d; + if (fscanf(f, LUA_NUMBER_SCAN, &d) == 1) { + lua_pushnumber(L, d); + return 1; + } + else { + lua_pushnil(L); /* "result" to be removed */ + return 0; /* read fails */ + } +} + + +static int test_eof (lua_State *L, FILE *f) { + int c = getc(f); + ungetc(c, f); + lua_pushlstring(L, NULL, 0); + return (c != EOF); +} + + +static int read_line (lua_State *L, FILE *f) { + luaL_Buffer b; + luaL_buffinit(L, &b); + for (;;) { + size_t l; + char *p = luaL_prepbuffer(&b); + if (fgets(p, LUAL_BUFFERSIZE, f) == NULL) { /* eof? */ + luaL_pushresult(&b); /* close buffer */ + return (lua_objlen(L, -1) > 0); /* check whether read something */ + } + l = strlen(p); + if (l == 0 || p[l-1] != '\n') + luaL_addsize(&b, l); + else { + luaL_addsize(&b, l - 1); /* do not include `eol' */ + luaL_pushresult(&b); /* close buffer */ + return 1; /* read at least an `eol' */ + } + } +} + + +static int read_chars (lua_State *L, FILE *f, size_t n) { + size_t rlen; /* how much to read */ + size_t nr; /* number of chars actually read */ + luaL_Buffer b; + luaL_buffinit(L, &b); + rlen = LUAL_BUFFERSIZE; /* try to read that much each time */ + do { + char *p = luaL_prepbuffer(&b); + if (rlen > n) rlen = n; /* cannot read more than asked */ + nr = fread(p, sizeof(char), rlen, f); + luaL_addsize(&b, nr); + n -= nr; /* still have to read `n' chars */ + } while (n > 0 && nr == rlen); /* until end of count or eof */ + luaL_pushresult(&b); /* close buffer */ + return (n == 0 || lua_objlen(L, -1) > 0); +} + + +static int g_read (lua_State *L, FILE *f, int first) { + int nargs = lua_gettop(L) - 1; + int success; + int n; + clearerr(f); + if (nargs == 0) { /* no arguments? */ + success = read_line(L, f); + n = first+1; /* to return 1 result */ + } + else { /* ensure stack space for all results and for auxlib's buffer */ + luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments"); + success = 1; + for (n = first; nargs-- && success; n++) { + if (lua_type(L, n) == LUA_TNUMBER) { + size_t l = (size_t)lua_tointeger(L, n); + success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l); + } + else { + const char *p = lua_tostring(L, n); + luaL_argcheck(L, p && p[0] == '*', n, "invalid option"); + switch (p[1]) { + case 'n': /* number */ + success = read_number(L, f); + break; + case 'l': /* line */ + success = read_line(L, f); + break; + case 'a': /* file */ + read_chars(L, f, ~((size_t)0)); /* read MAX_SIZE_T chars */ + success = 1; /* always success */ + break; + default: + return luaL_argerror(L, n, "invalid format"); + } + } + } + } + if (ferror(f)) + return pushresult(L, 0, NULL); + if (!success) { + lua_pop(L, 1); /* remove last result */ + lua_pushnil(L); /* push nil instead */ + } + return n - first; +} + + +static int io_read (lua_State *L) { + return g_read(L, getiofile(L, IO_INPUT), 1); +} + + +static int f_read (lua_State *L) { + return g_read(L, tofile(L), 2); +} + + +static int io_readline (lua_State *L) { + FILE *f = *(FILE **)lua_touserdata(L, lua_upvalueindex(1)); + int sucess; + if (f == NULL) /* file is already closed? */ + luaL_error(L, "file is already closed"); + sucess = read_line(L, f); + if (ferror(f)) + return luaL_error(L, "%s", strerror(errno)); + if (sucess) return 1; + else { /* EOF */ + if (lua_toboolean(L, lua_upvalueindex(2))) { /* generator created file? */ + lua_settop(L, 0); + lua_pushvalue(L, lua_upvalueindex(1)); + aux_close(L); /* close it */ + } + return 0; + } +} + +/* }====================================================== */ + + +static int g_write (lua_State *L, FILE *f, int arg) { + int nargs = lua_gettop(L) - 1; + int status = 1; + for (; nargs--; arg++) { + if (lua_type(L, arg) == LUA_TNUMBER) { + /* optimization: could be done exactly as for strings */ + status = status && + fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0; + } + else { + size_t l; + const char *s = luaL_checklstring(L, arg, &l); + status = status && (fwrite(s, sizeof(char), l, f) == l); + } + } + return pushresult(L, status, NULL); +} + + +static int io_write (lua_State *L) { + return g_write(L, getiofile(L, IO_OUTPUT), 1); +} + + +static int f_write (lua_State *L) { + return g_write(L, tofile(L), 2); +} + + +static int f_seek (lua_State *L) { + static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END}; + static const char *const modenames[] = {"set", "cur", "end", NULL}; + FILE *f = tofile(L); + int op = luaL_checkoption(L, 2, "cur", modenames); + long offset = luaL_optlong(L, 3, 0); + op = fseek(f, offset, mode[op]); + if (op) + return pushresult(L, 0, NULL); /* error */ + else { + lua_pushinteger(L, ftell(f)); + return 1; + } +} + + +static int f_setvbuf (lua_State *L) { + static const int mode[] = {_IONBF, _IOFBF, _IOLBF}; + static const char *const modenames[] = {"no", "full", "line", NULL}; + FILE *f = tofile(L); + int op = luaL_checkoption(L, 2, NULL, modenames); + lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE); + int res = setvbuf(f, NULL, mode[op], sz); + return pushresult(L, res == 0, NULL); +} + + + +static int io_flush (lua_State *L) { + return pushresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL); +} + + +static int f_flush (lua_State *L) { + return pushresult(L, fflush(tofile(L)) == 0, NULL); +} + + +static const luaL_Reg iolib[] = { + {"close", io_close}, + {"flush", io_flush}, + {"input", io_input}, + {"lines", io_lines}, + {"open", io_open}, + {"output", io_output}, + {"popen", io_popen}, + {"read", io_read}, + {"tmpfile", io_tmpfile}, + {"type", io_type}, + {"write", io_write}, + {NULL, NULL} +}; + + +static const luaL_Reg flib[] = { + {"close", io_close}, + {"flush", f_flush}, + {"lines", f_lines}, + {"read", f_read}, + {"seek", f_seek}, + {"setvbuf", f_setvbuf}, + {"write", f_write}, + {"__gc", io_gc}, + {"__tostring", io_tostring}, + {NULL, NULL} +}; + + +static void createmeta (lua_State *L) { + luaL_newmetatable(L, LUA_FILEHANDLE); /* create metatable for file handles */ + lua_pushvalue(L, -1); /* push metatable */ + lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */ + luaL_register(L, NULL, flib); /* file methods */ +} + + +static void createstdfile (lua_State *L, FILE *f, int k, const char *fname) { + *newfile(L) = f; + if (k > 0) { + lua_pushvalue(L, -1); + lua_rawseti(L, LUA_ENVIRONINDEX, k); + } + lua_pushvalue(L, -2); /* copy environment */ + lua_setfenv(L, -2); /* set it */ + lua_setfield(L, -3, fname); +} + + +static void newfenv (lua_State *L, lua_CFunction cls) { + lua_createtable(L, 0, 1); + lua_pushcfunction(L, cls); + lua_setfield(L, -2, "__close"); +} + + +LUALIB_API int luaopen_io (lua_State *L) { + createmeta(L); + /* create (private) environment (with fields IO_INPUT, IO_OUTPUT, __close) */ + newfenv(L, io_fclose); + lua_replace(L, LUA_ENVIRONINDEX); + /* open library */ + luaL_register(L, LUA_IOLIBNAME, iolib); + /* create (and set) default files */ + newfenv(L, io_noclose); /* close function for default files */ + createstdfile(L, stdin, IO_INPUT, "stdin"); + createstdfile(L, stdout, IO_OUTPUT, "stdout"); + createstdfile(L, stderr, 0, "stderr"); + lua_pop(L, 1); /* pop environment for default files */ + lua_getfield(L, -1, "popen"); + newfenv(L, io_pclose); /* create environment for 'popen' */ + lua_setfenv(L, -2); /* set fenv for 'popen' */ + lua_pop(L, 1); /* pop 'popen' */ + return 1; +} + diff --git a/external/mit/lua/dist/src/llex.c b/external/mit/lua/dist/src/llex.c new file mode 100644 index 000000000..09c08f191 --- /dev/null +++ b/external/mit/lua/dist/src/llex.c @@ -0,0 +1,465 @@ +/* $NetBSD: llex.c,v 1.1.1.2 2012/03/15 00:08:13 alnsn Exp $ */ + +/* +** $Id: llex.c,v 1.1.1.2 2012/03/15 00:08:13 alnsn Exp $ +** Lexical Analyzer +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include + +#define llex_c +#define LUA_CORE + +#include "lua.h" + +#include "ldo.h" +#include "llex.h" +#include "lobject.h" +#include "lparser.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "lzio.h" + + + +#define next(ls) (ls->current = zgetc(ls->z)) + + + + +#define currIsNewline(ls) (ls->current == '\n' || ls->current == '\r') + + +/* ORDER RESERVED */ +const char *const luaX_tokens [] = { + "and", "break", "do", "else", "elseif", + "end", "false", "for", "function", "if", + "in", "local", "nil", "not", "or", "repeat", + "return", "then", "true", "until", "while", + "..", "...", "==", ">=", "<=", "~=", + "", "", "", "", + NULL +}; + + +#define save_and_next(ls) (save(ls, ls->current), next(ls)) + + +static void save (LexState *ls, int c) { + Mbuffer *b = ls->buff; + if (b->n + 1 > b->buffsize) { + size_t newsize; + if (b->buffsize >= MAX_SIZET/2) + luaX_lexerror(ls, "lexical element too long", 0); + newsize = b->buffsize * 2; + luaZ_resizebuffer(ls->L, b, newsize); + } + b->buffer[b->n++] = cast(char, c); +} + + +void luaX_init (lua_State *L) { + int i; + for (i=0; itsv.reserved = cast_byte(i+1); /* reserved word */ + } +} + + +#define MAXSRC 80 + + +const char *luaX_token2str (LexState *ls, int token) { + if (token < FIRST_RESERVED) { + lua_assert(token == cast(unsigned char, token)); + return (iscntrl(token)) ? luaO_pushfstring(ls->L, "char(%d)", token) : + luaO_pushfstring(ls->L, "%c", token); + } + else + return luaX_tokens[token-FIRST_RESERVED]; +} + + +static const char *txtToken (LexState *ls, int token) { + switch (token) { + case TK_NAME: + case TK_STRING: + case TK_NUMBER: + save(ls, '\0'); + return luaZ_buffer(ls->buff); + default: + return luaX_token2str(ls, token); + } +} + + +void luaX_lexerror (LexState *ls, const char *msg, int token) { + char buff[MAXSRC]; + luaO_chunkid(buff, getstr(ls->source), MAXSRC); + msg = luaO_pushfstring(ls->L, "%s:%d: %s", buff, ls->linenumber, msg); + if (token) + luaO_pushfstring(ls->L, "%s near " LUA_QS, msg, txtToken(ls, token)); + luaD_throw(ls->L, LUA_ERRSYNTAX); +} + + +void luaX_syntaxerror (LexState *ls, const char *msg) { + luaX_lexerror(ls, msg, ls->t.token); +} + + +TString *luaX_newstring (LexState *ls, const char *str, size_t l) { + lua_State *L = ls->L; + TString *ts = luaS_newlstr(L, str, l); + TValue *o = luaH_setstr(L, ls->fs->h, ts); /* entry for `str' */ + if (ttisnil(o)) { + setbvalue(o, 1); /* make sure `str' will not be collected */ + luaC_checkGC(L); + } + return ts; +} + + +static void inclinenumber (LexState *ls) { + int old = ls->current; + lua_assert(currIsNewline(ls)); + next(ls); /* skip `\n' or `\r' */ + if (currIsNewline(ls) && ls->current != old) + next(ls); /* skip `\n\r' or `\r\n' */ + if (++ls->linenumber >= MAX_INT) + luaX_syntaxerror(ls, "chunk has too many lines"); +} + + +void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source) { + ls->decpoint = '.'; + ls->L = L; + ls->lookahead.token = TK_EOS; /* no look-ahead token */ + ls->z = z; + ls->fs = NULL; + ls->linenumber = 1; + ls->lastline = 1; + ls->source = source; + luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER); /* initialize buffer */ + next(ls); /* read first char */ +} + + + +/* +** ======================================================= +** LEXICAL ANALYZER +** ======================================================= +*/ + + + +static int check_next (LexState *ls, const char *set) { + if (!strchr(set, ls->current)) + return 0; + save_and_next(ls); + return 1; +} + + +static void buffreplace (LexState *ls, char from, char to) { + size_t n = luaZ_bufflen(ls->buff); + char *p = luaZ_buffer(ls->buff); + while (n--) + if (p[n] == from) p[n] = to; +} + + +static void trydecpoint (LexState *ls, SemInfo *seminfo) { + /* format error: try to update decimal point separator */ + struct lconv *cv = localeconv(); + char old = ls->decpoint; + ls->decpoint = (cv ? cv->decimal_point[0] : '.'); + buffreplace(ls, old, ls->decpoint); /* try updated decimal separator */ + if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) { + /* format error with correct decimal point: no more options */ + buffreplace(ls, ls->decpoint, '.'); /* undo change (for error message) */ + luaX_lexerror(ls, "malformed number", TK_NUMBER); + } +} + + +/* LUA_NUMBER */ +static void read_numeral (LexState *ls, SemInfo *seminfo) { + lua_assert(isdigit(ls->current)); + do { + save_and_next(ls); + } while (isdigit(ls->current) || ls->current == '.'); + if (check_next(ls, "Ee")) /* `E'? */ + check_next(ls, "+-"); /* optional exponent sign */ + while (isalnum(ls->current) || ls->current == '_') + save_and_next(ls); + save(ls, '\0'); + buffreplace(ls, '.', ls->decpoint); /* follow locale for decimal point */ + if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) /* format error? */ + trydecpoint(ls, seminfo); /* try to update decimal point separator */ +} + + +static int skip_sep (LexState *ls) { + int count = 0; + int s = ls->current; + lua_assert(s == '[' || s == ']'); + save_and_next(ls); + while (ls->current == '=') { + save_and_next(ls); + count++; + } + return (ls->current == s) ? count : (-count) - 1; +} + + +static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) { + int cont = 0; + (void)(cont); /* avoid warnings when `cont' is not used */ + save_and_next(ls); /* skip 2nd `[' */ + if (currIsNewline(ls)) /* string starts with a newline? */ + inclinenumber(ls); /* skip it */ + for (;;) { + switch (ls->current) { + case EOZ: + luaX_lexerror(ls, (seminfo) ? "unfinished long string" : + "unfinished long comment", TK_EOS); + break; /* to avoid warnings */ +#if defined(LUA_COMPAT_LSTR) + case '[': { + if (skip_sep(ls) == sep) { + save_and_next(ls); /* skip 2nd `[' */ + cont++; +#if LUA_COMPAT_LSTR == 1 + if (sep == 0) + luaX_lexerror(ls, "nesting of [[...]] is deprecated", '['); +#endif + } + break; + } +#endif + case ']': { + if (skip_sep(ls) == sep) { + save_and_next(ls); /* skip 2nd `]' */ +#if defined(LUA_COMPAT_LSTR) && LUA_COMPAT_LSTR == 2 + cont--; + if (sep == 0 && cont >= 0) break; +#endif + goto endloop; + } + break; + } + case '\n': + case '\r': { + save(ls, '\n'); + inclinenumber(ls); + if (!seminfo) luaZ_resetbuffer(ls->buff); /* avoid wasting space */ + break; + } + default: { + if (seminfo) save_and_next(ls); + else next(ls); + } + } + } endloop: + if (seminfo) + seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + (2 + sep), + luaZ_bufflen(ls->buff) - 2*(2 + sep)); +} + + +static void read_string (LexState *ls, int del, SemInfo *seminfo) { + save_and_next(ls); + while (ls->current != del) { + switch (ls->current) { + case EOZ: + luaX_lexerror(ls, "unfinished string", TK_EOS); + continue; /* to avoid warnings */ + case '\n': + case '\r': + luaX_lexerror(ls, "unfinished string", TK_STRING); + continue; /* to avoid warnings */ + case '\\': { + int c; + next(ls); /* do not save the `\' */ + switch (ls->current) { + case 'a': c = '\a'; break; + case 'b': c = '\b'; break; + case 'f': c = '\f'; break; + case 'n': c = '\n'; break; + case 'r': c = '\r'; break; + case 't': c = '\t'; break; + case 'v': c = '\v'; break; + case '\n': /* go through */ + case '\r': save(ls, '\n'); inclinenumber(ls); continue; + case EOZ: continue; /* will raise an error next loop */ + default: { + if (!isdigit(ls->current)) + save_and_next(ls); /* handles \\, \", \', and \? */ + else { /* \xxx */ + int i = 0; + c = 0; + do { + c = 10*c + (ls->current-'0'); + next(ls); + } while (++i<3 && isdigit(ls->current)); + if (c > UCHAR_MAX) + luaX_lexerror(ls, "escape sequence too large", TK_STRING); + save(ls, c); + } + continue; + } + } + save(ls, c); + next(ls); + continue; + } + default: + save_and_next(ls); + } + } + save_and_next(ls); /* skip delimiter */ + seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + 1, + luaZ_bufflen(ls->buff) - 2); +} + + +static int llex (LexState *ls, SemInfo *seminfo) { + luaZ_resetbuffer(ls->buff); + for (;;) { + switch (ls->current) { + case '\n': + case '\r': { + inclinenumber(ls); + continue; + } + case '-': { + next(ls); + if (ls->current != '-') return '-'; + /* else is a comment */ + next(ls); + if (ls->current == '[') { + int sep = skip_sep(ls); + luaZ_resetbuffer(ls->buff); /* `skip_sep' may dirty the buffer */ + if (sep >= 0) { + read_long_string(ls, NULL, sep); /* long comment */ + luaZ_resetbuffer(ls->buff); + continue; + } + } + /* else short comment */ + while (!currIsNewline(ls) && ls->current != EOZ) + next(ls); + continue; + } + case '[': { + int sep = skip_sep(ls); + if (sep >= 0) { + read_long_string(ls, seminfo, sep); + return TK_STRING; + } + else if (sep == -1) return '['; + else luaX_lexerror(ls, "invalid long string delimiter", TK_STRING); + } + case '=': { + next(ls); + if (ls->current != '=') return '='; + else { next(ls); return TK_EQ; } + } + case '<': { + next(ls); + if (ls->current != '=') return '<'; + else { next(ls); return TK_LE; } + } + case '>': { + next(ls); + if (ls->current != '=') return '>'; + else { next(ls); return TK_GE; } + } + case '~': { + next(ls); + if (ls->current != '=') return '~'; + else { next(ls); return TK_NE; } + } + case '"': + case '\'': { + read_string(ls, ls->current, seminfo); + return TK_STRING; + } + case '.': { + save_and_next(ls); + if (check_next(ls, ".")) { + if (check_next(ls, ".")) + return TK_DOTS; /* ... */ + else return TK_CONCAT; /* .. */ + } + else if (!isdigit(ls->current)) return '.'; + else { + read_numeral(ls, seminfo); + return TK_NUMBER; + } + } + case EOZ: { + return TK_EOS; + } + default: { + if (isspace(ls->current)) { + lua_assert(!currIsNewline(ls)); + next(ls); + continue; + } + else if (isdigit(ls->current)) { + read_numeral(ls, seminfo); + return TK_NUMBER; + } + else if (isalpha(ls->current) || ls->current == '_') { + /* identifier or reserved word */ + TString *ts; + do { + save_and_next(ls); + } while (isalnum(ls->current) || ls->current == '_'); + ts = luaX_newstring(ls, luaZ_buffer(ls->buff), + luaZ_bufflen(ls->buff)); + if (ts->tsv.reserved > 0) /* reserved word? */ + return ts->tsv.reserved - 1 + FIRST_RESERVED; + else { + seminfo->ts = ts; + return TK_NAME; + } + } + else { + int c = ls->current; + next(ls); + return c; /* single-char tokens (+ - / ...) */ + } + } + } + } +} + + +void luaX_next (LexState *ls) { + ls->lastline = ls->linenumber; + if (ls->lookahead.token != TK_EOS) { /* is there a look-ahead token? */ + ls->t = ls->lookahead; /* use this one */ + ls->lookahead.token = TK_EOS; /* and discharge it */ + } + else + ls->t.token = llex(ls, &ls->t.seminfo); /* read next token */ +} + + +void luaX_lookahead (LexState *ls) { + lua_assert(ls->lookahead.token == TK_EOS); + ls->lookahead.token = llex(ls, &ls->lookahead.seminfo); +} + diff --git a/external/mit/lua/dist/src/llex.h b/external/mit/lua/dist/src/llex.h new file mode 100644 index 000000000..eda0a4453 --- /dev/null +++ b/external/mit/lua/dist/src/llex.h @@ -0,0 +1,83 @@ +/* $NetBSD: llex.h,v 1.1.1.2 2012/03/15 00:08:12 alnsn Exp $ */ + +/* +** $Id: llex.h,v 1.1.1.2 2012/03/15 00:08:12 alnsn Exp $ +** Lexical Analyzer +** See Copyright Notice in lua.h +*/ + +#ifndef llex_h +#define llex_h + +#include "lobject.h" +#include "lzio.h" + + +#define FIRST_RESERVED 257 + +/* maximum length of a reserved word */ +#define TOKEN_LEN (sizeof("function")/sizeof(char)) + + +/* +* WARNING: if you change the order of this enumeration, +* grep "ORDER RESERVED" +*/ +enum RESERVED { + /* terminal symbols denoted by reserved words */ + TK_AND = FIRST_RESERVED, TK_BREAK, + TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION, + TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT, + TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE, + /* other terminal symbols */ + TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_NUMBER, + TK_NAME, TK_STRING, TK_EOS +}; + +/* number of reserved words */ +#define NUM_RESERVED (cast(int, TK_WHILE-FIRST_RESERVED+1)) + + +/* array with token `names' */ +LUAI_DATA const char *const luaX_tokens []; + + +typedef union { + lua_Number r; + TString *ts; +} SemInfo; /* semantics information */ + + +typedef struct Token { + int token; + SemInfo seminfo; +} Token; + + +typedef struct LexState { + int current; /* current character (charint) */ + int linenumber; /* input line counter */ + int lastline; /* line of last token `consumed' */ + Token t; /* current token */ + Token lookahead; /* look ahead token */ + struct FuncState *fs; /* `FuncState' is private to the parser */ + struct lua_State *L; + ZIO *z; /* input stream */ + Mbuffer *buff; /* buffer for tokens */ + TString *source; /* current source name */ + char decpoint; /* locale decimal point */ +} LexState; + + +LUAI_FUNC void luaX_init (lua_State *L); +LUAI_FUNC void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, + TString *source); +LUAI_FUNC TString *luaX_newstring (LexState *ls, const char *str, size_t l); +LUAI_FUNC void luaX_next (LexState *ls); +LUAI_FUNC void luaX_lookahead (LexState *ls); +LUAI_FUNC void luaX_lexerror (LexState *ls, const char *msg, int token); +LUAI_FUNC void luaX_syntaxerror (LexState *ls, const char *s); +LUAI_FUNC const char *luaX_token2str (LexState *ls, int token); + + +#endif diff --git a/external/mit/lua/dist/src/llimits.h b/external/mit/lua/dist/src/llimits.h new file mode 100644 index 000000000..a7010ee9c --- /dev/null +++ b/external/mit/lua/dist/src/llimits.h @@ -0,0 +1,130 @@ +/* $NetBSD: llimits.h,v 1.1.1.2 2012/03/15 00:08:12 alnsn Exp $ */ + +/* +** $Id: llimits.h,v 1.1.1.2 2012/03/15 00:08:12 alnsn Exp $ +** Limits, basic types, and some other `installation-dependent' definitions +** See Copyright Notice in lua.h +*/ + +#ifndef llimits_h +#define llimits_h + + +#include +#include + + +#include "lua.h" + + +typedef LUAI_UINT32 lu_int32; + +typedef LUAI_UMEM lu_mem; + +typedef LUAI_MEM l_mem; + + + +/* chars used as small naturals (so that `char' is reserved for characters) */ +typedef unsigned char lu_byte; + + +#define MAX_SIZET ((size_t)(~(size_t)0)-2) + +#define MAX_LUMEM ((lu_mem)(~(lu_mem)0)-2) + + +#define MAX_INT (INT_MAX-2) /* maximum value of an int (-2 for safety) */ + +/* +** conversion of pointer to integer +** this is for hashing only; there is no problem if the integer +** cannot hold the whole pointer value +*/ +#define IntPoint(p) ((unsigned int)(lu_mem)(p)) + + + +/* type to ensure maximum alignment */ +typedef LUAI_USER_ALIGNMENT_T L_Umaxalign; + + +/* result of a `usual argument conversion' over lua_Number */ +typedef LUAI_UACNUMBER l_uacNumber; + + +/* internal assertions for in-house debugging */ +#ifdef lua_assert + +#define check_exp(c,e) (lua_assert(c), (e)) +#define api_check(l,e) lua_assert(e) + +#else + +#define lua_assert(c) ((void)0) +#define check_exp(c,e) (e) +#define api_check luai_apicheck + +#endif + + +#ifndef UNUSED +#define UNUSED(x) ((void)(x)) /* to avoid warnings */ +#endif + + +#ifndef cast +#define cast(t, exp) ((t)(exp)) +#endif + +#define cast_byte(i) cast(lu_byte, (i)) +#define cast_num(i) cast(lua_Number, (i)) +#define cast_int(i) cast(int, (i)) + + + +/* +** type for virtual-machine instructions +** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h) +*/ +typedef lu_int32 Instruction; + + + +/* maximum stack for a Lua function */ +#define MAXSTACK 250 + + + +/* minimum size for the string table (must be power of 2) */ +#ifndef MINSTRTABSIZE +#define MINSTRTABSIZE 32 +#endif + + +/* minimum size for string buffer */ +#ifndef LUA_MINBUFFER +#define LUA_MINBUFFER 32 +#endif + + +#ifndef lua_lock +#define lua_lock(L) ((void) 0) +#define lua_unlock(L) ((void) 0) +#endif + +#ifndef luai_threadyield +#define luai_threadyield(L) {lua_unlock(L); lua_lock(L);} +#endif + + +/* +** macro to control inclusion of some hard tests on stack reallocation +*/ +#ifndef HARDSTACKTESTS +#define condhardstacktests(x) ((void)0) +#else +#define condhardstacktests(x) x +#endif + +#endif diff --git a/external/mit/lua/dist/src/lmathlib.c b/external/mit/lua/dist/src/lmathlib.c new file mode 100644 index 000000000..1ef3fc862 --- /dev/null +++ b/external/mit/lua/dist/src/lmathlib.c @@ -0,0 +1,265 @@ +/* $NetBSD: lmathlib.c,v 1.1.1.2 2012/03/15 00:08:05 alnsn Exp $ */ + +/* +** $Id: lmathlib.c,v 1.1.1.2 2012/03/15 00:08:05 alnsn Exp $ +** Standard mathematical library +** See Copyright Notice in lua.h +*/ + + +#include +#include + +#define lmathlib_c +#define LUA_LIB + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +#undef PI +#define PI (3.14159265358979323846) +#define RADIANS_PER_DEGREE (PI/180.0) + + + +static int math_abs (lua_State *L) { + lua_pushnumber(L, fabs(luaL_checknumber(L, 1))); + return 1; +} + +static int math_sin (lua_State *L) { + lua_pushnumber(L, sin(luaL_checknumber(L, 1))); + return 1; +} + +static int math_sinh (lua_State *L) { + lua_pushnumber(L, sinh(luaL_checknumber(L, 1))); + return 1; +} + +static int math_cos (lua_State *L) { + lua_pushnumber(L, cos(luaL_checknumber(L, 1))); + return 1; +} + +static int math_cosh (lua_State *L) { + lua_pushnumber(L, cosh(luaL_checknumber(L, 1))); + return 1; +} + +static int math_tan (lua_State *L) { + lua_pushnumber(L, tan(luaL_checknumber(L, 1))); + return 1; +} + +static int math_tanh (lua_State *L) { + lua_pushnumber(L, tanh(luaL_checknumber(L, 1))); + return 1; +} + +static int math_asin (lua_State *L) { + lua_pushnumber(L, asin(luaL_checknumber(L, 1))); + return 1; +} + +static int math_acos (lua_State *L) { + lua_pushnumber(L, acos(luaL_checknumber(L, 1))); + return 1; +} + +static int math_atan (lua_State *L) { + lua_pushnumber(L, atan(luaL_checknumber(L, 1))); + return 1; +} + +static int math_atan2 (lua_State *L) { + lua_pushnumber(L, atan2(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); + return 1; +} + +static int math_ceil (lua_State *L) { + lua_pushnumber(L, ceil(luaL_checknumber(L, 1))); + return 1; +} + +static int math_floor (lua_State *L) { + lua_pushnumber(L, floor(luaL_checknumber(L, 1))); + return 1; +} + +static int math_fmod (lua_State *L) { + lua_pushnumber(L, fmod(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); + return 1; +} + +static int math_modf (lua_State *L) { + double ip; + double fp = modf(luaL_checknumber(L, 1), &ip); + lua_pushnumber(L, ip); + lua_pushnumber(L, fp); + return 2; +} + +static int math_sqrt (lua_State *L) { + lua_pushnumber(L, sqrt(luaL_checknumber(L, 1))); + return 1; +} + +static int math_pow (lua_State *L) { + lua_pushnumber(L, pow(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); + return 1; +} + +static int math_log (lua_State *L) { + lua_pushnumber(L, log(luaL_checknumber(L, 1))); + return 1; +} + +static int math_log10 (lua_State *L) { + lua_pushnumber(L, log10(luaL_checknumber(L, 1))); + return 1; +} + +static int math_exp (lua_State *L) { + lua_pushnumber(L, exp(luaL_checknumber(L, 1))); + return 1; +} + +static int math_deg (lua_State *L) { + lua_pushnumber(L, luaL_checknumber(L, 1)/RADIANS_PER_DEGREE); + return 1; +} + +static int math_rad (lua_State *L) { + lua_pushnumber(L, luaL_checknumber(L, 1)*RADIANS_PER_DEGREE); + return 1; +} + +static int math_frexp (lua_State *L) { + int e; + lua_pushnumber(L, frexp(luaL_checknumber(L, 1), &e)); + lua_pushinteger(L, e); + return 2; +} + +static int math_ldexp (lua_State *L) { + lua_pushnumber(L, ldexp(luaL_checknumber(L, 1), luaL_checkint(L, 2))); + return 1; +} + + + +static int math_min (lua_State *L) { + int n = lua_gettop(L); /* number of arguments */ + lua_Number dmin = luaL_checknumber(L, 1); + int i; + for (i=2; i<=n; i++) { + lua_Number d = luaL_checknumber(L, i); + if (d < dmin) + dmin = d; + } + lua_pushnumber(L, dmin); + return 1; +} + + +static int math_max (lua_State *L) { + int n = lua_gettop(L); /* number of arguments */ + lua_Number dmax = luaL_checknumber(L, 1); + int i; + for (i=2; i<=n; i++) { + lua_Number d = luaL_checknumber(L, i); + if (d > dmax) + dmax = d; + } + lua_pushnumber(L, dmax); + return 1; +} + + +static int math_random (lua_State *L) { + /* the `%' avoids the (rare) case of r==1, and is needed also because on + some systems (SunOS!) `rand()' may return a value larger than RAND_MAX */ + lua_Number r = (lua_Number)(rand()%RAND_MAX) / (lua_Number)RAND_MAX; + switch (lua_gettop(L)) { /* check number of arguments */ + case 0: { /* no arguments */ + lua_pushnumber(L, r); /* Number between 0 and 1 */ + break; + } + case 1: { /* only upper limit */ + int u = luaL_checkint(L, 1); + luaL_argcheck(L, 1<=u, 1, "interval is empty"); + lua_pushnumber(L, floor(r*u)+1); /* int between 1 and `u' */ + break; + } + case 2: { /* lower and upper limits */ + int l = luaL_checkint(L, 1); + int u = luaL_checkint(L, 2); + luaL_argcheck(L, l<=u, 2, "interval is empty"); + lua_pushnumber(L, floor(r*(u-l+1))+l); /* int between `l' and `u' */ + break; + } + default: return luaL_error(L, "wrong number of arguments"); + } + return 1; +} + + +static int math_randomseed (lua_State *L) { + srand(luaL_checkint(L, 1)); + return 0; +} + + +static const luaL_Reg mathlib[] = { + {"abs", math_abs}, + {"acos", math_acos}, + {"asin", math_asin}, + {"atan2", math_atan2}, + {"atan", math_atan}, + {"ceil", math_ceil}, + {"cosh", math_cosh}, + {"cos", math_cos}, + {"deg", math_deg}, + {"exp", math_exp}, + {"floor", math_floor}, + {"fmod", math_fmod}, + {"frexp", math_frexp}, + {"ldexp", math_ldexp}, + {"log10", math_log10}, + {"log", math_log}, + {"max", math_max}, + {"min", math_min}, + {"modf", math_modf}, + {"pow", math_pow}, + {"rad", math_rad}, + {"random", math_random}, + {"randomseed", math_randomseed}, + {"sinh", math_sinh}, + {"sin", math_sin}, + {"sqrt", math_sqrt}, + {"tanh", math_tanh}, + {"tan", math_tan}, + {NULL, NULL} +}; + + +/* +** Open math library +*/ +LUALIB_API int luaopen_math (lua_State *L) { + luaL_register(L, LUA_MATHLIBNAME, mathlib); + lua_pushnumber(L, PI); + lua_setfield(L, -2, "pi"); + lua_pushnumber(L, HUGE_VAL); + lua_setfield(L, -2, "huge"); +#if defined(LUA_COMPAT_MOD) + lua_getfield(L, -1, "fmod"); + lua_setfield(L, -2, "mod"); +#endif + return 1; +} + diff --git a/external/mit/lua/dist/src/lmem.c b/external/mit/lua/dist/src/lmem.c new file mode 100644 index 000000000..5d1cfc71d --- /dev/null +++ b/external/mit/lua/dist/src/lmem.c @@ -0,0 +1,88 @@ +/* $NetBSD: lmem.c,v 1.1.1.2 2012/03/15 00:08:07 alnsn Exp $ */ + +/* +** $Id: lmem.c,v 1.1.1.2 2012/03/15 00:08:07 alnsn Exp $ +** Interface to Memory Manager +** See Copyright Notice in lua.h +*/ + + +#include + +#define lmem_c +#define LUA_CORE + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" + + + +/* +** About the realloc function: +** void * frealloc (void *ud, void *ptr, size_t osize, size_t nsize); +** (`osize' is the old size, `nsize' is the new size) +** +** Lua ensures that (ptr == NULL) iff (osize == 0). +** +** * frealloc(ud, NULL, 0, x) creates a new block of size `x' +** +** * frealloc(ud, p, x, 0) frees the block `p' +** (in this specific case, frealloc must return NULL). +** particularly, frealloc(ud, NULL, 0, 0) does nothing +** (which is equivalent to free(NULL) in ANSI C) +** +** frealloc returns NULL if it cannot create or reallocate the area +** (any reallocation to an equal or smaller size cannot fail!) +*/ + + + +#define MINSIZEARRAY 4 + + +void *luaM_growaux_ (lua_State *L, void *block, int *size, size_t size_elems, + int limit, const char *errormsg) { + void *newblock; + int newsize; + if (*size >= limit/2) { /* cannot double it? */ + if (*size >= limit) /* cannot grow even a little? */ + luaG_runerror(L, errormsg); + newsize = limit; /* still have at least one free place */ + } + else { + newsize = (*size)*2; + if (newsize < MINSIZEARRAY) + newsize = MINSIZEARRAY; /* minimum size */ + } + newblock = luaM_reallocv(L, block, *size, newsize, size_elems); + *size = newsize; /* update only when everything else is OK */ + return newblock; +} + + +void *luaM_toobig (lua_State *L) { + luaG_runerror(L, "memory allocation error: block too big"); + return NULL; /* to avoid warnings */ +} + + + +/* +** generic allocation routine. +*/ +void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) { + global_State *g = G(L); + lua_assert((osize == 0) == (block == NULL)); + block = (*g->frealloc)(g->ud, block, osize, nsize); + if (block == NULL && nsize > 0) + luaD_throw(L, LUA_ERRMEM); + lua_assert((nsize == 0) == (block == NULL)); + g->totalbytes = (g->totalbytes - osize) + nsize; + return block; +} + diff --git a/external/mit/lua/dist/src/lmem.h b/external/mit/lua/dist/src/lmem.h new file mode 100644 index 000000000..fe7e4705f --- /dev/null +++ b/external/mit/lua/dist/src/lmem.h @@ -0,0 +1,51 @@ +/* $NetBSD: lmem.h,v 1.1.1.2 2012/03/15 00:08:06 alnsn Exp $ */ + +/* +** $Id: lmem.h,v 1.1.1.2 2012/03/15 00:08:06 alnsn Exp $ +** Interface to Memory Manager +** See Copyright Notice in lua.h +*/ + +#ifndef lmem_h +#define lmem_h + + +#include + +#include "llimits.h" +#include "lua.h" + +#define MEMERRMSG "not enough memory" + + +#define luaM_reallocv(L,b,on,n,e) \ + ((cast(size_t, (n)+1) <= MAX_SIZET/(e)) ? /* +1 to avoid warnings */ \ + luaM_realloc_(L, (b), (on)*(e), (n)*(e)) : \ + luaM_toobig(L)) + +#define luaM_freemem(L, b, s) luaM_realloc_(L, (b), (s), 0) +#define luaM_free(L, b) luaM_realloc_(L, (b), sizeof(*(b)), 0) +#define luaM_freearray(L, b, n, t) luaM_reallocv(L, (b), n, 0, sizeof(t)) + +#define luaM_malloc(L,t) luaM_realloc_(L, NULL, 0, (t)) +#define luaM_new(L,t) cast(t *, luaM_malloc(L, sizeof(t))) +#define luaM_newvector(L,n,t) \ + cast(t *, luaM_reallocv(L, NULL, 0, n, sizeof(t))) + +#define luaM_growvector(L,v,nelems,size,t,limit,e) \ + if ((nelems)+1 > (size)) \ + ((v)=cast(t *, luaM_growaux_(L,v,&(size),sizeof(t),limit,e))) + +#define luaM_reallocvector(L, v,oldn,n,t) \ + ((v)=cast(t *, luaM_reallocv(L, v, oldn, n, sizeof(t)))) + + +LUAI_FUNC void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize, + size_t size); +LUAI_FUNC void *luaM_toobig (lua_State *L); +LUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int *size, + size_t size_elem, int limit, + const char *errormsg); + +#endif + diff --git a/external/mit/lua/dist/src/loadlib.c b/external/mit/lua/dist/src/loadlib.c new file mode 100644 index 000000000..21c67f800 --- /dev/null +++ b/external/mit/lua/dist/src/loadlib.c @@ -0,0 +1,668 @@ +/* $NetBSD: loadlib.c,v 1.1.1.2 2012/03/15 00:08:12 alnsn Exp $ */ + +/* +** $Id: loadlib.c,v 1.1.1.2 2012/03/15 00:08:12 alnsn Exp $ +** Dynamic library loader for Lua +** See Copyright Notice in lua.h +** +** This module contains an implementation of loadlib for Unix systems +** that have dlfcn, an implementation for Darwin (Mac OS X), an +** implementation for Windows, and a stub for other systems. +*/ + + +#include +#include + + +#define loadlib_c +#define LUA_LIB + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +/* prefix for open functions in C libraries */ +#define LUA_POF "luaopen_" + +/* separator for open functions in C libraries */ +#define LUA_OFSEP "_" + + +#define LIBPREFIX "LOADLIB: " + +#define POF LUA_POF +#define LIB_FAIL "open" + + +/* error codes for ll_loadfunc */ +#define ERRLIB 1 +#define ERRFUNC 2 + +#define setprogdir(L) ((void)0) + + +static void ll_unloadlib (void *lib); +static void *ll_load (lua_State *L, const char *path); +static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym); + + + +#if defined(LUA_DL_DLOPEN) +/* +** {======================================================================== +** This is an implementation of loadlib based on the dlfcn interface. +** The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD, +** NetBSD, AIX 4.2, HPUX 11, and probably most other Unix flavors, at least +** as an emulation layer on top of native functions. +** ========================================================================= +*/ + +#include + +static void ll_unloadlib (void *lib) { + dlclose(lib); +} + + +static void *ll_load (lua_State *L, const char *path) { + void *lib = dlopen(path, RTLD_NOW); + if (lib == NULL) lua_pushstring(L, dlerror()); + return lib; +} + + +static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { + lua_CFunction f = (lua_CFunction)dlsym(lib, sym); + if (f == NULL) lua_pushstring(L, dlerror()); + return f; +} + +/* }====================================================== */ + + + +#elif defined(LUA_DL_DLL) +/* +** {====================================================================== +** This is an implementation of loadlib for Windows using native functions. +** ======================================================================= +*/ + +#include + + +#undef setprogdir + +static void setprogdir (lua_State *L) { + char buff[MAX_PATH + 1]; + char *lb; + DWORD nsize = sizeof(buff)/sizeof(char); + DWORD n = GetModuleFileNameA(NULL, buff, nsize); + if (n == 0 || n == nsize || (lb = strrchr(buff, '\\')) == NULL) + luaL_error(L, "unable to get ModuleFileName"); + else { + *lb = '\0'; + luaL_gsub(L, lua_tostring(L, -1), LUA_EXECDIR, buff); + lua_remove(L, -2); /* remove original string */ + } +} + + +static void pusherror (lua_State *L) { + int error = GetLastError(); + char buffer[128]; + if (FormatMessageA(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, error, 0, buffer, sizeof(buffer), NULL)) + lua_pushstring(L, buffer); + else + lua_pushfstring(L, "system error %d\n", error); +} + +static void ll_unloadlib (void *lib) { + FreeLibrary((HINSTANCE)lib); +} + + +static void *ll_load (lua_State *L, const char *path) { + HINSTANCE lib = LoadLibraryA(path); + if (lib == NULL) pusherror(L); + return lib; +} + + +static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { + lua_CFunction f = (lua_CFunction)GetProcAddress((HINSTANCE)lib, sym); + if (f == NULL) pusherror(L); + return f; +} + +/* }====================================================== */ + + + +#elif defined(LUA_DL_DYLD) +/* +** {====================================================================== +** Native Mac OS X / Darwin Implementation +** ======================================================================= +*/ + +#include + + +/* Mac appends a `_' before C function names */ +#undef POF +#define POF "_" LUA_POF + + +static void pusherror (lua_State *L) { + const char *err_str; + const char *err_file; + NSLinkEditErrors err; + int err_num; + NSLinkEditError(&err, &err_num, &err_file, &err_str); + lua_pushstring(L, err_str); +} + + +static const char *errorfromcode (NSObjectFileImageReturnCode ret) { + switch (ret) { + case NSObjectFileImageInappropriateFile: + return "file is not a bundle"; + case NSObjectFileImageArch: + return "library is for wrong CPU type"; + case NSObjectFileImageFormat: + return "bad format"; + case NSObjectFileImageAccess: + return "cannot access file"; + case NSObjectFileImageFailure: + default: + return "unable to load library"; + } +} + + +static void ll_unloadlib (void *lib) { + NSUnLinkModule((NSModule)lib, NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES); +} + + +static void *ll_load (lua_State *L, const char *path) { + NSObjectFileImage img; + NSObjectFileImageReturnCode ret; + /* this would be a rare case, but prevents crashing if it happens */ + if(!_dyld_present()) { + lua_pushliteral(L, "dyld not present"); + return NULL; + } + ret = NSCreateObjectFileImageFromFile(path, &img); + if (ret == NSObjectFileImageSuccess) { + NSModule mod = NSLinkModule(img, path, NSLINKMODULE_OPTION_PRIVATE | + NSLINKMODULE_OPTION_RETURN_ON_ERROR); + NSDestroyObjectFileImage(img); + if (mod == NULL) pusherror(L); + return mod; + } + lua_pushstring(L, errorfromcode(ret)); + return NULL; +} + + +static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { + NSSymbol nss = NSLookupSymbolInModule((NSModule)lib, sym); + if (nss == NULL) { + lua_pushfstring(L, "symbol " LUA_QS " not found", sym); + return NULL; + } + return (lua_CFunction)NSAddressOfSymbol(nss); +} + +/* }====================================================== */ + + + +#else +/* +** {====================================================== +** Fallback for other systems +** ======================================================= +*/ + +#undef LIB_FAIL +#define LIB_FAIL "absent" + + +#define DLMSG "dynamic libraries not enabled; check your Lua installation" + + +static void ll_unloadlib (void *lib) { + (void)lib; /* to avoid warnings */ +} + + +static void *ll_load (lua_State *L, const char *path) { + (void)path; /* to avoid warnings */ + lua_pushliteral(L, DLMSG); + return NULL; +} + + +static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { + (void)lib; (void)sym; /* to avoid warnings */ + lua_pushliteral(L, DLMSG); + return NULL; +} + +/* }====================================================== */ +#endif + + + +static void **ll_register (lua_State *L, const char *path) { + void **plib; + lua_pushfstring(L, "%s%s", LIBPREFIX, path); + lua_gettable(L, LUA_REGISTRYINDEX); /* check library in registry? */ + if (!lua_isnil(L, -1)) /* is there an entry? */ + plib = (void **)lua_touserdata(L, -1); + else { /* no entry yet; create one */ + lua_pop(L, 1); + plib = (void **)lua_newuserdata(L, sizeof(const void *)); + *plib = NULL; + luaL_getmetatable(L, "_LOADLIB"); + lua_setmetatable(L, -2); + lua_pushfstring(L, "%s%s", LIBPREFIX, path); + lua_pushvalue(L, -2); + lua_settable(L, LUA_REGISTRYINDEX); + } + return plib; +} + + +/* +** __gc tag method: calls library's `ll_unloadlib' function with the lib +** handle +*/ +static int gctm (lua_State *L) { + void **lib = (void **)luaL_checkudata(L, 1, "_LOADLIB"); + if (*lib) ll_unloadlib(*lib); + *lib = NULL; /* mark library as closed */ + return 0; +} + + +static int ll_loadfunc (lua_State *L, const char *path, const char *sym) { + void **reg = ll_register(L, path); + if (*reg == NULL) *reg = ll_load(L, path); + if (*reg == NULL) + return ERRLIB; /* unable to load library */ + else { + lua_CFunction f = ll_sym(L, *reg, sym); + if (f == NULL) + return ERRFUNC; /* unable to find function */ + lua_pushcfunction(L, f); + return 0; /* return function */ + } +} + + +static int ll_loadlib (lua_State *L) { + const char *path = luaL_checkstring(L, 1); + const char *init = luaL_checkstring(L, 2); + int stat = ll_loadfunc(L, path, init); + if (stat == 0) /* no errors? */ + return 1; /* return the loaded function */ + else { /* error; error message is on stack top */ + lua_pushnil(L); + lua_insert(L, -2); + lua_pushstring(L, (stat == ERRLIB) ? LIB_FAIL : "init"); + return 3; /* return nil, error message, and where */ + } +} + + + +/* +** {====================================================== +** 'require' function +** ======================================================= +*/ + + +static int readable (const char *filename) { + FILE *f = fopen(filename, "r"); /* try to open file */ + if (f == NULL) return 0; /* open failed */ + fclose(f); + return 1; +} + + +static const char *pushnexttemplate (lua_State *L, const char *path) { + const char *l; + while (*path == *LUA_PATHSEP) path++; /* skip separators */ + if (*path == '\0') return NULL; /* no more templates */ + l = strchr(path, *LUA_PATHSEP); /* find next separator */ + if (l == NULL) l = path + strlen(path); + lua_pushlstring(L, path, l - path); /* template */ + return l; +} + + +static const char *findfile (lua_State *L, const char *name, + const char *pname) { + const char *path; + name = luaL_gsub(L, name, ".", LUA_DIRSEP); + lua_getfield(L, LUA_ENVIRONINDEX, pname); + path = lua_tostring(L, -1); + if (path == NULL) + luaL_error(L, LUA_QL("package.%s") " must be a string", pname); + lua_pushliteral(L, ""); /* error accumulator */ + while ((path = pushnexttemplate(L, path)) != NULL) { + const char *filename; + filename = luaL_gsub(L, lua_tostring(L, -1), LUA_PATH_MARK, name); + lua_remove(L, -2); /* remove path template */ + if (readable(filename)) /* does file exist and is readable? */ + return filename; /* return that file name */ + lua_pushfstring(L, "\n\tno file " LUA_QS, filename); + lua_remove(L, -2); /* remove file name */ + lua_concat(L, 2); /* add entry to possible error message */ + } + return NULL; /* not found */ +} + + +static void loaderror (lua_State *L, const char *filename) { + luaL_error(L, "error loading module " LUA_QS " from file " LUA_QS ":\n\t%s", + lua_tostring(L, 1), filename, lua_tostring(L, -1)); +} + + +static int loader_Lua (lua_State *L) { + const char *filename; + const char *name = luaL_checkstring(L, 1); + filename = findfile(L, name, "path"); + if (filename == NULL) return 1; /* library not found in this path */ + if (luaL_loadfile(L, filename) != 0) + loaderror(L, filename); + return 1; /* library loaded successfully */ +} + + +static const char *mkfuncname (lua_State *L, const char *modname) { + const char *funcname; + const char *mark = strchr(modname, *LUA_IGMARK); + if (mark) modname = mark + 1; + funcname = luaL_gsub(L, modname, ".", LUA_OFSEP); + funcname = lua_pushfstring(L, POF"%s", funcname); + lua_remove(L, -2); /* remove 'gsub' result */ + return funcname; +} + + +static int loader_C (lua_State *L) { + const char *funcname; + const char *name = luaL_checkstring(L, 1); + const char *filename = findfile(L, name, "cpath"); + if (filename == NULL) return 1; /* library not found in this path */ + funcname = mkfuncname(L, name); + if (ll_loadfunc(L, filename, funcname) != 0) + loaderror(L, filename); + return 1; /* library loaded successfully */ +} + + +static int loader_Croot (lua_State *L) { + const char *funcname; + const char *filename; + const char *name = luaL_checkstring(L, 1); + const char *p = strchr(name, '.'); + int stat; + if (p == NULL) return 0; /* is root */ + lua_pushlstring(L, name, p - name); + filename = findfile(L, lua_tostring(L, -1), "cpath"); + if (filename == NULL) return 1; /* root not found */ + funcname = mkfuncname(L, name); + if ((stat = ll_loadfunc(L, filename, funcname)) != 0) { + if (stat != ERRFUNC) loaderror(L, filename); /* real error */ + lua_pushfstring(L, "\n\tno module " LUA_QS " in file " LUA_QS, + name, filename); + return 1; /* function not found */ + } + return 1; +} + + +static int loader_preload (lua_State *L) { + const char *name = luaL_checkstring(L, 1); + lua_getfield(L, LUA_ENVIRONINDEX, "preload"); + if (!lua_istable(L, -1)) + luaL_error(L, LUA_QL("package.preload") " must be a table"); + lua_getfield(L, -1, name); + if (lua_isnil(L, -1)) /* not found? */ + lua_pushfstring(L, "\n\tno field package.preload['%s']", name); + return 1; +} + + +static const int sentinel_ = 0; +#define sentinel ((void *)&sentinel_) + + +static int ll_require (lua_State *L) { + const char *name = luaL_checkstring(L, 1); + int i; + lua_settop(L, 1); /* _LOADED table will be at index 2 */ + lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); + lua_getfield(L, 2, name); + if (lua_toboolean(L, -1)) { /* is it there? */ + if (lua_touserdata(L, -1) == sentinel) /* check loops */ + luaL_error(L, "loop or previous error loading module " LUA_QS, name); + return 1; /* package is already loaded */ + } + /* else must load it; iterate over available loaders */ + lua_getfield(L, LUA_ENVIRONINDEX, "loaders"); + if (!lua_istable(L, -1)) + luaL_error(L, LUA_QL("package.loaders") " must be a table"); + lua_pushliteral(L, ""); /* error message accumulator */ + for (i=1; ; i++) { + lua_rawgeti(L, -2, i); /* get a loader */ + if (lua_isnil(L, -1)) + luaL_error(L, "module " LUA_QS " not found:%s", + name, lua_tostring(L, -2)); + lua_pushstring(L, name); + lua_call(L, 1, 1); /* call it */ + if (lua_isfunction(L, -1)) /* did it find module? */ + break; /* module loaded successfully */ + else if (lua_isstring(L, -1)) /* loader returned error message? */ + lua_concat(L, 2); /* accumulate it */ + else + lua_pop(L, 1); + } + lua_pushlightuserdata(L, sentinel); + lua_setfield(L, 2, name); /* _LOADED[name] = sentinel */ + lua_pushstring(L, name); /* pass name as argument to module */ + lua_call(L, 1, 1); /* run loaded module */ + if (!lua_isnil(L, -1)) /* non-nil return? */ + lua_setfield(L, 2, name); /* _LOADED[name] = returned value */ + lua_getfield(L, 2, name); + if (lua_touserdata(L, -1) == sentinel) { /* module did not set a value? */ + lua_pushboolean(L, 1); /* use true as result */ + lua_pushvalue(L, -1); /* extra copy to be returned */ + lua_setfield(L, 2, name); /* _LOADED[name] = true */ + } + return 1; +} + +/* }====================================================== */ + + + +/* +** {====================================================== +** 'module' function +** ======================================================= +*/ + + +static void setfenv (lua_State *L) { + lua_Debug ar; + if (lua_getstack(L, 1, &ar) == 0 || + lua_getinfo(L, "f", &ar) == 0 || /* get calling function */ + lua_iscfunction(L, -1)) + luaL_error(L, LUA_QL("module") " not called from a Lua function"); + lua_pushvalue(L, -2); + lua_setfenv(L, -2); + lua_pop(L, 1); +} + + +static void dooptions (lua_State *L, int n) { + int i; + for (i = 2; i <= n; i++) { + lua_pushvalue(L, i); /* get option (a function) */ + lua_pushvalue(L, -2); /* module */ + lua_call(L, 1, 0); + } +} + + +static void modinit (lua_State *L, const char *modname) { + const char *dot; + lua_pushvalue(L, -1); + lua_setfield(L, -2, "_M"); /* module._M = module */ + lua_pushstring(L, modname); + lua_setfield(L, -2, "_NAME"); + dot = strrchr(modname, '.'); /* look for last dot in module name */ + if (dot == NULL) dot = modname; + else dot++; + /* set _PACKAGE as package name (full module name minus last part) */ + lua_pushlstring(L, modname, dot - modname); + lua_setfield(L, -2, "_PACKAGE"); +} + + +static int ll_module (lua_State *L) { + const char *modname = luaL_checkstring(L, 1); + int loaded = lua_gettop(L) + 1; /* index of _LOADED table */ + lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); + lua_getfield(L, loaded, modname); /* get _LOADED[modname] */ + if (!lua_istable(L, -1)) { /* not found? */ + lua_pop(L, 1); /* remove previous result */ + /* try global variable (and create one if it does not exist) */ + if (luaL_findtable(L, LUA_GLOBALSINDEX, modname, 1) != NULL) + return luaL_error(L, "name conflict for module " LUA_QS, modname); + lua_pushvalue(L, -1); + lua_setfield(L, loaded, modname); /* _LOADED[modname] = new table */ + } + /* check whether table already has a _NAME field */ + lua_getfield(L, -1, "_NAME"); + if (!lua_isnil(L, -1)) /* is table an initialized module? */ + lua_pop(L, 1); + else { /* no; initialize it */ + lua_pop(L, 1); + modinit(L, modname); + } + lua_pushvalue(L, -1); + setfenv(L); + dooptions(L, loaded - 1); + return 0; +} + + +static int ll_seeall (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + if (!lua_getmetatable(L, 1)) { + lua_createtable(L, 0, 1); /* create new metatable */ + lua_pushvalue(L, -1); + lua_setmetatable(L, 1); + } + lua_pushvalue(L, LUA_GLOBALSINDEX); + lua_setfield(L, -2, "__index"); /* mt.__index = _G */ + return 0; +} + + +/* }====================================================== */ + + + +/* auxiliary mark (for internal use) */ +#define AUXMARK "\1" + +static void setpath (lua_State *L, const char *fieldname, const char *envname, + const char *def) { + const char *path = getenv(envname); + if (path == NULL) /* no environment variable? */ + lua_pushstring(L, def); /* use default */ + else { + /* replace ";;" by ";AUXMARK;" and then AUXMARK by default path */ + path = luaL_gsub(L, path, LUA_PATHSEP LUA_PATHSEP, + LUA_PATHSEP AUXMARK LUA_PATHSEP); + luaL_gsub(L, path, AUXMARK, def); + lua_remove(L, -2); + } + setprogdir(L); + lua_setfield(L, -2, fieldname); +} + + +static const luaL_Reg pk_funcs[] = { + {"loadlib", ll_loadlib}, + {"seeall", ll_seeall}, + {NULL, NULL} +}; + + +static const luaL_Reg ll_funcs[] = { + {"module", ll_module}, + {"require", ll_require}, + {NULL, NULL} +}; + + +static const lua_CFunction loaders[] = + {loader_preload, loader_Lua, loader_C, loader_Croot, NULL}; + + +LUALIB_API int luaopen_package (lua_State *L) { + int i; + /* create new type _LOADLIB */ + luaL_newmetatable(L, "_LOADLIB"); + lua_pushcfunction(L, gctm); + lua_setfield(L, -2, "__gc"); + /* create `package' table */ + luaL_register(L, LUA_LOADLIBNAME, pk_funcs); +#if defined(LUA_COMPAT_LOADLIB) + lua_getfield(L, -1, "loadlib"); + lua_setfield(L, LUA_GLOBALSINDEX, "loadlib"); +#endif + lua_pushvalue(L, -1); + lua_replace(L, LUA_ENVIRONINDEX); + /* create `loaders' table */ + lua_createtable(L, sizeof(loaders)/sizeof(loaders[0]) - 1, 0); + /* fill it with pre-defined loaders */ + for (i=0; loaders[i] != NULL; i++) { + lua_pushcfunction(L, loaders[i]); + lua_rawseti(L, -2, i+1); + } + lua_setfield(L, -2, "loaders"); /* put it in field `loaders' */ + setpath(L, "path", LUA_PATH, LUA_PATH_DEFAULT); /* set field `path' */ + setpath(L, "cpath", LUA_CPATH, LUA_CPATH_DEFAULT); /* set field `cpath' */ + /* store config information */ + lua_pushliteral(L, LUA_DIRSEP "\n" LUA_PATHSEP "\n" LUA_PATH_MARK "\n" + LUA_EXECDIR "\n" LUA_IGMARK); + lua_setfield(L, -2, "config"); + /* set field `loaded' */ + luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 2); + lua_setfield(L, -2, "loaded"); + /* set field `preload' */ + lua_newtable(L); + lua_setfield(L, -2, "preload"); + lua_pushvalue(L, LUA_GLOBALSINDEX); + luaL_register(L, NULL, ll_funcs); /* open lib into global table */ + lua_pop(L, 1); + return 1; /* return 'package' table */ +} + diff --git a/external/mit/lua/dist/src/lobject.c b/external/mit/lua/dist/src/lobject.c new file mode 100644 index 000000000..192f86d0b --- /dev/null +++ b/external/mit/lua/dist/src/lobject.c @@ -0,0 +1,216 @@ +/* $NetBSD: lobject.c,v 1.1.1.2 2012/03/15 00:08:09 alnsn Exp $ */ + +/* +** $Id: lobject.c,v 1.1.1.2 2012/03/15 00:08:09 alnsn Exp $ +** Some generic functions over Lua objects +** See Copyright Notice in lua.h +*/ + +#include +#include +#include +#include +#include + +#define lobject_c +#define LUA_CORE + +#include "lua.h" + +#include "ldo.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" +#include "lvm.h" + + + +const TValue luaO_nilobject_ = {{NULL}, LUA_TNIL}; + + +/* +** converts an integer to a "floating point byte", represented as +** (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if +** eeeee != 0 and (xxx) otherwise. +*/ +int luaO_int2fb (unsigned int x) { + int e = 0; /* expoent */ + while (x >= 16) { + x = (x+1) >> 1; + e++; + } + if (x < 8) return x; + else return ((e+1) << 3) | (cast_int(x) - 8); +} + + +/* converts back */ +int luaO_fb2int (int x) { + int e = (x >> 3) & 31; + if (e == 0) return x; + else return ((x & 7)+8) << (e - 1); +} + + +int luaO_log2 (unsigned int x) { + static const lu_byte log_2[256] = { + 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 + }; + int l = -1; + while (x >= 256) { l += 8; x >>= 8; } + return l + log_2[x]; + +} + + +int luaO_rawequalObj (const TValue *t1, const TValue *t2) { + if (ttype(t1) != ttype(t2)) return 0; + else switch (ttype(t1)) { + case LUA_TNIL: + return 1; + case LUA_TNUMBER: + return luai_numeq(nvalue(t1), nvalue(t2)); + case LUA_TBOOLEAN: + return bvalue(t1) == bvalue(t2); /* boolean true must be 1 !! */ + case LUA_TLIGHTUSERDATA: + return pvalue(t1) == pvalue(t2); + default: + lua_assert(iscollectable(t1)); + return gcvalue(t1) == gcvalue(t2); + } +} + + +int luaO_str2d (const char *s, lua_Number *result) { + char *endptr; + *result = lua_str2number(s, &endptr); + if (endptr == s) return 0; /* conversion failed */ + if (*endptr == 'x' || *endptr == 'X') /* maybe an hexadecimal constant? */ + *result = cast_num(strtoul(s, &endptr, 16)); + if (*endptr == '\0') return 1; /* most common case */ + while (isspace(cast(unsigned char, *endptr))) endptr++; + if (*endptr != '\0') return 0; /* invalid trailing characters? */ + return 1; +} + + + +static void pushstr (lua_State *L, const char *str) { + setsvalue2s(L, L->top, luaS_new(L, str)); + incr_top(L); +} + + +/* this function handles only `%d', `%c', %f, %p, and `%s' formats */ +const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { + int n = 1; + pushstr(L, ""); + for (;;) { + const char *e = strchr(fmt, '%'); + if (e == NULL) break; + setsvalue2s(L, L->top, luaS_newlstr(L, fmt, e-fmt)); + incr_top(L); + switch (*(e+1)) { + case 's': { + const char *s = va_arg(argp, char *); + if (s == NULL) s = "(null)"; + pushstr(L, s); + break; + } + case 'c': { + char buff[2]; + buff[0] = cast(char, va_arg(argp, int)); + buff[1] = '\0'; + pushstr(L, buff); + break; + } + case 'd': { + setnvalue(L->top, cast_num(va_arg(argp, int))); + incr_top(L); + break; + } + case 'f': { + setnvalue(L->top, cast_num(va_arg(argp, l_uacNumber))); + incr_top(L); + break; + } + case 'p': { + char buff[4*sizeof(void *) + 8]; /* should be enough space for a `%p' */ + sprintf(buff, "%p", va_arg(argp, void *)); + pushstr(L, buff); + break; + } + case '%': { + pushstr(L, "%"); + break; + } + default: { + char buff[3]; + buff[0] = '%'; + buff[1] = *(e+1); + buff[2] = '\0'; + pushstr(L, buff); + break; + } + } + n += 2; + fmt = e+2; + } + pushstr(L, fmt); + luaV_concat(L, n+1, cast_int(L->top - L->base) - 1); + L->top -= n; + return svalue(L->top - 1); +} + + +const char *luaO_pushfstring (lua_State *L, const char *fmt, ...) { + const char *msg; + va_list argp; + va_start(argp, fmt); + msg = luaO_pushvfstring(L, fmt, argp); + va_end(argp); + return msg; +} + + +void luaO_chunkid (char *out, const char *source, size_t bufflen) { + if (*source == '=') { + strncpy(out, source+1, bufflen); /* remove first char */ + out[bufflen-1] = '\0'; /* ensures null termination */ + } + else { /* out = "source", or "...source" */ + if (*source == '@') { + size_t l; + source++; /* skip the `@' */ + bufflen -= sizeof(" '...' "); + l = strlen(source); + strcpy(out, ""); + if (l > bufflen) { + source += (l-bufflen); /* get last part of file name */ + strcat(out, "..."); + } + strcat(out, source); + } + else { /* out = [string "string"] */ + size_t len = strcspn(source, "\n\r"); /* stop at first newline */ + bufflen -= sizeof(" [string \"...\"] "); + if (len > bufflen) len = bufflen; + strcpy(out, "[string \""); + if (source[len] != '\0') { /* must truncate? */ + strncat(out, source, len); + strcat(out, "..."); + } + else + strcat(out, source); + strcat(out, "\"]"); + } + } +} diff --git a/external/mit/lua/dist/src/lobject.h b/external/mit/lua/dist/src/lobject.h new file mode 100644 index 000000000..94b70ed2c --- /dev/null +++ b/external/mit/lua/dist/src/lobject.h @@ -0,0 +1,383 @@ +/* $NetBSD: lobject.h,v 1.1.1.2 2012/03/15 00:08:07 alnsn Exp $ */ + +/* +** $Id: lobject.h,v 1.1.1.2 2012/03/15 00:08:07 alnsn Exp $ +** Type definitions for Lua objects +** See Copyright Notice in lua.h +*/ + + +#ifndef lobject_h +#define lobject_h + + +#include + + +#include "llimits.h" +#include "lua.h" + + +/* tags for values visible from Lua */ +#define LAST_TAG LUA_TTHREAD + +#define NUM_TAGS (LAST_TAG+1) + + +/* +** Extra tags for non-values +*/ +#define LUA_TPROTO (LAST_TAG+1) +#define LUA_TUPVAL (LAST_TAG+2) +#define LUA_TDEADKEY (LAST_TAG+3) + + +/* +** Union of all collectable objects +*/ +typedef union GCObject GCObject; + + +/* +** Common Header for all collectable objects (in macro form, to be +** included in other objects) +*/ +#define CommonHeader GCObject *next; lu_byte tt; lu_byte marked + + +/* +** Common header in struct form +*/ +typedef struct GCheader { + CommonHeader; +} GCheader; + + + + +/* +** Union of all Lua values +*/ +typedef union { + GCObject *gc; + void *p; + lua_Number n; + int b; +} Value; + + +/* +** Tagged Values +*/ + +#define TValuefields Value value; int tt + +typedef struct lua_TValue { + TValuefields; +} TValue; + + +/* Macros to test type */ +#define ttisnil(o) (ttype(o) == LUA_TNIL) +#define ttisnumber(o) (ttype(o) == LUA_TNUMBER) +#define ttisstring(o) (ttype(o) == LUA_TSTRING) +#define ttistable(o) (ttype(o) == LUA_TTABLE) +#define ttisfunction(o) (ttype(o) == LUA_TFUNCTION) +#define ttisboolean(o) (ttype(o) == LUA_TBOOLEAN) +#define ttisuserdata(o) (ttype(o) == LUA_TUSERDATA) +#define ttisthread(o) (ttype(o) == LUA_TTHREAD) +#define ttislightuserdata(o) (ttype(o) == LUA_TLIGHTUSERDATA) + +/* Macros to access values */ +#define ttype(o) ((o)->tt) +#define gcvalue(o) check_exp(iscollectable(o), (o)->value.gc) +#define pvalue(o) check_exp(ttislightuserdata(o), (o)->value.p) +#define nvalue(o) check_exp(ttisnumber(o), (o)->value.n) +#define rawtsvalue(o) check_exp(ttisstring(o), &(o)->value.gc->ts) +#define tsvalue(o) (&rawtsvalue(o)->tsv) +#define rawuvalue(o) check_exp(ttisuserdata(o), &(o)->value.gc->u) +#define uvalue(o) (&rawuvalue(o)->uv) +#define clvalue(o) check_exp(ttisfunction(o), &(o)->value.gc->cl) +#define hvalue(o) check_exp(ttistable(o), &(o)->value.gc->h) +#define bvalue(o) check_exp(ttisboolean(o), (o)->value.b) +#define thvalue(o) check_exp(ttisthread(o), &(o)->value.gc->th) + +#define l_isfalse(o) (ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0)) + +/* +** for internal debug only +*/ +#define checkconsistency(obj) \ + lua_assert(!iscollectable(obj) || (ttype(obj) == (obj)->value.gc->gch.tt)) + +#define checkliveness(g,obj) \ + lua_assert(!iscollectable(obj) || \ + ((ttype(obj) == (obj)->value.gc->gch.tt) && !isdead(g, (obj)->value.gc))) + + +/* Macros to set values */ +#define setnilvalue(obj) ((obj)->tt=LUA_TNIL) + +#define setnvalue(obj,x) \ + { TValue *i_o=(obj); i_o->value.n=(x); i_o->tt=LUA_TNUMBER; } + +#define setpvalue(obj,x) \ + { TValue *i_o=(obj); i_o->value.p=(x); i_o->tt=LUA_TLIGHTUSERDATA; } + +#define setbvalue(obj,x) \ + { TValue *i_o=(obj); i_o->value.b=(x); i_o->tt=LUA_TBOOLEAN; } + +#define setsvalue(L,obj,x) \ + { TValue *i_o=(obj); \ + i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TSTRING; \ + checkliveness(G(L),i_o); } + +#define setuvalue(L,obj,x) \ + { TValue *i_o=(obj); \ + i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TUSERDATA; \ + checkliveness(G(L),i_o); } + +#define setthvalue(L,obj,x) \ + { TValue *i_o=(obj); \ + i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTHREAD; \ + checkliveness(G(L),i_o); } + +#define setclvalue(L,obj,x) \ + { TValue *i_o=(obj); \ + i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TFUNCTION; \ + checkliveness(G(L),i_o); } + +#define sethvalue(L,obj,x) \ + { TValue *i_o=(obj); \ + i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTABLE; \ + checkliveness(G(L),i_o); } + +#define setptvalue(L,obj,x) \ + { TValue *i_o=(obj); \ + i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TPROTO; \ + checkliveness(G(L),i_o); } + + + + +#define setobj(L,obj1,obj2) \ + { const TValue *o2=(obj2); TValue *o1=(obj1); \ + o1->value = o2->value; o1->tt=o2->tt; \ + checkliveness(G(L),o1); } + + +/* +** different types of sets, according to destination +*/ + +/* from stack to (same) stack */ +#define setobjs2s setobj +/* to stack (not from same stack) */ +#define setobj2s setobj +#define setsvalue2s setsvalue +#define sethvalue2s sethvalue +#define setptvalue2s setptvalue +/* from table to same table */ +#define setobjt2t setobj +/* to table */ +#define setobj2t setobj +/* to new object */ +#define setobj2n setobj +#define setsvalue2n setsvalue + +#define setttype(obj, tt) (ttype(obj) = (tt)) + + +#define iscollectable(o) (ttype(o) >= LUA_TSTRING) + + + +typedef TValue *StkId; /* index to stack elements */ + + +/* +** String headers for string table +*/ +typedef union TString { + L_Umaxalign dummy; /* ensures maximum alignment for strings */ + struct { + CommonHeader; + lu_byte reserved; + unsigned int hash; + size_t len; + } tsv; +} TString; + + +#define getstr(ts) cast(const char *, (ts) + 1) +#define svalue(o) getstr(rawtsvalue(o)) + + + +typedef union Udata { + L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */ + struct { + CommonHeader; + struct Table *metatable; + struct Table *env; + size_t len; + } uv; +} Udata; + + + + +/* +** Function Prototypes +*/ +typedef struct Proto { + CommonHeader; + TValue *k; /* constants used by the function */ + Instruction *code; + struct Proto **p; /* functions defined inside the function */ + int *lineinfo; /* map from opcodes to source lines */ + struct LocVar *locvars; /* information about local variables */ + TString **upvalues; /* upvalue names */ + TString *source; + int sizeupvalues; + int sizek; /* size of `k' */ + int sizecode; + int sizelineinfo; + int sizep; /* size of `p' */ + int sizelocvars; + int linedefined; + int lastlinedefined; + GCObject *gclist; + lu_byte nups; /* number of upvalues */ + lu_byte numparams; + lu_byte is_vararg; + lu_byte maxstacksize; +} Proto; + + +/* masks for new-style vararg */ +#define VARARG_HASARG 1 +#define VARARG_ISVARARG 2 +#define VARARG_NEEDSARG 4 + + +typedef struct LocVar { + TString *varname; + int startpc; /* first point where variable is active */ + int endpc; /* first point where variable is dead */ +} LocVar; + + + +/* +** Upvalues +*/ + +typedef struct UpVal { + CommonHeader; + TValue *v; /* points to stack or to its own value */ + union { + TValue value; /* the value (when closed) */ + struct { /* double linked list (when open) */ + struct UpVal *prev; + struct UpVal *next; + } l; + } u; +} UpVal; + + +/* +** Closures +*/ + +#define ClosureHeader \ + CommonHeader; lu_byte isC; lu_byte nupvalues; GCObject *gclist; \ + struct Table *env + +typedef struct CClosure { + ClosureHeader; + lua_CFunction f; + TValue upvalue[1]; +} CClosure; + + +typedef struct LClosure { + ClosureHeader; + struct Proto *p; + UpVal *upvals[1]; +} LClosure; + + +typedef union Closure { + CClosure c; + LClosure l; +} Closure; + + +#define iscfunction(o) (ttype(o) == LUA_TFUNCTION && clvalue(o)->c.isC) +#define isLfunction(o) (ttype(o) == LUA_TFUNCTION && !clvalue(o)->c.isC) + + +/* +** Tables +*/ + +typedef union TKey { + struct { + TValuefields; + struct Node *next; /* for chaining */ + } nk; + TValue tvk; +} TKey; + + +typedef struct Node { + TValue i_val; + TKey i_key; +} Node; + + +typedef struct Table { + CommonHeader; + lu_byte flags; /* 1<

    lsizenode)) + + +#define luaO_nilobject (&luaO_nilobject_) + +LUAI_DATA const TValue luaO_nilobject_; + +#define ceillog2(x) (luaO_log2((x)-1) + 1) + +LUAI_FUNC int luaO_log2 (unsigned int x); +LUAI_FUNC int luaO_int2fb (unsigned int x); +LUAI_FUNC int luaO_fb2int (int x); +LUAI_FUNC int luaO_rawequalObj (const TValue *t1, const TValue *t2); +LUAI_FUNC int luaO_str2d (const char *s, lua_Number *result); +LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt, + va_list argp); +LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...); +LUAI_FUNC void luaO_chunkid (char *out, const char *source, size_t len); + + +#endif + diff --git a/external/mit/lua/dist/src/lopcodes.c b/external/mit/lua/dist/src/lopcodes.c new file mode 100644 index 000000000..8c4e9fea7 --- /dev/null +++ b/external/mit/lua/dist/src/lopcodes.c @@ -0,0 +1,104 @@ +/* $NetBSD: lopcodes.c,v 1.1.1.2 2012/03/15 00:08:07 alnsn Exp $ */ + +/* +** $Id: lopcodes.c,v 1.1.1.2 2012/03/15 00:08:07 alnsn Exp $ +** See Copyright Notice in lua.h +*/ + + +#define lopcodes_c +#define LUA_CORE + + +#include "lopcodes.h" + + +/* ORDER OP */ + +const char *const luaP_opnames[NUM_OPCODES+1] = { + "MOVE", + "LOADK", + "LOADBOOL", + "LOADNIL", + "GETUPVAL", + "GETGLOBAL", + "GETTABLE", + "SETGLOBAL", + "SETUPVAL", + "SETTABLE", + "NEWTABLE", + "SELF", + "ADD", + "SUB", + "MUL", + "DIV", + "MOD", + "POW", + "UNM", + "NOT", + "LEN", + "CONCAT", + "JMP", + "EQ", + "LT", + "LE", + "TEST", + "TESTSET", + "CALL", + "TAILCALL", + "RETURN", + "FORLOOP", + "FORPREP", + "TFORLOOP", + "SETLIST", + "CLOSE", + "CLOSURE", + "VARARG", + NULL +}; + + +#define opmode(t,a,b,c,m) (((t)<<7) | ((a)<<6) | ((b)<<4) | ((c)<<2) | (m)) + +const lu_byte luaP_opmodes[NUM_OPCODES] = { +/* T A B C mode opcode */ + opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_MOVE */ + ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_LOADK */ + ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_LOADBOOL */ + ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LOADNIL */ + ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_GETUPVAL */ + ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_GETGLOBAL */ + ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_GETTABLE */ + ,opmode(0, 0, OpArgK, OpArgN, iABx) /* OP_SETGLOBAL */ + ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_SETUPVAL */ + ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABLE */ + ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_NEWTABLE */ + ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_SELF */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_ADD */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_SUB */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MUL */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_DIV */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MOD */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_POW */ + ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_UNM */ + ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_NOT */ + ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LEN */ + ,opmode(0, 1, OpArgR, OpArgR, iABC) /* OP_CONCAT */ + ,opmode(0, 0, OpArgR, OpArgN, iAsBx) /* OP_JMP */ + ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_EQ */ + ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LT */ + ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LE */ + ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TEST */ + ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TESTSET */ + ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_CALL */ + ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_TAILCALL */ + ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_RETURN */ + ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORLOOP */ + ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORPREP */ + ,opmode(1, 0, OpArgN, OpArgU, iABC) /* OP_TFORLOOP */ + ,opmode(0, 0, OpArgU, OpArgU, iABC) /* OP_SETLIST */ + ,opmode(0, 0, OpArgN, OpArgN, iABC) /* OP_CLOSE */ + ,opmode(0, 1, OpArgU, OpArgN, iABx) /* OP_CLOSURE */ + ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_VARARG */ +}; + diff --git a/external/mit/lua/dist/src/lopcodes.h b/external/mit/lua/dist/src/lopcodes.h new file mode 100644 index 000000000..83351d4a4 --- /dev/null +++ b/external/mit/lua/dist/src/lopcodes.h @@ -0,0 +1,270 @@ +/* $NetBSD: lopcodes.h,v 1.1.1.2 2012/03/15 00:08:14 alnsn Exp $ */ + +/* +** $Id: lopcodes.h,v 1.1.1.2 2012/03/15 00:08:14 alnsn Exp $ +** Opcodes for Lua virtual machine +** See Copyright Notice in lua.h +*/ + +#ifndef lopcodes_h +#define lopcodes_h + +#include "llimits.h" + + +/*=========================================================================== + We assume that instructions are unsigned numbers. + All instructions have an opcode in the first 6 bits. + Instructions can have the following fields: + `A' : 8 bits + `B' : 9 bits + `C' : 9 bits + `Bx' : 18 bits (`B' and `C' together) + `sBx' : signed Bx + + A signed argument is represented in excess K; that is, the number + value is the unsigned value minus K. K is exactly the maximum value + for that argument (so that -max is represented by 0, and +max is + represented by 2*max), which is half the maximum for the corresponding + unsigned argument. +===========================================================================*/ + + +enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */ + + +/* +** size and position of opcode arguments. +*/ +#define SIZE_C 9 +#define SIZE_B 9 +#define SIZE_Bx (SIZE_C + SIZE_B) +#define SIZE_A 8 + +#define SIZE_OP 6 + +#define POS_OP 0 +#define POS_A (POS_OP + SIZE_OP) +#define POS_C (POS_A + SIZE_A) +#define POS_B (POS_C + SIZE_C) +#define POS_Bx POS_C + + +/* +** limits for opcode arguments. +** we use (signed) int to manipulate most arguments, +** so they must fit in LUAI_BITSINT-1 bits (-1 for sign) +*/ +#if SIZE_Bx < LUAI_BITSINT-1 +#define MAXARG_Bx ((1<>1) /* `sBx' is signed */ +#else +#define MAXARG_Bx MAX_INT +#define MAXARG_sBx MAX_INT +#endif + + +#define MAXARG_A ((1<>POS_OP) & MASK1(SIZE_OP,0))) +#define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \ + ((cast(Instruction, o)<>POS_A) & MASK1(SIZE_A,0))) +#define SETARG_A(i,u) ((i) = (((i)&MASK0(SIZE_A,POS_A)) | \ + ((cast(Instruction, u)<>POS_B) & MASK1(SIZE_B,0))) +#define SETARG_B(i,b) ((i) = (((i)&MASK0(SIZE_B,POS_B)) | \ + ((cast(Instruction, b)<>POS_C) & MASK1(SIZE_C,0))) +#define SETARG_C(i,b) ((i) = (((i)&MASK0(SIZE_C,POS_C)) | \ + ((cast(Instruction, b)<>POS_Bx) & MASK1(SIZE_Bx,0))) +#define SETARG_Bx(i,b) ((i) = (((i)&MASK0(SIZE_Bx,POS_Bx)) | \ + ((cast(Instruction, b)< C) then pc++ */ +OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */ + +OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */ +OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ +OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */ + +OP_FORLOOP,/* A sBx R(A)+=R(A+2); + if R(A) =) R(A)*/ +OP_CLOSURE,/* A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) */ + +OP_VARARG/* A B R(A), R(A+1), ..., R(A+B-1) = vararg */ +} OpCode; + + +#define NUM_OPCODES (cast(int, OP_VARARG) + 1) + + + +/*=========================================================================== + Notes: + (*) In OP_CALL, if (B == 0) then B = top. C is the number of returns - 1, + and can be 0: OP_CALL then sets `top' to last_result+1, so + next open instruction (OP_CALL, OP_RETURN, OP_SETLIST) may use `top'. + + (*) In OP_VARARG, if (B == 0) then use actual number of varargs and + set top (like in OP_CALL with C == 0). + + (*) In OP_RETURN, if (B == 0) then return up to `top' + + (*) In OP_SETLIST, if (B == 0) then B = `top'; + if (C == 0) then next `instruction' is real C + + (*) For comparisons, A specifies what condition the test should accept + (true or false). + + (*) All `skips' (pc++) assume that next instruction is a jump +===========================================================================*/ + + +/* +** masks for instruction properties. The format is: +** bits 0-1: op mode +** bits 2-3: C arg mode +** bits 4-5: B arg mode +** bit 6: instruction set register A +** bit 7: operator is a test +*/ + +enum OpArgMask { + OpArgN, /* argument is not used */ + OpArgU, /* argument is used */ + OpArgR, /* argument is a register or a jump offset */ + OpArgK /* argument is a constant or register/constant */ +}; + +LUAI_DATA const lu_byte luaP_opmodes[NUM_OPCODES]; + +#define getOpMode(m) (cast(enum OpMode, luaP_opmodes[m] & 3)) +#define getBMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 4) & 3)) +#define getCMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 2) & 3)) +#define testAMode(m) (luaP_opmodes[m] & (1 << 6)) +#define testTMode(m) (luaP_opmodes[m] & (1 << 7)) + + +LUAI_DATA const char *const luaP_opnames[NUM_OPCODES+1]; /* opcode names */ + + +/* number of list items to accumulate before a SETLIST instruction */ +#define LFIELDS_PER_FLUSH 50 + + +#endif diff --git a/external/mit/lua/dist/src/loslib.c b/external/mit/lua/dist/src/loslib.c new file mode 100644 index 000000000..1f79c37fd --- /dev/null +++ b/external/mit/lua/dist/src/loslib.c @@ -0,0 +1,245 @@ +/* $NetBSD: loslib.c,v 1.1.1.2 2012/03/15 00:08:13 alnsn Exp $ */ + +/* +** $Id: loslib.c,v 1.1.1.2 2012/03/15 00:08:13 alnsn Exp $ +** Standard Operating System library +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include +#include +#include + +#define loslib_c +#define LUA_LIB + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +static int os_pushresult (lua_State *L, int i, const char *filename) { + int en = errno; /* calls to Lua API may change this value */ + if (i) { + lua_pushboolean(L, 1); + return 1; + } + else { + lua_pushnil(L); + lua_pushfstring(L, "%s: %s", filename, strerror(en)); + lua_pushinteger(L, en); + return 3; + } +} + + +static int os_execute (lua_State *L) { + lua_pushinteger(L, system(luaL_optstring(L, 1, NULL))); + return 1; +} + + +static int os_remove (lua_State *L) { + const char *filename = luaL_checkstring(L, 1); + return os_pushresult(L, remove(filename) == 0, filename); +} + + +static int os_rename (lua_State *L) { + const char *fromname = luaL_checkstring(L, 1); + const char *toname = luaL_checkstring(L, 2); + return os_pushresult(L, rename(fromname, toname) == 0, fromname); +} + + +static int os_tmpname (lua_State *L) { + char buff[LUA_TMPNAMBUFSIZE]; + int err; + lua_tmpnam(buff, err); + if (err) + return luaL_error(L, "unable to generate a unique filename"); + lua_pushstring(L, buff); + return 1; +} + + +static int os_getenv (lua_State *L) { + lua_pushstring(L, getenv(luaL_checkstring(L, 1))); /* if NULL push nil */ + return 1; +} + + +static int os_clock (lua_State *L) { + lua_pushnumber(L, ((lua_Number)clock())/(lua_Number)CLOCKS_PER_SEC); + return 1; +} + + +/* +** {====================================================== +** Time/Date operations +** { year=%Y, month=%m, day=%d, hour=%H, min=%M, sec=%S, +** wday=%w+1, yday=%j, isdst=? } +** ======================================================= +*/ + +static void setfield (lua_State *L, const char *key, int value) { + lua_pushinteger(L, value); + lua_setfield(L, -2, key); +} + +static void setboolfield (lua_State *L, const char *key, int value) { + if (value < 0) /* undefined? */ + return; /* does not set field */ + lua_pushboolean(L, value); + lua_setfield(L, -2, key); +} + +static int getboolfield (lua_State *L, const char *key) { + int res; + lua_getfield(L, -1, key); + res = lua_isnil(L, -1) ? -1 : lua_toboolean(L, -1); + lua_pop(L, 1); + return res; +} + + +static int getfield (lua_State *L, const char *key, int d) { + int res; + lua_getfield(L, -1, key); + if (lua_isnumber(L, -1)) + res = (int)lua_tointeger(L, -1); + else { + if (d < 0) + return luaL_error(L, "field " LUA_QS " missing in date table", key); + res = d; + } + lua_pop(L, 1); + return res; +} + + +static int os_date (lua_State *L) { + const char *s = luaL_optstring(L, 1, "%c"); + time_t t = luaL_opt(L, (time_t)luaL_checknumber, 2, time(NULL)); + struct tm *stm; + if (*s == '!') { /* UTC? */ + stm = gmtime(&t); + s++; /* skip `!' */ + } + else + stm = localtime(&t); + if (stm == NULL) /* invalid date? */ + lua_pushnil(L); + else if (strcmp(s, "*t") == 0) { + lua_createtable(L, 0, 9); /* 9 = number of fields */ + setfield(L, "sec", stm->tm_sec); + setfield(L, "min", stm->tm_min); + setfield(L, "hour", stm->tm_hour); + setfield(L, "day", stm->tm_mday); + setfield(L, "month", stm->tm_mon+1); + setfield(L, "year", stm->tm_year+1900); + setfield(L, "wday", stm->tm_wday+1); + setfield(L, "yday", stm->tm_yday+1); + setboolfield(L, "isdst", stm->tm_isdst); + } + else { + char cc[3]; + luaL_Buffer b; + cc[0] = '%'; cc[2] = '\0'; + luaL_buffinit(L, &b); + for (; *s; s++) { + if (*s != '%' || *(s + 1) == '\0') /* no conversion specifier? */ + luaL_addchar(&b, *s); + else { + size_t reslen; + char buff[200]; /* should be big enough for any conversion result */ + cc[1] = *(++s); + reslen = strftime(buff, sizeof(buff), cc, stm); + luaL_addlstring(&b, buff, reslen); + } + } + luaL_pushresult(&b); + } + return 1; +} + + +static int os_time (lua_State *L) { + time_t t; + if (lua_isnoneornil(L, 1)) /* called without args? */ + t = time(NULL); /* get current time */ + else { + struct tm ts; + luaL_checktype(L, 1, LUA_TTABLE); + lua_settop(L, 1); /* make sure table is at the top */ + ts.tm_sec = getfield(L, "sec", 0); + ts.tm_min = getfield(L, "min", 0); + ts.tm_hour = getfield(L, "hour", 12); + ts.tm_mday = getfield(L, "day", -1); + ts.tm_mon = getfield(L, "month", -1) - 1; + ts.tm_year = getfield(L, "year", -1) - 1900; + ts.tm_isdst = getboolfield(L, "isdst"); + t = mktime(&ts); + } + if (t == (time_t)(-1)) + lua_pushnil(L); + else + lua_pushnumber(L, (lua_Number)t); + return 1; +} + + +static int os_difftime (lua_State *L) { + lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)), + (time_t)(luaL_optnumber(L, 2, 0)))); + return 1; +} + +/* }====================================================== */ + + +static int os_setlocale (lua_State *L) { + static const int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, + LC_NUMERIC, LC_TIME}; + static const char *const catnames[] = {"all", "collate", "ctype", "monetary", + "numeric", "time", NULL}; + const char *l = luaL_optstring(L, 1, NULL); + int op = luaL_checkoption(L, 2, "all", catnames); + lua_pushstring(L, setlocale(cat[op], l)); + return 1; +} + + +static int os_exit (lua_State *L) { + exit(luaL_optint(L, 1, EXIT_SUCCESS)); +} + +static const luaL_Reg syslib[] = { + {"clock", os_clock}, + {"date", os_date}, + {"difftime", os_difftime}, + {"execute", os_execute}, + {"exit", os_exit}, + {"getenv", os_getenv}, + {"remove", os_remove}, + {"rename", os_rename}, + {"setlocale", os_setlocale}, + {"time", os_time}, + {"tmpname", os_tmpname}, + {NULL, NULL} +}; + +/* }====================================================== */ + + + +LUALIB_API int luaopen_os (lua_State *L) { + luaL_register(L, LUA_OSLIBNAME, syslib); + return 1; +} + diff --git a/external/mit/lua/dist/src/lparser.c b/external/mit/lua/dist/src/lparser.c new file mode 100644 index 000000000..d37e70f7c --- /dev/null +++ b/external/mit/lua/dist/src/lparser.c @@ -0,0 +1,1341 @@ +/* $NetBSD: lparser.c,v 1.1.1.2 2012/03/15 00:08:07 alnsn Exp $ */ + +/* +** $Id: lparser.c,v 1.1.1.2 2012/03/15 00:08:07 alnsn Exp $ +** Lua Parser +** See Copyright Notice in lua.h +*/ + + +#include + +#define lparser_c +#define LUA_CORE + +#include "lua.h" + +#include "lcode.h" +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "llex.h" +#include "lmem.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lparser.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" + + + +#define hasmultret(k) ((k) == VCALL || (k) == VVARARG) + +#define getlocvar(fs, i) ((fs)->f->locvars[(fs)->actvar[i]]) + +#define luaY_checklimit(fs,v,l,m) if ((v)>(l)) errorlimit(fs,l,m) + + +/* +** nodes for block list (list of active blocks) +*/ +typedef struct BlockCnt { + struct BlockCnt *previous; /* chain */ + int breaklist; /* list of jumps out of this loop */ + lu_byte nactvar; /* # active locals outside the breakable structure */ + lu_byte upval; /* true if some variable in the block is an upvalue */ + lu_byte isbreakable; /* true if `block' is a loop */ +} BlockCnt; + + + +/* +** prototypes for recursive non-terminal functions +*/ +static void chunk (LexState *ls); +static void expr (LexState *ls, expdesc *v); + + +static void anchor_token (LexState *ls) { + if (ls->t.token == TK_NAME || ls->t.token == TK_STRING) { + TString *ts = ls->t.seminfo.ts; + luaX_newstring(ls, getstr(ts), ts->tsv.len); + } +} + + +static void error_expected (LexState *ls, int token) { + luaX_syntaxerror(ls, + luaO_pushfstring(ls->L, LUA_QS " expected", luaX_token2str(ls, token))); +} + + +static void errorlimit (FuncState *fs, int limit, const char *what) { + const char *msg = (fs->f->linedefined == 0) ? + luaO_pushfstring(fs->L, "main function has more than %d %s", limit, what) : + luaO_pushfstring(fs->L, "function at line %d has more than %d %s", + fs->f->linedefined, limit, what); + luaX_lexerror(fs->ls, msg, 0); +} + + +static int testnext (LexState *ls, int c) { + if (ls->t.token == c) { + luaX_next(ls); + return 1; + } + else return 0; +} + + +static void check (LexState *ls, int c) { + if (ls->t.token != c) + error_expected(ls, c); +} + +static void checknext (LexState *ls, int c) { + check(ls, c); + luaX_next(ls); +} + + +#define check_condition(ls,c,msg) { if (!(c)) luaX_syntaxerror(ls, msg); } + + + +static void check_match (LexState *ls, int what, int who, int where) { + if (!testnext(ls, what)) { + if (where == ls->linenumber) + error_expected(ls, what); + else { + luaX_syntaxerror(ls, luaO_pushfstring(ls->L, + LUA_QS " expected (to close " LUA_QS " at line %d)", + luaX_token2str(ls, what), luaX_token2str(ls, who), where)); + } + } +} + + +static TString *str_checkname (LexState *ls) { + TString *ts; + check(ls, TK_NAME); + ts = ls->t.seminfo.ts; + luaX_next(ls); + return ts; +} + + +static void init_exp (expdesc *e, expkind k, int i) { + e->f = e->t = NO_JUMP; + e->k = k; + e->u.s.info = i; +} + + +static void codestring (LexState *ls, expdesc *e, TString *s) { + init_exp(e, VK, luaK_stringK(ls->fs, s)); +} + + +static void checkname(LexState *ls, expdesc *e) { + codestring(ls, e, str_checkname(ls)); +} + + +static int registerlocalvar (LexState *ls, TString *varname) { + FuncState *fs = ls->fs; + Proto *f = fs->f; + int oldsize = f->sizelocvars; + luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars, + LocVar, SHRT_MAX, "too many local variables"); + while (oldsize < f->sizelocvars) f->locvars[oldsize++].varname = NULL; + f->locvars[fs->nlocvars].varname = varname; + luaC_objbarrier(ls->L, f, varname); + return fs->nlocvars++; +} + + +#define new_localvarliteral(ls,v,n) \ + new_localvar(ls, luaX_newstring(ls, "" v, (sizeof(v)/sizeof(char))-1), n) + + +static void new_localvar (LexState *ls, TString *name, int n) { + FuncState *fs = ls->fs; + luaY_checklimit(fs, fs->nactvar+n+1, LUAI_MAXVARS, "local variables"); + fs->actvar[fs->nactvar+n] = cast(unsigned short, registerlocalvar(ls, name)); +} + + +static void adjustlocalvars (LexState *ls, int nvars) { + FuncState *fs = ls->fs; + fs->nactvar = cast_byte(fs->nactvar + nvars); + for (; nvars; nvars--) { + getlocvar(fs, fs->nactvar - nvars).startpc = fs->pc; + } +} + + +static void removevars (LexState *ls, int tolevel) { + FuncState *fs = ls->fs; + while (fs->nactvar > tolevel) + getlocvar(fs, --fs->nactvar).endpc = fs->pc; +} + + +static int indexupvalue (FuncState *fs, TString *name, expdesc *v) { + int i; + Proto *f = fs->f; + int oldsize = f->sizeupvalues; + for (i=0; inups; i++) { + if (fs->upvalues[i].k == v->k && fs->upvalues[i].info == v->u.s.info) { + lua_assert(f->upvalues[i] == name); + return i; + } + } + /* new one */ + luaY_checklimit(fs, f->nups + 1, LUAI_MAXUPVALUES, "upvalues"); + luaM_growvector(fs->L, f->upvalues, f->nups, f->sizeupvalues, + TString *, MAX_INT, ""); + while (oldsize < f->sizeupvalues) f->upvalues[oldsize++] = NULL; + f->upvalues[f->nups] = name; + luaC_objbarrier(fs->L, f, name); + lua_assert(v->k == VLOCAL || v->k == VUPVAL); + fs->upvalues[f->nups].k = cast_byte(v->k); + fs->upvalues[f->nups].info = cast_byte(v->u.s.info); + return f->nups++; +} + + +static int searchvar (FuncState *fs, TString *n) { + int i; + for (i=fs->nactvar-1; i >= 0; i--) { + if (n == getlocvar(fs, i).varname) + return i; + } + return -1; /* not found */ +} + + +static void markupval (FuncState *fs, int level) { + BlockCnt *bl = fs->bl; + while (bl && bl->nactvar > level) bl = bl->previous; + if (bl) bl->upval = 1; +} + + +static int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { + if (fs == NULL) { /* no more levels? */ + init_exp(var, VGLOBAL, NO_REG); /* default is global variable */ + return VGLOBAL; + } + else { + int v = searchvar(fs, n); /* look up at current level */ + if (v >= 0) { + init_exp(var, VLOCAL, v); + if (!base) + markupval(fs, v); /* local will be used as an upval */ + return VLOCAL; + } + else { /* not found at current level; try upper one */ + if (singlevaraux(fs->prev, n, var, 0) == VGLOBAL) + return VGLOBAL; + var->u.s.info = indexupvalue(fs, n, var); /* else was LOCAL or UPVAL */ + var->k = VUPVAL; /* upvalue in this level */ + return VUPVAL; + } + } +} + + +static void singlevar (LexState *ls, expdesc *var) { + TString *varname = str_checkname(ls); + FuncState *fs = ls->fs; + if (singlevaraux(fs, varname, var, 1) == VGLOBAL) + var->u.s.info = luaK_stringK(fs, varname); /* info points to global name */ +} + + +static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { + FuncState *fs = ls->fs; + int extra = nvars - nexps; + if (hasmultret(e->k)) { + extra++; /* includes call itself */ + if (extra < 0) extra = 0; + luaK_setreturns(fs, e, extra); /* last exp. provides the difference */ + if (extra > 1) luaK_reserveregs(fs, extra-1); + } + else { + if (e->k != VVOID) luaK_exp2nextreg(fs, e); /* close last expression */ + if (extra > 0) { + int reg = fs->freereg; + luaK_reserveregs(fs, extra); + luaK_nil(fs, reg, extra); + } + } +} + + +static void enterlevel (LexState *ls) { + if (++ls->L->nCcalls > LUAI_MAXCCALLS) + luaX_lexerror(ls, "chunk has too many syntax levels", 0); +} + + +#define leavelevel(ls) ((ls)->L->nCcalls--) + + +static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isbreakable) { + bl->breaklist = NO_JUMP; + bl->isbreakable = isbreakable; + bl->nactvar = fs->nactvar; + bl->upval = 0; + bl->previous = fs->bl; + fs->bl = bl; + lua_assert(fs->freereg == fs->nactvar); +} + + +static void leaveblock (FuncState *fs) { + BlockCnt *bl = fs->bl; + fs->bl = bl->previous; + removevars(fs->ls, bl->nactvar); + if (bl->upval) + luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0); + /* a block either controls scope or breaks (never both) */ + lua_assert(!bl->isbreakable || !bl->upval); + lua_assert(bl->nactvar == fs->nactvar); + fs->freereg = fs->nactvar; /* free registers */ + luaK_patchtohere(fs, bl->breaklist); +} + + +static void pushclosure (LexState *ls, FuncState *func, expdesc *v) { + FuncState *fs = ls->fs; + Proto *f = fs->f; + int oldsize = f->sizep; + int i; + luaM_growvector(ls->L, f->p, fs->np, f->sizep, Proto *, + MAXARG_Bx, "constant table overflow"); + while (oldsize < f->sizep) f->p[oldsize++] = NULL; + f->p[fs->np++] = func->f; + luaC_objbarrier(ls->L, f, func->f); + init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np-1)); + for (i=0; if->nups; i++) { + OpCode o = (func->upvalues[i].k == VLOCAL) ? OP_MOVE : OP_GETUPVAL; + luaK_codeABC(fs, o, 0, func->upvalues[i].info, 0); + } +} + + +static void open_func (LexState *ls, FuncState *fs) { + lua_State *L = ls->L; + Proto *f = luaF_newproto(L); + fs->f = f; + fs->prev = ls->fs; /* linked list of funcstates */ + fs->ls = ls; + fs->L = L; + ls->fs = fs; + fs->pc = 0; + fs->lasttarget = -1; + fs->jpc = NO_JUMP; + fs->freereg = 0; + fs->nk = 0; + fs->np = 0; + fs->nlocvars = 0; + fs->nactvar = 0; + fs->bl = NULL; + f->source = ls->source; + f->maxstacksize = 2; /* registers 0/1 are always valid */ + fs->h = luaH_new(L, 0, 0); + /* anchor table of constants and prototype (to avoid being collected) */ + sethvalue2s(L, L->top, fs->h); + incr_top(L); + setptvalue2s(L, L->top, f); + incr_top(L); +} + + +static void close_func (LexState *ls) { + lua_State *L = ls->L; + FuncState *fs = ls->fs; + Proto *f = fs->f; + removevars(ls, 0); + luaK_ret(fs, 0, 0); /* final return */ + luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction); + f->sizecode = fs->pc; + luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int); + f->sizelineinfo = fs->pc; + luaM_reallocvector(L, f->k, f->sizek, fs->nk, TValue); + f->sizek = fs->nk; + luaM_reallocvector(L, f->p, f->sizep, fs->np, Proto *); + f->sizep = fs->np; + luaM_reallocvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar); + f->sizelocvars = fs->nlocvars; + luaM_reallocvector(L, f->upvalues, f->sizeupvalues, f->nups, TString *); + f->sizeupvalues = f->nups; + lua_assert(luaG_checkcode(f)); + lua_assert(fs->bl == NULL); + ls->fs = fs->prev; + /* last token read was anchored in defunct function; must reanchor it */ + if (fs) anchor_token(ls); + L->top -= 2; /* remove table and prototype from the stack */ +} + + +Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) { + struct LexState lexstate; + struct FuncState funcstate; + lexstate.buff = buff; + luaX_setinput(L, &lexstate, z, luaS_new(L, name)); + open_func(&lexstate, &funcstate); + funcstate.f->is_vararg = VARARG_ISVARARG; /* main func. is always vararg */ + luaX_next(&lexstate); /* read first token */ + chunk(&lexstate); + check(&lexstate, TK_EOS); + close_func(&lexstate); + lua_assert(funcstate.prev == NULL); + lua_assert(funcstate.f->nups == 0); + lua_assert(lexstate.fs == NULL); + return funcstate.f; +} + + + +/*============================================================*/ +/* GRAMMAR RULES */ +/*============================================================*/ + + +static void field (LexState *ls, expdesc *v) { + /* field -> ['.' | ':'] NAME */ + FuncState *fs = ls->fs; + expdesc key; + luaK_exp2anyreg(fs, v); + luaX_next(ls); /* skip the dot or colon */ + checkname(ls, &key); + luaK_indexed(fs, v, &key); +} + + +static void yindex (LexState *ls, expdesc *v) { + /* index -> '[' expr ']' */ + luaX_next(ls); /* skip the '[' */ + expr(ls, v); + luaK_exp2val(ls->fs, v); + checknext(ls, ']'); +} + + +/* +** {====================================================================== +** Rules for Constructors +** ======================================================================= +*/ + + +struct ConsControl { + expdesc v; /* last list item read */ + expdesc *t; /* table descriptor */ + int nh; /* total number of `record' elements */ + int na; /* total number of array elements */ + int tostore; /* number of array elements pending to be stored */ +}; + + +static void recfield (LexState *ls, struct ConsControl *cc) { + /* recfield -> (NAME | `['exp1`]') = exp1 */ + FuncState *fs = ls->fs; + int reg = ls->fs->freereg; + expdesc key, val; + int rkkey; + if (ls->t.token == TK_NAME) { + luaY_checklimit(fs, cc->nh, MAX_INT, "items in a constructor"); + checkname(ls, &key); + } + else /* ls->t.token == '[' */ + yindex(ls, &key); + cc->nh++; + checknext(ls, '='); + rkkey = luaK_exp2RK(fs, &key); + expr(ls, &val); + luaK_codeABC(fs, OP_SETTABLE, cc->t->u.s.info, rkkey, luaK_exp2RK(fs, &val)); + fs->freereg = reg; /* free registers */ +} + + +static void closelistfield (FuncState *fs, struct ConsControl *cc) { + if (cc->v.k == VVOID) return; /* there is no list item */ + luaK_exp2nextreg(fs, &cc->v); + cc->v.k = VVOID; + if (cc->tostore == LFIELDS_PER_FLUSH) { + luaK_setlist(fs, cc->t->u.s.info, cc->na, cc->tostore); /* flush */ + cc->tostore = 0; /* no more items pending */ + } +} + + +static void lastlistfield (FuncState *fs, struct ConsControl *cc) { + if (cc->tostore == 0) return; + if (hasmultret(cc->v.k)) { + luaK_setmultret(fs, &cc->v); + luaK_setlist(fs, cc->t->u.s.info, cc->na, LUA_MULTRET); + cc->na--; /* do not count last expression (unknown number of elements) */ + } + else { + if (cc->v.k != VVOID) + luaK_exp2nextreg(fs, &cc->v); + luaK_setlist(fs, cc->t->u.s.info, cc->na, cc->tostore); + } +} + + +static void listfield (LexState *ls, struct ConsControl *cc) { + expr(ls, &cc->v); + luaY_checklimit(ls->fs, cc->na, MAX_INT, "items in a constructor"); + cc->na++; + cc->tostore++; +} + + +static void constructor (LexState *ls, expdesc *t) { + /* constructor -> ?? */ + FuncState *fs = ls->fs; + int line = ls->linenumber; + int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0); + struct ConsControl cc; + cc.na = cc.nh = cc.tostore = 0; + cc.t = t; + init_exp(t, VRELOCABLE, pc); + init_exp(&cc.v, VVOID, 0); /* no value (yet) */ + luaK_exp2nextreg(ls->fs, t); /* fix it at stack top (for gc) */ + checknext(ls, '{'); + do { + lua_assert(cc.v.k == VVOID || cc.tostore > 0); + if (ls->t.token == '}') break; + closelistfield(fs, &cc); + switch(ls->t.token) { + case TK_NAME: { /* may be listfields or recfields */ + luaX_lookahead(ls); + if (ls->lookahead.token != '=') /* expression? */ + listfield(ls, &cc); + else + recfield(ls, &cc); + break; + } + case '[': { /* constructor_item -> recfield */ + recfield(ls, &cc); + break; + } + default: { /* constructor_part -> listfield */ + listfield(ls, &cc); + break; + } + } + } while (testnext(ls, ',') || testnext(ls, ';')); + check_match(ls, '}', '{', line); + lastlistfield(fs, &cc); + SETARG_B(fs->f->code[pc], luaO_int2fb(cc.na)); /* set initial array size */ + SETARG_C(fs->f->code[pc], luaO_int2fb(cc.nh)); /* set initial table size */ +} + +/* }====================================================================== */ + + + +static void parlist (LexState *ls) { + /* parlist -> [ param { `,' param } ] */ + FuncState *fs = ls->fs; + Proto *f = fs->f; + int nparams = 0; + f->is_vararg = 0; + if (ls->t.token != ')') { /* is `parlist' not empty? */ + do { + switch (ls->t.token) { + case TK_NAME: { /* param -> NAME */ + new_localvar(ls, str_checkname(ls), nparams++); + break; + } + case TK_DOTS: { /* param -> `...' */ + luaX_next(ls); +#if defined(LUA_COMPAT_VARARG) + /* use `arg' as default name */ + new_localvarliteral(ls, "arg", nparams++); + f->is_vararg = VARARG_HASARG | VARARG_NEEDSARG; +#endif + f->is_vararg |= VARARG_ISVARARG; + break; + } + default: luaX_syntaxerror(ls, " or " LUA_QL("...") " expected"); + } + } while (!f->is_vararg && testnext(ls, ',')); + } + adjustlocalvars(ls, nparams); + f->numparams = cast_byte(fs->nactvar - (f->is_vararg & VARARG_HASARG)); + luaK_reserveregs(fs, fs->nactvar); /* reserve register for parameters */ +} + + +static void body (LexState *ls, expdesc *e, int needself, int line) { + /* body -> `(' parlist `)' chunk END */ + FuncState new_fs; + open_func(ls, &new_fs); + new_fs.f->linedefined = line; + checknext(ls, '('); + if (needself) { + new_localvarliteral(ls, "self", 0); + adjustlocalvars(ls, 1); + } + parlist(ls); + checknext(ls, ')'); + chunk(ls); + new_fs.f->lastlinedefined = ls->linenumber; + check_match(ls, TK_END, TK_FUNCTION, line); + close_func(ls); + pushclosure(ls, &new_fs, e); +} + + +static int explist1 (LexState *ls, expdesc *v) { + /* explist1 -> expr { `,' expr } */ + int n = 1; /* at least one expression */ + expr(ls, v); + while (testnext(ls, ',')) { + luaK_exp2nextreg(ls->fs, v); + expr(ls, v); + n++; + } + return n; +} + + +static void funcargs (LexState *ls, expdesc *f) { + FuncState *fs = ls->fs; + expdesc args; + int base, nparams; + int line = ls->linenumber; + switch (ls->t.token) { + case '(': { /* funcargs -> `(' [ explist1 ] `)' */ + if (line != ls->lastline) + luaX_syntaxerror(ls,"ambiguous syntax (function call x new statement)"); + luaX_next(ls); + if (ls->t.token == ')') /* arg list is empty? */ + args.k = VVOID; + else { + explist1(ls, &args); + luaK_setmultret(fs, &args); + } + check_match(ls, ')', '(', line); + break; + } + case '{': { /* funcargs -> constructor */ + constructor(ls, &args); + break; + } + case TK_STRING: { /* funcargs -> STRING */ + codestring(ls, &args, ls->t.seminfo.ts); + luaX_next(ls); /* must use `seminfo' before `next' */ + break; + } + default: { + luaX_syntaxerror(ls, "function arguments expected"); + return; + } + } + lua_assert(f->k == VNONRELOC); + base = f->u.s.info; /* base register for call */ + if (hasmultret(args.k)) + nparams = LUA_MULTRET; /* open call */ + else { + if (args.k != VVOID) + luaK_exp2nextreg(fs, &args); /* close last argument */ + nparams = fs->freereg - (base+1); + } + init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams+1, 2)); + luaK_fixline(fs, line); + fs->freereg = base+1; /* call remove function and arguments and leaves + (unless changed) one result */ +} + + + + +/* +** {====================================================================== +** Expression parsing +** ======================================================================= +*/ + + +static void prefixexp (LexState *ls, expdesc *v) { + /* prefixexp -> NAME | '(' expr ')' */ + switch (ls->t.token) { + case '(': { + int line = ls->linenumber; + luaX_next(ls); + expr(ls, v); + check_match(ls, ')', '(', line); + luaK_dischargevars(ls->fs, v); + return; + } + case TK_NAME: { + singlevar(ls, v); + return; + } + default: { + luaX_syntaxerror(ls, "unexpected symbol"); + return; + } + } +} + + +static void primaryexp (LexState *ls, expdesc *v) { + /* primaryexp -> + prefixexp { `.' NAME | `[' exp `]' | `:' NAME funcargs | funcargs } */ + FuncState *fs = ls->fs; + prefixexp(ls, v); + for (;;) { + switch (ls->t.token) { + case '.': { /* field */ + field(ls, v); + break; + } + case '[': { /* `[' exp1 `]' */ + expdesc key; + luaK_exp2anyreg(fs, v); + yindex(ls, &key); + luaK_indexed(fs, v, &key); + break; + } + case ':': { /* `:' NAME funcargs */ + expdesc key; + luaX_next(ls); + checkname(ls, &key); + luaK_self(fs, v, &key); + funcargs(ls, v); + break; + } + case '(': case TK_STRING: case '{': { /* funcargs */ + luaK_exp2nextreg(fs, v); + funcargs(ls, v); + break; + } + default: return; + } + } +} + + +static void simpleexp (LexState *ls, expdesc *v) { + /* simpleexp -> NUMBER | STRING | NIL | true | false | ... | + constructor | FUNCTION body | primaryexp */ + switch (ls->t.token) { + case TK_NUMBER: { + init_exp(v, VKNUM, 0); + v->u.nval = ls->t.seminfo.r; + break; + } + case TK_STRING: { + codestring(ls, v, ls->t.seminfo.ts); + break; + } + case TK_NIL: { + init_exp(v, VNIL, 0); + break; + } + case TK_TRUE: { + init_exp(v, VTRUE, 0); + break; + } + case TK_FALSE: { + init_exp(v, VFALSE, 0); + break; + } + case TK_DOTS: { /* vararg */ + FuncState *fs = ls->fs; + check_condition(ls, fs->f->is_vararg, + "cannot use " LUA_QL("...") " outside a vararg function"); + fs->f->is_vararg &= ~VARARG_NEEDSARG; /* don't need 'arg' */ + init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0)); + break; + } + case '{': { /* constructor */ + constructor(ls, v); + return; + } + case TK_FUNCTION: { + luaX_next(ls); + body(ls, v, 0, ls->linenumber); + return; + } + default: { + primaryexp(ls, v); + return; + } + } + luaX_next(ls); +} + + +static UnOpr getunopr (int op) { + switch (op) { + case TK_NOT: return OPR_NOT; + case '-': return OPR_MINUS; + case '#': return OPR_LEN; + default: return OPR_NOUNOPR; + } +} + + +static BinOpr getbinopr (int op) { + switch (op) { + case '+': return OPR_ADD; + case '-': return OPR_SUB; + case '*': return OPR_MUL; + case '/': return OPR_DIV; + case '%': return OPR_MOD; + case '^': return OPR_POW; + case TK_CONCAT: return OPR_CONCAT; + case TK_NE: return OPR_NE; + case TK_EQ: return OPR_EQ; + case '<': return OPR_LT; + case TK_LE: return OPR_LE; + case '>': return OPR_GT; + case TK_GE: return OPR_GE; + case TK_AND: return OPR_AND; + case TK_OR: return OPR_OR; + default: return OPR_NOBINOPR; + } +} + + +static const struct { + lu_byte left; /* left priority for each binary operator */ + lu_byte right; /* right priority */ +} priority[] = { /* ORDER OPR */ + {6, 6}, {6, 6}, {7, 7}, {7, 7}, {7, 7}, /* `+' `-' `/' `%' */ + {10, 9}, {5, 4}, /* power and concat (right associative) */ + {3, 3}, {3, 3}, /* equality and inequality */ + {3, 3}, {3, 3}, {3, 3}, {3, 3}, /* order */ + {2, 2}, {1, 1} /* logical (and/or) */ +}; + +#define UNARY_PRIORITY 8 /* priority for unary operators */ + + +/* +** subexpr -> (simpleexp | unop subexpr) { binop subexpr } +** where `binop' is any binary operator with a priority higher than `limit' +*/ +static BinOpr subexpr (LexState *ls, expdesc *v, unsigned int limit) { + BinOpr op; + UnOpr uop; + enterlevel(ls); + uop = getunopr(ls->t.token); + if (uop != OPR_NOUNOPR) { + luaX_next(ls); + subexpr(ls, v, UNARY_PRIORITY); + luaK_prefix(ls->fs, uop, v); + } + else simpleexp(ls, v); + /* expand while operators have priorities higher than `limit' */ + op = getbinopr(ls->t.token); + while (op != OPR_NOBINOPR && priority[op].left > limit) { + expdesc v2; + BinOpr nextop; + luaX_next(ls); + luaK_infix(ls->fs, op, v); + /* read sub-expression with higher priority */ + nextop = subexpr(ls, &v2, priority[op].right); + luaK_posfix(ls->fs, op, v, &v2); + op = nextop; + } + leavelevel(ls); + return op; /* return first untreated operator */ +} + + +static void expr (LexState *ls, expdesc *v) { + subexpr(ls, v, 0); +} + +/* }==================================================================== */ + + + +/* +** {====================================================================== +** Rules for Statements +** ======================================================================= +*/ + + +static int block_follow (int token) { + switch (token) { + case TK_ELSE: case TK_ELSEIF: case TK_END: + case TK_UNTIL: case TK_EOS: + return 1; + default: return 0; + } +} + + +static void block (LexState *ls) { + /* block -> chunk */ + FuncState *fs = ls->fs; + BlockCnt bl; + enterblock(fs, &bl, 0); + chunk(ls); + lua_assert(bl.breaklist == NO_JUMP); + leaveblock(fs); +} + + +/* +** structure to chain all variables in the left-hand side of an +** assignment +*/ +struct LHS_assign { + struct LHS_assign *prev; + expdesc v; /* variable (global, local, upvalue, or indexed) */ +}; + + +/* +** check whether, in an assignment to a local variable, the local variable +** is needed in a previous assignment (to a table). If so, save original +** local value in a safe place and use this safe copy in the previous +** assignment. +*/ +static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) { + FuncState *fs = ls->fs; + int extra = fs->freereg; /* eventual position to save local variable */ + int conflict = 0; + for (; lh; lh = lh->prev) { + if (lh->v.k == VINDEXED) { + if (lh->v.u.s.info == v->u.s.info) { /* conflict? */ + conflict = 1; + lh->v.u.s.info = extra; /* previous assignment will use safe copy */ + } + if (lh->v.u.s.aux == v->u.s.info) { /* conflict? */ + conflict = 1; + lh->v.u.s.aux = extra; /* previous assignment will use safe copy */ + } + } + } + if (conflict) { + luaK_codeABC(fs, OP_MOVE, fs->freereg, v->u.s.info, 0); /* make copy */ + luaK_reserveregs(fs, 1); + } +} + + +static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { + expdesc e; + check_condition(ls, VLOCAL <= lh->v.k && lh->v.k <= VINDEXED, + "syntax error"); + if (testnext(ls, ',')) { /* assignment -> `,' primaryexp assignment */ + struct LHS_assign nv; + nv.prev = lh; + primaryexp(ls, &nv.v); + if (nv.v.k == VLOCAL) + check_conflict(ls, lh, &nv.v); + luaY_checklimit(ls->fs, nvars, LUAI_MAXCCALLS - ls->L->nCcalls, + "variables in assignment"); + assignment(ls, &nv, nvars+1); + } + else { /* assignment -> `=' explist1 */ + int nexps; + checknext(ls, '='); + nexps = explist1(ls, &e); + if (nexps != nvars) { + adjust_assign(ls, nvars, nexps, &e); + if (nexps > nvars) + ls->fs->freereg -= nexps - nvars; /* remove extra values */ + } + else { + luaK_setoneret(ls->fs, &e); /* close last expression */ + luaK_storevar(ls->fs, &lh->v, &e); + return; /* avoid default */ + } + } + init_exp(&e, VNONRELOC, ls->fs->freereg-1); /* default assignment */ + luaK_storevar(ls->fs, &lh->v, &e); +} + + +static int cond (LexState *ls) { + /* cond -> exp */ + expdesc v; + expr(ls, &v); /* read condition */ + if (v.k == VNIL) v.k = VFALSE; /* `falses' are all equal here */ + luaK_goiftrue(ls->fs, &v); + return v.f; +} + + +static void breakstat (LexState *ls) { + FuncState *fs = ls->fs; + BlockCnt *bl = fs->bl; + int upval = 0; + while (bl && !bl->isbreakable) { + upval |= bl->upval; + bl = bl->previous; + } + if (!bl) + luaX_syntaxerror(ls, "no loop to break"); + if (upval) + luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0); + luaK_concat(fs, &bl->breaklist, luaK_jump(fs)); +} + + +static void whilestat (LexState *ls, int line) { + /* whilestat -> WHILE cond DO block END */ + FuncState *fs = ls->fs; + int whileinit; + int condexit; + BlockCnt bl; + luaX_next(ls); /* skip WHILE */ + whileinit = luaK_getlabel(fs); + condexit = cond(ls); + enterblock(fs, &bl, 1); + checknext(ls, TK_DO); + block(ls); + luaK_patchlist(fs, luaK_jump(fs), whileinit); + check_match(ls, TK_END, TK_WHILE, line); + leaveblock(fs); + luaK_patchtohere(fs, condexit); /* false conditions finish the loop */ +} + + +static void repeatstat (LexState *ls, int line) { + /* repeatstat -> REPEAT block UNTIL cond */ + int condexit; + FuncState *fs = ls->fs; + int repeat_init = luaK_getlabel(fs); + BlockCnt bl1, bl2; + enterblock(fs, &bl1, 1); /* loop block */ + enterblock(fs, &bl2, 0); /* scope block */ + luaX_next(ls); /* skip REPEAT */ + chunk(ls); + check_match(ls, TK_UNTIL, TK_REPEAT, line); + condexit = cond(ls); /* read condition (inside scope block) */ + if (!bl2.upval) { /* no upvalues? */ + leaveblock(fs); /* finish scope */ + luaK_patchlist(ls->fs, condexit, repeat_init); /* close the loop */ + } + else { /* complete semantics when there are upvalues */ + breakstat(ls); /* if condition then break */ + luaK_patchtohere(ls->fs, condexit); /* else... */ + leaveblock(fs); /* finish scope... */ + luaK_patchlist(ls->fs, luaK_jump(fs), repeat_init); /* and repeat */ + } + leaveblock(fs); /* finish loop */ +} + + +static int exp1 (LexState *ls) { + expdesc e; + int k; + expr(ls, &e); + k = e.k; + luaK_exp2nextreg(ls->fs, &e); + return k; +} + + +static void forbody (LexState *ls, int base, int line, int nvars, int isnum) { + /* forbody -> DO block */ + BlockCnt bl; + FuncState *fs = ls->fs; + int prep, endfor; + adjustlocalvars(ls, 3); /* control variables */ + checknext(ls, TK_DO); + prep = isnum ? luaK_codeAsBx(fs, OP_FORPREP, base, NO_JUMP) : luaK_jump(fs); + enterblock(fs, &bl, 0); /* scope for declared variables */ + adjustlocalvars(ls, nvars); + luaK_reserveregs(fs, nvars); + block(ls); + leaveblock(fs); /* end of scope for declared variables */ + luaK_patchtohere(fs, prep); + endfor = (isnum) ? luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP) : + luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars); + luaK_fixline(fs, line); /* pretend that `OP_FOR' starts the loop */ + luaK_patchlist(fs, (isnum ? endfor : luaK_jump(fs)), prep + 1); +} + + +static void fornum (LexState *ls, TString *varname, int line) { + /* fornum -> NAME = exp1,exp1[,exp1] forbody */ + FuncState *fs = ls->fs; + int base = fs->freereg; + new_localvarliteral(ls, "(for index)", 0); + new_localvarliteral(ls, "(for limit)", 1); + new_localvarliteral(ls, "(for step)", 2); + new_localvar(ls, varname, 3); + checknext(ls, '='); + exp1(ls); /* initial value */ + checknext(ls, ','); + exp1(ls); /* limit */ + if (testnext(ls, ',')) + exp1(ls); /* optional step */ + else { /* default step = 1 */ + luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_numberK(fs, 1)); + luaK_reserveregs(fs, 1); + } + forbody(ls, base, line, 1, 1); +} + + +static void forlist (LexState *ls, TString *indexname) { + /* forlist -> NAME {,NAME} IN explist1 forbody */ + FuncState *fs = ls->fs; + expdesc e; + int nvars = 0; + int line; + int base = fs->freereg; + /* create control variables */ + new_localvarliteral(ls, "(for generator)", nvars++); + new_localvarliteral(ls, "(for state)", nvars++); + new_localvarliteral(ls, "(for control)", nvars++); + /* create declared variables */ + new_localvar(ls, indexname, nvars++); + while (testnext(ls, ',')) + new_localvar(ls, str_checkname(ls), nvars++); + checknext(ls, TK_IN); + line = ls->linenumber; + adjust_assign(ls, 3, explist1(ls, &e), &e); + luaK_checkstack(fs, 3); /* extra space to call generator */ + forbody(ls, base, line, nvars - 3, 0); +} + + +static void forstat (LexState *ls, int line) { + /* forstat -> FOR (fornum | forlist) END */ + FuncState *fs = ls->fs; + TString *varname; + BlockCnt bl; + enterblock(fs, &bl, 1); /* scope for loop and control variables */ + luaX_next(ls); /* skip `for' */ + varname = str_checkname(ls); /* first variable name */ + switch (ls->t.token) { + case '=': fornum(ls, varname, line); break; + case ',': case TK_IN: forlist(ls, varname); break; + default: luaX_syntaxerror(ls, LUA_QL("=") " or " LUA_QL("in") " expected"); + } + check_match(ls, TK_END, TK_FOR, line); + leaveblock(fs); /* loop scope (`break' jumps to this point) */ +} + + +static int test_then_block (LexState *ls) { + /* test_then_block -> [IF | ELSEIF] cond THEN block */ + int condexit; + luaX_next(ls); /* skip IF or ELSEIF */ + condexit = cond(ls); + checknext(ls, TK_THEN); + block(ls); /* `then' part */ + return condexit; +} + + +static void ifstat (LexState *ls, int line) { + /* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */ + FuncState *fs = ls->fs; + int flist; + int escapelist = NO_JUMP; + flist = test_then_block(ls); /* IF cond THEN block */ + while (ls->t.token == TK_ELSEIF) { + luaK_concat(fs, &escapelist, luaK_jump(fs)); + luaK_patchtohere(fs, flist); + flist = test_then_block(ls); /* ELSEIF cond THEN block */ + } + if (ls->t.token == TK_ELSE) { + luaK_concat(fs, &escapelist, luaK_jump(fs)); + luaK_patchtohere(fs, flist); + luaX_next(ls); /* skip ELSE (after patch, for correct line info) */ + block(ls); /* `else' part */ + } + else + luaK_concat(fs, &escapelist, flist); + luaK_patchtohere(fs, escapelist); + check_match(ls, TK_END, TK_IF, line); +} + + +static void localfunc (LexState *ls) { + expdesc v, b; + FuncState *fs = ls->fs; + new_localvar(ls, str_checkname(ls), 0); + init_exp(&v, VLOCAL, fs->freereg); + luaK_reserveregs(fs, 1); + adjustlocalvars(ls, 1); + body(ls, &b, 0, ls->linenumber); + luaK_storevar(fs, &v, &b); + /* debug information will only see the variable after this point! */ + getlocvar(fs, fs->nactvar - 1).startpc = fs->pc; +} + + +static void localstat (LexState *ls) { + /* stat -> LOCAL NAME {`,' NAME} [`=' explist1] */ + int nvars = 0; + int nexps; + expdesc e; + do { + new_localvar(ls, str_checkname(ls), nvars++); + } while (testnext(ls, ',')); + if (testnext(ls, '=')) + nexps = explist1(ls, &e); + else { + e.k = VVOID; + nexps = 0; + } + adjust_assign(ls, nvars, nexps, &e); + adjustlocalvars(ls, nvars); +} + + +static int funcname (LexState *ls, expdesc *v) { + /* funcname -> NAME {field} [`:' NAME] */ + int needself = 0; + singlevar(ls, v); + while (ls->t.token == '.') + field(ls, v); + if (ls->t.token == ':') { + needself = 1; + field(ls, v); + } + return needself; +} + + +static void funcstat (LexState *ls, int line) { + /* funcstat -> FUNCTION funcname body */ + int needself; + expdesc v, b; + luaX_next(ls); /* skip FUNCTION */ + needself = funcname(ls, &v); + body(ls, &b, needself, line); + luaK_storevar(ls->fs, &v, &b); + luaK_fixline(ls->fs, line); /* definition `happens' in the first line */ +} + + +static void exprstat (LexState *ls) { + /* stat -> func | assignment */ + FuncState *fs = ls->fs; + struct LHS_assign v; + primaryexp(ls, &v.v); + if (v.v.k == VCALL) /* stat -> func */ + SETARG_C(getcode(fs, &v.v), 1); /* call statement uses no results */ + else { /* stat -> assignment */ + v.prev = NULL; + assignment(ls, &v, 1); + } +} + + +static void retstat (LexState *ls) { + /* stat -> RETURN explist */ + FuncState *fs = ls->fs; + expdesc e; + int first, nret; /* registers with returned values */ + luaX_next(ls); /* skip RETURN */ + if (block_follow(ls->t.token) || ls->t.token == ';') + first = nret = 0; /* return no values */ + else { + nret = explist1(ls, &e); /* optional return values */ + if (hasmultret(e.k)) { + luaK_setmultret(fs, &e); + if (e.k == VCALL && nret == 1) { /* tail call? */ + SET_OPCODE(getcode(fs,&e), OP_TAILCALL); + lua_assert(GETARG_A(getcode(fs,&e)) == fs->nactvar); + } + first = fs->nactvar; + nret = LUA_MULTRET; /* return all values */ + } + else { + if (nret == 1) /* only one single value? */ + first = luaK_exp2anyreg(fs, &e); + else { + luaK_exp2nextreg(fs, &e); /* values must go to the `stack' */ + first = fs->nactvar; /* return all `active' values */ + lua_assert(nret == fs->freereg - first); + } + } + } + luaK_ret(fs, first, nret); +} + + +static int statement (LexState *ls) { + int line = ls->linenumber; /* may be needed for error messages */ + switch (ls->t.token) { + case TK_IF: { /* stat -> ifstat */ + ifstat(ls, line); + return 0; + } + case TK_WHILE: { /* stat -> whilestat */ + whilestat(ls, line); + return 0; + } + case TK_DO: { /* stat -> DO block END */ + luaX_next(ls); /* skip DO */ + block(ls); + check_match(ls, TK_END, TK_DO, line); + return 0; + } + case TK_FOR: { /* stat -> forstat */ + forstat(ls, line); + return 0; + } + case TK_REPEAT: { /* stat -> repeatstat */ + repeatstat(ls, line); + return 0; + } + case TK_FUNCTION: { + funcstat(ls, line); /* stat -> funcstat */ + return 0; + } + case TK_LOCAL: { /* stat -> localstat */ + luaX_next(ls); /* skip LOCAL */ + if (testnext(ls, TK_FUNCTION)) /* local function? */ + localfunc(ls); + else + localstat(ls); + return 0; + } + case TK_RETURN: { /* stat -> retstat */ + retstat(ls); + return 1; /* must be last statement */ + } + case TK_BREAK: { /* stat -> breakstat */ + luaX_next(ls); /* skip BREAK */ + breakstat(ls); + return 1; /* must be last statement */ + } + default: { + exprstat(ls); + return 0; /* to avoid warnings */ + } + } +} + + +static void chunk (LexState *ls) { + /* chunk -> { stat [`;'] } */ + int islast = 0; + enterlevel(ls); + while (!islast && !block_follow(ls->t.token)) { + islast = statement(ls); + testnext(ls, ';'); + lua_assert(ls->fs->f->maxstacksize >= ls->fs->freereg && + ls->fs->freereg >= ls->fs->nactvar); + ls->fs->freereg = ls->fs->nactvar; /* free registers */ + } + leavelevel(ls); +} + +/* }====================================================================== */ diff --git a/external/mit/lua/dist/src/lparser.h b/external/mit/lua/dist/src/lparser.h new file mode 100644 index 000000000..2a12aaba3 --- /dev/null +++ b/external/mit/lua/dist/src/lparser.h @@ -0,0 +1,84 @@ +/* $NetBSD: lparser.h,v 1.1.1.2 2012/03/15 00:08:10 alnsn Exp $ */ + +/* +** $Id: lparser.h,v 1.1.1.2 2012/03/15 00:08:10 alnsn Exp $ +** Lua Parser +** See Copyright Notice in lua.h +*/ + +#ifndef lparser_h +#define lparser_h + +#include "llimits.h" +#include "lobject.h" +#include "lzio.h" + + +/* +** Expression descriptor +*/ + +typedef enum { + VVOID, /* no value */ + VNIL, + VTRUE, + VFALSE, + VK, /* info = index of constant in `k' */ + VKNUM, /* nval = numerical value */ + VLOCAL, /* info = local register */ + VUPVAL, /* info = index of upvalue in `upvalues' */ + VGLOBAL, /* info = index of table; aux = index of global name in `k' */ + VINDEXED, /* info = table register; aux = index register (or `k') */ + VJMP, /* info = instruction pc */ + VRELOCABLE, /* info = instruction pc */ + VNONRELOC, /* info = result register */ + VCALL, /* info = instruction pc */ + VVARARG /* info = instruction pc */ +} expkind; + +typedef struct expdesc { + expkind k; + union { + struct { int info, aux; } s; + lua_Number nval; + } u; + int t; /* patch list of `exit when true' */ + int f; /* patch list of `exit when false' */ +} expdesc; + + +typedef struct upvaldesc { + lu_byte k; + lu_byte info; +} upvaldesc; + + +struct BlockCnt; /* defined in lparser.c */ + + +/* state needed to generate code for a given function */ +typedef struct FuncState { + Proto *f; /* current function header */ + Table *h; /* table to find (and reuse) elements in `k' */ + struct FuncState *prev; /* enclosing function */ + struct LexState *ls; /* lexical state */ + struct lua_State *L; /* copy of the Lua state */ + struct BlockCnt *bl; /* chain of current blocks */ + int pc; /* next position to code (equivalent to `ncode') */ + int lasttarget; /* `pc' of last `jump target' */ + int jpc; /* list of pending jumps to `pc' */ + int freereg; /* first free register */ + int nk; /* number of elements in `k' */ + int np; /* number of elements in `p' */ + short nlocvars; /* number of elements in `locvars' */ + lu_byte nactvar; /* number of active local variables */ + upvaldesc upvalues[LUAI_MAXUPVALUES]; /* upvalues */ + unsigned short actvar[LUAI_MAXVARS]; /* declared-variable stack */ +} FuncState; + + +LUAI_FUNC Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, + const char *name); + + +#endif diff --git a/external/mit/lua/dist/src/lstate.c b/external/mit/lua/dist/src/lstate.c new file mode 100644 index 000000000..923671f28 --- /dev/null +++ b/external/mit/lua/dist/src/lstate.c @@ -0,0 +1,216 @@ +/* $NetBSD: lstate.c,v 1.1.1.2 2012/03/15 00:08:14 alnsn Exp $ */ + +/* +** $Id: lstate.c,v 1.1.1.2 2012/03/15 00:08:14 alnsn Exp $ +** Global State +** See Copyright Notice in lua.h +*/ + + +#include + +#define lstate_c +#define LUA_CORE + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lgc.h" +#include "llex.h" +#include "lmem.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" + + +#define state_size(x) (sizeof(x) + LUAI_EXTRASPACE) +#define fromstate(l) (cast(lu_byte *, (l)) - LUAI_EXTRASPACE) +#define tostate(l) (cast(lua_State *, cast(lu_byte *, l) + LUAI_EXTRASPACE)) + + +/* +** Main thread combines a thread state and the global state +*/ +typedef struct LG { + lua_State l; + global_State g; +} LG; + + + +static void stack_init (lua_State *L1, lua_State *L) { + /* initialize CallInfo array */ + L1->base_ci = luaM_newvector(L, BASIC_CI_SIZE, CallInfo); + L1->ci = L1->base_ci; + L1->size_ci = BASIC_CI_SIZE; + L1->end_ci = L1->base_ci + L1->size_ci - 1; + /* initialize stack array */ + L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, TValue); + L1->stacksize = BASIC_STACK_SIZE + EXTRA_STACK; + L1->top = L1->stack; + L1->stack_last = L1->stack+(L1->stacksize - EXTRA_STACK)-1; + /* initialize first ci */ + L1->ci->func = L1->top; + setnilvalue(L1->top++); /* `function' entry for this `ci' */ + L1->base = L1->ci->base = L1->top; + L1->ci->top = L1->top + LUA_MINSTACK; +} + + +static void freestack (lua_State *L, lua_State *L1) { + luaM_freearray(L, L1->base_ci, L1->size_ci, CallInfo); + luaM_freearray(L, L1->stack, L1->stacksize, TValue); +} + + +/* +** open parts that may cause memory-allocation errors +*/ +static void f_luaopen (lua_State *L, void *ud) { + global_State *g = G(L); + UNUSED(ud); + stack_init(L, L); /* init stack */ + sethvalue(L, gt(L), luaH_new(L, 0, 2)); /* table of globals */ + sethvalue(L, registry(L), luaH_new(L, 0, 2)); /* registry */ + luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */ + luaT_init(L); + luaX_init(L); + luaS_fix(luaS_newliteral(L, MEMERRMSG)); + g->GCthreshold = 4*g->totalbytes; +} + + +static void preinit_state (lua_State *L, global_State *g) { + G(L) = g; + L->stack = NULL; + L->stacksize = 0; + L->errorJmp = NULL; + L->hook = NULL; + L->hookmask = 0; + L->basehookcount = 0; + L->allowhook = 1; + resethookcount(L); + L->openupval = NULL; + L->size_ci = 0; + L->nCcalls = L->baseCcalls = 0; + L->status = 0; + L->base_ci = L->ci = NULL; + L->savedpc = NULL; + L->errfunc = 0; + setnilvalue(gt(L)); +} + + +static void close_state (lua_State *L) { + global_State *g = G(L); + luaF_close(L, L->stack); /* close all upvalues for this thread */ + luaC_freeall(L); /* collect all objects */ + lua_assert(g->rootgc == obj2gco(L)); + lua_assert(g->strt.nuse == 0); + luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size, TString *); + luaZ_freebuffer(L, &g->buff); + freestack(L, L); + lua_assert(g->totalbytes == sizeof(LG)); + (*g->frealloc)(g->ud, fromstate(L), state_size(LG), 0); +} + + +lua_State *luaE_newthread (lua_State *L) { + lua_State *L1 = tostate(luaM_malloc(L, state_size(lua_State))); + luaC_link(L, obj2gco(L1), LUA_TTHREAD); + preinit_state(L1, G(L)); + stack_init(L1, L); /* init stack */ + setobj2n(L, gt(L1), gt(L)); /* share table of globals */ + L1->hookmask = L->hookmask; + L1->basehookcount = L->basehookcount; + L1->hook = L->hook; + resethookcount(L1); + lua_assert(iswhite(obj2gco(L1))); + return L1; +} + + +void luaE_freethread (lua_State *L, lua_State *L1) { + luaF_close(L1, L1->stack); /* close all upvalues for this thread */ + lua_assert(L1->openupval == NULL); + luai_userstatefree(L1); + freestack(L, L1); + luaM_freemem(L, fromstate(L1), state_size(lua_State)); +} + + +LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { + int i; + lua_State *L; + global_State *g; + void *l = (*f)(ud, NULL, 0, state_size(LG)); + if (l == NULL) return NULL; + L = tostate(l); + g = &((LG *)L)->g; + L->next = NULL; + L->tt = LUA_TTHREAD; + g->currentwhite = bit2mask(WHITE0BIT, FIXEDBIT); + L->marked = luaC_white(g); + set2bits(L->marked, FIXEDBIT, SFIXEDBIT); + preinit_state(L, g); + g->frealloc = f; + g->ud = ud; + g->mainthread = L; + g->uvhead.u.l.prev = &g->uvhead; + g->uvhead.u.l.next = &g->uvhead; + g->GCthreshold = 0; /* mark it as unfinished state */ + g->strt.size = 0; + g->strt.nuse = 0; + g->strt.hash = NULL; + setnilvalue(registry(L)); + luaZ_initbuffer(L, &g->buff); + g->panic = NULL; + g->gcstate = GCSpause; + g->rootgc = obj2gco(L); + g->sweepstrgc = 0; + g->sweepgc = &g->rootgc; + g->gray = NULL; + g->grayagain = NULL; + g->weak = NULL; + g->tmudata = NULL; + g->totalbytes = sizeof(LG); + g->gcpause = LUAI_GCPAUSE; + g->gcstepmul = LUAI_GCMUL; + g->gcdept = 0; + for (i=0; imt[i] = NULL; + if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) { + /* memory allocation error: free partial state */ + close_state(L); + L = NULL; + } + else + luai_userstateopen(L); + return L; +} + + +static void callallgcTM (lua_State *L, void *ud) { + UNUSED(ud); + luaC_callGCTM(L); /* call GC metamethods for all udata */ +} + + +LUA_API void lua_close (lua_State *L) { + L = G(L)->mainthread; /* only the main thread can be closed */ + lua_lock(L); + luaF_close(L, L->stack); /* close all upvalues for this thread */ + luaC_separateudata(L, 1); /* separate udata that have GC metamethods */ + L->errfunc = 0; /* no error function during GC metamethods */ + do { /* repeat until no more errors */ + L->ci = L->base_ci; + L->base = L->top = L->ci->base; + L->nCcalls = L->baseCcalls = 0; + } while (luaD_rawrunprotected(L, callallgcTM, NULL) != 0); + lua_assert(G(L)->tmudata == NULL); + luai_userstateclose(L); + close_state(L); +} + diff --git a/external/mit/lua/dist/src/lstate.h b/external/mit/lua/dist/src/lstate.h new file mode 100644 index 000000000..907af1e60 --- /dev/null +++ b/external/mit/lua/dist/src/lstate.h @@ -0,0 +1,171 @@ +/* $NetBSD: lstate.h,v 1.1.1.2 2012/03/15 00:08:04 alnsn Exp $ */ + +/* +** $Id: lstate.h,v 1.1.1.2 2012/03/15 00:08:04 alnsn Exp $ +** Global State +** See Copyright Notice in lua.h +*/ + +#ifndef lstate_h +#define lstate_h + +#include "lua.h" + +#include "lobject.h" +#include "ltm.h" +#include "lzio.h" + + + +struct lua_longjmp; /* defined in ldo.c */ + + +/* table of globals */ +#define gt(L) (&L->l_gt) + +/* registry */ +#define registry(L) (&G(L)->l_registry) + + +/* extra stack space to handle TM calls and some other extras */ +#define EXTRA_STACK 5 + + +#define BASIC_CI_SIZE 8 + +#define BASIC_STACK_SIZE (2*LUA_MINSTACK) + + + +typedef struct stringtable { + GCObject **hash; + lu_int32 nuse; /* number of elements */ + int size; +} stringtable; + + +/* +** informations about a call +*/ +typedef struct CallInfo { + StkId base; /* base for this function */ + StkId func; /* function index in the stack */ + StkId top; /* top for this function */ + const Instruction *savedpc; + int nresults; /* expected number of results from this function */ + int tailcalls; /* number of tail calls lost under this entry */ +} CallInfo; + + + +#define curr_func(L) (clvalue(L->ci->func)) +#define ci_func(ci) (clvalue((ci)->func)) +#define f_isLua(ci) (!ci_func(ci)->c.isC) +#define isLua(ci) (ttisfunction((ci)->func) && f_isLua(ci)) + + +/* +** `global state', shared by all threads of this state +*/ +typedef struct global_State { + stringtable strt; /* hash table for strings */ + lua_Alloc frealloc; /* function to reallocate memory */ + void *ud; /* auxiliary data to `frealloc' */ + lu_byte currentwhite; + lu_byte gcstate; /* state of garbage collector */ + int sweepstrgc; /* position of sweep in `strt' */ + GCObject *rootgc; /* list of all collectable objects */ + GCObject **sweepgc; /* position of sweep in `rootgc' */ + GCObject *gray; /* list of gray objects */ + GCObject *grayagain; /* list of objects to be traversed atomically */ + GCObject *weak; /* list of weak tables (to be cleared) */ + GCObject *tmudata; /* last element of list of userdata to be GC */ + Mbuffer buff; /* temporary buffer for string concatentation */ + lu_mem GCthreshold; + lu_mem totalbytes; /* number of bytes currently allocated */ + lu_mem estimate; /* an estimate of number of bytes actually in use */ + lu_mem gcdept; /* how much GC is `behind schedule' */ + int gcpause; /* size of pause between successive GCs */ + int gcstepmul; /* GC `granularity' */ + lua_CFunction panic; /* to be called in unprotected errors */ + TValue l_registry; + struct lua_State *mainthread; + UpVal uvhead; /* head of double-linked list of all open upvalues */ + struct Table *mt[NUM_TAGS]; /* metatables for basic types */ + TString *tmname[TM_N]; /* array with tag-method names */ +} global_State; + + +/* +** `per thread' state +*/ +struct lua_State { + CommonHeader; + lu_byte status; + StkId top; /* first free slot in the stack */ + StkId base; /* base of current function */ + global_State *l_G; + CallInfo *ci; /* call info for current function */ + const Instruction *savedpc; /* `savedpc' of current function */ + StkId stack_last; /* last free slot in the stack */ + StkId stack; /* stack base */ + CallInfo *end_ci; /* points after end of ci array*/ + CallInfo *base_ci; /* array of CallInfo's */ + int stacksize; + int size_ci; /* size of array `base_ci' */ + unsigned short nCcalls; /* number of nested C calls */ + unsigned short baseCcalls; /* nested C calls when resuming coroutine */ + lu_byte hookmask; + lu_byte allowhook; + int basehookcount; + int hookcount; + lua_Hook hook; + TValue l_gt; /* table of globals */ + TValue env; /* temporary place for environments */ + GCObject *openupval; /* list of open upvalues in this stack */ + GCObject *gclist; + struct lua_longjmp *errorJmp; /* current error recover point */ + ptrdiff_t errfunc; /* current error handling function (stack index) */ +}; + + +#define G(L) (L->l_G) + + +/* +** Union of all collectable objects +*/ +union GCObject { + GCheader gch; + union TString ts; + union Udata u; + union Closure cl; + struct Table h; + struct Proto p; + struct UpVal uv; + struct lua_State th; /* thread */ +}; + + +/* macros to convert a GCObject into a specific value */ +#define rawgco2ts(o) check_exp((o)->gch.tt == LUA_TSTRING, &((o)->ts)) +#define gco2ts(o) (&rawgco2ts(o)->tsv) +#define rawgco2u(o) check_exp((o)->gch.tt == LUA_TUSERDATA, &((o)->u)) +#define gco2u(o) (&rawgco2u(o)->uv) +#define gco2cl(o) check_exp((o)->gch.tt == LUA_TFUNCTION, &((o)->cl)) +#define gco2h(o) check_exp((o)->gch.tt == LUA_TTABLE, &((o)->h)) +#define gco2p(o) check_exp((o)->gch.tt == LUA_TPROTO, &((o)->p)) +#define gco2uv(o) check_exp((o)->gch.tt == LUA_TUPVAL, &((o)->uv)) +#define ngcotouv(o) \ + check_exp((o) == NULL || (o)->gch.tt == LUA_TUPVAL, &((o)->uv)) +#define gco2th(o) check_exp((o)->gch.tt == LUA_TTHREAD, &((o)->th)) + +/* macro to convert any Lua object into a GCObject */ +#define obj2gco(v) (cast(GCObject *, (v))) + + +LUAI_FUNC lua_State *luaE_newthread (lua_State *L); +LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1); + +#endif + diff --git a/external/mit/lua/dist/src/lstring.c b/external/mit/lua/dist/src/lstring.c new file mode 100644 index 000000000..07350b78f --- /dev/null +++ b/external/mit/lua/dist/src/lstring.c @@ -0,0 +1,113 @@ +/* $NetBSD: lstring.c,v 1.1.1.2 2012/03/15 00:08:08 alnsn Exp $ */ + +/* +** $Id: lstring.c,v 1.1.1.2 2012/03/15 00:08:08 alnsn Exp $ +** String table (keeps all strings handled by Lua) +** See Copyright Notice in lua.h +*/ + + +#include + +#define lstring_c +#define LUA_CORE + +#include "lua.h" + +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" + + + +void luaS_resize (lua_State *L, int newsize) { + GCObject **newhash; + stringtable *tb; + int i; + if (G(L)->gcstate == GCSsweepstring) + return; /* cannot resize during GC traverse */ + newhash = luaM_newvector(L, newsize, GCObject *); + tb = &G(L)->strt; + for (i=0; isize; i++) { + GCObject *p = tb->hash[i]; + while (p) { /* for each node in the list */ + GCObject *next = p->gch.next; /* save next */ + unsigned int h = gco2ts(p)->hash; + int h1 = lmod(h, newsize); /* new position */ + lua_assert(cast_int(h%newsize) == lmod(h, newsize)); + p->gch.next = newhash[h1]; /* chain it */ + newhash[h1] = p; + p = next; + } + } + luaM_freearray(L, tb->hash, tb->size, TString *); + tb->size = newsize; + tb->hash = newhash; +} + + +static TString *newlstr (lua_State *L, const char *str, size_t l, + unsigned int h) { + TString *ts; + stringtable *tb; + if (l+1 > (MAX_SIZET - sizeof(TString))/sizeof(char)) + luaM_toobig(L); + ts = cast(TString *, luaM_malloc(L, (l+1)*sizeof(char)+sizeof(TString))); + ts->tsv.len = l; + ts->tsv.hash = h; + ts->tsv.marked = luaC_white(G(L)); + ts->tsv.tt = LUA_TSTRING; + ts->tsv.reserved = 0; + memcpy(ts+1, str, l*sizeof(char)); + ((char *)(ts+1))[l] = '\0'; /* ending 0 */ + tb = &G(L)->strt; + h = lmod(h, tb->size); + ts->tsv.next = tb->hash[h]; /* chain new entry */ + tb->hash[h] = obj2gco(ts); + tb->nuse++; + if (tb->nuse > cast(lu_int32, tb->size) && tb->size <= MAX_INT/2) + luaS_resize(L, tb->size*2); /* too crowded */ + return ts; +} + + +TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { + GCObject *o; + unsigned int h = cast(unsigned int, l); /* seed */ + size_t step = (l>>5)+1; /* if string is too long, don't hash all its chars */ + size_t l1; + for (l1=l; l1>=step; l1-=step) /* compute hash */ + h = h ^ ((h<<5)+(h>>2)+cast(unsigned char, str[l1-1])); + for (o = G(L)->strt.hash[lmod(h, G(L)->strt.size)]; + o != NULL; + o = o->gch.next) { + TString *ts = rawgco2ts(o); + if (ts->tsv.len == l && (memcmp(str, getstr(ts), l) == 0)) { + /* string may be dead */ + if (isdead(G(L), o)) changewhite(o); + return ts; + } + } + return newlstr(L, str, l, h); /* not found */ +} + + +Udata *luaS_newudata (lua_State *L, size_t s, Table *e) { + Udata *u; + if (s > MAX_SIZET - sizeof(Udata)) + luaM_toobig(L); + u = cast(Udata *, luaM_malloc(L, s + sizeof(Udata))); + u->uv.marked = luaC_white(G(L)); /* is not finalized */ + u->uv.tt = LUA_TUSERDATA; + u->uv.len = s; + u->uv.metatable = NULL; + u->uv.env = e; + /* chain it on udata list (after main thread) */ + u->uv.next = G(L)->mainthread->next; + G(L)->mainthread->next = obj2gco(u); + return u; +} + diff --git a/external/mit/lua/dist/src/lstring.h b/external/mit/lua/dist/src/lstring.h new file mode 100644 index 000000000..5b8092d28 --- /dev/null +++ b/external/mit/lua/dist/src/lstring.h @@ -0,0 +1,33 @@ +/* $NetBSD: lstring.h,v 1.1.1.2 2012/03/15 00:08:04 alnsn Exp $ */ + +/* +** $Id: lstring.h,v 1.1.1.2 2012/03/15 00:08:04 alnsn Exp $ +** String table (keep all strings handled by Lua) +** See Copyright Notice in lua.h +*/ + +#ifndef lstring_h +#define lstring_h + + +#include "lgc.h" +#include "lobject.h" +#include "lstate.h" + + +#define sizestring(s) (sizeof(union TString)+((s)->len+1)*sizeof(char)) + +#define sizeudata(u) (sizeof(union Udata)+(u)->len) + +#define luaS_new(L, s) (luaS_newlstr(L, s, strlen(s))) +#define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \ + (sizeof(s)/sizeof(char))-1)) + +#define luaS_fix(s) l_setbit((s)->tsv.marked, FIXEDBIT) + +LUAI_FUNC void luaS_resize (lua_State *L, int newsize); +LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, Table *e); +LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l); + + +#endif diff --git a/external/mit/lua/dist/src/lstrlib.c b/external/mit/lua/dist/src/lstrlib.c new file mode 100644 index 000000000..ce4e586c8 --- /dev/null +++ b/external/mit/lua/dist/src/lstrlib.c @@ -0,0 +1,873 @@ +/* $NetBSD: lstrlib.c,v 1.1.1.2 2012/03/15 00:08:12 alnsn Exp $ */ + +/* +** $Id: lstrlib.c,v 1.1.1.2 2012/03/15 00:08:12 alnsn Exp $ +** Standard library for string operations and pattern-matching +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include +#include +#include + +#define lstrlib_c +#define LUA_LIB + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +/* macro to `unsign' a character */ +#define uchar(c) ((unsigned char)(c)) + + + +static int str_len (lua_State *L) { + size_t l; + luaL_checklstring(L, 1, &l); + lua_pushinteger(L, l); + return 1; +} + + +static ptrdiff_t posrelat (ptrdiff_t pos, size_t len) { + /* relative string position: negative means back from end */ + if (pos < 0) pos += (ptrdiff_t)len + 1; + return (pos >= 0) ? pos : 0; +} + + +static int str_sub (lua_State *L) { + size_t l; + const char *s = luaL_checklstring(L, 1, &l); + ptrdiff_t start = posrelat(luaL_checkinteger(L, 2), l); + ptrdiff_t end = posrelat(luaL_optinteger(L, 3, -1), l); + if (start < 1) start = 1; + if (end > (ptrdiff_t)l) end = (ptrdiff_t)l; + if (start <= end) + lua_pushlstring(L, s+start-1, end-start+1); + else lua_pushliteral(L, ""); + return 1; +} + + +static int str_reverse (lua_State *L) { + size_t l; + luaL_Buffer b; + const char *s = luaL_checklstring(L, 1, &l); + luaL_buffinit(L, &b); + while (l--) luaL_addchar(&b, s[l]); + luaL_pushresult(&b); + return 1; +} + + +static int str_lower (lua_State *L) { + size_t l; + size_t i; + luaL_Buffer b; + const char *s = luaL_checklstring(L, 1, &l); + luaL_buffinit(L, &b); + for (i=0; i 0) + luaL_addlstring(&b, s, l); + luaL_pushresult(&b); + return 1; +} + + +static int str_byte (lua_State *L) { + size_t l; + const char *s = luaL_checklstring(L, 1, &l); + ptrdiff_t posi = posrelat(luaL_optinteger(L, 2, 1), l); + ptrdiff_t pose = posrelat(luaL_optinteger(L, 3, posi), l); + int n, i; + if (posi <= 0) posi = 1; + if ((size_t)pose > l) pose = l; + if (posi > pose) return 0; /* empty interval; return no values */ + n = (int)(pose - posi + 1); + if (posi + n <= pose) /* overflow? */ + luaL_error(L, "string slice too long"); + luaL_checkstack(L, n, "string slice too long"); + for (i=0; i= ms->level || ms->capture[l].len == CAP_UNFINISHED) + return luaL_error(ms->L, "invalid capture index"); + return l; +} + + +static int capture_to_close (MatchState *ms) { + int level = ms->level; + for (level--; level>=0; level--) + if (ms->capture[level].len == CAP_UNFINISHED) return level; + return luaL_error(ms->L, "invalid pattern capture"); +} + + +static const char *classend (MatchState *ms, const char *p) { + switch (*p++) { + case L_ESC: { + if (*p == '\0') + luaL_error(ms->L, "malformed pattern (ends with " LUA_QL("%%") ")"); + return p+1; + } + case '[': { + if (*p == '^') p++; + do { /* look for a `]' */ + if (*p == '\0') + luaL_error(ms->L, "malformed pattern (missing " LUA_QL("]") ")"); + if (*(p++) == L_ESC && *p != '\0') + p++; /* skip escapes (e.g. `%]') */ + } while (*p != ']'); + return p+1; + } + default: { + return p; + } + } +} + + +static int match_class (int c, int cl) { + int res; + switch (tolower(cl)) { + case 'a' : res = isalpha(c); break; + case 'c' : res = iscntrl(c); break; + case 'd' : res = isdigit(c); break; + case 'l' : res = islower(c); break; + case 'p' : res = ispunct(c); break; + case 's' : res = isspace(c); break; + case 'u' : res = isupper(c); break; + case 'w' : res = isalnum(c); break; + case 'x' : res = isxdigit(c); break; + case 'z' : res = (c == 0); break; + default: return (cl == c); + } + return (islower(cl) ? res : !res); +} + + +static int matchbracketclass (int c, const char *p, const char *ec) { + int sig = 1; + if (*(p+1) == '^') { + sig = 0; + p++; /* skip the `^' */ + } + while (++p < ec) { + if (*p == L_ESC) { + p++; + if (match_class(c, uchar(*p))) + return sig; + } + else if ((*(p+1) == '-') && (p+2 < ec)) { + p+=2; + if (uchar(*(p-2)) <= c && c <= uchar(*p)) + return sig; + } + else if (uchar(*p) == c) return sig; + } + return !sig; +} + + +static int singlematch (int c, const char *p, const char *ep) { + switch (*p) { + case '.': return 1; /* matches any char */ + case L_ESC: return match_class(c, uchar(*(p+1))); + case '[': return matchbracketclass(c, p, ep-1); + default: return (uchar(*p) == c); + } +} + + +static const char *match (MatchState *ms, const char *s, const char *p); + + +static const char *matchbalance (MatchState *ms, const char *s, + const char *p) { + if (*p == 0 || *(p+1) == 0) + luaL_error(ms->L, "unbalanced pattern"); + if (*s != *p) return NULL; + else { + int b = *p; + int e = *(p+1); + int cont = 1; + while (++s < ms->src_end) { + if (*s == e) { + if (--cont == 0) return s+1; + } + else if (*s == b) cont++; + } + } + return NULL; /* string ends out of balance */ +} + + +static const char *max_expand (MatchState *ms, const char *s, + const char *p, const char *ep) { + ptrdiff_t i = 0; /* counts maximum expand for item */ + while ((s+i)src_end && singlematch(uchar(*(s+i)), p, ep)) + i++; + /* keeps trying to match with the maximum repetitions */ + while (i>=0) { + const char *res = match(ms, (s+i), ep+1); + if (res) return res; + i--; /* else didn't match; reduce 1 repetition to try again */ + } + return NULL; +} + + +static const char *min_expand (MatchState *ms, const char *s, + const char *p, const char *ep) { + for (;;) { + const char *res = match(ms, s, ep+1); + if (res != NULL) + return res; + else if (ssrc_end && singlematch(uchar(*s), p, ep)) + s++; /* try with one more repetition */ + else return NULL; + } +} + + +static const char *start_capture (MatchState *ms, const char *s, + const char *p, int what) { + const char *res; + int level = ms->level; + if (level >= LUA_MAXCAPTURES) luaL_error(ms->L, "too many captures"); + ms->capture[level].init = s; + ms->capture[level].len = what; + ms->level = level+1; + if ((res=match(ms, s, p)) == NULL) /* match failed? */ + ms->level--; /* undo capture */ + return res; +} + + +static const char *end_capture (MatchState *ms, const char *s, + const char *p) { + int l = capture_to_close(ms); + const char *res; + ms->capture[l].len = s - ms->capture[l].init; /* close capture */ + if ((res = match(ms, s, p)) == NULL) /* match failed? */ + ms->capture[l].len = CAP_UNFINISHED; /* undo capture */ + return res; +} + + +static const char *match_capture (MatchState *ms, const char *s, int l) { + size_t len; + l = check_capture(ms, l); + len = ms->capture[l].len; + if ((size_t)(ms->src_end-s) >= len && + memcmp(ms->capture[l].init, s, len) == 0) + return s+len; + else return NULL; +} + + +static const char *match (MatchState *ms, const char *s, const char *p) { + init: /* using goto's to optimize tail recursion */ + switch (*p) { + case '(': { /* start capture */ + if (*(p+1) == ')') /* position capture? */ + return start_capture(ms, s, p+2, CAP_POSITION); + else + return start_capture(ms, s, p+1, CAP_UNFINISHED); + } + case ')': { /* end capture */ + return end_capture(ms, s, p+1); + } + case L_ESC: { + switch (*(p+1)) { + case 'b': { /* balanced string? */ + s = matchbalance(ms, s, p+2); + if (s == NULL) return NULL; + p+=4; goto init; /* else return match(ms, s, p+4); */ + } + case 'f': { /* frontier? */ + const char *ep; char previous; + p += 2; + if (*p != '[') + luaL_error(ms->L, "missing " LUA_QL("[") " after " + LUA_QL("%%f") " in pattern"); + ep = classend(ms, p); /* points to what is next */ + previous = (s == ms->src_init) ? '\0' : *(s-1); + if (matchbracketclass(uchar(previous), p, ep-1) || + !matchbracketclass(uchar(*s), p, ep-1)) return NULL; + p=ep; goto init; /* else return match(ms, s, ep); */ + } + default: { + if (isdigit(uchar(*(p+1)))) { /* capture results (%0-%9)? */ + s = match_capture(ms, s, uchar(*(p+1))); + if (s == NULL) return NULL; + p+=2; goto init; /* else return match(ms, s, p+2) */ + } + goto dflt; /* case default */ + } + } + } + case '\0': { /* end of pattern */ + return s; /* match succeeded */ + } + case '$': { + if (*(p+1) == '\0') /* is the `$' the last char in pattern? */ + return (s == ms->src_end) ? s : NULL; /* check end of string */ + else goto dflt; + } + default: dflt: { /* it is a pattern item */ + const char *ep = classend(ms, p); /* points to what is next */ + int m = ssrc_end && singlematch(uchar(*s), p, ep); + switch (*ep) { + case '?': { /* optional */ + const char *res; + if (m && ((res=match(ms, s+1, ep+1)) != NULL)) + return res; + p=ep+1; goto init; /* else return match(ms, s, ep+1); */ + } + case '*': { /* 0 or more repetitions */ + return max_expand(ms, s, p, ep); + } + case '+': { /* 1 or more repetitions */ + return (m ? max_expand(ms, s+1, p, ep) : NULL); + } + case '-': { /* 0 or more repetitions (minimum) */ + return min_expand(ms, s, p, ep); + } + default: { + if (!m) return NULL; + s++; p=ep; goto init; /* else return match(ms, s+1, ep); */ + } + } + } + } +} + + + +static const char *lmemfind (const char *s1, size_t l1, + const char *s2, size_t l2) { + if (l2 == 0) return s1; /* empty strings are everywhere */ + else if (l2 > l1) return NULL; /* avoids a negative `l1' */ + else { + const char *init; /* to search for a `*s2' inside `s1' */ + l2--; /* 1st char will be checked by `memchr' */ + l1 = l1-l2; /* `s2' cannot be found after that */ + while (l1 > 0 && (init = (const char *)memchr(s1, *s2, l1)) != NULL) { + init++; /* 1st char is already checked */ + if (memcmp(init, s2+1, l2) == 0) + return init-1; + else { /* correct `l1' and `s1' to try again */ + l1 -= init-s1; + s1 = init; + } + } + return NULL; /* not found */ + } +} + + +static void push_onecapture (MatchState *ms, int i, const char *s, + const char *e) { + if (i >= ms->level) { + if (i == 0) /* ms->level == 0, too */ + lua_pushlstring(ms->L, s, e - s); /* add whole match */ + else + luaL_error(ms->L, "invalid capture index"); + } + else { + ptrdiff_t l = ms->capture[i].len; + if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture"); + if (l == CAP_POSITION) + lua_pushinteger(ms->L, ms->capture[i].init - ms->src_init + 1); + else + lua_pushlstring(ms->L, ms->capture[i].init, l); + } +} + + +static int push_captures (MatchState *ms, const char *s, const char *e) { + int i; + int nlevels = (ms->level == 0 && s) ? 1 : ms->level; + luaL_checkstack(ms->L, nlevels, "too many captures"); + for (i = 0; i < nlevels; i++) + push_onecapture(ms, i, s, e); + return nlevels; /* number of strings pushed */ +} + + +static int str_find_aux (lua_State *L, int find) { + size_t l1, l2; + const char *s = luaL_checklstring(L, 1, &l1); + const char *p = luaL_checklstring(L, 2, &l2); + ptrdiff_t init = posrelat(luaL_optinteger(L, 3, 1), l1) - 1; + if (init < 0) init = 0; + else if ((size_t)(init) > l1) init = (ptrdiff_t)l1; + if (find && (lua_toboolean(L, 4) || /* explicit request? */ + strpbrk(p, SPECIALS) == NULL)) { /* or no special characters? */ + /* do a plain search */ + const char *s2 = lmemfind(s+init, l1-init, p, l2); + if (s2) { + lua_pushinteger(L, s2-s+1); + lua_pushinteger(L, s2-s+l2); + return 2; + } + } + else { + MatchState ms; + int anchor = (*p == '^') ? (p++, 1) : 0; + const char *s1=s+init; + ms.L = L; + ms.src_init = s; + ms.src_end = s+l1; + do { + const char *res; + ms.level = 0; + if ((res=match(&ms, s1, p)) != NULL) { + if (find) { + lua_pushinteger(L, s1-s+1); /* start */ + lua_pushinteger(L, res-s); /* end */ + return push_captures(&ms, NULL, 0) + 2; + } + else + return push_captures(&ms, s1, res); + } + } while (s1++ < ms.src_end && !anchor); + } + lua_pushnil(L); /* not found */ + return 1; +} + + +static int str_find (lua_State *L) { + return str_find_aux(L, 1); +} + + +static int str_match (lua_State *L) { + return str_find_aux(L, 0); +} + + +static int gmatch_aux (lua_State *L) { + MatchState ms; + size_t ls; + const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls); + const char *p = lua_tostring(L, lua_upvalueindex(2)); + const char *src; + ms.L = L; + ms.src_init = s; + ms.src_end = s+ls; + for (src = s + (size_t)lua_tointeger(L, lua_upvalueindex(3)); + src <= ms.src_end; + src++) { + const char *e; + ms.level = 0; + if ((e = match(&ms, src, p)) != NULL) { + lua_Integer newstart = e-s; + if (e == src) newstart++; /* empty match? go at least one position */ + lua_pushinteger(L, newstart); + lua_replace(L, lua_upvalueindex(3)); + return push_captures(&ms, src, e); + } + } + return 0; /* not found */ +} + + +static int gmatch (lua_State *L) { + luaL_checkstring(L, 1); + luaL_checkstring(L, 2); + lua_settop(L, 2); + lua_pushinteger(L, 0); + lua_pushcclosure(L, gmatch_aux, 3); + return 1; +} + + +static int gfind_nodef (lua_State *L) { + return luaL_error(L, LUA_QL("string.gfind") " was renamed to " + LUA_QL("string.gmatch")); +} + + +static void add_s (MatchState *ms, luaL_Buffer *b, const char *s, + const char *e) { + size_t l, i; + const char *news = lua_tolstring(ms->L, 3, &l); + for (i = 0; i < l; i++) { + if (news[i] != L_ESC) + luaL_addchar(b, news[i]); + else { + i++; /* skip ESC */ + if (!isdigit(uchar(news[i]))) + luaL_addchar(b, news[i]); + else if (news[i] == '0') + luaL_addlstring(b, s, e - s); + else { + push_onecapture(ms, news[i] - '1', s, e); + luaL_addvalue(b); /* add capture to accumulated result */ + } + } + } +} + + +static void add_value (MatchState *ms, luaL_Buffer *b, const char *s, + const char *e) { + lua_State *L = ms->L; + switch (lua_type(L, 3)) { + case LUA_TNUMBER: + case LUA_TSTRING: { + add_s(ms, b, s, e); + return; + } + case LUA_TFUNCTION: { + int n; + lua_pushvalue(L, 3); + n = push_captures(ms, s, e); + lua_call(L, n, 1); + break; + } + case LUA_TTABLE: { + push_onecapture(ms, 0, s, e); + lua_gettable(L, 3); + break; + } + } + if (!lua_toboolean(L, -1)) { /* nil or false? */ + lua_pop(L, 1); + lua_pushlstring(L, s, e - s); /* keep original text */ + } + else if (!lua_isstring(L, -1)) + luaL_error(L, "invalid replacement value (a %s)", luaL_typename(L, -1)); + luaL_addvalue(b); /* add result to accumulator */ +} + + +static int str_gsub (lua_State *L) { + size_t srcl; + const char *src = luaL_checklstring(L, 1, &srcl); + const char *p = luaL_checkstring(L, 2); + int tr = lua_type(L, 3); + int max_s = luaL_optint(L, 4, srcl+1); + int anchor = (*p == '^') ? (p++, 1) : 0; + int n = 0; + MatchState ms; + luaL_Buffer b; + luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING || + tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3, + "string/function/table expected"); + luaL_buffinit(L, &b); + ms.L = L; + ms.src_init = src; + ms.src_end = src+srcl; + while (n < max_s) { + const char *e; + ms.level = 0; + e = match(&ms, src, p); + if (e) { + n++; + add_value(&ms, &b, src, e); + } + if (e && e>src) /* non empty match? */ + src = e; /* skip it */ + else if (src < ms.src_end) + luaL_addchar(&b, *src++); + else break; + if (anchor) break; + } + luaL_addlstring(&b, src, ms.src_end-src); + luaL_pushresult(&b); + lua_pushinteger(L, n); /* number of substitutions */ + return 2; +} + +/* }====================================================== */ + + +/* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */ +#define MAX_ITEM 512 +/* valid flags in a format specification */ +#define FLAGS "-+ #0" +/* +** maximum size of each format specification (such as '%-099.99d') +** (+10 accounts for %99.99x plus margin of error) +*/ +#define MAX_FORMAT (sizeof(FLAGS) + sizeof(LUA_INTFRMLEN) + 10) + + +static void addquoted (lua_State *L, luaL_Buffer *b, int arg) { + size_t l; + const char *s = luaL_checklstring(L, arg, &l); + luaL_addchar(b, '"'); + while (l--) { + switch (*s) { + case '"': case '\\': case '\n': { + luaL_addchar(b, '\\'); + luaL_addchar(b, *s); + break; + } + case '\r': { + luaL_addlstring(b, "\\r", 2); + break; + } + case '\0': { + luaL_addlstring(b, "\\000", 4); + break; + } + default: { + luaL_addchar(b, *s); + break; + } + } + s++; + } + luaL_addchar(b, '"'); +} + +static const char *scanformat (lua_State *L, const char *strfrmt, char *form) { + const char *p = strfrmt; + while (*p != '\0' && strchr(FLAGS, *p) != NULL) p++; /* skip flags */ + if ((size_t)(p - strfrmt) >= sizeof(FLAGS)) + luaL_error(L, "invalid format (repeated flags)"); + if (isdigit(uchar(*p))) p++; /* skip width */ + if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ + if (*p == '.') { + p++; + if (isdigit(uchar(*p))) p++; /* skip precision */ + if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ + } + if (isdigit(uchar(*p))) + luaL_error(L, "invalid format (width or precision too long)"); + *(form++) = '%'; + strncpy(form, strfrmt, p - strfrmt + 1); + form += p - strfrmt + 1; + *form = '\0'; + return p; +} + + +static void addintlen (char *form) { + size_t l = strlen(form); + char spec = form[l - 1]; + strcpy(form + l - 1, LUA_INTFRMLEN); + form[l + sizeof(LUA_INTFRMLEN) - 2] = spec; + form[l + sizeof(LUA_INTFRMLEN) - 1] = '\0'; +} + + +static int str_format (lua_State *L) { + int top = lua_gettop(L); + int arg = 1; + size_t sfl; + const char *strfrmt = luaL_checklstring(L, arg, &sfl); + const char *strfrmt_end = strfrmt+sfl; + luaL_Buffer b; + luaL_buffinit(L, &b); + while (strfrmt < strfrmt_end) { + if (*strfrmt != L_ESC) + luaL_addchar(&b, *strfrmt++); + else if (*++strfrmt == L_ESC) + luaL_addchar(&b, *strfrmt++); /* %% */ + else { /* format item */ + char form[MAX_FORMAT]; /* to store the format (`%...') */ + char buff[MAX_ITEM]; /* to store the formatted item */ + if (++arg > top) + luaL_argerror(L, arg, "no value"); + strfrmt = scanformat(L, strfrmt, form); + switch (*strfrmt++) { + case 'c': { + sprintf(buff, form, (int)luaL_checknumber(L, arg)); + break; + } + case 'd': case 'i': { + addintlen(form); + sprintf(buff, form, (LUA_INTFRM_T)luaL_checknumber(L, arg)); + break; + } + case 'o': case 'u': case 'x': case 'X': { + addintlen(form); + sprintf(buff, form, (unsigned LUA_INTFRM_T)luaL_checknumber(L, arg)); + break; + } + case 'e': case 'E': case 'f': + case 'g': case 'G': { + sprintf(buff, form, (double)luaL_checknumber(L, arg)); + break; + } + case 'q': { + addquoted(L, &b, arg); + continue; /* skip the 'addsize' at the end */ + } + case 's': { + size_t l; + const char *s = luaL_checklstring(L, arg, &l); + if (!strchr(form, '.') && l >= 100) { + /* no precision and string is too long to be formatted; + keep original string */ + lua_pushvalue(L, arg); + luaL_addvalue(&b); + continue; /* skip the `addsize' at the end */ + } + else { + sprintf(buff, form, s); + break; + } + } + default: { /* also treat cases `pnLlh' */ + return luaL_error(L, "invalid option " LUA_QL("%%%c") " to " + LUA_QL("format"), *(strfrmt - 1)); + } + } + luaL_addlstring(&b, buff, strlen(buff)); + } + } + luaL_pushresult(&b); + return 1; +} + + +static const luaL_Reg strlib[] = { + {"byte", str_byte}, + {"char", str_char}, + {"dump", str_dump}, + {"find", str_find}, + {"format", str_format}, + {"gfind", gfind_nodef}, + {"gmatch", gmatch}, + {"gsub", str_gsub}, + {"len", str_len}, + {"lower", str_lower}, + {"match", str_match}, + {"rep", str_rep}, + {"reverse", str_reverse}, + {"sub", str_sub}, + {"upper", str_upper}, + {NULL, NULL} +}; + + +static void createmetatable (lua_State *L) { + lua_createtable(L, 0, 1); /* create metatable for strings */ + lua_pushliteral(L, ""); /* dummy string */ + lua_pushvalue(L, -2); + lua_setmetatable(L, -2); /* set string metatable */ + lua_pop(L, 1); /* pop dummy string */ + lua_pushvalue(L, -2); /* string library... */ + lua_setfield(L, -2, "__index"); /* ...is the __index metamethod */ + lua_pop(L, 1); /* pop metatable */ +} + + +/* +** Open string library +*/ +LUALIB_API int luaopen_string (lua_State *L) { + luaL_register(L, LUA_STRLIBNAME, strlib); +#if defined(LUA_COMPAT_GFIND) + lua_getfield(L, -1, "gmatch"); + lua_setfield(L, -2, "gfind"); +#endif + createmetatable(L); + return 1; +} + diff --git a/external/mit/lua/dist/src/ltable.c b/external/mit/lua/dist/src/ltable.c new file mode 100644 index 000000000..659eb8988 --- /dev/null +++ b/external/mit/lua/dist/src/ltable.c @@ -0,0 +1,590 @@ +/* $NetBSD: ltable.c,v 1.1.1.2 2012/03/15 00:08:08 alnsn Exp $ */ + +/* +** $Id: ltable.c,v 1.1.1.2 2012/03/15 00:08:08 alnsn Exp $ +** Lua tables (hash) +** See Copyright Notice in lua.h +*/ + + +/* +** Implementation of tables (aka arrays, objects, or hash tables). +** Tables keep its elements in two parts: an array part and a hash part. +** Non-negative integer keys are all candidates to be kept in the array +** part. The actual size of the array is the largest `n' such that at +** least half the slots between 0 and n are in use. +** Hash uses a mix of chained scatter table with Brent's variation. +** A main invariant of these tables is that, if an element is not +** in its main position (i.e. the `original' position that its hash gives +** to it), then the colliding element is in its own main position. +** Hence even when the load factor reaches 100%, performance remains good. +*/ + +#include +#include + +#define ltable_c +#define LUA_CORE + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lgc.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" +#include "ltable.h" + + +/* +** max size of array part is 2^MAXBITS +*/ +#if LUAI_BITSINT > 26 +#define MAXBITS 26 +#else +#define MAXBITS (LUAI_BITSINT-2) +#endif + +#define MAXASIZE (1 << MAXBITS) + + +#define hashpow2(t,n) (gnode(t, lmod((n), sizenode(t)))) + +#define hashstr(t,str) hashpow2(t, (str)->tsv.hash) +#define hashboolean(t,p) hashpow2(t, p) + + +/* +** for some types, it is better to avoid modulus by power of 2, as +** they tend to have many 2 factors. +*/ +#define hashmod(t,n) (gnode(t, ((n) % ((sizenode(t)-1)|1)))) + + +#define hashpointer(t,p) hashmod(t, IntPoint(p)) + + +/* +** number of ints inside a lua_Number +*/ +#define numints cast_int(sizeof(lua_Number)/sizeof(int)) + + + +#define dummynode (&dummynode_) + +static const Node dummynode_ = { + {{NULL}, LUA_TNIL}, /* value */ + {{{NULL}, LUA_TNIL, NULL}} /* key */ +}; + + +/* +** hash for lua_Numbers +*/ +static Node *hashnum (const Table *t, lua_Number n) { + unsigned int a[numints]; + int i; + if (luai_numeq(n, 0)) /* avoid problems with -0 */ + return gnode(t, 0); + memcpy(a, &n, sizeof(a)); + for (i = 1; i < numints; i++) a[0] += a[i]; + return hashmod(t, a[0]); +} + + + +/* +** returns the `main' position of an element in a table (that is, the index +** of its hash value) +*/ +static Node *mainposition (const Table *t, const TValue *key) { + switch (ttype(key)) { + case LUA_TNUMBER: + return hashnum(t, nvalue(key)); + case LUA_TSTRING: + return hashstr(t, rawtsvalue(key)); + case LUA_TBOOLEAN: + return hashboolean(t, bvalue(key)); + case LUA_TLIGHTUSERDATA: + return hashpointer(t, pvalue(key)); + default: + return hashpointer(t, gcvalue(key)); + } +} + + +/* +** returns the index for `key' if `key' is an appropriate key to live in +** the array part of the table, -1 otherwise. +*/ +static int arrayindex (const TValue *key) { + if (ttisnumber(key)) { + lua_Number n = nvalue(key); + int k; + lua_number2int(k, n); + if (luai_numeq(cast_num(k), n)) + return k; + } + return -1; /* `key' did not match some condition */ +} + + +/* +** returns the index of a `key' for table traversals. First goes all +** elements in the array part, then elements in the hash part. The +** beginning of a traversal is signalled by -1. +*/ +static int findindex (lua_State *L, Table *t, StkId key) { + int i; + if (ttisnil(key)) return -1; /* first iteration */ + i = arrayindex(key); + if (0 < i && i <= t->sizearray) /* is `key' inside array part? */ + return i-1; /* yes; that's the index (corrected to C) */ + else { + Node *n = mainposition(t, key); + do { /* check whether `key' is somewhere in the chain */ + /* key may be dead already, but it is ok to use it in `next' */ + if (luaO_rawequalObj(key2tval(n), key) || + (ttype(gkey(n)) == LUA_TDEADKEY && iscollectable(key) && + gcvalue(gkey(n)) == gcvalue(key))) { + i = cast_int(n - gnode(t, 0)); /* key index in hash table */ + /* hash elements are numbered after array ones */ + return i + t->sizearray; + } + else n = gnext(n); + } while (n); + luaG_runerror(L, "invalid key to " LUA_QL("next")); /* key not found */ + return 0; /* to avoid warnings */ + } +} + + +int luaH_next (lua_State *L, Table *t, StkId key) { + int i = findindex(L, t, key); /* find original element */ + for (i++; i < t->sizearray; i++) { /* try first array part */ + if (!ttisnil(&t->array[i])) { /* a non-nil value? */ + setnvalue(key, cast_num(i+1)); + setobj2s(L, key+1, &t->array[i]); + return 1; + } + } + for (i -= t->sizearray; i < sizenode(t); i++) { /* then hash part */ + if (!ttisnil(gval(gnode(t, i)))) { /* a non-nil value? */ + setobj2s(L, key, key2tval(gnode(t, i))); + setobj2s(L, key+1, gval(gnode(t, i))); + return 1; + } + } + return 0; /* no more elements */ +} + + +/* +** {============================================================= +** Rehash +** ============================================================== +*/ + + +static int computesizes (int nums[], int *narray) { + int i; + int twotoi; /* 2^i */ + int a = 0; /* number of elements smaller than 2^i */ + int na = 0; /* number of elements to go to array part */ + int n = 0; /* optimal size for array part */ + for (i = 0, twotoi = 1; twotoi/2 < *narray; i++, twotoi *= 2) { + if (nums[i] > 0) { + a += nums[i]; + if (a > twotoi/2) { /* more than half elements present? */ + n = twotoi; /* optimal size (till now) */ + na = a; /* all elements smaller than n will go to array part */ + } + } + if (a == *narray) break; /* all elements already counted */ + } + *narray = n; + lua_assert(*narray/2 <= na && na <= *narray); + return na; +} + + +static int countint (const TValue *key, int *nums) { + int k = arrayindex(key); + if (0 < k && k <= MAXASIZE) { /* is `key' an appropriate array index? */ + nums[ceillog2(k)]++; /* count as such */ + return 1; + } + else + return 0; +} + + +static int numusearray (const Table *t, int *nums) { + int lg; + int ttlg; /* 2^lg */ + int ause = 0; /* summation of `nums' */ + int i = 1; /* count to traverse all array keys */ + for (lg=0, ttlg=1; lg<=MAXBITS; lg++, ttlg*=2) { /* for each slice */ + int lc = 0; /* counter */ + int lim = ttlg; + if (lim > t->sizearray) { + lim = t->sizearray; /* adjust upper limit */ + if (i > lim) + break; /* no more elements to count */ + } + /* count elements in range (2^(lg-1), 2^lg] */ + for (; i <= lim; i++) { + if (!ttisnil(&t->array[i-1])) + lc++; + } + nums[lg] += lc; + ause += lc; + } + return ause; +} + + +static int numusehash (const Table *t, int *nums, int *pnasize) { + int totaluse = 0; /* total number of elements */ + int ause = 0; /* summation of `nums' */ + int i = sizenode(t); + while (i--) { + Node *n = &t->node[i]; + if (!ttisnil(gval(n))) { + ause += countint(key2tval(n), nums); + totaluse++; + } + } + *pnasize += ause; + return totaluse; +} + + +static void setarrayvector (lua_State *L, Table *t, int size) { + int i; + luaM_reallocvector(L, t->array, t->sizearray, size, TValue); + for (i=t->sizearray; iarray[i]); + t->sizearray = size; +} + + +static void setnodevector (lua_State *L, Table *t, int size) { + int lsize; + if (size == 0) { /* no elements to hash part? */ + t->node = cast(Node *, dummynode); /* use common `dummynode' */ + lsize = 0; + } + else { + int i; + lsize = ceillog2(size); + if (lsize > MAXBITS) + luaG_runerror(L, "table overflow"); + size = twoto(lsize); + t->node = luaM_newvector(L, size, Node); + for (i=0; ilsizenode = cast_byte(lsize); + t->lastfree = gnode(t, size); /* all positions are free */ +} + + +static void resize (lua_State *L, Table *t, int nasize, int nhsize) { + int i; + int oldasize = t->sizearray; + int oldhsize = t->lsizenode; + Node *nold = t->node; /* save old hash ... */ + if (nasize > oldasize) /* array part must grow? */ + setarrayvector(L, t, nasize); + /* create new hash part with appropriate size */ + setnodevector(L, t, nhsize); + if (nasize < oldasize) { /* array part must shrink? */ + t->sizearray = nasize; + /* re-insert elements from vanishing slice */ + for (i=nasize; iarray[i])) + setobjt2t(L, luaH_setnum(L, t, i+1), &t->array[i]); + } + /* shrink array */ + luaM_reallocvector(L, t->array, oldasize, nasize, TValue); + } + /* re-insert elements from hash part */ + for (i = twoto(oldhsize) - 1; i >= 0; i--) { + Node *old = nold+i; + if (!ttisnil(gval(old))) + setobjt2t(L, luaH_set(L, t, key2tval(old)), gval(old)); + } + if (nold != dummynode) + luaM_freearray(L, nold, twoto(oldhsize), Node); /* free old array */ +} + + +void luaH_resizearray (lua_State *L, Table *t, int nasize) { + int nsize = (t->node == dummynode) ? 0 : sizenode(t); + resize(L, t, nasize, nsize); +} + + +static void rehash (lua_State *L, Table *t, const TValue *ek) { + int nasize, na; + int nums[MAXBITS+1]; /* nums[i] = number of keys between 2^(i-1) and 2^i */ + int i; + int totaluse; + for (i=0; i<=MAXBITS; i++) nums[i] = 0; /* reset counts */ + nasize = numusearray(t, nums); /* count keys in array part */ + totaluse = nasize; /* all those keys are integer keys */ + totaluse += numusehash(t, nums, &nasize); /* count keys in hash part */ + /* count extra key */ + nasize += countint(ek, nums); + totaluse++; + /* compute new size for array part */ + na = computesizes(nums, &nasize); + /* resize the table to new computed sizes */ + resize(L, t, nasize, totaluse - na); +} + + + +/* +** }============================================================= +*/ + + +Table *luaH_new (lua_State *L, int narray, int nhash) { + Table *t = luaM_new(L, Table); + luaC_link(L, obj2gco(t), LUA_TTABLE); + t->metatable = NULL; + t->flags = cast_byte(~0); + /* temporary values (kept only if some malloc fails) */ + t->array = NULL; + t->sizearray = 0; + t->lsizenode = 0; + t->node = cast(Node *, dummynode); + setarrayvector(L, t, narray); + setnodevector(L, t, nhash); + return t; +} + + +void luaH_free (lua_State *L, Table *t) { + if (t->node != dummynode) + luaM_freearray(L, t->node, sizenode(t), Node); + luaM_freearray(L, t->array, t->sizearray, TValue); + luaM_free(L, t); +} + + +static Node *getfreepos (Table *t) { + while (t->lastfree-- > t->node) { + if (ttisnil(gkey(t->lastfree))) + return t->lastfree; + } + return NULL; /* could not find a free place */ +} + + + +/* +** inserts a new key into a hash table; first, check whether key's main +** position is free. If not, check whether colliding node is in its main +** position or not: if it is not, move colliding node to an empty place and +** put new key in its main position; otherwise (colliding node is in its main +** position), new key goes to an empty position. +*/ +static TValue *newkey (lua_State *L, Table *t, const TValue *key) { + Node *mp = mainposition(t, key); + if (!ttisnil(gval(mp)) || mp == dummynode) { + Node *othern; + Node *n = getfreepos(t); /* get a free place */ + if (n == NULL) { /* cannot find a free place? */ + rehash(L, t, key); /* grow table */ + return luaH_set(L, t, key); /* re-insert key into grown table */ + } + lua_assert(n != dummynode); + othern = mainposition(t, key2tval(mp)); + if (othern != mp) { /* is colliding node out of its main position? */ + /* yes; move colliding node into free position */ + while (gnext(othern) != mp) othern = gnext(othern); /* find previous */ + gnext(othern) = n; /* redo the chain with `n' in place of `mp' */ + *n = *mp; /* copy colliding node into free pos. (mp->next also goes) */ + gnext(mp) = NULL; /* now `mp' is free */ + setnilvalue(gval(mp)); + } + else { /* colliding node is in its own main position */ + /* new node will go into free position */ + gnext(n) = gnext(mp); /* chain new position */ + gnext(mp) = n; + mp = n; + } + } + gkey(mp)->value = key->value; gkey(mp)->tt = key->tt; + luaC_barriert(L, t, key); + lua_assert(ttisnil(gval(mp))); + return gval(mp); +} + + +/* +** search function for integers +*/ +const TValue *luaH_getnum (Table *t, int key) { + /* (1 <= key && key <= t->sizearray) */ + if (cast(unsigned int, key-1) < cast(unsigned int, t->sizearray)) + return &t->array[key-1]; + else { + lua_Number nk = cast_num(key); + Node *n = hashnum(t, nk); + do { /* check whether `key' is somewhere in the chain */ + if (ttisnumber(gkey(n)) && luai_numeq(nvalue(gkey(n)), nk)) + return gval(n); /* that's it */ + else n = gnext(n); + } while (n); + return luaO_nilobject; + } +} + + +/* +** search function for strings +*/ +const TValue *luaH_getstr (Table *t, TString *key) { + Node *n = hashstr(t, key); + do { /* check whether `key' is somewhere in the chain */ + if (ttisstring(gkey(n)) && rawtsvalue(gkey(n)) == key) + return gval(n); /* that's it */ + else n = gnext(n); + } while (n); + return luaO_nilobject; +} + + +/* +** main search function +*/ +const TValue *luaH_get (Table *t, const TValue *key) { + switch (ttype(key)) { + case LUA_TNIL: return luaO_nilobject; + case LUA_TSTRING: return luaH_getstr(t, rawtsvalue(key)); + case LUA_TNUMBER: { + int k; + lua_Number n = nvalue(key); + lua_number2int(k, n); + if (luai_numeq(cast_num(k), nvalue(key))) /* index is int? */ + return luaH_getnum(t, k); /* use specialized version */ + /* else go through */ + } + default: { + Node *n = mainposition(t, key); + do { /* check whether `key' is somewhere in the chain */ + if (luaO_rawequalObj(key2tval(n), key)) + return gval(n); /* that's it */ + else n = gnext(n); + } while (n); + return luaO_nilobject; + } + } +} + + +TValue *luaH_set (lua_State *L, Table *t, const TValue *key) { + const TValue *p = luaH_get(t, key); + t->flags = 0; + if (p != luaO_nilobject) + return cast(TValue *, p); + else { + if (ttisnil(key)) luaG_runerror(L, "table index is nil"); + else if (ttisnumber(key) && luai_numisnan(nvalue(key))) + luaG_runerror(L, "table index is NaN"); + return newkey(L, t, key); + } +} + + +TValue *luaH_setnum (lua_State *L, Table *t, int key) { + const TValue *p = luaH_getnum(t, key); + if (p != luaO_nilobject) + return cast(TValue *, p); + else { + TValue k; + setnvalue(&k, cast_num(key)); + return newkey(L, t, &k); + } +} + + +TValue *luaH_setstr (lua_State *L, Table *t, TString *key) { + const TValue *p = luaH_getstr(t, key); + if (p != luaO_nilobject) + return cast(TValue *, p); + else { + TValue k; + setsvalue(L, &k, key); + return newkey(L, t, &k); + } +} + + +static int unbound_search (Table *t, unsigned int j) { + unsigned int i = j; /* i is zero or a present index */ + j++; + /* find `i' and `j' such that i is present and j is not */ + while (!ttisnil(luaH_getnum(t, j))) { + i = j; + j *= 2; + if (j > cast(unsigned int, MAX_INT)) { /* overflow? */ + /* table was built with bad purposes: resort to linear search */ + i = 1; + while (!ttisnil(luaH_getnum(t, i))) i++; + return i - 1; + } + } + /* now do a binary search between them */ + while (j - i > 1) { + unsigned int m = (i+j)/2; + if (ttisnil(luaH_getnum(t, m))) j = m; + else i = m; + } + return i; +} + + +/* +** Try to find a boundary in table `t'. A `boundary' is an integer index +** such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil). +*/ +int luaH_getn (Table *t) { + unsigned int j = t->sizearray; + if (j > 0 && ttisnil(&t->array[j - 1])) { + /* there is a boundary in the array part: (binary) search for it */ + unsigned int i = 0; + while (j - i > 1) { + unsigned int m = (i+j)/2; + if (ttisnil(&t->array[m - 1])) j = m; + else i = m; + } + return i; + } + /* else must find a boundary in hash part */ + else if (t->node == dummynode) /* hash part is empty? */ + return j; /* that is easy... */ + else return unbound_search(t, j); +} + + + +#if defined(LUA_DEBUG) + +Node *luaH_mainposition (const Table *t, const TValue *key) { + return mainposition(t, key); +} + +int luaH_isdummy (Node *n) { return n == dummynode; } + +#endif diff --git a/external/mit/lua/dist/src/ltable.h b/external/mit/lua/dist/src/ltable.h new file mode 100644 index 000000000..58792e901 --- /dev/null +++ b/external/mit/lua/dist/src/ltable.h @@ -0,0 +1,42 @@ +/* $NetBSD: ltable.h,v 1.1.1.2 2012/03/15 00:08:11 alnsn Exp $ */ + +/* +** $Id: ltable.h,v 1.1.1.2 2012/03/15 00:08:11 alnsn Exp $ +** Lua tables (hash) +** See Copyright Notice in lua.h +*/ + +#ifndef ltable_h +#define ltable_h + +#include "lobject.h" + + +#define gnode(t,i) (&(t)->node[i]) +#define gkey(n) (&(n)->i_key.nk) +#define gval(n) (&(n)->i_val) +#define gnext(n) ((n)->i_key.nk.next) + +#define key2tval(n) (&(n)->i_key.tvk) + + +LUAI_FUNC const TValue *luaH_getnum (Table *t, int key); +LUAI_FUNC TValue *luaH_setnum (lua_State *L, Table *t, int key); +LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key); +LUAI_FUNC TValue *luaH_setstr (lua_State *L, Table *t, TString *key); +LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key); +LUAI_FUNC TValue *luaH_set (lua_State *L, Table *t, const TValue *key); +LUAI_FUNC Table *luaH_new (lua_State *L, int narray, int lnhash); +LUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, int nasize); +LUAI_FUNC void luaH_free (lua_State *L, Table *t); +LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key); +LUAI_FUNC int luaH_getn (Table *t); + + +#if defined(LUA_DEBUG) +LUAI_FUNC Node *luaH_mainposition (const Table *t, const TValue *key); +LUAI_FUNC int luaH_isdummy (Node *n); +#endif + + +#endif diff --git a/external/mit/lua/dist/src/ltablib.c b/external/mit/lua/dist/src/ltablib.c new file mode 100644 index 000000000..14537ce4d --- /dev/null +++ b/external/mit/lua/dist/src/ltablib.c @@ -0,0 +1,289 @@ +/* $NetBSD: ltablib.c,v 1.1.1.2 2012/03/15 00:08:07 alnsn Exp $ */ + +/* +** $Id: ltablib.c,v 1.1.1.2 2012/03/15 00:08:07 alnsn Exp $ +** Library for Table Manipulation +** See Copyright Notice in lua.h +*/ + + +#include + +#define ltablib_c +#define LUA_LIB + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +#define aux_getn(L,n) (luaL_checktype(L, n, LUA_TTABLE), luaL_getn(L, n)) + + +static int foreachi (lua_State *L) { + int i; + int n = aux_getn(L, 1); + luaL_checktype(L, 2, LUA_TFUNCTION); + for (i=1; i <= n; i++) { + lua_pushvalue(L, 2); /* function */ + lua_pushinteger(L, i); /* 1st argument */ + lua_rawgeti(L, 1, i); /* 2nd argument */ + lua_call(L, 2, 1); + if (!lua_isnil(L, -1)) + return 1; + lua_pop(L, 1); /* remove nil result */ + } + return 0; +} + + +static int foreach (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + luaL_checktype(L, 2, LUA_TFUNCTION); + lua_pushnil(L); /* first key */ + while (lua_next(L, 1)) { + lua_pushvalue(L, 2); /* function */ + lua_pushvalue(L, -3); /* key */ + lua_pushvalue(L, -3); /* value */ + lua_call(L, 2, 1); + if (!lua_isnil(L, -1)) + return 1; + lua_pop(L, 2); /* remove value and result */ + } + return 0; +} + + +static int maxn (lua_State *L) { + lua_Number max = 0; + luaL_checktype(L, 1, LUA_TTABLE); + lua_pushnil(L); /* first key */ + while (lua_next(L, 1)) { + lua_pop(L, 1); /* remove value */ + if (lua_type(L, -1) == LUA_TNUMBER) { + lua_Number v = lua_tonumber(L, -1); + if (v > max) max = v; + } + } + lua_pushnumber(L, max); + return 1; +} + + +static int getn (lua_State *L) { + lua_pushinteger(L, aux_getn(L, 1)); + return 1; +} + + +static int setn (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); +#ifndef luaL_setn + luaL_setn(L, 1, luaL_checkint(L, 2)); +#else + luaL_error(L, LUA_QL("setn") " is obsolete"); +#endif + lua_pushvalue(L, 1); + return 1; +} + + +static int tinsert (lua_State *L) { + int e = aux_getn(L, 1) + 1; /* first empty element */ + int pos; /* where to insert new element */ + switch (lua_gettop(L)) { + case 2: { /* called with only 2 arguments */ + pos = e; /* insert new element at the end */ + break; + } + case 3: { + int i; + pos = luaL_checkint(L, 2); /* 2nd argument is the position */ + if (pos > e) e = pos; /* `grow' array if necessary */ + for (i = e; i > pos; i--) { /* move up elements */ + lua_rawgeti(L, 1, i-1); + lua_rawseti(L, 1, i); /* t[i] = t[i-1] */ + } + break; + } + default: { + return luaL_error(L, "wrong number of arguments to " LUA_QL("insert")); + } + } + luaL_setn(L, 1, e); /* new size */ + lua_rawseti(L, 1, pos); /* t[pos] = v */ + return 0; +} + + +static int tremove (lua_State *L) { + int e = aux_getn(L, 1); + int pos = luaL_optint(L, 2, e); + if (!(1 <= pos && pos <= e)) /* position is outside bounds? */ + return 0; /* nothing to remove */ + luaL_setn(L, 1, e - 1); /* t.n = n-1 */ + lua_rawgeti(L, 1, pos); /* result = t[pos] */ + for ( ;pos= P */ + while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) { + if (i>u) luaL_error(L, "invalid order function for sorting"); + lua_pop(L, 1); /* remove a[i] */ + } + /* repeat --j until a[j] <= P */ + while (lua_rawgeti(L, 1, --j), sort_comp(L, -3, -1)) { + if (j + +#define ltm_c +#define LUA_CORE + +#include "lua.h" + +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" + + + +const char *const luaT_typenames[] = { + "nil", "boolean", "userdata", "number", + "string", "table", "function", "userdata", "thread", + "proto", "upval" +}; + + +void luaT_init (lua_State *L) { + static const char *const luaT_eventname[] = { /* ORDER TM */ + "__index", "__newindex", + "__gc", "__mode", "__eq", + "__add", "__sub", "__mul", "__div", "__mod", + "__pow", "__unm", "__len", "__lt", "__le", + "__concat", "__call" + }; + int i; + for (i=0; itmname[i] = luaS_new(L, luaT_eventname[i]); + luaS_fix(G(L)->tmname[i]); /* never collect these names */ + } +} + + +/* +** function to be used with macro "fasttm": optimized for absence of +** tag methods +*/ +const TValue *luaT_gettm (Table *events, TMS event, TString *ename) { + const TValue *tm = luaH_getstr(events, ename); + lua_assert(event <= TM_EQ); + if (ttisnil(tm)) { /* no tag method? */ + events->flags |= cast_byte(1u<metatable; + break; + case LUA_TUSERDATA: + mt = uvalue(o)->metatable; + break; + default: + mt = G(L)->mt[ttype(o)]; + } + return (mt ? luaH_getstr(mt, G(L)->tmname[event]) : luaO_nilobject); +} + diff --git a/external/mit/lua/dist/src/ltm.h b/external/mit/lua/dist/src/ltm.h new file mode 100644 index 000000000..ecf91b020 --- /dev/null +++ b/external/mit/lua/dist/src/ltm.h @@ -0,0 +1,56 @@ +/* $NetBSD: ltm.h,v 1.1.1.2 2012/03/15 00:08:07 alnsn Exp $ */ + +/* +** $Id: ltm.h,v 1.1.1.2 2012/03/15 00:08:07 alnsn Exp $ +** Tag methods +** See Copyright Notice in lua.h +*/ + +#ifndef ltm_h +#define ltm_h + + +#include "lobject.h" + + +/* +* WARNING: if you change the order of this enumeration, +* grep "ORDER TM" +*/ +typedef enum { + TM_INDEX, + TM_NEWINDEX, + TM_GC, + TM_MODE, + TM_EQ, /* last tag method with `fast' access */ + TM_ADD, + TM_SUB, + TM_MUL, + TM_DIV, + TM_MOD, + TM_POW, + TM_UNM, + TM_LEN, + TM_LT, + TM_LE, + TM_CONCAT, + TM_CALL, + TM_N /* number of elements in the enum */ +} TMS; + + + +#define gfasttm(g,et,e) ((et) == NULL ? NULL : \ + ((et)->flags & (1u<<(e))) ? NULL : luaT_gettm(et, e, (g)->tmname[e])) + +#define fasttm(l,et,e) gfasttm(G(l), et, e) + +LUAI_DATA const char *const luaT_typenames[]; + + +LUAI_FUNC const TValue *luaT_gettm (Table *events, TMS event, TString *ename); +LUAI_FUNC const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, + TMS event); +LUAI_FUNC void luaT_init (lua_State *L); + +#endif diff --git a/external/mit/lua/dist/src/lua.c b/external/mit/lua/dist/src/lua.c new file mode 100644 index 000000000..b637ab244 --- /dev/null +++ b/external/mit/lua/dist/src/lua.c @@ -0,0 +1,394 @@ +/* $NetBSD: lua.c,v 1.1.1.2 2012/03/15 00:08:11 alnsn Exp $ */ + +/* +** $Id: lua.c,v 1.1.1.2 2012/03/15 00:08:11 alnsn Exp $ +** Lua stand-alone interpreter +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include +#include + +#define lua_c + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + + +static lua_State *globalL = NULL; + +static const char *progname = LUA_PROGNAME; + + + +static void lstop (lua_State *L, lua_Debug *ar) { + (void)ar; /* unused arg. */ + lua_sethook(L, NULL, 0, 0); + luaL_error(L, "interrupted!"); +} + + +static void laction (int i) { + signal(i, SIG_DFL); /* if another SIGINT happens before lstop, + terminate process (default action) */ + lua_sethook(globalL, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1); +} + + +static void print_usage (void) { + fprintf(stderr, + "usage: %s [options] [script [args]].\n" + "Available options are:\n" + " -e stat execute string " LUA_QL("stat") "\n" + " -l name require library " LUA_QL("name") "\n" + " -i enter interactive mode after executing " LUA_QL("script") "\n" + " -v show version information\n" + " -- stop handling options\n" + " - execute stdin and stop handling options\n" + , + progname); + fflush(stderr); +} + + +static void l_message (const char *pname, const char *msg) { + if (pname) fprintf(stderr, "%s: ", pname); + fprintf(stderr, "%s\n", msg); + fflush(stderr); +} + + +static int report (lua_State *L, int status) { + if (status && !lua_isnil(L, -1)) { + const char *msg = lua_tostring(L, -1); + if (msg == NULL) msg = "(error object is not a string)"; + l_message(progname, msg); + lua_pop(L, 1); + } + return status; +} + + +static int traceback (lua_State *L) { + if (!lua_isstring(L, 1)) /* 'message' not a string? */ + return 1; /* keep it intact */ + lua_getfield(L, LUA_GLOBALSINDEX, "debug"); + if (!lua_istable(L, -1)) { + lua_pop(L, 1); + return 1; + } + lua_getfield(L, -1, "traceback"); + if (!lua_isfunction(L, -1)) { + lua_pop(L, 2); + return 1; + } + lua_pushvalue(L, 1); /* pass error message */ + lua_pushinteger(L, 2); /* skip this function and traceback */ + lua_call(L, 2, 1); /* call debug.traceback */ + return 1; +} + + +static int docall (lua_State *L, int narg, int clear) { + int status; + int base = lua_gettop(L) - narg; /* function index */ + lua_pushcfunction(L, traceback); /* push traceback function */ + lua_insert(L, base); /* put it under chunk and args */ + signal(SIGINT, laction); + status = lua_pcall(L, narg, (clear ? 0 : LUA_MULTRET), base); + signal(SIGINT, SIG_DFL); + lua_remove(L, base); /* remove traceback function */ + /* force a complete garbage collection in case of errors */ + if (status != 0) lua_gc(L, LUA_GCCOLLECT, 0); + return status; +} + + +static void print_version (void) { + l_message(NULL, LUA_RELEASE " " LUA_COPYRIGHT); +} + + +static int getargs (lua_State *L, char **argv, int n) { + int narg; + int i; + int argc = 0; + while (argv[argc]) argc++; /* count total number of arguments */ + narg = argc - (n + 1); /* number of arguments to the script */ + luaL_checkstack(L, narg + 3, "too many arguments to script"); + for (i=n+1; i < argc; i++) + lua_pushstring(L, argv[i]); + lua_createtable(L, narg, n + 1); + for (i=0; i < argc; i++) { + lua_pushstring(L, argv[i]); + lua_rawseti(L, -2, i - n); + } + return narg; +} + + +static int dofile (lua_State *L, const char *name) { + int status = luaL_loadfile(L, name) || docall(L, 0, 1); + return report(L, status); +} + + +static int dostring (lua_State *L, const char *s, const char *name) { + int status = luaL_loadbuffer(L, s, strlen(s), name) || docall(L, 0, 1); + return report(L, status); +} + + +static int dolibrary (lua_State *L, const char *name) { + lua_getglobal(L, "require"); + lua_pushstring(L, name); + return report(L, docall(L, 1, 1)); +} + + +static const char *get_prompt (lua_State *L, int firstline) { + const char *p; + lua_getfield(L, LUA_GLOBALSINDEX, firstline ? "_PROMPT" : "_PROMPT2"); + p = lua_tostring(L, -1); + if (p == NULL) p = (firstline ? LUA_PROMPT : LUA_PROMPT2); + lua_pop(L, 1); /* remove global */ + return p; +} + + +static int incomplete (lua_State *L, int status) { + if (status == LUA_ERRSYNTAX) { + size_t lmsg; + const char *msg = lua_tolstring(L, -1, &lmsg); + const char *tp = msg + lmsg - (sizeof(LUA_QL("")) - 1); + if (strstr(msg, LUA_QL("")) == tp) { + lua_pop(L, 1); + return 1; + } + } + return 0; /* else... */ +} + + +static int pushline (lua_State *L, int firstline) { + char buffer[LUA_MAXINPUT]; + char *b = buffer; + size_t l; + const char *prmt = get_prompt(L, firstline); + if (lua_readline(L, b, prmt) == 0) + return 0; /* no input */ + l = strlen(b); + if (l > 0 && b[l-1] == '\n') /* line ends with newline? */ + b[l-1] = '\0'; /* remove it */ + if (firstline && b[0] == '=') /* first line starts with `=' ? */ + lua_pushfstring(L, "return %s", b+1); /* change it to `return' */ + else + lua_pushstring(L, b); + lua_freeline(L, b); + return 1; +} + + +static int loadline (lua_State *L) { + int status; + lua_settop(L, 0); + if (!pushline(L, 1)) + return -1; /* no input */ + for (;;) { /* repeat until gets a complete line */ + status = luaL_loadbuffer(L, lua_tostring(L, 1), lua_strlen(L, 1), "=stdin"); + if (!incomplete(L, status)) break; /* cannot try to add lines? */ + if (!pushline(L, 0)) /* no more input? */ + return -1; + lua_pushliteral(L, "\n"); /* add a new line... */ + lua_insert(L, -2); /* ...between the two lines */ + lua_concat(L, 3); /* join them */ + } + lua_saveline(L, 1); + lua_remove(L, 1); /* remove line */ + return status; +} + + +static void dotty (lua_State *L) { + int status; + const char *oldprogname = progname; + progname = NULL; + while ((status = loadline(L)) != -1) { + if (status == 0) status = docall(L, 0, 0); + report(L, status); + if (status == 0 && lua_gettop(L) > 0) { /* any result to print? */ + lua_getglobal(L, "print"); + lua_insert(L, 1); + if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != 0) + l_message(progname, lua_pushfstring(L, + "error calling " LUA_QL("print") " (%s)", + lua_tostring(L, -1))); + } + } + lua_settop(L, 0); /* clear stack */ + fputs("\n", stdout); + fflush(stdout); + progname = oldprogname; +} + + +static int handle_script (lua_State *L, char **argv, int n) { + int status; + const char *fname; + int narg = getargs(L, argv, n); /* collect arguments */ + lua_setglobal(L, "arg"); + fname = argv[n]; + if (strcmp(fname, "-") == 0 && strcmp(argv[n-1], "--") != 0) + fname = NULL; /* stdin */ + status = luaL_loadfile(L, fname); + lua_insert(L, -(narg+1)); + if (status == 0) + status = docall(L, narg, 0); + else + lua_pop(L, narg); + return report(L, status); +} + + +/* check that argument has no extra characters at the end */ +#define notail(x) {if ((x)[2] != '\0') return -1;} + + +static int collectargs (char **argv, int *pi, int *pv, int *pe) { + int i; + for (i = 1; argv[i] != NULL; i++) { + if (argv[i][0] != '-') /* not an option? */ + return i; + switch (argv[i][1]) { /* option */ + case '-': + notail(argv[i]); + return (argv[i+1] != NULL ? i+1 : 0); + case '\0': + return i; + case 'i': + notail(argv[i]); + *pi = 1; /* go through */ + case 'v': + notail(argv[i]); + *pv = 1; + break; + case 'e': + *pe = 1; /* go through */ + case 'l': + if (argv[i][2] == '\0') { + i++; + if (argv[i] == NULL) return -1; + } + break; + default: return -1; /* invalid option */ + } + } + return 0; +} + + +static int runargs (lua_State *L, char **argv, int n) { + int i; + for (i = 1; i < n; i++) { + if (argv[i] == NULL) continue; + lua_assert(argv[i][0] == '-'); + switch (argv[i][1]) { /* option */ + case 'e': { + const char *chunk = argv[i] + 2; + if (*chunk == '\0') chunk = argv[++i]; + lua_assert(chunk != NULL); + if (dostring(L, chunk, "=(command line)") != 0) + return 1; + break; + } + case 'l': { + const char *filename = argv[i] + 2; + if (*filename == '\0') filename = argv[++i]; + lua_assert(filename != NULL); + if (dolibrary(L, filename)) + return 1; /* stop if file fails */ + break; + } + default: break; + } + } + return 0; +} + + +static int handle_luainit (lua_State *L) { + const char *init = getenv(LUA_INIT); + if (init == NULL) return 0; /* status OK */ + else if (init[0] == '@') + return dofile(L, init+1); + else + return dostring(L, init, "=" LUA_INIT); +} + + +struct Smain { + int argc; + char **argv; + int status; +}; + + +static int pmain (lua_State *L) { + struct Smain *s = (struct Smain *)lua_touserdata(L, 1); + char **argv = s->argv; + int script; + int has_i = 0, has_v = 0, has_e = 0; + globalL = L; + if (argv[0] && argv[0][0]) progname = argv[0]; + lua_gc(L, LUA_GCSTOP, 0); /* stop collector during initialization */ + luaL_openlibs(L); /* open libraries */ + lua_gc(L, LUA_GCRESTART, 0); + s->status = handle_luainit(L); + if (s->status != 0) return 0; + script = collectargs(argv, &has_i, &has_v, &has_e); + if (script < 0) { /* invalid args? */ + print_usage(); + s->status = 1; + return 0; + } + if (has_v) print_version(); + s->status = runargs(L, argv, (script > 0) ? script : s->argc); + if (s->status != 0) return 0; + if (script) + s->status = handle_script(L, argv, script); + if (s->status != 0) return 0; + if (has_i) + dotty(L); + else if (script == 0 && !has_e && !has_v) { + if (lua_stdin_is_tty()) { + print_version(); + dotty(L); + } + else dofile(L, NULL); /* executes stdin as a file */ + } + return 0; +} + + +int main (int argc, char **argv) { + int status; + struct Smain s; + lua_State *L = lua_open(); /* create state */ + if (L == NULL) { + l_message(argv[0], "cannot create state: not enough memory"); + return EXIT_FAILURE; + } + s.argc = argc; + s.argv = argv; + status = lua_cpcall(L, &pmain, &s); + report(L, status); + lua_close(L); + return (status || s.status) ? EXIT_FAILURE : EXIT_SUCCESS; +} + diff --git a/external/mit/lua/dist/src/lua.h b/external/mit/lua/dist/src/lua.h new file mode 100644 index 000000000..a42d9238c --- /dev/null +++ b/external/mit/lua/dist/src/lua.h @@ -0,0 +1,390 @@ +/* $NetBSD: lua.h,v 1.1.1.2 2012/03/15 00:08:14 alnsn Exp $ */ + +/* +** $Id: lua.h,v 1.1.1.2 2012/03/15 00:08:14 alnsn Exp $ +** Lua - An Extensible Extension Language +** Lua.org, PUC-Rio, Brazil (http://www.lua.org) +** See Copyright Notice at the end of this file +*/ + + +#ifndef lua_h +#define lua_h + +#include +#include + + +#include "luaconf.h" + + +#define LUA_VERSION "Lua 5.1" +#define LUA_RELEASE "Lua 5.1.5" +#define LUA_VERSION_NUM 501 +#define LUA_COPYRIGHT "Copyright (C) 1994-2012 Lua.org, PUC-Rio" +#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes" + + +/* mark for precompiled code (`Lua') */ +#define LUA_SIGNATURE "\033Lua" + +/* option for multiple returns in `lua_pcall' and `lua_call' */ +#define LUA_MULTRET (-1) + + +/* +** pseudo-indices +*/ +#define LUA_REGISTRYINDEX (-10000) +#define LUA_ENVIRONINDEX (-10001) +#define LUA_GLOBALSINDEX (-10002) +#define lua_upvalueindex(i) (LUA_GLOBALSINDEX-(i)) + + +/* thread status; 0 is OK */ +#define LUA_YIELD 1 +#define LUA_ERRRUN 2 +#define LUA_ERRSYNTAX 3 +#define LUA_ERRMEM 4 +#define LUA_ERRERR 5 + + +typedef struct lua_State lua_State; + +typedef int (*lua_CFunction) (lua_State *L); + + +/* +** functions that read/write blocks when loading/dumping Lua chunks +*/ +typedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz); + +typedef int (*lua_Writer) (lua_State *L, const void* p, size_t sz, void* ud); + + +/* +** prototype for memory-allocation functions +*/ +typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize); + + +/* +** basic types +*/ +#define LUA_TNONE (-1) + +#define LUA_TNIL 0 +#define LUA_TBOOLEAN 1 +#define LUA_TLIGHTUSERDATA 2 +#define LUA_TNUMBER 3 +#define LUA_TSTRING 4 +#define LUA_TTABLE 5 +#define LUA_TFUNCTION 6 +#define LUA_TUSERDATA 7 +#define LUA_TTHREAD 8 + + + +/* minimum Lua stack available to a C function */ +#define LUA_MINSTACK 20 + + +/* +** generic extra include file +*/ +#if defined(LUA_USER_H) +#include LUA_USER_H +#endif + + +/* type of numbers in Lua */ +typedef LUA_NUMBER lua_Number; + + +/* type for integer functions */ +typedef LUA_INTEGER lua_Integer; + + + +/* +** state manipulation +*/ +LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud); +LUA_API void (lua_close) (lua_State *L); +LUA_API lua_State *(lua_newthread) (lua_State *L); + +LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf); + + +/* +** basic stack manipulation +*/ +LUA_API int (lua_gettop) (lua_State *L); +LUA_API void (lua_settop) (lua_State *L, int idx); +LUA_API void (lua_pushvalue) (lua_State *L, int idx); +LUA_API void (lua_remove) (lua_State *L, int idx); +LUA_API void (lua_insert) (lua_State *L, int idx); +LUA_API void (lua_replace) (lua_State *L, int idx); +LUA_API int (lua_checkstack) (lua_State *L, int sz); + +LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n); + + +/* +** access functions (stack -> C) +*/ + +LUA_API int (lua_isnumber) (lua_State *L, int idx); +LUA_API int (lua_isstring) (lua_State *L, int idx); +LUA_API int (lua_iscfunction) (lua_State *L, int idx); +LUA_API int (lua_isuserdata) (lua_State *L, int idx); +LUA_API int (lua_type) (lua_State *L, int idx); +LUA_API const char *(lua_typename) (lua_State *L, int tp); + +LUA_API int (lua_equal) (lua_State *L, int idx1, int idx2); +LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2); +LUA_API int (lua_lessthan) (lua_State *L, int idx1, int idx2); + +LUA_API lua_Number (lua_tonumber) (lua_State *L, int idx); +LUA_API lua_Integer (lua_tointeger) (lua_State *L, int idx); +LUA_API int (lua_toboolean) (lua_State *L, int idx); +LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len); +LUA_API size_t (lua_objlen) (lua_State *L, int idx); +LUA_API lua_CFunction (lua_tocfunction) (lua_State *L, int idx); +LUA_API void *(lua_touserdata) (lua_State *L, int idx); +LUA_API lua_State *(lua_tothread) (lua_State *L, int idx); +LUA_API const void *(lua_topointer) (lua_State *L, int idx); + + +/* +** push functions (C -> stack) +*/ +LUA_API void (lua_pushnil) (lua_State *L); +LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n); +LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n); +LUA_API void (lua_pushlstring) (lua_State *L, const char *s, size_t l); +LUA_API void (lua_pushstring) (lua_State *L, const char *s); +LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt, + va_list argp); +LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...); +LUA_API void (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n); +LUA_API void (lua_pushboolean) (lua_State *L, int b); +LUA_API void (lua_pushlightuserdata) (lua_State *L, void *p); +LUA_API int (lua_pushthread) (lua_State *L); + + +/* +** get functions (Lua -> stack) +*/ +LUA_API void (lua_gettable) (lua_State *L, int idx); +LUA_API void (lua_getfield) (lua_State *L, int idx, const char *k); +LUA_API void (lua_rawget) (lua_State *L, int idx); +LUA_API void (lua_rawgeti) (lua_State *L, int idx, int n); +LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec); +LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz); +LUA_API int (lua_getmetatable) (lua_State *L, int objindex); +LUA_API void (lua_getfenv) (lua_State *L, int idx); + + +/* +** set functions (stack -> Lua) +*/ +LUA_API void (lua_settable) (lua_State *L, int idx); +LUA_API void (lua_setfield) (lua_State *L, int idx, const char *k); +LUA_API void (lua_rawset) (lua_State *L, int idx); +LUA_API void (lua_rawseti) (lua_State *L, int idx, int n); +LUA_API int (lua_setmetatable) (lua_State *L, int objindex); +LUA_API int (lua_setfenv) (lua_State *L, int idx); + + +/* +** `load' and `call' functions (load and run Lua code) +*/ +LUA_API void (lua_call) (lua_State *L, int nargs, int nresults); +LUA_API int (lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc); +LUA_API int (lua_cpcall) (lua_State *L, lua_CFunction func, void *ud); +LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt, + const char *chunkname); + +LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data); + + +/* +** coroutine functions +*/ +LUA_API int (lua_yield) (lua_State *L, int nresults); +LUA_API int (lua_resume) (lua_State *L, int narg); +LUA_API int (lua_status) (lua_State *L); + +/* +** garbage-collection function and options +*/ + +#define LUA_GCSTOP 0 +#define LUA_GCRESTART 1 +#define LUA_GCCOLLECT 2 +#define LUA_GCCOUNT 3 +#define LUA_GCCOUNTB 4 +#define LUA_GCSTEP 5 +#define LUA_GCSETPAUSE 6 +#define LUA_GCSETSTEPMUL 7 + +LUA_API int (lua_gc) (lua_State *L, int what, int data); + + +/* +** miscellaneous functions +*/ + +LUA_API int (lua_error) (lua_State *L); + +LUA_API int (lua_next) (lua_State *L, int idx); + +LUA_API void (lua_concat) (lua_State *L, int n); + +LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud); +LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud); + + + +/* +** =============================================================== +** some useful macros +** =============================================================== +*/ + +#define lua_pop(L,n) lua_settop(L, -(n)-1) + +#define lua_newtable(L) lua_createtable(L, 0, 0) + +#define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n))) + +#define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0) + +#define lua_strlen(L,i) lua_objlen(L, (i)) + +#define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION) +#define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE) +#define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA) +#define lua_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL) +#define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN) +#define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD) +#define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE) +#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0) + +#define lua_pushliteral(L, s) \ + lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1) + +#define lua_setglobal(L,s) lua_setfield(L, LUA_GLOBALSINDEX, (s)) +#define lua_getglobal(L,s) lua_getfield(L, LUA_GLOBALSINDEX, (s)) + +#define lua_tostring(L,i) lua_tolstring(L, (i), NULL) + + + +/* +** compatibility macros and functions +*/ + +#define lua_open() luaL_newstate() + +#define lua_getregistry(L) lua_pushvalue(L, LUA_REGISTRYINDEX) + +#define lua_getgccount(L) lua_gc(L, LUA_GCCOUNT, 0) + +#define lua_Chunkreader lua_Reader +#define lua_Chunkwriter lua_Writer + + +/* hack */ +LUA_API void lua_setlevel (lua_State *from, lua_State *to); + + +/* +** {====================================================================== +** Debug API +** ======================================================================= +*/ + + +/* +** Event codes +*/ +#define LUA_HOOKCALL 0 +#define LUA_HOOKRET 1 +#define LUA_HOOKLINE 2 +#define LUA_HOOKCOUNT 3 +#define LUA_HOOKTAILRET 4 + + +/* +** Event masks +*/ +#define LUA_MASKCALL (1 << LUA_HOOKCALL) +#define LUA_MASKRET (1 << LUA_HOOKRET) +#define LUA_MASKLINE (1 << LUA_HOOKLINE) +#define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT) + +typedef struct lua_Debug lua_Debug; /* activation record */ + + +/* Functions to be called by the debuger in specific events */ +typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar); + + +LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar); +LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar); +LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n); +LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n); +LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n); +LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n); + +LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count); +LUA_API lua_Hook lua_gethook (lua_State *L); +LUA_API int lua_gethookmask (lua_State *L); +LUA_API int lua_gethookcount (lua_State *L); + + +struct lua_Debug { + int event; + const char *name; /* (n) */ + const char *namewhat; /* (n) `global', `local', `field', `method' */ + const char *what; /* (S) `Lua', `C', `main', `tail' */ + const char *source; /* (S) */ + int currentline; /* (l) */ + int nups; /* (u) number of upvalues */ + int linedefined; /* (S) */ + int lastlinedefined; /* (S) */ + char short_src[LUA_IDSIZE]; /* (S) */ + /* private part */ + int i_ci; /* active function */ +}; + +/* }====================================================================== */ + + +/****************************************************************************** +* Copyright (C) 1994-2012 Lua.org, PUC-Rio. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to deal in the Software without restriction, including +* without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to +* permit persons to whom the Software is furnished to do so, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be +* included in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +******************************************************************************/ + + +#endif diff --git a/external/mit/lua/dist/src/luac.c b/external/mit/lua/dist/src/luac.c new file mode 100644 index 000000000..ecd42b8d6 --- /dev/null +++ b/external/mit/lua/dist/src/luac.c @@ -0,0 +1,202 @@ +/* $NetBSD: luac.c,v 1.1.1.2 2012/03/15 00:08:14 alnsn Exp $ */ + +/* +** $Id: luac.c,v 1.1.1.2 2012/03/15 00:08:14 alnsn Exp $ +** Lua compiler (saves bytecodes to files; also list bytecodes) +** See Copyright Notice in lua.h +*/ + +#include +#include +#include +#include + +#define luac_c +#define LUA_CORE + +#include "lua.h" +#include "lauxlib.h" + +#include "ldo.h" +#include "lfunc.h" +#include "lmem.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lstring.h" +#include "lundump.h" + +#define PROGNAME "luac" /* default program name */ +#define OUTPUT PROGNAME ".out" /* default output file */ + +static int listing=0; /* list bytecodes? */ +static int dumping=1; /* dump bytecodes? */ +static int stripping=0; /* strip debug information? */ +static char Output[]={ OUTPUT }; /* default output file name */ +static const char* output=Output; /* actual output file name */ +static const char* progname=PROGNAME; /* actual program name */ + +static void fatal(const char* message) +{ + fprintf(stderr,"%s: %s\n",progname,message); + exit(EXIT_FAILURE); +} + +static void cannot(const char* what) +{ + fprintf(stderr,"%s: cannot %s %s: %s\n",progname,what,output,strerror(errno)); + exit(EXIT_FAILURE); +} + +static void usage(const char* message) +{ + if (*message=='-') + fprintf(stderr,"%s: unrecognized option " LUA_QS "\n",progname,message); + else + fprintf(stderr,"%s: %s\n",progname,message); + fprintf(stderr, + "usage: %s [options] [filenames].\n" + "Available options are:\n" + " - process stdin\n" + " -l list\n" + " -o name output to file " LUA_QL("name") " (default is \"%s\")\n" + " -p parse only\n" + " -s strip debug information\n" + " -v show version information\n" + " -- stop handling options\n", + progname,Output); + exit(EXIT_FAILURE); +} + +#define IS(s) (strcmp(argv[i],s)==0) + +static int doargs(int argc, char* argv[]) +{ + int i; + int version=0; + if (argv[0]!=NULL && *argv[0]!=0) progname=argv[0]; + for (i=1; itop+(i))->l.p) + +static const Proto* combine(lua_State* L, int n) +{ + if (n==1) + return toproto(L,-1); + else + { + int i,pc; + Proto* f=luaF_newproto(L); + setptvalue2s(L,L->top,f); incr_top(L); + f->source=luaS_newliteral(L,"=(" PROGNAME ")"); + f->maxstacksize=1; + pc=2*n+1; + f->code=luaM_newvector(L,pc,Instruction); + f->sizecode=pc; + f->p=luaM_newvector(L,n,Proto*); + f->sizep=n; + pc=0; + for (i=0; ip[i]=toproto(L,i-n-1); + f->code[pc++]=CREATE_ABx(OP_CLOSURE,0,i); + f->code[pc++]=CREATE_ABC(OP_CALL,0,1,1); + } + f->code[pc++]=CREATE_ABC(OP_RETURN,0,1,0); + return f; + } +} + +static int writer(lua_State* L, const void* p, size_t size, void* u) +{ + UNUSED(L); + return (fwrite(p,size,1,(FILE*)u)!=1) && (size!=0); +} + +struct Smain { + int argc; + char** argv; +}; + +static int pmain(lua_State* L) +{ + struct Smain* s = (struct Smain*)lua_touserdata(L, 1); + int argc=s->argc; + char** argv=s->argv; + const Proto* f; + int i; + if (!lua_checkstack(L,argc)) fatal("too many input files"); + for (i=0; i1); + if (dumping) + { + FILE* D= (output==NULL) ? stdout : fopen(output,"wb"); + if (D==NULL) cannot("open"); + lua_lock(L); + luaU_dump(L,f,writer,D,stripping); + lua_unlock(L); + if (ferror(D)) cannot("write"); + if (fclose(D)) cannot("close"); + } + return 0; +} + +int main(int argc, char* argv[]) +{ + lua_State* L; + struct Smain s; + int i=doargs(argc,argv); + argc-=i; argv+=i; + if (argc<=0) usage("no input files given"); + L=lua_open(); + if (L==NULL) fatal("not enough memory for state"); + s.argc=argc; + s.argv=argv; + if (lua_cpcall(L,pmain,&s)!=0) fatal(lua_tostring(L,-1)); + lua_close(L); + return EXIT_SUCCESS; +} diff --git a/external/mit/lua/dist/src/luaconf.h b/external/mit/lua/dist/src/luaconf.h new file mode 100644 index 000000000..aef71c335 --- /dev/null +++ b/external/mit/lua/dist/src/luaconf.h @@ -0,0 +1,772 @@ +/* $NetBSD: luaconf.h,v 1.4 2012/03/15 01:02:19 alnsn Exp $ */ + +/* +** Id: luaconf.h,v 1.82.1.7 2008/02/11 16:25:08 roberto Exp $ +** Configuration file for Lua +** See Copyright Notice in lua.h +*/ + + +#ifndef lconfig_h +#define lconfig_h + +#include +#include + + +/* +** ================================================================== +** Search for "@@" to find all configurable definitions. +** =================================================================== +*/ + + +/* +@@ LUA_ANSI controls the use of non-ansi features. +** CHANGE it (define it) if you want Lua to avoid the use of any +** non-ansi feature or library. +*/ +#if defined(__STRICT_ANSI__) +#define LUA_ANSI +#endif + + +#if !defined(LUA_ANSI) && defined(_WIN32) +#define LUA_WIN +#endif + +#if defined(LUA_USE_LINUX) +#define LUA_USE_POSIX +#define LUA_USE_DLOPEN /* needs an extra library: -ldl */ +#define LUA_USE_READLINE /* needs some extra libraries */ +#endif + +#if defined(LUA_USE_MACOSX) +#define LUA_USE_POSIX +#define LUA_DL_DYLD /* does not need extra library */ +#endif + + + +/* +@@ LUA_USE_POSIX includes all functionallity listed as X/Open System +@* Interfaces Extension (XSI). +** CHANGE it (define it) if your system is XSI compatible. +*/ +#if defined(LUA_USE_POSIX) +#define LUA_USE_MKSTEMP +#define LUA_USE_ISATTY +#define LUA_USE_POPEN +#define LUA_USE_ULONGJMP +#endif + + +/* +@@ LUA_PATH and LUA_CPATH are the names of the environment variables that +@* Lua check to set its paths. +@@ LUA_INIT is the name of the environment variable that Lua +@* checks for initialization code. +** CHANGE them if you want different names. +*/ +#define LUA_PATH "LUA_PATH" +#define LUA_CPATH "LUA_CPATH" +#define LUA_INIT "LUA_INIT" + + +/* +@@ LUA_PATH_DEFAULT is the default path that Lua uses to look for +@* Lua libraries. +@@ LUA_CPATH_DEFAULT is the default path that Lua uses to look for +@* C libraries. +** CHANGE them if your machine has a non-conventional directory +** hierarchy or if you want to install your libraries in +** non-conventional directories. +*/ +#if defined(_WIN32) +/* +** In Windows, any exclamation mark ('!') in the path is replaced by the +** path of the directory of the executable file of the current process. +*/ +#define LUA_LDIR "!\\lua\\" +#define LUA_CDIR "!\\" +#define LUA_PATH_DEFAULT \ + ".\\?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \ + LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua" +#define LUA_CPATH_DEFAULT \ + ".\\?.dll;" LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll" + +#else +#define LUA_ROOT "/usr/" +#define LUA_LDIR LUA_ROOT "share/lua/5.1/" +#define LUA_CDIR LUA_ROOT "lib/lua/5.1/" + +/* + * The original Lua distribution contain "./?.lua" at the beginning + * of LUA_PATH_DEFAULT and "./?.so" at the beginning of LUA_CPATH_DEFAULT. + * These path elements have been removed for the NetBSD version of Lua + * to avoid potential security problems. + */ +#define LUA_PATH_DEFAULT \ + LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \ + LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua" +#define LUA_CPATH_DEFAULT \ + LUA_CDIR"?.so;" LUA_CDIR"loadall.so" +#endif + + +/* +@@ LUA_DIRSEP is the directory separator (for submodules). +** CHANGE it if your machine does not use "/" as the directory separator +** and is not Windows. (On Windows Lua automatically uses "\".) +*/ +#if defined(_WIN32) +#define LUA_DIRSEP "\\" +#else +#define LUA_DIRSEP "/" +#endif + + +/* +@@ LUA_PATHSEP is the character that separates templates in a path. +@@ LUA_PATH_MARK is the string that marks the substitution points in a +@* template. +@@ LUA_EXECDIR in a Windows path is replaced by the executable's +@* directory. +@@ LUA_IGMARK is a mark to ignore all before it when bulding the +@* luaopen_ function name. +** CHANGE them if for some reason your system cannot use those +** characters. (E.g., if one of those characters is a common character +** in file/directory names.) Probably you do not need to change them. +*/ +#define LUA_PATHSEP ";" +#define LUA_PATH_MARK "?" +#define LUA_EXECDIR "!" +#define LUA_IGMARK "-" + + +/* +@@ LUA_INTEGER is the integral type used by lua_pushinteger/lua_tointeger. +** CHANGE that if ptrdiff_t is not adequate on your machine. (On most +** machines, ptrdiff_t gives a good choice between int or long.) +*/ +#define LUA_INTEGER ptrdiff_t + + +/* +@@ LUA_API is a mark for all core API functions. +@@ LUALIB_API is a mark for all standard library functions. +** CHANGE them if you need to define those functions in some special way. +** For instance, if you want to create one Windows DLL with the core and +** the libraries, you may want to use the following definition (define +** LUA_BUILD_AS_DLL to get it). +*/ +#if defined(LUA_BUILD_AS_DLL) + +#if defined(LUA_CORE) || defined(LUA_LIB) +#define LUA_API __declspec(dllexport) +#else +#define LUA_API __declspec(dllimport) +#endif + +#else + +#define LUA_API extern + +#endif + +/* more often than not the libs go together with the core */ +#define LUALIB_API LUA_API + + +/* +@@ LUAI_FUNC is a mark for all extern functions that are not to be +@* exported to outside modules. +@@ LUAI_DATA is a mark for all extern (const) variables that are not to +@* be exported to outside modules. +** CHANGE them if you need to mark them in some special way. Elf/gcc +** (versions 3.2 and later) mark them as "hidden" to optimize access +** when Lua is compiled as a shared library. +*/ +#if defined(luaall_c) +#define LUAI_FUNC static +#define LUAI_DATA /* empty */ + +#elif defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \ + defined(__ELF__) +#define LUAI_FUNC __attribute__((visibility("hidden"))) extern +#define LUAI_DATA LUAI_FUNC + +#else +#define LUAI_FUNC extern +#define LUAI_DATA extern +#endif + + + +/* +@@ LUA_QL describes how error messages quote program elements. +** CHANGE it if you want a different appearance. +*/ +#define LUA_QL(x) "'" x "'" +#define LUA_QS LUA_QL("%s") + + +/* +@@ LUA_IDSIZE gives the maximum size for the description of the source +@* of a function in debug information. +** CHANGE it if you want a different size. +*/ +#define LUA_IDSIZE 60 + + +/* +** {================================================================== +** Stand-alone configuration +** =================================================================== +*/ + +#if defined(lua_c) || defined(luaall_c) + +/* +@@ lua_stdin_is_tty detects whether the standard input is a 'tty' (that +@* is, whether we're running lua interactively). +** CHANGE it if you have a better definition for non-POSIX/non-Windows +** systems. +*/ +#if defined(LUA_USE_ISATTY) +#include +#define lua_stdin_is_tty() isatty(0) +#elif defined(LUA_WIN) +#include +#include +#define lua_stdin_is_tty() _isatty(_fileno(stdin)) +#else +#define lua_stdin_is_tty() 1 /* assume stdin is a tty */ +#endif + + +/* +@@ LUA_PROMPT is the default prompt used by stand-alone Lua. +@@ LUA_PROMPT2 is the default continuation prompt used by stand-alone Lua. +** CHANGE them if you want different prompts. (You can also change the +** prompts dynamically, assigning to globals _PROMPT/_PROMPT2.) +*/ +#define LUA_PROMPT "> " +#define LUA_PROMPT2 ">> " + + +/* +@@ LUA_PROGNAME is the default name for the stand-alone Lua program. +** CHANGE it if your stand-alone interpreter has a different name and +** your system is not able to detect that name automatically. +*/ +#define LUA_PROGNAME "lua" + + +/* +@@ LUA_MAXINPUT is the maximum length for an input line in the +@* stand-alone interpreter. +** CHANGE it if you need longer lines. +*/ +#define LUA_MAXINPUT 512 + + +/* +@@ lua_readline defines how to show a prompt and then read a line from +@* the standard input. +@@ lua_saveline defines how to "save" a read line in a "history". +@@ lua_freeline defines how to free a line read by lua_readline. +** CHANGE them if you want to improve this functionality (e.g., by using +** GNU readline and history facilities). +*/ +#if defined(LUA_USE_READLINE) +#include +#include +#include +#define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL) +#define lua_saveline(L,idx) \ + if (lua_strlen(L,idx) > 0) /* non-empty line? */ \ + add_history(lua_tostring(L, idx)); /* add it to history */ +#define lua_freeline(L,b) ((void)L, free(b)) +#else +#define lua_readline(L,b,p) \ + ((void)L, fputs(p, stdout), fflush(stdout), /* show prompt */ \ + fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */ +#define lua_saveline(L,idx) { (void)L; (void)idx; } +#define lua_freeline(L,b) { (void)L; (void)b; } +#endif + +#endif + +/* }================================================================== */ + + +/* +@@ LUAI_GCPAUSE defines the default pause between garbage-collector cycles +@* as a percentage. +** CHANGE it if you want the GC to run faster or slower (higher values +** mean larger pauses which mean slower collection.) You can also change +** this value dynamically. +*/ +#define LUAI_GCPAUSE 200 /* 200% (wait memory to double before next GC) */ + + +/* +@@ LUAI_GCMUL defines the default speed of garbage collection relative to +@* memory allocation as a percentage. +** CHANGE it if you want to change the granularity of the garbage +** collection. (Higher values mean coarser collections. 0 represents +** infinity, where each step performs a full collection.) You can also +** change this value dynamically. +*/ +#define LUAI_GCMUL 200 /* GC runs 'twice the speed' of memory allocation */ + + + +/* +@@ LUA_COMPAT_GETN controls compatibility with old getn behavior. +** CHANGE it (define it) if you want exact compatibility with the +** behavior of setn/getn in Lua 5.0. +*/ +#undef LUA_COMPAT_GETN + +/* +@@ LUA_COMPAT_LOADLIB controls compatibility about global loadlib. +** CHANGE it to undefined as soon as you do not need a global 'loadlib' +** function (the function is still available as 'package.loadlib'). +*/ +#undef LUA_COMPAT_LOADLIB + +/* +@@ LUA_COMPAT_VARARG controls compatibility with old vararg feature. +** CHANGE it to undefined as soon as your programs use only '...' to +** access vararg parameters (instead of the old 'arg' table). +*/ +#define LUA_COMPAT_VARARG + +/* +@@ LUA_COMPAT_MOD controls compatibility with old math.mod function. +** CHANGE it to undefined as soon as your programs use 'math.fmod' or +** the new '%' operator instead of 'math.mod'. +*/ +#define LUA_COMPAT_MOD + +/* +@@ LUA_COMPAT_LSTR controls compatibility with old long string nesting +@* facility. +** CHANGE it to 2 if you want the old behaviour, or undefine it to turn +** off the advisory error when nesting [[...]]. +*/ +#define LUA_COMPAT_LSTR 1 + +/* +@@ LUA_COMPAT_GFIND controls compatibility with old 'string.gfind' name. +** CHANGE it to undefined as soon as you rename 'string.gfind' to +** 'string.gmatch'. +*/ +#define LUA_COMPAT_GFIND + +/* +@@ LUA_COMPAT_OPENLIB controls compatibility with old 'luaL_openlib' +@* behavior. +** CHANGE it to undefined as soon as you replace to 'luaL_register' +** your uses of 'luaL_openlib' +*/ +#define LUA_COMPAT_OPENLIB + + + +/* +@@ luai_apicheck is the assert macro used by the Lua-C API. +** CHANGE luai_apicheck if you want Lua to perform some checks in the +** parameters it gets from API calls. This may slow down the interpreter +** a bit, but may be quite useful when debugging C code that interfaces +** with Lua. A useful redefinition is to use assert.h. +*/ +#if defined(LUA_USE_APICHECK) +#include +#define luai_apicheck(L,o) { (void)L; assert(o); } +#else +#define luai_apicheck(L,o) { (void)L; } +#endif + + +/* +@@ LUAI_BITSINT defines the number of bits in an int. +** CHANGE here if Lua cannot automatically detect the number of bits of +** your machine. Probably you do not need to change this. +*/ +/* avoid overflows in comparison */ +#if INT_MAX-20 < 32760 +#define LUAI_BITSINT 16 +#elif INT_MAX > 2147483640L +/* int has at least 32 bits */ +#define LUAI_BITSINT 32 +#else +#error "you must define LUA_BITSINT with number of bits in an integer" +#endif + + +/* +@@ LUAI_UINT32 is an unsigned integer with at least 32 bits. +@@ LUAI_INT32 is an signed integer with at least 32 bits. +@@ LUAI_UMEM is an unsigned integer big enough to count the total +@* memory used by Lua. +@@ LUAI_MEM is a signed integer big enough to count the total memory +@* used by Lua. +** CHANGE here if for some weird reason the default definitions are not +** good enough for your machine. (The definitions in the 'else' +** part always works, but may waste space on machines with 64-bit +** longs.) Probably you do not need to change this. +*/ +#if LUAI_BITSINT >= 32 +#define LUAI_UINT32 unsigned int +#define LUAI_INT32 int +#define LUAI_MAXINT32 INT_MAX +#define LUAI_UMEM size_t +#define LUAI_MEM ptrdiff_t +#else +/* 16-bit ints */ +#define LUAI_UINT32 unsigned long +#define LUAI_INT32 long +#define LUAI_MAXINT32 LONG_MAX +#define LUAI_UMEM unsigned long +#define LUAI_MEM long +#endif + + +/* +@@ LUAI_MAXCALLS limits the number of nested calls. +** CHANGE it if you need really deep recursive calls. This limit is +** arbitrary; its only purpose is to stop infinite recursion before +** exhausting memory. +*/ +#define LUAI_MAXCALLS 20000 + + +/* +@@ LUAI_MAXCSTACK limits the number of Lua stack slots that a C function +@* can use. +** CHANGE it if you need lots of (Lua) stack space for your C +** functions. This limit is arbitrary; its only purpose is to stop C +** functions to consume unlimited stack space. (must be smaller than +** -LUA_REGISTRYINDEX) +*/ +#define LUAI_MAXCSTACK 8000 + + + +/* +** {================================================================== +** CHANGE (to smaller values) the following definitions if your system +** has a small C stack. (Or you may want to change them to larger +** values if your system has a large C stack and these limits are +** too rigid for you.) Some of these constants control the size of +** stack-allocated arrays used by the compiler or the interpreter, while +** others limit the maximum number of recursive calls that the compiler +** or the interpreter can perform. Values too large may cause a C stack +** overflow for some forms of deep constructs. +** =================================================================== +*/ + + +/* +@@ LUAI_MAXCCALLS is the maximum depth for nested C calls (short) and +@* syntactical nested non-terminals in a program. +*/ +#define LUAI_MAXCCALLS 200 + + +/* +@@ LUAI_MAXVARS is the maximum number of local variables per function +@* (must be smaller than 250). +*/ +#define LUAI_MAXVARS 200 + + +/* +@@ LUAI_MAXUPVALUES is the maximum number of upvalues per function +@* (must be smaller than 250). +*/ +#define LUAI_MAXUPVALUES 60 + + +/* +@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system. +*/ +#define LUAL_BUFFERSIZE BUFSIZ + +/* }================================================================== */ + + + + +/* +** {================================================================== +@@ LUA_NUMBER is the type of numbers in Lua. +** CHANGE the following definitions only if you want to build Lua +** with a number type different from double. You may also need to +** change lua_number2int & lua_number2integer. +** =================================================================== +*/ + +#define LUA_NUMBER_DOUBLE +#define LUA_NUMBER double + +/* +@@ LUAI_UACNUMBER is the result of an 'usual argument conversion' +@* over a number. +*/ +#define LUAI_UACNUMBER double + + +/* +@@ LUA_NUMBER_SCAN is the format for reading numbers. +@@ LUA_NUMBER_FMT is the format for writing numbers. +@@ lua_number2str converts a number to a string. +@@ LUAI_MAXNUMBER2STR is maximum size of previous conversion. +@@ lua_str2number converts a string to a number. +*/ +#define LUA_NUMBER_SCAN "%lf" +#define LUA_NUMBER_FMT "%.14g" +#define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n)) +#define LUAI_MAXNUMBER2STR 32 /* 16 digits, sign, point, and \0 */ +#define lua_str2number(s,p) strtod((s), (p)) + + +/* +@@ The luai_num* macros define the primitive operations over numbers. +*/ +#if defined(LUA_CORE) +#include +#define luai_numadd(a,b) ((a)+(b)) +#define luai_numsub(a,b) ((a)-(b)) +#define luai_nummul(a,b) ((a)*(b)) +#define luai_numdiv(a,b) ((a)/(b)) +#define luai_nummod(a,b) ((a) - floor((a)/(b))*(b)) +#define luai_numpow(a,b) (pow(a,b)) +#define luai_numunm(a) (-(a)) +#define luai_numeq(a,b) ((a)==(b)) +#define luai_numlt(a,b) ((a)<(b)) +#define luai_numle(a,b) ((a)<=(b)) +#define luai_numisnan(a) (!luai_numeq((a), (a))) +#endif + + +/* +@@ lua_number2int is a macro to convert lua_Number to int. +@@ lua_number2integer is a macro to convert lua_Number to lua_Integer. +** CHANGE them if you know a faster way to convert a lua_Number to +** int (with any rounding method and without throwing errors) in your +** system. In Pentium machines, a naive typecast from double to int +** in C is extremely slow, so any alternative is worth trying. +*/ + +/* On a Pentium, resort to a trick */ +#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) && !defined(__SSE2__) && \ + (defined(__i386) || defined (_M_IX86) || defined(__i386__)) + +/* On a Microsoft compiler, use assembler */ +#if defined(_MSC_VER) + +#define lua_number2int(i,d) __asm fld d __asm fistp i +#define lua_number2integer(i,n) lua_number2int(i, n) + +/* the next trick should work on any Pentium, but sometimes clashes + with a DirectX idiosyncrasy */ +#else + +union luai_Cast { double l_d; long l_l; }; +#define lua_number2int(i,d) \ + { volatile union luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; } +#define lua_number2integer(i,n) lua_number2int(i, n) + +#endif + + +/* this option always works, but may be slow */ +#else +#define lua_number2int(i,d) ((i)=(int)(d)) +#define lua_number2integer(i,d) ((i)=(lua_Integer)(d)) + +#endif + +/* }================================================================== */ + + +/* +@@ LUAI_USER_ALIGNMENT_T is a type that requires maximum alignment. +** CHANGE it if your system requires alignments larger than double. (For +** instance, if your system supports long doubles and they must be +** aligned in 16-byte boundaries, then you should add long double in the +** union.) Probably you do not need to change this. +*/ +#define LUAI_USER_ALIGNMENT_T union { double u; void *s; long l; } + + +/* +@@ LUAI_THROW/LUAI_TRY define how Lua does exception handling. +** CHANGE them if you prefer to use longjmp/setjmp even with C++ +** or if want/don't to use _longjmp/_setjmp instead of regular +** longjmp/setjmp. By default, Lua handles errors with exceptions when +** compiling as C++ code, with _longjmp/_setjmp when asked to use them, +** and with longjmp/setjmp otherwise. +*/ +#if defined(__cplusplus) +/* C++ exceptions */ +#define LUAI_THROW(L,c) throw(c) +#define LUAI_TRY(L,c,a) try { a } catch(...) \ + { if ((c)->status == 0) (c)->status = -1; } +#define luai_jmpbuf int /* dummy variable */ + +#elif defined(LUA_USE_ULONGJMP) +/* in Unix, try _longjmp/_setjmp (more efficient) */ +#define LUAI_THROW(L,c) _longjmp((c)->b, 1) +#define LUAI_TRY(L,c,a) if (_setjmp((c)->b) == 0) { a } +#define luai_jmpbuf jmp_buf + +#else +/* default handling with long jumps */ +#define LUAI_THROW(L,c) longjmp((c)->b, 1) +#define LUAI_TRY(L,c,a) if (setjmp((c)->b) == 0) { a } +#define luai_jmpbuf jmp_buf + +#endif + + +/* +@@ LUA_MAXCAPTURES is the maximum number of captures that a pattern +@* can do during pattern-matching. +** CHANGE it if you need more captures. This limit is arbitrary. +*/ +#define LUA_MAXCAPTURES 32 + + +/* +@@ lua_tmpnam is the function that the OS library uses to create a +@* temporary name. +@@ LUA_TMPNAMBUFSIZE is the maximum size of a name created by lua_tmpnam. +** CHANGE them if you have an alternative to tmpnam (which is considered +** insecure) or if you want the original tmpnam anyway. By default, Lua +** uses tmpnam except when POSIX is available, where it uses mkstemp. +*/ +#if defined(loslib_c) || defined(luaall_c) + +#if defined(LUA_USE_MKSTEMP) +#include +#define LUA_TMPNAMBUFSIZE 32 +#define lua_tmpnam(b,e) { \ + strcpy(b, "/tmp/lua_XXXXXX"); \ + e = mkstemp(b); \ + if (e != -1) close(e); \ + e = (e == -1); } + +#else +#define LUA_TMPNAMBUFSIZE L_tmpnam +#define lua_tmpnam(b,e) { e = (tmpnam(b) == NULL); } +#endif + +#endif + + +/* +@@ lua_popen spawns a new process connected to the current one through +@* the file streams. +** CHANGE it if you have a way to implement it in your system. +*/ +#if defined(LUA_USE_POPEN) + +#define lua_popen(L,c,m) ((void)L, fflush(NULL), popen(c,m)) +#define lua_pclose(L,file) ((void)L, (pclose(file) != -1)) + +#elif defined(LUA_WIN) + +#define lua_popen(L,c,m) ((void)L, _popen(c,m)) +#define lua_pclose(L,file) ((void)L, (_pclose(file) != -1)) + +#else + +#define lua_popen(L,c,m) ((void)((void)c, m), \ + luaL_error(L, LUA_QL("popen") " not supported"), (FILE*)0) +#define lua_pclose(L,file) ((void)((void)L, file), 0) + +#endif + +/* +@@ LUA_DL_* define which dynamic-library system Lua should use. +** CHANGE here if Lua has problems choosing the appropriate +** dynamic-library system for your platform (either Windows' DLL, Mac's +** dyld, or Unix's dlopen). If your system is some kind of Unix, there +** is a good chance that it has dlopen, so LUA_DL_DLOPEN will work for +** it. To use dlopen you also need to adapt the src/Makefile (probably +** adding -ldl to the linker options), so Lua does not select it +** automatically. (When you change the makefile to add -ldl, you must +** also add -DLUA_USE_DLOPEN.) +** If you do not want any kind of dynamic library, undefine all these +** options. +** By default, _WIN32 gets LUA_DL_DLL and MAC OS X gets LUA_DL_DYLD. +*/ +#if defined(LUA_USE_DLOPEN) +#define LUA_DL_DLOPEN +#endif + +#if defined(LUA_WIN) +#define LUA_DL_DLL +#endif + + +/* +@@ LUAI_EXTRASPACE allows you to add user-specific data in a lua_State +@* (the data goes just *before* the lua_State pointer). +** CHANGE (define) this if you really need that. This value must be +** a multiple of the maximum alignment required for your machine. +*/ +#define LUAI_EXTRASPACE 0 + + +/* +@@ luai_userstate* allow user-specific actions on threads. +** CHANGE them if you defined LUAI_EXTRASPACE and need to do something +** extra when a thread is created/deleted/resumed/yielded. +*/ +#define luai_userstateopen(L) ((void)L) +#define luai_userstateclose(L) ((void)L) +#define luai_userstatethread(L,L1) ((void)L) +#define luai_userstatefree(L) ((void)L) +#define luai_userstateresume(L,n) ((void)L) +#define luai_userstateyield(L,n) ((void)L) + + +/* +@@ LUA_INTFRMLEN is the length modifier for integer conversions +@* in 'string.format'. +@@ LUA_INTFRM_T is the integer type correspoding to the previous length +@* modifier. +** CHANGE them if your system supports long long or does not support long. +*/ + +#if defined(LUA_USELONGLONG) + +#define LUA_INTFRMLEN "ll" +#define LUA_INTFRM_T long long + +#else + +#define LUA_INTFRMLEN "l" +#define LUA_INTFRM_T long + +#endif + + + +/* =================================================================== */ + +/* +** Local configuration. You can use this space to add your redefinitions +** without modifying the main part of the file. +*/ + + + +#endif + diff --git a/external/mit/lua/dist/src/lualib.h b/external/mit/lua/dist/src/lualib.h new file mode 100644 index 000000000..b307a80d7 --- /dev/null +++ b/external/mit/lua/dist/src/lualib.h @@ -0,0 +1,55 @@ +/* $NetBSD: lualib.h,v 1.1.1.2 2012/03/15 00:08:10 alnsn Exp $ */ + +/* +** $Id: lualib.h,v 1.1.1.2 2012/03/15 00:08:10 alnsn Exp $ +** Lua standard libraries +** See Copyright Notice in lua.h +*/ + + +#ifndef lualib_h +#define lualib_h + +#include "lua.h" + + +/* Key to file-handle type */ +#define LUA_FILEHANDLE "FILE*" + + +#define LUA_COLIBNAME "coroutine" +LUALIB_API int (luaopen_base) (lua_State *L); + +#define LUA_TABLIBNAME "table" +LUALIB_API int (luaopen_table) (lua_State *L); + +#define LUA_IOLIBNAME "io" +LUALIB_API int (luaopen_io) (lua_State *L); + +#define LUA_OSLIBNAME "os" +LUALIB_API int (luaopen_os) (lua_State *L); + +#define LUA_STRLIBNAME "string" +LUALIB_API int (luaopen_string) (lua_State *L); + +#define LUA_MATHLIBNAME "math" +LUALIB_API int (luaopen_math) (lua_State *L); + +#define LUA_DBLIBNAME "debug" +LUALIB_API int (luaopen_debug) (lua_State *L); + +#define LUA_LOADLIBNAME "package" +LUALIB_API int (luaopen_package) (lua_State *L); + + +/* open all previous libraries */ +LUALIB_API void (luaL_openlibs) (lua_State *L); + + + +#ifndef lua_assert +#define lua_assert(x) ((void)0) +#endif + + +#endif diff --git a/external/mit/lua/dist/src/lundump.c b/external/mit/lua/dist/src/lundump.c new file mode 100644 index 000000000..fe84b5dbb --- /dev/null +++ b/external/mit/lua/dist/src/lundump.c @@ -0,0 +1,229 @@ +/* $NetBSD: lundump.c,v 1.1.1.2 2012/03/15 00:08:14 alnsn Exp $ */ + +/* +** $Id: lundump.c,v 1.1.1.2 2012/03/15 00:08:14 alnsn Exp $ +** load precompiled Lua chunks +** See Copyright Notice in lua.h +*/ + +#include + +#define lundump_c +#define LUA_CORE + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lmem.h" +#include "lobject.h" +#include "lstring.h" +#include "lundump.h" +#include "lzio.h" + +typedef struct { + lua_State* L; + ZIO* Z; + Mbuffer* b; + const char* name; +} LoadState; + +#ifdef LUAC_TRUST_BINARIES +#define IF(c,s) +#define error(S,s) +#else +#define IF(c,s) if (c) error(S,s) + +static void error(LoadState* S, const char* why) +{ + luaO_pushfstring(S->L,"%s: %s in precompiled chunk",S->name,why); + luaD_throw(S->L,LUA_ERRSYNTAX); +} +#endif + +#define LoadMem(S,b,n,size) LoadBlock(S,b,(n)*(size)) +#define LoadByte(S) (lu_byte)LoadChar(S) +#define LoadVar(S,x) LoadMem(S,&x,1,sizeof(x)) +#define LoadVector(S,b,n,size) LoadMem(S,b,n,size) + +static void LoadBlock(LoadState* S, void* b, size_t size) +{ + size_t r=luaZ_read(S->Z,b,size); + IF (r!=0, "unexpected end"); +} + +static int LoadChar(LoadState* S) +{ + char x; + LoadVar(S,x); + return x; +} + +static int LoadInt(LoadState* S) +{ + int x; + LoadVar(S,x); + IF (x<0, "bad integer"); + return x; +} + +static lua_Number LoadNumber(LoadState* S) +{ + lua_Number x; + LoadVar(S,x); + return x; +} + +static TString* LoadString(LoadState* S) +{ + size_t size; + LoadVar(S,size); + if (size==0) + return NULL; + else + { + char* s=luaZ_openspace(S->L,S->b,size); + LoadBlock(S,s,size); + return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */ + } +} + +static void LoadCode(LoadState* S, Proto* f) +{ + int n=LoadInt(S); + f->code=luaM_newvector(S->L,n,Instruction); + f->sizecode=n; + LoadVector(S,f->code,n,sizeof(Instruction)); +} + +static Proto* LoadFunction(LoadState* S, TString* p); + +static void LoadConstants(LoadState* S, Proto* f) +{ + int i,n; + n=LoadInt(S); + f->k=luaM_newvector(S->L,n,TValue); + f->sizek=n; + for (i=0; ik[i]); + for (i=0; ik[i]; + int t=LoadChar(S); + switch (t) + { + case LUA_TNIL: + setnilvalue(o); + break; + case LUA_TBOOLEAN: + setbvalue(o,LoadChar(S)!=0); + break; + case LUA_TNUMBER: + setnvalue(o,LoadNumber(S)); + break; + case LUA_TSTRING: + setsvalue2n(S->L,o,LoadString(S)); + break; + default: + error(S,"bad constant"); + break; + } + } + n=LoadInt(S); + f->p=luaM_newvector(S->L,n,Proto*); + f->sizep=n; + for (i=0; ip[i]=NULL; + for (i=0; ip[i]=LoadFunction(S,f->source); +} + +static void LoadDebug(LoadState* S, Proto* f) +{ + int i,n; + n=LoadInt(S); + f->lineinfo=luaM_newvector(S->L,n,int); + f->sizelineinfo=n; + LoadVector(S,f->lineinfo,n,sizeof(int)); + n=LoadInt(S); + f->locvars=luaM_newvector(S->L,n,LocVar); + f->sizelocvars=n; + for (i=0; ilocvars[i].varname=NULL; + for (i=0; ilocvars[i].varname=LoadString(S); + f->locvars[i].startpc=LoadInt(S); + f->locvars[i].endpc=LoadInt(S); + } + n=LoadInt(S); + f->upvalues=luaM_newvector(S->L,n,TString*); + f->sizeupvalues=n; + for (i=0; iupvalues[i]=NULL; + for (i=0; iupvalues[i]=LoadString(S); +} + +static Proto* LoadFunction(LoadState* S, TString* p) +{ + Proto* f; + if (++S->L->nCcalls > LUAI_MAXCCALLS) error(S,"code too deep"); + f=luaF_newproto(S->L); + setptvalue2s(S->L,S->L->top,f); incr_top(S->L); + f->source=LoadString(S); if (f->source==NULL) f->source=p; + f->linedefined=LoadInt(S); + f->lastlinedefined=LoadInt(S); + f->nups=LoadByte(S); + f->numparams=LoadByte(S); + f->is_vararg=LoadByte(S); + f->maxstacksize=LoadByte(S); + LoadCode(S,f); + LoadConstants(S,f); + LoadDebug(S,f); + IF (!luaG_checkcode(f), "bad code"); + S->L->top--; + S->L->nCcalls--; + return f; +} + +static void LoadHeader(LoadState* S) +{ + char h[LUAC_HEADERSIZE]; + char s[LUAC_HEADERSIZE]; + luaU_header(h); + LoadBlock(S,s,LUAC_HEADERSIZE); + IF (memcmp(h,s,LUAC_HEADERSIZE)!=0, "bad header"); +} + +/* +** load precompiled chunk +*/ +Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name) +{ + LoadState S; + if (*name=='@' || *name=='=') + S.name=name+1; + else if (*name==LUA_SIGNATURE[0]) + S.name="binary string"; + else + S.name=name; + S.L=L; + S.Z=Z; + S.b=buff; + LoadHeader(&S); + return LoadFunction(&S,luaS_newliteral(L,"=?")); +} + +/* +* make header +*/ +void luaU_header (char* h) +{ + int x=1; + memcpy(h,LUA_SIGNATURE,sizeof(LUA_SIGNATURE)-1); + h+=sizeof(LUA_SIGNATURE)-1; + *h++=(char)LUAC_VERSION; + *h++=(char)LUAC_FORMAT; + *h++=(char)*(char*)&x; /* endianness */ + *h++=(char)sizeof(int); + *h++=(char)sizeof(size_t); + *h++=(char)sizeof(Instruction); + *h++=(char)sizeof(lua_Number); + *h++=(char)(((lua_Number)0.5)==0); /* is lua_Number integral? */ +} diff --git a/external/mit/lua/dist/src/lundump.h b/external/mit/lua/dist/src/lundump.h new file mode 100644 index 000000000..e49af4018 --- /dev/null +++ b/external/mit/lua/dist/src/lundump.h @@ -0,0 +1,38 @@ +/* $NetBSD: lundump.h,v 1.1.1.2 2012/03/15 00:08:04 alnsn Exp $ */ + +/* +** $Id: lundump.h,v 1.1.1.2 2012/03/15 00:08:04 alnsn Exp $ +** load precompiled Lua chunks +** See Copyright Notice in lua.h +*/ + +#ifndef lundump_h +#define lundump_h + +#include "lobject.h" +#include "lzio.h" + +/* load one chunk; from lundump.c */ +LUAI_FUNC Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name); + +/* make header; from lundump.c */ +LUAI_FUNC void luaU_header (char* h); + +/* dump one chunk; from ldump.c */ +LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip); + +#ifdef luac_c +/* print one chunk; from print.c */ +LUAI_FUNC void luaU_print (const Proto* f, int full); +#endif + +/* for header of binary files -- this is Lua 5.1 */ +#define LUAC_VERSION 0x51 + +/* for header of binary files -- this is the official format */ +#define LUAC_FORMAT 0 + +/* size of header of binary files */ +#define LUAC_HEADERSIZE 12 + +#endif diff --git a/external/mit/lua/dist/src/lvm.c b/external/mit/lua/dist/src/lvm.c new file mode 100644 index 000000000..e08300889 --- /dev/null +++ b/external/mit/lua/dist/src/lvm.c @@ -0,0 +1,769 @@ +/* $NetBSD: lvm.c,v 1.1.1.2 2012/03/15 00:08:05 alnsn Exp $ */ + +/* +** $Id: lvm.c,v 1.1.1.2 2012/03/15 00:08:05 alnsn Exp $ +** Lua virtual machine +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include + +#define lvm_c +#define LUA_CORE + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lgc.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" +#include "lvm.h" + + + +/* limit for table tag-method chains (to avoid loops) */ +#define MAXTAGLOOP 100 + + +const TValue *luaV_tonumber (const TValue *obj, TValue *n) { + lua_Number num; + if (ttisnumber(obj)) return obj; + if (ttisstring(obj) && luaO_str2d(svalue(obj), &num)) { + setnvalue(n, num); + return n; + } + else + return NULL; +} + + +int luaV_tostring (lua_State *L, StkId obj) { + if (!ttisnumber(obj)) + return 0; + else { + char s[LUAI_MAXNUMBER2STR]; + lua_Number n = nvalue(obj); + lua_number2str(s, n); + setsvalue2s(L, obj, luaS_new(L, s)); + return 1; + } +} + + +static void traceexec (lua_State *L, const Instruction *pc) { + lu_byte mask = L->hookmask; + const Instruction *oldpc = L->savedpc; + L->savedpc = pc; + if ((mask & LUA_MASKCOUNT) && L->hookcount == 0) { + resethookcount(L); + luaD_callhook(L, LUA_HOOKCOUNT, -1); + } + if (mask & LUA_MASKLINE) { + Proto *p = ci_func(L->ci)->l.p; + int npc = pcRel(pc, p); + int newline = getline(p, npc); + /* call linehook when enter a new function, when jump back (loop), + or when enter a new line */ + if (npc == 0 || pc <= oldpc || newline != getline(p, pcRel(oldpc, p))) + luaD_callhook(L, LUA_HOOKLINE, newline); + } +} + + +static void callTMres (lua_State *L, StkId res, const TValue *f, + const TValue *p1, const TValue *p2) { + ptrdiff_t result = savestack(L, res); + setobj2s(L, L->top, f); /* push function */ + setobj2s(L, L->top+1, p1); /* 1st argument */ + setobj2s(L, L->top+2, p2); /* 2nd argument */ + luaD_checkstack(L, 3); + L->top += 3; + luaD_call(L, L->top - 3, 1); + res = restorestack(L, result); + L->top--; + setobjs2s(L, res, L->top); +} + + + +static void callTM (lua_State *L, const TValue *f, const TValue *p1, + const TValue *p2, const TValue *p3) { + setobj2s(L, L->top, f); /* push function */ + setobj2s(L, L->top+1, p1); /* 1st argument */ + setobj2s(L, L->top+2, p2); /* 2nd argument */ + setobj2s(L, L->top+3, p3); /* 3th argument */ + luaD_checkstack(L, 4); + L->top += 4; + luaD_call(L, L->top - 4, 0); +} + + +void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) { + int loop; + for (loop = 0; loop < MAXTAGLOOP; loop++) { + const TValue *tm; + if (ttistable(t)) { /* `t' is a table? */ + Table *h = hvalue(t); + const TValue *res = luaH_get(h, key); /* do a primitive get */ + if (!ttisnil(res) || /* result is no nil? */ + (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */ + setobj2s(L, val, res); + return; + } + /* else will try the tag method */ + } + else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX))) + luaG_typeerror(L, t, "index"); + if (ttisfunction(tm)) { + callTMres(L, val, tm, t, key); + return; + } + t = tm; /* else repeat with `tm' */ + } + luaG_runerror(L, "loop in gettable"); +} + + +void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { + int loop; + TValue temp; + for (loop = 0; loop < MAXTAGLOOP; loop++) { + const TValue *tm; + if (ttistable(t)) { /* `t' is a table? */ + Table *h = hvalue(t); + TValue *oldval = luaH_set(L, h, key); /* do a primitive set */ + if (!ttisnil(oldval) || /* result is no nil? */ + (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */ + setobj2t(L, oldval, val); + h->flags = 0; + luaC_barriert(L, h, val); + return; + } + /* else will try the tag method */ + } + else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) + luaG_typeerror(L, t, "index"); + if (ttisfunction(tm)) { + callTM(L, tm, t, key, val); + return; + } + /* else repeat with `tm' */ + setobj(L, &temp, tm); /* avoid pointing inside table (may rehash) */ + t = &temp; + } + luaG_runerror(L, "loop in settable"); +} + + +static int call_binTM (lua_State *L, const TValue *p1, const TValue *p2, + StkId res, TMS event) { + const TValue *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */ + if (ttisnil(tm)) + tm = luaT_gettmbyobj(L, p2, event); /* try second operand */ + if (ttisnil(tm)) return 0; + callTMres(L, res, tm, p1, p2); + return 1; +} + + +static const TValue *get_compTM (lua_State *L, Table *mt1, Table *mt2, + TMS event) { + const TValue *tm1 = fasttm(L, mt1, event); + const TValue *tm2; + if (tm1 == NULL) return NULL; /* no metamethod */ + if (mt1 == mt2) return tm1; /* same metatables => same metamethods */ + tm2 = fasttm(L, mt2, event); + if (tm2 == NULL) return NULL; /* no metamethod */ + if (luaO_rawequalObj(tm1, tm2)) /* same metamethods? */ + return tm1; + return NULL; +} + + +static int call_orderTM (lua_State *L, const TValue *p1, const TValue *p2, + TMS event) { + const TValue *tm1 = luaT_gettmbyobj(L, p1, event); + const TValue *tm2; + if (ttisnil(tm1)) return -1; /* no metamethod? */ + tm2 = luaT_gettmbyobj(L, p2, event); + if (!luaO_rawequalObj(tm1, tm2)) /* different metamethods? */ + return -1; + callTMres(L, L->top, tm1, p1, p2); + return !l_isfalse(L->top); +} + + +static int l_strcmp (const TString *ls, const TString *rs) { + const char *l = getstr(ls); + size_t ll = ls->tsv.len; + const char *r = getstr(rs); + size_t lr = rs->tsv.len; + for (;;) { + int temp = strcoll(l, r); + if (temp != 0) return temp; + else { /* strings are equal up to a `\0' */ + size_t len = strlen(l); /* index of first `\0' in both strings */ + if (len == lr) /* r is finished? */ + return (len == ll) ? 0 : 1; + else if (len == ll) /* l is finished? */ + return -1; /* l is smaller than r (because r is not finished) */ + /* both strings longer than `len'; go on comparing (after the `\0') */ + len++; + l += len; ll -= len; r += len; lr -= len; + } + } +} + + +int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) { + int res; + if (ttype(l) != ttype(r)) + return luaG_ordererror(L, l, r); + else if (ttisnumber(l)) + return luai_numlt(nvalue(l), nvalue(r)); + else if (ttisstring(l)) + return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0; + else if ((res = call_orderTM(L, l, r, TM_LT)) != -1) + return res; + return luaG_ordererror(L, l, r); +} + + +static int lessequal (lua_State *L, const TValue *l, const TValue *r) { + int res; + if (ttype(l) != ttype(r)) + return luaG_ordererror(L, l, r); + else if (ttisnumber(l)) + return luai_numle(nvalue(l), nvalue(r)); + else if (ttisstring(l)) + return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0; + else if ((res = call_orderTM(L, l, r, TM_LE)) != -1) /* first try `le' */ + return res; + else if ((res = call_orderTM(L, r, l, TM_LT)) != -1) /* else try `lt' */ + return !res; + return luaG_ordererror(L, l, r); +} + + +int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2) { + const TValue *tm; + lua_assert(ttype(t1) == ttype(t2)); + switch (ttype(t1)) { + case LUA_TNIL: return 1; + case LUA_TNUMBER: return luai_numeq(nvalue(t1), nvalue(t2)); + case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */ + case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2); + case LUA_TUSERDATA: { + if (uvalue(t1) == uvalue(t2)) return 1; + tm = get_compTM(L, uvalue(t1)->metatable, uvalue(t2)->metatable, + TM_EQ); + break; /* will try TM */ + } + case LUA_TTABLE: { + if (hvalue(t1) == hvalue(t2)) return 1; + tm = get_compTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ); + break; /* will try TM */ + } + default: return gcvalue(t1) == gcvalue(t2); + } + if (tm == NULL) return 0; /* no TM? */ + callTMres(L, L->top, tm, t1, t2); /* call TM */ + return !l_isfalse(L->top); +} + + +void luaV_concat (lua_State *L, int total, int last) { + do { + StkId top = L->base + last + 1; + int n = 2; /* number of elements handled in this pass (at least 2) */ + if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) { + if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT)) + luaG_concaterror(L, top-2, top-1); + } else if (tsvalue(top-1)->len == 0) /* second op is empty? */ + (void)tostring(L, top - 2); /* result is first op (as string) */ + else { + /* at least two string values; get as many as possible */ + size_t tl = tsvalue(top-1)->len; + char *buffer; + int i; + /* collect total length */ + for (n = 1; n < total && tostring(L, top-n-1); n++) { + size_t l = tsvalue(top-n-1)->len; + if (l >= MAX_SIZET - tl) luaG_runerror(L, "string length overflow"); + tl += l; + } + buffer = luaZ_openspace(L, &G(L)->buff, tl); + tl = 0; + for (i=n; i>0; i--) { /* concat all strings */ + size_t l = tsvalue(top-i)->len; + memcpy(buffer+tl, svalue(top-i), l); + tl += l; + } + setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl)); + } + total -= n-1; /* got `n' strings to create 1 new */ + last -= n-1; + } while (total > 1); /* repeat until only 1 result left */ +} + + +static void Arith (lua_State *L, StkId ra, const TValue *rb, + const TValue *rc, TMS op) { + TValue tempb, tempc; + const TValue *b, *c; + if ((b = luaV_tonumber(rb, &tempb)) != NULL && + (c = luaV_tonumber(rc, &tempc)) != NULL) { + lua_Number nb = nvalue(b), nc = nvalue(c); + switch (op) { + case TM_ADD: setnvalue(ra, luai_numadd(nb, nc)); break; + case TM_SUB: setnvalue(ra, luai_numsub(nb, nc)); break; + case TM_MUL: setnvalue(ra, luai_nummul(nb, nc)); break; + case TM_DIV: setnvalue(ra, luai_numdiv(nb, nc)); break; + case TM_MOD: setnvalue(ra, luai_nummod(nb, nc)); break; + case TM_POW: setnvalue(ra, luai_numpow(nb, nc)); break; + case TM_UNM: setnvalue(ra, luai_numunm(nb)); break; + default: lua_assert(0); break; + } + } + else if (!call_binTM(L, rb, rc, ra, op)) + luaG_aritherror(L, rb, rc); +} + + + +/* +** some macros for common tasks in `luaV_execute' +*/ + +#define runtime_check(L, c) { if (!(c)) break; } + +#define RA(i) (base+GETARG_A(i)) +/* to be used after possible stack reallocation */ +#define RB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgR, base+GETARG_B(i)) +#define RC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgR, base+GETARG_C(i)) +#define RKB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, \ + ISK(GETARG_B(i)) ? k+INDEXK(GETARG_B(i)) : base+GETARG_B(i)) +#define RKC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgK, \ + ISK(GETARG_C(i)) ? k+INDEXK(GETARG_C(i)) : base+GETARG_C(i)) +#define KBx(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, k+GETARG_Bx(i)) + + +#define dojump(L,pc,i) {(pc) += (i); luai_threadyield(L);} + + +#define Protect(x) { L->savedpc = pc; {x;}; base = L->base; } + + +#define arith_op(op,tm) { \ + TValue *rb = RKB(i); \ + TValue *rc = RKC(i); \ + if (ttisnumber(rb) && ttisnumber(rc)) { \ + lua_Number nb = nvalue(rb), nc = nvalue(rc); \ + setnvalue(ra, op(nb, nc)); \ + } \ + else \ + Protect(Arith(L, ra, rb, rc, tm)); \ + } + + + +void luaV_execute (lua_State *L, int nexeccalls) { + LClosure *cl; + StkId base; + TValue *k; + const Instruction *pc; + reentry: /* entry point */ + lua_assert(isLua(L->ci)); + pc = L->savedpc; + cl = &clvalue(L->ci->func)->l; + base = L->base; + k = cl->p->k; + /* main loop of interpreter */ + for (;;) { + const Instruction i = *pc++; + StkId ra; + if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) && + (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) { + traceexec(L, pc); + if (L->status == LUA_YIELD) { /* did hook yield? */ + L->savedpc = pc - 1; + return; + } + base = L->base; + } + /* warning!! several calls may realloc the stack and invalidate `ra' */ + ra = RA(i); + lua_assert(base == L->base && L->base == L->ci->base); + lua_assert(base <= L->top && L->top <= L->stack + L->stacksize); + lua_assert(L->top == L->ci->top || luaG_checkopenop(i)); + switch (GET_OPCODE(i)) { + case OP_MOVE: { + setobjs2s(L, ra, RB(i)); + continue; + } + case OP_LOADK: { + setobj2s(L, ra, KBx(i)); + continue; + } + case OP_LOADBOOL: { + setbvalue(ra, GETARG_B(i)); + if (GETARG_C(i)) pc++; /* skip next instruction (if C) */ + continue; + } + case OP_LOADNIL: { + TValue *rb = RB(i); + do { + setnilvalue(rb--); + } while (rb >= ra); + continue; + } + case OP_GETUPVAL: { + int b = GETARG_B(i); + setobj2s(L, ra, cl->upvals[b]->v); + continue; + } + case OP_GETGLOBAL: { + TValue g; + TValue *rb = KBx(i); + sethvalue(L, &g, cl->env); + lua_assert(ttisstring(rb)); + Protect(luaV_gettable(L, &g, rb, ra)); + continue; + } + case OP_GETTABLE: { + Protect(luaV_gettable(L, RB(i), RKC(i), ra)); + continue; + } + case OP_SETGLOBAL: { + TValue g; + sethvalue(L, &g, cl->env); + lua_assert(ttisstring(KBx(i))); + Protect(luaV_settable(L, &g, KBx(i), ra)); + continue; + } + case OP_SETUPVAL: { + UpVal *uv = cl->upvals[GETARG_B(i)]; + setobj(L, uv->v, ra); + luaC_barrier(L, uv, ra); + continue; + } + case OP_SETTABLE: { + Protect(luaV_settable(L, ra, RKB(i), RKC(i))); + continue; + } + case OP_NEWTABLE: { + int b = GETARG_B(i); + int c = GETARG_C(i); + sethvalue(L, ra, luaH_new(L, luaO_fb2int(b), luaO_fb2int(c))); + Protect(luaC_checkGC(L)); + continue; + } + case OP_SELF: { + StkId rb = RB(i); + setobjs2s(L, ra+1, rb); + Protect(luaV_gettable(L, rb, RKC(i), ra)); + continue; + } + case OP_ADD: { + arith_op(luai_numadd, TM_ADD); + continue; + } + case OP_SUB: { + arith_op(luai_numsub, TM_SUB); + continue; + } + case OP_MUL: { + arith_op(luai_nummul, TM_MUL); + continue; + } + case OP_DIV: { + arith_op(luai_numdiv, TM_DIV); + continue; + } + case OP_MOD: { + arith_op(luai_nummod, TM_MOD); + continue; + } + case OP_POW: { + arith_op(luai_numpow, TM_POW); + continue; + } + case OP_UNM: { + TValue *rb = RB(i); + if (ttisnumber(rb)) { + lua_Number nb = nvalue(rb); + setnvalue(ra, luai_numunm(nb)); + } + else { + Protect(Arith(L, ra, rb, rb, TM_UNM)); + } + continue; + } + case OP_NOT: { + int res = l_isfalse(RB(i)); /* next assignment may change this value */ + setbvalue(ra, res); + continue; + } + case OP_LEN: { + const TValue *rb = RB(i); + switch (ttype(rb)) { + case LUA_TTABLE: { + setnvalue(ra, cast_num(luaH_getn(hvalue(rb)))); + break; + } + case LUA_TSTRING: { + setnvalue(ra, cast_num(tsvalue(rb)->len)); + break; + } + default: { /* try metamethod */ + Protect( + if (!call_binTM(L, rb, luaO_nilobject, ra, TM_LEN)) + luaG_typeerror(L, rb, "get length of"); + ) + } + } + continue; + } + case OP_CONCAT: { + int b = GETARG_B(i); + int c = GETARG_C(i); + Protect(luaV_concat(L, c-b+1, c); luaC_checkGC(L)); + setobjs2s(L, RA(i), base+b); + continue; + } + case OP_JMP: { + dojump(L, pc, GETARG_sBx(i)); + continue; + } + case OP_EQ: { + TValue *rb = RKB(i); + TValue *rc = RKC(i); + Protect( + if (equalobj(L, rb, rc) == GETARG_A(i)) + dojump(L, pc, GETARG_sBx(*pc)); + ) + pc++; + continue; + } + case OP_LT: { + Protect( + if (luaV_lessthan(L, RKB(i), RKC(i)) == GETARG_A(i)) + dojump(L, pc, GETARG_sBx(*pc)); + ) + pc++; + continue; + } + case OP_LE: { + Protect( + if (lessequal(L, RKB(i), RKC(i)) == GETARG_A(i)) + dojump(L, pc, GETARG_sBx(*pc)); + ) + pc++; + continue; + } + case OP_TEST: { + if (l_isfalse(ra) != GETARG_C(i)) + dojump(L, pc, GETARG_sBx(*pc)); + pc++; + continue; + } + case OP_TESTSET: { + TValue *rb = RB(i); + if (l_isfalse(rb) != GETARG_C(i)) { + setobjs2s(L, ra, rb); + dojump(L, pc, GETARG_sBx(*pc)); + } + pc++; + continue; + } + case OP_CALL: { + int b = GETARG_B(i); + int nresults = GETARG_C(i) - 1; + if (b != 0) L->top = ra+b; /* else previous instruction set top */ + L->savedpc = pc; + switch (luaD_precall(L, ra, nresults)) { + case PCRLUA: { + nexeccalls++; + goto reentry; /* restart luaV_execute over new Lua function */ + } + case PCRC: { + /* it was a C function (`precall' called it); adjust results */ + if (nresults >= 0) L->top = L->ci->top; + base = L->base; + continue; + } + default: { + return; /* yield */ + } + } + } + case OP_TAILCALL: { + int b = GETARG_B(i); + if (b != 0) L->top = ra+b; /* else previous instruction set top */ + L->savedpc = pc; + lua_assert(GETARG_C(i) - 1 == LUA_MULTRET); + switch (luaD_precall(L, ra, LUA_MULTRET)) { + case PCRLUA: { + /* tail call: put new frame in place of previous one */ + CallInfo *ci = L->ci - 1; /* previous frame */ + int aux; + StkId func = ci->func; + StkId pfunc = (ci+1)->func; /* previous function index */ + if (L->openupval) luaF_close(L, ci->base); + L->base = ci->base = ci->func + ((ci+1)->base - pfunc); + for (aux = 0; pfunc+aux < L->top; aux++) /* move frame down */ + setobjs2s(L, func+aux, pfunc+aux); + ci->top = L->top = func+aux; /* correct top */ + lua_assert(L->top == L->base + clvalue(func)->l.p->maxstacksize); + ci->savedpc = L->savedpc; + ci->tailcalls++; /* one more call lost */ + L->ci--; /* remove new frame */ + goto reentry; + } + case PCRC: { /* it was a C function (`precall' called it) */ + base = L->base; + continue; + } + default: { + return; /* yield */ + } + } + } + case OP_RETURN: { + int b = GETARG_B(i); + if (b != 0) L->top = ra+b-1; + if (L->openupval) luaF_close(L, base); + L->savedpc = pc; + b = luaD_poscall(L, ra); + if (--nexeccalls == 0) /* was previous function running `here'? */ + return; /* no: return */ + else { /* yes: continue its execution */ + if (b) L->top = L->ci->top; + lua_assert(isLua(L->ci)); + lua_assert(GET_OPCODE(*((L->ci)->savedpc - 1)) == OP_CALL); + goto reentry; + } + } + case OP_FORLOOP: { + lua_Number step = nvalue(ra+2); + lua_Number idx = luai_numadd(nvalue(ra), step); /* increment index */ + lua_Number limit = nvalue(ra+1); + if (luai_numlt(0, step) ? luai_numle(idx, limit) + : luai_numle(limit, idx)) { + dojump(L, pc, GETARG_sBx(i)); /* jump back */ + setnvalue(ra, idx); /* update internal index... */ + setnvalue(ra+3, idx); /* ...and external index */ + } + continue; + } + case OP_FORPREP: { + const TValue *init = ra; + const TValue *plimit = ra+1; + const TValue *pstep = ra+2; + L->savedpc = pc; /* next steps may throw errors */ + if (!tonumber(init, ra)) + luaG_runerror(L, LUA_QL("for") " initial value must be a number"); + else if (!tonumber(plimit, ra+1)) + luaG_runerror(L, LUA_QL("for") " limit must be a number"); + else if (!tonumber(pstep, ra+2)) + luaG_runerror(L, LUA_QL("for") " step must be a number"); + setnvalue(ra, luai_numsub(nvalue(ra), nvalue(pstep))); + dojump(L, pc, GETARG_sBx(i)); + continue; + } + case OP_TFORLOOP: { + StkId cb = ra + 3; /* call base */ + setobjs2s(L, cb+2, ra+2); + setobjs2s(L, cb+1, ra+1); + setobjs2s(L, cb, ra); + L->top = cb+3; /* func. + 2 args (state and index) */ + Protect(luaD_call(L, cb, GETARG_C(i))); + L->top = L->ci->top; + cb = RA(i) + 3; /* previous call may change the stack */ + if (!ttisnil(cb)) { /* continue loop? */ + setobjs2s(L, cb-1, cb); /* save control variable */ + dojump(L, pc, GETARG_sBx(*pc)); /* jump back */ + } + pc++; + continue; + } + case OP_SETLIST: { + int n = GETARG_B(i); + int c = GETARG_C(i); + int last; + Table *h; + if (n == 0) { + n = cast_int(L->top - ra) - 1; + L->top = L->ci->top; + } + if (c == 0) c = cast_int(*pc++); + runtime_check(L, ttistable(ra)); + h = hvalue(ra); + last = ((c-1)*LFIELDS_PER_FLUSH) + n; + if (last > h->sizearray) /* needs more space? */ + luaH_resizearray(L, h, last); /* pre-alloc it at once */ + for (; n > 0; n--) { + TValue *val = ra+n; + setobj2t(L, luaH_setnum(L, h, last--), val); + luaC_barriert(L, h, val); + } + continue; + } + case OP_CLOSE: { + luaF_close(L, ra); + continue; + } + case OP_CLOSURE: { + Proto *p; + Closure *ncl; + int nup, j; + p = cl->p->p[GETARG_Bx(i)]; + nup = p->nups; + ncl = luaF_newLclosure(L, nup, cl->env); + ncl->l.p = p; + for (j=0; jl.upvals[j] = cl->upvals[GETARG_B(*pc)]; + else { + lua_assert(GET_OPCODE(*pc) == OP_MOVE); + ncl->l.upvals[j] = luaF_findupval(L, base + GETARG_B(*pc)); + } + } + setclvalue(L, ra, ncl); + Protect(luaC_checkGC(L)); + continue; + } + case OP_VARARG: { + int b = GETARG_B(i) - 1; + int j; + CallInfo *ci = L->ci; + int n = cast_int(ci->base - ci->func) - cl->p->numparams - 1; + if (b == LUA_MULTRET) { + Protect(luaD_checkstack(L, n)); + ra = RA(i); /* previous call may change the stack */ + b = n; + L->top = ra + n; + } + for (j = 0; j < b; j++) { + if (j < n) { + setobjs2s(L, ra + j, ci->base - n + j); + } + else { + setnilvalue(ra + j); + } + } + continue; + } + } + } +} + diff --git a/external/mit/lua/dist/src/lvm.h b/external/mit/lua/dist/src/lvm.h new file mode 100644 index 000000000..0171dc7f2 --- /dev/null +++ b/external/mit/lua/dist/src/lvm.h @@ -0,0 +1,38 @@ +/* $NetBSD: lvm.h,v 1.1.1.2 2012/03/15 00:08:09 alnsn Exp $ */ + +/* +** $Id: lvm.h,v 1.1.1.2 2012/03/15 00:08:09 alnsn Exp $ +** Lua virtual machine +** See Copyright Notice in lua.h +*/ + +#ifndef lvm_h +#define lvm_h + + +#include "ldo.h" +#include "lobject.h" +#include "ltm.h" + + +#define tostring(L,o) ((ttype(o) == LUA_TSTRING) || (luaV_tostring(L, o))) + +#define tonumber(o,n) (ttype(o) == LUA_TNUMBER || \ + (((o) = luaV_tonumber(o,n)) != NULL)) + +#define equalobj(L,o1,o2) \ + (ttype(o1) == ttype(o2) && luaV_equalval(L, o1, o2)) + + +LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r); +LUAI_FUNC int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2); +LUAI_FUNC const TValue *luaV_tonumber (const TValue *obj, TValue *n); +LUAI_FUNC int luaV_tostring (lua_State *L, StkId obj); +LUAI_FUNC void luaV_gettable (lua_State *L, const TValue *t, TValue *key, + StkId val); +LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key, + StkId val); +LUAI_FUNC void luaV_execute (lua_State *L, int nexeccalls); +LUAI_FUNC void luaV_concat (lua_State *L, int total, int last); + +#endif diff --git a/external/mit/lua/dist/src/lzio.c b/external/mit/lua/dist/src/lzio.c new file mode 100644 index 000000000..fe01c6121 --- /dev/null +++ b/external/mit/lua/dist/src/lzio.c @@ -0,0 +1,84 @@ +/* $NetBSD: lzio.c,v 1.1.1.2 2012/03/15 00:08:14 alnsn Exp $ */ + +/* +** $Id: lzio.c,v 1.1.1.2 2012/03/15 00:08:14 alnsn Exp $ +** a generic input stream interface +** See Copyright Notice in lua.h +*/ + + +#include + +#define lzio_c +#define LUA_CORE + +#include "lua.h" + +#include "llimits.h" +#include "lmem.h" +#include "lstate.h" +#include "lzio.h" + + +int luaZ_fill (ZIO *z) { + size_t size; + lua_State *L = z->L; + const char *buff; + lua_unlock(L); + buff = z->reader(L, z->data, &size); + lua_lock(L); + if (buff == NULL || size == 0) return EOZ; + z->n = size - 1; + z->p = buff; + return char2int(*(z->p++)); +} + + +int luaZ_lookahead (ZIO *z) { + if (z->n == 0) { + if (luaZ_fill(z) == EOZ) + return EOZ; + else { + z->n++; /* luaZ_fill removed first byte; put back it */ + z->p--; + } + } + return char2int(*z->p); +} + + +void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, void *data) { + z->L = L; + z->reader = reader; + z->data = data; + z->n = 0; + z->p = NULL; +} + + +/* --------------------------------------------------------------- read --- */ +size_t luaZ_read (ZIO *z, void *b, size_t n) { + while (n) { + size_t m; + if (luaZ_lookahead(z) == EOZ) + return n; /* return number of missing bytes */ + m = (n <= z->n) ? n : z->n; /* min. between n and z->n */ + memcpy(b, z->p, m); + z->n -= m; + z->p += m; + b = (char *)b + m; + n -= m; + } + return 0; +} + +/* ------------------------------------------------------------------------ */ +char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n) { + if (n > buff->buffsize) { + if (n < LUA_MINBUFFER) n = LUA_MINBUFFER; + luaZ_resizebuffer(L, buff, n); + } + return buff->buffer; +} + + diff --git a/external/mit/lua/dist/src/lzio.h b/external/mit/lua/dist/src/lzio.h new file mode 100644 index 000000000..ebfab9521 --- /dev/null +++ b/external/mit/lua/dist/src/lzio.h @@ -0,0 +1,69 @@ +/* $NetBSD: lzio.h,v 1.1.1.2 2012/03/15 00:08:14 alnsn Exp $ */ + +/* +** $Id: lzio.h,v 1.1.1.2 2012/03/15 00:08:14 alnsn Exp $ +** Buffered streams +** See Copyright Notice in lua.h +*/ + + +#ifndef lzio_h +#define lzio_h + +#include "lua.h" + +#include "lmem.h" + + +#define EOZ (-1) /* end of stream */ + +typedef struct Zio ZIO; + +#define char2int(c) cast(int, cast(unsigned char, (c))) + +#define zgetc(z) (((z)->n--)>0 ? char2int(*(z)->p++) : luaZ_fill(z)) + +typedef struct Mbuffer { + char *buffer; + size_t n; + size_t buffsize; +} Mbuffer; + +#define luaZ_initbuffer(L, buff) ((buff)->buffer = NULL, (buff)->buffsize = 0) + +#define luaZ_buffer(buff) ((buff)->buffer) +#define luaZ_sizebuffer(buff) ((buff)->buffsize) +#define luaZ_bufflen(buff) ((buff)->n) + +#define luaZ_resetbuffer(buff) ((buff)->n = 0) + + +#define luaZ_resizebuffer(L, buff, size) \ + (luaM_reallocvector(L, (buff)->buffer, (buff)->buffsize, size, char), \ + (buff)->buffsize = size) + +#define luaZ_freebuffer(L, buff) luaZ_resizebuffer(L, buff, 0) + + +LUAI_FUNC char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n); +LUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, + void *data); +LUAI_FUNC size_t luaZ_read (ZIO* z, void* b, size_t n); /* read next n bytes */ +LUAI_FUNC int luaZ_lookahead (ZIO *z); + + + +/* --------- Private Part ------------------ */ + +struct Zio { + size_t n; /* bytes still unread */ + const char *p; /* current position in buffer */ + lua_Reader reader; + void* data; /* additional data */ + lua_State *L; /* Lua state (for reader) */ +}; + + +LUAI_FUNC int luaZ_fill (ZIO *z); + +#endif diff --git a/external/mit/lua/dist/src/print.c b/external/mit/lua/dist/src/print.c new file mode 100644 index 000000000..ad53aaa2a --- /dev/null +++ b/external/mit/lua/dist/src/print.c @@ -0,0 +1,229 @@ +/* $NetBSD: print.c,v 1.1.1.2 2012/03/15 00:08:12 alnsn Exp $ */ + +/* +** $Id: print.c,v 1.1.1.2 2012/03/15 00:08:12 alnsn Exp $ +** print bytecodes +** See Copyright Notice in lua.h +*/ + +#include +#include + +#define luac_c +#define LUA_CORE + +#include "ldebug.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lundump.h" + +#define PrintFunction luaU_print + +#define Sizeof(x) ((int)sizeof(x)) +#define VOID(p) ((const void*)(p)) + +static void PrintString(const TString* ts) +{ + const char* s=getstr(ts); + size_t i,n=ts->tsv.len; + putchar('"'); + for (i=0; ik[i]; + switch (ttype(o)) + { + case LUA_TNIL: + printf("nil"); + break; + case LUA_TBOOLEAN: + printf(bvalue(o) ? "true" : "false"); + break; + case LUA_TNUMBER: + printf(LUA_NUMBER_FMT,nvalue(o)); + break; + case LUA_TSTRING: + PrintString(rawtsvalue(o)); + break; + default: /* cannot happen */ + printf("? type=%d",ttype(o)); + break; + } +} + +static void PrintCode(const Proto* f) +{ + const Instruction* code=f->code; + int pc,n=f->sizecode; + for (pc=0; pc0) printf("[%d]\t",line); else printf("[-]\t"); + printf("%-9s\t",luaP_opnames[o]); + switch (getOpMode(o)) + { + case iABC: + printf("%d",a); + if (getBMode(o)!=OpArgN) printf(" %d",ISK(b) ? (-1-INDEXK(b)) : b); + if (getCMode(o)!=OpArgN) printf(" %d",ISK(c) ? (-1-INDEXK(c)) : c); + break; + case iABx: + if (getBMode(o)==OpArgK) printf("%d %d",a,-1-bx); else printf("%d %d",a,bx); + break; + case iAsBx: + if (o==OP_JMP) printf("%d",sbx); else printf("%d %d",a,sbx); + break; + } + switch (o) + { + case OP_LOADK: + printf("\t; "); PrintConstant(f,bx); + break; + case OP_GETUPVAL: + case OP_SETUPVAL: + printf("\t; %s", (f->sizeupvalues>0) ? getstr(f->upvalues[b]) : "-"); + break; + case OP_GETGLOBAL: + case OP_SETGLOBAL: + printf("\t; %s",svalue(&f->k[bx])); + break; + case OP_GETTABLE: + case OP_SELF: + if (ISK(c)) { printf("\t; "); PrintConstant(f,INDEXK(c)); } + break; + case OP_SETTABLE: + case OP_ADD: + case OP_SUB: + case OP_MUL: + case OP_DIV: + case OP_POW: + case OP_EQ: + case OP_LT: + case OP_LE: + if (ISK(b) || ISK(c)) + { + printf("\t; "); + if (ISK(b)) PrintConstant(f,INDEXK(b)); else printf("-"); + printf(" "); + if (ISK(c)) PrintConstant(f,INDEXK(c)); else printf("-"); + } + break; + case OP_JMP: + case OP_FORLOOP: + case OP_FORPREP: + printf("\t; to %d",sbx+pc+2); + break; + case OP_CLOSURE: + printf("\t; %p",VOID(f->p[bx])); + break; + case OP_SETLIST: + if (c==0) printf("\t; %d",(int)code[++pc]); + else printf("\t; %d",c); + break; + default: + break; + } + printf("\n"); + } +} + +#define SS(x) (x==1)?"":"s" +#define S(x) x,SS(x) + +static void PrintHeader(const Proto* f) +{ + const char* s=getstr(f->source); + if (*s=='@' || *s=='=') + s++; + else if (*s==LUA_SIGNATURE[0]) + s="(bstring)"; + else + s="(string)"; + printf("\n%s <%s:%d,%d> (%d instruction%s, %d bytes at %p)\n", + (f->linedefined==0)?"main":"function",s, + f->linedefined,f->lastlinedefined, + S(f->sizecode),f->sizecode*Sizeof(Instruction),VOID(f)); + printf("%d%s param%s, %d slot%s, %d upvalue%s, ", + f->numparams,f->is_vararg?"+":"",SS(f->numparams), + S(f->maxstacksize),S(f->nups)); + printf("%d local%s, %d constant%s, %d function%s\n", + S(f->sizelocvars),S(f->sizek),S(f->sizep)); +} + +static void PrintConstants(const Proto* f) +{ + int i,n=f->sizek; + printf("constants (%d) for %p:\n",n,VOID(f)); + for (i=0; isizelocvars; + printf("locals (%d) for %p:\n",n,VOID(f)); + for (i=0; ilocvars[i].varname),f->locvars[i].startpc+1,f->locvars[i].endpc+1); + } +} + +static void PrintUpvalues(const Proto* f) +{ + int i,n=f->sizeupvalues; + printf("upvalues (%d) for %p:\n",n,VOID(f)); + if (f->upvalues==NULL) return; + for (i=0; iupvalues[i])); + } +} + +void PrintFunction(const Proto* f, int full) +{ + int i,n=f->sizep; + PrintHeader(f); + PrintCode(f); + if (full) + { + PrintConstants(f); + PrintLocals(f); + PrintUpvalues(f); + } + for (i=0; ip[i],full); +} diff --git a/external/mit/lua/dist/test/README b/external/mit/lua/dist/test/README new file mode 100644 index 000000000..0c7f38bc2 --- /dev/null +++ b/external/mit/lua/dist/test/README @@ -0,0 +1,26 @@ +These are simple tests for Lua. Some of them contain useful code. +They are meant to be run to make sure Lua is built correctly and also +to be read, to see how Lua programs look. + +Here is a one-line summary of each program: + + bisect.lua bisection method for solving non-linear equations + cf.lua temperature conversion table (celsius to farenheit) + echo.lua echo command line arguments + env.lua environment variables as automatic global variables + factorial.lua factorial without recursion + fib.lua fibonacci function with cache + fibfor.lua fibonacci numbers with coroutines and generators + globals.lua report global variable usage + hello.lua the first program in every language + life.lua Conway's Game of Life + luac.lua bare-bones luac + printf.lua an implementation of printf + readonly.lua make global variables readonly + sieve.lua the sieve of of Eratosthenes programmed with coroutines + sort.lua two implementations of a sort function + table.lua make table, grouping all data for the same item + trace-calls.lua trace calls + trace-globals.lua trace assigments to global variables + xd.lua hex dump + diff --git a/external/mit/lua/dist/test/bisect.lua b/external/mit/lua/dist/test/bisect.lua new file mode 100644 index 000000000..f91e69bfb --- /dev/null +++ b/external/mit/lua/dist/test/bisect.lua @@ -0,0 +1,27 @@ +-- bisection method for solving non-linear equations + +delta=1e-6 -- tolerance + +function bisect(f,a,b,fa,fb) + local c=(a+b)/2 + io.write(n," c=",c," a=",a," b=",b,"\n") + if c==a or c==b or math.abs(a-b) posted to lua-l +-- modified to use ANSI terminal escape sequences +-- modified to use for instead of while + +local write=io.write + +ALIVE="¥" DEAD="þ" +ALIVE="O" DEAD="-" + +function delay() -- NOTE: SYSTEM-DEPENDENT, adjust as necessary + for i=1,10000 do end + -- local i=os.clock()+1 while(os.clock() 0 do + local xm1,x,xp1,xi=self.w-1,self.w,1,self.w + while xi > 0 do + local sum = self[ym1][xm1] + self[ym1][x] + self[ym1][xp1] + + self[y][xm1] + self[y][xp1] + + self[yp1][xm1] + self[yp1][x] + self[yp1][xp1] + next[y][x] = ((sum==2) and self[y][x]) or ((sum==3) and 1) or 0 + xm1,x,xp1,xi = x,xp1,xp1+1,xi-1 + end + ym1,y,yp1,yi = y,yp1,yp1+1,yi-1 + end +end + +-- output the array to screen +function _CELLS:draw() + local out="" -- accumulate to reduce flicker + for y=1,self.h do + for x=1,self.w do + out=out..(((self[y][x]>0) and ALIVE) or DEAD) + end + out=out.."\n" + end + write(out) +end + +-- constructor +function CELLS(w,h) + local c = ARRAY2D(w,h) + c.spawn = _CELLS.spawn + c.evolve = _CELLS.evolve + c.draw = _CELLS.draw + return c +end + +-- +-- shapes suitable for use with spawn() above +-- +HEART = { 1,0,1,1,0,1,1,1,1; w=3,h=3 } +GLIDER = { 0,0,1,1,0,1,0,1,1; w=3,h=3 } +EXPLODE = { 0,1,0,1,1,1,1,0,1,0,1,0; w=3,h=4 } +FISH = { 0,1,1,1,1,1,0,0,0,1,0,0,0,0,1,1,0,0,1,0; w=5,h=4 } +BUTTERFLY = { 1,0,0,0,1,0,1,1,1,0,1,0,0,0,1,1,0,1,0,1,1,0,0,0,1; w=5,h=5 } + +-- the main routine +function LIFE(w,h) + -- create two arrays + local thisgen = CELLS(w,h) + local nextgen = CELLS(w,h) + + -- create some life + -- about 1000 generations of fun, then a glider steady-state + thisgen:spawn(GLIDER,5,4) + thisgen:spawn(EXPLODE,25,10) + thisgen:spawn(FISH,4,12) + + -- run until break + local gen=1 + write("\027[2J") -- ANSI clear screen + while 1 do + thisgen:evolve(nextgen) + thisgen,nextgen = nextgen,thisgen + write("\027[H") -- ANSI home cursor + thisgen:draw() + write("Life - generation ",gen,"\n") + gen=gen+1 + if gen>2000 then break end + --delay() -- no delay + end +end + +LIFE(40,20) diff --git a/external/mit/lua/dist/test/luac.lua b/external/mit/lua/dist/test/luac.lua new file mode 100644 index 000000000..96a0a97ce --- /dev/null +++ b/external/mit/lua/dist/test/luac.lua @@ -0,0 +1,7 @@ +-- bare-bones luac in Lua +-- usage: lua luac.lua file.lua + +assert(arg[1]~=nil and arg[2]==nil,"usage: lua luac.lua file.lua") +f=assert(io.open("luac.out","wb")) +assert(f:write(string.dump(assert(loadfile(arg[1]))))) +assert(f:close()) diff --git a/external/mit/lua/dist/test/printf.lua b/external/mit/lua/dist/test/printf.lua new file mode 100644 index 000000000..58c63ff51 --- /dev/null +++ b/external/mit/lua/dist/test/printf.lua @@ -0,0 +1,7 @@ +-- an implementation of printf + +function printf(...) + io.write(string.format(...)) +end + +printf("Hello %s from %s on %s\n",os.getenv"USER" or "there",_VERSION,os.date()) diff --git a/external/mit/lua/dist/test/readonly.lua b/external/mit/lua/dist/test/readonly.lua new file mode 100644 index 000000000..85c0b4e01 --- /dev/null +++ b/external/mit/lua/dist/test/readonly.lua @@ -0,0 +1,12 @@ +-- make global variables readonly + +local f=function (t,i) error("cannot redefine global variable `"..i.."'",2) end +local g={} +local G=getfenv() +setmetatable(g,{__index=G,__newindex=f}) +setfenv(1,g) + +-- an example +rawset(g,"x",3) +x=2 +y=1 -- cannot redefine `y' diff --git a/external/mit/lua/dist/test/sieve.lua b/external/mit/lua/dist/test/sieve.lua new file mode 100644 index 000000000..0871bb212 --- /dev/null +++ b/external/mit/lua/dist/test/sieve.lua @@ -0,0 +1,29 @@ +-- the sieve of of Eratosthenes programmed with coroutines +-- typical usage: lua -e N=1000 sieve.lua | column + +-- generate all the numbers from 2 to n +function gen (n) + return coroutine.wrap(function () + for i=2,n do coroutine.yield(i) end + end) +end + +-- filter the numbers generated by `g', removing multiples of `p' +function filter (p, g) + return coroutine.wrap(function () + while 1 do + local n = g() + if n == nil then return end + if math.mod(n, p) ~= 0 then coroutine.yield(n) end + end + end) +end + +N=N or 1000 -- from command line +x = gen(N) -- generate primes up to N +while 1 do + local n = x() -- pick a number until done + if n == nil then break end + print(n) -- must be a prime number + x = filter(n, x) -- now remove its multiples +end diff --git a/external/mit/lua/dist/test/sort.lua b/external/mit/lua/dist/test/sort.lua new file mode 100644 index 000000000..0bcb15f83 --- /dev/null +++ b/external/mit/lua/dist/test/sort.lua @@ -0,0 +1,66 @@ +-- two implementations of a sort function +-- this is an example only. Lua has now a built-in function "sort" + +-- extracted from Programming Pearls, page 110 +function qsort(x,l,u,f) + if ly end) + show("after reverse selection sort",x) + qsort(x,1,n,function (x,y) return x>> ",string.rep(" ",level)) + if t~=nil and t.currentline>=0 then io.write(t.short_src,":",t.currentline," ") end + t=debug.getinfo(2) + if event=="call" then + level=level+1 + else + level=level-1 if level<0 then level=0 end + end + if t.what=="main" then + if event=="call" then + io.write("begin ",t.short_src) + else + io.write("end ",t.short_src) + end + elseif t.what=="Lua" then +-- table.foreach(t,print) + io.write(event," ",t.name or "(Lua)"," <",t.linedefined,":",t.short_src,">") + else + io.write(event," ",t.name or "(C)"," [",t.what,"] ") + end + io.write("\n") +end + +debug.sethook(hook,"cr") +level=0 diff --git a/external/mit/lua/dist/test/trace-globals.lua b/external/mit/lua/dist/test/trace-globals.lua new file mode 100644 index 000000000..295e670ca --- /dev/null +++ b/external/mit/lua/dist/test/trace-globals.lua @@ -0,0 +1,38 @@ +-- trace assigments to global variables + +do + -- a tostring that quotes strings. note the use of the original tostring. + local _tostring=tostring + local tostring=function(a) + if type(a)=="string" then + return string.format("%q",a) + else + return _tostring(a) + end + end + + local log=function (name,old,new) + local t=debug.getinfo(3,"Sl") + local line=t.currentline + io.write(t.short_src) + if line>=0 then io.write(":",line) end + io.write(": ",name," is now ",tostring(new)," (was ",tostring(old),")","\n") + end + + local g={} + local set=function (t,name,value) + log(name,g[name],value) + g[name]=value + end + setmetatable(getfenv(),{__index=g,__newindex=set}) +end + +-- an example + +a=1 +b=2 +a=10 +b=20 +b=nil +b=200 +print(a,b,c) diff --git a/external/mit/lua/dist/test/xd.lua b/external/mit/lua/dist/test/xd.lua new file mode 100644 index 000000000..ebc3effc0 --- /dev/null +++ b/external/mit/lua/dist/test/xd.lua @@ -0,0 +1,14 @@ +-- hex dump +-- usage: lua xd.lua < file + +local offset=0 +while true do + local s=io.read(16) + if s==nil then return end + io.write(string.format("%08X ",offset)) + string.gsub(s,"(.)", + function (c) io.write(string.format("%02X ",string.byte(c))) end) + io.write(string.rep(" ",3*(16-string.len(s)))) + io.write(" ",string.gsub(s,"%c","."),"\n") + offset=offset+16 +end diff --git a/external/mit/lua/lib/Makefile b/external/mit/lua/lib/Makefile new file mode 100644 index 000000000..7753ce33d --- /dev/null +++ b/external/mit/lua/lib/Makefile @@ -0,0 +1,5 @@ +# $NetBSD: Makefile,v 1.1 2010/10/31 11:26:01 mbalmer Exp $ + +SUBDIR+= liblua + +.include diff --git a/external/mit/lua/lib/liblua/Makefile b/external/mit/lua/lib/liblua/Makefile new file mode 100644 index 000000000..f2be41471 --- /dev/null +++ b/external/mit/lua/lib/liblua/Makefile @@ -0,0 +1,21 @@ +# $NetBSD: Makefile,v 1.4 2013/02/15 20:07:06 jmmv Exp $ + +LIB= lua +SRCS= lapi.c lauxlib.c lbaselib.c lcode.c ldblib.c ldebug.c ldo.c \ + ldump.c lfunc.c lgc.c linit.c liolib.c llex.c lmathlib.c \ + lmem.c loadlib.c lobject.c lopcodes.c loslib.c lparser.c \ + lstate.c lstring.c lstrlib.c ltable.c ltablib.c ltm.c \ + lundump.c lvm.c lzio.c + +.include + +INCS= lauxlib.h lua.h lua.hpp luaconf.h lualib.h +INCSDIR= /usr/include + +CFLAGS+= -DLUA_USE_POSIX -DLUA_USE_DLOPEN +CWARNFLAGS.clang+= -Wno-empty-body + +.PATH: ${NETBSDSRCDIR}/external/mit/lua/dist/etc +.PATH: ${NETBSDSRCDIR}/external/mit/lua/dist/src + +.include diff --git a/external/mit/lua/lib/liblua/shlib_version b/external/mit/lua/lib/liblua/shlib_version new file mode 100644 index 000000000..1eb6ff6d9 --- /dev/null +++ b/external/mit/lua/lib/liblua/shlib_version @@ -0,0 +1,3 @@ +# $NetBSD: shlib_version,v 1.1 2010/10/31 11:26:01 mbalmer Exp $ +major=1 +minor=0 diff --git a/external/mit/lua/usr.bin/Makefile b/external/mit/lua/usr.bin/Makefile new file mode 100644 index 000000000..c89f90793 --- /dev/null +++ b/external/mit/lua/usr.bin/Makefile @@ -0,0 +1,5 @@ +# $NetBSD: Makefile,v 1.1 2010/10/31 11:26:01 mbalmer Exp $ + +SUBDIR+= lua luac + +.include diff --git a/external/mit/lua/usr.bin/lua/Makefile b/external/mit/lua/usr.bin/lua/Makefile new file mode 100644 index 000000000..5a415d87e --- /dev/null +++ b/external/mit/lua/usr.bin/lua/Makefile @@ -0,0 +1,17 @@ +# $NetBSD: Makefile,v 1.5 2011/01/19 11:55:50 plunky Exp $ + +PROG= lua +SRCS= lua.c +BINDIR= /usr/bin + +CPPFLAGS+= -DLUA_USE_READLINE + +LDADD+= -llua -lm -ledit -lterminfo +DPADD+= ${LIBLUA} ${LIBM} ${LIBEDIT} ${LIBTERMINFO} + +.include + +.PATH: ${NETBSDSRCDIR}/external/mit/lua/dist/src \ + ${NETBSDSRCDIR}/external/mit/lua/dist/doc + +.include diff --git a/external/mit/lua/usr.bin/luac/Makefile b/external/mit/lua/usr.bin/luac/Makefile new file mode 100644 index 000000000..0c7b8c0ec --- /dev/null +++ b/external/mit/lua/usr.bin/luac/Makefile @@ -0,0 +1,18 @@ +# $NetBSD: Makefile,v 1.3 2011/01/19 11:43:18 plunky Exp $ + +PROG= luac +SRCS= luac.c print.c +BINDIR= /usr/bin + +# +# statically link ${LIBLUA} as "hidden" symbols need to be accessed +# +DPADD+= ${LIBLUA} ${LIBM} +LDADD+= ${LIBLUA} -lm + +.include + +.PATH: ${NETBSDSRCDIR}/external/mit/lua/dist/src \ + ${NETBSDSRCDIR}/external/mit/lua/dist/doc + +.include diff --git a/external/public-domain/Makefile b/external/public-domain/Makefile new file mode 100644 index 000000000..ecb2c389d --- /dev/null +++ b/external/public-domain/Makefile @@ -0,0 +1,7 @@ +# $NetBSD: Makefile,v 1.2 2011/10/13 22:08:20 joerg Exp $ + +.include + +SUBDIR+= sqlite xz + +.include diff --git a/external/public-domain/sqlite/Makefile b/external/public-domain/sqlite/Makefile new file mode 100644 index 000000000..b9a4b1bc2 --- /dev/null +++ b/external/public-domain/sqlite/Makefile @@ -0,0 +1,5 @@ +# $NetBSD: Makefile,v 1.1 2011/10/13 21:40:27 joerg Exp $ + +SUBDIR+= lib .WAIT bin + +.include diff --git a/external/public-domain/sqlite/Makefile.inc b/external/public-domain/sqlite/Makefile.inc new file mode 100644 index 000000000..09616af0a --- /dev/null +++ b/external/public-domain/sqlite/Makefile.inc @@ -0,0 +1,30 @@ +# $NetBSD: Makefile.inc,v 1.5 2012/06/01 20:28:02 wiz Exp $ + +WARNS= 2 + +SRCDIR:= ${.PARSEDIR}/dist + +.PATH: ${SRCDIR} + +CPPFLAGS+= \ + -DHAVE_GMTIME_R=1 \ + -DHAVE_INTTYPES_H=1 \ + -DHAVE_LOCALTIME_R=1 \ + -DHAVE_READLINE=1 \ + -DHAVE_STDINT_H=1 \ + -DHAVE_STRERROR_R=1 \ + -DHAVE_USLEEP=1 \ + -DSQLITE_ENABLE_COLUMN_METADATA \ + -DSQLITE_ENABLE_FTS3_PARENTHESIS \ + -DSQLITE_ENABLE_FTS4 \ + -DSQLITE_ENABLE_LOAD_EXTENSION \ + -DSQLITE_ENABLE_UNLOCK_NOTIFY \ + -DSQLITE_HAVE_ISNAN + +.if defined(__MINIX) +CPPFLAGS+= \ + -DSQLITE_THREADSAFE=0 \ + -DSQLITE_OMIT_WAL +.endif # defined(__MINIX) + +CWARNFLAGS+= -Wno-shadow -Wno-unused diff --git a/external/public-domain/sqlite/bin/Makefile b/external/public-domain/sqlite/bin/Makefile new file mode 100644 index 000000000..126362770 --- /dev/null +++ b/external/public-domain/sqlite/bin/Makefile @@ -0,0 +1,12 @@ +# $NetBSD: Makefile,v 1.5 2013/02/14 21:07:25 martin Exp $ + +PROG= sqlite3 + +SRCS= shell.c + +DPADD+= ${LIBSQLITE3} ${LIBEDIT} ${LIBTERIMINFO} +LDADD+= -lsqlite3 -ledit -lterminfo + +BINDIR= /usr/bin + +.include diff --git a/external/public-domain/sqlite/dist/shell.c b/external/public-domain/sqlite/dist/shell.c new file mode 100644 index 000000000..31d3dd8fc --- /dev/null +++ b/external/public-domain/sqlite/dist/shell.c @@ -0,0 +1,2988 @@ +/* +** 2001 September 15 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This file contains code to implement the "sqlite" command line +** utility for accessing SQLite databases. +*/ +#if (defined(_WIN32) || defined(WIN32)) && !defined(_CRT_SECURE_NO_WARNINGS) +/* This needs to come before any includes for MSVC compiler */ +#define _CRT_SECURE_NO_WARNINGS +#endif + +/* +** Enable large-file support for fopen() and friends on unix. +*/ +#ifndef SQLITE_DISABLE_LFS +# define _LARGE_FILE 1 +# ifndef _FILE_OFFSET_BITS +# define _FILE_OFFSET_BITS 64 +# endif +# define _LARGEFILE_SOURCE 1 +#endif + +#include +#include +#include +#include +#include "sqlite3.h" +#include +#include + +#if !defined(_WIN32) && !defined(WIN32) && !defined(__OS2__) +# include +# if !defined(__RTP__) && !defined(_WRS_KERNEL) +# include +# endif +# include +# include +#endif + +#ifdef __OS2__ +# include +#endif + +#ifdef HAVE_EDITLINE +# include +#endif +#if defined(HAVE_READLINE) && HAVE_READLINE==1 +# include +# include +#endif +#if !defined(HAVE_EDITLINE) && (!defined(HAVE_READLINE) || HAVE_READLINE!=1) +# define readline(p) local_getline(p,stdin) +# define add_history(X) +# define read_history(X) +# define write_history(X) +# define stifle_history(X) +#endif + +#if defined(_WIN32) || defined(WIN32) +# include +#define isatty(h) _isatty(h) +#define access(f,m) _access((f),(m)) +#else +/* Make sure isatty() has a prototype. +*/ +extern int isatty(int); +#endif + +#if defined(_WIN32_WCE) +/* Windows CE (arm-wince-mingw32ce-gcc) does not provide isatty() + * thus we always assume that we have a console. That can be + * overridden with the -batch command line option. + */ +#define isatty(x) 1 +#endif + +/* True if the timer is enabled */ +static int enableTimer = 0; + +/* ctype macros that work with signed characters */ +#define IsSpace(X) isspace((unsigned char)X) +#define IsDigit(X) isdigit((unsigned char)X) +#define ToLower(X) (char)tolower((unsigned char)X) + +#if !defined(_WIN32) && !defined(WIN32) && !defined(__OS2__) && !defined(__RTP__) && !defined(_WRS_KERNEL) +#include +#include + +/* Saved resource information for the beginning of an operation */ +static struct rusage sBegin; + +/* +** Begin timing an operation +*/ +static void beginTimer(void){ + if( enableTimer ){ + getrusage(RUSAGE_SELF, &sBegin); + } +} + +/* Return the difference of two time_structs in seconds */ +static double timeDiff(struct timeval *pStart, struct timeval *pEnd){ + return (pEnd->tv_usec - pStart->tv_usec)*0.000001 + + (double)(pEnd->tv_sec - pStart->tv_sec); +} + +/* +** Print the timing results. +*/ +static void endTimer(void){ + if( enableTimer ){ + struct rusage sEnd; + getrusage(RUSAGE_SELF, &sEnd); + printf("CPU Time: user %f sys %f\n", + timeDiff(&sBegin.ru_utime, &sEnd.ru_utime), + timeDiff(&sBegin.ru_stime, &sEnd.ru_stime)); + } +} + +#define BEGIN_TIMER beginTimer() +#define END_TIMER endTimer() +#define HAS_TIMER 1 + +#elif (defined(_WIN32) || defined(WIN32)) + +#include + +/* Saved resource information for the beginning of an operation */ +static HANDLE hProcess; +static FILETIME ftKernelBegin; +static FILETIME ftUserBegin; +typedef BOOL (WINAPI *GETPROCTIMES)(HANDLE, LPFILETIME, LPFILETIME, LPFILETIME, LPFILETIME); +static GETPROCTIMES getProcessTimesAddr = NULL; + +/* +** Check to see if we have timer support. Return 1 if necessary +** support found (or found previously). +*/ +static int hasTimer(void){ + if( getProcessTimesAddr ){ + return 1; + } else { + /* GetProcessTimes() isn't supported in WIN95 and some other Windows versions. + ** See if the version we are running on has it, and if it does, save off + ** a pointer to it and the current process handle. + */ + hProcess = GetCurrentProcess(); + if( hProcess ){ + HINSTANCE hinstLib = LoadLibrary(TEXT("Kernel32.dll")); + if( NULL != hinstLib ){ + getProcessTimesAddr = (GETPROCTIMES) GetProcAddress(hinstLib, "GetProcessTimes"); + if( NULL != getProcessTimesAddr ){ + return 1; + } + FreeLibrary(hinstLib); + } + } + } + return 0; +} + +/* +** Begin timing an operation +*/ +static void beginTimer(void){ + if( enableTimer && getProcessTimesAddr ){ + FILETIME ftCreation, ftExit; + getProcessTimesAddr(hProcess, &ftCreation, &ftExit, &ftKernelBegin, &ftUserBegin); + } +} + +/* Return the difference of two FILETIME structs in seconds */ +static double timeDiff(FILETIME *pStart, FILETIME *pEnd){ + sqlite_int64 i64Start = *((sqlite_int64 *) pStart); + sqlite_int64 i64End = *((sqlite_int64 *) pEnd); + return (double) ((i64End - i64Start) / 10000000.0); +} + +/* +** Print the timing results. +*/ +static void endTimer(void){ + if( enableTimer && getProcessTimesAddr){ + FILETIME ftCreation, ftExit, ftKernelEnd, ftUserEnd; + getProcessTimesAddr(hProcess, &ftCreation, &ftExit, &ftKernelEnd, &ftUserEnd); + printf("CPU Time: user %f sys %f\n", + timeDiff(&ftUserBegin, &ftUserEnd), + timeDiff(&ftKernelBegin, &ftKernelEnd)); + } +} + +#define BEGIN_TIMER beginTimer() +#define END_TIMER endTimer() +#define HAS_TIMER hasTimer() + +#else +#define BEGIN_TIMER +#define END_TIMER +#define HAS_TIMER 0 +#endif + +/* +** Used to prevent warnings about unused parameters +*/ +#define UNUSED_PARAMETER(x) (void)(x) + +/* +** If the following flag is set, then command execution stops +** at an error if we are not interactive. +*/ +static int bail_on_error = 0; + +/* +** Threat stdin as an interactive input if the following variable +** is true. Otherwise, assume stdin is connected to a file or pipe. +*/ +static int stdin_is_interactive = 1; + +/* +** The following is the open SQLite database. We make a pointer +** to this database a static variable so that it can be accessed +** by the SIGINT handler to interrupt database processing. +*/ +static sqlite3 *db = 0; + +/* +** True if an interrupt (Control-C) has been received. +*/ +static volatile int seenInterrupt = 0; + +/* +** This is the name of our program. It is set in main(), used +** in a number of other places, mostly for error messages. +*/ +static char *Argv0; + +/* +** Prompt strings. Initialized in main. Settable with +** .prompt main continue +*/ +static char mainPrompt[20]; /* First line prompt. default: "sqlite> "*/ +static char continuePrompt[20]; /* Continuation prompt. default: " ...> " */ + +/* +** Write I/O traces to the following stream. +*/ +#ifdef SQLITE_ENABLE_IOTRACE +static FILE *iotrace = 0; +#endif + +/* +** This routine works like printf in that its first argument is a +** format string and subsequent arguments are values to be substituted +** in place of % fields. The result of formatting this string +** is written to iotrace. +*/ +#ifdef SQLITE_ENABLE_IOTRACE +static void iotracePrintf(const char *zFormat, ...){ + va_list ap; + char *z; + if( iotrace==0 ) return; + va_start(ap, zFormat); + z = sqlite3_vmprintf(zFormat, ap); + va_end(ap); + fprintf(iotrace, "%s", z); + sqlite3_free(z); +} +#endif + + +/* +** Determines if a string is a number of not. +*/ +static int isNumber(const char *z, int *realnum){ + if( *z=='-' || *z=='+' ) z++; + if( !IsDigit(*z) ){ + return 0; + } + z++; + if( realnum ) *realnum = 0; + while( IsDigit(*z) ){ z++; } + if( *z=='.' ){ + z++; + if( !IsDigit(*z) ) return 0; + while( IsDigit(*z) ){ z++; } + if( realnum ) *realnum = 1; + } + if( *z=='e' || *z=='E' ){ + z++; + if( *z=='+' || *z=='-' ) z++; + if( !IsDigit(*z) ) return 0; + while( IsDigit(*z) ){ z++; } + if( realnum ) *realnum = 1; + } + return *z==0; +} + +/* +** A global char* and an SQL function to access its current value +** from within an SQL statement. This program used to use the +** sqlite_exec_printf() API to substitue a string into an SQL statement. +** The correct way to do this with sqlite3 is to use the bind API, but +** since the shell is built around the callback paradigm it would be a lot +** of work. Instead just use this hack, which is quite harmless. +*/ +static const char *zShellStatic = 0; +static void shellstaticFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + assert( 0==argc ); + assert( zShellStatic ); + UNUSED_PARAMETER(argc); + UNUSED_PARAMETER(argv); + sqlite3_result_text(context, zShellStatic, -1, SQLITE_STATIC); +} + + +/* +** This routine reads a line of text from FILE in, stores +** the text in memory obtained from malloc() and returns a pointer +** to the text. NULL is returned at end of file, or if malloc() +** fails. +** +** The interface is like "readline" but no command-line editing +** is done. +*/ +static char *local_getline(char *zPrompt, FILE *in){ + char *zLine; + int nLine; + int n; + + if( zPrompt && *zPrompt ){ + printf("%s",zPrompt); + fflush(stdout); + } + nLine = 100; + zLine = malloc( nLine ); + if( zLine==0 ) return 0; + n = 0; + while( 1 ){ + if( n+100>nLine ){ + nLine = nLine*2 + 100; + zLine = realloc(zLine, nLine); + if( zLine==0 ) return 0; + } + if( fgets(&zLine[n], nLine - n, in)==0 ){ + if( n==0 ){ + free(zLine); + return 0; + } + zLine[n] = 0; + break; + } + while( zLine[n] ){ n++; } + if( n>0 && zLine[n-1]=='\n' ){ + n--; + if( n>0 && zLine[n-1]=='\r' ) n--; + zLine[n] = 0; + break; + } + } + zLine = realloc( zLine, n+1 ); + return zLine; +} + +/* +** Retrieve a single line of input text. +** +** zPrior is a string of prior text retrieved. If not the empty +** string, then issue a continuation prompt. +*/ +static char *one_input_line(const char *zPrior, FILE *in){ + char *zPrompt; + char *zResult; + if( in!=0 ){ + return local_getline(0, in); + } + if( zPrior && zPrior[0] ){ + zPrompt = continuePrompt; + }else{ + zPrompt = mainPrompt; + } + zResult = readline(zPrompt); +#if defined(HAVE_READLINE) && HAVE_READLINE==1 + if( zResult && *zResult ) add_history(zResult); +#endif + return zResult; +} + +struct previous_mode_data { + int valid; /* Is there legit data in here? */ + int mode; + int showHeader; + int colWidth[100]; +}; + +/* +** An pointer to an instance of this structure is passed from +** the main program to the callback. This is used to communicate +** state and mode information. +*/ +struct callback_data { + sqlite3 *db; /* The database */ + int echoOn; /* True to echo input commands */ + int statsOn; /* True to display memory stats before each finalize */ + int cnt; /* Number of records displayed so far */ + FILE *out; /* Write results here */ + int nErr; /* Number of errors seen */ + int mode; /* An output mode setting */ + int writableSchema; /* True if PRAGMA writable_schema=ON */ + int showHeader; /* True to show column names in List or Column mode */ + char *zDestTable; /* Name of destination table when MODE_Insert */ + char separator[20]; /* Separator character for MODE_List */ + int colWidth[100]; /* Requested width of each column when in column mode*/ + int actualWidth[100]; /* Actual width of each column */ + char nullvalue[20]; /* The text to print when a NULL comes back from + ** the database */ + struct previous_mode_data explainPrev; + /* Holds the mode information just before + ** .explain ON */ + char outfile[FILENAME_MAX]; /* Filename for *out */ + const char *zDbFilename; /* name of the database file */ + const char *zVfs; /* Name of VFS to use */ + sqlite3_stmt *pStmt; /* Current statement if any. */ + FILE *pLog; /* Write log output here */ +}; + +/* +** These are the allowed modes. +*/ +#define MODE_Line 0 /* One column per line. Blank line between records */ +#define MODE_Column 1 /* One record per line in neat columns */ +#define MODE_List 2 /* One record per line with a separator */ +#define MODE_Semi 3 /* Same as MODE_List but append ";" to each line */ +#define MODE_Html 4 /* Generate an XHTML table */ +#define MODE_Insert 5 /* Generate SQL "insert" statements */ +#define MODE_Tcl 6 /* Generate ANSI-C or TCL quoted elements */ +#define MODE_Csv 7 /* Quote strings, numbers are plain */ +#define MODE_Explain 8 /* Like MODE_Column, but do not truncate data */ + +static const char *modeDescr[] = { + "line", + "column", + "list", + "semi", + "html", + "insert", + "tcl", + "csv", + "explain", +}; + +/* +** Number of elements in an array +*/ +#define ArraySize(X) (int)(sizeof(X)/sizeof(X[0])) + +/* +** Compute a string length that is limited to what can be stored in +** lower 30 bits of a 32-bit signed integer. +*/ +static int strlen30(const char *z){ + const char *z2 = z; + while( *z2 ){ z2++; } + return 0x3fffffff & (int)(z2 - z); +} + +/* +** A callback for the sqlite3_log() interface. +*/ +static void shellLog(void *pArg, int iErrCode, const char *zMsg){ + struct callback_data *p = (struct callback_data*)pArg; + if( p->pLog==0 ) return; + fprintf(p->pLog, "(%d) %s\n", iErrCode, zMsg); + fflush(p->pLog); +} + +/* +** Output the given string as a hex-encoded blob (eg. X'1234' ) +*/ +static void output_hex_blob(FILE *out, const void *pBlob, int nBlob){ + int i; + char *zBlob = (char *)pBlob; + fprintf(out,"X'"); + for(i=0; i0 ){ + fprintf(out,"%.*s",i,z); + } + if( z[i]=='<' ){ + fprintf(out,"<"); + }else if( z[i]=='&' ){ + fprintf(out,"&"); + }else if( z[i]=='>' ){ + fprintf(out,">"); + }else if( z[i]=='\"' ){ + fprintf(out,"""); + }else if( z[i]=='\'' ){ + fprintf(out,"'"); + }else{ + break; + } + z += i + 1; + } +} + +/* +** If a field contains any character identified by a 1 in the following +** array, then the string must be quoted for CSV. +*/ +static const char needCsvQuote[] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +}; + +/* +** Output a single term of CSV. Actually, p->separator is used for +** the separator, which may or may not be a comma. p->nullvalue is +** the null value. Strings are quoted using ANSI-C rules. Numbers +** appear outside of quotes. +*/ +static void output_csv(struct callback_data *p, const char *z, int bSep){ + FILE *out = p->out; + if( z==0 ){ + fprintf(out,"%s",p->nullvalue); + }else{ + int i; + int nSep = strlen30(p->separator); + for(i=0; z[i]; i++){ + if( needCsvQuote[((unsigned char*)z)[i]] + || (z[i]==p->separator[0] && + (nSep==1 || memcmp(z, p->separator, nSep)==0)) ){ + i = 0; + break; + } + } + if( i==0 ){ + putc('"', out); + for(i=0; z[i]; i++){ + if( z[i]=='"' ) putc('"', out); + putc(z[i], out); + } + putc('"', out); + }else{ + fprintf(out, "%s", z); + } + } + if( bSep ){ + fprintf(p->out, "%s", p->separator); + } +} + +#ifdef SIGINT +/* +** This routine runs when the user presses Ctrl-C +*/ +static void interrupt_handler(int NotUsed){ + UNUSED_PARAMETER(NotUsed); + seenInterrupt = 1; + if( db ) sqlite3_interrupt(db); +} +#endif + +/* +** This is the callback routine that the shell +** invokes for each row of a query result. +*/ +static int shell_callback(void *pArg, int nArg, char **azArg, char **azCol, int *aiType){ + int i; + struct callback_data *p = (struct callback_data*)pArg; + + switch( p->mode ){ + case MODE_Line: { + int w = 5; + if( azArg==0 ) break; + for(i=0; iw ) w = len; + } + if( p->cnt++>0 ) fprintf(p->out,"\n"); + for(i=0; iout,"%*s = %s\n", w, azCol[i], + azArg[i] ? azArg[i] : p->nullvalue); + } + break; + } + case MODE_Explain: + case MODE_Column: { + if( p->cnt++==0 ){ + for(i=0; icolWidth) ){ + w = p->colWidth[i]; + }else{ + w = 0; + } + if( w<=0 ){ + w = strlen30(azCol[i] ? azCol[i] : ""); + if( w<10 ) w = 10; + n = strlen30(azArg && azArg[i] ? azArg[i] : p->nullvalue); + if( wactualWidth) ){ + p->actualWidth[i] = w; + } + if( p->showHeader ){ + fprintf(p->out,"%-*.*s%s",w,w,azCol[i], i==nArg-1 ? "\n": " "); + } + } + if( p->showHeader ){ + for(i=0; iactualWidth) ){ + w = p->actualWidth[i]; + }else{ + w = 10; + } + fprintf(p->out,"%-*.*s%s",w,w,"-----------------------------------" + "----------------------------------------------------------", + i==nArg-1 ? "\n": " "); + } + } + } + if( azArg==0 ) break; + for(i=0; iactualWidth) ){ + w = p->actualWidth[i]; + }else{ + w = 10; + } + if( p->mode==MODE_Explain && azArg[i] && + strlen30(azArg[i])>w ){ + w = strlen30(azArg[i]); + } + fprintf(p->out,"%-*.*s%s",w,w, + azArg[i] ? azArg[i] : p->nullvalue, i==nArg-1 ? "\n": " "); + } + break; + } + case MODE_Semi: + case MODE_List: { + if( p->cnt++==0 && p->showHeader ){ + for(i=0; iout,"%s%s",azCol[i], i==nArg-1 ? "\n" : p->separator); + } + } + if( azArg==0 ) break; + for(i=0; inullvalue; + fprintf(p->out, "%s", z); + if( iout, "%s", p->separator); + }else if( p->mode==MODE_Semi ){ + fprintf(p->out, ";\n"); + }else{ + fprintf(p->out, "\n"); + } + } + break; + } + case MODE_Html: { + if( p->cnt++==0 && p->showHeader ){ + fprintf(p->out,""); + for(i=0; iout,""); + output_html_string(p->out, azCol[i]); + fprintf(p->out,"\n"); + } + fprintf(p->out,"\n"); + } + if( azArg==0 ) break; + fprintf(p->out,""); + for(i=0; iout,""); + output_html_string(p->out, azArg[i] ? azArg[i] : p->nullvalue); + fprintf(p->out,"\n"); + } + fprintf(p->out,"\n"); + break; + } + case MODE_Tcl: { + if( p->cnt++==0 && p->showHeader ){ + for(i=0; iout,azCol[i] ? azCol[i] : ""); + fprintf(p->out, "%s", p->separator); + } + fprintf(p->out,"\n"); + } + if( azArg==0 ) break; + for(i=0; iout, azArg[i] ? azArg[i] : p->nullvalue); + fprintf(p->out, "%s", p->separator); + } + fprintf(p->out,"\n"); + break; + } + case MODE_Csv: { + if( p->cnt++==0 && p->showHeader ){ + for(i=0; iout,"\n"); + } + if( azArg==0 ) break; + for(i=0; iout,"\n"); + break; + } + case MODE_Insert: { + p->cnt++; + if( azArg==0 ) break; + fprintf(p->out,"INSERT INTO %s VALUES(",p->zDestTable); + for(i=0; i0 ? ",": ""; + if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){ + fprintf(p->out,"%sNULL",zSep); + }else if( aiType && aiType[i]==SQLITE_TEXT ){ + if( zSep[0] ) fprintf(p->out,"%s",zSep); + output_quoted_string(p->out, azArg[i]); + }else if( aiType && (aiType[i]==SQLITE_INTEGER || aiType[i]==SQLITE_FLOAT) ){ + fprintf(p->out,"%s%s",zSep, azArg[i]); + }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){ + const void *pBlob = sqlite3_column_blob(p->pStmt, i); + int nBlob = sqlite3_column_bytes(p->pStmt, i); + if( zSep[0] ) fprintf(p->out,"%s",zSep); + output_hex_blob(p->out, pBlob, nBlob); + }else if( isNumber(azArg[i], 0) ){ + fprintf(p->out,"%s%s",zSep, azArg[i]); + }else{ + if( zSep[0] ) fprintf(p->out,"%s",zSep); + output_quoted_string(p->out, azArg[i]); + } + } + fprintf(p->out,");\n"); + break; + } + } + return 0; +} + +/* +** This is the callback routine that the SQLite library +** invokes for each row of a query result. +*/ +static int callback(void *pArg, int nArg, char **azArg, char **azCol){ + /* since we don't have type info, call the shell_callback with a NULL value */ + return shell_callback(pArg, nArg, azArg, azCol, NULL); +} + +/* +** Set the destination table field of the callback_data structure to +** the name of the table given. Escape any quote characters in the +** table name. +*/ +static void set_table_name(struct callback_data *p, const char *zName){ + int i, n; + int needQuote; + char *z; + + if( p->zDestTable ){ + free(p->zDestTable); + p->zDestTable = 0; + } + if( zName==0 ) return; + needQuote = !isalpha((unsigned char)*zName) && *zName!='_'; + for(i=n=0; zName[i]; i++, n++){ + if( !isalnum((unsigned char)zName[i]) && zName[i]!='_' ){ + needQuote = 1; + if( zName[i]=='\'' ) n++; + } + } + if( needQuote ) n += 2; + z = p->zDestTable = malloc( n+1 ); + if( z==0 ){ + fprintf(stderr,"Error: out of memory\n"); + exit(1); + } + n = 0; + if( needQuote ) z[n++] = '\''; + for(i=0; zName[i]; i++){ + z[n++] = zName[i]; + if( zName[i]=='\'' ) z[n++] = '\''; + } + if( needQuote ) z[n++] = '\''; + z[n] = 0; +} + +/* zIn is either a pointer to a NULL-terminated string in memory obtained +** from malloc(), or a NULL pointer. The string pointed to by zAppend is +** added to zIn, and the result returned in memory obtained from malloc(). +** zIn, if it was not NULL, is freed. +** +** If the third argument, quote, is not '\0', then it is used as a +** quote character for zAppend. +*/ +static char *appendText(char *zIn, char const *zAppend, char quote){ + int len; + int i; + int nAppend = strlen30(zAppend); + int nIn = (zIn?strlen30(zIn):0); + + len = nAppend+nIn+1; + if( quote ){ + len += 2; + for(i=0; idb, zSelect, -1, &pSelect, 0); + if( rc!=SQLITE_OK || !pSelect ){ + fprintf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, sqlite3_errmsg(p->db)); + p->nErr++; + return rc; + } + rc = sqlite3_step(pSelect); + while( rc==SQLITE_ROW ){ + if( zFirstRow ){ + fprintf(p->out, "%s", zFirstRow); + zFirstRow = 0; + } + fprintf(p->out, "%s;\n", sqlite3_column_text(pSelect, 0)); + rc = sqlite3_step(pSelect); + } + rc = sqlite3_finalize(pSelect); + if( rc!=SQLITE_OK ){ + fprintf(p->out, "/**** ERROR: (%d) %s *****/\n", rc, sqlite3_errmsg(p->db)); + p->nErr++; + } + return rc; +} + +/* +** Allocate space and save off current error string. +*/ +static char *save_err_msg( + sqlite3 *db /* Database to query */ +){ + int nErrMsg = 1+strlen30(sqlite3_errmsg(db)); + char *zErrMsg = sqlite3_malloc(nErrMsg); + if( zErrMsg ){ + memcpy(zErrMsg, sqlite3_errmsg(db), nErrMsg); + } + return zErrMsg; +} + +/* +** Display memory stats. +*/ +static int display_stats( + sqlite3 *db, /* Database to query */ + struct callback_data *pArg, /* Pointer to struct callback_data */ + int bReset /* True to reset the stats */ +){ + int iCur; + int iHiwtr; + + if( pArg && pArg->out ){ + + iHiwtr = iCur = -1; + sqlite3_status(SQLITE_STATUS_MEMORY_USED, &iCur, &iHiwtr, bReset); + fprintf(pArg->out, "Memory Used: %d (max %d) bytes\n", iCur, iHiwtr); + iHiwtr = iCur = -1; + sqlite3_status(SQLITE_STATUS_MALLOC_COUNT, &iCur, &iHiwtr, bReset); + fprintf(pArg->out, "Number of Outstanding Allocations: %d (max %d)\n", iCur, iHiwtr); +/* +** Not currently used by the CLI. +** iHiwtr = iCur = -1; +** sqlite3_status(SQLITE_STATUS_PAGECACHE_USED, &iCur, &iHiwtr, bReset); +** fprintf(pArg->out, "Number of Pcache Pages Used: %d (max %d) pages\n", iCur, iHiwtr); +*/ + iHiwtr = iCur = -1; + sqlite3_status(SQLITE_STATUS_PAGECACHE_OVERFLOW, &iCur, &iHiwtr, bReset); + fprintf(pArg->out, "Number of Pcache Overflow Bytes: %d (max %d) bytes\n", iCur, iHiwtr); +/* +** Not currently used by the CLI. +** iHiwtr = iCur = -1; +** sqlite3_status(SQLITE_STATUS_SCRATCH_USED, &iCur, &iHiwtr, bReset); +** fprintf(pArg->out, "Number of Scratch Allocations Used: %d (max %d)\n", iCur, iHiwtr); +*/ + iHiwtr = iCur = -1; + sqlite3_status(SQLITE_STATUS_SCRATCH_OVERFLOW, &iCur, &iHiwtr, bReset); + fprintf(pArg->out, "Number of Scratch Overflow Bytes: %d (max %d) bytes\n", iCur, iHiwtr); + iHiwtr = iCur = -1; + sqlite3_status(SQLITE_STATUS_MALLOC_SIZE, &iCur, &iHiwtr, bReset); + fprintf(pArg->out, "Largest Allocation: %d bytes\n", iHiwtr); + iHiwtr = iCur = -1; + sqlite3_status(SQLITE_STATUS_PAGECACHE_SIZE, &iCur, &iHiwtr, bReset); + fprintf(pArg->out, "Largest Pcache Allocation: %d bytes\n", iHiwtr); + iHiwtr = iCur = -1; + sqlite3_status(SQLITE_STATUS_SCRATCH_SIZE, &iCur, &iHiwtr, bReset); + fprintf(pArg->out, "Largest Scratch Allocation: %d bytes\n", iHiwtr); +#ifdef YYTRACKMAXSTACKDEPTH + iHiwtr = iCur = -1; + sqlite3_status(SQLITE_STATUS_PARSER_STACK, &iCur, &iHiwtr, bReset); + fprintf(pArg->out, "Deepest Parser Stack: %d (max %d)\n", iCur, iHiwtr); +#endif + } + + if( pArg && pArg->out && db ){ + iHiwtr = iCur = -1; + sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_USED, &iCur, &iHiwtr, bReset); + fprintf(pArg->out, "Lookaside Slots Used: %d (max %d)\n", iCur, iHiwtr); + sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &iCur, &iHiwtr, bReset); + fprintf(pArg->out, "Successful lookaside attempts: %d\n", iHiwtr); + sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE, &iCur, &iHiwtr, bReset); + fprintf(pArg->out, "Lookaside failures due to size: %d\n", iHiwtr); + sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL, &iCur, &iHiwtr, bReset); + fprintf(pArg->out, "Lookaside failures due to OOM: %d\n", iHiwtr); + iHiwtr = iCur = -1; + sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHiwtr, bReset); + fprintf(pArg->out, "Pager Heap Usage: %d bytes\n", iCur); iHiwtr = iCur = -1; + sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHiwtr, 1); + fprintf(pArg->out, "Page cache hits: %d\n", iCur); + iHiwtr = iCur = -1; + sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHiwtr, 1); + fprintf(pArg->out, "Page cache misses: %d\n", iCur); + iHiwtr = iCur = -1; + sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHiwtr, bReset); + fprintf(pArg->out, "Schema Heap Usage: %d bytes\n", iCur); + iHiwtr = iCur = -1; + sqlite3_db_status(db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHiwtr, bReset); + fprintf(pArg->out, "Statement Heap/Lookaside Usage: %d bytes\n", iCur); + } + + if( pArg && pArg->out && db && pArg->pStmt ){ + iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FULLSCAN_STEP, bReset); + fprintf(pArg->out, "Fullscan Steps: %d\n", iCur); + iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_SORT, bReset); + fprintf(pArg->out, "Sort Operations: %d\n", iCur); + iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_AUTOINDEX, bReset); + fprintf(pArg->out, "Autoindex Inserts: %d\n", iCur); + } + + return 0; +} + +/* +** Execute a statement or set of statements. Print +** any result rows/columns depending on the current mode +** set via the supplied callback. +** +** This is very similar to SQLite's built-in sqlite3_exec() +** function except it takes a slightly different callback +** and callback data argument. +*/ +static int shell_exec( + sqlite3 *db, /* An open database */ + const char *zSql, /* SQL to be evaluated */ + int (*xCallback)(void*,int,char**,char**,int*), /* Callback function */ + /* (not the same as sqlite3_exec) */ + struct callback_data *pArg, /* Pointer to struct callback_data */ + char **pzErrMsg /* Error msg written here */ +){ + sqlite3_stmt *pStmt = NULL; /* Statement to execute. */ + int rc = SQLITE_OK; /* Return Code */ + int rc2; + const char *zLeftover; /* Tail of unprocessed SQL */ + + if( pzErrMsg ){ + *pzErrMsg = NULL; + } + + while( zSql[0] && (SQLITE_OK == rc) ){ + rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover); + if( SQLITE_OK != rc ){ + if( pzErrMsg ){ + *pzErrMsg = save_err_msg(db); + } + }else{ + if( !pStmt ){ + /* this happens for a comment or white-space */ + zSql = zLeftover; + while( IsSpace(zSql[0]) ) zSql++; + continue; + } + + /* save off the prepared statment handle and reset row count */ + if( pArg ){ + pArg->pStmt = pStmt; + pArg->cnt = 0; + } + + /* echo the sql statement if echo on */ + if( pArg && pArg->echoOn ){ + const char *zStmtSql = sqlite3_sql(pStmt); + fprintf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql); + } + + /* Output TESTCTRL_EXPLAIN text of requested */ + if( pArg && pArg->mode==MODE_Explain ){ + const char *zExplain = 0; + sqlite3_test_control(SQLITE_TESTCTRL_EXPLAIN_STMT, pStmt, &zExplain); + if( zExplain && zExplain[0] ){ + fprintf(pArg->out, "%s", zExplain); + } + } + + /* perform the first step. this will tell us if we + ** have a result set or not and how wide it is. + */ + rc = sqlite3_step(pStmt); + /* if we have a result set... */ + if( SQLITE_ROW == rc ){ + /* if we have a callback... */ + if( xCallback ){ + /* allocate space for col name ptr, value ptr, and type */ + int nCol = sqlite3_column_count(pStmt); + void *pData = sqlite3_malloc(3*nCol*sizeof(const char*) + 1); + if( !pData ){ + rc = SQLITE_NOMEM; + }else{ + char **azCols = (char **)pData; /* Names of result columns */ + char **azVals = &azCols[nCol]; /* Results */ + int *aiTypes = (int *)&azVals[nCol]; /* Result types */ + int i; + assert(sizeof(int) <= sizeof(char *)); + /* save off ptrs to column names */ + for(i=0; istatsOn ){ + display_stats(db, pArg, 0); + } + + /* Finalize the statement just executed. If this fails, save a + ** copy of the error message. Otherwise, set zSql to point to the + ** next statement to execute. */ + rc2 = sqlite3_finalize(pStmt); + if( rc!=SQLITE_NOMEM ) rc = rc2; + if( rc==SQLITE_OK ){ + zSql = zLeftover; + while( IsSpace(zSql[0]) ) zSql++; + }else if( pzErrMsg ){ + *pzErrMsg = save_err_msg(db); + } + + /* clear saved stmt handle */ + if( pArg ){ + pArg->pStmt = NULL; + } + } + } /* end while */ + + return rc; +} + + +/* +** This is a different callback routine used for dumping the database. +** Each row received by this callback consists of a table name, +** the table type ("index" or "table") and SQL to create the table. +** This routine should print text sufficient to recreate the table. +*/ +static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){ + int rc; + const char *zTable; + const char *zType; + const char *zSql; + const char *zPrepStmt = 0; + struct callback_data *p = (struct callback_data *)pArg; + + UNUSED_PARAMETER(azCol); + if( nArg!=3 ) return 1; + zTable = azArg[0]; + zType = azArg[1]; + zSql = azArg[2]; + + if( strcmp(zTable, "sqlite_sequence")==0 ){ + zPrepStmt = "DELETE FROM sqlite_sequence;\n"; + }else if( strcmp(zTable, "sqlite_stat1")==0 ){ + fprintf(p->out, "ANALYZE sqlite_master;\n"); + }else if( strncmp(zTable, "sqlite_", 7)==0 ){ + return 0; + }else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){ + char *zIns; + if( !p->writableSchema ){ + fprintf(p->out, "PRAGMA writable_schema=ON;\n"); + p->writableSchema = 1; + } + zIns = sqlite3_mprintf( + "INSERT INTO sqlite_master(type,name,tbl_name,rootpage,sql)" + "VALUES('table','%q','%q',0,'%q');", + zTable, zTable, zSql); + fprintf(p->out, "%s\n", zIns); + sqlite3_free(zIns); + return 0; + }else{ + fprintf(p->out, "%s;\n", zSql); + } + + if( strcmp(zType, "table")==0 ){ + sqlite3_stmt *pTableInfo = 0; + char *zSelect = 0; + char *zTableInfo = 0; + char *zTmp = 0; + int nRow = 0; + + zTableInfo = appendText(zTableInfo, "PRAGMA table_info(", 0); + zTableInfo = appendText(zTableInfo, zTable, '"'); + zTableInfo = appendText(zTableInfo, ");", 0); + + rc = sqlite3_prepare(p->db, zTableInfo, -1, &pTableInfo, 0); + free(zTableInfo); + if( rc!=SQLITE_OK || !pTableInfo ){ + return 1; + } + + zSelect = appendText(zSelect, "SELECT 'INSERT INTO ' || ", 0); + zTmp = appendText(zTmp, zTable, '"'); + if( zTmp ){ + zSelect = appendText(zSelect, zTmp, '\''); + } + zSelect = appendText(zSelect, " || ' VALUES(' || ", 0); + rc = sqlite3_step(pTableInfo); + while( rc==SQLITE_ROW ){ + const char *zText = (const char *)sqlite3_column_text(pTableInfo, 1); + zSelect = appendText(zSelect, "quote(", 0); + zSelect = appendText(zSelect, zText, '"'); + rc = sqlite3_step(pTableInfo); + if( rc==SQLITE_ROW ){ + zSelect = appendText(zSelect, ") || ',' || ", 0); + }else{ + zSelect = appendText(zSelect, ") ", 0); + } + nRow++; + } + rc = sqlite3_finalize(pTableInfo); + if( rc!=SQLITE_OK || nRow==0 ){ + free(zSelect); + return 1; + } + zSelect = appendText(zSelect, "|| ')' FROM ", 0); + zSelect = appendText(zSelect, zTable, '"'); + + rc = run_table_dump_query(p, zSelect, zPrepStmt); + if( rc==SQLITE_CORRUPT ){ + zSelect = appendText(zSelect, " ORDER BY rowid DESC", 0); + run_table_dump_query(p, zSelect, 0); + } + if( zSelect ) free(zSelect); + } + return 0; +} + +/* +** Run zQuery. Use dump_callback() as the callback routine so that +** the contents of the query are output as SQL statements. +** +** If we get a SQLITE_CORRUPT error, rerun the query after appending +** "ORDER BY rowid DESC" to the end. +*/ +static int run_schema_dump_query( + struct callback_data *p, + const char *zQuery +){ + int rc; + char *zErr = 0; + rc = sqlite3_exec(p->db, zQuery, dump_callback, p, &zErr); + if( rc==SQLITE_CORRUPT ){ + char *zQ2; + int len = strlen30(zQuery); + fprintf(p->out, "/****** CORRUPTION ERROR *******/\n"); + if( zErr ){ + fprintf(p->out, "/****** %s ******/\n", zErr); + sqlite3_free(zErr); + zErr = 0; + } + zQ2 = malloc( len+100 ); + if( zQ2==0 ) return rc; + sqlite3_snprintf(sizeof(zQ2), zQ2, "%s ORDER BY rowid DESC", zQuery); + rc = sqlite3_exec(p->db, zQ2, dump_callback, p, &zErr); + if( rc ){ + fprintf(p->out, "/****** ERROR: %s ******/\n", zErr); + }else{ + rc = SQLITE_CORRUPT; + } + sqlite3_free(zErr); + free(zQ2); + } + return rc; +} + +/* +** Text of a help message +*/ +static char zHelp[] = + ".backup ?DB? FILE Backup DB (default \"main\") to FILE\n" + ".bail ON|OFF Stop after hitting an error. Default OFF\n" + ".databases List names and files of attached databases\n" + ".dump ?TABLE? ... Dump the database in an SQL text format\n" + " If TABLE specified, only dump tables matching\n" + " LIKE pattern TABLE.\n" + ".echo ON|OFF Turn command echo on or off\n" + ".exit Exit this program\n" + ".explain ?ON|OFF? Turn output mode suitable for EXPLAIN on or off.\n" + " With no args, it turns EXPLAIN on.\n" + ".header(s) ON|OFF Turn display of headers on or off\n" + ".help Show this message\n" + ".import FILE TABLE Import data from FILE into TABLE\n" + ".indices ?TABLE? Show names of all indices\n" + " If TABLE specified, only show indices for tables\n" + " matching LIKE pattern TABLE.\n" +#ifdef SQLITE_ENABLE_IOTRACE + ".iotrace FILE Enable I/O diagnostic logging to FILE\n" +#endif +#ifndef SQLITE_OMIT_LOAD_EXTENSION + ".load FILE ?ENTRY? Load an extension library\n" +#endif + ".log FILE|off Turn logging on or off. FILE can be stderr/stdout\n" + ".mode MODE ?TABLE? Set output mode where MODE is one of:\n" + " csv Comma-separated values\n" + " column Left-aligned columns. (See .width)\n" + " html HTML code\n" + " insert SQL insert statements for TABLE\n" + " line One value per line\n" + " list Values delimited by .separator string\n" + " tabs Tab-separated values\n" + " tcl TCL list elements\n" + ".nullvalue STRING Print STRING in place of NULL values\n" + ".output FILENAME Send output to FILENAME\n" + ".output stdout Send output to the screen\n" + ".prompt MAIN CONTINUE Replace the standard prompts\n" + ".quit Exit this program\n" + ".read FILENAME Execute SQL in FILENAME\n" + ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE\n" + ".schema ?TABLE? Show the CREATE statements\n" + " If TABLE specified, only show tables matching\n" + " LIKE pattern TABLE.\n" + ".separator STRING Change separator used by output mode and .import\n" + ".show Show the current values for various settings\n" + ".stats ON|OFF Turn stats on or off\n" + ".tables ?TABLE? List names of tables\n" + " If TABLE specified, only list tables matching\n" + " LIKE pattern TABLE.\n" + ".timeout MS Try opening locked tables for MS milliseconds\n" + ".vfsname ?AUX? Print the name of the VFS stack\n" + ".width NUM1 NUM2 ... Set column widths for \"column\" mode\n" +; + +static char zTimerHelp[] = + ".timer ON|OFF Turn the CPU timer measurement on or off\n" +; + +/* Forward reference */ +static int process_input(struct callback_data *p, FILE *in); + +/* +** Make sure the database is open. If it is not, then open it. If +** the database fails to open, print an error message and exit. +*/ +static void open_db(struct callback_data *p){ + if( p->db==0 ){ + sqlite3_open(p->zDbFilename, &p->db); + db = p->db; + if( db && sqlite3_errcode(db)==SQLITE_OK ){ + sqlite3_create_function(db, "shellstatic", 0, SQLITE_UTF8, 0, + shellstaticFunc, 0, 0); + } + if( db==0 || SQLITE_OK!=sqlite3_errcode(db) ){ + fprintf(stderr,"Error: unable to open database \"%s\": %s\n", + p->zDbFilename, sqlite3_errmsg(db)); + exit(1); + } +#ifndef SQLITE_OMIT_LOAD_EXTENSION + sqlite3_enable_load_extension(p->db, 1); +#endif + } +} + +/* +** Do C-language style dequoting. +** +** \t -> tab +** \n -> newline +** \r -> carriage return +** \NNN -> ascii character NNN in octal +** \\ -> backslash +*/ +static void resolve_backslashes(char *z){ + int i, j; + char c; + for(i=j=0; (c = z[i])!=0; i++, j++){ + if( c=='\\' ){ + c = z[++i]; + if( c=='n' ){ + c = '\n'; + }else if( c=='t' ){ + c = '\t'; + }else if( c=='r' ){ + c = '\r'; + }else if( c>='0' && c<='7' ){ + c -= '0'; + if( z[i+1]>='0' && z[i+1]<='7' ){ + i++; + c = (c<<3) + z[i] - '0'; + if( z[i+1]>='0' && z[i+1]<='7' ){ + i++; + c = (c<<3) + z[i] - '0'; + } + } + } + } + z[j] = c; + } + z[j] = 0; +} + +/* +** Interpret zArg as a boolean value. Return either 0 or 1. +*/ +static int booleanValue(char *zArg){ + int val = atoi(zArg); + int j; + for(j=0; zArg[j]; j++){ + zArg[j] = ToLower(zArg[j]); + } + if( strcmp(zArg,"on")==0 ){ + val = 1; + }else if( strcmp(zArg,"yes")==0 ){ + val = 1; + } + return val; +} + +/* +** If an input line begins with "." then invoke this routine to +** process that line. +** +** Return 1 on error, 2 to exit, and 0 otherwise. +*/ +static int do_meta_command(char *zLine, struct callback_data *p){ + int i = 1; + int nArg = 0; + int n, c; + int rc = 0; + char *azArg[50]; + + /* Parse the input line into tokens. + */ + while( zLine[i] && nArg=3 && strncmp(azArg[0], "backup", n)==0 && nArg>1 && nArg<4){ + const char *zDestFile; + const char *zDb; + sqlite3 *pDest; + sqlite3_backup *pBackup; + if( nArg==2 ){ + zDestFile = azArg[1]; + zDb = "main"; + }else{ + zDestFile = azArg[2]; + zDb = azArg[1]; + } + rc = sqlite3_open(zDestFile, &pDest); + if( rc!=SQLITE_OK ){ + fprintf(stderr, "Error: cannot open \"%s\"\n", zDestFile); + sqlite3_close(pDest); + return 1; + } + open_db(p); + pBackup = sqlite3_backup_init(pDest, "main", p->db, zDb); + if( pBackup==0 ){ + fprintf(stderr, "Error: %s\n", sqlite3_errmsg(pDest)); + sqlite3_close(pDest); + return 1; + } + while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK ){} + sqlite3_backup_finish(pBackup); + if( rc==SQLITE_DONE ){ + rc = 0; + }else{ + fprintf(stderr, "Error: %s\n", sqlite3_errmsg(pDest)); + rc = 1; + } + sqlite3_close(pDest); + }else + + if( c=='b' && n>=3 && strncmp(azArg[0], "bail", n)==0 && nArg>1 && nArg<3 ){ + bail_on_error = booleanValue(azArg[1]); + }else + + if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 && nArg==1 ){ + struct callback_data data; + char *zErrMsg = 0; + open_db(p); + memcpy(&data, p, sizeof(data)); + data.showHeader = 1; + data.mode = MODE_Column; + data.colWidth[0] = 3; + data.colWidth[1] = 15; + data.colWidth[2] = 58; + data.cnt = 0; + sqlite3_exec(p->db, "PRAGMA database_list; ", callback, &data, &zErrMsg); + if( zErrMsg ){ + fprintf(stderr,"Error: %s\n", zErrMsg); + sqlite3_free(zErrMsg); + rc = 1; + } + }else + + if( c=='d' && strncmp(azArg[0], "dump", n)==0 && nArg<3 ){ + open_db(p); + /* When playing back a "dump", the content might appear in an order + ** which causes immediate foreign key constraints to be violated. + ** So disable foreign-key constraint enforcement to prevent problems. */ + fprintf(p->out, "PRAGMA foreign_keys=OFF;\n"); + fprintf(p->out, "BEGIN TRANSACTION;\n"); + p->writableSchema = 0; + sqlite3_exec(p->db, "SAVEPOINT dump; PRAGMA writable_schema=ON", 0, 0, 0); + p->nErr = 0; + if( nArg==1 ){ + run_schema_dump_query(p, + "SELECT name, type, sql FROM sqlite_master " + "WHERE sql NOT NULL AND type=='table' AND name!='sqlite_sequence'" + ); + run_schema_dump_query(p, + "SELECT name, type, sql FROM sqlite_master " + "WHERE name=='sqlite_sequence'" + ); + run_table_dump_query(p, + "SELECT sql FROM sqlite_master " + "WHERE sql NOT NULL AND type IN ('index','trigger','view')", 0 + ); + }else{ + int i; + for(i=1; iwritableSchema ){ + fprintf(p->out, "PRAGMA writable_schema=OFF;\n"); + p->writableSchema = 0; + } + sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0); + sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0); + fprintf(p->out, p->nErr ? "ROLLBACK; -- due to errors\n" : "COMMIT;\n"); + }else + + if( c=='e' && strncmp(azArg[0], "echo", n)==0 && nArg>1 && nArg<3 ){ + p->echoOn = booleanValue(azArg[1]); + }else + + if( c=='e' && strncmp(azArg[0], "exit", n)==0 && nArg==1 ){ + rc = 2; + }else + + if( c=='e' && strncmp(azArg[0], "explain", n)==0 && nArg<3 ){ + int val = nArg>=2 ? booleanValue(azArg[1]) : 1; + if(val == 1) { + if(!p->explainPrev.valid) { + p->explainPrev.valid = 1; + p->explainPrev.mode = p->mode; + p->explainPrev.showHeader = p->showHeader; + memcpy(p->explainPrev.colWidth,p->colWidth,sizeof(p->colWidth)); + } + /* We could put this code under the !p->explainValid + ** condition so that it does not execute if we are already in + ** explain mode. However, always executing it allows us an easy + ** was to reset to explain mode in case the user previously + ** did an .explain followed by a .width, .mode or .header + ** command. + */ + p->mode = MODE_Explain; + p->showHeader = 1; + memset(p->colWidth,0,ArraySize(p->colWidth)); + p->colWidth[0] = 4; /* addr */ + p->colWidth[1] = 13; /* opcode */ + p->colWidth[2] = 4; /* P1 */ + p->colWidth[3] = 4; /* P2 */ + p->colWidth[4] = 4; /* P3 */ + p->colWidth[5] = 13; /* P4 */ + p->colWidth[6] = 2; /* P5 */ + p->colWidth[7] = 13; /* Comment */ + }else if (p->explainPrev.valid) { + p->explainPrev.valid = 0; + p->mode = p->explainPrev.mode; + p->showHeader = p->explainPrev.showHeader; + memcpy(p->colWidth,p->explainPrev.colWidth,sizeof(p->colWidth)); + } + }else + + if( c=='h' && (strncmp(azArg[0], "header", n)==0 || + strncmp(azArg[0], "headers", n)==0) && nArg>1 && nArg<3 ){ + p->showHeader = booleanValue(azArg[1]); + }else + + if( c=='h' && strncmp(azArg[0], "help", n)==0 ){ + fprintf(stderr,"%s",zHelp); + if( HAS_TIMER ){ + fprintf(stderr,"%s",zTimerHelp); + } + }else + + if( c=='i' && strncmp(azArg[0], "import", n)==0 && nArg==3 ){ + char *zTable = azArg[2]; /* Insert data into this table */ + char *zFile = azArg[1]; /* The file from which to extract data */ + sqlite3_stmt *pStmt = NULL; /* A statement */ + int nCol; /* Number of columns in the table */ + int nByte; /* Number of bytes in an SQL string */ + int i, j; /* Loop counters */ + int nSep; /* Number of bytes in p->separator[] */ + char *zSql; /* An SQL statement */ + char *zLine; /* A single line of input from the file */ + char **azCol; /* zLine[] broken up into columns */ + char *zCommit; /* How to commit changes */ + FILE *in; /* The input file */ + int lineno = 0; /* Line number of input file */ + + open_db(p); + nSep = strlen30(p->separator); + if( nSep==0 ){ + fprintf(stderr, "Error: non-null separator required for import\n"); + return 1; + } + zSql = sqlite3_mprintf("SELECT * FROM %s", zTable); + if( zSql==0 ){ + fprintf(stderr, "Error: out of memory\n"); + return 1; + } + nByte = strlen30(zSql); + rc = sqlite3_prepare(p->db, zSql, -1, &pStmt, 0); + sqlite3_free(zSql); + if( rc ){ + if (pStmt) sqlite3_finalize(pStmt); + fprintf(stderr,"Error: %s\n", sqlite3_errmsg(db)); + return 1; + } + nCol = sqlite3_column_count(pStmt); + sqlite3_finalize(pStmt); + pStmt = 0; + if( nCol==0 ) return 0; /* no columns, no error */ + zSql = malloc( nByte + 20 + nCol*2 ); + if( zSql==0 ){ + fprintf(stderr, "Error: out of memory\n"); + return 1; + } + sqlite3_snprintf(nByte+20, zSql, "INSERT INTO %s VALUES(?", zTable); + j = strlen30(zSql); + for(i=1; idb, zSql, -1, &pStmt, 0); + free(zSql); + if( rc ){ + fprintf(stderr, "Error: %s\n", sqlite3_errmsg(db)); + if (pStmt) sqlite3_finalize(pStmt); + return 1; + } + in = fopen(zFile, "rb"); + if( in==0 ){ + fprintf(stderr, "Error: cannot open \"%s\"\n", zFile); + sqlite3_finalize(pStmt); + return 1; + } + azCol = malloc( sizeof(azCol[0])*(nCol+1) ); + if( azCol==0 ){ + fprintf(stderr, "Error: out of memory\n"); + fclose(in); + sqlite3_finalize(pStmt); + return 1; + } + sqlite3_exec(p->db, "BEGIN", 0, 0, 0); + zCommit = "COMMIT"; + while( (zLine = local_getline(0, in))!=0 ){ + char *z; + lineno++; + azCol[0] = zLine; + for(i=0, z=zLine; *z && *z!='\n' && *z!='\r'; z++){ + if( *z==p->separator[0] && strncmp(z, p->separator, nSep)==0 ){ + *z = 0; + i++; + if( idb, zCommit, 0, 0, 0); + }else + + if( c=='i' && strncmp(azArg[0], "indices", n)==0 && nArg<3 ){ + struct callback_data data; + char *zErrMsg = 0; + open_db(p); + memcpy(&data, p, sizeof(data)); + data.showHeader = 0; + data.mode = MODE_List; + if( nArg==1 ){ + rc = sqlite3_exec(p->db, + "SELECT name FROM sqlite_master " + "WHERE type='index' AND name NOT LIKE 'sqlite_%' " + "UNION ALL " + "SELECT name FROM sqlite_temp_master " + "WHERE type='index' " + "ORDER BY 1", + callback, &data, &zErrMsg + ); + }else{ + zShellStatic = azArg[1]; + rc = sqlite3_exec(p->db, + "SELECT name FROM sqlite_master " + "WHERE type='index' AND tbl_name LIKE shellstatic() " + "UNION ALL " + "SELECT name FROM sqlite_temp_master " + "WHERE type='index' AND tbl_name LIKE shellstatic() " + "ORDER BY 1", + callback, &data, &zErrMsg + ); + zShellStatic = 0; + } + if( zErrMsg ){ + fprintf(stderr,"Error: %s\n", zErrMsg); + sqlite3_free(zErrMsg); + rc = 1; + }else if( rc != SQLITE_OK ){ + fprintf(stderr,"Error: querying sqlite_master and sqlite_temp_master\n"); + rc = 1; + } + }else + +#ifdef SQLITE_ENABLE_IOTRACE + if( c=='i' && strncmp(azArg[0], "iotrace", n)==0 ){ + extern void (*sqlite3IoTrace)(const char*, ...); + if( iotrace && iotrace!=stdout ) fclose(iotrace); + iotrace = 0; + if( nArg<2 ){ + sqlite3IoTrace = 0; + }else if( strcmp(azArg[1], "-")==0 ){ + sqlite3IoTrace = iotracePrintf; + iotrace = stdout; + }else{ + iotrace = fopen(azArg[1], "w"); + if( iotrace==0 ){ + fprintf(stderr, "Error: cannot open \"%s\"\n", azArg[1]); + sqlite3IoTrace = 0; + rc = 1; + }else{ + sqlite3IoTrace = iotracePrintf; + } + } + }else +#endif + +#ifndef SQLITE_OMIT_LOAD_EXTENSION + if( c=='l' && strncmp(azArg[0], "load", n)==0 && nArg>=2 ){ + const char *zFile, *zProc; + char *zErrMsg = 0; + zFile = azArg[1]; + zProc = nArg>=3 ? azArg[2] : 0; + open_db(p); + rc = sqlite3_load_extension(p->db, zFile, zProc, &zErrMsg); + if( rc!=SQLITE_OK ){ + fprintf(stderr, "Error: %s\n", zErrMsg); + sqlite3_free(zErrMsg); + rc = 1; + } + }else +#endif + + if( c=='l' && strncmp(azArg[0], "log", n)==0 && nArg>=2 ){ + const char *zFile = azArg[1]; + if( p->pLog && p->pLog!=stdout && p->pLog!=stderr ){ + fclose(p->pLog); + p->pLog = 0; + } + if( strcmp(zFile,"stdout")==0 ){ + p->pLog = stdout; + }else if( strcmp(zFile, "stderr")==0 ){ + p->pLog = stderr; + }else if( strcmp(zFile, "off")==0 ){ + p->pLog = 0; + }else{ + p->pLog = fopen(zFile, "w"); + if( p->pLog==0 ){ + fprintf(stderr, "Error: cannot open \"%s\"\n", zFile); + } + } + }else + + if( c=='m' && strncmp(azArg[0], "mode", n)==0 && nArg==2 ){ + int n2 = strlen30(azArg[1]); + if( (n2==4 && strncmp(azArg[1],"line",n2)==0) + || + (n2==5 && strncmp(azArg[1],"lines",n2)==0) ){ + p->mode = MODE_Line; + }else if( (n2==6 && strncmp(azArg[1],"column",n2)==0) + || + (n2==7 && strncmp(azArg[1],"columns",n2)==0) ){ + p->mode = MODE_Column; + }else if( n2==4 && strncmp(azArg[1],"list",n2)==0 ){ + p->mode = MODE_List; + }else if( n2==4 && strncmp(azArg[1],"html",n2)==0 ){ + p->mode = MODE_Html; + }else if( n2==3 && strncmp(azArg[1],"tcl",n2)==0 ){ + p->mode = MODE_Tcl; + }else if( n2==3 && strncmp(azArg[1],"csv",n2)==0 ){ + p->mode = MODE_Csv; + sqlite3_snprintf(sizeof(p->separator), p->separator, ","); + }else if( n2==4 && strncmp(azArg[1],"tabs",n2)==0 ){ + p->mode = MODE_List; + sqlite3_snprintf(sizeof(p->separator), p->separator, "\t"); + }else if( n2==6 && strncmp(azArg[1],"insert",n2)==0 ){ + p->mode = MODE_Insert; + set_table_name(p, "table"); + }else { + fprintf(stderr,"Error: mode should be one of: " + "column csv html insert line list tabs tcl\n"); + rc = 1; + } + }else + + if( c=='m' && strncmp(azArg[0], "mode", n)==0 && nArg==3 ){ + int n2 = strlen30(azArg[1]); + if( n2==6 && strncmp(azArg[1],"insert",n2)==0 ){ + p->mode = MODE_Insert; + set_table_name(p, azArg[2]); + }else { + fprintf(stderr, "Error: invalid arguments: " + " \"%s\". Enter \".help\" for help\n", azArg[2]); + rc = 1; + } + }else + + if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 && nArg==2 ) { + sqlite3_snprintf(sizeof(p->nullvalue), p->nullvalue, + "%.*s", (int)ArraySize(p->nullvalue)-1, azArg[1]); + }else + + if( c=='o' && strncmp(azArg[0], "output", n)==0 && nArg==2 ){ + if( p->out!=stdout ){ + fclose(p->out); + } + if( strcmp(azArg[1],"stdout")==0 ){ + p->out = stdout; + sqlite3_snprintf(sizeof(p->outfile), p->outfile, "stdout"); + }else{ + p->out = fopen(azArg[1], "wb"); + if( p->out==0 ){ + fprintf(stderr,"Error: cannot write to \"%s\"\n", azArg[1]); + p->out = stdout; + rc = 1; + } else { + sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", azArg[1]); + } + } + }else + + if( c=='p' && strncmp(azArg[0], "prompt", n)==0 && (nArg==2 || nArg==3)){ + if( nArg >= 2) { + strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1); + } + if( nArg >= 3) { + strncpy(continuePrompt,azArg[2],(int)ArraySize(continuePrompt)-1); + } + }else + + if( c=='q' && strncmp(azArg[0], "quit", n)==0 && nArg==1 ){ + rc = 2; + }else + + if( c=='r' && n>=3 && strncmp(azArg[0], "read", n)==0 && nArg==2 ){ + FILE *alt = fopen(azArg[1], "rb"); + if( alt==0 ){ + fprintf(stderr,"Error: cannot open \"%s\"\n", azArg[1]); + rc = 1; + }else{ + rc = process_input(p, alt); + fclose(alt); + } + }else + + if( c=='r' && n>=3 && strncmp(azArg[0], "restore", n)==0 && nArg>1 && nArg<4){ + const char *zSrcFile; + const char *zDb; + sqlite3 *pSrc; + sqlite3_backup *pBackup; + int nTimeout = 0; + + if( nArg==2 ){ + zSrcFile = azArg[1]; + zDb = "main"; + }else{ + zSrcFile = azArg[2]; + zDb = azArg[1]; + } + rc = sqlite3_open(zSrcFile, &pSrc); + if( rc!=SQLITE_OK ){ + fprintf(stderr, "Error: cannot open \"%s\"\n", zSrcFile); + sqlite3_close(pSrc); + return 1; + } + open_db(p); + pBackup = sqlite3_backup_init(p->db, zDb, pSrc, "main"); + if( pBackup==0 ){ + fprintf(stderr, "Error: %s\n", sqlite3_errmsg(p->db)); + sqlite3_close(pSrc); + return 1; + } + while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK + || rc==SQLITE_BUSY ){ + if( rc==SQLITE_BUSY ){ + if( nTimeout++ >= 3 ) break; + sqlite3_sleep(100); + } + } + sqlite3_backup_finish(pBackup); + if( rc==SQLITE_DONE ){ + rc = 0; + }else if( rc==SQLITE_BUSY || rc==SQLITE_LOCKED ){ + fprintf(stderr, "Error: source database is busy\n"); + rc = 1; + }else{ + fprintf(stderr, "Error: %s\n", sqlite3_errmsg(p->db)); + rc = 1; + } + sqlite3_close(pSrc); + }else + + if( c=='s' && strncmp(azArg[0], "schema", n)==0 && nArg<3 ){ + struct callback_data data; + char *zErrMsg = 0; + open_db(p); + memcpy(&data, p, sizeof(data)); + data.showHeader = 0; + data.mode = MODE_Semi; + if( nArg>1 ){ + int i; + for(i=0; azArg[1][i]; i++) azArg[1][i] = ToLower(azArg[1][i]); + if( strcmp(azArg[1],"sqlite_master")==0 ){ + char *new_argv[2], *new_colv[2]; + new_argv[0] = "CREATE TABLE sqlite_master (\n" + " type text,\n" + " name text,\n" + " tbl_name text,\n" + " rootpage integer,\n" + " sql text\n" + ")"; + new_argv[1] = 0; + new_colv[0] = "sql"; + new_colv[1] = 0; + callback(&data, 1, new_argv, new_colv); + rc = SQLITE_OK; + }else if( strcmp(azArg[1],"sqlite_temp_master")==0 ){ + char *new_argv[2], *new_colv[2]; + new_argv[0] = "CREATE TEMP TABLE sqlite_temp_master (\n" + " type text,\n" + " name text,\n" + " tbl_name text,\n" + " rootpage integer,\n" + " sql text\n" + ")"; + new_argv[1] = 0; + new_colv[0] = "sql"; + new_colv[1] = 0; + callback(&data, 1, new_argv, new_colv); + rc = SQLITE_OK; + }else{ + zShellStatic = azArg[1]; + rc = sqlite3_exec(p->db, + "SELECT sql FROM " + " (SELECT sql sql, type type, tbl_name tbl_name, name name" + " FROM sqlite_master UNION ALL" + " SELECT sql, type, tbl_name, name FROM sqlite_temp_master) " + "WHERE lower(tbl_name) LIKE shellstatic()" + " AND type!='meta' AND sql NOTNULL " + "ORDER BY substr(type,2,1), name", + callback, &data, &zErrMsg); + zShellStatic = 0; + } + }else{ + rc = sqlite3_exec(p->db, + "SELECT sql FROM " + " (SELECT sql sql, type type, tbl_name tbl_name, name name" + " FROM sqlite_master UNION ALL" + " SELECT sql, type, tbl_name, name FROM sqlite_temp_master) " + "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%'" + "ORDER BY substr(type,2,1), name", + callback, &data, &zErrMsg + ); + } + if( zErrMsg ){ + fprintf(stderr,"Error: %s\n", zErrMsg); + sqlite3_free(zErrMsg); + rc = 1; + }else if( rc != SQLITE_OK ){ + fprintf(stderr,"Error: querying schema information\n"); + rc = 1; + }else{ + rc = 0; + } + }else + + if( c=='s' && strncmp(azArg[0], "separator", n)==0 && nArg==2 ){ + sqlite3_snprintf(sizeof(p->separator), p->separator, + "%.*s", (int)sizeof(p->separator)-1, azArg[1]); + }else + + if( c=='s' && strncmp(azArg[0], "show", n)==0 && nArg==1 ){ + int i; + fprintf(p->out,"%9.9s: %s\n","echo", p->echoOn ? "on" : "off"); + fprintf(p->out,"%9.9s: %s\n","explain", p->explainPrev.valid ? "on" :"off"); + fprintf(p->out,"%9.9s: %s\n","headers", p->showHeader ? "on" : "off"); + fprintf(p->out,"%9.9s: %s\n","mode", modeDescr[p->mode]); + fprintf(p->out,"%9.9s: ", "nullvalue"); + output_c_string(p->out, p->nullvalue); + fprintf(p->out, "\n"); + fprintf(p->out,"%9.9s: %s\n","output", + strlen30(p->outfile) ? p->outfile : "stdout"); + fprintf(p->out,"%9.9s: ", "separator"); + output_c_string(p->out, p->separator); + fprintf(p->out, "\n"); + fprintf(p->out,"%9.9s: %s\n","stats", p->statsOn ? "on" : "off"); + fprintf(p->out,"%9.9s: ","width"); + for (i=0;i<(int)ArraySize(p->colWidth) && p->colWidth[i] != 0;i++) { + fprintf(p->out,"%d ",p->colWidth[i]); + } + fprintf(p->out,"\n"); + }else + + if( c=='s' && strncmp(azArg[0], "stats", n)==0 && nArg>1 && nArg<3 ){ + p->statsOn = booleanValue(azArg[1]); + }else + + if( c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0 && nArg<3 ){ + char **azResult; + int nRow; + char *zErrMsg; + open_db(p); + if( nArg==1 ){ + rc = sqlite3_get_table(p->db, + "SELECT name FROM sqlite_master " + "WHERE type IN ('table','view') AND name NOT LIKE 'sqlite_%' " + "UNION ALL " + "SELECT name FROM sqlite_temp_master " + "WHERE type IN ('table','view') " + "ORDER BY 1", + &azResult, &nRow, 0, &zErrMsg + ); + }else{ + zShellStatic = azArg[1]; + rc = sqlite3_get_table(p->db, + "SELECT name FROM sqlite_master " + "WHERE type IN ('table','view') AND name LIKE shellstatic() " + "UNION ALL " + "SELECT name FROM sqlite_temp_master " + "WHERE type IN ('table','view') AND name LIKE shellstatic() " + "ORDER BY 1", + &azResult, &nRow, 0, &zErrMsg + ); + zShellStatic = 0; + } + if( zErrMsg ){ + fprintf(stderr,"Error: %s\n", zErrMsg); + sqlite3_free(zErrMsg); + rc = 1; + }else if( rc != SQLITE_OK ){ + fprintf(stderr,"Error: querying sqlite_master and sqlite_temp_master\n"); + rc = 1; + }else{ + int len, maxlen = 0; + int i, j; + int nPrintCol, nPrintRow; + for(i=1; i<=nRow; i++){ + if( azResult[i]==0 ) continue; + len = strlen30(azResult[i]); + if( len>maxlen ) maxlen = len; + } + nPrintCol = 80/(maxlen+2); + if( nPrintCol<1 ) nPrintCol = 1; + nPrintRow = (nRow + nPrintCol - 1)/nPrintCol; + for(i=0; i=8 && strncmp(azArg[0], "testctrl", n)==0 && nArg>=2 ){ + static const struct { + const char *zCtrlName; /* Name of a test-control option */ + int ctrlCode; /* Integer code for that option */ + } aCtrl[] = { + { "prng_save", SQLITE_TESTCTRL_PRNG_SAVE }, + { "prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE }, + { "prng_reset", SQLITE_TESTCTRL_PRNG_RESET }, + { "bitvec_test", SQLITE_TESTCTRL_BITVEC_TEST }, + { "fault_install", SQLITE_TESTCTRL_FAULT_INSTALL }, + { "benign_malloc_hooks", SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS }, + { "pending_byte", SQLITE_TESTCTRL_PENDING_BYTE }, + { "assert", SQLITE_TESTCTRL_ASSERT }, + { "always", SQLITE_TESTCTRL_ALWAYS }, + { "reserve", SQLITE_TESTCTRL_RESERVE }, + { "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS }, + { "iskeyword", SQLITE_TESTCTRL_ISKEYWORD }, + { "scratchmalloc", SQLITE_TESTCTRL_SCRATCHMALLOC }, + }; + int testctrl = -1; + int rc = 0; + int i, n; + open_db(p); + + /* convert testctrl text option to value. allow any unique prefix + ** of the option name, or a numerical value. */ + n = strlen30(azArg[1]); + for(i=0; i<(int)(sizeof(aCtrl)/sizeof(aCtrl[0])); i++){ + if( strncmp(azArg[1], aCtrl[i].zCtrlName, n)==0 ){ + if( testctrl<0 ){ + testctrl = aCtrl[i].ctrlCode; + }else{ + fprintf(stderr, "ambiguous option name: \"%s\"\n", azArg[1]); + testctrl = -1; + break; + } + } + } + if( testctrl<0 ) testctrl = atoi(azArg[1]); + if( (testctrlSQLITE_TESTCTRL_LAST) ){ + fprintf(stderr,"Error: invalid testctrl option: %s\n", azArg[1]); + }else{ + switch(testctrl){ + + /* sqlite3_test_control(int, db, int) */ + case SQLITE_TESTCTRL_OPTIMIZATIONS: + case SQLITE_TESTCTRL_RESERVE: + if( nArg==3 ){ + int opt = (int)strtol(azArg[2], 0, 0); + rc = sqlite3_test_control(testctrl, p->db, opt); + printf("%d (0x%08x)\n", rc, rc); + } else { + fprintf(stderr,"Error: testctrl %s takes a single int option\n", + azArg[1]); + } + break; + + /* sqlite3_test_control(int) */ + case SQLITE_TESTCTRL_PRNG_SAVE: + case SQLITE_TESTCTRL_PRNG_RESTORE: + case SQLITE_TESTCTRL_PRNG_RESET: + if( nArg==2 ){ + rc = sqlite3_test_control(testctrl); + printf("%d (0x%08x)\n", rc, rc); + } else { + fprintf(stderr,"Error: testctrl %s takes no options\n", azArg[1]); + } + break; + + /* sqlite3_test_control(int, uint) */ + case SQLITE_TESTCTRL_PENDING_BYTE: + if( nArg==3 ){ + unsigned int opt = (unsigned int)atoi(azArg[2]); + rc = sqlite3_test_control(testctrl, opt); + printf("%d (0x%08x)\n", rc, rc); + } else { + fprintf(stderr,"Error: testctrl %s takes a single unsigned" + " int option\n", azArg[1]); + } + break; + + /* sqlite3_test_control(int, int) */ + case SQLITE_TESTCTRL_ASSERT: + case SQLITE_TESTCTRL_ALWAYS: + if( nArg==3 ){ + int opt = atoi(azArg[2]); + rc = sqlite3_test_control(testctrl, opt); + printf("%d (0x%08x)\n", rc, rc); + } else { + fprintf(stderr,"Error: testctrl %s takes a single int option\n", + azArg[1]); + } + break; + + /* sqlite3_test_control(int, char *) */ +#ifdef SQLITE_N_KEYWORD + case SQLITE_TESTCTRL_ISKEYWORD: + if( nArg==3 ){ + const char *opt = azArg[2]; + rc = sqlite3_test_control(testctrl, opt); + printf("%d (0x%08x)\n", rc, rc); + } else { + fprintf(stderr,"Error: testctrl %s takes a single char * option\n", + azArg[1]); + } + break; +#endif + + case SQLITE_TESTCTRL_BITVEC_TEST: + case SQLITE_TESTCTRL_FAULT_INSTALL: + case SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS: + case SQLITE_TESTCTRL_SCRATCHMALLOC: + default: + fprintf(stderr,"Error: CLI support for testctrl %s not implemented\n", + azArg[1]); + break; + } + } + }else + + if( c=='t' && n>4 && strncmp(azArg[0], "timeout", n)==0 && nArg==2 ){ + open_db(p); + sqlite3_busy_timeout(p->db, atoi(azArg[1])); + }else + + if( HAS_TIMER && c=='t' && n>=5 && strncmp(azArg[0], "timer", n)==0 + && nArg==2 + ){ + enableTimer = booleanValue(azArg[1]); + }else + + if( c=='v' && strncmp(azArg[0], "version", n)==0 ){ + printf("SQLite %s %s\n" /*extra-version-info*/, + sqlite3_libversion(), sqlite3_sourceid()); + }else + + if( c=='v' && strncmp(azArg[0], "vfsname", n)==0 ){ + const char *zDbName = nArg==2 ? azArg[1] : "main"; + char *zVfsName = 0; + if( p->db ){ + sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFSNAME, &zVfsName); + if( zVfsName ){ + printf("%s\n", zVfsName); + sqlite3_free(zVfsName); + } + } + }else + + if( c=='w' && strncmp(azArg[0], "width", n)==0 && nArg>1 ){ + int j; + assert( nArg<=ArraySize(azArg) ); + for(j=1; jcolWidth); j++){ + p->colWidth[j-1] = atoi(azArg[j]); + } + }else + + { + fprintf(stderr, "Error: unknown command or invalid arguments: " + " \"%s\". Enter \".help\" for help\n", azArg[0]); + rc = 1; + } + + return rc; +} + +/* +** Return TRUE if a semicolon occurs anywhere in the first N characters +** of string z[]. +*/ +static int _contains_semicolon(const char *z, int N){ + int i; + for(i=0; iout); + free(zLine); + zLine = one_input_line(zSql, in); + if( zLine==0 ){ + break; /* We have reached EOF */ + } + if( seenInterrupt ){ + if( in!=0 ) break; + seenInterrupt = 0; + } + lineno++; + if( (zSql==0 || zSql[0]==0) && _all_whitespace(zLine) ) continue; + if( zLine && zLine[0]=='.' && nSql==0 ){ + if( p->echoOn ) printf("%s\n", zLine); + rc = do_meta_command(zLine, p); + if( rc==2 ){ /* exit requested */ + break; + }else if( rc ){ + errCnt++; + } + continue; + } + if( _is_command_terminator(zLine) && _is_complete(zSql, nSql) ){ + memcpy(zLine,";",2); + } + nSqlPrior = nSql; + if( zSql==0 ){ + int i; + for(i=0; zLine[i] && IsSpace(zLine[i]); i++){} + if( zLine[i]!=0 ){ + nSql = strlen30(zLine); + zSql = malloc( nSql+3 ); + if( zSql==0 ){ + fprintf(stderr, "Error: out of memory\n"); + exit(1); + } + memcpy(zSql, zLine, nSql+1); + startline = lineno; + } + }else{ + int len = strlen30(zLine); + zSql = realloc( zSql, nSql + len + 4 ); + if( zSql==0 ){ + fprintf(stderr,"Error: out of memory\n"); + exit(1); + } + zSql[nSql++] = '\n'; + memcpy(&zSql[nSql], zLine, len+1); + nSql += len; + } + if( zSql && _contains_semicolon(&zSql[nSqlPrior], nSql-nSqlPrior) + && sqlite3_complete(zSql) ){ + p->cnt = 0; + open_db(p); + BEGIN_TIMER; + rc = shell_exec(p->db, zSql, shell_callback, p, &zErrMsg); + END_TIMER; + if( rc || zErrMsg ){ + char zPrefix[100]; + if( in!=0 || !stdin_is_interactive ){ + sqlite3_snprintf(sizeof(zPrefix), zPrefix, + "Error: near line %d:", startline); + }else{ + sqlite3_snprintf(sizeof(zPrefix), zPrefix, "Error:"); + } + if( zErrMsg!=0 ){ + fprintf(stderr, "%s %s\n", zPrefix, zErrMsg); + sqlite3_free(zErrMsg); + zErrMsg = 0; + }else{ + fprintf(stderr, "%s %s\n", zPrefix, sqlite3_errmsg(p->db)); + } + errCnt++; + } + free(zSql); + zSql = 0; + nSql = 0; + } + } + if( zSql ){ + if( !_all_whitespace(zSql) ){ + fprintf(stderr, "Error: incomplete SQL: %s\n", zSql); + } + free(zSql); + } + free(zLine); + return errCnt; +} + +/* +** Return a pathname which is the user's home directory. A +** 0 return indicates an error of some kind. Space to hold the +** resulting string is obtained from malloc(). The calling +** function should free the result. +*/ +static char *find_home_dir(void){ + char *home_dir = NULL; + +#if !defined(_WIN32) && !defined(WIN32) && !defined(__OS2__) && !defined(_WIN32_WCE) && !defined(__RTP__) && !defined(_WRS_KERNEL) + struct passwd *pwent; + uid_t uid = getuid(); + if( (pwent=getpwuid(uid)) != NULL) { + home_dir = pwent->pw_dir; + } +#endif + +#if defined(_WIN32_WCE) + /* Windows CE (arm-wince-mingw32ce-gcc) does not provide getenv() + */ + home_dir = strdup("/"); +#else + +#if defined(_WIN32) || defined(WIN32) || defined(__OS2__) + if (!home_dir) { + home_dir = getenv("USERPROFILE"); + } +#endif + + if (!home_dir) { + home_dir = getenv("HOME"); + } + +#if defined(_WIN32) || defined(WIN32) || defined(__OS2__) + if (!home_dir) { + char *zDrive, *zPath; + int n; + zDrive = getenv("HOMEDRIVE"); + zPath = getenv("HOMEPATH"); + if( zDrive && zPath ){ + n = strlen30(zDrive) + strlen30(zPath) + 1; + home_dir = malloc( n ); + if( home_dir==0 ) return 0; + sqlite3_snprintf(n, home_dir, "%s%s", zDrive, zPath); + return home_dir; + } + home_dir = "c:\\"; + } +#endif + +#endif /* !_WIN32_WCE */ + + if( home_dir ){ + int n = strlen30(home_dir) + 1; + char *z = malloc( n ); + if( z ) memcpy(z, home_dir, n); + home_dir = z; + } + + return home_dir; +} + +/* +** Read input from the file given by sqliterc_override. Or if that +** parameter is NULL, take input from ~/.sqliterc +** +** Returns the number of errors. +*/ +static int process_sqliterc( + struct callback_data *p, /* Configuration data */ + const char *sqliterc_override /* Name of config file. NULL to use default */ +){ + char *home_dir = NULL; + const char *sqliterc = sqliterc_override; + char *zBuf = 0; + FILE *in = NULL; + int nBuf; + int rc = 0; + + if (sqliterc == NULL) { + home_dir = find_home_dir(); + if( home_dir==0 ){ +#if !defined(__RTP__) && !defined(_WRS_KERNEL) + fprintf(stderr,"%s: Error: cannot locate your home directory\n", Argv0); +#endif + return 1; + } + nBuf = strlen30(home_dir) + 16; + zBuf = malloc( nBuf ); + if( zBuf==0 ){ + fprintf(stderr,"%s: Error: out of memory\n",Argv0); + return 1; + } + sqlite3_snprintf(nBuf, zBuf,"%s/.sqliterc",home_dir); + free(home_dir); + sqliterc = (const char*)zBuf; + } + in = fopen(sqliterc,"rb"); + if( in ){ + if( stdin_is_interactive ){ + fprintf(stderr,"-- Loading resources from %s\n",sqliterc); + } + rc = process_input(p,in); + fclose(in); + } + free(zBuf); + return rc; +} + +/* +** Show available command line options +*/ +static const char zOptions[] = + " -help show this message\n" + " -init filename read/process named file\n" + " -echo print commands before execution\n" + " -[no]header turn headers on or off\n" + " -bail stop after hitting an error\n" + " -interactive force interactive I/O\n" + " -batch force batch I/O\n" + " -column set output mode to 'column'\n" + " -csv set output mode to 'csv'\n" + " -html set output mode to HTML\n" + " -line set output mode to 'line'\n" + " -list set output mode to 'list'\n" + " -separator 'x' set output field separator (|)\n" + " -stats print memory stats before each finalize\n" + " -nullvalue 'text' set text string for NULL values\n" + " -version show SQLite version\n" + " -vfs NAME use NAME as the default VFS\n" +#ifdef SQLITE_ENABLE_VFSTRACE + " -vfstrace enable tracing of all VFS calls\n" +#endif +#ifdef SQLITE_ENABLE_MULTIPLEX + " -multiplex enable the multiplexor VFS\n" +#endif +; +static void usage(int showDetail){ + fprintf(stderr, + "Usage: %s [OPTIONS] FILENAME [SQL]\n" + "FILENAME is the name of an SQLite database. A new database is created\n" + "if the file does not previously exist.\n", Argv0); + if( showDetail ){ + fprintf(stderr, "OPTIONS include:\n%s", zOptions); + }else{ + fprintf(stderr, "Use the -help option for additional information\n"); + } + exit(1); +} + +/* +** Initialize the state information in data +*/ +static void main_init(struct callback_data *data) { + memset(data, 0, sizeof(*data)); + data->mode = MODE_List; + memcpy(data->separator,"|", 2); + data->showHeader = 0; + sqlite3_config(SQLITE_CONFIG_URI, 1); + sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data); + sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> "); + sqlite3_snprintf(sizeof(continuePrompt), continuePrompt," ...> "); + sqlite3_config(SQLITE_CONFIG_SINGLETHREAD); +} + +int main(int argc, char **argv){ + char *zErrMsg = 0; + struct callback_data data; + const char *zInitFile = 0; + char *zFirstCmd = 0; + int i; + int rc = 0; + + if( strcmp(sqlite3_sourceid(),SQLITE_SOURCE_ID)!=0 ){ + fprintf(stderr, "SQLite header and source version mismatch\n%s\n%s\n", + sqlite3_sourceid(), SQLITE_SOURCE_ID); + exit(1); + } + Argv0 = argv[0]; + main_init(&data); + stdin_is_interactive = isatty(0); + + /* Make sure we have a valid signal handler early, before anything + ** else is done. + */ +#ifdef SIGINT + signal(SIGINT, interrupt_handler); +#endif + + /* Do an initial pass through the command-line argument to locate + ** the name of the database file, the name of the initialization file, + ** the size of the alternative malloc heap, + ** and the first command to execute. + */ + for(i=1; i0x7fff0000 ) szHeap = 0x7fff0000; + sqlite3_config(SQLITE_CONFIG_HEAP, malloc((int)szHeap), (int)szHeap, 64); +#endif +#ifdef SQLITE_ENABLE_VFSTRACE + }else if( strcmp(argv[i],"-vfstrace")==0 ){ + extern int vfstrace_register( + const char *zTraceName, + const char *zOldVfsName, + int (*xOut)(const char*,void*), + void *pOutArg, + int makeDefault + ); + vfstrace_register("trace",0,(int(*)(const char*,void*))fputs,stderr,1); +#endif +#ifdef SQLITE_ENABLE_MULTIPLEX + }else if( strcmp(argv[i],"-multiplex")==0 ){ + extern int sqlite3_multiple_initialize(const char*,int); + sqlite3_multiplex_initialize(0, 1); +#endif + }else if( strcmp(argv[i],"-vfs")==0 ){ + sqlite3_vfs *pVfs = sqlite3_vfs_find(argv[++i]); + if( pVfs ){ + sqlite3_vfs_register(pVfs, 1); + }else{ + fprintf(stderr, "no such VFS: \"%s\"\n", argv[i]); + exit(1); + } + } + } + if( i0 ){ + return rc; + } + + /* Make a second pass through the command-line argument and set + ** options. This second pass is delayed until after the initialization + ** file is processed so that the command-line arguments will override + ** settings in the initialization file. + */ + for(i=1; i=argc){ + fprintf(stderr,"%s: Error: missing argument for option: %s\n", Argv0, z); + fprintf(stderr,"Use -help for a list of options.\n"); + return 1; + } + sqlite3_snprintf(sizeof(data.separator), data.separator, + "%.*s",(int)sizeof(data.separator)-1,argv[i]); + }else if( strcmp(z,"-nullvalue")==0 ){ + i++; + if(i>=argc){ + fprintf(stderr,"%s: Error: missing argument for option: %s\n", Argv0, z); + fprintf(stderr,"Use -help for a list of options.\n"); + return 1; + } + sqlite3_snprintf(sizeof(data.nullvalue), data.nullvalue, + "%.*s",(int)sizeof(data.nullvalue)-1,argv[i]); + }else if( strcmp(z,"-header")==0 ){ + data.showHeader = 1; + }else if( strcmp(z,"-noheader")==0 ){ + data.showHeader = 0; + }else if( strcmp(z,"-echo")==0 ){ + data.echoOn = 1; + }else if( strcmp(z,"-stats")==0 ){ + data.statsOn = 1; + }else if( strcmp(z,"-bail")==0 ){ + bail_on_error = 1; + }else if( strcmp(z,"-version")==0 ){ + printf("%s %s\n", sqlite3_libversion(), sqlite3_sourceid()); + return 0; + }else if( strcmp(z,"-interactive")==0 ){ + stdin_is_interactive = 1; + }else if( strcmp(z,"-batch")==0 ){ + stdin_is_interactive = 0; + }else if( strcmp(z,"-heap")==0 ){ + i++; + }else if( strcmp(z,"-vfs")==0 ){ + i++; +#ifdef SQLITE_ENABLE_VFSTRACE + }else if( strcmp(z,"-vfstrace")==0 ){ + i++; +#endif +#ifdef SQLITE_ENABLE_MULTIPLEX + }else if( strcmp(z,"-multiplex")==0 ){ + i++; +#endif + }else if( strcmp(z,"-help")==0 || strcmp(z, "--help")==0 ){ + usage(1); + }else{ + fprintf(stderr,"%s: Error: unknown option: %s\n", Argv0, z); + fprintf(stderr,"Use -help for a list of options.\n"); + return 1; + } + } + + if( zFirstCmd ){ + /* Run just the command that follows the database name + */ + if( zFirstCmd[0]=='.' ){ + rc = do_meta_command(zFirstCmd, &data); + }else{ + open_db(&data); + rc = shell_exec(data.db, zFirstCmd, shell_callback, &data, &zErrMsg); + if( zErrMsg!=0 ){ + fprintf(stderr,"Error: %s\n", zErrMsg); + return rc!=0 ? rc : 1; + }else if( rc!=0 ){ + fprintf(stderr,"Error: unable to process SQL \"%s\"\n", zFirstCmd); + return rc; + } + } + }else{ + /* Run commands received from standard input + */ + if( stdin_is_interactive ){ + char *zHome; + char *zHistory = 0; + int nHistory; + printf( + "SQLite version %s %.19s\n" /*extra-version-info*/ + "Enter \".help\" for instructions\n" + "Enter SQL statements terminated with a \";\"\n", + sqlite3_libversion(), sqlite3_sourceid() + ); + zHome = find_home_dir(); + if( zHome ){ + nHistory = strlen30(zHome) + 20; + if( (zHistory = malloc(nHistory))!=0 ){ + sqlite3_snprintf(nHistory, zHistory,"%s/.sqlite_history", zHome); + } + } +#if defined(HAVE_READLINE) && HAVE_READLINE==1 + if( zHistory ) read_history(zHistory); +#endif + rc = process_input(&data, 0); + if( zHistory ){ + stifle_history(100); + write_history(zHistory); + free(zHistory); + } + free(zHome); + }else{ + rc = process_input(&data, stdin); + } + } + set_table_name(&data, 0); + if( data.db ){ + sqlite3_close(data.db); + } + return rc; +} diff --git a/external/public-domain/sqlite/dist/sqlite3.1 b/external/public-domain/sqlite/dist/sqlite3.1 new file mode 100644 index 000000000..80da46e18 --- /dev/null +++ b/external/public-domain/sqlite/dist/sqlite3.1 @@ -0,0 +1,190 @@ +.\" $NetBSD: sqlite3.1,v 1.5 2012/12/21 19:26:39 njoly Exp $ +.Dd December 16, 2012 +.Dt SQLITE3 1 +.Os +.Sh NAME +.Nm sqlite3 +.Nd A command line interface for SQLite version 3 +.Sh SYNOPSIS +.Nm +.Op Ar options +.Op Ar databasefile +.Op Ar SQL +.Sh DESCRIPTION +.Nm +is a terminal-based front-end to the SQLite library that can evaluate +queries interactively and display the results in multiple formats. +.Nm +can also be used within shell scripts and other applications to provide +batch processing features. +.Pp +To start a +.Nm +interactive session, invoke the +.Nm +command and optionally provide the name of a database file. +If the database file does not exist, it will be created. +If the database file does exist, it will be opened. +.Pp +For example, to create a new database file named "mydata.db", create +a table named "memos" and insert a couple of records into that table: +.Bd -literal -offset indent +$ sqlite3 mydata.db +SQLite version 3.1.3 +Enter ".help" for instructions +sqlite> create table memos(text, priority INTEGER); +sqlite> insert into memos values('deliver project description', 10); +sqlite> insert into memos values('lunch with Christine', 100); +sqlite> select * from memos; +deliver project description|10 +lunch with Christine|100 +sqlite> +.Ed +.Pp +If no database name is supplied, the +.Em ATTACH +sql command can be used +to attach to existing or create new database files. +.Em ATTACH +can also be used to attach to multiple databases within the same +interactive session. +This is useful for migrating data between databases, +possibly changing the schema along the way. +.Pp +Optionally, a SQL statement or set of SQL statements can be supplied as +a single argument. +Multiple statements should be separated by semi-colons. +.Pp +For example: +.Bd -literal -offset indent +$ sqlite3 -line mydata.db 'select * from memos where priority > 20;' + text = lunch with Christine + priority = 100 +.Ed +.Ss SQLITE META-COMMANDS +The interactive interpreter offers a set of meta-commands that can be +used to control the output format, examine the currently attached +database files, or perform administrative operations upon the +attached databases (such as rebuilding indices). +Meta-commands are always prefixed with a dot +.Dq \&. . +.Pp +A list of available meta-commands can be viewed at any time by issuing +the '.help' command. +For example: +.Bd -literal -offset indent +sqlite> .help +\&.databases List names and files of attached databases +\&.dump ?TABLE? ... Dump the database in an SQL text format +\&.echo ON|OFF Turn command echo on or off +\&.exit Exit this program +\&.explain ON|OFF Turn output mode suitable for EXPLAIN on or off. +\&.header(s) ON|OFF Turn display of headers on or off +\&.help Show this message +\&.import FILE TABLE Import data from FILE into TABLE +\&.indices TABLE Show names of all indices on TABLE +\&.mode MODE ?TABLE? Set output mode where MODE is one of: + csv Comma-separated values + column Left-aligned columns. (See .width) + html HTML
    code + insert SQL insert statements for TABLE + line One value per line + list Values delimited by .separator string + tabs Tab-separated values + tcl TCL list elements +\&.nullvalue STRING Print STRING in place of NULL values +\&.output FILENAME Send output to FILENAME +\&.output stdout Send output to the screen +\&.prompt MAIN CONTINUE Replace the standard prompts +\&.quit Exit this program +\&.read FILENAME Execute SQL in FILENAME +\&.schema ?TABLE? Show the CREATE statements +\&.separator STRING Change separator used by output mode and .import +\&.show Show the current values for various settings +\&.tables ?PATTERN? List names of tables matching a LIKE pattern +\&.timeout MS Try opening locked tables for MS milliseconds +\&.width NUM NUM ... Set column widths for "column" mode +sqlite> +.Ed +.Sh OPTIONS +.Nm +has the following options: +.Bl -tag -width abcdefghij +.It Fl init Ar file +Read and execute commands from +.Ar file , +which can contain a mix of SQL statements and meta-commands. +.It Fl echo +Print commands before execution. +.It Fl header +Turn headers on. +.It Fl noheader +Turn headers off. +.It Fl column +Query results will be displayed in a table like form, using +whitespace characters to separate the columns and align the +output. +.It Fl html +Query results will be output as simple HTML tables. +.It Fl line +Query results will be displayed with one value per line, rows +separated by a blank line. +Designed to be easily parsed by scripts or other programs +.It Fl list +Query results will be displayed with the separator (|, by default) +character between each field value. +.It Fl separator Ar separator +Set output field separator. +Default is +.Dq | . +.It Fl nullvalue Ar string +Set +.Ar string +used to represent +.Dv NULL +values. +Default is +.Dq \e +(empty string). +.It Fl version +Show SQLite version. +.It Fl help +Show help on options and exit. +.El +.Ss INIT FILE +.Nm +reads an initialization file to set the configuration of the +interactive environment. +Throughout initialization, any previously specified setting can be overridden. +The sequence of initialization is as follows: +.Bl -enum +.It +The default configuration is established as follows: +.Bd -literal -offset indent +mode = LIST +separator = "|" +main prompt = "sqlite> " +continue prompt = " ...> " +.Ed +.It +If the file +.Pa ~/.sqliterc +exists, it is processed first. +can be found in the user's home directory, it is +read and processed. +It should generally only contain meta-commands. +.It +If the +.Fl init +option is present, the specified file is processed. +.It +All other command line options are processed. +.El +.Sh SEE ALSO +.Lk http://www.sqlite.org/ +.Sh AUTHORS +This manual page was originally written by Andreas Rottmann +.Aq rotty@debian.org , +for the Debian GNU/Linux system (but may be used by others). +It was subsequently revised by Bill Bumgarner +.Aq bbum@mac.com . diff --git a/external/public-domain/sqlite/dist/sqlite3.c b/external/public-domain/sqlite/dist/sqlite3.c new file mode 100644 index 000000000..419d963b6 --- /dev/null +++ b/external/public-domain/sqlite/dist/sqlite3.c @@ -0,0 +1,133623 @@ +/****************************************************************************** +** This file is an amalgamation of many separate C source files from SQLite +** version 3.7.10. By combining all the individual C code files into this +** single large file, the entire code can be compiled as a single translation +** unit. This allows many compilers to do optimizations that would not be +** possible if the files were compiled separately. Performance improvements +** of 5% or more are commonly seen when SQLite is compiled as a single +** translation unit. +** +** This file is all you need to compile SQLite. To use SQLite in other +** programs, you need this file and the "sqlite3.h" header file that defines +** the programming interface to the SQLite library. (If you do not have +** the "sqlite3.h" header file at hand, you will find a copy embedded within +** the text of this file. Search for "Begin file sqlite3.h" to find the start +** of the embedded sqlite3.h header file.) Additional code files may be needed +** if you want a wrapper to interface SQLite with your choice of programming +** language. The code for the "sqlite3" command-line shell is also in a +** separate file. This file contains only code for the core SQLite library. +*/ +#define SQLITE_CORE 1 +#define SQLITE_AMALGAMATION 1 +#ifndef SQLITE_PRIVATE +# define SQLITE_PRIVATE static +#endif +#ifndef SQLITE_API +# define SQLITE_API +#endif +/************** Begin file sqliteInt.h ***************************************/ +/* +** 2001 September 15 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** Internal interface definitions for SQLite. +** +*/ +#ifndef _SQLITEINT_H_ +#define _SQLITEINT_H_ + +/* +** These #defines should enable >2GB file support on POSIX if the +** underlying operating system supports it. If the OS lacks +** large file support, or if the OS is windows, these should be no-ops. +** +** Ticket #2739: The _LARGEFILE_SOURCE macro must appear before any +** system #includes. Hence, this block of code must be the very first +** code in all source files. +** +** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch +** on the compiler command line. This is necessary if you are compiling +** on a recent machine (ex: Red Hat 7.2) but you want your code to work +** on an older machine (ex: Red Hat 6.0). If you compile on Red Hat 7.2 +** without this option, LFS is enable. But LFS does not exist in the kernel +** in Red Hat 6.0, so the code won't work. Hence, for maximum binary +** portability you should omit LFS. +** +** Similar is true for Mac OS X. LFS is only supported on Mac OS X 9 and later. +*/ +#ifndef SQLITE_DISABLE_LFS +# define _LARGE_FILE 1 +# ifndef _FILE_OFFSET_BITS +# define _FILE_OFFSET_BITS 64 +# endif +# define _LARGEFILE_SOURCE 1 +#endif + +/* +** Include the configuration header output by 'configure' if we're using the +** autoconf-based build +*/ +#ifdef _HAVE_SQLITE_CONFIG_H +#include "config.h" +#endif + +/************** Include sqliteLimit.h in the middle of sqliteInt.h ***********/ +/************** Begin file sqliteLimit.h *************************************/ +/* +** 2007 May 7 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** +** This file defines various limits of what SQLite can process. +*/ + +/* +** The maximum length of a TEXT or BLOB in bytes. This also +** limits the size of a row in a table or index. +** +** The hard limit is the ability of a 32-bit signed integer +** to count the size: 2^31-1 or 2147483647. +*/ +#ifndef SQLITE_MAX_LENGTH +# define SQLITE_MAX_LENGTH 1000000000 +#endif + +/* +** This is the maximum number of +** +** * Columns in a table +** * Columns in an index +** * Columns in a view +** * Terms in the SET clause of an UPDATE statement +** * Terms in the result set of a SELECT statement +** * Terms in the GROUP BY or ORDER BY clauses of a SELECT statement. +** * Terms in the VALUES clause of an INSERT statement +** +** The hard upper limit here is 32676. Most database people will +** tell you that in a well-normalized database, you usually should +** not have more than a dozen or so columns in any table. And if +** that is the case, there is no point in having more than a few +** dozen values in any of the other situations described above. +*/ +#ifndef SQLITE_MAX_COLUMN +# define SQLITE_MAX_COLUMN 2000 +#endif + +/* +** The maximum length of a single SQL statement in bytes. +** +** It used to be the case that setting this value to zero would +** turn the limit off. That is no longer true. It is not possible +** to turn this limit off. +*/ +#ifndef SQLITE_MAX_SQL_LENGTH +# define SQLITE_MAX_SQL_LENGTH 1000000000 +#endif + +/* +** The maximum depth of an expression tree. This is limited to +** some extent by SQLITE_MAX_SQL_LENGTH. But sometime you might +** want to place more severe limits on the complexity of an +** expression. +** +** A value of 0 used to mean that the limit was not enforced. +** But that is no longer true. The limit is now strictly enforced +** at all times. +*/ +#ifndef SQLITE_MAX_EXPR_DEPTH +# define SQLITE_MAX_EXPR_DEPTH 1000 +#endif + +/* +** The maximum number of terms in a compound SELECT statement. +** The code generator for compound SELECT statements does one +** level of recursion for each term. A stack overflow can result +** if the number of terms is too large. In practice, most SQL +** never has more than 3 or 4 terms. Use a value of 0 to disable +** any limit on the number of terms in a compount SELECT. +*/ +#ifndef SQLITE_MAX_COMPOUND_SELECT +# define SQLITE_MAX_COMPOUND_SELECT 500 +#endif + +/* +** The maximum number of opcodes in a VDBE program. +** Not currently enforced. +*/ +#ifndef SQLITE_MAX_VDBE_OP +# define SQLITE_MAX_VDBE_OP 25000 +#endif + +/* +** The maximum number of arguments to an SQL function. +*/ +#ifndef SQLITE_MAX_FUNCTION_ARG +# define SQLITE_MAX_FUNCTION_ARG 127 +#endif + +/* +** The maximum number of in-memory pages to use for the main database +** table and for temporary tables. The SQLITE_DEFAULT_CACHE_SIZE +*/ +#ifndef SQLITE_DEFAULT_CACHE_SIZE +# define SQLITE_DEFAULT_CACHE_SIZE 2000 +#endif +#ifndef SQLITE_DEFAULT_TEMP_CACHE_SIZE +# define SQLITE_DEFAULT_TEMP_CACHE_SIZE 500 +#endif + +/* +** The default number of frames to accumulate in the log file before +** checkpointing the database in WAL mode. +*/ +#ifndef SQLITE_DEFAULT_WAL_AUTOCHECKPOINT +# define SQLITE_DEFAULT_WAL_AUTOCHECKPOINT 1000 +#endif + +/* +** The maximum number of attached databases. This must be between 0 +** and 62. The upper bound on 62 is because a 64-bit integer bitmap +** is used internally to track attached databases. +*/ +#ifndef SQLITE_MAX_ATTACHED +# define SQLITE_MAX_ATTACHED 10 +#endif + + +/* +** The maximum value of a ?nnn wildcard that the parser will accept. +*/ +#ifndef SQLITE_MAX_VARIABLE_NUMBER +# define SQLITE_MAX_VARIABLE_NUMBER 999 +#endif + +/* Maximum page size. The upper bound on this value is 65536. This a limit +** imposed by the use of 16-bit offsets within each page. +** +** Earlier versions of SQLite allowed the user to change this value at +** compile time. This is no longer permitted, on the grounds that it creates +** a library that is technically incompatible with an SQLite library +** compiled with a different limit. If a process operating on a database +** with a page-size of 65536 bytes crashes, then an instance of SQLite +** compiled with the default page-size limit will not be able to rollback +** the aborted transaction. This could lead to database corruption. +*/ +#ifdef SQLITE_MAX_PAGE_SIZE +# undef SQLITE_MAX_PAGE_SIZE +#endif +#define SQLITE_MAX_PAGE_SIZE 65536 + + +/* +** The default size of a database page. +*/ +#ifndef SQLITE_DEFAULT_PAGE_SIZE +# define SQLITE_DEFAULT_PAGE_SIZE 1024 +#endif +#if SQLITE_DEFAULT_PAGE_SIZE>SQLITE_MAX_PAGE_SIZE +# undef SQLITE_DEFAULT_PAGE_SIZE +# define SQLITE_DEFAULT_PAGE_SIZE SQLITE_MAX_PAGE_SIZE +#endif + +/* +** Ordinarily, if no value is explicitly provided, SQLite creates databases +** with page size SQLITE_DEFAULT_PAGE_SIZE. However, based on certain +** device characteristics (sector-size and atomic write() support), +** SQLite may choose a larger value. This constant is the maximum value +** SQLite will choose on its own. +*/ +#ifndef SQLITE_MAX_DEFAULT_PAGE_SIZE +# define SQLITE_MAX_DEFAULT_PAGE_SIZE 8192 +#endif +#if SQLITE_MAX_DEFAULT_PAGE_SIZE>SQLITE_MAX_PAGE_SIZE +# undef SQLITE_MAX_DEFAULT_PAGE_SIZE +# define SQLITE_MAX_DEFAULT_PAGE_SIZE SQLITE_MAX_PAGE_SIZE +#endif + + +/* +** Maximum number of pages in one database file. +** +** This is really just the default value for the max_page_count pragma. +** This value can be lowered (or raised) at run-time using that the +** max_page_count macro. +*/ +#ifndef SQLITE_MAX_PAGE_COUNT +# define SQLITE_MAX_PAGE_COUNT 1073741823 +#endif + +/* +** Maximum length (in bytes) of the pattern in a LIKE or GLOB +** operator. +*/ +#ifndef SQLITE_MAX_LIKE_PATTERN_LENGTH +# define SQLITE_MAX_LIKE_PATTERN_LENGTH 50000 +#endif + +/* +** Maximum depth of recursion for triggers. +** +** A value of 1 means that a trigger program will not be able to itself +** fire any triggers. A value of 0 means that no trigger programs at all +** may be executed. +*/ +#ifndef SQLITE_MAX_TRIGGER_DEPTH +# define SQLITE_MAX_TRIGGER_DEPTH 1000 +#endif + +/************** End of sqliteLimit.h *****************************************/ +/************** Continuing where we left off in sqliteInt.h ******************/ + +/* Disable nuisance warnings on Borland compilers */ +#if defined(__BORLANDC__) +#pragma warn -rch /* unreachable code */ +#pragma warn -ccc /* Condition is always true or false */ +#pragma warn -aus /* Assigned value is never used */ +#pragma warn -csu /* Comparing signed and unsigned */ +#pragma warn -spa /* Suspicious pointer arithmetic */ +#endif + +/* Needed for various definitions... */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE +#endif + +/* +** Include standard header files as necessary +*/ +#ifdef HAVE_STDINT_H +#include +#endif +#ifdef HAVE_INTTYPES_H +#include +#endif + +/* +** The following macros are used to cast pointers to integers and +** integers to pointers. The way you do this varies from one compiler +** to the next, so we have developed the following set of #if statements +** to generate appropriate macros for a wide range of compilers. +** +** The correct "ANSI" way to do this is to use the intptr_t type. +** Unfortunately, that typedef is not available on all compilers, or +** if it is available, it requires an #include of specific headers +** that vary from one machine to the next. +** +** Ticket #3860: The llvm-gcc-4.2 compiler from Apple chokes on +** the ((void*)&((char*)0)[X]) construct. But MSVC chokes on ((void*)(X)). +** So we have to define the macros in different ways depending on the +** compiler. +*/ +#if defined(__PTRDIFF_TYPE__) /* This case should work for GCC */ +# define SQLITE_INT_TO_PTR(X) ((void*)(__PTRDIFF_TYPE__)(X)) +# define SQLITE_PTR_TO_INT(X) ((int)(__PTRDIFF_TYPE__)(X)) +#elif !defined(__GNUC__) /* Works for compilers other than LLVM */ +# define SQLITE_INT_TO_PTR(X) ((void*)&((char*)0)[X]) +# define SQLITE_PTR_TO_INT(X) ((int)(((char*)X)-(char*)0)) +#elif defined(HAVE_STDINT_H) /* Use this case if we have ANSI headers */ +# define SQLITE_INT_TO_PTR(X) ((void*)(intptr_t)(X)) +# define SQLITE_PTR_TO_INT(X) ((int)(intptr_t)(X)) +#else /* Generates a warning - but it always works */ +# define SQLITE_INT_TO_PTR(X) ((void*)(X)) +# define SQLITE_PTR_TO_INT(X) ((int)(X)) +#endif + +/* +** The SQLITE_THREADSAFE macro must be defined as 0, 1, or 2. +** 0 means mutexes are permanently disable and the library is never +** threadsafe. 1 means the library is serialized which is the highest +** level of threadsafety. 2 means the libary is multithreaded - multiple +** threads can use SQLite as long as no two threads try to use the same +** database connection at the same time. +** +** Older versions of SQLite used an optional THREADSAFE macro. +** We support that for legacy. +*/ +#if !defined(SQLITE_THREADSAFE) +#if defined(THREADSAFE) +# define SQLITE_THREADSAFE THREADSAFE +#else +# define SQLITE_THREADSAFE 1 /* IMP: R-07272-22309 */ +#endif +#endif + +/* +** Powersafe overwrite is on by default. But can be turned off using +** the -DSQLITE_POWERSAFE_OVERWRITE=0 command-line option. +*/ +#ifndef SQLITE_POWERSAFE_OVERWRITE +# define SQLITE_POWERSAFE_OVERWRITE 1 +#endif + +/* +** The SQLITE_DEFAULT_MEMSTATUS macro must be defined as either 0 or 1. +** It determines whether or not the features related to +** SQLITE_CONFIG_MEMSTATUS are available by default or not. This value can +** be overridden at runtime using the sqlite3_config() API. +*/ +#if !defined(SQLITE_DEFAULT_MEMSTATUS) +# define SQLITE_DEFAULT_MEMSTATUS 1 +#endif + +/* +** Exactly one of the following macros must be defined in order to +** specify which memory allocation subsystem to use. +** +** SQLITE_SYSTEM_MALLOC // Use normal system malloc() +** SQLITE_WIN32_MALLOC // Use Win32 native heap API +** SQLITE_MEMDEBUG // Debugging version of system malloc() +** +** On Windows, if the SQLITE_WIN32_MALLOC_VALIDATE macro is defined and the +** assert() macro is enabled, each call into the Win32 native heap subsystem +** will cause HeapValidate to be called. If heap validation should fail, an +** assertion will be triggered. +** +** (Historical note: There used to be several other options, but we've +** pared it down to just these three.) +** +** If none of the above are defined, then set SQLITE_SYSTEM_MALLOC as +** the default. +*/ +#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_WIN32_MALLOC)+defined(SQLITE_MEMDEBUG)>1 +# error "At most one of the following compile-time configuration options\ + is allows: SQLITE_SYSTEM_MALLOC, SQLITE_WIN32_MALLOC, SQLITE_MEMDEBUG" +#endif +#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_WIN32_MALLOC)+defined(SQLITE_MEMDEBUG)==0 +# define SQLITE_SYSTEM_MALLOC 1 +#endif + +/* +** If SQLITE_MALLOC_SOFT_LIMIT is not zero, then try to keep the +** sizes of memory allocations below this value where possible. +*/ +#if !defined(SQLITE_MALLOC_SOFT_LIMIT) +# define SQLITE_MALLOC_SOFT_LIMIT 1024 +#endif + +/* +** We need to define _XOPEN_SOURCE as follows in order to enable +** recursive mutexes on most Unix systems. But Mac OS X is different. +** The _XOPEN_SOURCE define causes problems for Mac OS X we are told, +** so it is omitted there. See ticket #2673. +** +** Later we learn that _XOPEN_SOURCE is poorly or incorrectly +** implemented on some systems. So we avoid defining it at all +** if it is already defined or if it is unneeded because we are +** not doing a threadsafe build. Ticket #2681. +** +** See also ticket #2741. +*/ +#if !defined(_XOPEN_SOURCE) && !defined(__DARWIN__) && !defined(__APPLE__) && SQLITE_THREADSAFE +# define _XOPEN_SOURCE 500 /* Needed to enable pthread recursive mutexes */ +#endif + +/* +** The TCL headers are only needed when compiling the TCL bindings. +*/ +#if defined(SQLITE_TCL) || defined(TCLSH) +# include +#endif + +/* +** Many people are failing to set -DNDEBUG=1 when compiling SQLite. +** Setting NDEBUG makes the code smaller and run faster. So the following +** lines are added to automatically set NDEBUG unless the -DSQLITE_DEBUG=1 +** option is set. Thus NDEBUG becomes an opt-in rather than an opt-out +** feature. +*/ +#if !defined(NDEBUG) && !defined(SQLITE_DEBUG) +# define NDEBUG 1 +#endif + +/* +** The testcase() macro is used to aid in coverage testing. When +** doing coverage testing, the condition inside the argument to +** testcase() must be evaluated both true and false in order to +** get full branch coverage. The testcase() macro is inserted +** to help ensure adequate test coverage in places where simple +** condition/decision coverage is inadequate. For example, testcase() +** can be used to make sure boundary values are tested. For +** bitmask tests, testcase() can be used to make sure each bit +** is significant and used at least once. On switch statements +** where multiple cases go to the same block of code, testcase() +** can insure that all cases are evaluated. +** +*/ +#ifdef SQLITE_COVERAGE_TEST +SQLITE_PRIVATE void sqlite3Coverage(int); +# define testcase(X) if( X ){ sqlite3Coverage(__LINE__); } +#else +# define testcase(X) +#endif + +/* +** The TESTONLY macro is used to enclose variable declarations or +** other bits of code that are needed to support the arguments +** within testcase() and assert() macros. +*/ +#if !defined(NDEBUG) || defined(SQLITE_COVERAGE_TEST) +# define TESTONLY(X) X +#else +# define TESTONLY(X) +#endif + +/* +** Sometimes we need a small amount of code such as a variable initialization +** to setup for a later assert() statement. We do not want this code to +** appear when assert() is disabled. The following macro is therefore +** used to contain that setup code. The "VVA" acronym stands for +** "Verification, Validation, and Accreditation". In other words, the +** code within VVA_ONLY() will only run during verification processes. +*/ +#ifndef NDEBUG +# define VVA_ONLY(X) X +#else +# define VVA_ONLY(X) +#endif + +/* +** The ALWAYS and NEVER macros surround boolean expressions which +** are intended to always be true or false, respectively. Such +** expressions could be omitted from the code completely. But they +** are included in a few cases in order to enhance the resilience +** of SQLite to unexpected behavior - to make the code "self-healing" +** or "ductile" rather than being "brittle" and crashing at the first +** hint of unplanned behavior. +** +** In other words, ALWAYS and NEVER are added for defensive code. +** +** When doing coverage testing ALWAYS and NEVER are hard-coded to +** be true and false so that the unreachable code then specify will +** not be counted as untested code. +*/ +#if defined(SQLITE_COVERAGE_TEST) +# define ALWAYS(X) (1) +# define NEVER(X) (0) +#elif !defined(NDEBUG) +# define ALWAYS(X) ((X)?1:(assert(0),0)) +# define NEVER(X) ((X)?(assert(0),1):0) +#else +# define ALWAYS(X) (X) +# define NEVER(X) (X) +#endif + +/* +** Return true (non-zero) if the input is a integer that is too large +** to fit in 32-bits. This macro is used inside of various testcase() +** macros to verify that we have tested SQLite for large-file support. +*/ +#define IS_BIG_INT(X) (((X)&~(i64)0xffffffff)!=0) + +/* +** The macro unlikely() is a hint that surrounds a boolean +** expression that is usually false. Macro likely() surrounds +** a boolean expression that is usually true. GCC is able to +** use these hints to generate better code, sometimes. +*/ +#if defined(__GNUC__) && 0 +# define likely(X) __builtin_expect((X),1) +# define unlikely(X) __builtin_expect((X),0) +#else +# define likely(X) !!(X) +# define unlikely(X) !!(X) +#endif + +/************** Include sqlite3.h in the middle of sqliteInt.h ***************/ +/************** Begin file sqlite3.h *****************************************/ +/* +** 2001 September 15 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This header file defines the interface that the SQLite library +** presents to client programs. If a C-function, structure, datatype, +** or constant definition does not appear in this file, then it is +** not a published API of SQLite, is subject to change without +** notice, and should not be referenced by programs that use SQLite. +** +** Some of the definitions that are in this file are marked as +** "experimental". Experimental interfaces are normally new +** features recently added to SQLite. We do not anticipate changes +** to experimental interfaces but reserve the right to make minor changes +** if experience from use "in the wild" suggest such changes are prudent. +** +** The official C-language API documentation for SQLite is derived +** from comments in this file. This file is the authoritative source +** on how SQLite interfaces are suppose to operate. +** +** The name of this file under configuration management is "sqlite.h.in". +** The makefile makes some minor changes to this file (such as inserting +** the version number) and changes its name to "sqlite3.h" as +** part of the build process. +*/ +#ifndef _SQLITE3_H_ +#define _SQLITE3_H_ +#include /* Needed for the definition of va_list */ + +/* +** Make sure we can call this stuff from C++. +*/ +#if 0 +extern "C" { +#endif + + +/* +** Add the ability to override 'extern' +*/ +#ifndef SQLITE_EXTERN +# define SQLITE_EXTERN extern +#endif + +#ifndef SQLITE_API +# define SQLITE_API +#endif + + +/* +** These no-op macros are used in front of interfaces to mark those +** interfaces as either deprecated or experimental. New applications +** should not use deprecated interfaces - they are support for backwards +** compatibility only. Application writers should be aware that +** experimental interfaces are subject to change in point releases. +** +** These macros used to resolve to various kinds of compiler magic that +** would generate warning messages when they were used. But that +** compiler magic ended up generating such a flurry of bug reports +** that we have taken it all out and gone back to using simple +** noop macros. +*/ +#define SQLITE_DEPRECATED +#define SQLITE_EXPERIMENTAL + +/* +** Ensure these symbols were not defined by some previous header file. +*/ +#ifdef SQLITE_VERSION +# undef SQLITE_VERSION +#endif +#ifdef SQLITE_VERSION_NUMBER +# undef SQLITE_VERSION_NUMBER +#endif + +/* +** CAPI3REF: Compile-Time Library Version Numbers +** +** ^(The [SQLITE_VERSION] C preprocessor macro in the sqlite3.h header +** evaluates to a string literal that is the SQLite version in the +** format "X.Y.Z" where X is the major version number (always 3 for +** SQLite3) and Y is the minor version number and Z is the release number.)^ +** ^(The [SQLITE_VERSION_NUMBER] C preprocessor macro resolves to an integer +** with the value (X*1000000 + Y*1000 + Z) where X, Y, and Z are the same +** numbers used in [SQLITE_VERSION].)^ +** The SQLITE_VERSION_NUMBER for any given release of SQLite will also +** be larger than the release from which it is derived. Either Y will +** be held constant and Z will be incremented or else Y will be incremented +** and Z will be reset to zero. +** +** Since version 3.6.18, SQLite source code has been stored in the +** Fossil configuration management +** system. ^The SQLITE_SOURCE_ID macro evaluates to +** a string which identifies a particular check-in of SQLite +** within its configuration management system. ^The SQLITE_SOURCE_ID +** string contains the date and time of the check-in (UTC) and an SHA1 +** hash of the entire source tree. +** +** See also: [sqlite3_libversion()], +** [sqlite3_libversion_number()], [sqlite3_sourceid()], +** [sqlite_version()] and [sqlite_source_id()]. +*/ +#define SQLITE_VERSION "3.7.10" +#define SQLITE_VERSION_NUMBER 3007010 +#define SQLITE_SOURCE_ID "2012-01-16 13:28:40 ebd01a8deffb5024a5d7494eef800d2366d97204" + +/* +** CAPI3REF: Run-Time Library Version Numbers +** KEYWORDS: sqlite3_version, sqlite3_sourceid +** +** These interfaces provide the same information as the [SQLITE_VERSION], +** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros +** but are associated with the library instead of the header file. ^(Cautious +** programmers might include assert() statements in their application to +** verify that values returned by these interfaces match the macros in +** the header, and thus insure that the application is +** compiled with matching library and header files. +** +**
    +** assert( sqlite3_libversion_number()==SQLITE_VERSION_NUMBER );
    +** assert( strcmp(sqlite3_sourceid(),SQLITE_SOURCE_ID)==0 );
    +** assert( strcmp(sqlite3_libversion(),SQLITE_VERSION)==0 );
    +** 
    )^ +** +** ^The sqlite3_version[] string constant contains the text of [SQLITE_VERSION] +** macro. ^The sqlite3_libversion() function returns a pointer to the +** to the sqlite3_version[] string constant. The sqlite3_libversion() +** function is provided for use in DLLs since DLL users usually do not have +** direct access to string constants within the DLL. ^The +** sqlite3_libversion_number() function returns an integer equal to +** [SQLITE_VERSION_NUMBER]. ^The sqlite3_sourceid() function returns +** a pointer to a string constant whose value is the same as the +** [SQLITE_SOURCE_ID] C preprocessor macro. +** +** See also: [sqlite_version()] and [sqlite_source_id()]. +*/ +SQLITE_API const char sqlite3_version[] = SQLITE_VERSION; +SQLITE_API const char *sqlite3_libversion(void); +SQLITE_API const char *sqlite3_sourceid(void); +SQLITE_API int sqlite3_libversion_number(void); + +/* +** CAPI3REF: Run-Time Library Compilation Options Diagnostics +** +** ^The sqlite3_compileoption_used() function returns 0 or 1 +** indicating whether the specified option was defined at +** compile time. ^The SQLITE_ prefix may be omitted from the +** option name passed to sqlite3_compileoption_used(). +** +** ^The sqlite3_compileoption_get() function allows iterating +** over the list of options that were defined at compile time by +** returning the N-th compile time option string. ^If N is out of range, +** sqlite3_compileoption_get() returns a NULL pointer. ^The SQLITE_ +** prefix is omitted from any strings returned by +** sqlite3_compileoption_get(). +** +** ^Support for the diagnostic functions sqlite3_compileoption_used() +** and sqlite3_compileoption_get() may be omitted by specifying the +** [SQLITE_OMIT_COMPILEOPTION_DIAGS] option at compile time. +** +** See also: SQL functions [sqlite_compileoption_used()] and +** [sqlite_compileoption_get()] and the [compile_options pragma]. +*/ +#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS +SQLITE_API int sqlite3_compileoption_used(const char *zOptName); +SQLITE_API const char *sqlite3_compileoption_get(int N); +#endif + +/* +** CAPI3REF: Test To See If The Library Is Threadsafe +** +** ^The sqlite3_threadsafe() function returns zero if and only if +** SQLite was compiled with mutexing code omitted due to the +** [SQLITE_THREADSAFE] compile-time option being set to 0. +** +** SQLite can be compiled with or without mutexes. When +** the [SQLITE_THREADSAFE] C preprocessor macro is 1 or 2, mutexes +** are enabled and SQLite is threadsafe. When the +** [SQLITE_THREADSAFE] macro is 0, +** the mutexes are omitted. Without the mutexes, it is not safe +** to use SQLite concurrently from more than one thread. +** +** Enabling mutexes incurs a measurable performance penalty. +** So if speed is of utmost importance, it makes sense to disable +** the mutexes. But for maximum safety, mutexes should be enabled. +** ^The default behavior is for mutexes to be enabled. +** +** This interface can be used by an application to make sure that the +** version of SQLite that it is linking against was compiled with +** the desired setting of the [SQLITE_THREADSAFE] macro. +** +** This interface only reports on the compile-time mutex setting +** of the [SQLITE_THREADSAFE] flag. If SQLite is compiled with +** SQLITE_THREADSAFE=1 or =2 then mutexes are enabled by default but +** can be fully or partially disabled using a call to [sqlite3_config()] +** with the verbs [SQLITE_CONFIG_SINGLETHREAD], [SQLITE_CONFIG_MULTITHREAD], +** or [SQLITE_CONFIG_MUTEX]. ^(The return value of the +** sqlite3_threadsafe() function shows only the compile-time setting of +** thread safety, not any run-time changes to that setting made by +** sqlite3_config(). In other words, the return value from sqlite3_threadsafe() +** is unchanged by calls to sqlite3_config().)^ +** +** See the [threading mode] documentation for additional information. +*/ +SQLITE_API int sqlite3_threadsafe(void); + +/* +** CAPI3REF: Database Connection Handle +** KEYWORDS: {database connection} {database connections} +** +** Each open SQLite database is represented by a pointer to an instance of +** the opaque structure named "sqlite3". It is useful to think of an sqlite3 +** pointer as an object. The [sqlite3_open()], [sqlite3_open16()], and +** [sqlite3_open_v2()] interfaces are its constructors, and [sqlite3_close()] +** is its destructor. There are many other interfaces (such as +** [sqlite3_prepare_v2()], [sqlite3_create_function()], and +** [sqlite3_busy_timeout()] to name but three) that are methods on an +** sqlite3 object. +*/ +typedef struct sqlite3 sqlite3; + +/* +** CAPI3REF: 64-Bit Integer Types +** KEYWORDS: sqlite_int64 sqlite_uint64 +** +** Because there is no cross-platform way to specify 64-bit integer types +** SQLite includes typedefs for 64-bit signed and unsigned integers. +** +** The sqlite3_int64 and sqlite3_uint64 are the preferred type definitions. +** The sqlite_int64 and sqlite_uint64 types are supported for backwards +** compatibility only. +** +** ^The sqlite3_int64 and sqlite_int64 types can store integer values +** between -9223372036854775808 and +9223372036854775807 inclusive. ^The +** sqlite3_uint64 and sqlite_uint64 types can store integer values +** between 0 and +18446744073709551615 inclusive. +*/ +#ifdef SQLITE_INT64_TYPE + typedef SQLITE_INT64_TYPE sqlite_int64; + typedef unsigned SQLITE_INT64_TYPE sqlite_uint64; +#elif defined(_MSC_VER) || defined(__BORLANDC__) + typedef __int64 sqlite_int64; + typedef unsigned __int64 sqlite_uint64; +#else + typedef long long int sqlite_int64; + typedef unsigned long long int sqlite_uint64; +#endif +typedef sqlite_int64 sqlite3_int64; +typedef sqlite_uint64 sqlite3_uint64; + +/* +** If compiling for a processor that lacks floating point support, +** substitute integer for floating-point. +*/ +#ifdef SQLITE_OMIT_FLOATING_POINT +# define double sqlite3_int64 +#endif + +/* +** CAPI3REF: Closing A Database Connection +** +** ^The sqlite3_close() routine is the destructor for the [sqlite3] object. +** ^Calls to sqlite3_close() return SQLITE_OK if the [sqlite3] object is +** successfully destroyed and all associated resources are deallocated. +** +** Applications must [sqlite3_finalize | finalize] all [prepared statements] +** and [sqlite3_blob_close | close] all [BLOB handles] associated with +** the [sqlite3] object prior to attempting to close the object. ^If +** sqlite3_close() is called on a [database connection] that still has +** outstanding [prepared statements] or [BLOB handles], then it returns +** SQLITE_BUSY. +** +** ^If [sqlite3_close()] is invoked while a transaction is open, +** the transaction is automatically rolled back. +** +** The C parameter to [sqlite3_close(C)] must be either a NULL +** pointer or an [sqlite3] object pointer obtained +** from [sqlite3_open()], [sqlite3_open16()], or +** [sqlite3_open_v2()], and not previously closed. +** ^Calling sqlite3_close() with a NULL pointer argument is a +** harmless no-op. +*/ +SQLITE_API int sqlite3_close(sqlite3 *); + +/* +** The type for a callback function. +** This is legacy and deprecated. It is included for historical +** compatibility and is not documented. +*/ +typedef int (*sqlite3_callback)(void*,int,char**, char**); + +/* +** CAPI3REF: One-Step Query Execution Interface +** +** The sqlite3_exec() interface is a convenience wrapper around +** [sqlite3_prepare_v2()], [sqlite3_step()], and [sqlite3_finalize()], +** that allows an application to run multiple statements of SQL +** without having to use a lot of C code. +** +** ^The sqlite3_exec() interface runs zero or more UTF-8 encoded, +** semicolon-separate SQL statements passed into its 2nd argument, +** in the context of the [database connection] passed in as its 1st +** argument. ^If the callback function of the 3rd argument to +** sqlite3_exec() is not NULL, then it is invoked for each result row +** coming out of the evaluated SQL statements. ^The 4th argument to +** sqlite3_exec() is relayed through to the 1st argument of each +** callback invocation. ^If the callback pointer to sqlite3_exec() +** is NULL, then no callback is ever invoked and result rows are +** ignored. +** +** ^If an error occurs while evaluating the SQL statements passed into +** sqlite3_exec(), then execution of the current statement stops and +** subsequent statements are skipped. ^If the 5th parameter to sqlite3_exec() +** is not NULL then any error message is written into memory obtained +** from [sqlite3_malloc()] and passed back through the 5th parameter. +** To avoid memory leaks, the application should invoke [sqlite3_free()] +** on error message strings returned through the 5th parameter of +** of sqlite3_exec() after the error message string is no longer needed. +** ^If the 5th parameter to sqlite3_exec() is not NULL and no errors +** occur, then sqlite3_exec() sets the pointer in its 5th parameter to +** NULL before returning. +** +** ^If an sqlite3_exec() callback returns non-zero, the sqlite3_exec() +** routine returns SQLITE_ABORT without invoking the callback again and +** without running any subsequent SQL statements. +** +** ^The 2nd argument to the sqlite3_exec() callback function is the +** number of columns in the result. ^The 3rd argument to the sqlite3_exec() +** callback is an array of pointers to strings obtained as if from +** [sqlite3_column_text()], one for each column. ^If an element of a +** result row is NULL then the corresponding string pointer for the +** sqlite3_exec() callback is a NULL pointer. ^The 4th argument to the +** sqlite3_exec() callback is an array of pointers to strings where each +** entry represents the name of corresponding result column as obtained +** from [sqlite3_column_name()]. +** +** ^If the 2nd parameter to sqlite3_exec() is a NULL pointer, a pointer +** to an empty string, or a pointer that contains only whitespace and/or +** SQL comments, then no SQL statements are evaluated and the database +** is not changed. +** +** Restrictions: +** +**
      +**
    • The application must insure that the 1st parameter to sqlite3_exec() +** is a valid and open [database connection]. +**
    • The application must not close [database connection] specified by +** the 1st parameter to sqlite3_exec() while sqlite3_exec() is running. +**
    • The application must not modify the SQL statement text passed into +** the 2nd parameter of sqlite3_exec() while sqlite3_exec() is running. +**
    +*/ +SQLITE_API int sqlite3_exec( + sqlite3*, /* An open database */ + const char *sql, /* SQL to be evaluated */ + int (*callback)(void*,int,char**,char**), /* Callback function */ + void *, /* 1st argument to callback */ + char **errmsg /* Error msg written here */ +); + +/* +** CAPI3REF: Result Codes +** KEYWORDS: SQLITE_OK {error code} {error codes} +** KEYWORDS: {result code} {result codes} +** +** Many SQLite functions return an integer result code from the set shown +** here in order to indicate success or failure. +** +** New error codes may be added in future versions of SQLite. +** +** See also: [SQLITE_IOERR_READ | extended result codes], +** [sqlite3_vtab_on_conflict()] [SQLITE_ROLLBACK | result codes]. +*/ +#define SQLITE_OK 0 /* Successful result */ +/* beginning-of-error-codes */ +#define SQLITE_ERROR 1 /* SQL error or missing database */ +#define SQLITE_INTERNAL 2 /* Internal logic error in SQLite */ +#define SQLITE_PERM 3 /* Access permission denied */ +#define SQLITE_ABORT 4 /* Callback routine requested an abort */ +#define SQLITE_BUSY 5 /* The database file is locked */ +#define SQLITE_LOCKED 6 /* A table in the database is locked */ +#define SQLITE_NOMEM 7 /* A malloc() failed */ +#define SQLITE_READONLY 8 /* Attempt to write a readonly database */ +#define SQLITE_INTERRUPT 9 /* Operation terminated by sqlite3_interrupt()*/ +#define SQLITE_IOERR 10 /* Some kind of disk I/O error occurred */ +#define SQLITE_CORRUPT 11 /* The database disk image is malformed */ +#define SQLITE_NOTFOUND 12 /* Unknown opcode in sqlite3_file_control() */ +#define SQLITE_FULL 13 /* Insertion failed because database is full */ +#define SQLITE_CANTOPEN 14 /* Unable to open the database file */ +#define SQLITE_PROTOCOL 15 /* Database lock protocol error */ +#define SQLITE_EMPTY 16 /* Database is empty */ +#define SQLITE_SCHEMA 17 /* The database schema changed */ +#define SQLITE_TOOBIG 18 /* String or BLOB exceeds size limit */ +#define SQLITE_CONSTRAINT 19 /* Abort due to constraint violation */ +#define SQLITE_MISMATCH 20 /* Data type mismatch */ +#define SQLITE_MISUSE 21 /* Library used incorrectly */ +#define SQLITE_NOLFS 22 /* Uses OS features not supported on host */ +#define SQLITE_AUTH 23 /* Authorization denied */ +#define SQLITE_FORMAT 24 /* Auxiliary database format error */ +#define SQLITE_RANGE 25 /* 2nd parameter to sqlite3_bind out of range */ +#define SQLITE_NOTADB 26 /* File opened that is not a database file */ +#define SQLITE_ROW 100 /* sqlite3_step() has another row ready */ +#define SQLITE_DONE 101 /* sqlite3_step() has finished executing */ +/* end-of-error-codes */ + +/* +** CAPI3REF: Extended Result Codes +** KEYWORDS: {extended error code} {extended error codes} +** KEYWORDS: {extended result code} {extended result codes} +** +** In its default configuration, SQLite API routines return one of 26 integer +** [SQLITE_OK | result codes]. However, experience has shown that many of +** these result codes are too coarse-grained. They do not provide as +** much information about problems as programmers might like. In an effort to +** address this, newer versions of SQLite (version 3.3.8 and later) include +** support for additional result codes that provide more detailed information +** about errors. The extended result codes are enabled or disabled +** on a per database connection basis using the +** [sqlite3_extended_result_codes()] API. +** +** Some of the available extended result codes are listed here. +** One may expect the number of extended result codes will be expand +** over time. Software that uses extended result codes should expect +** to see new result codes in future releases of SQLite. +** +** The SQLITE_OK result code will never be extended. It will always +** be exactly zero. +*/ +#define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8)) +#define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8)) +#define SQLITE_IOERR_WRITE (SQLITE_IOERR | (3<<8)) +#define SQLITE_IOERR_FSYNC (SQLITE_IOERR | (4<<8)) +#define SQLITE_IOERR_DIR_FSYNC (SQLITE_IOERR | (5<<8)) +#define SQLITE_IOERR_TRUNCATE (SQLITE_IOERR | (6<<8)) +#define SQLITE_IOERR_FSTAT (SQLITE_IOERR | (7<<8)) +#define SQLITE_IOERR_UNLOCK (SQLITE_IOERR | (8<<8)) +#define SQLITE_IOERR_RDLOCK (SQLITE_IOERR | (9<<8)) +#define SQLITE_IOERR_DELETE (SQLITE_IOERR | (10<<8)) +#define SQLITE_IOERR_BLOCKED (SQLITE_IOERR | (11<<8)) +#define SQLITE_IOERR_NOMEM (SQLITE_IOERR | (12<<8)) +#define SQLITE_IOERR_ACCESS (SQLITE_IOERR | (13<<8)) +#define SQLITE_IOERR_CHECKRESERVEDLOCK (SQLITE_IOERR | (14<<8)) +#define SQLITE_IOERR_LOCK (SQLITE_IOERR | (15<<8)) +#define SQLITE_IOERR_CLOSE (SQLITE_IOERR | (16<<8)) +#define SQLITE_IOERR_DIR_CLOSE (SQLITE_IOERR | (17<<8)) +#define SQLITE_IOERR_SHMOPEN (SQLITE_IOERR | (18<<8)) +#define SQLITE_IOERR_SHMSIZE (SQLITE_IOERR | (19<<8)) +#define SQLITE_IOERR_SHMLOCK (SQLITE_IOERR | (20<<8)) +#define SQLITE_IOERR_SHMMAP (SQLITE_IOERR | (21<<8)) +#define SQLITE_IOERR_SEEK (SQLITE_IOERR | (22<<8)) +#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8)) +#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) +#define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8)) +#define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8)) +#define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8)) +#define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8)) + +/* +** CAPI3REF: Flags For File Open Operations +** +** These bit values are intended for use in the +** 3rd parameter to the [sqlite3_open_v2()] interface and +** in the 4th parameter to the [sqlite3_vfs.xOpen] method. +*/ +#define SQLITE_OPEN_READONLY 0x00000001 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_READWRITE 0x00000002 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_CREATE 0x00000004 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_DELETEONCLOSE 0x00000008 /* VFS only */ +#define SQLITE_OPEN_EXCLUSIVE 0x00000010 /* VFS only */ +#define SQLITE_OPEN_AUTOPROXY 0x00000020 /* VFS only */ +#define SQLITE_OPEN_URI 0x00000040 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_MAIN_DB 0x00000100 /* VFS only */ +#define SQLITE_OPEN_TEMP_DB 0x00000200 /* VFS only */ +#define SQLITE_OPEN_TRANSIENT_DB 0x00000400 /* VFS only */ +#define SQLITE_OPEN_MAIN_JOURNAL 0x00000800 /* VFS only */ +#define SQLITE_OPEN_TEMP_JOURNAL 0x00001000 /* VFS only */ +#define SQLITE_OPEN_SUBJOURNAL 0x00002000 /* VFS only */ +#define SQLITE_OPEN_MASTER_JOURNAL 0x00004000 /* VFS only */ +#define SQLITE_OPEN_NOMUTEX 0x00008000 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_FULLMUTEX 0x00010000 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_SHAREDCACHE 0x00020000 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_PRIVATECACHE 0x00040000 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_WAL 0x00080000 /* VFS only */ + +/* Reserved: 0x00F00000 */ + +/* +** CAPI3REF: Device Characteristics +** +** The xDeviceCharacteristics method of the [sqlite3_io_methods] +** object returns an integer which is a vector of the these +** bit values expressing I/O characteristics of the mass storage +** device that holds the file that the [sqlite3_io_methods] +** refers to. +** +** The SQLITE_IOCAP_ATOMIC property means that all writes of +** any size are atomic. The SQLITE_IOCAP_ATOMICnnn values +** mean that writes of blocks that are nnn bytes in size and +** are aligned to an address which is an integer multiple of +** nnn are atomic. The SQLITE_IOCAP_SAFE_APPEND value means +** that when data is appended to a file, the data is appended +** first then the size of the file is extended, never the other +** way around. The SQLITE_IOCAP_SEQUENTIAL property means that +** information is written to disk in the same order as calls +** to xWrite(). The SQLITE_IOCAP_POWERSAFE_OVERWRITE property means that +** after reboot following a crash or power loss, the only bytes in a +** file that were written at the application level might have changed +** and that adjacent bytes, even bytes within the same sector are +** guaranteed to be unchanged. +*/ +#define SQLITE_IOCAP_ATOMIC 0x00000001 +#define SQLITE_IOCAP_ATOMIC512 0x00000002 +#define SQLITE_IOCAP_ATOMIC1K 0x00000004 +#define SQLITE_IOCAP_ATOMIC2K 0x00000008 +#define SQLITE_IOCAP_ATOMIC4K 0x00000010 +#define SQLITE_IOCAP_ATOMIC8K 0x00000020 +#define SQLITE_IOCAP_ATOMIC16K 0x00000040 +#define SQLITE_IOCAP_ATOMIC32K 0x00000080 +#define SQLITE_IOCAP_ATOMIC64K 0x00000100 +#define SQLITE_IOCAP_SAFE_APPEND 0x00000200 +#define SQLITE_IOCAP_SEQUENTIAL 0x00000400 +#define SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN 0x00000800 +#define SQLITE_IOCAP_POWERSAFE_OVERWRITE 0x00001000 + +/* +** CAPI3REF: File Locking Levels +** +** SQLite uses one of these integer values as the second +** argument to calls it makes to the xLock() and xUnlock() methods +** of an [sqlite3_io_methods] object. +*/ +#define SQLITE_LOCK_NONE 0 +#define SQLITE_LOCK_SHARED 1 +#define SQLITE_LOCK_RESERVED 2 +#define SQLITE_LOCK_PENDING 3 +#define SQLITE_LOCK_EXCLUSIVE 4 + +/* +** CAPI3REF: Synchronization Type Flags +** +** When SQLite invokes the xSync() method of an +** [sqlite3_io_methods] object it uses a combination of +** these integer values as the second argument. +** +** When the SQLITE_SYNC_DATAONLY flag is used, it means that the +** sync operation only needs to flush data to mass storage. Inode +** information need not be flushed. If the lower four bits of the flag +** equal SQLITE_SYNC_NORMAL, that means to use normal fsync() semantics. +** If the lower four bits equal SQLITE_SYNC_FULL, that means +** to use Mac OS X style fullsync instead of fsync(). +** +** Do not confuse the SQLITE_SYNC_NORMAL and SQLITE_SYNC_FULL flags +** with the [PRAGMA synchronous]=NORMAL and [PRAGMA synchronous]=FULL +** settings. The [synchronous pragma] determines when calls to the +** xSync VFS method occur and applies uniformly across all platforms. +** The SQLITE_SYNC_NORMAL and SQLITE_SYNC_FULL flags determine how +** energetic or rigorous or forceful the sync operations are and +** only make a difference on Mac OSX for the default SQLite code. +** (Third-party VFS implementations might also make the distinction +** between SQLITE_SYNC_NORMAL and SQLITE_SYNC_FULL, but among the +** operating systems natively supported by SQLite, only Mac OSX +** cares about the difference.) +*/ +#define SQLITE_SYNC_NORMAL 0x00002 +#define SQLITE_SYNC_FULL 0x00003 +#define SQLITE_SYNC_DATAONLY 0x00010 + +/* +** CAPI3REF: OS Interface Open File Handle +** +** An [sqlite3_file] object represents an open file in the +** [sqlite3_vfs | OS interface layer]. Individual OS interface +** implementations will +** want to subclass this object by appending additional fields +** for their own use. The pMethods entry is a pointer to an +** [sqlite3_io_methods] object that defines methods for performing +** I/O operations on the open file. +*/ +typedef struct sqlite3_file sqlite3_file; +struct sqlite3_file { + const struct sqlite3_io_methods *pMethods; /* Methods for an open file */ +}; + +/* +** CAPI3REF: OS Interface File Virtual Methods Object +** +** Every file opened by the [sqlite3_vfs.xOpen] method populates an +** [sqlite3_file] object (or, more commonly, a subclass of the +** [sqlite3_file] object) with a pointer to an instance of this object. +** This object defines the methods used to perform various operations +** against the open file represented by the [sqlite3_file] object. +** +** If the [sqlite3_vfs.xOpen] method sets the sqlite3_file.pMethods element +** to a non-NULL pointer, then the sqlite3_io_methods.xClose method +** may be invoked even if the [sqlite3_vfs.xOpen] reported that it failed. The +** only way to prevent a call to xClose following a failed [sqlite3_vfs.xOpen] +** is for the [sqlite3_vfs.xOpen] to set the sqlite3_file.pMethods element +** to NULL. +** +** The flags argument to xSync may be one of [SQLITE_SYNC_NORMAL] or +** [SQLITE_SYNC_FULL]. The first choice is the normal fsync(). +** The second choice is a Mac OS X style fullsync. The [SQLITE_SYNC_DATAONLY] +** flag may be ORed in to indicate that only the data of the file +** and not its inode needs to be synced. +** +** The integer values to xLock() and xUnlock() are one of +**
      +**
    • [SQLITE_LOCK_NONE], +**
    • [SQLITE_LOCK_SHARED], +**
    • [SQLITE_LOCK_RESERVED], +**
    • [SQLITE_LOCK_PENDING], or +**
    • [SQLITE_LOCK_EXCLUSIVE]. +**
    +** xLock() increases the lock. xUnlock() decreases the lock. +** The xCheckReservedLock() method checks whether any database connection, +** either in this process or in some other process, is holding a RESERVED, +** PENDING, or EXCLUSIVE lock on the file. It returns true +** if such a lock exists and false otherwise. +** +** The xFileControl() method is a generic interface that allows custom +** VFS implementations to directly control an open file using the +** [sqlite3_file_control()] interface. The second "op" argument is an +** integer opcode. The third argument is a generic pointer intended to +** point to a structure that may contain arguments or space in which to +** write return values. Potential uses for xFileControl() might be +** functions to enable blocking locks with timeouts, to change the +** locking strategy (for example to use dot-file locks), to inquire +** about the status of a lock, or to break stale locks. The SQLite +** core reserves all opcodes less than 100 for its own use. +** A [SQLITE_FCNTL_LOCKSTATE | list of opcodes] less than 100 is available. +** Applications that define a custom xFileControl method should use opcodes +** greater than 100 to avoid conflicts. VFS implementations should +** return [SQLITE_NOTFOUND] for file control opcodes that they do not +** recognize. +** +** The xSectorSize() method returns the sector size of the +** device that underlies the file. The sector size is the +** minimum write that can be performed without disturbing +** other bytes in the file. The xDeviceCharacteristics() +** method returns a bit vector describing behaviors of the +** underlying device: +** +**
      +**
    • [SQLITE_IOCAP_ATOMIC] +**
    • [SQLITE_IOCAP_ATOMIC512] +**
    • [SQLITE_IOCAP_ATOMIC1K] +**
    • [SQLITE_IOCAP_ATOMIC2K] +**
    • [SQLITE_IOCAP_ATOMIC4K] +**
    • [SQLITE_IOCAP_ATOMIC8K] +**
    • [SQLITE_IOCAP_ATOMIC16K] +**
    • [SQLITE_IOCAP_ATOMIC32K] +**
    • [SQLITE_IOCAP_ATOMIC64K] +**
    • [SQLITE_IOCAP_SAFE_APPEND] +**
    • [SQLITE_IOCAP_SEQUENTIAL] +**
    +** +** The SQLITE_IOCAP_ATOMIC property means that all writes of +** any size are atomic. The SQLITE_IOCAP_ATOMICnnn values +** mean that writes of blocks that are nnn bytes in size and +** are aligned to an address which is an integer multiple of +** nnn are atomic. The SQLITE_IOCAP_SAFE_APPEND value means +** that when data is appended to a file, the data is appended +** first then the size of the file is extended, never the other +** way around. The SQLITE_IOCAP_SEQUENTIAL property means that +** information is written to disk in the same order as calls +** to xWrite(). +** +** If xRead() returns SQLITE_IOERR_SHORT_READ it must also fill +** in the unread portions of the buffer with zeros. A VFS that +** fails to zero-fill short reads might seem to work. However, +** failure to zero-fill short reads will eventually lead to +** database corruption. +*/ +typedef struct sqlite3_io_methods sqlite3_io_methods; +struct sqlite3_io_methods { + int iVersion; + int (*xClose)(sqlite3_file*); + int (*xRead)(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); + int (*xWrite)(sqlite3_file*, const void*, int iAmt, sqlite3_int64 iOfst); + int (*xTruncate)(sqlite3_file*, sqlite3_int64 size); + int (*xSync)(sqlite3_file*, int flags); + int (*xFileSize)(sqlite3_file*, sqlite3_int64 *pSize); + int (*xLock)(sqlite3_file*, int); + int (*xUnlock)(sqlite3_file*, int); + int (*xCheckReservedLock)(sqlite3_file*, int *pResOut); + int (*xFileControl)(sqlite3_file*, int op, void *pArg); + int (*xSectorSize)(sqlite3_file*); + int (*xDeviceCharacteristics)(sqlite3_file*); + /* Methods above are valid for version 1 */ + int (*xShmMap)(sqlite3_file*, int iPg, int pgsz, int, void volatile**); + int (*xShmLock)(sqlite3_file*, int offset, int n, int flags); + void (*xShmBarrier)(sqlite3_file*); + int (*xShmUnmap)(sqlite3_file*, int deleteFlag); + /* Methods above are valid for version 2 */ + /* Additional methods may be added in future releases */ +}; + +/* +** CAPI3REF: Standard File Control Opcodes +** +** These integer constants are opcodes for the xFileControl method +** of the [sqlite3_io_methods] object and for the [sqlite3_file_control()] +** interface. +** +** The [SQLITE_FCNTL_LOCKSTATE] opcode is used for debugging. This +** opcode causes the xFileControl method to write the current state of +** the lock (one of [SQLITE_LOCK_NONE], [SQLITE_LOCK_SHARED], +** [SQLITE_LOCK_RESERVED], [SQLITE_LOCK_PENDING], or [SQLITE_LOCK_EXCLUSIVE]) +** into an integer that the pArg argument points to. This capability +** is used during testing and only needs to be supported when SQLITE_TEST +** is defined. +** +** The [SQLITE_FCNTL_SIZE_HINT] opcode is used by SQLite to give the VFS +** layer a hint of how large the database file will grow to be during the +** current transaction. This hint is not guaranteed to be accurate but it +** is often close. The underlying VFS might choose to preallocate database +** file space based on this hint in order to help writes to the database +** file run faster. +** +** The [SQLITE_FCNTL_CHUNK_SIZE] opcode is used to request that the VFS +** extends and truncates the database file in chunks of a size specified +** by the user. The fourth argument to [sqlite3_file_control()] should +** point to an integer (type int) containing the new chunk-size to use +** for the nominated database. Allocating database file space in large +** chunks (say 1MB at a time), may reduce file-system fragmentation and +** improve performance on some systems. +** +** The [SQLITE_FCNTL_FILE_POINTER] opcode is used to obtain a pointer +** to the [sqlite3_file] object associated with a particular database +** connection. See the [sqlite3_file_control()] documentation for +** additional information. +** +** ^(The [SQLITE_FCNTL_SYNC_OMITTED] opcode is generated internally by +** SQLite and sent to all VFSes in place of a call to the xSync method +** when the database connection has [PRAGMA synchronous] set to OFF.)^ +** Some specialized VFSes need this signal in order to operate correctly +** when [PRAGMA synchronous | PRAGMA synchronous=OFF] is set, but most +** VFSes do not need this signal and should silently ignore this opcode. +** Applications should not call [sqlite3_file_control()] with this +** opcode as doing so may disrupt the operation of the specialized VFSes +** that do require it. +** +** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic +** retry counts and intervals for certain disk I/O operations for the +** windows [VFS] in order to provide robustness in the presence of +** anti-virus programs. By default, the windows VFS will retry file read, +** file write, and file delete operations up to 10 times, with a delay +** of 25 milliseconds before the first retry and with the delay increasing +** by an additional 25 milliseconds with each subsequent retry. This +** opcode allows these two values (10 retries and 25 milliseconds of delay) +** to be adjusted. The values are changed for all database connections +** within the same process. The argument is a pointer to an array of two +** integers where the first integer i the new retry count and the second +** integer is the delay. If either integer is negative, then the setting +** is not changed but instead the prior value of that setting is written +** into the array entry, allowing the current retry settings to be +** interrogated. The zDbName parameter is ignored. +** +** ^The [SQLITE_FCNTL_PERSIST_WAL] opcode is used to set or query the +** persistent [WAL | Write AHead Log] setting. By default, the auxiliary +** write ahead log and shared memory files used for transaction control +** are automatically deleted when the latest connection to the database +** closes. Setting persistent WAL mode causes those files to persist after +** close. Persisting the files is useful when other processes that do not +** have write permission on the directory containing the database file want +** to read the database file, as the WAL and shared memory files must exist +** in order for the database to be readable. The fourth parameter to +** [sqlite3_file_control()] for this opcode should be a pointer to an integer. +** That integer is 0 to disable persistent WAL mode or 1 to enable persistent +** WAL mode. If the integer is -1, then it is overwritten with the current +** WAL persistence setting. +** +** ^The [SQLITE_FCNTL_POWERSAFE_OVERWRITE] opcode is used to set or query the +** persistent "powersafe-overwrite" or "PSOW" setting. The PSOW setting +** determines the [SQLITE_IOCAP_POWERSAFE_OVERWRITE] bit of the +** xDeviceCharacteristics methods. The fourth parameter to +** [sqlite3_file_control()] for this opcode should be a pointer to an integer. +** That integer is 0 to disable zero-damage mode or 1 to enable zero-damage +** mode. If the integer is -1, then it is overwritten with the current +** zero-damage mode setting. +** +** ^The [SQLITE_FCNTL_OVERWRITE] opcode is invoked by SQLite after opening +** a write transaction to indicate that, unless it is rolled back for some +** reason, the entire database file will be overwritten by the current +** transaction. This is used by VACUUM operations. +** +** ^The [SQLITE_FCNTL_VFSNAME] opcode can be used to obtain the names of +** all [VFSes] in the VFS stack. The names are of all VFS shims and the +** final bottom-level VFS are written into memory obtained from +** [sqlite3_malloc()] and the result is stored in the char* variable +** that the fourth parameter of [sqlite3_file_control()] points to. +** The caller is responsible for freeing the memory when done. As with +** all file-control actions, there is no guarantee that this will actually +** do anything. Callers should initialize the char* variable to a NULL +** pointer in case this file-control is not implemented. This file-control +** is intended for diagnostic use only. +*/ +#define SQLITE_FCNTL_LOCKSTATE 1 +#define SQLITE_GET_LOCKPROXYFILE 2 +#define SQLITE_SET_LOCKPROXYFILE 3 +#define SQLITE_LAST_ERRNO 4 +#define SQLITE_FCNTL_SIZE_HINT 5 +#define SQLITE_FCNTL_CHUNK_SIZE 6 +#define SQLITE_FCNTL_FILE_POINTER 7 +#define SQLITE_FCNTL_SYNC_OMITTED 8 +#define SQLITE_FCNTL_WIN32_AV_RETRY 9 +#define SQLITE_FCNTL_PERSIST_WAL 10 +#define SQLITE_FCNTL_OVERWRITE 11 +#define SQLITE_FCNTL_VFSNAME 12 +#define SQLITE_FCNTL_POWERSAFE_OVERWRITE 13 + +/* +** CAPI3REF: Mutex Handle +** +** The mutex module within SQLite defines [sqlite3_mutex] to be an +** abstract type for a mutex object. The SQLite core never looks +** at the internal representation of an [sqlite3_mutex]. It only +** deals with pointers to the [sqlite3_mutex] object. +** +** Mutexes are created using [sqlite3_mutex_alloc()]. +*/ +typedef struct sqlite3_mutex sqlite3_mutex; + +/* +** CAPI3REF: OS Interface Object +** +** An instance of the sqlite3_vfs object defines the interface between +** the SQLite core and the underlying operating system. The "vfs" +** in the name of the object stands for "virtual file system". See +** the [VFS | VFS documentation] for further information. +** +** The value of the iVersion field is initially 1 but may be larger in +** future versions of SQLite. Additional fields may be appended to this +** object when the iVersion value is increased. Note that the structure +** of the sqlite3_vfs object changes in the transaction between +** SQLite version 3.5.9 and 3.6.0 and yet the iVersion field was not +** modified. +** +** The szOsFile field is the size of the subclassed [sqlite3_file] +** structure used by this VFS. mxPathname is the maximum length of +** a pathname in this VFS. +** +** Registered sqlite3_vfs objects are kept on a linked list formed by +** the pNext pointer. The [sqlite3_vfs_register()] +** and [sqlite3_vfs_unregister()] interfaces manage this list +** in a thread-safe way. The [sqlite3_vfs_find()] interface +** searches the list. Neither the application code nor the VFS +** implementation should use the pNext pointer. +** +** The pNext field is the only field in the sqlite3_vfs +** structure that SQLite will ever modify. SQLite will only access +** or modify this field while holding a particular static mutex. +** The application should never modify anything within the sqlite3_vfs +** object once the object has been registered. +** +** The zName field holds the name of the VFS module. The name must +** be unique across all VFS modules. +** +** [[sqlite3_vfs.xOpen]] +** ^SQLite guarantees that the zFilename parameter to xOpen +** is either a NULL pointer or string obtained +** from xFullPathname() with an optional suffix added. +** ^If a suffix is added to the zFilename parameter, it will +** consist of a single "-" character followed by no more than +** 11 alphanumeric and/or "-" characters. +** ^SQLite further guarantees that +** the string will be valid and unchanged until xClose() is +** called. Because of the previous sentence, +** the [sqlite3_file] can safely store a pointer to the +** filename if it needs to remember the filename for some reason. +** If the zFilename parameter to xOpen is a NULL pointer then xOpen +** must invent its own temporary name for the file. ^Whenever the +** xFilename parameter is NULL it will also be the case that the +** flags parameter will include [SQLITE_OPEN_DELETEONCLOSE]. +** +** The flags argument to xOpen() includes all bits set in +** the flags argument to [sqlite3_open_v2()]. Or if [sqlite3_open()] +** or [sqlite3_open16()] is used, then flags includes at least +** [SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE]. +** If xOpen() opens a file read-only then it sets *pOutFlags to +** include [SQLITE_OPEN_READONLY]. Other bits in *pOutFlags may be set. +** +** ^(SQLite will also add one of the following flags to the xOpen() +** call, depending on the object being opened: +** +**
      +**
    • [SQLITE_OPEN_MAIN_DB] +**
    • [SQLITE_OPEN_MAIN_JOURNAL] +**
    • [SQLITE_OPEN_TEMP_DB] +**
    • [SQLITE_OPEN_TEMP_JOURNAL] +**
    • [SQLITE_OPEN_TRANSIENT_DB] +**
    • [SQLITE_OPEN_SUBJOURNAL] +**
    • [SQLITE_OPEN_MASTER_JOURNAL] +**
    • [SQLITE_OPEN_WAL] +**
    )^ +** +** The file I/O implementation can use the object type flags to +** change the way it deals with files. For example, an application +** that does not care about crash recovery or rollback might make +** the open of a journal file a no-op. Writes to this journal would +** also be no-ops, and any attempt to read the journal would return +** SQLITE_IOERR. Or the implementation might recognize that a database +** file will be doing page-aligned sector reads and writes in a random +** order and set up its I/O subsystem accordingly. +** +** SQLite might also add one of the following flags to the xOpen method: +** +**
      +**
    • [SQLITE_OPEN_DELETEONCLOSE] +**
    • [SQLITE_OPEN_EXCLUSIVE] +**
    +** +** The [SQLITE_OPEN_DELETEONCLOSE] flag means the file should be +** deleted when it is closed. ^The [SQLITE_OPEN_DELETEONCLOSE] +** will be set for TEMP databases and their journals, transient +** databases, and subjournals. +** +** ^The [SQLITE_OPEN_EXCLUSIVE] flag is always used in conjunction +** with the [SQLITE_OPEN_CREATE] flag, which are both directly +** analogous to the O_EXCL and O_CREAT flags of the POSIX open() +** API. The SQLITE_OPEN_EXCLUSIVE flag, when paired with the +** SQLITE_OPEN_CREATE, is used to indicate that file should always +** be created, and that it is an error if it already exists. +** It is not used to indicate the file should be opened +** for exclusive access. +** +** ^At least szOsFile bytes of memory are allocated by SQLite +** to hold the [sqlite3_file] structure passed as the third +** argument to xOpen. The xOpen method does not have to +** allocate the structure; it should just fill it in. Note that +** the xOpen method must set the sqlite3_file.pMethods to either +** a valid [sqlite3_io_methods] object or to NULL. xOpen must do +** this even if the open fails. SQLite expects that the sqlite3_file.pMethods +** element will be valid after xOpen returns regardless of the success +** or failure of the xOpen call. +** +** [[sqlite3_vfs.xAccess]] +** ^The flags argument to xAccess() may be [SQLITE_ACCESS_EXISTS] +** to test for the existence of a file, or [SQLITE_ACCESS_READWRITE] to +** test whether a file is readable and writable, or [SQLITE_ACCESS_READ] +** to test whether a file is at least readable. The file can be a +** directory. +** +** ^SQLite will always allocate at least mxPathname+1 bytes for the +** output buffer xFullPathname. The exact size of the output buffer +** is also passed as a parameter to both methods. If the output buffer +** is not large enough, [SQLITE_CANTOPEN] should be returned. Since this is +** handled as a fatal error by SQLite, vfs implementations should endeavor +** to prevent this by setting mxPathname to a sufficiently large value. +** +** The xRandomness(), xSleep(), xCurrentTime(), and xCurrentTimeInt64() +** interfaces are not strictly a part of the filesystem, but they are +** included in the VFS structure for completeness. +** The xRandomness() function attempts to return nBytes bytes +** of good-quality randomness into zOut. The return value is +** the actual number of bytes of randomness obtained. +** The xSleep() method causes the calling thread to sleep for at +** least the number of microseconds given. ^The xCurrentTime() +** method returns a Julian Day Number for the current date and time as +** a floating point value. +** ^The xCurrentTimeInt64() method returns, as an integer, the Julian +** Day Number multiplied by 86400000 (the number of milliseconds in +** a 24-hour day). +** ^SQLite will use the xCurrentTimeInt64() method to get the current +** date and time if that method is available (if iVersion is 2 or +** greater and the function pointer is not NULL) and will fall back +** to xCurrentTime() if xCurrentTimeInt64() is unavailable. +** +** ^The xSetSystemCall(), xGetSystemCall(), and xNestSystemCall() interfaces +** are not used by the SQLite core. These optional interfaces are provided +** by some VFSes to facilitate testing of the VFS code. By overriding +** system calls with functions under its control, a test program can +** simulate faults and error conditions that would otherwise be difficult +** or impossible to induce. The set of system calls that can be overridden +** varies from one VFS to another, and from one version of the same VFS to the +** next. Applications that use these interfaces must be prepared for any +** or all of these interfaces to be NULL or for their behavior to change +** from one release to the next. Applications must not attempt to access +** any of these methods if the iVersion of the VFS is less than 3. +*/ +typedef struct sqlite3_vfs sqlite3_vfs; +typedef void (*sqlite3_syscall_ptr)(void); +struct sqlite3_vfs { + int iVersion; /* Structure version number (currently 3) */ + int szOsFile; /* Size of subclassed sqlite3_file */ + int mxPathname; /* Maximum file pathname length */ + sqlite3_vfs *pNext; /* Next registered VFS */ + const char *zName; /* Name of this virtual file system */ + void *pAppData; /* Pointer to application-specific data */ + int (*xOpen)(sqlite3_vfs*, const char *zName, sqlite3_file*, + int flags, int *pOutFlags); + int (*xDelete)(sqlite3_vfs*, const char *zName, int syncDir); + int (*xAccess)(sqlite3_vfs*, const char *zName, int flags, int *pResOut); + int (*xFullPathname)(sqlite3_vfs*, const char *zName, int nOut, char *zOut); + void *(*xDlOpen)(sqlite3_vfs*, const char *zFilename); + void (*xDlError)(sqlite3_vfs*, int nByte, char *zErrMsg); + void (*(*xDlSym)(sqlite3_vfs*,void*, const char *zSymbol))(void); + void (*xDlClose)(sqlite3_vfs*, void*); + int (*xRandomness)(sqlite3_vfs*, int nByte, char *zOut); + int (*xSleep)(sqlite3_vfs*, int microseconds); + int (*xCurrentTime)(sqlite3_vfs*, double*); + int (*xGetLastError)(sqlite3_vfs*, int, char *); + /* + ** The methods above are in version 1 of the sqlite_vfs object + ** definition. Those that follow are added in version 2 or later + */ + int (*xCurrentTimeInt64)(sqlite3_vfs*, sqlite3_int64*); + /* + ** The methods above are in versions 1 and 2 of the sqlite_vfs object. + ** Those below are for version 3 and greater. + */ + int (*xSetSystemCall)(sqlite3_vfs*, const char *zName, sqlite3_syscall_ptr); + sqlite3_syscall_ptr (*xGetSystemCall)(sqlite3_vfs*, const char *zName); + const char *(*xNextSystemCall)(sqlite3_vfs*, const char *zName); + /* + ** The methods above are in versions 1 through 3 of the sqlite_vfs object. + ** New fields may be appended in figure versions. The iVersion + ** value will increment whenever this happens. + */ +}; + +/* +** CAPI3REF: Flags for the xAccess VFS method +** +** These integer constants can be used as the third parameter to +** the xAccess method of an [sqlite3_vfs] object. They determine +** what kind of permissions the xAccess method is looking for. +** With SQLITE_ACCESS_EXISTS, the xAccess method +** simply checks whether the file exists. +** With SQLITE_ACCESS_READWRITE, the xAccess method +** checks whether the named directory is both readable and writable +** (in other words, if files can be added, removed, and renamed within +** the directory). +** The SQLITE_ACCESS_READWRITE constant is currently used only by the +** [temp_store_directory pragma], though this could change in a future +** release of SQLite. +** With SQLITE_ACCESS_READ, the xAccess method +** checks whether the file is readable. The SQLITE_ACCESS_READ constant is +** currently unused, though it might be used in a future release of +** SQLite. +*/ +#define SQLITE_ACCESS_EXISTS 0 +#define SQLITE_ACCESS_READWRITE 1 /* Used by PRAGMA temp_store_directory */ +#define SQLITE_ACCESS_READ 2 /* Unused */ + +/* +** CAPI3REF: Flags for the xShmLock VFS method +** +** These integer constants define the various locking operations +** allowed by the xShmLock method of [sqlite3_io_methods]. The +** following are the only legal combinations of flags to the +** xShmLock method: +** +**
      +**
    • SQLITE_SHM_LOCK | SQLITE_SHM_SHARED +**
    • SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE +**
    • SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED +**
    • SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE +**
    +** +** When unlocking, the same SHARED or EXCLUSIVE flag must be supplied as +** was given no the corresponding lock. +** +** The xShmLock method can transition between unlocked and SHARED or +** between unlocked and EXCLUSIVE. It cannot transition between SHARED +** and EXCLUSIVE. +*/ +#define SQLITE_SHM_UNLOCK 1 +#define SQLITE_SHM_LOCK 2 +#define SQLITE_SHM_SHARED 4 +#define SQLITE_SHM_EXCLUSIVE 8 + +/* +** CAPI3REF: Maximum xShmLock index +** +** The xShmLock method on [sqlite3_io_methods] may use values +** between 0 and this upper bound as its "offset" argument. +** The SQLite core will never attempt to acquire or release a +** lock outside of this range +*/ +#define SQLITE_SHM_NLOCK 8 + + +/* +** CAPI3REF: Initialize The SQLite Library +** +** ^The sqlite3_initialize() routine initializes the +** SQLite library. ^The sqlite3_shutdown() routine +** deallocates any resources that were allocated by sqlite3_initialize(). +** These routines are designed to aid in process initialization and +** shutdown on embedded systems. Workstation applications using +** SQLite normally do not need to invoke either of these routines. +** +** A call to sqlite3_initialize() is an "effective" call if it is +** the first time sqlite3_initialize() is invoked during the lifetime of +** the process, or if it is the first time sqlite3_initialize() is invoked +** following a call to sqlite3_shutdown(). ^(Only an effective call +** of sqlite3_initialize() does any initialization. All other calls +** are harmless no-ops.)^ +** +** A call to sqlite3_shutdown() is an "effective" call if it is the first +** call to sqlite3_shutdown() since the last sqlite3_initialize(). ^(Only +** an effective call to sqlite3_shutdown() does any deinitialization. +** All other valid calls to sqlite3_shutdown() are harmless no-ops.)^ +** +** The sqlite3_initialize() interface is threadsafe, but sqlite3_shutdown() +** is not. The sqlite3_shutdown() interface must only be called from a +** single thread. All open [database connections] must be closed and all +** other SQLite resources must be deallocated prior to invoking +** sqlite3_shutdown(). +** +** Among other things, ^sqlite3_initialize() will invoke +** sqlite3_os_init(). Similarly, ^sqlite3_shutdown() +** will invoke sqlite3_os_end(). +** +** ^The sqlite3_initialize() routine returns [SQLITE_OK] on success. +** ^If for some reason, sqlite3_initialize() is unable to initialize +** the library (perhaps it is unable to allocate a needed resource such +** as a mutex) it returns an [error code] other than [SQLITE_OK]. +** +** ^The sqlite3_initialize() routine is called internally by many other +** SQLite interfaces so that an application usually does not need to +** invoke sqlite3_initialize() directly. For example, [sqlite3_open()] +** calls sqlite3_initialize() so the SQLite library will be automatically +** initialized when [sqlite3_open()] is called if it has not be initialized +** already. ^However, if SQLite is compiled with the [SQLITE_OMIT_AUTOINIT] +** compile-time option, then the automatic calls to sqlite3_initialize() +** are omitted and the application must call sqlite3_initialize() directly +** prior to using any other SQLite interface. For maximum portability, +** it is recommended that applications always invoke sqlite3_initialize() +** directly prior to using any other SQLite interface. Future releases +** of SQLite may require this. In other words, the behavior exhibited +** when SQLite is compiled with [SQLITE_OMIT_AUTOINIT] might become the +** default behavior in some future release of SQLite. +** +** The sqlite3_os_init() routine does operating-system specific +** initialization of the SQLite library. The sqlite3_os_end() +** routine undoes the effect of sqlite3_os_init(). Typical tasks +** performed by these routines include allocation or deallocation +** of static resources, initialization of global variables, +** setting up a default [sqlite3_vfs] module, or setting up +** a default configuration using [sqlite3_config()]. +** +** The application should never invoke either sqlite3_os_init() +** or sqlite3_os_end() directly. The application should only invoke +** sqlite3_initialize() and sqlite3_shutdown(). The sqlite3_os_init() +** interface is called automatically by sqlite3_initialize() and +** sqlite3_os_end() is called by sqlite3_shutdown(). Appropriate +** implementations for sqlite3_os_init() and sqlite3_os_end() +** are built into SQLite when it is compiled for Unix, Windows, or OS/2. +** When [custom builds | built for other platforms] +** (using the [SQLITE_OS_OTHER=1] compile-time +** option) the application must supply a suitable implementation for +** sqlite3_os_init() and sqlite3_os_end(). An application-supplied +** implementation of sqlite3_os_init() or sqlite3_os_end() +** must return [SQLITE_OK] on success and some other [error code] upon +** failure. +*/ +SQLITE_API int sqlite3_initialize(void); +SQLITE_API int sqlite3_shutdown(void); +SQLITE_API int sqlite3_os_init(void); +SQLITE_API int sqlite3_os_end(void); + +/* +** CAPI3REF: Configuring The SQLite Library +** +** The sqlite3_config() interface is used to make global configuration +** changes to SQLite in order to tune SQLite to the specific needs of +** the application. The default configuration is recommended for most +** applications and so this routine is usually not necessary. It is +** provided to support rare applications with unusual needs. +** +** The sqlite3_config() interface is not threadsafe. The application +** must insure that no other SQLite interfaces are invoked by other +** threads while sqlite3_config() is running. Furthermore, sqlite3_config() +** may only be invoked prior to library initialization using +** [sqlite3_initialize()] or after shutdown by [sqlite3_shutdown()]. +** ^If sqlite3_config() is called after [sqlite3_initialize()] and before +** [sqlite3_shutdown()] then it will return SQLITE_MISUSE. +** Note, however, that ^sqlite3_config() can be called as part of the +** implementation of an application-defined [sqlite3_os_init()]. +** +** The first argument to sqlite3_config() is an integer +** [configuration option] that determines +** what property of SQLite is to be configured. Subsequent arguments +** vary depending on the [configuration option] +** in the first argument. +** +** ^When a configuration option is set, sqlite3_config() returns [SQLITE_OK]. +** ^If the option is unknown or SQLite is unable to set the option +** then this routine returns a non-zero [error code]. +*/ +SQLITE_API int sqlite3_config(int, ...); + +/* +** CAPI3REF: Configure database connections +** +** The sqlite3_db_config() interface is used to make configuration +** changes to a [database connection]. The interface is similar to +** [sqlite3_config()] except that the changes apply to a single +** [database connection] (specified in the first argument). +** +** The second argument to sqlite3_db_config(D,V,...) is the +** [SQLITE_DBCONFIG_LOOKASIDE | configuration verb] - an integer code +** that indicates what aspect of the [database connection] is being configured. +** Subsequent arguments vary depending on the configuration verb. +** +** ^Calls to sqlite3_db_config() return SQLITE_OK if and only if +** the call is considered successful. +*/ +SQLITE_API int sqlite3_db_config(sqlite3*, int op, ...); + +/* +** CAPI3REF: Memory Allocation Routines +** +** An instance of this object defines the interface between SQLite +** and low-level memory allocation routines. +** +** This object is used in only one place in the SQLite interface. +** A pointer to an instance of this object is the argument to +** [sqlite3_config()] when the configuration option is +** [SQLITE_CONFIG_MALLOC] or [SQLITE_CONFIG_GETMALLOC]. +** By creating an instance of this object +** and passing it to [sqlite3_config]([SQLITE_CONFIG_MALLOC]) +** during configuration, an application can specify an alternative +** memory allocation subsystem for SQLite to use for all of its +** dynamic memory needs. +** +** Note that SQLite comes with several [built-in memory allocators] +** that are perfectly adequate for the overwhelming majority of applications +** and that this object is only useful to a tiny minority of applications +** with specialized memory allocation requirements. This object is +** also used during testing of SQLite in order to specify an alternative +** memory allocator that simulates memory out-of-memory conditions in +** order to verify that SQLite recovers gracefully from such +** conditions. +** +** The xMalloc, xRealloc, and xFree methods must work like the +** malloc(), realloc() and free() functions from the standard C library. +** ^SQLite guarantees that the second argument to +** xRealloc is always a value returned by a prior call to xRoundup. +** +** xSize should return the allocated size of a memory allocation +** previously obtained from xMalloc or xRealloc. The allocated size +** is always at least as big as the requested size but may be larger. +** +** The xRoundup method returns what would be the allocated size of +** a memory allocation given a particular requested size. Most memory +** allocators round up memory allocations at least to the next multiple +** of 8. Some allocators round up to a larger multiple or to a power of 2. +** Every memory allocation request coming in through [sqlite3_malloc()] +** or [sqlite3_realloc()] first calls xRoundup. If xRoundup returns 0, +** that causes the corresponding memory allocation to fail. +** +** The xInit method initializes the memory allocator. (For example, +** it might allocate any require mutexes or initialize internal data +** structures. The xShutdown method is invoked (indirectly) by +** [sqlite3_shutdown()] and should deallocate any resources acquired +** by xInit. The pAppData pointer is used as the only parameter to +** xInit and xShutdown. +** +** SQLite holds the [SQLITE_MUTEX_STATIC_MASTER] mutex when it invokes +** the xInit method, so the xInit method need not be threadsafe. The +** xShutdown method is only called from [sqlite3_shutdown()] so it does +** not need to be threadsafe either. For all other methods, SQLite +** holds the [SQLITE_MUTEX_STATIC_MEM] mutex as long as the +** [SQLITE_CONFIG_MEMSTATUS] configuration option is turned on (which +** it is by default) and so the methods are automatically serialized. +** However, if [SQLITE_CONFIG_MEMSTATUS] is disabled, then the other +** methods must be threadsafe or else make their own arrangements for +** serialization. +** +** SQLite will never invoke xInit() more than once without an intervening +** call to xShutdown(). +*/ +typedef struct sqlite3_mem_methods sqlite3_mem_methods; +struct sqlite3_mem_methods { + void *(*xMalloc)(int); /* Memory allocation function */ + void (*xFree)(void*); /* Free a prior allocation */ + void *(*xRealloc)(void*,int); /* Resize an allocation */ + int (*xSize)(void*); /* Return the size of an allocation */ + int (*xRoundup)(int); /* Round up request size to allocation size */ + int (*xInit)(void*); /* Initialize the memory allocator */ + void (*xShutdown)(void*); /* Deinitialize the memory allocator */ + void *pAppData; /* Argument to xInit() and xShutdown() */ +}; + +/* +** CAPI3REF: Configuration Options +** KEYWORDS: {configuration option} +** +** These constants are the available integer configuration options that +** can be passed as the first argument to the [sqlite3_config()] interface. +** +** New configuration options may be added in future releases of SQLite. +** Existing configuration options might be discontinued. Applications +** should check the return code from [sqlite3_config()] to make sure that +** the call worked. The [sqlite3_config()] interface will return a +** non-zero [error code] if a discontinued or unsupported configuration option +** is invoked. +** +**
    +** [[SQLITE_CONFIG_SINGLETHREAD]]
    SQLITE_CONFIG_SINGLETHREAD
    +**
    There are no arguments to this option. ^This option sets the +** [threading mode] to Single-thread. In other words, it disables +** all mutexing and puts SQLite into a mode where it can only be used +** by a single thread. ^If SQLite is compiled with +** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then +** it is not possible to change the [threading mode] from its default +** value of Single-thread and so [sqlite3_config()] will return +** [SQLITE_ERROR] if called with the SQLITE_CONFIG_SINGLETHREAD +** configuration option.
    +** +** [[SQLITE_CONFIG_MULTITHREAD]]
    SQLITE_CONFIG_MULTITHREAD
    +**
    There are no arguments to this option. ^This option sets the +** [threading mode] to Multi-thread. In other words, it disables +** mutexing on [database connection] and [prepared statement] objects. +** The application is responsible for serializing access to +** [database connections] and [prepared statements]. But other mutexes +** are enabled so that SQLite will be safe to use in a multi-threaded +** environment as long as no two threads attempt to use the same +** [database connection] at the same time. ^If SQLite is compiled with +** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then +** it is not possible to set the Multi-thread [threading mode] and +** [sqlite3_config()] will return [SQLITE_ERROR] if called with the +** SQLITE_CONFIG_MULTITHREAD configuration option.
    +** +** [[SQLITE_CONFIG_SERIALIZED]]
    SQLITE_CONFIG_SERIALIZED
    +**
    There are no arguments to this option. ^This option sets the +** [threading mode] to Serialized. In other words, this option enables +** all mutexes including the recursive +** mutexes on [database connection] and [prepared statement] objects. +** In this mode (which is the default when SQLite is compiled with +** [SQLITE_THREADSAFE=1]) the SQLite library will itself serialize access +** to [database connections] and [prepared statements] so that the +** application is free to use the same [database connection] or the +** same [prepared statement] in different threads at the same time. +** ^If SQLite is compiled with +** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then +** it is not possible to set the Serialized [threading mode] and +** [sqlite3_config()] will return [SQLITE_ERROR] if called with the +** SQLITE_CONFIG_SERIALIZED configuration option.
    +** +** [[SQLITE_CONFIG_MALLOC]]
    SQLITE_CONFIG_MALLOC
    +**
    ^(This option takes a single argument which is a pointer to an +** instance of the [sqlite3_mem_methods] structure. The argument specifies +** alternative low-level memory allocation routines to be used in place of +** the memory allocation routines built into SQLite.)^ ^SQLite makes +** its own private copy of the content of the [sqlite3_mem_methods] structure +** before the [sqlite3_config()] call returns.
    +** +** [[SQLITE_CONFIG_GETMALLOC]]
    SQLITE_CONFIG_GETMALLOC
    +**
    ^(This option takes a single argument which is a pointer to an +** instance of the [sqlite3_mem_methods] structure. The [sqlite3_mem_methods] +** structure is filled with the currently defined memory allocation routines.)^ +** This option can be used to overload the default memory allocation +** routines with a wrapper that simulations memory allocation failure or +** tracks memory usage, for example.
    +** +** [[SQLITE_CONFIG_MEMSTATUS]]
    SQLITE_CONFIG_MEMSTATUS
    +**
    ^This option takes single argument of type int, interpreted as a +** boolean, which enables or disables the collection of memory allocation +** statistics. ^(When memory allocation statistics are disabled, the +** following SQLite interfaces become non-operational: +**
      +**
    • [sqlite3_memory_used()] +**
    • [sqlite3_memory_highwater()] +**
    • [sqlite3_soft_heap_limit64()] +**
    • [sqlite3_status()] +**
    )^ +** ^Memory allocation statistics are enabled by default unless SQLite is +** compiled with [SQLITE_DEFAULT_MEMSTATUS]=0 in which case memory +** allocation statistics are disabled by default. +**
    +** +** [[SQLITE_CONFIG_SCRATCH]]
    SQLITE_CONFIG_SCRATCH
    +**
    ^This option specifies a static memory buffer that SQLite can use for +** scratch memory. There are three arguments: A pointer an 8-byte +** aligned memory buffer from which the scratch allocations will be +** drawn, the size of each scratch allocation (sz), +** and the maximum number of scratch allocations (N). The sz +** argument must be a multiple of 16. +** The first argument must be a pointer to an 8-byte aligned buffer +** of at least sz*N bytes of memory. +** ^SQLite will use no more than two scratch buffers per thread. So +** N should be set to twice the expected maximum number of threads. +** ^SQLite will never require a scratch buffer that is more than 6 +** times the database page size. ^If SQLite needs needs additional +** scratch memory beyond what is provided by this configuration option, then +** [sqlite3_malloc()] will be used to obtain the memory needed.
    +** +** [[SQLITE_CONFIG_PAGECACHE]]
    SQLITE_CONFIG_PAGECACHE
    +**
    ^This option specifies a static memory buffer that SQLite can use for +** the database page cache with the default page cache implementation. +** This configuration should not be used if an application-define page +** cache implementation is loaded using the SQLITE_CONFIG_PCACHE2 option. +** There are three arguments to this option: A pointer to 8-byte aligned +** memory, the size of each page buffer (sz), and the number of pages (N). +** The sz argument should be the size of the largest database page +** (a power of two between 512 and 32768) plus a little extra for each +** page header. ^The page header size is 20 to 40 bytes depending on +** the host architecture. ^It is harmless, apart from the wasted memory, +** to make sz a little too large. The first +** argument should point to an allocation of at least sz*N bytes of memory. +** ^SQLite will use the memory provided by the first argument to satisfy its +** memory needs for the first N pages that it adds to cache. ^If additional +** page cache memory is needed beyond what is provided by this option, then +** SQLite goes to [sqlite3_malloc()] for the additional storage space. +** The pointer in the first argument must +** be aligned to an 8-byte boundary or subsequent behavior of SQLite +** will be undefined.
    +** +** [[SQLITE_CONFIG_HEAP]]
    SQLITE_CONFIG_HEAP
    +**
    ^This option specifies a static memory buffer that SQLite will use +** for all of its dynamic memory allocation needs beyond those provided +** for by [SQLITE_CONFIG_SCRATCH] and [SQLITE_CONFIG_PAGECACHE]. +** There are three arguments: An 8-byte aligned pointer to the memory, +** the number of bytes in the memory buffer, and the minimum allocation size. +** ^If the first pointer (the memory pointer) is NULL, then SQLite reverts +** to using its default memory allocator (the system malloc() implementation), +** undoing any prior invocation of [SQLITE_CONFIG_MALLOC]. ^If the +** memory pointer is not NULL and either [SQLITE_ENABLE_MEMSYS3] or +** [SQLITE_ENABLE_MEMSYS5] are defined, then the alternative memory +** allocator is engaged to handle all of SQLites memory allocation needs. +** The first pointer (the memory pointer) must be aligned to an 8-byte +** boundary or subsequent behavior of SQLite will be undefined. +** The minimum allocation size is capped at 2**12. Reasonable values +** for the minimum allocation size are 2**5 through 2**8.
    +** +** [[SQLITE_CONFIG_MUTEX]]
    SQLITE_CONFIG_MUTEX
    +**
    ^(This option takes a single argument which is a pointer to an +** instance of the [sqlite3_mutex_methods] structure. The argument specifies +** alternative low-level mutex routines to be used in place +** the mutex routines built into SQLite.)^ ^SQLite makes a copy of the +** content of the [sqlite3_mutex_methods] structure before the call to +** [sqlite3_config()] returns. ^If SQLite is compiled with +** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then +** the entire mutexing subsystem is omitted from the build and hence calls to +** [sqlite3_config()] with the SQLITE_CONFIG_MUTEX configuration option will +** return [SQLITE_ERROR].
    +** +** [[SQLITE_CONFIG_GETMUTEX]]
    SQLITE_CONFIG_GETMUTEX
    +**
    ^(This option takes a single argument which is a pointer to an +** instance of the [sqlite3_mutex_methods] structure. The +** [sqlite3_mutex_methods] +** structure is filled with the currently defined mutex routines.)^ +** This option can be used to overload the default mutex allocation +** routines with a wrapper used to track mutex usage for performance +** profiling or testing, for example. ^If SQLite is compiled with +** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then +** the entire mutexing subsystem is omitted from the build and hence calls to +** [sqlite3_config()] with the SQLITE_CONFIG_GETMUTEX configuration option will +** return [SQLITE_ERROR].
    +** +** [[SQLITE_CONFIG_LOOKASIDE]]
    SQLITE_CONFIG_LOOKASIDE
    +**
    ^(This option takes two arguments that determine the default +** memory allocation for the lookaside memory allocator on each +** [database connection]. The first argument is the +** size of each lookaside buffer slot and the second is the number of +** slots allocated to each database connection.)^ ^(This option sets the +** default lookaside size. The [SQLITE_DBCONFIG_LOOKASIDE] +** verb to [sqlite3_db_config()] can be used to change the lookaside +** configuration on individual connections.)^
    +** +** [[SQLITE_CONFIG_PCACHE2]]
    SQLITE_CONFIG_PCACHE2
    +**
    ^(This option takes a single argument which is a pointer to +** an [sqlite3_pcache_methods2] object. This object specifies the interface +** to a custom page cache implementation.)^ ^SQLite makes a copy of the +** object and uses it for page cache memory allocations.
    +** +** [[SQLITE_CONFIG_GETPCACHE2]]
    SQLITE_CONFIG_GETPCACHE2
    +**
    ^(This option takes a single argument which is a pointer to an +** [sqlite3_pcache_methods2] object. SQLite copies of the current +** page cache implementation into that object.)^
    +** +** [[SQLITE_CONFIG_LOG]]
    SQLITE_CONFIG_LOG
    +**
    ^The SQLITE_CONFIG_LOG option takes two arguments: a pointer to a +** function with a call signature of void(*)(void*,int,const char*), +** and a pointer to void. ^If the function pointer is not NULL, it is +** invoked by [sqlite3_log()] to process each logging event. ^If the +** function pointer is NULL, the [sqlite3_log()] interface becomes a no-op. +** ^The void pointer that is the second argument to SQLITE_CONFIG_LOG is +** passed through as the first parameter to the application-defined logger +** function whenever that function is invoked. ^The second parameter to +** the logger function is a copy of the first parameter to the corresponding +** [sqlite3_log()] call and is intended to be a [result code] or an +** [extended result code]. ^The third parameter passed to the logger is +** log message after formatting via [sqlite3_snprintf()]. +** The SQLite logging interface is not reentrant; the logger function +** supplied by the application must not invoke any SQLite interface. +** In a multi-threaded application, the application-defined logger +** function must be threadsafe.
    +** +** [[SQLITE_CONFIG_URI]]
    SQLITE_CONFIG_URI +**
    This option takes a single argument of type int. If non-zero, then +** URI handling is globally enabled. If the parameter is zero, then URI handling +** is globally disabled. If URI handling is globally enabled, all filenames +** passed to [sqlite3_open()], [sqlite3_open_v2()], [sqlite3_open16()] or +** specified as part of [ATTACH] commands are interpreted as URIs, regardless +** of whether or not the [SQLITE_OPEN_URI] flag is set when the database +** connection is opened. If it is globally disabled, filenames are +** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the +** database connection is opened. By default, URI handling is globally +** disabled. The default value may be changed by compiling with the +** [SQLITE_USE_URI] symbol defined. +** +** [[SQLITE_CONFIG_PCACHE]] [[SQLITE_CONFIG_GETPCACHE]] +**
    SQLITE_CONFIG_PCACHE and SQLITE_CONFNIG_GETPCACHE +**
    These options are obsolete and should not be used by new code. +** They are retained for backwards compatibility but are now no-ops. +**
    +*/ +#define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ +#define SQLITE_CONFIG_MULTITHREAD 2 /* nil */ +#define SQLITE_CONFIG_SERIALIZED 3 /* nil */ +#define SQLITE_CONFIG_MALLOC 4 /* sqlite3_mem_methods* */ +#define SQLITE_CONFIG_GETMALLOC 5 /* sqlite3_mem_methods* */ +#define SQLITE_CONFIG_SCRATCH 6 /* void*, int sz, int N */ +#define SQLITE_CONFIG_PAGECACHE 7 /* void*, int sz, int N */ +#define SQLITE_CONFIG_HEAP 8 /* void*, int nByte, int min */ +#define SQLITE_CONFIG_MEMSTATUS 9 /* boolean */ +#define SQLITE_CONFIG_MUTEX 10 /* sqlite3_mutex_methods* */ +#define SQLITE_CONFIG_GETMUTEX 11 /* sqlite3_mutex_methods* */ +/* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */ +#define SQLITE_CONFIG_LOOKASIDE 13 /* int int */ +#define SQLITE_CONFIG_PCACHE 14 /* no-op */ +#define SQLITE_CONFIG_GETPCACHE 15 /* no-op */ +#define SQLITE_CONFIG_LOG 16 /* xFunc, void* */ +#define SQLITE_CONFIG_URI 17 /* int */ +#define SQLITE_CONFIG_PCACHE2 18 /* sqlite3_pcache_methods2* */ +#define SQLITE_CONFIG_GETPCACHE2 19 /* sqlite3_pcache_methods2* */ + +/* +** CAPI3REF: Database Connection Configuration Options +** +** These constants are the available integer configuration options that +** can be passed as the second argument to the [sqlite3_db_config()] interface. +** +** New configuration options may be added in future releases of SQLite. +** Existing configuration options might be discontinued. Applications +** should check the return code from [sqlite3_db_config()] to make sure that +** the call worked. ^The [sqlite3_db_config()] interface will return a +** non-zero [error code] if a discontinued or unsupported configuration option +** is invoked. +** +**
    +**
    SQLITE_DBCONFIG_LOOKASIDE
    +**
    ^This option takes three additional arguments that determine the +** [lookaside memory allocator] configuration for the [database connection]. +** ^The first argument (the third parameter to [sqlite3_db_config()] is a +** pointer to a memory buffer to use for lookaside memory. +** ^The first argument after the SQLITE_DBCONFIG_LOOKASIDE verb +** may be NULL in which case SQLite will allocate the +** lookaside buffer itself using [sqlite3_malloc()]. ^The second argument is the +** size of each lookaside buffer slot. ^The third argument is the number of +** slots. The size of the buffer in the first argument must be greater than +** or equal to the product of the second and third arguments. The buffer +** must be aligned to an 8-byte boundary. ^If the second argument to +** SQLITE_DBCONFIG_LOOKASIDE is not a multiple of 8, it is internally +** rounded down to the next smaller multiple of 8. ^(The lookaside memory +** configuration for a database connection can only be changed when that +** connection is not currently using lookaside memory, or in other words +** when the "current value" returned by +** [sqlite3_db_status](D,[SQLITE_CONFIG_LOOKASIDE],...) is zero. +** Any attempt to change the lookaside memory configuration when lookaside +** memory is in use leaves the configuration unchanged and returns +** [SQLITE_BUSY].)^
    +** +**
    SQLITE_DBCONFIG_ENABLE_FKEY
    +**
    ^This option is used to enable or disable the enforcement of +** [foreign key constraints]. There should be two additional arguments. +** The first argument is an integer which is 0 to disable FK enforcement, +** positive to enable FK enforcement or negative to leave FK enforcement +** unchanged. The second parameter is a pointer to an integer into which +** is written 0 or 1 to indicate whether FK enforcement is off or on +** following this call. The second parameter may be a NULL pointer, in +** which case the FK enforcement setting is not reported back.
    +** +**
    SQLITE_DBCONFIG_ENABLE_TRIGGER
    +**
    ^This option is used to enable or disable [CREATE TRIGGER | triggers]. +** There should be two additional arguments. +** The first argument is an integer which is 0 to disable triggers, +** positive to enable triggers or negative to leave the setting unchanged. +** The second parameter is a pointer to an integer into which +** is written 0 or 1 to indicate whether triggers are disabled or enabled +** following this call. The second parameter may be a NULL pointer, in +** which case the trigger setting is not reported back.
    +** +**
    +*/ +#define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */ +#define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */ +#define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */ + + +/* +** CAPI3REF: Enable Or Disable Extended Result Codes +** +** ^The sqlite3_extended_result_codes() routine enables or disables the +** [extended result codes] feature of SQLite. ^The extended result +** codes are disabled by default for historical compatibility. +*/ +SQLITE_API int sqlite3_extended_result_codes(sqlite3*, int onoff); + +/* +** CAPI3REF: Last Insert Rowid +** +** ^Each entry in an SQLite table has a unique 64-bit signed +** integer key called the [ROWID | "rowid"]. ^The rowid is always available +** as an undeclared column named ROWID, OID, or _ROWID_ as long as those +** names are not also used by explicitly declared columns. ^If +** the table has a column of type [INTEGER PRIMARY KEY] then that column +** is another alias for the rowid. +** +** ^This routine returns the [rowid] of the most recent +** successful [INSERT] into the database from the [database connection] +** in the first argument. ^As of SQLite version 3.7.7, this routines +** records the last insert rowid of both ordinary tables and [virtual tables]. +** ^If no successful [INSERT]s +** have ever occurred on that database connection, zero is returned. +** +** ^(If an [INSERT] occurs within a trigger or within a [virtual table] +** method, then this routine will return the [rowid] of the inserted +** row as long as the trigger or virtual table method is running. +** But once the trigger or virtual table method ends, the value returned +** by this routine reverts to what it was before the trigger or virtual +** table method began.)^ +** +** ^An [INSERT] that fails due to a constraint violation is not a +** successful [INSERT] and does not change the value returned by this +** routine. ^Thus INSERT OR FAIL, INSERT OR IGNORE, INSERT OR ROLLBACK, +** and INSERT OR ABORT make no changes to the return value of this +** routine when their insertion fails. ^(When INSERT OR REPLACE +** encounters a constraint violation, it does not fail. The +** INSERT continues to completion after deleting rows that caused +** the constraint problem so INSERT OR REPLACE will always change +** the return value of this interface.)^ +** +** ^For the purposes of this routine, an [INSERT] is considered to +** be successful even if it is subsequently rolled back. +** +** This function is accessible to SQL statements via the +** [last_insert_rowid() SQL function]. +** +** If a separate thread performs a new [INSERT] on the same +** database connection while the [sqlite3_last_insert_rowid()] +** function is running and thus changes the last insert [rowid], +** then the value returned by [sqlite3_last_insert_rowid()] is +** unpredictable and might not equal either the old or the new +** last insert [rowid]. +*/ +SQLITE_API sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*); + +/* +** CAPI3REF: Count The Number Of Rows Modified +** +** ^This function returns the number of database rows that were changed +** or inserted or deleted by the most recently completed SQL statement +** on the [database connection] specified by the first parameter. +** ^(Only changes that are directly specified by the [INSERT], [UPDATE], +** or [DELETE] statement are counted. Auxiliary changes caused by +** triggers or [foreign key actions] are not counted.)^ Use the +** [sqlite3_total_changes()] function to find the total number of changes +** including changes caused by triggers and foreign key actions. +** +** ^Changes to a view that are simulated by an [INSTEAD OF trigger] +** are not counted. Only real table changes are counted. +** +** ^(A "row change" is a change to a single row of a single table +** caused by an INSERT, DELETE, or UPDATE statement. Rows that +** are changed as side effects of [REPLACE] constraint resolution, +** rollback, ABORT processing, [DROP TABLE], or by any other +** mechanisms do not count as direct row changes.)^ +** +** A "trigger context" is a scope of execution that begins and +** ends with the script of a [CREATE TRIGGER | trigger]. +** Most SQL statements are +** evaluated outside of any trigger. This is the "top level" +** trigger context. If a trigger fires from the top level, a +** new trigger context is entered for the duration of that one +** trigger. Subtriggers create subcontexts for their duration. +** +** ^Calling [sqlite3_exec()] or [sqlite3_step()] recursively does +** not create a new trigger context. +** +** ^This function returns the number of direct row changes in the +** most recent INSERT, UPDATE, or DELETE statement within the same +** trigger context. +** +** ^Thus, when called from the top level, this function returns the +** number of changes in the most recent INSERT, UPDATE, or DELETE +** that also occurred at the top level. ^(Within the body of a trigger, +** the sqlite3_changes() interface can be called to find the number of +** changes in the most recently completed INSERT, UPDATE, or DELETE +** statement within the body of the same trigger. +** However, the number returned does not include changes +** caused by subtriggers since those have their own context.)^ +** +** See also the [sqlite3_total_changes()] interface, the +** [count_changes pragma], and the [changes() SQL function]. +** +** If a separate thread makes changes on the same database connection +** while [sqlite3_changes()] is running then the value returned +** is unpredictable and not meaningful. +*/ +SQLITE_API int sqlite3_changes(sqlite3*); + +/* +** CAPI3REF: Total Number Of Rows Modified +** +** ^This function returns the number of row changes caused by [INSERT], +** [UPDATE] or [DELETE] statements since the [database connection] was opened. +** ^(The count returned by sqlite3_total_changes() includes all changes +** from all [CREATE TRIGGER | trigger] contexts and changes made by +** [foreign key actions]. However, +** the count does not include changes used to implement [REPLACE] constraints, +** do rollbacks or ABORT processing, or [DROP TABLE] processing. The +** count does not include rows of views that fire an [INSTEAD OF trigger], +** though if the INSTEAD OF trigger makes changes of its own, those changes +** are counted.)^ +** ^The sqlite3_total_changes() function counts the changes as soon as +** the statement that makes them is completed (when the statement handle +** is passed to [sqlite3_reset()] or [sqlite3_finalize()]). +** +** See also the [sqlite3_changes()] interface, the +** [count_changes pragma], and the [total_changes() SQL function]. +** +** If a separate thread makes changes on the same database connection +** while [sqlite3_total_changes()] is running then the value +** returned is unpredictable and not meaningful. +*/ +SQLITE_API int sqlite3_total_changes(sqlite3*); + +/* +** CAPI3REF: Interrupt A Long-Running Query +** +** ^This function causes any pending database operation to abort and +** return at its earliest opportunity. This routine is typically +** called in response to a user action such as pressing "Cancel" +** or Ctrl-C where the user wants a long query operation to halt +** immediately. +** +** ^It is safe to call this routine from a thread different from the +** thread that is currently running the database operation. But it +** is not safe to call this routine with a [database connection] that +** is closed or might close before sqlite3_interrupt() returns. +** +** ^If an SQL operation is very nearly finished at the time when +** sqlite3_interrupt() is called, then it might not have an opportunity +** to be interrupted and might continue to completion. +** +** ^An SQL operation that is interrupted will return [SQLITE_INTERRUPT]. +** ^If the interrupted SQL operation is an INSERT, UPDATE, or DELETE +** that is inside an explicit transaction, then the entire transaction +** will be rolled back automatically. +** +** ^The sqlite3_interrupt(D) call is in effect until all currently running +** SQL statements on [database connection] D complete. ^Any new SQL statements +** that are started after the sqlite3_interrupt() call and before the +** running statements reaches zero are interrupted as if they had been +** running prior to the sqlite3_interrupt() call. ^New SQL statements +** that are started after the running statement count reaches zero are +** not effected by the sqlite3_interrupt(). +** ^A call to sqlite3_interrupt(D) that occurs when there are no running +** SQL statements is a no-op and has no effect on SQL statements +** that are started after the sqlite3_interrupt() call returns. +** +** If the database connection closes while [sqlite3_interrupt()] +** is running then bad things will likely happen. +*/ +SQLITE_API void sqlite3_interrupt(sqlite3*); + +/* +** CAPI3REF: Determine If An SQL Statement Is Complete +** +** These routines are useful during command-line input to determine if the +** currently entered text seems to form a complete SQL statement or +** if additional input is needed before sending the text into +** SQLite for parsing. ^These routines return 1 if the input string +** appears to be a complete SQL statement. ^A statement is judged to be +** complete if it ends with a semicolon token and is not a prefix of a +** well-formed CREATE TRIGGER statement. ^Semicolons that are embedded within +** string literals or quoted identifier names or comments are not +** independent tokens (they are part of the token in which they are +** embedded) and thus do not count as a statement terminator. ^Whitespace +** and comments that follow the final semicolon are ignored. +** +** ^These routines return 0 if the statement is incomplete. ^If a +** memory allocation fails, then SQLITE_NOMEM is returned. +** +** ^These routines do not parse the SQL statements thus +** will not detect syntactically incorrect SQL. +** +** ^(If SQLite has not been initialized using [sqlite3_initialize()] prior +** to invoking sqlite3_complete16() then sqlite3_initialize() is invoked +** automatically by sqlite3_complete16(). If that initialization fails, +** then the return value from sqlite3_complete16() will be non-zero +** regardless of whether or not the input SQL is complete.)^ +** +** The input to [sqlite3_complete()] must be a zero-terminated +** UTF-8 string. +** +** The input to [sqlite3_complete16()] must be a zero-terminated +** UTF-16 string in native byte order. +*/ +SQLITE_API int sqlite3_complete(const char *sql); +SQLITE_API int sqlite3_complete16(const void *sql); + +/* +** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors +** +** ^This routine sets a callback function that might be invoked whenever +** an attempt is made to open a database table that another thread +** or process has locked. +** +** ^If the busy callback is NULL, then [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED] +** is returned immediately upon encountering the lock. ^If the busy callback +** is not NULL, then the callback might be invoked with two arguments. +** +** ^The first argument to the busy handler is a copy of the void* pointer which +** is the third argument to sqlite3_busy_handler(). ^The second argument to +** the busy handler callback is the number of times that the busy handler has +** been invoked for this locking event. ^If the +** busy callback returns 0, then no additional attempts are made to +** access the database and [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED] is returned. +** ^If the callback returns non-zero, then another attempt +** is made to open the database for reading and the cycle repeats. +** +** The presence of a busy handler does not guarantee that it will be invoked +** when there is lock contention. ^If SQLite determines that invoking the busy +** handler could result in a deadlock, it will go ahead and return [SQLITE_BUSY] +** or [SQLITE_IOERR_BLOCKED] instead of invoking the busy handler. +** Consider a scenario where one process is holding a read lock that +** it is trying to promote to a reserved lock and +** a second process is holding a reserved lock that it is trying +** to promote to an exclusive lock. The first process cannot proceed +** because it is blocked by the second and the second process cannot +** proceed because it is blocked by the first. If both processes +** invoke the busy handlers, neither will make any progress. Therefore, +** SQLite returns [SQLITE_BUSY] for the first process, hoping that this +** will induce the first process to release its read lock and allow +** the second process to proceed. +** +** ^The default busy callback is NULL. +** +** ^The [SQLITE_BUSY] error is converted to [SQLITE_IOERR_BLOCKED] +** when SQLite is in the middle of a large transaction where all the +** changes will not fit into the in-memory cache. SQLite will +** already hold a RESERVED lock on the database file, but it needs +** to promote this lock to EXCLUSIVE so that it can spill cache +** pages into the database file without harm to concurrent +** readers. ^If it is unable to promote the lock, then the in-memory +** cache will be left in an inconsistent state and so the error +** code is promoted from the relatively benign [SQLITE_BUSY] to +** the more severe [SQLITE_IOERR_BLOCKED]. ^This error code promotion +** forces an automatic rollback of the changes. See the +** +** CorruptionFollowingBusyError wiki page for a discussion of why +** this is important. +** +** ^(There can only be a single busy handler defined for each +** [database connection]. Setting a new busy handler clears any +** previously set handler.)^ ^Note that calling [sqlite3_busy_timeout()] +** will also set or clear the busy handler. +** +** The busy callback should not take any actions which modify the +** database connection that invoked the busy handler. Any such actions +** result in undefined behavior. +** +** A busy handler must not close the database connection +** or [prepared statement] that invoked the busy handler. +*/ +SQLITE_API int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*); + +/* +** CAPI3REF: Set A Busy Timeout +** +** ^This routine sets a [sqlite3_busy_handler | busy handler] that sleeps +** for a specified amount of time when a table is locked. ^The handler +** will sleep multiple times until at least "ms" milliseconds of sleeping +** have accumulated. ^After at least "ms" milliseconds of sleeping, +** the handler returns 0 which causes [sqlite3_step()] to return +** [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED]. +** +** ^Calling this routine with an argument less than or equal to zero +** turns off all busy handlers. +** +** ^(There can only be a single busy handler for a particular +** [database connection] any any given moment. If another busy handler +** was defined (using [sqlite3_busy_handler()]) prior to calling +** this routine, that other busy handler is cleared.)^ +*/ +SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms); + +/* +** CAPI3REF: Convenience Routines For Running Queries +** +** This is a legacy interface that is preserved for backwards compatibility. +** Use of this interface is not recommended. +** +** Definition: A result table is memory data structure created by the +** [sqlite3_get_table()] interface. A result table records the +** complete query results from one or more queries. +** +** The table conceptually has a number of rows and columns. But +** these numbers are not part of the result table itself. These +** numbers are obtained separately. Let N be the number of rows +** and M be the number of columns. +** +** A result table is an array of pointers to zero-terminated UTF-8 strings. +** There are (N+1)*M elements in the array. The first M pointers point +** to zero-terminated strings that contain the names of the columns. +** The remaining entries all point to query results. NULL values result +** in NULL pointers. All other values are in their UTF-8 zero-terminated +** string representation as returned by [sqlite3_column_text()]. +** +** A result table might consist of one or more memory allocations. +** It is not safe to pass a result table directly to [sqlite3_free()]. +** A result table should be deallocated using [sqlite3_free_table()]. +** +** ^(As an example of the result table format, suppose a query result +** is as follows: +** +**
    +**        Name        | Age
    +**        -----------------------
    +**        Alice       | 43
    +**        Bob         | 28
    +**        Cindy       | 21
    +** 
    +** +** There are two column (M==2) and three rows (N==3). Thus the +** result table has 8 entries. Suppose the result table is stored +** in an array names azResult. Then azResult holds this content: +** +**
    +**        azResult[0] = "Name";
    +**        azResult[1] = "Age";
    +**        azResult[2] = "Alice";
    +**        azResult[3] = "43";
    +**        azResult[4] = "Bob";
    +**        azResult[5] = "28";
    +**        azResult[6] = "Cindy";
    +**        azResult[7] = "21";
    +** 
    )^ +** +** ^The sqlite3_get_table() function evaluates one or more +** semicolon-separated SQL statements in the zero-terminated UTF-8 +** string of its 2nd parameter and returns a result table to the +** pointer given in its 3rd parameter. +** +** After the application has finished with the result from sqlite3_get_table(), +** it must pass the result table pointer to sqlite3_free_table() in order to +** release the memory that was malloced. Because of the way the +** [sqlite3_malloc()] happens within sqlite3_get_table(), the calling +** function must not try to call [sqlite3_free()] directly. Only +** [sqlite3_free_table()] is able to release the memory properly and safely. +** +** The sqlite3_get_table() interface is implemented as a wrapper around +** [sqlite3_exec()]. The sqlite3_get_table() routine does not have access +** to any internal data structures of SQLite. It uses only the public +** interface defined here. As a consequence, errors that occur in the +** wrapper layer outside of the internal [sqlite3_exec()] call are not +** reflected in subsequent calls to [sqlite3_errcode()] or +** [sqlite3_errmsg()]. +*/ +SQLITE_API int sqlite3_get_table( + sqlite3 *db, /* An open database */ + const char *zSql, /* SQL to be evaluated */ + char ***pazResult, /* Results of the query */ + int *pnRow, /* Number of result rows written here */ + int *pnColumn, /* Number of result columns written here */ + char **pzErrmsg /* Error msg written here */ +); +SQLITE_API void sqlite3_free_table(char **result); + +/* +** CAPI3REF: Formatted String Printing Functions +** +** These routines are work-alikes of the "printf()" family of functions +** from the standard C library. +** +** ^The sqlite3_mprintf() and sqlite3_vmprintf() routines write their +** results into memory obtained from [sqlite3_malloc()]. +** The strings returned by these two routines should be +** released by [sqlite3_free()]. ^Both routines return a +** NULL pointer if [sqlite3_malloc()] is unable to allocate enough +** memory to hold the resulting string. +** +** ^(The sqlite3_snprintf() routine is similar to "snprintf()" from +** the standard C library. The result is written into the +** buffer supplied as the second parameter whose size is given by +** the first parameter. Note that the order of the +** first two parameters is reversed from snprintf().)^ This is an +** historical accident that cannot be fixed without breaking +** backwards compatibility. ^(Note also that sqlite3_snprintf() +** returns a pointer to its buffer instead of the number of +** characters actually written into the buffer.)^ We admit that +** the number of characters written would be a more useful return +** value but we cannot change the implementation of sqlite3_snprintf() +** now without breaking compatibility. +** +** ^As long as the buffer size is greater than zero, sqlite3_snprintf() +** guarantees that the buffer is always zero-terminated. ^The first +** parameter "n" is the total size of the buffer, including space for +** the zero terminator. So the longest string that can be completely +** written will be n-1 characters. +** +** ^The sqlite3_vsnprintf() routine is a varargs version of sqlite3_snprintf(). +** +** These routines all implement some additional formatting +** options that are useful for constructing SQL statements. +** All of the usual printf() formatting options apply. In addition, there +** is are "%q", "%Q", and "%z" options. +** +** ^(The %q option works like %s in that it substitutes a nul-terminated +** string from the argument list. But %q also doubles every '\'' character. +** %q is designed for use inside a string literal.)^ By doubling each '\'' +** character it escapes that character and allows it to be inserted into +** the string. +** +** For example, assume the string variable zText contains text as follows: +** +**
    +**  char *zText = "It's a happy day!";
    +** 
    +** +** One can use this text in an SQL statement as follows: +** +**
    +**  char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES('%q')", zText);
    +**  sqlite3_exec(db, zSQL, 0, 0, 0);
    +**  sqlite3_free(zSQL);
    +** 
    +** +** Because the %q format string is used, the '\'' character in zText +** is escaped and the SQL generated is as follows: +** +**
    +**  INSERT INTO table1 VALUES('It''s a happy day!')
    +** 
    +** +** This is correct. Had we used %s instead of %q, the generated SQL +** would have looked like this: +** +**
    +**  INSERT INTO table1 VALUES('It's a happy day!');
    +** 
    +** +** This second example is an SQL syntax error. As a general rule you should +** always use %q instead of %s when inserting text into a string literal. +** +** ^(The %Q option works like %q except it also adds single quotes around +** the outside of the total string. Additionally, if the parameter in the +** argument list is a NULL pointer, %Q substitutes the text "NULL" (without +** single quotes).)^ So, for example, one could say: +** +**
    +**  char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES(%Q)", zText);
    +**  sqlite3_exec(db, zSQL, 0, 0, 0);
    +**  sqlite3_free(zSQL);
    +** 
    +** +** The code above will render a correct SQL statement in the zSQL +** variable even if the zText variable is a NULL pointer. +** +** ^(The "%z" formatting option works like "%s" but with the +** addition that after the string has been read and copied into +** the result, [sqlite3_free()] is called on the input string.)^ +*/ +SQLITE_API char *sqlite3_mprintf(const char*,...); +SQLITE_API char *sqlite3_vmprintf(const char*, va_list); +SQLITE_API char *sqlite3_snprintf(int,char*,const char*, ...); +SQLITE_API char *sqlite3_vsnprintf(int,char*,const char*, va_list); + +/* +** CAPI3REF: Memory Allocation Subsystem +** +** The SQLite core uses these three routines for all of its own +** internal memory allocation needs. "Core" in the previous sentence +** does not include operating-system specific VFS implementation. The +** Windows VFS uses native malloc() and free() for some operations. +** +** ^The sqlite3_malloc() routine returns a pointer to a block +** of memory at least N bytes in length, where N is the parameter. +** ^If sqlite3_malloc() is unable to obtain sufficient free +** memory, it returns a NULL pointer. ^If the parameter N to +** sqlite3_malloc() is zero or negative then sqlite3_malloc() returns +** a NULL pointer. +** +** ^Calling sqlite3_free() with a pointer previously returned +** by sqlite3_malloc() or sqlite3_realloc() releases that memory so +** that it might be reused. ^The sqlite3_free() routine is +** a no-op if is called with a NULL pointer. Passing a NULL pointer +** to sqlite3_free() is harmless. After being freed, memory +** should neither be read nor written. Even reading previously freed +** memory might result in a segmentation fault or other severe error. +** Memory corruption, a segmentation fault, or other severe error +** might result if sqlite3_free() is called with a non-NULL pointer that +** was not obtained from sqlite3_malloc() or sqlite3_realloc(). +** +** ^(The sqlite3_realloc() interface attempts to resize a +** prior memory allocation to be at least N bytes, where N is the +** second parameter. The memory allocation to be resized is the first +** parameter.)^ ^ If the first parameter to sqlite3_realloc() +** is a NULL pointer then its behavior is identical to calling +** sqlite3_malloc(N) where N is the second parameter to sqlite3_realloc(). +** ^If the second parameter to sqlite3_realloc() is zero or +** negative then the behavior is exactly the same as calling +** sqlite3_free(P) where P is the first parameter to sqlite3_realloc(). +** ^sqlite3_realloc() returns a pointer to a memory allocation +** of at least N bytes in size or NULL if sufficient memory is unavailable. +** ^If M is the size of the prior allocation, then min(N,M) bytes +** of the prior allocation are copied into the beginning of buffer returned +** by sqlite3_realloc() and the prior allocation is freed. +** ^If sqlite3_realloc() returns NULL, then the prior allocation +** is not freed. +** +** ^The memory returned by sqlite3_malloc() and sqlite3_realloc() +** is always aligned to at least an 8 byte boundary, or to a +** 4 byte boundary if the [SQLITE_4_BYTE_ALIGNED_MALLOC] compile-time +** option is used. +** +** In SQLite version 3.5.0 and 3.5.1, it was possible to define +** the SQLITE_OMIT_MEMORY_ALLOCATION which would cause the built-in +** implementation of these routines to be omitted. That capability +** is no longer provided. Only built-in memory allocators can be used. +** +** The Windows OS interface layer calls +** the system malloc() and free() directly when converting +** filenames between the UTF-8 encoding used by SQLite +** and whatever filename encoding is used by the particular Windows +** installation. Memory allocation errors are detected, but +** they are reported back as [SQLITE_CANTOPEN] or +** [SQLITE_IOERR] rather than [SQLITE_NOMEM]. +** +** The pointer arguments to [sqlite3_free()] and [sqlite3_realloc()] +** must be either NULL or else pointers obtained from a prior +** invocation of [sqlite3_malloc()] or [sqlite3_realloc()] that have +** not yet been released. +** +** The application must not read or write any part of +** a block of memory after it has been released using +** [sqlite3_free()] or [sqlite3_realloc()]. +*/ +SQLITE_API void *sqlite3_malloc(int); +SQLITE_API void *sqlite3_realloc(void*, int); +SQLITE_API void sqlite3_free(void*); + +/* +** CAPI3REF: Memory Allocator Statistics +** +** SQLite provides these two interfaces for reporting on the status +** of the [sqlite3_malloc()], [sqlite3_free()], and [sqlite3_realloc()] +** routines, which form the built-in memory allocation subsystem. +** +** ^The [sqlite3_memory_used()] routine returns the number of bytes +** of memory currently outstanding (malloced but not freed). +** ^The [sqlite3_memory_highwater()] routine returns the maximum +** value of [sqlite3_memory_used()] since the high-water mark +** was last reset. ^The values returned by [sqlite3_memory_used()] and +** [sqlite3_memory_highwater()] include any overhead +** added by SQLite in its implementation of [sqlite3_malloc()], +** but not overhead added by the any underlying system library +** routines that [sqlite3_malloc()] may call. +** +** ^The memory high-water mark is reset to the current value of +** [sqlite3_memory_used()] if and only if the parameter to +** [sqlite3_memory_highwater()] is true. ^The value returned +** by [sqlite3_memory_highwater(1)] is the high-water mark +** prior to the reset. +*/ +SQLITE_API sqlite3_int64 sqlite3_memory_used(void); +SQLITE_API sqlite3_int64 sqlite3_memory_highwater(int resetFlag); + +/* +** CAPI3REF: Pseudo-Random Number Generator +** +** SQLite contains a high-quality pseudo-random number generator (PRNG) used to +** select random [ROWID | ROWIDs] when inserting new records into a table that +** already uses the largest possible [ROWID]. The PRNG is also used for +** the build-in random() and randomblob() SQL functions. This interface allows +** applications to access the same PRNG for other purposes. +** +** ^A call to this routine stores N bytes of randomness into buffer P. +** +** ^The first time this routine is invoked (either internally or by +** the application) the PRNG is seeded using randomness obtained +** from the xRandomness method of the default [sqlite3_vfs] object. +** ^On all subsequent invocations, the pseudo-randomness is generated +** internally and without recourse to the [sqlite3_vfs] xRandomness +** method. +*/ +SQLITE_API void sqlite3_randomness(int N, void *P); + +/* +** CAPI3REF: Compile-Time Authorization Callbacks +** +** ^This routine registers an authorizer callback with a particular +** [database connection], supplied in the first argument. +** ^The authorizer callback is invoked as SQL statements are being compiled +** by [sqlite3_prepare()] or its variants [sqlite3_prepare_v2()], +** [sqlite3_prepare16()] and [sqlite3_prepare16_v2()]. ^At various +** points during the compilation process, as logic is being created +** to perform various actions, the authorizer callback is invoked to +** see if those actions are allowed. ^The authorizer callback should +** return [SQLITE_OK] to allow the action, [SQLITE_IGNORE] to disallow the +** specific action but allow the SQL statement to continue to be +** compiled, or [SQLITE_DENY] to cause the entire SQL statement to be +** rejected with an error. ^If the authorizer callback returns +** any value other than [SQLITE_IGNORE], [SQLITE_OK], or [SQLITE_DENY] +** then the [sqlite3_prepare_v2()] or equivalent call that triggered +** the authorizer will fail with an error message. +** +** When the callback returns [SQLITE_OK], that means the operation +** requested is ok. ^When the callback returns [SQLITE_DENY], the +** [sqlite3_prepare_v2()] or equivalent call that triggered the +** authorizer will fail with an error message explaining that +** access is denied. +** +** ^The first parameter to the authorizer callback is a copy of the third +** parameter to the sqlite3_set_authorizer() interface. ^The second parameter +** to the callback is an integer [SQLITE_COPY | action code] that specifies +** the particular action to be authorized. ^The third through sixth parameters +** to the callback are zero-terminated strings that contain additional +** details about the action to be authorized. +** +** ^If the action code is [SQLITE_READ] +** and the callback returns [SQLITE_IGNORE] then the +** [prepared statement] statement is constructed to substitute +** a NULL value in place of the table column that would have +** been read if [SQLITE_OK] had been returned. The [SQLITE_IGNORE] +** return can be used to deny an untrusted user access to individual +** columns of a table. +** ^If the action code is [SQLITE_DELETE] and the callback returns +** [SQLITE_IGNORE] then the [DELETE] operation proceeds but the +** [truncate optimization] is disabled and all rows are deleted individually. +** +** An authorizer is used when [sqlite3_prepare | preparing] +** SQL statements from an untrusted source, to ensure that the SQL statements +** do not try to access data they are not allowed to see, or that they do not +** try to execute malicious statements that damage the database. For +** example, an application may allow a user to enter arbitrary +** SQL queries for evaluation by a database. But the application does +** not want the user to be able to make arbitrary changes to the +** database. An authorizer could then be put in place while the +** user-entered SQL is being [sqlite3_prepare | prepared] that +** disallows everything except [SELECT] statements. +** +** Applications that need to process SQL from untrusted sources +** might also consider lowering resource limits using [sqlite3_limit()] +** and limiting database size using the [max_page_count] [PRAGMA] +** in addition to using an authorizer. +** +** ^(Only a single authorizer can be in place on a database connection +** at a time. Each call to sqlite3_set_authorizer overrides the +** previous call.)^ ^Disable the authorizer by installing a NULL callback. +** The authorizer is disabled by default. +** +** The authorizer callback must not do anything that will modify +** the database connection that invoked the authorizer callback. +** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their +** database connections for the meaning of "modify" in this paragraph. +** +** ^When [sqlite3_prepare_v2()] is used to prepare a statement, the +** statement might be re-prepared during [sqlite3_step()] due to a +** schema change. Hence, the application should ensure that the +** correct authorizer callback remains in place during the [sqlite3_step()]. +** +** ^Note that the authorizer callback is invoked only during +** [sqlite3_prepare()] or its variants. Authorization is not +** performed during statement evaluation in [sqlite3_step()], unless +** as stated in the previous paragraph, sqlite3_step() invokes +** sqlite3_prepare_v2() to reprepare a statement after a schema change. +*/ +SQLITE_API int sqlite3_set_authorizer( + sqlite3*, + int (*xAuth)(void*,int,const char*,const char*,const char*,const char*), + void *pUserData +); + +/* +** CAPI3REF: Authorizer Return Codes +** +** The [sqlite3_set_authorizer | authorizer callback function] must +** return either [SQLITE_OK] or one of these two constants in order +** to signal SQLite whether or not the action is permitted. See the +** [sqlite3_set_authorizer | authorizer documentation] for additional +** information. +** +** Note that SQLITE_IGNORE is also used as a [SQLITE_ROLLBACK | return code] +** from the [sqlite3_vtab_on_conflict()] interface. +*/ +#define SQLITE_DENY 1 /* Abort the SQL statement with an error */ +#define SQLITE_IGNORE 2 /* Don't allow access, but don't generate an error */ + +/* +** CAPI3REF: Authorizer Action Codes +** +** The [sqlite3_set_authorizer()] interface registers a callback function +** that is invoked to authorize certain SQL statement actions. The +** second parameter to the callback is an integer code that specifies +** what action is being authorized. These are the integer action codes that +** the authorizer callback may be passed. +** +** These action code values signify what kind of operation is to be +** authorized. The 3rd and 4th parameters to the authorization +** callback function will be parameters or NULL depending on which of these +** codes is used as the second parameter. ^(The 5th parameter to the +** authorizer callback is the name of the database ("main", "temp", +** etc.) if applicable.)^ ^The 6th parameter to the authorizer callback +** is the name of the inner-most trigger or view that is responsible for +** the access attempt or NULL if this access attempt is directly from +** top-level SQL code. +*/ +/******************************************* 3rd ************ 4th ***********/ +#define SQLITE_CREATE_INDEX 1 /* Index Name Table Name */ +#define SQLITE_CREATE_TABLE 2 /* Table Name NULL */ +#define SQLITE_CREATE_TEMP_INDEX 3 /* Index Name Table Name */ +#define SQLITE_CREATE_TEMP_TABLE 4 /* Table Name NULL */ +#define SQLITE_CREATE_TEMP_TRIGGER 5 /* Trigger Name Table Name */ +#define SQLITE_CREATE_TEMP_VIEW 6 /* View Name NULL */ +#define SQLITE_CREATE_TRIGGER 7 /* Trigger Name Table Name */ +#define SQLITE_CREATE_VIEW 8 /* View Name NULL */ +#define SQLITE_DELETE 9 /* Table Name NULL */ +#define SQLITE_DROP_INDEX 10 /* Index Name Table Name */ +#define SQLITE_DROP_TABLE 11 /* Table Name NULL */ +#define SQLITE_DROP_TEMP_INDEX 12 /* Index Name Table Name */ +#define SQLITE_DROP_TEMP_TABLE 13 /* Table Name NULL */ +#define SQLITE_DROP_TEMP_TRIGGER 14 /* Trigger Name Table Name */ +#define SQLITE_DROP_TEMP_VIEW 15 /* View Name NULL */ +#define SQLITE_DROP_TRIGGER 16 /* Trigger Name Table Name */ +#define SQLITE_DROP_VIEW 17 /* View Name NULL */ +#define SQLITE_INSERT 18 /* Table Name NULL */ +#define SQLITE_PRAGMA 19 /* Pragma Name 1st arg or NULL */ +#define SQLITE_READ 20 /* Table Name Column Name */ +#define SQLITE_SELECT 21 /* NULL NULL */ +#define SQLITE_TRANSACTION 22 /* Operation NULL */ +#define SQLITE_UPDATE 23 /* Table Name Column Name */ +#define SQLITE_ATTACH 24 /* Filename NULL */ +#define SQLITE_DETACH 25 /* Database Name NULL */ +#define SQLITE_ALTER_TABLE 26 /* Database Name Table Name */ +#define SQLITE_REINDEX 27 /* Index Name NULL */ +#define SQLITE_ANALYZE 28 /* Table Name NULL */ +#define SQLITE_CREATE_VTABLE 29 /* Table Name Module Name */ +#define SQLITE_DROP_VTABLE 30 /* Table Name Module Name */ +#define SQLITE_FUNCTION 31 /* NULL Function Name */ +#define SQLITE_SAVEPOINT 32 /* Operation Savepoint Name */ +#define SQLITE_COPY 0 /* No longer used */ + +/* +** CAPI3REF: Tracing And Profiling Functions +** +** These routines register callback functions that can be used for +** tracing and profiling the execution of SQL statements. +** +** ^The callback function registered by sqlite3_trace() is invoked at +** various times when an SQL statement is being run by [sqlite3_step()]. +** ^The sqlite3_trace() callback is invoked with a UTF-8 rendering of the +** SQL statement text as the statement first begins executing. +** ^(Additional sqlite3_trace() callbacks might occur +** as each triggered subprogram is entered. The callbacks for triggers +** contain a UTF-8 SQL comment that identifies the trigger.)^ +** +** ^The callback function registered by sqlite3_profile() is invoked +** as each SQL statement finishes. ^The profile callback contains +** the original statement text and an estimate of wall-clock time +** of how long that statement took to run. ^The profile callback +** time is in units of nanoseconds, however the current implementation +** is only capable of millisecond resolution so the six least significant +** digits in the time are meaningless. Future versions of SQLite +** might provide greater resolution on the profiler callback. The +** sqlite3_profile() function is considered experimental and is +** subject to change in future versions of SQLite. +*/ +SQLITE_API void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*); +SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_profile(sqlite3*, + void(*xProfile)(void*,const char*,sqlite3_uint64), void*); + +/* +** CAPI3REF: Query Progress Callbacks +** +** ^The sqlite3_progress_handler(D,N,X,P) interface causes the callback +** function X to be invoked periodically during long running calls to +** [sqlite3_exec()], [sqlite3_step()] and [sqlite3_get_table()] for +** database connection D. An example use for this +** interface is to keep a GUI updated during a large query. +** +** ^The parameter P is passed through as the only parameter to the +** callback function X. ^The parameter N is the number of +** [virtual machine instructions] that are evaluated between successive +** invocations of the callback X. +** +** ^Only a single progress handler may be defined at one time per +** [database connection]; setting a new progress handler cancels the +** old one. ^Setting parameter X to NULL disables the progress handler. +** ^The progress handler is also disabled by setting N to a value less +** than 1. +** +** ^If the progress callback returns non-zero, the operation is +** interrupted. This feature can be used to implement a +** "Cancel" button on a GUI progress dialog box. +** +** The progress handler callback must not do anything that will modify +** the database connection that invoked the progress handler. +** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their +** database connections for the meaning of "modify" in this paragraph. +** +*/ +SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); + +/* +** CAPI3REF: Opening A New Database Connection +** +** ^These routines open an SQLite database file as specified by the +** filename argument. ^The filename argument is interpreted as UTF-8 for +** sqlite3_open() and sqlite3_open_v2() and as UTF-16 in the native byte +** order for sqlite3_open16(). ^(A [database connection] handle is usually +** returned in *ppDb, even if an error occurs. The only exception is that +** if SQLite is unable to allocate memory to hold the [sqlite3] object, +** a NULL will be written into *ppDb instead of a pointer to the [sqlite3] +** object.)^ ^(If the database is opened (and/or created) successfully, then +** [SQLITE_OK] is returned. Otherwise an [error code] is returned.)^ ^The +** [sqlite3_errmsg()] or [sqlite3_errmsg16()] routines can be used to obtain +** an English language description of the error following a failure of any +** of the sqlite3_open() routines. +** +** ^The default encoding for the database will be UTF-8 if +** sqlite3_open() or sqlite3_open_v2() is called and +** UTF-16 in the native byte order if sqlite3_open16() is used. +** +** Whether or not an error occurs when it is opened, resources +** associated with the [database connection] handle should be released by +** passing it to [sqlite3_close()] when it is no longer required. +** +** The sqlite3_open_v2() interface works like sqlite3_open() +** except that it accepts two additional parameters for additional control +** over the new database connection. ^(The flags parameter to +** sqlite3_open_v2() can take one of +** the following three values, optionally combined with the +** [SQLITE_OPEN_NOMUTEX], [SQLITE_OPEN_FULLMUTEX], [SQLITE_OPEN_SHAREDCACHE], +** [SQLITE_OPEN_PRIVATECACHE], and/or [SQLITE_OPEN_URI] flags:)^ +** +**
    +** ^(
    [SQLITE_OPEN_READONLY]
    +**
    The database is opened in read-only mode. If the database does not +** already exist, an error is returned.
    )^ +** +** ^(
    [SQLITE_OPEN_READWRITE]
    +**
    The database is opened for reading and writing if possible, or reading +** only if the file is write protected by the operating system. In either +** case the database must already exist, otherwise an error is returned.
    )^ +** +** ^(
    [SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE]
    +**
    The database is opened for reading and writing, and is created if +** it does not already exist. This is the behavior that is always used for +** sqlite3_open() and sqlite3_open16().
    )^ +**
    +** +** If the 3rd parameter to sqlite3_open_v2() is not one of the +** combinations shown above optionally combined with other +** [SQLITE_OPEN_READONLY | SQLITE_OPEN_* bits] +** then the behavior is undefined. +** +** ^If the [SQLITE_OPEN_NOMUTEX] flag is set, then the database connection +** opens in the multi-thread [threading mode] as long as the single-thread +** mode has not been set at compile-time or start-time. ^If the +** [SQLITE_OPEN_FULLMUTEX] flag is set then the database connection opens +** in the serialized [threading mode] unless single-thread was +** previously selected at compile-time or start-time. +** ^The [SQLITE_OPEN_SHAREDCACHE] flag causes the database connection to be +** eligible to use [shared cache mode], regardless of whether or not shared +** cache is enabled using [sqlite3_enable_shared_cache()]. ^The +** [SQLITE_OPEN_PRIVATECACHE] flag causes the database connection to not +** participate in [shared cache mode] even if it is enabled. +** +** ^The fourth parameter to sqlite3_open_v2() is the name of the +** [sqlite3_vfs] object that defines the operating system interface that +** the new database connection should use. ^If the fourth parameter is +** a NULL pointer then the default [sqlite3_vfs] object is used. +** +** ^If the filename is ":memory:", then a private, temporary in-memory database +** is created for the connection. ^This in-memory database will vanish when +** the database connection is closed. Future versions of SQLite might +** make use of additional special filenames that begin with the ":" character. +** It is recommended that when a database filename actually does begin with +** a ":" character you should prefix the filename with a pathname such as +** "./" to avoid ambiguity. +** +** ^If the filename is an empty string, then a private, temporary +** on-disk database will be created. ^This private database will be +** automatically deleted as soon as the database connection is closed. +** +** [[URI filenames in sqlite3_open()]]

    URI Filenames

    +** +** ^If [URI filename] interpretation is enabled, and the filename argument +** begins with "file:", then the filename is interpreted as a URI. ^URI +** filename interpretation is enabled if the [SQLITE_OPEN_URI] flag is +** set in the fourth argument to sqlite3_open_v2(), or if it has +** been enabled globally using the [SQLITE_CONFIG_URI] option with the +** [sqlite3_config()] method or by the [SQLITE_USE_URI] compile-time option. +** As of SQLite version 3.7.7, URI filename interpretation is turned off +** by default, but future releases of SQLite might enable URI filename +** interpretation by default. See "[URI filenames]" for additional +** information. +** +** URI filenames are parsed according to RFC 3986. ^If the URI contains an +** authority, then it must be either an empty string or the string +** "localhost". ^If the authority is not an empty string or "localhost", an +** error is returned to the caller. ^The fragment component of a URI, if +** present, is ignored. +** +** ^SQLite uses the path component of the URI as the name of the disk file +** which contains the database. ^If the path begins with a '/' character, +** then it is interpreted as an absolute path. ^If the path does not begin +** with a '/' (meaning that the authority section is omitted from the URI) +** then the path is interpreted as a relative path. +** ^On windows, the first component of an absolute path +** is a drive specification (e.g. "C:"). +** +** [[core URI query parameters]] +** The query component of a URI may contain parameters that are interpreted +** either by SQLite itself, or by a [VFS | custom VFS implementation]. +** SQLite interprets the following three query parameters: +** +**
      +**
    • vfs: ^The "vfs" parameter may be used to specify the name of +** a VFS object that provides the operating system interface that should +** be used to access the database file on disk. ^If this option is set to +** an empty string the default VFS object is used. ^Specifying an unknown +** VFS is an error. ^If sqlite3_open_v2() is used and the vfs option is +** present, then the VFS specified by the option takes precedence over +** the value passed as the fourth parameter to sqlite3_open_v2(). +** +**
    • mode: ^(The mode parameter may be set to either "ro", "rw" or +** "rwc". Attempting to set it to any other value is an error)^. +** ^If "ro" is specified, then the database is opened for read-only +** access, just as if the [SQLITE_OPEN_READONLY] flag had been set in the +** third argument to sqlite3_prepare_v2(). ^If the mode option is set to +** "rw", then the database is opened for read-write (but not create) +** access, as if SQLITE_OPEN_READWRITE (but not SQLITE_OPEN_CREATE) had +** been set. ^Value "rwc" is equivalent to setting both +** SQLITE_OPEN_READWRITE and SQLITE_OPEN_CREATE. ^If sqlite3_open_v2() is +** used, it is an error to specify a value for the mode parameter that is +** less restrictive than that specified by the flags passed as the third +** parameter. +** +**
    • cache: ^The cache parameter may be set to either "shared" or +** "private". ^Setting it to "shared" is equivalent to setting the +** SQLITE_OPEN_SHAREDCACHE bit in the flags argument passed to +** sqlite3_open_v2(). ^Setting the cache parameter to "private" is +** equivalent to setting the SQLITE_OPEN_PRIVATECACHE bit. +** ^If sqlite3_open_v2() is used and the "cache" parameter is present in +** a URI filename, its value overrides any behaviour requested by setting +** SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag. +**
    +** +** ^Specifying an unknown parameter in the query component of a URI is not an +** error. Future versions of SQLite might understand additional query +** parameters. See "[query parameters with special meaning to SQLite]" for +** additional information. +** +** [[URI filename examples]]

    URI filename examples

    +** +**
    +**
    URI filenames Results +**
    file:data.db +** Open the file "data.db" in the current directory. +**
    file:/home/fred/data.db
    +** file:///home/fred/data.db
    +** file://localhost/home/fred/data.db
    +** Open the database file "/home/fred/data.db". +**
    file://darkstar/home/fred/data.db +** An error. "darkstar" is not a recognized authority. +**
    +** file:///C:/Documents%20and%20Settings/fred/Desktop/data.db +** Windows only: Open the file "data.db" on fred's desktop on drive +** C:. Note that the %20 escaping in this example is not strictly +** necessary - space characters can be used literally +** in URI filenames. +**
    file:data.db?mode=ro&cache=private +** Open file "data.db" in the current directory for read-only access. +** Regardless of whether or not shared-cache mode is enabled by +** default, use a private cache. +**
    file:/home/fred/data.db?vfs=unix-nolock +** Open file "/home/fred/data.db". Use the special VFS "unix-nolock". +**
    file:data.db?mode=readonly +** An error. "readonly" is not a valid option for the "mode" parameter. +**
    +** +** ^URI hexadecimal escape sequences (%HH) are supported within the path and +** query components of a URI. A hexadecimal escape sequence consists of a +** percent sign - "%" - followed by exactly two hexadecimal digits +** specifying an octet value. ^Before the path or query components of a +** URI filename are interpreted, they are encoded using UTF-8 and all +** hexadecimal escape sequences replaced by a single byte containing the +** corresponding octet. If this process generates an invalid UTF-8 encoding, +** the results are undefined. +** +** Note to Windows users: The encoding used for the filename argument +** of sqlite3_open() and sqlite3_open_v2() must be UTF-8, not whatever +** codepage is currently defined. Filenames containing international +** characters must be converted to UTF-8 prior to passing them into +** sqlite3_open() or sqlite3_open_v2(). +*/ +SQLITE_API int sqlite3_open( + const char *filename, /* Database filename (UTF-8) */ + sqlite3 **ppDb /* OUT: SQLite db handle */ +); +SQLITE_API int sqlite3_open16( + const void *filename, /* Database filename (UTF-16) */ + sqlite3 **ppDb /* OUT: SQLite db handle */ +); +SQLITE_API int sqlite3_open_v2( + const char *filename, /* Database filename (UTF-8) */ + sqlite3 **ppDb, /* OUT: SQLite db handle */ + int flags, /* Flags */ + const char *zVfs /* Name of VFS module to use */ +); + +/* +** CAPI3REF: Obtain Values For URI Parameters +** +** These are utility routines, useful to VFS implementations, that check +** to see if a database file was a URI that contained a specific query +** parameter, and if so obtains the value of that query parameter. +** +** If F is the database filename pointer passed into the xOpen() method of +** a VFS implementation when the flags parameter to xOpen() has one or +** more of the [SQLITE_OPEN_URI] or [SQLITE_OPEN_MAIN_DB] bits set and +** P is the name of the query parameter, then +** sqlite3_uri_parameter(F,P) returns the value of the P +** parameter if it exists or a NULL pointer if P does not appear as a +** query parameter on F. If P is a query parameter of F +** has no explicit value, then sqlite3_uri_parameter(F,P) returns +** a pointer to an empty string. +** +** The sqlite3_uri_boolean(F,P,B) routine assumes that P is a boolean +** parameter and returns true (1) or false (0) according to the value +** of P. The value of P is true if it is "yes" or "true" or "on" or +** a non-zero number and is false otherwise. If P is not a query parameter +** on F then sqlite3_uri_boolean(F,P,B) returns (B!=0). +** +** The sqlite3_uri_int64(F,P,D) routine converts the value of P into a +** 64-bit signed integer and returns that integer, or D if P does not +** exist. If the value of P is something other than an integer, then +** zero is returned. +** +** If F is a NULL pointer, then sqlite3_uri_parameter(F,P) returns NULL and +** sqlite3_uri_boolean(F,P,B) returns B. If F is not a NULL pointer and +** is not a database file pathname pointer that SQLite passed into the xOpen +** VFS method, then the behavior of this routine is undefined and probably +** undesirable. +*/ +SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam); +SQLITE_API int sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault); +SQLITE_API sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int64); + + +/* +** CAPI3REF: Error Codes And Messages +** +** ^The sqlite3_errcode() interface returns the numeric [result code] or +** [extended result code] for the most recent failed sqlite3_* API call +** associated with a [database connection]. If a prior API call failed +** but the most recent API call succeeded, the return value from +** sqlite3_errcode() is undefined. ^The sqlite3_extended_errcode() +** interface is the same except that it always returns the +** [extended result code] even when extended result codes are +** disabled. +** +** ^The sqlite3_errmsg() and sqlite3_errmsg16() return English-language +** text that describes the error, as either UTF-8 or UTF-16 respectively. +** ^(Memory to hold the error message string is managed internally. +** The application does not need to worry about freeing the result. +** However, the error string might be overwritten or deallocated by +** subsequent calls to other SQLite interface functions.)^ +** +** When the serialized [threading mode] is in use, it might be the +** case that a second error occurs on a separate thread in between +** the time of the first error and the call to these interfaces. +** When that happens, the second error will be reported since these +** interfaces always report the most recent result. To avoid +** this, each thread can obtain exclusive use of the [database connection] D +** by invoking [sqlite3_mutex_enter]([sqlite3_db_mutex](D)) before beginning +** to use D and invoking [sqlite3_mutex_leave]([sqlite3_db_mutex](D)) after +** all calls to the interfaces listed here are completed. +** +** If an interface fails with SQLITE_MISUSE, that means the interface +** was invoked incorrectly by the application. In that case, the +** error code and message may or may not be set. +*/ +SQLITE_API int sqlite3_errcode(sqlite3 *db); +SQLITE_API int sqlite3_extended_errcode(sqlite3 *db); +SQLITE_API const char *sqlite3_errmsg(sqlite3*); +SQLITE_API const void *sqlite3_errmsg16(sqlite3*); + +/* +** CAPI3REF: SQL Statement Object +** KEYWORDS: {prepared statement} {prepared statements} +** +** An instance of this object represents a single SQL statement. +** This object is variously known as a "prepared statement" or a +** "compiled SQL statement" or simply as a "statement". +** +** The life of a statement object goes something like this: +** +**

      +**
    1. Create the object using [sqlite3_prepare_v2()] or a related +** function. +**
    2. Bind values to [host parameters] using the sqlite3_bind_*() +** interfaces. +**
    3. Run the SQL by calling [sqlite3_step()] one or more times. +**
    4. Reset the statement using [sqlite3_reset()] then go back +** to step 2. Do this zero or more times. +**
    5. Destroy the object using [sqlite3_finalize()]. +**
    +** +** Refer to documentation on individual methods above for additional +** information. +*/ +typedef struct sqlite3_stmt sqlite3_stmt; + +/* +** CAPI3REF: Run-time Limits +** +** ^(This interface allows the size of various constructs to be limited +** on a connection by connection basis. The first parameter is the +** [database connection] whose limit is to be set or queried. The +** second parameter is one of the [limit categories] that define a +** class of constructs to be size limited. The third parameter is the +** new limit for that construct.)^ +** +** ^If the new limit is a negative number, the limit is unchanged. +** ^(For each limit category SQLITE_LIMIT_NAME there is a +** [limits | hard upper bound] +** set at compile-time by a C preprocessor macro called +** [limits | SQLITE_MAX_NAME]. +** (The "_LIMIT_" in the name is changed to "_MAX_".))^ +** ^Attempts to increase a limit above its hard upper bound are +** silently truncated to the hard upper bound. +** +** ^Regardless of whether or not the limit was changed, the +** [sqlite3_limit()] interface returns the prior value of the limit. +** ^Hence, to find the current value of a limit without changing it, +** simply invoke this interface with the third parameter set to -1. +** +** Run-time limits are intended for use in applications that manage +** both their own internal database and also databases that are controlled +** by untrusted external sources. An example application might be a +** web browser that has its own databases for storing history and +** separate databases controlled by JavaScript applications downloaded +** off the Internet. The internal databases can be given the +** large, default limits. Databases managed by external sources can +** be given much smaller limits designed to prevent a denial of service +** attack. Developers might also want to use the [sqlite3_set_authorizer()] +** interface to further control untrusted SQL. The size of the database +** created by an untrusted script can be contained using the +** [max_page_count] [PRAGMA]. +** +** New run-time limit categories may be added in future releases. +*/ +SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); + +/* +** CAPI3REF: Run-Time Limit Categories +** KEYWORDS: {limit category} {*limit categories} +** +** These constants define various performance limits +** that can be lowered at run-time using [sqlite3_limit()]. +** The synopsis of the meanings of the various limits is shown below. +** Additional information is available at [limits | Limits in SQLite]. +** +**
    +** [[SQLITE_LIMIT_LENGTH]] ^(
    SQLITE_LIMIT_LENGTH
    +**
    The maximum size of any string or BLOB or table row, in bytes.
    )^ +** +** [[SQLITE_LIMIT_SQL_LENGTH]] ^(
    SQLITE_LIMIT_SQL_LENGTH
    +**
    The maximum length of an SQL statement, in bytes.
    )^ +** +** [[SQLITE_LIMIT_COLUMN]] ^(
    SQLITE_LIMIT_COLUMN
    +**
    The maximum number of columns in a table definition or in the +** result set of a [SELECT] or the maximum number of columns in an index +** or in an ORDER BY or GROUP BY clause.
    )^ +** +** [[SQLITE_LIMIT_EXPR_DEPTH]] ^(
    SQLITE_LIMIT_EXPR_DEPTH
    +**
    The maximum depth of the parse tree on any expression.
    )^ +** +** [[SQLITE_LIMIT_COMPOUND_SELECT]] ^(
    SQLITE_LIMIT_COMPOUND_SELECT
    +**
    The maximum number of terms in a compound SELECT statement.
    )^ +** +** [[SQLITE_LIMIT_VDBE_OP]] ^(
    SQLITE_LIMIT_VDBE_OP
    +**
    The maximum number of instructions in a virtual machine program +** used to implement an SQL statement. This limit is not currently +** enforced, though that might be added in some future release of +** SQLite.
    )^ +** +** [[SQLITE_LIMIT_FUNCTION_ARG]] ^(
    SQLITE_LIMIT_FUNCTION_ARG
    +**
    The maximum number of arguments on a function.
    )^ +** +** [[SQLITE_LIMIT_ATTACHED]] ^(
    SQLITE_LIMIT_ATTACHED
    +**
    The maximum number of [ATTACH | attached databases].)^
    +** +** [[SQLITE_LIMIT_LIKE_PATTERN_LENGTH]] +** ^(
    SQLITE_LIMIT_LIKE_PATTERN_LENGTH
    +**
    The maximum length of the pattern argument to the [LIKE] or +** [GLOB] operators.
    )^ +** +** [[SQLITE_LIMIT_VARIABLE_NUMBER]] +** ^(
    SQLITE_LIMIT_VARIABLE_NUMBER
    +**
    The maximum index number of any [parameter] in an SQL statement.)^ +** +** [[SQLITE_LIMIT_TRIGGER_DEPTH]] ^(
    SQLITE_LIMIT_TRIGGER_DEPTH
    +**
    The maximum depth of recursion for triggers.
    )^ +**
    +*/ +#define SQLITE_LIMIT_LENGTH 0 +#define SQLITE_LIMIT_SQL_LENGTH 1 +#define SQLITE_LIMIT_COLUMN 2 +#define SQLITE_LIMIT_EXPR_DEPTH 3 +#define SQLITE_LIMIT_COMPOUND_SELECT 4 +#define SQLITE_LIMIT_VDBE_OP 5 +#define SQLITE_LIMIT_FUNCTION_ARG 6 +#define SQLITE_LIMIT_ATTACHED 7 +#define SQLITE_LIMIT_LIKE_PATTERN_LENGTH 8 +#define SQLITE_LIMIT_VARIABLE_NUMBER 9 +#define SQLITE_LIMIT_TRIGGER_DEPTH 10 + +/* +** CAPI3REF: Compiling An SQL Statement +** KEYWORDS: {SQL statement compiler} +** +** To execute an SQL query, it must first be compiled into a byte-code +** program using one of these routines. +** +** The first argument, "db", is a [database connection] obtained from a +** prior successful call to [sqlite3_open()], [sqlite3_open_v2()] or +** [sqlite3_open16()]. The database connection must not have been closed. +** +** The second argument, "zSql", is the statement to be compiled, encoded +** as either UTF-8 or UTF-16. The sqlite3_prepare() and sqlite3_prepare_v2() +** interfaces use UTF-8, and sqlite3_prepare16() and sqlite3_prepare16_v2() +** use UTF-16. +** +** ^If the nByte argument is less than zero, then zSql is read up to the +** first zero terminator. ^If nByte is non-negative, then it is the maximum +** number of bytes read from zSql. ^When nByte is non-negative, the +** zSql string ends at either the first '\000' or '\u0000' character or +** the nByte-th byte, whichever comes first. If the caller knows +** that the supplied string is nul-terminated, then there is a small +** performance advantage to be gained by passing an nByte parameter that +** is equal to the number of bytes in the input string including +** the nul-terminator bytes as this saves SQLite from having to +** make a copy of the input string. +** +** ^If pzTail is not NULL then *pzTail is made to point to the first byte +** past the end of the first SQL statement in zSql. These routines only +** compile the first statement in zSql, so *pzTail is left pointing to +** what remains uncompiled. +** +** ^*ppStmt is left pointing to a compiled [prepared statement] that can be +** executed using [sqlite3_step()]. ^If there is an error, *ppStmt is set +** to NULL. ^If the input text contains no SQL (if the input is an empty +** string or a comment) then *ppStmt is set to NULL. +** The calling procedure is responsible for deleting the compiled +** SQL statement using [sqlite3_finalize()] after it has finished with it. +** ppStmt may not be NULL. +** +** ^On success, the sqlite3_prepare() family of routines return [SQLITE_OK]; +** otherwise an [error code] is returned. +** +** The sqlite3_prepare_v2() and sqlite3_prepare16_v2() interfaces are +** recommended for all new programs. The two older interfaces are retained +** for backwards compatibility, but their use is discouraged. +** ^In the "v2" interfaces, the prepared statement +** that is returned (the [sqlite3_stmt] object) contains a copy of the +** original SQL text. This causes the [sqlite3_step()] interface to +** behave differently in three ways: +** +**
      +**
    1. +** ^If the database schema changes, instead of returning [SQLITE_SCHEMA] as it +** always used to do, [sqlite3_step()] will automatically recompile the SQL +** statement and try to run it again. +**
    2. +** +**
    3. +** ^When an error occurs, [sqlite3_step()] will return one of the detailed +** [error codes] or [extended error codes]. ^The legacy behavior was that +** [sqlite3_step()] would only return a generic [SQLITE_ERROR] result code +** and the application would have to make a second call to [sqlite3_reset()] +** in order to find the underlying cause of the problem. With the "v2" prepare +** interfaces, the underlying reason for the error is returned immediately. +**
    4. +** +**
    5. +** ^If the specific value bound to [parameter | host parameter] in the +** WHERE clause might influence the choice of query plan for a statement, +** then the statement will be automatically recompiled, as if there had been +** a schema change, on the first [sqlite3_step()] call following any change +** to the [sqlite3_bind_text | bindings] of that [parameter]. +** ^The specific value of WHERE-clause [parameter] might influence the +** choice of query plan if the parameter is the left-hand side of a [LIKE] +** or [GLOB] operator or if the parameter is compared to an indexed column +** and the [SQLITE_ENABLE_STAT3] compile-time option is enabled. +** the +**
    6. +**
    +*/ +SQLITE_API int sqlite3_prepare( + sqlite3 *db, /* Database handle */ + const char *zSql, /* SQL statement, UTF-8 encoded */ + int nByte, /* Maximum length of zSql in bytes. */ + sqlite3_stmt **ppStmt, /* OUT: Statement handle */ + const char **pzTail /* OUT: Pointer to unused portion of zSql */ +); +SQLITE_API int sqlite3_prepare_v2( + sqlite3 *db, /* Database handle */ + const char *zSql, /* SQL statement, UTF-8 encoded */ + int nByte, /* Maximum length of zSql in bytes. */ + sqlite3_stmt **ppStmt, /* OUT: Statement handle */ + const char **pzTail /* OUT: Pointer to unused portion of zSql */ +); +SQLITE_API int sqlite3_prepare16( + sqlite3 *db, /* Database handle */ + const void *zSql, /* SQL statement, UTF-16 encoded */ + int nByte, /* Maximum length of zSql in bytes. */ + sqlite3_stmt **ppStmt, /* OUT: Statement handle */ + const void **pzTail /* OUT: Pointer to unused portion of zSql */ +); +SQLITE_API int sqlite3_prepare16_v2( + sqlite3 *db, /* Database handle */ + const void *zSql, /* SQL statement, UTF-16 encoded */ + int nByte, /* Maximum length of zSql in bytes. */ + sqlite3_stmt **ppStmt, /* OUT: Statement handle */ + const void **pzTail /* OUT: Pointer to unused portion of zSql */ +); + +/* +** CAPI3REF: Retrieving Statement SQL +** +** ^This interface can be used to retrieve a saved copy of the original +** SQL text used to create a [prepared statement] if that statement was +** compiled using either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()]. +*/ +SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt); + +/* +** CAPI3REF: Determine If An SQL Statement Writes The Database +** +** ^The sqlite3_stmt_readonly(X) interface returns true (non-zero) if +** and only if the [prepared statement] X makes no direct changes to +** the content of the database file. +** +** Note that [application-defined SQL functions] or +** [virtual tables] might change the database indirectly as a side effect. +** ^(For example, if an application defines a function "eval()" that +** calls [sqlite3_exec()], then the following SQL statement would +** change the database file through side-effects: +** +**
    +**    SELECT eval('DELETE FROM t1') FROM t2;
    +** 
    +** +** But because the [SELECT] statement does not change the database file +** directly, sqlite3_stmt_readonly() would still return true.)^ +** +** ^Transaction control statements such as [BEGIN], [COMMIT], [ROLLBACK], +** [SAVEPOINT], and [RELEASE] cause sqlite3_stmt_readonly() to return true, +** since the statements themselves do not actually modify the database but +** rather they control the timing of when other statements modify the +** database. ^The [ATTACH] and [DETACH] statements also cause +** sqlite3_stmt_readonly() to return true since, while those statements +** change the configuration of a database connection, they do not make +** changes to the content of the database files on disk. +*/ +SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt); + +/* +** CAPI3REF: Determine If A Prepared Statement Has Been Reset +** +** ^The sqlite3_stmt_busy(S) interface returns true (non-zero) if the +** [prepared statement] S has been stepped at least once using +** [sqlite3_step(S)] but has not run to completion and/or has not +** been reset using [sqlite3_reset(S)]. ^The sqlite3_stmt_busy(S) +** interface returns false if S is a NULL pointer. If S is not a +** NULL pointer and is not a pointer to a valid [prepared statement] +** object, then the behavior is undefined and probably undesirable. +** +** This interface can be used in combination [sqlite3_next_stmt()] +** to locate all prepared statements associated with a database +** connection that are in need of being reset. This can be used, +** for example, in diagnostic routines to search for prepared +** statements that are holding a transaction open. +*/ +SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt*); + +/* +** CAPI3REF: Dynamically Typed Value Object +** KEYWORDS: {protected sqlite3_value} {unprotected sqlite3_value} +** +** SQLite uses the sqlite3_value object to represent all values +** that can be stored in a database table. SQLite uses dynamic typing +** for the values it stores. ^Values stored in sqlite3_value objects +** can be integers, floating point values, strings, BLOBs, or NULL. +** +** An sqlite3_value object may be either "protected" or "unprotected". +** Some interfaces require a protected sqlite3_value. Other interfaces +** will accept either a protected or an unprotected sqlite3_value. +** Every interface that accepts sqlite3_value arguments specifies +** whether or not it requires a protected sqlite3_value. +** +** The terms "protected" and "unprotected" refer to whether or not +** a mutex is held. An internal mutex is held for a protected +** sqlite3_value object but no mutex is held for an unprotected +** sqlite3_value object. If SQLite is compiled to be single-threaded +** (with [SQLITE_THREADSAFE=0] and with [sqlite3_threadsafe()] returning 0) +** or if SQLite is run in one of reduced mutex modes +** [SQLITE_CONFIG_SINGLETHREAD] or [SQLITE_CONFIG_MULTITHREAD] +** then there is no distinction between protected and unprotected +** sqlite3_value objects and they can be used interchangeably. However, +** for maximum code portability it is recommended that applications +** still make the distinction between protected and unprotected +** sqlite3_value objects even when not strictly required. +** +** ^The sqlite3_value objects that are passed as parameters into the +** implementation of [application-defined SQL functions] are protected. +** ^The sqlite3_value object returned by +** [sqlite3_column_value()] is unprotected. +** Unprotected sqlite3_value objects may only be used with +** [sqlite3_result_value()] and [sqlite3_bind_value()]. +** The [sqlite3_value_blob | sqlite3_value_type()] family of +** interfaces require protected sqlite3_value objects. +*/ +typedef struct Mem sqlite3_value; + +/* +** CAPI3REF: SQL Function Context Object +** +** The context in which an SQL function executes is stored in an +** sqlite3_context object. ^A pointer to an sqlite3_context object +** is always first parameter to [application-defined SQL functions]. +** The application-defined SQL function implementation will pass this +** pointer through into calls to [sqlite3_result_int | sqlite3_result()], +** [sqlite3_aggregate_context()], [sqlite3_user_data()], +** [sqlite3_context_db_handle()], [sqlite3_get_auxdata()], +** and/or [sqlite3_set_auxdata()]. +*/ +typedef struct sqlite3_context sqlite3_context; + +/* +** CAPI3REF: Binding Values To Prepared Statements +** KEYWORDS: {host parameter} {host parameters} {host parameter name} +** KEYWORDS: {SQL parameter} {SQL parameters} {parameter binding} +** +** ^(In the SQL statement text input to [sqlite3_prepare_v2()] and its variants, +** literals may be replaced by a [parameter] that matches one of following +** templates: +** +**
      +**
    • ? +**
    • ?NNN +**
    • :VVV +**
    • @VVV +**
    • $VVV +**
    +** +** In the templates above, NNN represents an integer literal, +** and VVV represents an alphanumeric identifier.)^ ^The values of these +** parameters (also called "host parameter names" or "SQL parameters") +** can be set using the sqlite3_bind_*() routines defined here. +** +** ^The first argument to the sqlite3_bind_*() routines is always +** a pointer to the [sqlite3_stmt] object returned from +** [sqlite3_prepare_v2()] or its variants. +** +** ^The second argument is the index of the SQL parameter to be set. +** ^The leftmost SQL parameter has an index of 1. ^When the same named +** SQL parameter is used more than once, second and subsequent +** occurrences have the same index as the first occurrence. +** ^The index for named parameters can be looked up using the +** [sqlite3_bind_parameter_index()] API if desired. ^The index +** for "?NNN" parameters is the value of NNN. +** ^The NNN value must be between 1 and the [sqlite3_limit()] +** parameter [SQLITE_LIMIT_VARIABLE_NUMBER] (default value: 999). +** +** ^The third argument is the value to bind to the parameter. +** +** ^(In those routines that have a fourth argument, its value is the +** number of bytes in the parameter. To be clear: the value is the +** number of bytes in the value, not the number of characters.)^ +** ^If the fourth parameter is negative, the length of the string is +** the number of bytes up to the first zero terminator. +** If a non-negative fourth parameter is provided to sqlite3_bind_text() +** or sqlite3_bind_text16() then that parameter must be the byte offset +** where the NUL terminator would occur assuming the string were NUL +** terminated. If any NUL characters occur at byte offsets less than +** the value of the fourth parameter then the resulting string value will +** contain embedded NULs. The result of expressions involving strings +** with embedded NULs is undefined. +** +** ^The fifth argument to sqlite3_bind_blob(), sqlite3_bind_text(), and +** sqlite3_bind_text16() is a destructor used to dispose of the BLOB or +** string after SQLite has finished with it. ^The destructor is called +** to dispose of the BLOB or string even if the call to sqlite3_bind_blob(), +** sqlite3_bind_text(), or sqlite3_bind_text16() fails. +** ^If the fifth argument is +** the special value [SQLITE_STATIC], then SQLite assumes that the +** information is in static, unmanaged space and does not need to be freed. +** ^If the fifth argument has the value [SQLITE_TRANSIENT], then +** SQLite makes its own private copy of the data immediately, before +** the sqlite3_bind_*() routine returns. +** +** ^The sqlite3_bind_zeroblob() routine binds a BLOB of length N that +** is filled with zeroes. ^A zeroblob uses a fixed amount of memory +** (just an integer to hold its size) while it is being processed. +** Zeroblobs are intended to serve as placeholders for BLOBs whose +** content is later written using +** [sqlite3_blob_open | incremental BLOB I/O] routines. +** ^A negative value for the zeroblob results in a zero-length BLOB. +** +** ^If any of the sqlite3_bind_*() routines are called with a NULL pointer +** for the [prepared statement] or with a prepared statement for which +** [sqlite3_step()] has been called more recently than [sqlite3_reset()], +** then the call will return [SQLITE_MISUSE]. If any sqlite3_bind_() +** routine is passed a [prepared statement] that has been finalized, the +** result is undefined and probably harmful. +** +** ^Bindings are not cleared by the [sqlite3_reset()] routine. +** ^Unbound parameters are interpreted as NULL. +** +** ^The sqlite3_bind_* routines return [SQLITE_OK] on success or an +** [error code] if anything goes wrong. +** ^[SQLITE_RANGE] is returned if the parameter +** index is out of range. ^[SQLITE_NOMEM] is returned if malloc() fails. +** +** See also: [sqlite3_bind_parameter_count()], +** [sqlite3_bind_parameter_name()], and [sqlite3_bind_parameter_index()]. +*/ +SQLITE_API int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*)); +SQLITE_API int sqlite3_bind_double(sqlite3_stmt*, int, double); +SQLITE_API int sqlite3_bind_int(sqlite3_stmt*, int, int); +SQLITE_API int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64); +SQLITE_API int sqlite3_bind_null(sqlite3_stmt*, int); +SQLITE_API int sqlite3_bind_text(sqlite3_stmt*, int, const char*, int n, void(*)(void*)); +SQLITE_API int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*)); +SQLITE_API int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*); +SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n); + +/* +** CAPI3REF: Number Of SQL Parameters +** +** ^This routine can be used to find the number of [SQL parameters] +** in a [prepared statement]. SQL parameters are tokens of the +** form "?", "?NNN", ":AAA", "$AAA", or "@AAA" that serve as +** placeholders for values that are [sqlite3_bind_blob | bound] +** to the parameters at a later time. +** +** ^(This routine actually returns the index of the largest (rightmost) +** parameter. For all forms except ?NNN, this will correspond to the +** number of unique parameters. If parameters of the ?NNN form are used, +** there may be gaps in the list.)^ +** +** See also: [sqlite3_bind_blob|sqlite3_bind()], +** [sqlite3_bind_parameter_name()], and +** [sqlite3_bind_parameter_index()]. +*/ +SQLITE_API int sqlite3_bind_parameter_count(sqlite3_stmt*); + +/* +** CAPI3REF: Name Of A Host Parameter +** +** ^The sqlite3_bind_parameter_name(P,N) interface returns +** the name of the N-th [SQL parameter] in the [prepared statement] P. +** ^(SQL parameters of the form "?NNN" or ":AAA" or "@AAA" or "$AAA" +** have a name which is the string "?NNN" or ":AAA" or "@AAA" or "$AAA" +** respectively. +** In other words, the initial ":" or "$" or "@" or "?" +** is included as part of the name.)^ +** ^Parameters of the form "?" without a following integer have no name +** and are referred to as "nameless" or "anonymous parameters". +** +** ^The first host parameter has an index of 1, not 0. +** +** ^If the value N is out of range or if the N-th parameter is +** nameless, then NULL is returned. ^The returned string is +** always in UTF-8 encoding even if the named parameter was +** originally specified as UTF-16 in [sqlite3_prepare16()] or +** [sqlite3_prepare16_v2()]. +** +** See also: [sqlite3_bind_blob|sqlite3_bind()], +** [sqlite3_bind_parameter_count()], and +** [sqlite3_bind_parameter_index()]. +*/ +SQLITE_API const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int); + +/* +** CAPI3REF: Index Of A Parameter With A Given Name +** +** ^Return the index of an SQL parameter given its name. ^The +** index value returned is suitable for use as the second +** parameter to [sqlite3_bind_blob|sqlite3_bind()]. ^A zero +** is returned if no matching parameter is found. ^The parameter +** name must be given in UTF-8 even if the original statement +** was prepared from UTF-16 text using [sqlite3_prepare16_v2()]. +** +** See also: [sqlite3_bind_blob|sqlite3_bind()], +** [sqlite3_bind_parameter_count()], and +** [sqlite3_bind_parameter_index()]. +*/ +SQLITE_API int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName); + +/* +** CAPI3REF: Reset All Bindings On A Prepared Statement +** +** ^Contrary to the intuition of many, [sqlite3_reset()] does not reset +** the [sqlite3_bind_blob | bindings] on a [prepared statement]. +** ^Use this routine to reset all host parameters to NULL. +*/ +SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt*); + +/* +** CAPI3REF: Number Of Columns In A Result Set +** +** ^Return the number of columns in the result set returned by the +** [prepared statement]. ^This routine returns 0 if pStmt is an SQL +** statement that does not return data (for example an [UPDATE]). +** +** See also: [sqlite3_data_count()] +*/ +SQLITE_API int sqlite3_column_count(sqlite3_stmt *pStmt); + +/* +** CAPI3REF: Column Names In A Result Set +** +** ^These routines return the name assigned to a particular column +** in the result set of a [SELECT] statement. ^The sqlite3_column_name() +** interface returns a pointer to a zero-terminated UTF-8 string +** and sqlite3_column_name16() returns a pointer to a zero-terminated +** UTF-16 string. ^The first parameter is the [prepared statement] +** that implements the [SELECT] statement. ^The second parameter is the +** column number. ^The leftmost column is number 0. +** +** ^The returned string pointer is valid until either the [prepared statement] +** is destroyed by [sqlite3_finalize()] or until the statement is automatically +** reprepared by the first call to [sqlite3_step()] for a particular run +** or until the next call to +** sqlite3_column_name() or sqlite3_column_name16() on the same column. +** +** ^If sqlite3_malloc() fails during the processing of either routine +** (for example during a conversion from UTF-8 to UTF-16) then a +** NULL pointer is returned. +** +** ^The name of a result column is the value of the "AS" clause for +** that column, if there is an AS clause. If there is no AS clause +** then the name of the column is unspecified and may change from +** one release of SQLite to the next. +*/ +SQLITE_API const char *sqlite3_column_name(sqlite3_stmt*, int N); +SQLITE_API const void *sqlite3_column_name16(sqlite3_stmt*, int N); + +/* +** CAPI3REF: Source Of Data In A Query Result +** +** ^These routines provide a means to determine the database, table, and +** table column that is the origin of a particular result column in +** [SELECT] statement. +** ^The name of the database or table or column can be returned as +** either a UTF-8 or UTF-16 string. ^The _database_ routines return +** the database name, the _table_ routines return the table name, and +** the origin_ routines return the column name. +** ^The returned string is valid until the [prepared statement] is destroyed +** using [sqlite3_finalize()] or until the statement is automatically +** reprepared by the first call to [sqlite3_step()] for a particular run +** or until the same information is requested +** again in a different encoding. +** +** ^The names returned are the original un-aliased names of the +** database, table, and column. +** +** ^The first argument to these interfaces is a [prepared statement]. +** ^These functions return information about the Nth result column returned by +** the statement, where N is the second function argument. +** ^The left-most column is column 0 for these routines. +** +** ^If the Nth column returned by the statement is an expression or +** subquery and is not a column value, then all of these functions return +** NULL. ^These routine might also return NULL if a memory allocation error +** occurs. ^Otherwise, they return the name of the attached database, table, +** or column that query result column was extracted from. +** +** ^As with all other SQLite APIs, those whose names end with "16" return +** UTF-16 encoded strings and the other functions return UTF-8. +** +** ^These APIs are only available if the library was compiled with the +** [SQLITE_ENABLE_COLUMN_METADATA] C-preprocessor symbol. +** +** If two or more threads call one or more of these routines against the same +** prepared statement and column at the same time then the results are +** undefined. +** +** If two or more threads call one or more +** [sqlite3_column_database_name | column metadata interfaces] +** for the same [prepared statement] and result column +** at the same time then the results are undefined. +*/ +SQLITE_API const char *sqlite3_column_database_name(sqlite3_stmt*,int); +SQLITE_API const void *sqlite3_column_database_name16(sqlite3_stmt*,int); +SQLITE_API const char *sqlite3_column_table_name(sqlite3_stmt*,int); +SQLITE_API const void *sqlite3_column_table_name16(sqlite3_stmt*,int); +SQLITE_API const char *sqlite3_column_origin_name(sqlite3_stmt*,int); +SQLITE_API const void *sqlite3_column_origin_name16(sqlite3_stmt*,int); + +/* +** CAPI3REF: Declared Datatype Of A Query Result +** +** ^(The first parameter is a [prepared statement]. +** If this statement is a [SELECT] statement and the Nth column of the +** returned result set of that [SELECT] is a table column (not an +** expression or subquery) then the declared type of the table +** column is returned.)^ ^If the Nth column of the result set is an +** expression or subquery, then a NULL pointer is returned. +** ^The returned string is always UTF-8 encoded. +** +** ^(For example, given the database schema: +** +** CREATE TABLE t1(c1 VARIANT); +** +** and the following statement to be compiled: +** +** SELECT c1 + 1, c1 FROM t1; +** +** this routine would return the string "VARIANT" for the second result +** column (i==1), and a NULL pointer for the first result column (i==0).)^ +** +** ^SQLite uses dynamic run-time typing. ^So just because a column +** is declared to contain a particular type does not mean that the +** data stored in that column is of the declared type. SQLite is +** strongly typed, but the typing is dynamic not static. ^Type +** is associated with individual values, not with the containers +** used to hold those values. +*/ +SQLITE_API const char *sqlite3_column_decltype(sqlite3_stmt*,int); +SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt*,int); + +/* +** CAPI3REF: Evaluate An SQL Statement +** +** After a [prepared statement] has been prepared using either +** [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] or one of the legacy +** interfaces [sqlite3_prepare()] or [sqlite3_prepare16()], this function +** must be called one or more times to evaluate the statement. +** +** The details of the behavior of the sqlite3_step() interface depend +** on whether the statement was prepared using the newer "v2" interface +** [sqlite3_prepare_v2()] and [sqlite3_prepare16_v2()] or the older legacy +** interface [sqlite3_prepare()] and [sqlite3_prepare16()]. The use of the +** new "v2" interface is recommended for new applications but the legacy +** interface will continue to be supported. +** +** ^In the legacy interface, the return value will be either [SQLITE_BUSY], +** [SQLITE_DONE], [SQLITE_ROW], [SQLITE_ERROR], or [SQLITE_MISUSE]. +** ^With the "v2" interface, any of the other [result codes] or +** [extended result codes] might be returned as well. +** +** ^[SQLITE_BUSY] means that the database engine was unable to acquire the +** database locks it needs to do its job. ^If the statement is a [COMMIT] +** or occurs outside of an explicit transaction, then you can retry the +** statement. If the statement is not a [COMMIT] and occurs within an +** explicit transaction then you should rollback the transaction before +** continuing. +** +** ^[SQLITE_DONE] means that the statement has finished executing +** successfully. sqlite3_step() should not be called again on this virtual +** machine without first calling [sqlite3_reset()] to reset the virtual +** machine back to its initial state. +** +** ^If the SQL statement being executed returns any data, then [SQLITE_ROW] +** is returned each time a new row of data is ready for processing by the +** caller. The values may be accessed using the [column access functions]. +** sqlite3_step() is called again to retrieve the next row of data. +** +** ^[SQLITE_ERROR] means that a run-time error (such as a constraint +** violation) has occurred. sqlite3_step() should not be called again on +** the VM. More information may be found by calling [sqlite3_errmsg()]. +** ^With the legacy interface, a more specific error code (for example, +** [SQLITE_INTERRUPT], [SQLITE_SCHEMA], [SQLITE_CORRUPT], and so forth) +** can be obtained by calling [sqlite3_reset()] on the +** [prepared statement]. ^In the "v2" interface, +** the more specific error code is returned directly by sqlite3_step(). +** +** [SQLITE_MISUSE] means that the this routine was called inappropriately. +** Perhaps it was called on a [prepared statement] that has +** already been [sqlite3_finalize | finalized] or on one that had +** previously returned [SQLITE_ERROR] or [SQLITE_DONE]. Or it could +** be the case that the same database connection is being used by two or +** more threads at the same moment in time. +** +** For all versions of SQLite up to and including 3.6.23.1, a call to +** [sqlite3_reset()] was required after sqlite3_step() returned anything +** other than [SQLITE_ROW] before any subsequent invocation of +** sqlite3_step(). Failure to reset the prepared statement using +** [sqlite3_reset()] would result in an [SQLITE_MISUSE] return from +** sqlite3_step(). But after version 3.6.23.1, sqlite3_step() began +** calling [sqlite3_reset()] automatically in this circumstance rather +** than returning [SQLITE_MISUSE]. This is not considered a compatibility +** break because any application that ever receives an SQLITE_MISUSE error +** is broken by definition. The [SQLITE_OMIT_AUTORESET] compile-time option +** can be used to restore the legacy behavior. +** +** Goofy Interface Alert: In the legacy interface, the sqlite3_step() +** API always returns a generic error code, [SQLITE_ERROR], following any +** error other than [SQLITE_BUSY] and [SQLITE_MISUSE]. You must call +** [sqlite3_reset()] or [sqlite3_finalize()] in order to find one of the +** specific [error codes] that better describes the error. +** We admit that this is a goofy design. The problem has been fixed +** with the "v2" interface. If you prepare all of your SQL statements +** using either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] instead +** of the legacy [sqlite3_prepare()] and [sqlite3_prepare16()] interfaces, +** then the more specific [error codes] are returned directly +** by sqlite3_step(). The use of the "v2" interface is recommended. +*/ +SQLITE_API int sqlite3_step(sqlite3_stmt*); + +/* +** CAPI3REF: Number of columns in a result set +** +** ^The sqlite3_data_count(P) interface returns the number of columns in the +** current row of the result set of [prepared statement] P. +** ^If prepared statement P does not have results ready to return +** (via calls to the [sqlite3_column_int | sqlite3_column_*()] of +** interfaces) then sqlite3_data_count(P) returns 0. +** ^The sqlite3_data_count(P) routine also returns 0 if P is a NULL pointer. +** ^The sqlite3_data_count(P) routine returns 0 if the previous call to +** [sqlite3_step](P) returned [SQLITE_DONE]. ^The sqlite3_data_count(P) +** will return non-zero if previous call to [sqlite3_step](P) returned +** [SQLITE_ROW], except in the case of the [PRAGMA incremental_vacuum] +** where it always returns zero since each step of that multi-step +** pragma returns 0 columns of data. +** +** See also: [sqlite3_column_count()] +*/ +SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt); + +/* +** CAPI3REF: Fundamental Datatypes +** KEYWORDS: SQLITE_TEXT +** +** ^(Every value in SQLite has one of five fundamental datatypes: +** +**
      +**
    • 64-bit signed integer +**
    • 64-bit IEEE floating point number +**
    • string +**
    • BLOB +**
    • NULL +**
    )^ +** +** These constants are codes for each of those types. +** +** Note that the SQLITE_TEXT constant was also used in SQLite version 2 +** for a completely different meaning. Software that links against both +** SQLite version 2 and SQLite version 3 should use SQLITE3_TEXT, not +** SQLITE_TEXT. +*/ +#define SQLITE_INTEGER 1 +#define SQLITE_FLOAT 2 +#define SQLITE_BLOB 4 +#define SQLITE_NULL 5 +#ifdef SQLITE_TEXT +# undef SQLITE_TEXT +#else +# define SQLITE_TEXT 3 +#endif +#define SQLITE3_TEXT 3 + +/* +** CAPI3REF: Result Values From A Query +** KEYWORDS: {column access functions} +** +** These routines form the "result set" interface. +** +** ^These routines return information about a single column of the current +** result row of a query. ^In every case the first argument is a pointer +** to the [prepared statement] that is being evaluated (the [sqlite3_stmt*] +** that was returned from [sqlite3_prepare_v2()] or one of its variants) +** and the second argument is the index of the column for which information +** should be returned. ^The leftmost column of the result set has the index 0. +** ^The number of columns in the result can be determined using +** [sqlite3_column_count()]. +** +** If the SQL statement does not currently point to a valid row, or if the +** column index is out of range, the result is undefined. +** These routines may only be called when the most recent call to +** [sqlite3_step()] has returned [SQLITE_ROW] and neither +** [sqlite3_reset()] nor [sqlite3_finalize()] have been called subsequently. +** If any of these routines are called after [sqlite3_reset()] or +** [sqlite3_finalize()] or after [sqlite3_step()] has returned +** something other than [SQLITE_ROW], the results are undefined. +** If [sqlite3_step()] or [sqlite3_reset()] or [sqlite3_finalize()] +** are called from a different thread while any of these routines +** are pending, then the results are undefined. +** +** ^The sqlite3_column_type() routine returns the +** [SQLITE_INTEGER | datatype code] for the initial data type +** of the result column. ^The returned value is one of [SQLITE_INTEGER], +** [SQLITE_FLOAT], [SQLITE_TEXT], [SQLITE_BLOB], or [SQLITE_NULL]. The value +** returned by sqlite3_column_type() is only meaningful if no type +** conversions have occurred as described below. After a type conversion, +** the value returned by sqlite3_column_type() is undefined. Future +** versions of SQLite may change the behavior of sqlite3_column_type() +** following a type conversion. +** +** ^If the result is a BLOB or UTF-8 string then the sqlite3_column_bytes() +** routine returns the number of bytes in that BLOB or string. +** ^If the result is a UTF-16 string, then sqlite3_column_bytes() converts +** the string to UTF-8 and then returns the number of bytes. +** ^If the result is a numeric value then sqlite3_column_bytes() uses +** [sqlite3_snprintf()] to convert that value to a UTF-8 string and returns +** the number of bytes in that string. +** ^If the result is NULL, then sqlite3_column_bytes() returns zero. +** +** ^If the result is a BLOB or UTF-16 string then the sqlite3_column_bytes16() +** routine returns the number of bytes in that BLOB or string. +** ^If the result is a UTF-8 string, then sqlite3_column_bytes16() converts +** the string to UTF-16 and then returns the number of bytes. +** ^If the result is a numeric value then sqlite3_column_bytes16() uses +** [sqlite3_snprintf()] to convert that value to a UTF-16 string and returns +** the number of bytes in that string. +** ^If the result is NULL, then sqlite3_column_bytes16() returns zero. +** +** ^The values returned by [sqlite3_column_bytes()] and +** [sqlite3_column_bytes16()] do not include the zero terminators at the end +** of the string. ^For clarity: the values returned by +** [sqlite3_column_bytes()] and [sqlite3_column_bytes16()] are the number of +** bytes in the string, not the number of characters. +** +** ^Strings returned by sqlite3_column_text() and sqlite3_column_text16(), +** even empty strings, are always zero-terminated. ^The return +** value from sqlite3_column_blob() for a zero-length BLOB is a NULL pointer. +** +** ^The object returned by [sqlite3_column_value()] is an +** [unprotected sqlite3_value] object. An unprotected sqlite3_value object +** may only be used with [sqlite3_bind_value()] and [sqlite3_result_value()]. +** If the [unprotected sqlite3_value] object returned by +** [sqlite3_column_value()] is used in any other way, including calls +** to routines like [sqlite3_value_int()], [sqlite3_value_text()], +** or [sqlite3_value_bytes()], then the behavior is undefined. +** +** These routines attempt to convert the value where appropriate. ^For +** example, if the internal representation is FLOAT and a text result +** is requested, [sqlite3_snprintf()] is used internally to perform the +** conversion automatically. ^(The following table details the conversions +** that are applied: +** +**
    +** +**
    Internal
    Type
    Requested
    Type
    Conversion +** +**
    NULL INTEGER Result is 0 +**
    NULL FLOAT Result is 0.0 +**
    NULL TEXT Result is NULL pointer +**
    NULL BLOB Result is NULL pointer +**
    INTEGER FLOAT Convert from integer to float +**
    INTEGER TEXT ASCII rendering of the integer +**
    INTEGER BLOB Same as INTEGER->TEXT +**
    FLOAT INTEGER Convert from float to integer +**
    FLOAT TEXT ASCII rendering of the float +**
    FLOAT BLOB Same as FLOAT->TEXT +**
    TEXT INTEGER Use atoi() +**
    TEXT FLOAT Use atof() +**
    TEXT BLOB No change +**
    BLOB INTEGER Convert to TEXT then use atoi() +**
    BLOB FLOAT Convert to TEXT then use atof() +**
    BLOB TEXT Add a zero terminator if needed +**
    +**
    )^ +** +** The table above makes reference to standard C library functions atoi() +** and atof(). SQLite does not really use these functions. It has its +** own equivalent internal routines. The atoi() and atof() names are +** used in the table for brevity and because they are familiar to most +** C programmers. +** +** Note that when type conversions occur, pointers returned by prior +** calls to sqlite3_column_blob(), sqlite3_column_text(), and/or +** sqlite3_column_text16() may be invalidated. +** Type conversions and pointer invalidations might occur +** in the following cases: +** +**
      +**
    • The initial content is a BLOB and sqlite3_column_text() or +** sqlite3_column_text16() is called. A zero-terminator might +** need to be added to the string.
    • +**
    • The initial content is UTF-8 text and sqlite3_column_bytes16() or +** sqlite3_column_text16() is called. The content must be converted +** to UTF-16.
    • +**
    • The initial content is UTF-16 text and sqlite3_column_bytes() or +** sqlite3_column_text() is called. The content must be converted +** to UTF-8.
    • +**
    +** +** ^Conversions between UTF-16be and UTF-16le are always done in place and do +** not invalidate a prior pointer, though of course the content of the buffer +** that the prior pointer references will have been modified. Other kinds +** of conversion are done in place when it is possible, but sometimes they +** are not possible and in those cases prior pointers are invalidated. +** +** The safest and easiest to remember policy is to invoke these routines +** in one of the following ways: +** +**
      +**
    • sqlite3_column_text() followed by sqlite3_column_bytes()
    • +**
    • sqlite3_column_blob() followed by sqlite3_column_bytes()
    • +**
    • sqlite3_column_text16() followed by sqlite3_column_bytes16()
    • +**
    +** +** In other words, you should call sqlite3_column_text(), +** sqlite3_column_blob(), or sqlite3_column_text16() first to force the result +** into the desired format, then invoke sqlite3_column_bytes() or +** sqlite3_column_bytes16() to find the size of the result. Do not mix calls +** to sqlite3_column_text() or sqlite3_column_blob() with calls to +** sqlite3_column_bytes16(), and do not mix calls to sqlite3_column_text16() +** with calls to sqlite3_column_bytes(). +** +** ^The pointers returned are valid until a type conversion occurs as +** described above, or until [sqlite3_step()] or [sqlite3_reset()] or +** [sqlite3_finalize()] is called. ^The memory space used to hold strings +** and BLOBs is freed automatically. Do not pass the pointers returned +** [sqlite3_column_blob()], [sqlite3_column_text()], etc. into +** [sqlite3_free()]. +** +** ^(If a memory allocation error occurs during the evaluation of any +** of these routines, a default value is returned. The default value +** is either the integer 0, the floating point number 0.0, or a NULL +** pointer. Subsequent calls to [sqlite3_errcode()] will return +** [SQLITE_NOMEM].)^ +*/ +SQLITE_API const void *sqlite3_column_blob(sqlite3_stmt*, int iCol); +SQLITE_API int sqlite3_column_bytes(sqlite3_stmt*, int iCol); +SQLITE_API int sqlite3_column_bytes16(sqlite3_stmt*, int iCol); +SQLITE_API double sqlite3_column_double(sqlite3_stmt*, int iCol); +SQLITE_API int sqlite3_column_int(sqlite3_stmt*, int iCol); +SQLITE_API sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol); +SQLITE_API const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol); +SQLITE_API const void *sqlite3_column_text16(sqlite3_stmt*, int iCol); +SQLITE_API int sqlite3_column_type(sqlite3_stmt*, int iCol); +SQLITE_API sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol); + +/* +** CAPI3REF: Destroy A Prepared Statement Object +** +** ^The sqlite3_finalize() function is called to delete a [prepared statement]. +** ^If the most recent evaluation of the statement encountered no errors +** or if the statement is never been evaluated, then sqlite3_finalize() returns +** SQLITE_OK. ^If the most recent evaluation of statement S failed, then +** sqlite3_finalize(S) returns the appropriate [error code] or +** [extended error code]. +** +** ^The sqlite3_finalize(S) routine can be called at any point during +** the life cycle of [prepared statement] S: +** before statement S is ever evaluated, after +** one or more calls to [sqlite3_reset()], or after any call +** to [sqlite3_step()] regardless of whether or not the statement has +** completed execution. +** +** ^Invoking sqlite3_finalize() on a NULL pointer is a harmless no-op. +** +** The application must finalize every [prepared statement] in order to avoid +** resource leaks. It is a grievous error for the application to try to use +** a prepared statement after it has been finalized. Any use of a prepared +** statement after it has been finalized can result in undefined and +** undesirable behavior such as segfaults and heap corruption. +*/ +SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt); + +/* +** CAPI3REF: Reset A Prepared Statement Object +** +** The sqlite3_reset() function is called to reset a [prepared statement] +** object back to its initial state, ready to be re-executed. +** ^Any SQL statement variables that had values bound to them using +** the [sqlite3_bind_blob | sqlite3_bind_*() API] retain their values. +** Use [sqlite3_clear_bindings()] to reset the bindings. +** +** ^The [sqlite3_reset(S)] interface resets the [prepared statement] S +** back to the beginning of its program. +** +** ^If the most recent call to [sqlite3_step(S)] for the +** [prepared statement] S returned [SQLITE_ROW] or [SQLITE_DONE], +** or if [sqlite3_step(S)] has never before been called on S, +** then [sqlite3_reset(S)] returns [SQLITE_OK]. +** +** ^If the most recent call to [sqlite3_step(S)] for the +** [prepared statement] S indicated an error, then +** [sqlite3_reset(S)] returns an appropriate [error code]. +** +** ^The [sqlite3_reset(S)] interface does not change the values +** of any [sqlite3_bind_blob|bindings] on the [prepared statement] S. +*/ +SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt); + +/* +** CAPI3REF: Create Or Redefine SQL Functions +** KEYWORDS: {function creation routines} +** KEYWORDS: {application-defined SQL function} +** KEYWORDS: {application-defined SQL functions} +** +** ^These functions (collectively known as "function creation routines") +** are used to add SQL functions or aggregates or to redefine the behavior +** of existing SQL functions or aggregates. The only differences between +** these routines are the text encoding expected for +** the second parameter (the name of the function being created) +** and the presence or absence of a destructor callback for +** the application data pointer. +** +** ^The first parameter is the [database connection] to which the SQL +** function is to be added. ^If an application uses more than one database +** connection then application-defined SQL functions must be added +** to each database connection separately. +** +** ^The second parameter is the name of the SQL function to be created or +** redefined. ^The length of the name is limited to 255 bytes in a UTF-8 +** representation, exclusive of the zero-terminator. ^Note that the name +** length limit is in UTF-8 bytes, not characters nor UTF-16 bytes. +** ^Any attempt to create a function with a longer name +** will result in [SQLITE_MISUSE] being returned. +** +** ^The third parameter (nArg) +** is the number of arguments that the SQL function or +** aggregate takes. ^If this parameter is -1, then the SQL function or +** aggregate may take any number of arguments between 0 and the limit +** set by [sqlite3_limit]([SQLITE_LIMIT_FUNCTION_ARG]). If the third +** parameter is less than -1 or greater than 127 then the behavior is +** undefined. +** +** ^The fourth parameter, eTextRep, specifies what +** [SQLITE_UTF8 | text encoding] this SQL function prefers for +** its parameters. Every SQL function implementation must be able to work +** with UTF-8, UTF-16le, or UTF-16be. But some implementations may be +** more efficient with one encoding than another. ^An application may +** invoke sqlite3_create_function() or sqlite3_create_function16() multiple +** times with the same function but with different values of eTextRep. +** ^When multiple implementations of the same function are available, SQLite +** will pick the one that involves the least amount of data conversion. +** If there is only a single implementation which does not care what text +** encoding is used, then the fourth argument should be [SQLITE_ANY]. +** +** ^(The fifth parameter is an arbitrary pointer. The implementation of the +** function can gain access to this pointer using [sqlite3_user_data()].)^ +** +** ^The sixth, seventh and eighth parameters, xFunc, xStep and xFinal, are +** pointers to C-language functions that implement the SQL function or +** aggregate. ^A scalar SQL function requires an implementation of the xFunc +** callback only; NULL pointers must be passed as the xStep and xFinal +** parameters. ^An aggregate SQL function requires an implementation of xStep +** and xFinal and NULL pointer must be passed for xFunc. ^To delete an existing +** SQL function or aggregate, pass NULL pointers for all three function +** callbacks. +** +** ^(If the ninth parameter to sqlite3_create_function_v2() is not NULL, +** then it is destructor for the application data pointer. +** The destructor is invoked when the function is deleted, either by being +** overloaded or when the database connection closes.)^ +** ^The destructor is also invoked if the call to +** sqlite3_create_function_v2() fails. +** ^When the destructor callback of the tenth parameter is invoked, it +** is passed a single argument which is a copy of the application data +** pointer which was the fifth parameter to sqlite3_create_function_v2(). +** +** ^It is permitted to register multiple implementations of the same +** functions with the same name but with either differing numbers of +** arguments or differing preferred text encodings. ^SQLite will use +** the implementation that most closely matches the way in which the +** SQL function is used. ^A function implementation with a non-negative +** nArg parameter is a better match than a function implementation with +** a negative nArg. ^A function where the preferred text encoding +** matches the database encoding is a better +** match than a function where the encoding is different. +** ^A function where the encoding difference is between UTF16le and UTF16be +** is a closer match than a function where the encoding difference is +** between UTF8 and UTF16. +** +** ^Built-in functions may be overloaded by new application-defined functions. +** +** ^An application-defined function is permitted to call other +** SQLite interfaces. However, such calls must not +** close the database connection nor finalize or reset the prepared +** statement in which the function is running. +*/ +SQLITE_API int sqlite3_create_function( + sqlite3 *db, + const char *zFunctionName, + int nArg, + int eTextRep, + void *pApp, + void (*xFunc)(sqlite3_context*,int,sqlite3_value**), + void (*xStep)(sqlite3_context*,int,sqlite3_value**), + void (*xFinal)(sqlite3_context*) +); +SQLITE_API int sqlite3_create_function16( + sqlite3 *db, + const void *zFunctionName, + int nArg, + int eTextRep, + void *pApp, + void (*xFunc)(sqlite3_context*,int,sqlite3_value**), + void (*xStep)(sqlite3_context*,int,sqlite3_value**), + void (*xFinal)(sqlite3_context*) +); +SQLITE_API int sqlite3_create_function_v2( + sqlite3 *db, + const char *zFunctionName, + int nArg, + int eTextRep, + void *pApp, + void (*xFunc)(sqlite3_context*,int,sqlite3_value**), + void (*xStep)(sqlite3_context*,int,sqlite3_value**), + void (*xFinal)(sqlite3_context*), + void(*xDestroy)(void*) +); + +/* +** CAPI3REF: Text Encodings +** +** These constant define integer codes that represent the various +** text encodings supported by SQLite. +*/ +#define SQLITE_UTF8 1 +#define SQLITE_UTF16LE 2 +#define SQLITE_UTF16BE 3 +#define SQLITE_UTF16 4 /* Use native byte order */ +#define SQLITE_ANY 5 /* sqlite3_create_function only */ +#define SQLITE_UTF16_ALIGNED 8 /* sqlite3_create_collation only */ + +/* +** CAPI3REF: Deprecated Functions +** DEPRECATED +** +** These functions are [deprecated]. In order to maintain +** backwards compatibility with older code, these functions continue +** to be supported. However, new applications should avoid +** the use of these functions. To help encourage people to avoid +** using these functions, we are not going to tell you what they do. +*/ +#ifndef SQLITE_OMIT_DEPRECATED +SQLITE_API SQLITE_DEPRECATED int sqlite3_aggregate_count(sqlite3_context*); +SQLITE_API SQLITE_DEPRECATED int sqlite3_expired(sqlite3_stmt*); +SQLITE_API SQLITE_DEPRECATED int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*); +SQLITE_API SQLITE_DEPRECATED int sqlite3_global_recover(void); +SQLITE_API SQLITE_DEPRECATED void sqlite3_thread_cleanup(void); +SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),void*,sqlite3_int64); +#endif + +/* +** CAPI3REF: Obtaining SQL Function Parameter Values +** +** The C-language implementation of SQL functions and aggregates uses +** this set of interface routines to access the parameter values on +** the function or aggregate. +** +** The xFunc (for scalar functions) or xStep (for aggregates) parameters +** to [sqlite3_create_function()] and [sqlite3_create_function16()] +** define callbacks that implement the SQL functions and aggregates. +** The 3rd parameter to these callbacks is an array of pointers to +** [protected sqlite3_value] objects. There is one [sqlite3_value] object for +** each parameter to the SQL function. These routines are used to +** extract values from the [sqlite3_value] objects. +** +** These routines work only with [protected sqlite3_value] objects. +** Any attempt to use these routines on an [unprotected sqlite3_value] +** object results in undefined behavior. +** +** ^These routines work just like the corresponding [column access functions] +** except that these routines take a single [protected sqlite3_value] object +** pointer instead of a [sqlite3_stmt*] pointer and an integer column number. +** +** ^The sqlite3_value_text16() interface extracts a UTF-16 string +** in the native byte-order of the host machine. ^The +** sqlite3_value_text16be() and sqlite3_value_text16le() interfaces +** extract UTF-16 strings as big-endian and little-endian respectively. +** +** ^(The sqlite3_value_numeric_type() interface attempts to apply +** numeric affinity to the value. This means that an attempt is +** made to convert the value to an integer or floating point. If +** such a conversion is possible without loss of information (in other +** words, if the value is a string that looks like a number) +** then the conversion is performed. Otherwise no conversion occurs. +** The [SQLITE_INTEGER | datatype] after conversion is returned.)^ +** +** Please pay particular attention to the fact that the pointer returned +** from [sqlite3_value_blob()], [sqlite3_value_text()], or +** [sqlite3_value_text16()] can be invalidated by a subsequent call to +** [sqlite3_value_bytes()], [sqlite3_value_bytes16()], [sqlite3_value_text()], +** or [sqlite3_value_text16()]. +** +** These routines must be called from the same thread as +** the SQL function that supplied the [sqlite3_value*] parameters. +*/ +SQLITE_API const void *sqlite3_value_blob(sqlite3_value*); +SQLITE_API int sqlite3_value_bytes(sqlite3_value*); +SQLITE_API int sqlite3_value_bytes16(sqlite3_value*); +SQLITE_API double sqlite3_value_double(sqlite3_value*); +SQLITE_API int sqlite3_value_int(sqlite3_value*); +SQLITE_API sqlite3_int64 sqlite3_value_int64(sqlite3_value*); +SQLITE_API const unsigned char *sqlite3_value_text(sqlite3_value*); +SQLITE_API const void *sqlite3_value_text16(sqlite3_value*); +SQLITE_API const void *sqlite3_value_text16le(sqlite3_value*); +SQLITE_API const void *sqlite3_value_text16be(sqlite3_value*); +SQLITE_API int sqlite3_value_type(sqlite3_value*); +SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*); + +/* +** CAPI3REF: Obtain Aggregate Function Context +** +** Implementations of aggregate SQL functions use this +** routine to allocate memory for storing their state. +** +** ^The first time the sqlite3_aggregate_context(C,N) routine is called +** for a particular aggregate function, SQLite +** allocates N of memory, zeroes out that memory, and returns a pointer +** to the new memory. ^On second and subsequent calls to +** sqlite3_aggregate_context() for the same aggregate function instance, +** the same buffer is returned. Sqlite3_aggregate_context() is normally +** called once for each invocation of the xStep callback and then one +** last time when the xFinal callback is invoked. ^(When no rows match +** an aggregate query, the xStep() callback of the aggregate function +** implementation is never called and xFinal() is called exactly once. +** In those cases, sqlite3_aggregate_context() might be called for the +** first time from within xFinal().)^ +** +** ^The sqlite3_aggregate_context(C,N) routine returns a NULL pointer if N is +** less than or equal to zero or if a memory allocate error occurs. +** +** ^(The amount of space allocated by sqlite3_aggregate_context(C,N) is +** determined by the N parameter on first successful call. Changing the +** value of N in subsequent call to sqlite3_aggregate_context() within +** the same aggregate function instance will not resize the memory +** allocation.)^ +** +** ^SQLite automatically frees the memory allocated by +** sqlite3_aggregate_context() when the aggregate query concludes. +** +** The first parameter must be a copy of the +** [sqlite3_context | SQL function context] that is the first parameter +** to the xStep or xFinal callback routine that implements the aggregate +** function. +** +** This routine must be called from the same thread in which +** the aggregate SQL function is running. +*/ +SQLITE_API void *sqlite3_aggregate_context(sqlite3_context*, int nBytes); + +/* +** CAPI3REF: User Data For Functions +** +** ^The sqlite3_user_data() interface returns a copy of +** the pointer that was the pUserData parameter (the 5th parameter) +** of the [sqlite3_create_function()] +** and [sqlite3_create_function16()] routines that originally +** registered the application defined function. +** +** This routine must be called from the same thread in which +** the application-defined function is running. +*/ +SQLITE_API void *sqlite3_user_data(sqlite3_context*); + +/* +** CAPI3REF: Database Connection For Functions +** +** ^The sqlite3_context_db_handle() interface returns a copy of +** the pointer to the [database connection] (the 1st parameter) +** of the [sqlite3_create_function()] +** and [sqlite3_create_function16()] routines that originally +** registered the application defined function. +*/ +SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*); + +/* +** CAPI3REF: Function Auxiliary Data +** +** The following two functions may be used by scalar SQL functions to +** associate metadata with argument values. If the same value is passed to +** multiple invocations of the same SQL function during query execution, under +** some circumstances the associated metadata may be preserved. This may +** be used, for example, to add a regular-expression matching scalar +** function. The compiled version of the regular expression is stored as +** metadata associated with the SQL value passed as the regular expression +** pattern. The compiled regular expression can be reused on multiple +** invocations of the same function so that the original pattern string +** does not need to be recompiled on each invocation. +** +** ^The sqlite3_get_auxdata() interface returns a pointer to the metadata +** associated by the sqlite3_set_auxdata() function with the Nth argument +** value to the application-defined function. ^If no metadata has been ever +** been set for the Nth argument of the function, or if the corresponding +** function parameter has changed since the meta-data was set, +** then sqlite3_get_auxdata() returns a NULL pointer. +** +** ^The sqlite3_set_auxdata() interface saves the metadata +** pointed to by its 3rd parameter as the metadata for the N-th +** argument of the application-defined function. Subsequent +** calls to sqlite3_get_auxdata() might return this data, if it has +** not been destroyed. +** ^If it is not NULL, SQLite will invoke the destructor +** function given by the 4th parameter to sqlite3_set_auxdata() on +** the metadata when the corresponding function parameter changes +** or when the SQL statement completes, whichever comes first. +** +** SQLite is free to call the destructor and drop metadata on any +** parameter of any function at any time. ^The only guarantee is that +** the destructor will be called before the metadata is dropped. +** +** ^(In practice, metadata is preserved between function calls for +** expressions that are constant at compile time. This includes literal +** values and [parameters].)^ +** +** These routines must be called from the same thread in which +** the SQL function is running. +*/ +SQLITE_API void *sqlite3_get_auxdata(sqlite3_context*, int N); +SQLITE_API void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*)); + + +/* +** CAPI3REF: Constants Defining Special Destructor Behavior +** +** These are special values for the destructor that is passed in as the +** final argument to routines like [sqlite3_result_blob()]. ^If the destructor +** argument is SQLITE_STATIC, it means that the content pointer is constant +** and will never change. It does not need to be destroyed. ^The +** SQLITE_TRANSIENT value means that the content will likely change in +** the near future and that SQLite should make its own private copy of +** the content before returning. +** +** The typedef is necessary to work around problems in certain +** C++ compilers. See ticket #2191. +*/ +typedef void (*sqlite3_destructor_type)(void*); +#define SQLITE_STATIC ((sqlite3_destructor_type)0) +#define SQLITE_TRANSIENT ((sqlite3_destructor_type)-1) + +/* +** CAPI3REF: Setting The Result Of An SQL Function +** +** These routines are used by the xFunc or xFinal callbacks that +** implement SQL functions and aggregates. See +** [sqlite3_create_function()] and [sqlite3_create_function16()] +** for additional information. +** +** These functions work very much like the [parameter binding] family of +** functions used to bind values to host parameters in prepared statements. +** Refer to the [SQL parameter] documentation for additional information. +** +** ^The sqlite3_result_blob() interface sets the result from +** an application-defined function to be the BLOB whose content is pointed +** to by the second parameter and which is N bytes long where N is the +** third parameter. +** +** ^The sqlite3_result_zeroblob() interfaces set the result of +** the application-defined function to be a BLOB containing all zero +** bytes and N bytes in size, where N is the value of the 2nd parameter. +** +** ^The sqlite3_result_double() interface sets the result from +** an application-defined function to be a floating point value specified +** by its 2nd argument. +** +** ^The sqlite3_result_error() and sqlite3_result_error16() functions +** cause the implemented SQL function to throw an exception. +** ^SQLite uses the string pointed to by the +** 2nd parameter of sqlite3_result_error() or sqlite3_result_error16() +** as the text of an error message. ^SQLite interprets the error +** message string from sqlite3_result_error() as UTF-8. ^SQLite +** interprets the string from sqlite3_result_error16() as UTF-16 in native +** byte order. ^If the third parameter to sqlite3_result_error() +** or sqlite3_result_error16() is negative then SQLite takes as the error +** message all text up through the first zero character. +** ^If the third parameter to sqlite3_result_error() or +** sqlite3_result_error16() is non-negative then SQLite takes that many +** bytes (not characters) from the 2nd parameter as the error message. +** ^The sqlite3_result_error() and sqlite3_result_error16() +** routines make a private copy of the error message text before +** they return. Hence, the calling function can deallocate or +** modify the text after they return without harm. +** ^The sqlite3_result_error_code() function changes the error code +** returned by SQLite as a result of an error in a function. ^By default, +** the error code is SQLITE_ERROR. ^A subsequent call to sqlite3_result_error() +** or sqlite3_result_error16() resets the error code to SQLITE_ERROR. +** +** ^The sqlite3_result_toobig() interface causes SQLite to throw an error +** indicating that a string or BLOB is too long to represent. +** +** ^The sqlite3_result_nomem() interface causes SQLite to throw an error +** indicating that a memory allocation failed. +** +** ^The sqlite3_result_int() interface sets the return value +** of the application-defined function to be the 32-bit signed integer +** value given in the 2nd argument. +** ^The sqlite3_result_int64() interface sets the return value +** of the application-defined function to be the 64-bit signed integer +** value given in the 2nd argument. +** +** ^The sqlite3_result_null() interface sets the return value +** of the application-defined function to be NULL. +** +** ^The sqlite3_result_text(), sqlite3_result_text16(), +** sqlite3_result_text16le(), and sqlite3_result_text16be() interfaces +** set the return value of the application-defined function to be +** a text string which is represented as UTF-8, UTF-16 native byte order, +** UTF-16 little endian, or UTF-16 big endian, respectively. +** ^SQLite takes the text result from the application from +** the 2nd parameter of the sqlite3_result_text* interfaces. +** ^If the 3rd parameter to the sqlite3_result_text* interfaces +** is negative, then SQLite takes result text from the 2nd parameter +** through the first zero character. +** ^If the 3rd parameter to the sqlite3_result_text* interfaces +** is non-negative, then as many bytes (not characters) of the text +** pointed to by the 2nd parameter are taken as the application-defined +** function result. If the 3rd parameter is non-negative, then it +** must be the byte offset into the string where the NUL terminator would +** appear if the string where NUL terminated. If any NUL characters occur +** in the string at a byte offset that is less than the value of the 3rd +** parameter, then the resulting string will contain embedded NULs and the +** result of expressions operating on strings with embedded NULs is undefined. +** ^If the 4th parameter to the sqlite3_result_text* interfaces +** or sqlite3_result_blob is a non-NULL pointer, then SQLite calls that +** function as the destructor on the text or BLOB result when it has +** finished using that result. +** ^If the 4th parameter to the sqlite3_result_text* interfaces or to +** sqlite3_result_blob is the special constant SQLITE_STATIC, then SQLite +** assumes that the text or BLOB result is in constant space and does not +** copy the content of the parameter nor call a destructor on the content +** when it has finished using that result. +** ^If the 4th parameter to the sqlite3_result_text* interfaces +** or sqlite3_result_blob is the special constant SQLITE_TRANSIENT +** then SQLite makes a copy of the result into space obtained from +** from [sqlite3_malloc()] before it returns. +** +** ^The sqlite3_result_value() interface sets the result of +** the application-defined function to be a copy the +** [unprotected sqlite3_value] object specified by the 2nd parameter. ^The +** sqlite3_result_value() interface makes a copy of the [sqlite3_value] +** so that the [sqlite3_value] specified in the parameter may change or +** be deallocated after sqlite3_result_value() returns without harm. +** ^A [protected sqlite3_value] object may always be used where an +** [unprotected sqlite3_value] object is required, so either +** kind of [sqlite3_value] object can be used with this interface. +** +** If these routines are called from within the different thread +** than the one containing the application-defined function that received +** the [sqlite3_context] pointer, the results are undefined. +*/ +SQLITE_API void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); +SQLITE_API void sqlite3_result_double(sqlite3_context*, double); +SQLITE_API void sqlite3_result_error(sqlite3_context*, const char*, int); +SQLITE_API void sqlite3_result_error16(sqlite3_context*, const void*, int); +SQLITE_API void sqlite3_result_error_toobig(sqlite3_context*); +SQLITE_API void sqlite3_result_error_nomem(sqlite3_context*); +SQLITE_API void sqlite3_result_error_code(sqlite3_context*, int); +SQLITE_API void sqlite3_result_int(sqlite3_context*, int); +SQLITE_API void sqlite3_result_int64(sqlite3_context*, sqlite3_int64); +SQLITE_API void sqlite3_result_null(sqlite3_context*); +SQLITE_API void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*)); +SQLITE_API void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*)); +SQLITE_API void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*)); +SQLITE_API void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*)); +SQLITE_API void sqlite3_result_value(sqlite3_context*, sqlite3_value*); +SQLITE_API void sqlite3_result_zeroblob(sqlite3_context*, int n); + +/* +** CAPI3REF: Define New Collating Sequences +** +** ^These functions add, remove, or modify a [collation] associated +** with the [database connection] specified as the first argument. +** +** ^The name of the collation is a UTF-8 string +** for sqlite3_create_collation() and sqlite3_create_collation_v2() +** and a UTF-16 string in native byte order for sqlite3_create_collation16(). +** ^Collation names that compare equal according to [sqlite3_strnicmp()] are +** considered to be the same name. +** +** ^(The third argument (eTextRep) must be one of the constants: +**
      +**
    • [SQLITE_UTF8], +**
    • [SQLITE_UTF16LE], +**
    • [SQLITE_UTF16BE], +**
    • [SQLITE_UTF16], or +**
    • [SQLITE_UTF16_ALIGNED]. +**
    )^ +** ^The eTextRep argument determines the encoding of strings passed +** to the collating function callback, xCallback. +** ^The [SQLITE_UTF16] and [SQLITE_UTF16_ALIGNED] values for eTextRep +** force strings to be UTF16 with native byte order. +** ^The [SQLITE_UTF16_ALIGNED] value for eTextRep forces strings to begin +** on an even byte address. +** +** ^The fourth argument, pArg, is an application data pointer that is passed +** through as the first argument to the collating function callback. +** +** ^The fifth argument, xCallback, is a pointer to the collating function. +** ^Multiple collating functions can be registered using the same name but +** with different eTextRep parameters and SQLite will use whichever +** function requires the least amount of data transformation. +** ^If the xCallback argument is NULL then the collating function is +** deleted. ^When all collating functions having the same name are deleted, +** that collation is no longer usable. +** +** ^The collating function callback is invoked with a copy of the pArg +** application data pointer and with two strings in the encoding specified +** by the eTextRep argument. The collating function must return an +** integer that is negative, zero, or positive +** if the first string is less than, equal to, or greater than the second, +** respectively. A collating function must always return the same answer +** given the same inputs. If two or more collating functions are registered +** to the same collation name (using different eTextRep values) then all +** must give an equivalent answer when invoked with equivalent strings. +** The collating function must obey the following properties for all +** strings A, B, and C: +** +**
      +**
    1. If A==B then B==A. +**
    2. If A==B and B==C then A==C. +**
    3. If A<B THEN B>A. +**
    4. If A<B and B<C then A<C. +**
    +** +** If a collating function fails any of the above constraints and that +** collating function is registered and used, then the behavior of SQLite +** is undefined. +** +** ^The sqlite3_create_collation_v2() works like sqlite3_create_collation() +** with the addition that the xDestroy callback is invoked on pArg when +** the collating function is deleted. +** ^Collating functions are deleted when they are overridden by later +** calls to the collation creation functions or when the +** [database connection] is closed using [sqlite3_close()]. +** +** ^The xDestroy callback is not called if the +** sqlite3_create_collation_v2() function fails. Applications that invoke +** sqlite3_create_collation_v2() with a non-NULL xDestroy argument should +** check the return code and dispose of the application data pointer +** themselves rather than expecting SQLite to deal with it for them. +** This is different from every other SQLite interface. The inconsistency +** is unfortunate but cannot be changed without breaking backwards +** compatibility. +** +** See also: [sqlite3_collation_needed()] and [sqlite3_collation_needed16()]. +*/ +SQLITE_API int sqlite3_create_collation( + sqlite3*, + const char *zName, + int eTextRep, + void *pArg, + int(*xCompare)(void*,int,const void*,int,const void*) +); +SQLITE_API int sqlite3_create_collation_v2( + sqlite3*, + const char *zName, + int eTextRep, + void *pArg, + int(*xCompare)(void*,int,const void*,int,const void*), + void(*xDestroy)(void*) +); +SQLITE_API int sqlite3_create_collation16( + sqlite3*, + const void *zName, + int eTextRep, + void *pArg, + int(*xCompare)(void*,int,const void*,int,const void*) +); + +/* +** CAPI3REF: Collation Needed Callbacks +** +** ^To avoid having to register all collation sequences before a database +** can be used, a single callback function may be registered with the +** [database connection] to be invoked whenever an undefined collation +** sequence is required. +** +** ^If the function is registered using the sqlite3_collation_needed() API, +** then it is passed the names of undefined collation sequences as strings +** encoded in UTF-8. ^If sqlite3_collation_needed16() is used, +** the names are passed as UTF-16 in machine native byte order. +** ^A call to either function replaces the existing collation-needed callback. +** +** ^(When the callback is invoked, the first argument passed is a copy +** of the second argument to sqlite3_collation_needed() or +** sqlite3_collation_needed16(). The second argument is the database +** connection. The third argument is one of [SQLITE_UTF8], [SQLITE_UTF16BE], +** or [SQLITE_UTF16LE], indicating the most desirable form of the collation +** sequence function required. The fourth parameter is the name of the +** required collation sequence.)^ +** +** The callback function should register the desired collation using +** [sqlite3_create_collation()], [sqlite3_create_collation16()], or +** [sqlite3_create_collation_v2()]. +*/ +SQLITE_API int sqlite3_collation_needed( + sqlite3*, + void*, + void(*)(void*,sqlite3*,int eTextRep,const char*) +); +SQLITE_API int sqlite3_collation_needed16( + sqlite3*, + void*, + void(*)(void*,sqlite3*,int eTextRep,const void*) +); + +#ifdef SQLITE_HAS_CODEC +/* +** Specify the key for an encrypted database. This routine should be +** called right after sqlite3_open(). +** +** The code to implement this API is not available in the public release +** of SQLite. +*/ +SQLITE_API int sqlite3_key( + sqlite3 *db, /* Database to be rekeyed */ + const void *pKey, int nKey /* The key */ +); + +/* +** Change the key on an open database. If the current database is not +** encrypted, this routine will encrypt it. If pNew==0 or nNew==0, the +** database is decrypted. +** +** The code to implement this API is not available in the public release +** of SQLite. +*/ +SQLITE_API int sqlite3_rekey( + sqlite3 *db, /* Database to be rekeyed */ + const void *pKey, int nKey /* The new key */ +); + +/* +** Specify the activation key for a SEE database. Unless +** activated, none of the SEE routines will work. +*/ +SQLITE_API void sqlite3_activate_see( + const char *zPassPhrase /* Activation phrase */ +); +#endif + +#ifdef SQLITE_ENABLE_CEROD +/* +** Specify the activation key for a CEROD database. Unless +** activated, none of the CEROD routines will work. +*/ +SQLITE_API void sqlite3_activate_cerod( + const char *zPassPhrase /* Activation phrase */ +); +#endif + +/* +** CAPI3REF: Suspend Execution For A Short Time +** +** The sqlite3_sleep() function causes the current thread to suspend execution +** for at least a number of milliseconds specified in its parameter. +** +** If the operating system does not support sleep requests with +** millisecond time resolution, then the time will be rounded up to +** the nearest second. The number of milliseconds of sleep actually +** requested from the operating system is returned. +** +** ^SQLite implements this interface by calling the xSleep() +** method of the default [sqlite3_vfs] object. If the xSleep() method +** of the default VFS is not implemented correctly, or not implemented at +** all, then the behavior of sqlite3_sleep() may deviate from the description +** in the previous paragraphs. +*/ +SQLITE_API int sqlite3_sleep(int); + +/* +** CAPI3REF: Name Of The Folder Holding Temporary Files +** +** ^(If this global variable is made to point to a string which is +** the name of a folder (a.k.a. directory), then all temporary files +** created by SQLite when using a built-in [sqlite3_vfs | VFS] +** will be placed in that directory.)^ ^If this variable +** is a NULL pointer, then SQLite performs a search for an appropriate +** temporary file directory. +** +** It is not safe to read or modify this variable in more than one +** thread at a time. It is not safe to read or modify this variable +** if a [database connection] is being used at the same time in a separate +** thread. +** It is intended that this variable be set once +** as part of process initialization and before any SQLite interface +** routines have been called and that this variable remain unchanged +** thereafter. +** +** ^The [temp_store_directory pragma] may modify this variable and cause +** it to point to memory obtained from [sqlite3_malloc]. ^Furthermore, +** the [temp_store_directory pragma] always assumes that any string +** that this variable points to is held in memory obtained from +** [sqlite3_malloc] and the pragma may attempt to free that memory +** using [sqlite3_free]. +** Hence, if this variable is modified directly, either it should be +** made NULL or made to point to memory obtained from [sqlite3_malloc] +** or else the use of the [temp_store_directory pragma] should be avoided. +*/ +SQLITE_API char *sqlite3_temp_directory; + +/* +** CAPI3REF: Test For Auto-Commit Mode +** KEYWORDS: {autocommit mode} +** +** ^The sqlite3_get_autocommit() interface returns non-zero or +** zero if the given database connection is or is not in autocommit mode, +** respectively. ^Autocommit mode is on by default. +** ^Autocommit mode is disabled by a [BEGIN] statement. +** ^Autocommit mode is re-enabled by a [COMMIT] or [ROLLBACK]. +** +** If certain kinds of errors occur on a statement within a multi-statement +** transaction (errors including [SQLITE_FULL], [SQLITE_IOERR], +** [SQLITE_NOMEM], [SQLITE_BUSY], and [SQLITE_INTERRUPT]) then the +** transaction might be rolled back automatically. The only way to +** find out whether SQLite automatically rolled back the transaction after +** an error is to use this function. +** +** If another thread changes the autocommit status of the database +** connection while this routine is running, then the return value +** is undefined. +*/ +SQLITE_API int sqlite3_get_autocommit(sqlite3*); + +/* +** CAPI3REF: Find The Database Handle Of A Prepared Statement +** +** ^The sqlite3_db_handle interface returns the [database connection] handle +** to which a [prepared statement] belongs. ^The [database connection] +** returned by sqlite3_db_handle is the same [database connection] +** that was the first argument +** to the [sqlite3_prepare_v2()] call (or its variants) that was used to +** create the statement in the first place. +*/ +SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt*); + +/* +** CAPI3REF: Return The Filename For A Database Connection +** +** ^The sqlite3_db_filename(D,N) interface returns a pointer to a filename +** associated with database N of connection D. ^The main database file +** has the name "main". If there is no attached database N on the database +** connection D, or if database N is a temporary or in-memory database, then +** a NULL pointer is returned. +** +** ^The filename returned by this function is the output of the +** xFullPathname method of the [VFS]. ^In other words, the filename +** will be an absolute pathname, even if the filename used +** to open the database originally was a URI or relative pathname. +*/ +SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName); + +/* +** CAPI3REF: Find the next prepared statement +** +** ^This interface returns a pointer to the next [prepared statement] after +** pStmt associated with the [database connection] pDb. ^If pStmt is NULL +** then this interface returns a pointer to the first prepared statement +** associated with the database connection pDb. ^If no prepared statement +** satisfies the conditions of this routine, it returns NULL. +** +** The [database connection] pointer D in a call to +** [sqlite3_next_stmt(D,S)] must refer to an open database +** connection and in particular must not be a NULL pointer. +*/ +SQLITE_API sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt); + +/* +** CAPI3REF: Commit And Rollback Notification Callbacks +** +** ^The sqlite3_commit_hook() interface registers a callback +** function to be invoked whenever a transaction is [COMMIT | committed]. +** ^Any callback set by a previous call to sqlite3_commit_hook() +** for the same database connection is overridden. +** ^The sqlite3_rollback_hook() interface registers a callback +** function to be invoked whenever a transaction is [ROLLBACK | rolled back]. +** ^Any callback set by a previous call to sqlite3_rollback_hook() +** for the same database connection is overridden. +** ^The pArg argument is passed through to the callback. +** ^If the callback on a commit hook function returns non-zero, +** then the commit is converted into a rollback. +** +** ^The sqlite3_commit_hook(D,C,P) and sqlite3_rollback_hook(D,C,P) functions +** return the P argument from the previous call of the same function +** on the same [database connection] D, or NULL for +** the first call for each function on D. +** +** The commit and rollback hook callbacks are not reentrant. +** The callback implementation must not do anything that will modify +** the database connection that invoked the callback. Any actions +** to modify the database connection must be deferred until after the +** completion of the [sqlite3_step()] call that triggered the commit +** or rollback hook in the first place. +** Note that running any other SQL statements, including SELECT statements, +** or merely calling [sqlite3_prepare_v2()] and [sqlite3_step()] will modify +** the database connections for the meaning of "modify" in this paragraph. +** +** ^Registering a NULL function disables the callback. +** +** ^When the commit hook callback routine returns zero, the [COMMIT] +** operation is allowed to continue normally. ^If the commit hook +** returns non-zero, then the [COMMIT] is converted into a [ROLLBACK]. +** ^The rollback hook is invoked on a rollback that results from a commit +** hook returning non-zero, just as it would be with any other rollback. +** +** ^For the purposes of this API, a transaction is said to have been +** rolled back if an explicit "ROLLBACK" statement is executed, or +** an error or constraint causes an implicit rollback to occur. +** ^The rollback callback is not invoked if a transaction is +** automatically rolled back because the database connection is closed. +** +** See also the [sqlite3_update_hook()] interface. +*/ +SQLITE_API void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*); +SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); + +/* +** CAPI3REF: Data Change Notification Callbacks +** +** ^The sqlite3_update_hook() interface registers a callback function +** with the [database connection] identified by the first argument +** to be invoked whenever a row is updated, inserted or deleted. +** ^Any callback set by a previous call to this function +** for the same database connection is overridden. +** +** ^The second argument is a pointer to the function to invoke when a +** row is updated, inserted or deleted. +** ^The first argument to the callback is a copy of the third argument +** to sqlite3_update_hook(). +** ^The second callback argument is one of [SQLITE_INSERT], [SQLITE_DELETE], +** or [SQLITE_UPDATE], depending on the operation that caused the callback +** to be invoked. +** ^The third and fourth arguments to the callback contain pointers to the +** database and table name containing the affected row. +** ^The final callback parameter is the [rowid] of the row. +** ^In the case of an update, this is the [rowid] after the update takes place. +** +** ^(The update hook is not invoked when internal system tables are +** modified (i.e. sqlite_master and sqlite_sequence).)^ +** +** ^In the current implementation, the update hook +** is not invoked when duplication rows are deleted because of an +** [ON CONFLICT | ON CONFLICT REPLACE] clause. ^Nor is the update hook +** invoked when rows are deleted using the [truncate optimization]. +** The exceptions defined in this paragraph might change in a future +** release of SQLite. +** +** The update hook implementation must not do anything that will modify +** the database connection that invoked the update hook. Any actions +** to modify the database connection must be deferred until after the +** completion of the [sqlite3_step()] call that triggered the update hook. +** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their +** database connections for the meaning of "modify" in this paragraph. +** +** ^The sqlite3_update_hook(D,C,P) function +** returns the P argument from the previous call +** on the same [database connection] D, or NULL for +** the first call on D. +** +** See also the [sqlite3_commit_hook()] and [sqlite3_rollback_hook()] +** interfaces. +*/ +SQLITE_API void *sqlite3_update_hook( + sqlite3*, + void(*)(void *,int ,char const *,char const *,sqlite3_int64), + void* +); + +/* +** CAPI3REF: Enable Or Disable Shared Pager Cache +** KEYWORDS: {shared cache} +** +** ^(This routine enables or disables the sharing of the database cache +** and schema data structures between [database connection | connections] +** to the same database. Sharing is enabled if the argument is true +** and disabled if the argument is false.)^ +** +** ^Cache sharing is enabled and disabled for an entire process. +** This is a change as of SQLite version 3.5.0. In prior versions of SQLite, +** sharing was enabled or disabled for each thread separately. +** +** ^(The cache sharing mode set by this interface effects all subsequent +** calls to [sqlite3_open()], [sqlite3_open_v2()], and [sqlite3_open16()]. +** Existing database connections continue use the sharing mode +** that was in effect at the time they were opened.)^ +** +** ^(This routine returns [SQLITE_OK] if shared cache was enabled or disabled +** successfully. An [error code] is returned otherwise.)^ +** +** ^Shared cache is disabled by default. But this might change in +** future releases of SQLite. Applications that care about shared +** cache setting should set it explicitly. +** +** See Also: [SQLite Shared-Cache Mode] +*/ +SQLITE_API int sqlite3_enable_shared_cache(int); + +/* +** CAPI3REF: Attempt To Free Heap Memory +** +** ^The sqlite3_release_memory() interface attempts to free N bytes +** of heap memory by deallocating non-essential memory allocations +** held by the database library. Memory used to cache database +** pages to improve performance is an example of non-essential memory. +** ^sqlite3_release_memory() returns the number of bytes actually freed, +** which might be more or less than the amount requested. +** ^The sqlite3_release_memory() routine is a no-op returning zero +** if SQLite is not compiled with [SQLITE_ENABLE_MEMORY_MANAGEMENT]. +** +** See also: [sqlite3_db_release_memory()] +*/ +SQLITE_API int sqlite3_release_memory(int); + +/* +** CAPI3REF: Free Memory Used By A Database Connection +** +** ^The sqlite3_db_release_memory(D) interface attempts to free as much heap +** memory as possible from database connection D. Unlike the +** [sqlite3_release_memory()] interface, this interface is effect even +** when then [SQLITE_ENABLE_MEMORY_MANAGEMENT] compile-time option is +** omitted. +** +** See also: [sqlite3_release_memory()] +*/ +SQLITE_API int sqlite3_db_release_memory(sqlite3*); + +/* +** CAPI3REF: Impose A Limit On Heap Size +** +** ^The sqlite3_soft_heap_limit64() interface sets and/or queries the +** soft limit on the amount of heap memory that may be allocated by SQLite. +** ^SQLite strives to keep heap memory utilization below the soft heap +** limit by reducing the number of pages held in the page cache +** as heap memory usages approaches the limit. +** ^The soft heap limit is "soft" because even though SQLite strives to stay +** below the limit, it will exceed the limit rather than generate +** an [SQLITE_NOMEM] error. In other words, the soft heap limit +** is advisory only. +** +** ^The return value from sqlite3_soft_heap_limit64() is the size of +** the soft heap limit prior to the call, or negative in the case of an +** error. ^If the argument N is negative +** then no change is made to the soft heap limit. Hence, the current +** size of the soft heap limit can be determined by invoking +** sqlite3_soft_heap_limit64() with a negative argument. +** +** ^If the argument N is zero then the soft heap limit is disabled. +** +** ^(The soft heap limit is not enforced in the current implementation +** if one or more of following conditions are true: +** +**
      +**
    • The soft heap limit is set to zero. +**
    • Memory accounting is disabled using a combination of the +** [sqlite3_config]([SQLITE_CONFIG_MEMSTATUS],...) start-time option and +** the [SQLITE_DEFAULT_MEMSTATUS] compile-time option. +**
    • An alternative page cache implementation is specified using +** [sqlite3_config]([SQLITE_CONFIG_PCACHE2],...). +**
    • The page cache allocates from its own memory pool supplied +** by [sqlite3_config]([SQLITE_CONFIG_PAGECACHE],...) rather than +** from the heap. +**
    )^ +** +** Beginning with SQLite version 3.7.3, the soft heap limit is enforced +** regardless of whether or not the [SQLITE_ENABLE_MEMORY_MANAGEMENT] +** compile-time option is invoked. With [SQLITE_ENABLE_MEMORY_MANAGEMENT], +** the soft heap limit is enforced on every memory allocation. Without +** [SQLITE_ENABLE_MEMORY_MANAGEMENT], the soft heap limit is only enforced +** when memory is allocated by the page cache. Testing suggests that because +** the page cache is the predominate memory user in SQLite, most +** applications will achieve adequate soft heap limit enforcement without +** the use of [SQLITE_ENABLE_MEMORY_MANAGEMENT]. +** +** The circumstances under which SQLite will enforce the soft heap limit may +** changes in future releases of SQLite. +*/ +SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 N); + +/* +** CAPI3REF: Deprecated Soft Heap Limit Interface +** DEPRECATED +** +** This is a deprecated version of the [sqlite3_soft_heap_limit64()] +** interface. This routine is provided for historical compatibility +** only. All new applications should use the +** [sqlite3_soft_heap_limit64()] interface rather than this one. +*/ +SQLITE_API SQLITE_DEPRECATED void sqlite3_soft_heap_limit(int N); + + +/* +** CAPI3REF: Extract Metadata About A Column Of A Table +** +** ^This routine returns metadata about a specific column of a specific +** database table accessible using the [database connection] handle +** passed as the first function argument. +** +** ^The column is identified by the second, third and fourth parameters to +** this function. ^The second parameter is either the name of the database +** (i.e. "main", "temp", or an attached database) containing the specified +** table or NULL. ^If it is NULL, then all attached databases are searched +** for the table using the same algorithm used by the database engine to +** resolve unqualified table references. +** +** ^The third and fourth parameters to this function are the table and column +** name of the desired column, respectively. Neither of these parameters +** may be NULL. +** +** ^Metadata is returned by writing to the memory locations passed as the 5th +** and subsequent parameters to this function. ^Any of these arguments may be +** NULL, in which case the corresponding element of metadata is omitted. +** +** ^(
    +** +**
    Parameter Output
    Type
    Description +** +**
    5th const char* Data type +**
    6th const char* Name of default collation sequence +**
    7th int True if column has a NOT NULL constraint +**
    8th int True if column is part of the PRIMARY KEY +**
    9th int True if column is [AUTOINCREMENT] +**
    +**
    )^ +** +** ^The memory pointed to by the character pointers returned for the +** declaration type and collation sequence is valid only until the next +** call to any SQLite API function. +** +** ^If the specified table is actually a view, an [error code] is returned. +** +** ^If the specified column is "rowid", "oid" or "_rowid_" and an +** [INTEGER PRIMARY KEY] column has been explicitly declared, then the output +** parameters are set for the explicitly declared column. ^(If there is no +** explicitly declared [INTEGER PRIMARY KEY] column, then the output +** parameters are set as follows: +** +**
    +**     data type: "INTEGER"
    +**     collation sequence: "BINARY"
    +**     not null: 0
    +**     primary key: 1
    +**     auto increment: 0
    +** 
    )^ +** +** ^(This function may load one or more schemas from database files. If an +** error occurs during this process, or if the requested table or column +** cannot be found, an [error code] is returned and an error message left +** in the [database connection] (to be retrieved using sqlite3_errmsg()).)^ +** +** ^This API is only available if the library was compiled with the +** [SQLITE_ENABLE_COLUMN_METADATA] C-preprocessor symbol defined. +*/ +SQLITE_API int sqlite3_table_column_metadata( + sqlite3 *db, /* Connection handle */ + const char *zDbName, /* Database name or NULL */ + const char *zTableName, /* Table name */ + const char *zColumnName, /* Column name */ + char const **pzDataType, /* OUTPUT: Declared data type */ + char const **pzCollSeq, /* OUTPUT: Collation sequence name */ + int *pNotNull, /* OUTPUT: True if NOT NULL constraint exists */ + int *pPrimaryKey, /* OUTPUT: True if column part of PK */ + int *pAutoinc /* OUTPUT: True if column is auto-increment */ +); + +/* +** CAPI3REF: Load An Extension +** +** ^This interface loads an SQLite extension library from the named file. +** +** ^The sqlite3_load_extension() interface attempts to load an +** SQLite extension library contained in the file zFile. +** +** ^The entry point is zProc. +** ^zProc may be 0, in which case the name of the entry point +** defaults to "sqlite3_extension_init". +** ^The sqlite3_load_extension() interface returns +** [SQLITE_OK] on success and [SQLITE_ERROR] if something goes wrong. +** ^If an error occurs and pzErrMsg is not 0, then the +** [sqlite3_load_extension()] interface shall attempt to +** fill *pzErrMsg with error message text stored in memory +** obtained from [sqlite3_malloc()]. The calling function +** should free this memory by calling [sqlite3_free()]. +** +** ^Extension loading must be enabled using +** [sqlite3_enable_load_extension()] prior to calling this API, +** otherwise an error will be returned. +** +** See also the [load_extension() SQL function]. +*/ +SQLITE_API int sqlite3_load_extension( + sqlite3 *db, /* Load the extension into this database connection */ + const char *zFile, /* Name of the shared library containing extension */ + const char *zProc, /* Entry point. Derived from zFile if 0 */ + char **pzErrMsg /* Put error message here if not 0 */ +); + +/* +** CAPI3REF: Enable Or Disable Extension Loading +** +** ^So as not to open security holes in older applications that are +** unprepared to deal with extension loading, and as a means of disabling +** extension loading while evaluating user-entered SQL, the following API +** is provided to turn the [sqlite3_load_extension()] mechanism on and off. +** +** ^Extension loading is off by default. See ticket #1863. +** ^Call the sqlite3_enable_load_extension() routine with onoff==1 +** to turn extension loading on and call it with onoff==0 to turn +** it back off again. +*/ +SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff); + +/* +** CAPI3REF: Automatically Load Statically Linked Extensions +** +** ^This interface causes the xEntryPoint() function to be invoked for +** each new [database connection] that is created. The idea here is that +** xEntryPoint() is the entry point for a statically linked SQLite extension +** that is to be automatically loaded into all new database connections. +** +** ^(Even though the function prototype shows that xEntryPoint() takes +** no arguments and returns void, SQLite invokes xEntryPoint() with three +** arguments and expects and integer result as if the signature of the +** entry point where as follows: +** +**
    +**    int xEntryPoint(
    +**      sqlite3 *db,
    +**      const char **pzErrMsg,
    +**      const struct sqlite3_api_routines *pThunk
    +**    );
    +** 
    )^ +** +** If the xEntryPoint routine encounters an error, it should make *pzErrMsg +** point to an appropriate error message (obtained from [sqlite3_mprintf()]) +** and return an appropriate [error code]. ^SQLite ensures that *pzErrMsg +** is NULL before calling the xEntryPoint(). ^SQLite will invoke +** [sqlite3_free()] on *pzErrMsg after xEntryPoint() returns. ^If any +** xEntryPoint() returns an error, the [sqlite3_open()], [sqlite3_open16()], +** or [sqlite3_open_v2()] call that provoked the xEntryPoint() will fail. +** +** ^Calling sqlite3_auto_extension(X) with an entry point X that is already +** on the list of automatic extensions is a harmless no-op. ^No entry point +** will be called more than once for each database connection that is opened. +** +** See also: [sqlite3_reset_auto_extension()]. +*/ +SQLITE_API int sqlite3_auto_extension(void (*xEntryPoint)(void)); + +/* +** CAPI3REF: Reset Automatic Extension Loading +** +** ^This interface disables all automatic extensions previously +** registered using [sqlite3_auto_extension()]. +*/ +SQLITE_API void sqlite3_reset_auto_extension(void); + +/* +** The interface to the virtual-table mechanism is currently considered +** to be experimental. The interface might change in incompatible ways. +** If this is a problem for you, do not use the interface at this time. +** +** When the virtual-table mechanism stabilizes, we will declare the +** interface fixed, support it indefinitely, and remove this comment. +*/ + +/* +** Structures used by the virtual table interface +*/ +typedef struct sqlite3_vtab sqlite3_vtab; +typedef struct sqlite3_index_info sqlite3_index_info; +typedef struct sqlite3_vtab_cursor sqlite3_vtab_cursor; +typedef struct sqlite3_module sqlite3_module; + +/* +** CAPI3REF: Virtual Table Object +** KEYWORDS: sqlite3_module {virtual table module} +** +** This structure, sometimes called a "virtual table module", +** defines the implementation of a [virtual tables]. +** This structure consists mostly of methods for the module. +** +** ^A virtual table module is created by filling in a persistent +** instance of this structure and passing a pointer to that instance +** to [sqlite3_create_module()] or [sqlite3_create_module_v2()]. +** ^The registration remains valid until it is replaced by a different +** module or until the [database connection] closes. The content +** of this structure must not change while it is registered with +** any database connection. +*/ +struct sqlite3_module { + int iVersion; + int (*xCreate)(sqlite3*, void *pAux, + int argc, const char *const*argv, + sqlite3_vtab **ppVTab, char**); + int (*xConnect)(sqlite3*, void *pAux, + int argc, const char *const*argv, + sqlite3_vtab **ppVTab, char**); + int (*xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info*); + int (*xDisconnect)(sqlite3_vtab *pVTab); + int (*xDestroy)(sqlite3_vtab *pVTab); + int (*xOpen)(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor); + int (*xClose)(sqlite3_vtab_cursor*); + int (*xFilter)(sqlite3_vtab_cursor*, int idxNum, const char *idxStr, + int argc, sqlite3_value **argv); + int (*xNext)(sqlite3_vtab_cursor*); + int (*xEof)(sqlite3_vtab_cursor*); + int (*xColumn)(sqlite3_vtab_cursor*, sqlite3_context*, int); + int (*xRowid)(sqlite3_vtab_cursor*, sqlite3_int64 *pRowid); + int (*xUpdate)(sqlite3_vtab *, int, sqlite3_value **, sqlite3_int64 *); + int (*xBegin)(sqlite3_vtab *pVTab); + int (*xSync)(sqlite3_vtab *pVTab); + int (*xCommit)(sqlite3_vtab *pVTab); + int (*xRollback)(sqlite3_vtab *pVTab); + int (*xFindFunction)(sqlite3_vtab *pVtab, int nArg, const char *zName, + void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), + void **ppArg); + int (*xRename)(sqlite3_vtab *pVtab, const char *zNew); + /* The methods above are in version 1 of the sqlite_module object. Those + ** below are for version 2 and greater. */ + int (*xSavepoint)(sqlite3_vtab *pVTab, int); + int (*xRelease)(sqlite3_vtab *pVTab, int); + int (*xRollbackTo)(sqlite3_vtab *pVTab, int); +}; + +/* +** CAPI3REF: Virtual Table Indexing Information +** KEYWORDS: sqlite3_index_info +** +** The sqlite3_index_info structure and its substructures is used as part +** of the [virtual table] interface to +** pass information into and receive the reply from the [xBestIndex] +** method of a [virtual table module]. The fields under **Inputs** are the +** inputs to xBestIndex and are read-only. xBestIndex inserts its +** results into the **Outputs** fields. +** +** ^(The aConstraint[] array records WHERE clause constraints of the form: +** +**
    column OP expr
    +** +** where OP is =, <, <=, >, or >=.)^ ^(The particular operator is +** stored in aConstraint[].op using one of the +** [SQLITE_INDEX_CONSTRAINT_EQ | SQLITE_INDEX_CONSTRAINT_ values].)^ +** ^(The index of the column is stored in +** aConstraint[].iColumn.)^ ^(aConstraint[].usable is TRUE if the +** expr on the right-hand side can be evaluated (and thus the constraint +** is usable) and false if it cannot.)^ +** +** ^The optimizer automatically inverts terms of the form "expr OP column" +** and makes other simplifications to the WHERE clause in an attempt to +** get as many WHERE clause terms into the form shown above as possible. +** ^The aConstraint[] array only reports WHERE clause terms that are +** relevant to the particular virtual table being queried. +** +** ^Information about the ORDER BY clause is stored in aOrderBy[]. +** ^Each term of aOrderBy records a column of the ORDER BY clause. +** +** The [xBestIndex] method must fill aConstraintUsage[] with information +** about what parameters to pass to xFilter. ^If argvIndex>0 then +** the right-hand side of the corresponding aConstraint[] is evaluated +** and becomes the argvIndex-th entry in argv. ^(If aConstraintUsage[].omit +** is true, then the constraint is assumed to be fully handled by the +** virtual table and is not checked again by SQLite.)^ +** +** ^The idxNum and idxPtr values are recorded and passed into the +** [xFilter] method. +** ^[sqlite3_free()] is used to free idxPtr if and only if +** needToFreeIdxPtr is true. +** +** ^The orderByConsumed means that output from [xFilter]/[xNext] will occur in +** the correct order to satisfy the ORDER BY clause so that no separate +** sorting step is required. +** +** ^The estimatedCost value is an estimate of the cost of doing the +** particular lookup. A full scan of a table with N entries should have +** a cost of N. A binary search of a table of N entries should have a +** cost of approximately log(N). +*/ +struct sqlite3_index_info { + /* Inputs */ + int nConstraint; /* Number of entries in aConstraint */ + struct sqlite3_index_constraint { + int iColumn; /* Column on left-hand side of constraint */ + unsigned char op; /* Constraint operator */ + unsigned char usable; /* True if this constraint is usable */ + int iTermOffset; /* Used internally - xBestIndex should ignore */ + } *aConstraint; /* Table of WHERE clause constraints */ + int nOrderBy; /* Number of terms in the ORDER BY clause */ + struct sqlite3_index_orderby { + int iColumn; /* Column number */ + unsigned char desc; /* True for DESC. False for ASC. */ + } *aOrderBy; /* The ORDER BY clause */ + /* Outputs */ + struct sqlite3_index_constraint_usage { + int argvIndex; /* if >0, constraint is part of argv to xFilter */ + unsigned char omit; /* Do not code a test for this constraint */ + } *aConstraintUsage; + int idxNum; /* Number used to identify the index */ + char *idxStr; /* String, possibly obtained from sqlite3_malloc */ + int needToFreeIdxStr; /* Free idxStr using sqlite3_free() if true */ + int orderByConsumed; /* True if output is already ordered */ + double estimatedCost; /* Estimated cost of using this index */ +}; + +/* +** CAPI3REF: Virtual Table Constraint Operator Codes +** +** These macros defined the allowed values for the +** [sqlite3_index_info].aConstraint[].op field. Each value represents +** an operator that is part of a constraint term in the wHERE clause of +** a query that uses a [virtual table]. +*/ +#define SQLITE_INDEX_CONSTRAINT_EQ 2 +#define SQLITE_INDEX_CONSTRAINT_GT 4 +#define SQLITE_INDEX_CONSTRAINT_LE 8 +#define SQLITE_INDEX_CONSTRAINT_LT 16 +#define SQLITE_INDEX_CONSTRAINT_GE 32 +#define SQLITE_INDEX_CONSTRAINT_MATCH 64 + +/* +** CAPI3REF: Register A Virtual Table Implementation +** +** ^These routines are used to register a new [virtual table module] name. +** ^Module names must be registered before +** creating a new [virtual table] using the module and before using a +** preexisting [virtual table] for the module. +** +** ^The module name is registered on the [database connection] specified +** by the first parameter. ^The name of the module is given by the +** second parameter. ^The third parameter is a pointer to +** the implementation of the [virtual table module]. ^The fourth +** parameter is an arbitrary client data pointer that is passed through +** into the [xCreate] and [xConnect] methods of the virtual table module +** when a new virtual table is be being created or reinitialized. +** +** ^The sqlite3_create_module_v2() interface has a fifth parameter which +** is a pointer to a destructor for the pClientData. ^SQLite will +** invoke the destructor function (if it is not NULL) when SQLite +** no longer needs the pClientData pointer. ^The destructor will also +** be invoked if the call to sqlite3_create_module_v2() fails. +** ^The sqlite3_create_module() +** interface is equivalent to sqlite3_create_module_v2() with a NULL +** destructor. +*/ +SQLITE_API int sqlite3_create_module( + sqlite3 *db, /* SQLite connection to register module with */ + const char *zName, /* Name of the module */ + const sqlite3_module *p, /* Methods for the module */ + void *pClientData /* Client data for xCreate/xConnect */ +); +SQLITE_API int sqlite3_create_module_v2( + sqlite3 *db, /* SQLite connection to register module with */ + const char *zName, /* Name of the module */ + const sqlite3_module *p, /* Methods for the module */ + void *pClientData, /* Client data for xCreate/xConnect */ + void(*xDestroy)(void*) /* Module destructor function */ +); + +/* +** CAPI3REF: Virtual Table Instance Object +** KEYWORDS: sqlite3_vtab +** +** Every [virtual table module] implementation uses a subclass +** of this object to describe a particular instance +** of the [virtual table]. Each subclass will +** be tailored to the specific needs of the module implementation. +** The purpose of this superclass is to define certain fields that are +** common to all module implementations. +** +** ^Virtual tables methods can set an error message by assigning a +** string obtained from [sqlite3_mprintf()] to zErrMsg. The method should +** take care that any prior string is freed by a call to [sqlite3_free()] +** prior to assigning a new string to zErrMsg. ^After the error message +** is delivered up to the client application, the string will be automatically +** freed by sqlite3_free() and the zErrMsg field will be zeroed. +*/ +struct sqlite3_vtab { + const sqlite3_module *pModule; /* The module for this virtual table */ + int nRef; /* NO LONGER USED */ + char *zErrMsg; /* Error message from sqlite3_mprintf() */ + /* Virtual table implementations will typically add additional fields */ +}; + +/* +** CAPI3REF: Virtual Table Cursor Object +** KEYWORDS: sqlite3_vtab_cursor {virtual table cursor} +** +** Every [virtual table module] implementation uses a subclass of the +** following structure to describe cursors that point into the +** [virtual table] and are used +** to loop through the virtual table. Cursors are created using the +** [sqlite3_module.xOpen | xOpen] method of the module and are destroyed +** by the [sqlite3_module.xClose | xClose] method. Cursors are used +** by the [xFilter], [xNext], [xEof], [xColumn], and [xRowid] methods +** of the module. Each module implementation will define +** the content of a cursor structure to suit its own needs. +** +** This superclass exists in order to define fields of the cursor that +** are common to all implementations. +*/ +struct sqlite3_vtab_cursor { + sqlite3_vtab *pVtab; /* Virtual table of this cursor */ + /* Virtual table implementations will typically add additional fields */ +}; + +/* +** CAPI3REF: Declare The Schema Of A Virtual Table +** +** ^The [xCreate] and [xConnect] methods of a +** [virtual table module] call this interface +** to declare the format (the names and datatypes of the columns) of +** the virtual tables they implement. +*/ +SQLITE_API int sqlite3_declare_vtab(sqlite3*, const char *zSQL); + +/* +** CAPI3REF: Overload A Function For A Virtual Table +** +** ^(Virtual tables can provide alternative implementations of functions +** using the [xFindFunction] method of the [virtual table module]. +** But global versions of those functions +** must exist in order to be overloaded.)^ +** +** ^(This API makes sure a global version of a function with a particular +** name and number of parameters exists. If no such function exists +** before this API is called, a new function is created.)^ ^The implementation +** of the new function always causes an exception to be thrown. So +** the new function is not good for anything by itself. Its only +** purpose is to be a placeholder function that can be overloaded +** by a [virtual table]. +*/ +SQLITE_API int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg); + +/* +** The interface to the virtual-table mechanism defined above (back up +** to a comment remarkably similar to this one) is currently considered +** to be experimental. The interface might change in incompatible ways. +** If this is a problem for you, do not use the interface at this time. +** +** When the virtual-table mechanism stabilizes, we will declare the +** interface fixed, support it indefinitely, and remove this comment. +*/ + +/* +** CAPI3REF: A Handle To An Open BLOB +** KEYWORDS: {BLOB handle} {BLOB handles} +** +** An instance of this object represents an open BLOB on which +** [sqlite3_blob_open | incremental BLOB I/O] can be performed. +** ^Objects of this type are created by [sqlite3_blob_open()] +** and destroyed by [sqlite3_blob_close()]. +** ^The [sqlite3_blob_read()] and [sqlite3_blob_write()] interfaces +** can be used to read or write small subsections of the BLOB. +** ^The [sqlite3_blob_bytes()] interface returns the size of the BLOB in bytes. +*/ +typedef struct sqlite3_blob sqlite3_blob; + +/* +** CAPI3REF: Open A BLOB For Incremental I/O +** +** ^(This interfaces opens a [BLOB handle | handle] to the BLOB located +** in row iRow, column zColumn, table zTable in database zDb; +** in other words, the same BLOB that would be selected by: +** +**
    +**     SELECT zColumn FROM zDb.zTable WHERE [rowid] = iRow;
    +** 
    )^ +** +** ^If the flags parameter is non-zero, then the BLOB is opened for read +** and write access. ^If it is zero, the BLOB is opened for read access. +** ^It is not possible to open a column that is part of an index or primary +** key for writing. ^If [foreign key constraints] are enabled, it is +** not possible to open a column that is part of a [child key] for writing. +** +** ^Note that the database name is not the filename that contains +** the database but rather the symbolic name of the database that +** appears after the AS keyword when the database is connected using [ATTACH]. +** ^For the main database file, the database name is "main". +** ^For TEMP tables, the database name is "temp". +** +** ^(On success, [SQLITE_OK] is returned and the new [BLOB handle] is written +** to *ppBlob. Otherwise an [error code] is returned and *ppBlob is set +** to be a null pointer.)^ +** ^This function sets the [database connection] error code and message +** accessible via [sqlite3_errcode()] and [sqlite3_errmsg()] and related +** functions. ^Note that the *ppBlob variable is always initialized in a +** way that makes it safe to invoke [sqlite3_blob_close()] on *ppBlob +** regardless of the success or failure of this routine. +** +** ^(If the row that a BLOB handle points to is modified by an +** [UPDATE], [DELETE], or by [ON CONFLICT] side-effects +** then the BLOB handle is marked as "expired". +** This is true if any column of the row is changed, even a column +** other than the one the BLOB handle is open on.)^ +** ^Calls to [sqlite3_blob_read()] and [sqlite3_blob_write()] for +** an expired BLOB handle fail with a return code of [SQLITE_ABORT]. +** ^(Changes written into a BLOB prior to the BLOB expiring are not +** rolled back by the expiration of the BLOB. Such changes will eventually +** commit if the transaction continues to completion.)^ +** +** ^Use the [sqlite3_blob_bytes()] interface to determine the size of +** the opened blob. ^The size of a blob may not be changed by this +** interface. Use the [UPDATE] SQL command to change the size of a +** blob. +** +** ^The [sqlite3_bind_zeroblob()] and [sqlite3_result_zeroblob()] interfaces +** and the built-in [zeroblob] SQL function can be used, if desired, +** to create an empty, zero-filled blob in which to read or write using +** this interface. +** +** To avoid a resource leak, every open [BLOB handle] should eventually +** be released by a call to [sqlite3_blob_close()]. +*/ +SQLITE_API int sqlite3_blob_open( + sqlite3*, + const char *zDb, + const char *zTable, + const char *zColumn, + sqlite3_int64 iRow, + int flags, + sqlite3_blob **ppBlob +); + +/* +** CAPI3REF: Move a BLOB Handle to a New Row +** +** ^This function is used to move an existing blob handle so that it points +** to a different row of the same database table. ^The new row is identified +** by the rowid value passed as the second argument. Only the row can be +** changed. ^The database, table and column on which the blob handle is open +** remain the same. Moving an existing blob handle to a new row can be +** faster than closing the existing handle and opening a new one. +** +** ^(The new row must meet the same criteria as for [sqlite3_blob_open()] - +** it must exist and there must be either a blob or text value stored in +** the nominated column.)^ ^If the new row is not present in the table, or if +** it does not contain a blob or text value, or if another error occurs, an +** SQLite error code is returned and the blob handle is considered aborted. +** ^All subsequent calls to [sqlite3_blob_read()], [sqlite3_blob_write()] or +** [sqlite3_blob_reopen()] on an aborted blob handle immediately return +** SQLITE_ABORT. ^Calling [sqlite3_blob_bytes()] on an aborted blob handle +** always returns zero. +** +** ^This function sets the database handle error code and message. +*/ +SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64); + +/* +** CAPI3REF: Close A BLOB Handle +** +** ^Closes an open [BLOB handle]. +** +** ^Closing a BLOB shall cause the current transaction to commit +** if there are no other BLOBs, no pending prepared statements, and the +** database connection is in [autocommit mode]. +** ^If any writes were made to the BLOB, they might be held in cache +** until the close operation if they will fit. +** +** ^(Closing the BLOB often forces the changes +** out to disk and so if any I/O errors occur, they will likely occur +** at the time when the BLOB is closed. Any errors that occur during +** closing are reported as a non-zero return value.)^ +** +** ^(The BLOB is closed unconditionally. Even if this routine returns +** an error code, the BLOB is still closed.)^ +** +** ^Calling this routine with a null pointer (such as would be returned +** by a failed call to [sqlite3_blob_open()]) is a harmless no-op. +*/ +SQLITE_API int sqlite3_blob_close(sqlite3_blob *); + +/* +** CAPI3REF: Return The Size Of An Open BLOB +** +** ^Returns the size in bytes of the BLOB accessible via the +** successfully opened [BLOB handle] in its only argument. ^The +** incremental blob I/O routines can only read or overwriting existing +** blob content; they cannot change the size of a blob. +** +** This routine only works on a [BLOB handle] which has been created +** by a prior successful call to [sqlite3_blob_open()] and which has not +** been closed by [sqlite3_blob_close()]. Passing any other pointer in +** to this routine results in undefined and probably undesirable behavior. +*/ +SQLITE_API int sqlite3_blob_bytes(sqlite3_blob *); + +/* +** CAPI3REF: Read Data From A BLOB Incrementally +** +** ^(This function is used to read data from an open [BLOB handle] into a +** caller-supplied buffer. N bytes of data are copied into buffer Z +** from the open BLOB, starting at offset iOffset.)^ +** +** ^If offset iOffset is less than N bytes from the end of the BLOB, +** [SQLITE_ERROR] is returned and no data is read. ^If N or iOffset is +** less than zero, [SQLITE_ERROR] is returned and no data is read. +** ^The size of the blob (and hence the maximum value of N+iOffset) +** can be determined using the [sqlite3_blob_bytes()] interface. +** +** ^An attempt to read from an expired [BLOB handle] fails with an +** error code of [SQLITE_ABORT]. +** +** ^(On success, sqlite3_blob_read() returns SQLITE_OK. +** Otherwise, an [error code] or an [extended error code] is returned.)^ +** +** This routine only works on a [BLOB handle] which has been created +** by a prior successful call to [sqlite3_blob_open()] and which has not +** been closed by [sqlite3_blob_close()]. Passing any other pointer in +** to this routine results in undefined and probably undesirable behavior. +** +** See also: [sqlite3_blob_write()]. +*/ +SQLITE_API int sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset); + +/* +** CAPI3REF: Write Data Into A BLOB Incrementally +** +** ^This function is used to write data into an open [BLOB handle] from a +** caller-supplied buffer. ^N bytes of data are copied from the buffer Z +** into the open BLOB, starting at offset iOffset. +** +** ^If the [BLOB handle] passed as the first argument was not opened for +** writing (the flags parameter to [sqlite3_blob_open()] was zero), +** this function returns [SQLITE_READONLY]. +** +** ^This function may only modify the contents of the BLOB; it is +** not possible to increase the size of a BLOB using this API. +** ^If offset iOffset is less than N bytes from the end of the BLOB, +** [SQLITE_ERROR] is returned and no data is written. ^If N is +** less than zero [SQLITE_ERROR] is returned and no data is written. +** The size of the BLOB (and hence the maximum value of N+iOffset) +** can be determined using the [sqlite3_blob_bytes()] interface. +** +** ^An attempt to write to an expired [BLOB handle] fails with an +** error code of [SQLITE_ABORT]. ^Writes to the BLOB that occurred +** before the [BLOB handle] expired are not rolled back by the +** expiration of the handle, though of course those changes might +** have been overwritten by the statement that expired the BLOB handle +** or by other independent statements. +** +** ^(On success, sqlite3_blob_write() returns SQLITE_OK. +** Otherwise, an [error code] or an [extended error code] is returned.)^ +** +** This routine only works on a [BLOB handle] which has been created +** by a prior successful call to [sqlite3_blob_open()] and which has not +** been closed by [sqlite3_blob_close()]. Passing any other pointer in +** to this routine results in undefined and probably undesirable behavior. +** +** See also: [sqlite3_blob_read()]. +*/ +SQLITE_API int sqlite3_blob_write(sqlite3_blob *, const void *z, int n, int iOffset); + +/* +** CAPI3REF: Virtual File System Objects +** +** A virtual filesystem (VFS) is an [sqlite3_vfs] object +** that SQLite uses to interact +** with the underlying operating system. Most SQLite builds come with a +** single default VFS that is appropriate for the host computer. +** New VFSes can be registered and existing VFSes can be unregistered. +** The following interfaces are provided. +** +** ^The sqlite3_vfs_find() interface returns a pointer to a VFS given its name. +** ^Names are case sensitive. +** ^Names are zero-terminated UTF-8 strings. +** ^If there is no match, a NULL pointer is returned. +** ^If zVfsName is NULL then the default VFS is returned. +** +** ^New VFSes are registered with sqlite3_vfs_register(). +** ^Each new VFS becomes the default VFS if the makeDflt flag is set. +** ^The same VFS can be registered multiple times without injury. +** ^To make an existing VFS into the default VFS, register it again +** with the makeDflt flag set. If two different VFSes with the +** same name are registered, the behavior is undefined. If a +** VFS is registered with a name that is NULL or an empty string, +** then the behavior is undefined. +** +** ^Unregister a VFS with the sqlite3_vfs_unregister() interface. +** ^(If the default VFS is unregistered, another VFS is chosen as +** the default. The choice for the new VFS is arbitrary.)^ +*/ +SQLITE_API sqlite3_vfs *sqlite3_vfs_find(const char *zVfsName); +SQLITE_API int sqlite3_vfs_register(sqlite3_vfs*, int makeDflt); +SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs*); + +/* +** CAPI3REF: Mutexes +** +** The SQLite core uses these routines for thread +** synchronization. Though they are intended for internal +** use by SQLite, code that links against SQLite is +** permitted to use any of these routines. +** +** The SQLite source code contains multiple implementations +** of these mutex routines. An appropriate implementation +** is selected automatically at compile-time. ^(The following +** implementations are available in the SQLite core: +** +**
      +**
    • SQLITE_MUTEX_OS2 +**
    • SQLITE_MUTEX_PTHREADS +**
    • SQLITE_MUTEX_W32 +**
    • SQLITE_MUTEX_NOOP +**
    )^ +** +** ^The SQLITE_MUTEX_NOOP implementation is a set of routines +** that does no real locking and is appropriate for use in +** a single-threaded application. ^The SQLITE_MUTEX_OS2, +** SQLITE_MUTEX_PTHREADS, and SQLITE_MUTEX_W32 implementations +** are appropriate for use on OS/2, Unix, and Windows. +** +** ^(If SQLite is compiled with the SQLITE_MUTEX_APPDEF preprocessor +** macro defined (with "-DSQLITE_MUTEX_APPDEF=1"), then no mutex +** implementation is included with the library. In this case the +** application must supply a custom mutex implementation using the +** [SQLITE_CONFIG_MUTEX] option of the sqlite3_config() function +** before calling sqlite3_initialize() or any other public sqlite3_ +** function that calls sqlite3_initialize().)^ +** +** ^The sqlite3_mutex_alloc() routine allocates a new +** mutex and returns a pointer to it. ^If it returns NULL +** that means that a mutex could not be allocated. ^SQLite +** will unwind its stack and return an error. ^(The argument +** to sqlite3_mutex_alloc() is one of these integer constants: +** +**
      +**
    • SQLITE_MUTEX_FAST +**
    • SQLITE_MUTEX_RECURSIVE +**
    • SQLITE_MUTEX_STATIC_MASTER +**
    • SQLITE_MUTEX_STATIC_MEM +**
    • SQLITE_MUTEX_STATIC_MEM2 +**
    • SQLITE_MUTEX_STATIC_PRNG +**
    • SQLITE_MUTEX_STATIC_LRU +**
    • SQLITE_MUTEX_STATIC_LRU2 +**
    )^ +** +** ^The first two constants (SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE) +** cause sqlite3_mutex_alloc() to create +** a new mutex. ^The new mutex is recursive when SQLITE_MUTEX_RECURSIVE +** is used but not necessarily so when SQLITE_MUTEX_FAST is used. +** The mutex implementation does not need to make a distinction +** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does +** not want to. ^SQLite will only request a recursive mutex in +** cases where it really needs one. ^If a faster non-recursive mutex +** implementation is available on the host platform, the mutex subsystem +** might return such a mutex in response to SQLITE_MUTEX_FAST. +** +** ^The other allowed parameters to sqlite3_mutex_alloc() (anything other +** than SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE) each return +** a pointer to a static preexisting mutex. ^Six static mutexes are +** used by the current version of SQLite. Future versions of SQLite +** may add additional static mutexes. Static mutexes are for internal +** use by SQLite only. Applications that use SQLite mutexes should +** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or +** SQLITE_MUTEX_RECURSIVE. +** +** ^Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST +** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc() +** returns a different mutex on every call. ^But for the static +** mutex types, the same mutex is returned on every call that has +** the same type number. +** +** ^The sqlite3_mutex_free() routine deallocates a previously +** allocated dynamic mutex. ^SQLite is careful to deallocate every +** dynamic mutex that it allocates. The dynamic mutexes must not be in +** use when they are deallocated. Attempting to deallocate a static +** mutex results in undefined behavior. ^SQLite never deallocates +** a static mutex. +** +** ^The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt +** to enter a mutex. ^If another thread is already within the mutex, +** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return +** SQLITE_BUSY. ^The sqlite3_mutex_try() interface returns [SQLITE_OK] +** upon successful entry. ^(Mutexes created using +** SQLITE_MUTEX_RECURSIVE can be entered multiple times by the same thread. +** In such cases the, +** mutex must be exited an equal number of times before another thread +** can enter.)^ ^(If the same thread tries to enter any other +** kind of mutex more than once, the behavior is undefined. +** SQLite will never exhibit +** such behavior in its own use of mutexes.)^ +** +** ^(Some systems (for example, Windows 95) do not support the operation +** implemented by sqlite3_mutex_try(). On those systems, sqlite3_mutex_try() +** will always return SQLITE_BUSY. The SQLite core only ever uses +** sqlite3_mutex_try() as an optimization so this is acceptable behavior.)^ +** +** ^The sqlite3_mutex_leave() routine exits a mutex that was +** previously entered by the same thread. ^(The behavior +** is undefined if the mutex is not currently entered by the +** calling thread or is not currently allocated. SQLite will +** never do either.)^ +** +** ^If the argument to sqlite3_mutex_enter(), sqlite3_mutex_try(), or +** sqlite3_mutex_leave() is a NULL pointer, then all three routines +** behave as no-ops. +** +** See also: [sqlite3_mutex_held()] and [sqlite3_mutex_notheld()]. +*/ +SQLITE_API sqlite3_mutex *sqlite3_mutex_alloc(int); +SQLITE_API void sqlite3_mutex_free(sqlite3_mutex*); +SQLITE_API void sqlite3_mutex_enter(sqlite3_mutex*); +SQLITE_API int sqlite3_mutex_try(sqlite3_mutex*); +SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex*); + +/* +** CAPI3REF: Mutex Methods Object +** +** An instance of this structure defines the low-level routines +** used to allocate and use mutexes. +** +** Usually, the default mutex implementations provided by SQLite are +** sufficient, however the user has the option of substituting a custom +** implementation for specialized deployments or systems for which SQLite +** does not provide a suitable implementation. In this case, the user +** creates and populates an instance of this structure to pass +** to sqlite3_config() along with the [SQLITE_CONFIG_MUTEX] option. +** Additionally, an instance of this structure can be used as an +** output variable when querying the system for the current mutex +** implementation, using the [SQLITE_CONFIG_GETMUTEX] option. +** +** ^The xMutexInit method defined by this structure is invoked as +** part of system initialization by the sqlite3_initialize() function. +** ^The xMutexInit routine is called by SQLite exactly once for each +** effective call to [sqlite3_initialize()]. +** +** ^The xMutexEnd method defined by this structure is invoked as +** part of system shutdown by the sqlite3_shutdown() function. The +** implementation of this method is expected to release all outstanding +** resources obtained by the mutex methods implementation, especially +** those obtained by the xMutexInit method. ^The xMutexEnd() +** interface is invoked exactly once for each call to [sqlite3_shutdown()]. +** +** ^(The remaining seven methods defined by this structure (xMutexAlloc, +** xMutexFree, xMutexEnter, xMutexTry, xMutexLeave, xMutexHeld and +** xMutexNotheld) implement the following interfaces (respectively): +** +**
      +**
    • [sqlite3_mutex_alloc()]
    • +**
    • [sqlite3_mutex_free()]
    • +**
    • [sqlite3_mutex_enter()]
    • +**
    • [sqlite3_mutex_try()]
    • +**
    • [sqlite3_mutex_leave()]
    • +**
    • [sqlite3_mutex_held()]
    • +**
    • [sqlite3_mutex_notheld()]
    • +**
    )^ +** +** The only difference is that the public sqlite3_XXX functions enumerated +** above silently ignore any invocations that pass a NULL pointer instead +** of a valid mutex handle. The implementations of the methods defined +** by this structure are not required to handle this case, the results +** of passing a NULL pointer instead of a valid mutex handle are undefined +** (i.e. it is acceptable to provide an implementation that segfaults if +** it is passed a NULL pointer). +** +** The xMutexInit() method must be threadsafe. ^It must be harmless to +** invoke xMutexInit() multiple times within the same process and without +** intervening calls to xMutexEnd(). Second and subsequent calls to +** xMutexInit() must be no-ops. +** +** ^xMutexInit() must not use SQLite memory allocation ([sqlite3_malloc()] +** and its associates). ^Similarly, xMutexAlloc() must not use SQLite memory +** allocation for a static mutex. ^However xMutexAlloc() may use SQLite +** memory allocation for a fast or recursive mutex. +** +** ^SQLite will invoke the xMutexEnd() method when [sqlite3_shutdown()] is +** called, but only if the prior call to xMutexInit returned SQLITE_OK. +** If xMutexInit fails in any way, it is expected to clean up after itself +** prior to returning. +*/ +typedef struct sqlite3_mutex_methods sqlite3_mutex_methods; +struct sqlite3_mutex_methods { + int (*xMutexInit)(void); + int (*xMutexEnd)(void); + sqlite3_mutex *(*xMutexAlloc)(int); + void (*xMutexFree)(sqlite3_mutex *); + void (*xMutexEnter)(sqlite3_mutex *); + int (*xMutexTry)(sqlite3_mutex *); + void (*xMutexLeave)(sqlite3_mutex *); + int (*xMutexHeld)(sqlite3_mutex *); + int (*xMutexNotheld)(sqlite3_mutex *); +}; + +/* +** CAPI3REF: Mutex Verification Routines +** +** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routines +** are intended for use inside assert() statements. ^The SQLite core +** never uses these routines except inside an assert() and applications +** are advised to follow the lead of the core. ^The SQLite core only +** provides implementations for these routines when it is compiled +** with the SQLITE_DEBUG flag. ^External mutex implementations +** are only required to provide these routines if SQLITE_DEBUG is +** defined and if NDEBUG is not defined. +** +** ^These routines should return true if the mutex in their argument +** is held or not held, respectively, by the calling thread. +** +** ^The implementation is not required to provide versions of these +** routines that actually work. If the implementation does not provide working +** versions of these routines, it should at least provide stubs that always +** return true so that one does not get spurious assertion failures. +** +** ^If the argument to sqlite3_mutex_held() is a NULL pointer then +** the routine should return 1. This seems counter-intuitive since +** clearly the mutex cannot be held if it does not exist. But +** the reason the mutex does not exist is because the build is not +** using mutexes. And we do not want the assert() containing the +** call to sqlite3_mutex_held() to fail, so a non-zero return is +** the appropriate thing to do. ^The sqlite3_mutex_notheld() +** interface should also return 1 when given a NULL pointer. +*/ +#ifndef NDEBUG +SQLITE_API int sqlite3_mutex_held(sqlite3_mutex*); +SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex*); +#endif + +/* +** CAPI3REF: Mutex Types +** +** The [sqlite3_mutex_alloc()] interface takes a single argument +** which is one of these integer constants. +** +** The set of static mutexes may change from one SQLite release to the +** next. Applications that override the built-in mutex logic must be +** prepared to accommodate additional static mutexes. +*/ +#define SQLITE_MUTEX_FAST 0 +#define SQLITE_MUTEX_RECURSIVE 1 +#define SQLITE_MUTEX_STATIC_MASTER 2 +#define SQLITE_MUTEX_STATIC_MEM 3 /* sqlite3_malloc() */ +#define SQLITE_MUTEX_STATIC_MEM2 4 /* NOT USED */ +#define SQLITE_MUTEX_STATIC_OPEN 4 /* sqlite3BtreeOpen() */ +#define SQLITE_MUTEX_STATIC_PRNG 5 /* sqlite3_random() */ +#define SQLITE_MUTEX_STATIC_LRU 6 /* lru page list */ +#define SQLITE_MUTEX_STATIC_LRU2 7 /* NOT USED */ +#define SQLITE_MUTEX_STATIC_PMEM 7 /* sqlite3PageMalloc() */ + +/* +** CAPI3REF: Retrieve the mutex for a database connection +** +** ^This interface returns a pointer the [sqlite3_mutex] object that +** serializes access to the [database connection] given in the argument +** when the [threading mode] is Serialized. +** ^If the [threading mode] is Single-thread or Multi-thread then this +** routine returns a NULL pointer. +*/ +SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3*); + +/* +** CAPI3REF: Low-Level Control Of Database Files +** +** ^The [sqlite3_file_control()] interface makes a direct call to the +** xFileControl method for the [sqlite3_io_methods] object associated +** with a particular database identified by the second argument. ^The +** name of the database is "main" for the main database or "temp" for the +** TEMP database, or the name that appears after the AS keyword for +** databases that are added using the [ATTACH] SQL command. +** ^A NULL pointer can be used in place of "main" to refer to the +** main database file. +** ^The third and fourth parameters to this routine +** are passed directly through to the second and third parameters of +** the xFileControl method. ^The return value of the xFileControl +** method becomes the return value of this routine. +** +** ^The SQLITE_FCNTL_FILE_POINTER value for the op parameter causes +** a pointer to the underlying [sqlite3_file] object to be written into +** the space pointed to by the 4th parameter. ^The SQLITE_FCNTL_FILE_POINTER +** case is a short-circuit path which does not actually invoke the +** underlying sqlite3_io_methods.xFileControl method. +** +** ^If the second parameter (zDbName) does not match the name of any +** open database file, then SQLITE_ERROR is returned. ^This error +** code is not remembered and will not be recalled by [sqlite3_errcode()] +** or [sqlite3_errmsg()]. The underlying xFileControl method might +** also return SQLITE_ERROR. There is no way to distinguish between +** an incorrect zDbName and an SQLITE_ERROR return from the underlying +** xFileControl method. +** +** See also: [SQLITE_FCNTL_LOCKSTATE] +*/ +SQLITE_API int sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*); + +/* +** CAPI3REF: Testing Interface +** +** ^The sqlite3_test_control() interface is used to read out internal +** state of SQLite and to inject faults into SQLite for testing +** purposes. ^The first parameter is an operation code that determines +** the number, meaning, and operation of all subsequent parameters. +** +** This interface is not for use by applications. It exists solely +** for verifying the correct operation of the SQLite library. Depending +** on how the SQLite library is compiled, this interface might not exist. +** +** The details of the operation codes, their meanings, the parameters +** they take, and what they do are all subject to change without notice. +** Unlike most of the SQLite API, this function is not guaranteed to +** operate consistently from one release to the next. +*/ +SQLITE_API int sqlite3_test_control(int op, ...); + +/* +** CAPI3REF: Testing Interface Operation Codes +** +** These constants are the valid operation code parameters used +** as the first argument to [sqlite3_test_control()]. +** +** These parameters and their meanings are subject to change +** without notice. These values are for testing purposes only. +** Applications should not use any of these parameters or the +** [sqlite3_test_control()] interface. +*/ +#define SQLITE_TESTCTRL_FIRST 5 +#define SQLITE_TESTCTRL_PRNG_SAVE 5 +#define SQLITE_TESTCTRL_PRNG_RESTORE 6 +#define SQLITE_TESTCTRL_PRNG_RESET 7 +#define SQLITE_TESTCTRL_BITVEC_TEST 8 +#define SQLITE_TESTCTRL_FAULT_INSTALL 9 +#define SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS 10 +#define SQLITE_TESTCTRL_PENDING_BYTE 11 +#define SQLITE_TESTCTRL_ASSERT 12 +#define SQLITE_TESTCTRL_ALWAYS 13 +#define SQLITE_TESTCTRL_RESERVE 14 +#define SQLITE_TESTCTRL_OPTIMIZATIONS 15 +#define SQLITE_TESTCTRL_ISKEYWORD 16 +#define SQLITE_TESTCTRL_SCRATCHMALLOC 17 +#define SQLITE_TESTCTRL_LOCALTIME_FAULT 18 +#define SQLITE_TESTCTRL_EXPLAIN_STMT 19 +#define SQLITE_TESTCTRL_LAST 19 + +/* +** CAPI3REF: SQLite Runtime Status +** +** ^This interface is used to retrieve runtime status information +** about the performance of SQLite, and optionally to reset various +** highwater marks. ^The first argument is an integer code for +** the specific parameter to measure. ^(Recognized integer codes +** are of the form [status parameters | SQLITE_STATUS_...].)^ +** ^The current value of the parameter is returned into *pCurrent. +** ^The highest recorded value is returned in *pHighwater. ^If the +** resetFlag is true, then the highest record value is reset after +** *pHighwater is written. ^(Some parameters do not record the highest +** value. For those parameters +** nothing is written into *pHighwater and the resetFlag is ignored.)^ +** ^(Other parameters record only the highwater mark and not the current +** value. For these latter parameters nothing is written into *pCurrent.)^ +** +** ^The sqlite3_status() routine returns SQLITE_OK on success and a +** non-zero [error code] on failure. +** +** This routine is threadsafe but is not atomic. This routine can be +** called while other threads are running the same or different SQLite +** interfaces. However the values returned in *pCurrent and +** *pHighwater reflect the status of SQLite at different points in time +** and it is possible that another thread might change the parameter +** in between the times when *pCurrent and *pHighwater are written. +** +** See also: [sqlite3_db_status()] +*/ +SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag); + + +/* +** CAPI3REF: Status Parameters +** KEYWORDS: {status parameters} +** +** These integer constants designate various run-time status parameters +** that can be returned by [sqlite3_status()]. +** +**
    +** [[SQLITE_STATUS_MEMORY_USED]] ^(
    SQLITE_STATUS_MEMORY_USED
    +**
    This parameter is the current amount of memory checked out +** using [sqlite3_malloc()], either directly or indirectly. The +** figure includes calls made to [sqlite3_malloc()] by the application +** and internal memory usage by the SQLite library. Scratch memory +** controlled by [SQLITE_CONFIG_SCRATCH] and auxiliary page-cache +** memory controlled by [SQLITE_CONFIG_PAGECACHE] is not included in +** this parameter. The amount returned is the sum of the allocation +** sizes as reported by the xSize method in [sqlite3_mem_methods].
    )^ +** +** [[SQLITE_STATUS_MALLOC_SIZE]] ^(
    SQLITE_STATUS_MALLOC_SIZE
    +**
    This parameter records the largest memory allocation request +** handed to [sqlite3_malloc()] or [sqlite3_realloc()] (or their +** internal equivalents). Only the value returned in the +** *pHighwater parameter to [sqlite3_status()] is of interest. +** The value written into the *pCurrent parameter is undefined.
    )^ +** +** [[SQLITE_STATUS_MALLOC_COUNT]] ^(
    SQLITE_STATUS_MALLOC_COUNT
    +**
    This parameter records the number of separate memory allocations +** currently checked out.
    )^ +** +** [[SQLITE_STATUS_PAGECACHE_USED]] ^(
    SQLITE_STATUS_PAGECACHE_USED
    +**
    This parameter returns the number of pages used out of the +** [pagecache memory allocator] that was configured using +** [SQLITE_CONFIG_PAGECACHE]. The +** value returned is in pages, not in bytes.
    )^ +** +** [[SQLITE_STATUS_PAGECACHE_OVERFLOW]] +** ^(
    SQLITE_STATUS_PAGECACHE_OVERFLOW
    +**
    This parameter returns the number of bytes of page cache +** allocation which could not be satisfied by the [SQLITE_CONFIG_PAGECACHE] +** buffer and where forced to overflow to [sqlite3_malloc()]. The +** returned value includes allocations that overflowed because they +** where too large (they were larger than the "sz" parameter to +** [SQLITE_CONFIG_PAGECACHE]) and allocations that overflowed because +** no space was left in the page cache.
    )^ +** +** [[SQLITE_STATUS_PAGECACHE_SIZE]] ^(
    SQLITE_STATUS_PAGECACHE_SIZE
    +**
    This parameter records the largest memory allocation request +** handed to [pagecache memory allocator]. Only the value returned in the +** *pHighwater parameter to [sqlite3_status()] is of interest. +** The value written into the *pCurrent parameter is undefined.
    )^ +** +** [[SQLITE_STATUS_SCRATCH_USED]] ^(
    SQLITE_STATUS_SCRATCH_USED
    +**
    This parameter returns the number of allocations used out of the +** [scratch memory allocator] configured using +** [SQLITE_CONFIG_SCRATCH]. The value returned is in allocations, not +** in bytes. Since a single thread may only have one scratch allocation +** outstanding at time, this parameter also reports the number of threads +** using scratch memory at the same time.
    )^ +** +** [[SQLITE_STATUS_SCRATCH_OVERFLOW]] ^(
    SQLITE_STATUS_SCRATCH_OVERFLOW
    +**
    This parameter returns the number of bytes of scratch memory +** allocation which could not be satisfied by the [SQLITE_CONFIG_SCRATCH] +** buffer and where forced to overflow to [sqlite3_malloc()]. The values +** returned include overflows because the requested allocation was too +** larger (that is, because the requested allocation was larger than the +** "sz" parameter to [SQLITE_CONFIG_SCRATCH]) and because no scratch buffer +** slots were available. +**
    )^ +** +** [[SQLITE_STATUS_SCRATCH_SIZE]] ^(
    SQLITE_STATUS_SCRATCH_SIZE
    +**
    This parameter records the largest memory allocation request +** handed to [scratch memory allocator]. Only the value returned in the +** *pHighwater parameter to [sqlite3_status()] is of interest. +** The value written into the *pCurrent parameter is undefined.
    )^ +** +** [[SQLITE_STATUS_PARSER_STACK]] ^(
    SQLITE_STATUS_PARSER_STACK
    +**
    This parameter records the deepest parser stack. It is only +** meaningful if SQLite is compiled with [YYTRACKMAXSTACKDEPTH].
    )^ +**
    +** +** New status parameters may be added from time to time. +*/ +#define SQLITE_STATUS_MEMORY_USED 0 +#define SQLITE_STATUS_PAGECACHE_USED 1 +#define SQLITE_STATUS_PAGECACHE_OVERFLOW 2 +#define SQLITE_STATUS_SCRATCH_USED 3 +#define SQLITE_STATUS_SCRATCH_OVERFLOW 4 +#define SQLITE_STATUS_MALLOC_SIZE 5 +#define SQLITE_STATUS_PARSER_STACK 6 +#define SQLITE_STATUS_PAGECACHE_SIZE 7 +#define SQLITE_STATUS_SCRATCH_SIZE 8 +#define SQLITE_STATUS_MALLOC_COUNT 9 + +/* +** CAPI3REF: Database Connection Status +** +** ^This interface is used to retrieve runtime status information +** about a single [database connection]. ^The first argument is the +** database connection object to be interrogated. ^The second argument +** is an integer constant, taken from the set of +** [SQLITE_DBSTATUS options], that +** determines the parameter to interrogate. The set of +** [SQLITE_DBSTATUS options] is likely +** to grow in future releases of SQLite. +** +** ^The current value of the requested parameter is written into *pCur +** and the highest instantaneous value is written into *pHiwtr. ^If +** the resetFlg is true, then the highest instantaneous value is +** reset back down to the current value. +** +** ^The sqlite3_db_status() routine returns SQLITE_OK on success and a +** non-zero [error code] on failure. +** +** See also: [sqlite3_status()] and [sqlite3_stmt_status()]. +*/ +SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg); + +/* +** CAPI3REF: Status Parameters for database connections +** KEYWORDS: {SQLITE_DBSTATUS options} +** +** These constants are the available integer "verbs" that can be passed as +** the second argument to the [sqlite3_db_status()] interface. +** +** New verbs may be added in future releases of SQLite. Existing verbs +** might be discontinued. Applications should check the return code from +** [sqlite3_db_status()] to make sure that the call worked. +** The [sqlite3_db_status()] interface will return a non-zero error code +** if a discontinued or unsupported verb is invoked. +** +**
    +** [[SQLITE_DBSTATUS_LOOKASIDE_USED]] ^(
    SQLITE_DBSTATUS_LOOKASIDE_USED
    +**
    This parameter returns the number of lookaside memory slots currently +** checked out.
    )^ +** +** [[SQLITE_DBSTATUS_LOOKASIDE_HIT]] ^(
    SQLITE_DBSTATUS_LOOKASIDE_HIT
    +**
    This parameter returns the number malloc attempts that were +** satisfied using lookaside memory. Only the high-water value is meaningful; +** the current value is always zero.)^ +** +** [[SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE]] +** ^(
    SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE
    +**
    This parameter returns the number malloc attempts that might have +** been satisfied using lookaside memory but failed due to the amount of +** memory requested being larger than the lookaside slot size. +** Only the high-water value is meaningful; +** the current value is always zero.)^ +** +** [[SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL]] +** ^(
    SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL
    +**
    This parameter returns the number malloc attempts that might have +** been satisfied using lookaside memory but failed due to all lookaside +** memory already being in use. +** Only the high-water value is meaningful; +** the current value is always zero.)^ +** +** [[SQLITE_DBSTATUS_CACHE_USED]] ^(
    SQLITE_DBSTATUS_CACHE_USED
    +**
    This parameter returns the approximate number of of bytes of heap +** memory used by all pager caches associated with the database connection.)^ +** ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_USED is always 0. +** +** [[SQLITE_DBSTATUS_SCHEMA_USED]] ^(
    SQLITE_DBSTATUS_SCHEMA_USED
    +**
    This parameter returns the approximate number of of bytes of heap +** memory used to store the schema for all databases associated +** with the connection - main, temp, and any [ATTACH]-ed databases.)^ +** ^The full amount of memory used by the schemas is reported, even if the +** schema memory is shared with other database connections due to +** [shared cache mode] being enabled. +** ^The highwater mark associated with SQLITE_DBSTATUS_SCHEMA_USED is always 0. +** +** [[SQLITE_DBSTATUS_STMT_USED]] ^(
    SQLITE_DBSTATUS_STMT_USED
    +**
    This parameter returns the approximate number of of bytes of heap +** and lookaside memory used by all prepared statements associated with +** the database connection.)^ +** ^The highwater mark associated with SQLITE_DBSTATUS_STMT_USED is always 0. +**
    +** +** [[SQLITE_DBSTATUS_CACHE_HIT]] ^(
    SQLITE_DBSTATUS_CACHE_HIT
    +**
    This parameter returns the number of pager cache hits that have +** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_HIT +** is always 0. +**
    +** +** [[SQLITE_DBSTATUS_CACHE_MISS]] ^(
    SQLITE_DBSTATUS_CACHE_MISS
    +**
    This parameter returns the number of pager cache misses that have +** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_MISS +** is always 0. +**
    +**
    +*/ +#define SQLITE_DBSTATUS_LOOKASIDE_USED 0 +#define SQLITE_DBSTATUS_CACHE_USED 1 +#define SQLITE_DBSTATUS_SCHEMA_USED 2 +#define SQLITE_DBSTATUS_STMT_USED 3 +#define SQLITE_DBSTATUS_LOOKASIDE_HIT 4 +#define SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE 5 +#define SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL 6 +#define SQLITE_DBSTATUS_CACHE_HIT 7 +#define SQLITE_DBSTATUS_CACHE_MISS 8 +#define SQLITE_DBSTATUS_MAX 8 /* Largest defined DBSTATUS */ + + +/* +** CAPI3REF: Prepared Statement Status +** +** ^(Each prepared statement maintains various +** [SQLITE_STMTSTATUS counters] that measure the number +** of times it has performed specific operations.)^ These counters can +** be used to monitor the performance characteristics of the prepared +** statements. For example, if the number of table steps greatly exceeds +** the number of table searches or result rows, that would tend to indicate +** that the prepared statement is using a full table scan rather than +** an index. +** +** ^(This interface is used to retrieve and reset counter values from +** a [prepared statement]. The first argument is the prepared statement +** object to be interrogated. The second argument +** is an integer code for a specific [SQLITE_STMTSTATUS counter] +** to be interrogated.)^ +** ^The current value of the requested counter is returned. +** ^If the resetFlg is true, then the counter is reset to zero after this +** interface call returns. +** +** See also: [sqlite3_status()] and [sqlite3_db_status()]. +*/ +SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg); + +/* +** CAPI3REF: Status Parameters for prepared statements +** KEYWORDS: {SQLITE_STMTSTATUS counter} {SQLITE_STMTSTATUS counters} +** +** These preprocessor macros define integer codes that name counter +** values associated with the [sqlite3_stmt_status()] interface. +** The meanings of the various counters are as follows: +** +**
    +** [[SQLITE_STMTSTATUS_FULLSCAN_STEP]]
    SQLITE_STMTSTATUS_FULLSCAN_STEP
    +**
    ^This is the number of times that SQLite has stepped forward in +** a table as part of a full table scan. Large numbers for this counter +** may indicate opportunities for performance improvement through +** careful use of indices.
    +** +** [[SQLITE_STMTSTATUS_SORT]]
    SQLITE_STMTSTATUS_SORT
    +**
    ^This is the number of sort operations that have occurred. +** A non-zero value in this counter may indicate an opportunity to +** improvement performance through careful use of indices.
    +** +** [[SQLITE_STMTSTATUS_AUTOINDEX]]
    SQLITE_STMTSTATUS_AUTOINDEX
    +**
    ^This is the number of rows inserted into transient indices that +** were created automatically in order to help joins run faster. +** A non-zero value in this counter may indicate an opportunity to +** improvement performance by adding permanent indices that do not +** need to be reinitialized each time the statement is run.
    +**
    +*/ +#define SQLITE_STMTSTATUS_FULLSCAN_STEP 1 +#define SQLITE_STMTSTATUS_SORT 2 +#define SQLITE_STMTSTATUS_AUTOINDEX 3 + +/* +** CAPI3REF: Custom Page Cache Object +** +** The sqlite3_pcache type is opaque. It is implemented by +** the pluggable module. The SQLite core has no knowledge of +** its size or internal structure and never deals with the +** sqlite3_pcache object except by holding and passing pointers +** to the object. +** +** See [sqlite3_pcache_methods2] for additional information. +*/ +typedef struct sqlite3_pcache sqlite3_pcache; + +/* +** CAPI3REF: Custom Page Cache Object +** +** The sqlite3_pcache_page object represents a single page in the +** page cache. The page cache will allocate instances of this +** object. Various methods of the page cache use pointers to instances +** of this object as parameters or as their return value. +** +** See [sqlite3_pcache_methods2] for additional information. +*/ +typedef struct sqlite3_pcache_page sqlite3_pcache_page; +struct sqlite3_pcache_page { + void *pBuf; /* The content of the page */ + void *pExtra; /* Extra information associated with the page */ +}; + +/* +** CAPI3REF: Application Defined Page Cache. +** KEYWORDS: {page cache} +** +** ^(The [sqlite3_config]([SQLITE_CONFIG_PCACHE2], ...) interface can +** register an alternative page cache implementation by passing in an +** instance of the sqlite3_pcache_methods2 structure.)^ +** In many applications, most of the heap memory allocated by +** SQLite is used for the page cache. +** By implementing a +** custom page cache using this API, an application can better control +** the amount of memory consumed by SQLite, the way in which +** that memory is allocated and released, and the policies used to +** determine exactly which parts of a database file are cached and for +** how long. +** +** The alternative page cache mechanism is an +** extreme measure that is only needed by the most demanding applications. +** The built-in page cache is recommended for most uses. +** +** ^(The contents of the sqlite3_pcache_methods2 structure are copied to an +** internal buffer by SQLite within the call to [sqlite3_config]. Hence +** the application may discard the parameter after the call to +** [sqlite3_config()] returns.)^ +** +** [[the xInit() page cache method]] +** ^(The xInit() method is called once for each effective +** call to [sqlite3_initialize()])^ +** (usually only once during the lifetime of the process). ^(The xInit() +** method is passed a copy of the sqlite3_pcache_methods2.pArg value.)^ +** The intent of the xInit() method is to set up global data structures +** required by the custom page cache implementation. +** ^(If the xInit() method is NULL, then the +** built-in default page cache is used instead of the application defined +** page cache.)^ +** +** [[the xShutdown() page cache method]] +** ^The xShutdown() method is called by [sqlite3_shutdown()]. +** It can be used to clean up +** any outstanding resources before process shutdown, if required. +** ^The xShutdown() method may be NULL. +** +** ^SQLite automatically serializes calls to the xInit method, +** so the xInit method need not be threadsafe. ^The +** xShutdown method is only called from [sqlite3_shutdown()] so it does +** not need to be threadsafe either. All other methods must be threadsafe +** in multithreaded applications. +** +** ^SQLite will never invoke xInit() more than once without an intervening +** call to xShutdown(). +** +** [[the xCreate() page cache methods]] +** ^SQLite invokes the xCreate() method to construct a new cache instance. +** SQLite will typically create one cache instance for each open database file, +** though this is not guaranteed. ^The +** first parameter, szPage, is the size in bytes of the pages that must +** be allocated by the cache. ^szPage will always a power of two. ^The +** second parameter szExtra is a number of bytes of extra storage +** associated with each page cache entry. ^The szExtra parameter will +** a number less than 250. SQLite will use the +** extra szExtra bytes on each page to store metadata about the underlying +** database page on disk. The value passed into szExtra depends +** on the SQLite version, the target platform, and how SQLite was compiled. +** ^The third argument to xCreate(), bPurgeable, is true if the cache being +** created will be used to cache database pages of a file stored on disk, or +** false if it is used for an in-memory database. The cache implementation +** does not have to do anything special based with the value of bPurgeable; +** it is purely advisory. ^On a cache where bPurgeable is false, SQLite will +** never invoke xUnpin() except to deliberately delete a page. +** ^In other words, calls to xUnpin() on a cache with bPurgeable set to +** false will always have the "discard" flag set to true. +** ^Hence, a cache created with bPurgeable false will +** never contain any unpinned pages. +** +** [[the xCachesize() page cache method]] +** ^(The xCachesize() method may be called at any time by SQLite to set the +** suggested maximum cache-size (number of pages stored by) the cache +** instance passed as the first argument. This is the value configured using +** the SQLite "[PRAGMA cache_size]" command.)^ As with the bPurgeable +** parameter, the implementation is not required to do anything with this +** value; it is advisory only. +** +** [[the xPagecount() page cache methods]] +** The xPagecount() method must return the number of pages currently +** stored in the cache, both pinned and unpinned. +** +** [[the xFetch() page cache methods]] +** The xFetch() method locates a page in the cache and returns a pointer to +** an sqlite3_pcache_page object associated with that page, or a NULL pointer. +** The pBuf element of the returned sqlite3_pcache_page object will be a +** pointer to a buffer of szPage bytes used to store the content of a +** single database page. The pExtra element of sqlite3_pcache_page will be +** a pointer to the szExtra bytes of extra storage that SQLite has requested +** for each entry in the page cache. +** +** The page to be fetched is determined by the key. ^The minimum key value +** is 1. After it has been retrieved using xFetch, the page is considered +** to be "pinned". +** +** If the requested page is already in the page cache, then the page cache +** implementation must return a pointer to the page buffer with its content +** intact. If the requested page is not already in the cache, then the +** cache implementation should use the value of the createFlag +** parameter to help it determined what action to take: +** +** +**
    createFlag Behaviour when page is not already in cache +**
    0 Do not allocate a new page. Return NULL. +**
    1 Allocate a new page if it easy and convenient to do so. +** Otherwise return NULL. +**
    2 Make every effort to allocate a new page. Only return +** NULL if allocating a new page is effectively impossible. +**
    +** +** ^(SQLite will normally invoke xFetch() with a createFlag of 0 or 1. SQLite +** will only use a createFlag of 2 after a prior call with a createFlag of 1 +** failed.)^ In between the to xFetch() calls, SQLite may +** attempt to unpin one or more cache pages by spilling the content of +** pinned pages to disk and synching the operating system disk cache. +** +** [[the xUnpin() page cache method]] +** ^xUnpin() is called by SQLite with a pointer to a currently pinned page +** as its second argument. If the third parameter, discard, is non-zero, +** then the page must be evicted from the cache. +** ^If the discard parameter is +** zero, then the page may be discarded or retained at the discretion of +** page cache implementation. ^The page cache implementation +** may choose to evict unpinned pages at any time. +** +** The cache must not perform any reference counting. A single +** call to xUnpin() unpins the page regardless of the number of prior calls +** to xFetch(). +** +** [[the xRekey() page cache methods]] +** The xRekey() method is used to change the key value associated with the +** page passed as the second argument. If the cache +** previously contains an entry associated with newKey, it must be +** discarded. ^Any prior cache entry associated with newKey is guaranteed not +** to be pinned. +** +** When SQLite calls the xTruncate() method, the cache must discard all +** existing cache entries with page numbers (keys) greater than or equal +** to the value of the iLimit parameter passed to xTruncate(). If any +** of these pages are pinned, they are implicitly unpinned, meaning that +** they can be safely discarded. +** +** [[the xDestroy() page cache method]] +** ^The xDestroy() method is used to delete a cache allocated by xCreate(). +** All resources associated with the specified cache should be freed. ^After +** calling the xDestroy() method, SQLite considers the [sqlite3_pcache*] +** handle invalid, and will not use it with any other sqlite3_pcache_methods2 +** functions. +** +** [[the xShrink() page cache method]] +** ^SQLite invokes the xShrink() method when it wants the page cache to +** free up as much of heap memory as possible. The page cache implementation +** is not obligated to free any memory, but well-behaved implementations should +** do their best. +*/ +typedef struct sqlite3_pcache_methods2 sqlite3_pcache_methods2; +struct sqlite3_pcache_methods2 { + int iVersion; + void *pArg; + int (*xInit)(void*); + void (*xShutdown)(void*); + sqlite3_pcache *(*xCreate)(int szPage, int szExtra, int bPurgeable); + void (*xCachesize)(sqlite3_pcache*, int nCachesize); + int (*xPagecount)(sqlite3_pcache*); + sqlite3_pcache_page *(*xFetch)(sqlite3_pcache*, unsigned key, int createFlag); + void (*xUnpin)(sqlite3_pcache*, sqlite3_pcache_page*, int discard); + void (*xRekey)(sqlite3_pcache*, sqlite3_pcache_page*, + unsigned oldKey, unsigned newKey); + void (*xTruncate)(sqlite3_pcache*, unsigned iLimit); + void (*xDestroy)(sqlite3_pcache*); + void (*xShrink)(sqlite3_pcache*); +}; + +/* +** This is the obsolete pcache_methods object that has now been replaced +** by sqlite3_pcache_methods2. This object is not used by SQLite. It is +** retained in the header file for backwards compatibility only. +*/ +typedef struct sqlite3_pcache_methods sqlite3_pcache_methods; +struct sqlite3_pcache_methods { + void *pArg; + int (*xInit)(void*); + void (*xShutdown)(void*); + sqlite3_pcache *(*xCreate)(int szPage, int bPurgeable); + void (*xCachesize)(sqlite3_pcache*, int nCachesize); + int (*xPagecount)(sqlite3_pcache*); + void *(*xFetch)(sqlite3_pcache*, unsigned key, int createFlag); + void (*xUnpin)(sqlite3_pcache*, void*, int discard); + void (*xRekey)(sqlite3_pcache*, void*, unsigned oldKey, unsigned newKey); + void (*xTruncate)(sqlite3_pcache*, unsigned iLimit); + void (*xDestroy)(sqlite3_pcache*); +}; + + +/* +** CAPI3REF: Online Backup Object +** +** The sqlite3_backup object records state information about an ongoing +** online backup operation. ^The sqlite3_backup object is created by +** a call to [sqlite3_backup_init()] and is destroyed by a call to +** [sqlite3_backup_finish()]. +** +** See Also: [Using the SQLite Online Backup API] +*/ +typedef struct sqlite3_backup sqlite3_backup; + +/* +** CAPI3REF: Online Backup API. +** +** The backup API copies the content of one database into another. +** It is useful either for creating backups of databases or +** for copying in-memory databases to or from persistent files. +** +** See Also: [Using the SQLite Online Backup API] +** +** ^SQLite holds a write transaction open on the destination database file +** for the duration of the backup operation. +** ^The source database is read-locked only while it is being read; +** it is not locked continuously for the entire backup operation. +** ^Thus, the backup may be performed on a live source database without +** preventing other database connections from +** reading or writing to the source database while the backup is underway. +** +** ^(To perform a backup operation: +**
      +**
    1. sqlite3_backup_init() is called once to initialize the +** backup, +**
    2. sqlite3_backup_step() is called one or more times to transfer +** the data between the two databases, and finally +**
    3. sqlite3_backup_finish() is called to release all resources +** associated with the backup operation. +**
    )^ +** There should be exactly one call to sqlite3_backup_finish() for each +** successful call to sqlite3_backup_init(). +** +** [[sqlite3_backup_init()]] sqlite3_backup_init() +** +** ^The D and N arguments to sqlite3_backup_init(D,N,S,M) are the +** [database connection] associated with the destination database +** and the database name, respectively. +** ^The database name is "main" for the main database, "temp" for the +** temporary database, or the name specified after the AS keyword in +** an [ATTACH] statement for an attached database. +** ^The S and M arguments passed to +** sqlite3_backup_init(D,N,S,M) identify the [database connection] +** and database name of the source database, respectively. +** ^The source and destination [database connections] (parameters S and D) +** must be different or else sqlite3_backup_init(D,N,S,M) will fail with +** an error. +** +** ^If an error occurs within sqlite3_backup_init(D,N,S,M), then NULL is +** returned and an error code and error message are stored in the +** destination [database connection] D. +** ^The error code and message for the failed call to sqlite3_backup_init() +** can be retrieved using the [sqlite3_errcode()], [sqlite3_errmsg()], and/or +** [sqlite3_errmsg16()] functions. +** ^A successful call to sqlite3_backup_init() returns a pointer to an +** [sqlite3_backup] object. +** ^The [sqlite3_backup] object may be used with the sqlite3_backup_step() and +** sqlite3_backup_finish() functions to perform the specified backup +** operation. +** +** [[sqlite3_backup_step()]] sqlite3_backup_step() +** +** ^Function sqlite3_backup_step(B,N) will copy up to N pages between +** the source and destination databases specified by [sqlite3_backup] object B. +** ^If N is negative, all remaining source pages are copied. +** ^If sqlite3_backup_step(B,N) successfully copies N pages and there +** are still more pages to be copied, then the function returns [SQLITE_OK]. +** ^If sqlite3_backup_step(B,N) successfully finishes copying all pages +** from source to destination, then it returns [SQLITE_DONE]. +** ^If an error occurs while running sqlite3_backup_step(B,N), +** then an [error code] is returned. ^As well as [SQLITE_OK] and +** [SQLITE_DONE], a call to sqlite3_backup_step() may return [SQLITE_READONLY], +** [SQLITE_NOMEM], [SQLITE_BUSY], [SQLITE_LOCKED], or an +** [SQLITE_IOERR_ACCESS | SQLITE_IOERR_XXX] extended error code. +** +** ^(The sqlite3_backup_step() might return [SQLITE_READONLY] if +**
      +**
    1. the destination database was opened read-only, or +**
    2. the destination database is using write-ahead-log journaling +** and the destination and source page sizes differ, or +**
    3. the destination database is an in-memory database and the +** destination and source page sizes differ. +**
    )^ +** +** ^If sqlite3_backup_step() cannot obtain a required file-system lock, then +** the [sqlite3_busy_handler | busy-handler function] +** is invoked (if one is specified). ^If the +** busy-handler returns non-zero before the lock is available, then +** [SQLITE_BUSY] is returned to the caller. ^In this case the call to +** sqlite3_backup_step() can be retried later. ^If the source +** [database connection] +** is being used to write to the source database when sqlite3_backup_step() +** is called, then [SQLITE_LOCKED] is returned immediately. ^Again, in this +** case the call to sqlite3_backup_step() can be retried later on. ^(If +** [SQLITE_IOERR_ACCESS | SQLITE_IOERR_XXX], [SQLITE_NOMEM], or +** [SQLITE_READONLY] is returned, then +** there is no point in retrying the call to sqlite3_backup_step(). These +** errors are considered fatal.)^ The application must accept +** that the backup operation has failed and pass the backup operation handle +** to the sqlite3_backup_finish() to release associated resources. +** +** ^The first call to sqlite3_backup_step() obtains an exclusive lock +** on the destination file. ^The exclusive lock is not released until either +** sqlite3_backup_finish() is called or the backup operation is complete +** and sqlite3_backup_step() returns [SQLITE_DONE]. ^Every call to +** sqlite3_backup_step() obtains a [shared lock] on the source database that +** lasts for the duration of the sqlite3_backup_step() call. +** ^Because the source database is not locked between calls to +** sqlite3_backup_step(), the source database may be modified mid-way +** through the backup process. ^If the source database is modified by an +** external process or via a database connection other than the one being +** used by the backup operation, then the backup will be automatically +** restarted by the next call to sqlite3_backup_step(). ^If the source +** database is modified by the using the same database connection as is used +** by the backup operation, then the backup database is automatically +** updated at the same time. +** +** [[sqlite3_backup_finish()]] sqlite3_backup_finish() +** +** When sqlite3_backup_step() has returned [SQLITE_DONE], or when the +** application wishes to abandon the backup operation, the application +** should destroy the [sqlite3_backup] by passing it to sqlite3_backup_finish(). +** ^The sqlite3_backup_finish() interfaces releases all +** resources associated with the [sqlite3_backup] object. +** ^If sqlite3_backup_step() has not yet returned [SQLITE_DONE], then any +** active write-transaction on the destination database is rolled back. +** The [sqlite3_backup] object is invalid +** and may not be used following a call to sqlite3_backup_finish(). +** +** ^The value returned by sqlite3_backup_finish is [SQLITE_OK] if no +** sqlite3_backup_step() errors occurred, regardless or whether or not +** sqlite3_backup_step() completed. +** ^If an out-of-memory condition or IO error occurred during any prior +** sqlite3_backup_step() call on the same [sqlite3_backup] object, then +** sqlite3_backup_finish() returns the corresponding [error code]. +** +** ^A return of [SQLITE_BUSY] or [SQLITE_LOCKED] from sqlite3_backup_step() +** is not a permanent error and does not affect the return value of +** sqlite3_backup_finish(). +** +** [[sqlite3_backup__remaining()]] [[sqlite3_backup_pagecount()]] +** sqlite3_backup_remaining() and sqlite3_backup_pagecount() +** +** ^Each call to sqlite3_backup_step() sets two values inside +** the [sqlite3_backup] object: the number of pages still to be backed +** up and the total number of pages in the source database file. +** The sqlite3_backup_remaining() and sqlite3_backup_pagecount() interfaces +** retrieve these two values, respectively. +** +** ^The values returned by these functions are only updated by +** sqlite3_backup_step(). ^If the source database is modified during a backup +** operation, then the values are not updated to account for any extra +** pages that need to be updated or the size of the source database file +** changing. +** +** Concurrent Usage of Database Handles +** +** ^The source [database connection] may be used by the application for other +** purposes while a backup operation is underway or being initialized. +** ^If SQLite is compiled and configured to support threadsafe database +** connections, then the source database connection may be used concurrently +** from within other threads. +** +** However, the application must guarantee that the destination +** [database connection] is not passed to any other API (by any thread) after +** sqlite3_backup_init() is called and before the corresponding call to +** sqlite3_backup_finish(). SQLite does not currently check to see +** if the application incorrectly accesses the destination [database connection] +** and so no error code is reported, but the operations may malfunction +** nevertheless. Use of the destination database connection while a +** backup is in progress might also also cause a mutex deadlock. +** +** If running in [shared cache mode], the application must +** guarantee that the shared cache used by the destination database +** is not accessed while the backup is running. In practice this means +** that the application must guarantee that the disk file being +** backed up to is not accessed by any connection within the process, +** not just the specific connection that was passed to sqlite3_backup_init(). +** +** The [sqlite3_backup] object itself is partially threadsafe. Multiple +** threads may safely make multiple concurrent calls to sqlite3_backup_step(). +** However, the sqlite3_backup_remaining() and sqlite3_backup_pagecount() +** APIs are not strictly speaking threadsafe. If they are invoked at the +** same time as another thread is invoking sqlite3_backup_step() it is +** possible that they return invalid values. +*/ +SQLITE_API sqlite3_backup *sqlite3_backup_init( + sqlite3 *pDest, /* Destination database handle */ + const char *zDestName, /* Destination database name */ + sqlite3 *pSource, /* Source database handle */ + const char *zSourceName /* Source database name */ +); +SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage); +SQLITE_API int sqlite3_backup_finish(sqlite3_backup *p); +SQLITE_API int sqlite3_backup_remaining(sqlite3_backup *p); +SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p); + +/* +** CAPI3REF: Unlock Notification +** +** ^When running in shared-cache mode, a database operation may fail with +** an [SQLITE_LOCKED] error if the required locks on the shared-cache or +** individual tables within the shared-cache cannot be obtained. See +** [SQLite Shared-Cache Mode] for a description of shared-cache locking. +** ^This API may be used to register a callback that SQLite will invoke +** when the connection currently holding the required lock relinquishes it. +** ^This API is only available if the library was compiled with the +** [SQLITE_ENABLE_UNLOCK_NOTIFY] C-preprocessor symbol defined. +** +** See Also: [Using the SQLite Unlock Notification Feature]. +** +** ^Shared-cache locks are released when a database connection concludes +** its current transaction, either by committing it or rolling it back. +** +** ^When a connection (known as the blocked connection) fails to obtain a +** shared-cache lock and SQLITE_LOCKED is returned to the caller, the +** identity of the database connection (the blocking connection) that +** has locked the required resource is stored internally. ^After an +** application receives an SQLITE_LOCKED error, it may call the +** sqlite3_unlock_notify() method with the blocked connection handle as +** the first argument to register for a callback that will be invoked +** when the blocking connections current transaction is concluded. ^The +** callback is invoked from within the [sqlite3_step] or [sqlite3_close] +** call that concludes the blocking connections transaction. +** +** ^(If sqlite3_unlock_notify() is called in a multi-threaded application, +** there is a chance that the blocking connection will have already +** concluded its transaction by the time sqlite3_unlock_notify() is invoked. +** If this happens, then the specified callback is invoked immediately, +** from within the call to sqlite3_unlock_notify().)^ +** +** ^If the blocked connection is attempting to obtain a write-lock on a +** shared-cache table, and more than one other connection currently holds +** a read-lock on the same table, then SQLite arbitrarily selects one of +** the other connections to use as the blocking connection. +** +** ^(There may be at most one unlock-notify callback registered by a +** blocked connection. If sqlite3_unlock_notify() is called when the +** blocked connection already has a registered unlock-notify callback, +** then the new callback replaces the old.)^ ^If sqlite3_unlock_notify() is +** called with a NULL pointer as its second argument, then any existing +** unlock-notify callback is canceled. ^The blocked connections +** unlock-notify callback may also be canceled by closing the blocked +** connection using [sqlite3_close()]. +** +** The unlock-notify callback is not reentrant. If an application invokes +** any sqlite3_xxx API functions from within an unlock-notify callback, a +** crash or deadlock may be the result. +** +** ^Unless deadlock is detected (see below), sqlite3_unlock_notify() always +** returns SQLITE_OK. +** +** Callback Invocation Details +** +** When an unlock-notify callback is registered, the application provides a +** single void* pointer that is passed to the callback when it is invoked. +** However, the signature of the callback function allows SQLite to pass +** it an array of void* context pointers. The first argument passed to +** an unlock-notify callback is a pointer to an array of void* pointers, +** and the second is the number of entries in the array. +** +** When a blocking connections transaction is concluded, there may be +** more than one blocked connection that has registered for an unlock-notify +** callback. ^If two or more such blocked connections have specified the +** same callback function, then instead of invoking the callback function +** multiple times, it is invoked once with the set of void* context pointers +** specified by the blocked connections bundled together into an array. +** This gives the application an opportunity to prioritize any actions +** related to the set of unblocked database connections. +** +** Deadlock Detection +** +** Assuming that after registering for an unlock-notify callback a +** database waits for the callback to be issued before taking any further +** action (a reasonable assumption), then using this API may cause the +** application to deadlock. For example, if connection X is waiting for +** connection Y's transaction to be concluded, and similarly connection +** Y is waiting on connection X's transaction, then neither connection +** will proceed and the system may remain deadlocked indefinitely. +** +** To avoid this scenario, the sqlite3_unlock_notify() performs deadlock +** detection. ^If a given call to sqlite3_unlock_notify() would put the +** system in a deadlocked state, then SQLITE_LOCKED is returned and no +** unlock-notify callback is registered. The system is said to be in +** a deadlocked state if connection A has registered for an unlock-notify +** callback on the conclusion of connection B's transaction, and connection +** B has itself registered for an unlock-notify callback when connection +** A's transaction is concluded. ^Indirect deadlock is also detected, so +** the system is also considered to be deadlocked if connection B has +** registered for an unlock-notify callback on the conclusion of connection +** C's transaction, where connection C is waiting on connection A. ^Any +** number of levels of indirection are allowed. +** +** The "DROP TABLE" Exception +** +** When a call to [sqlite3_step()] returns SQLITE_LOCKED, it is almost +** always appropriate to call sqlite3_unlock_notify(). There is however, +** one exception. When executing a "DROP TABLE" or "DROP INDEX" statement, +** SQLite checks if there are any currently executing SELECT statements +** that belong to the same connection. If there are, SQLITE_LOCKED is +** returned. In this case there is no "blocking connection", so invoking +** sqlite3_unlock_notify() results in the unlock-notify callback being +** invoked immediately. If the application then re-attempts the "DROP TABLE" +** or "DROP INDEX" query, an infinite loop might be the result. +** +** One way around this problem is to check the extended error code returned +** by an sqlite3_step() call. ^(If there is a blocking connection, then the +** extended error code is set to SQLITE_LOCKED_SHAREDCACHE. Otherwise, in +** the special "DROP TABLE/INDEX" case, the extended error code is just +** SQLITE_LOCKED.)^ +*/ +SQLITE_API int sqlite3_unlock_notify( + sqlite3 *pBlocked, /* Waiting connection */ + void (*xNotify)(void **apArg, int nArg), /* Callback function to invoke */ + void *pNotifyArg /* Argument to pass to xNotify */ +); + + +/* +** CAPI3REF: String Comparison +** +** ^The [sqlite3_strnicmp()] API allows applications and extensions to +** compare the contents of two buffers containing UTF-8 strings in a +** case-independent fashion, using the same definition of case independence +** that SQLite uses internally when comparing identifiers. +*/ +SQLITE_API int sqlite3_strnicmp(const char *, const char *, int); + +/* +** CAPI3REF: Error Logging Interface +** +** ^The [sqlite3_log()] interface writes a message into the error log +** established by the [SQLITE_CONFIG_LOG] option to [sqlite3_config()]. +** ^If logging is enabled, the zFormat string and subsequent arguments are +** used with [sqlite3_snprintf()] to generate the final output string. +** +** The sqlite3_log() interface is intended for use by extensions such as +** virtual tables, collating functions, and SQL functions. While there is +** nothing to prevent an application from calling sqlite3_log(), doing so +** is considered bad form. +** +** The zFormat string must not be NULL. +** +** To avoid deadlocks and other threading problems, the sqlite3_log() routine +** will not use dynamically allocated memory. The log message is stored in +** a fixed-length buffer on the stack. If the log message is longer than +** a few hundred characters, it will be truncated to the length of the +** buffer. +*/ +SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...); + +/* +** CAPI3REF: Write-Ahead Log Commit Hook +** +** ^The [sqlite3_wal_hook()] function is used to register a callback that +** will be invoked each time a database connection commits data to a +** [write-ahead log] (i.e. whenever a transaction is committed in +** [journal_mode | journal_mode=WAL mode]). +** +** ^The callback is invoked by SQLite after the commit has taken place and +** the associated write-lock on the database released, so the implementation +** may read, write or [checkpoint] the database as required. +** +** ^The first parameter passed to the callback function when it is invoked +** is a copy of the third parameter passed to sqlite3_wal_hook() when +** registering the callback. ^The second is a copy of the database handle. +** ^The third parameter is the name of the database that was written to - +** either "main" or the name of an [ATTACH]-ed database. ^The fourth parameter +** is the number of pages currently in the write-ahead log file, +** including those that were just committed. +** +** The callback function should normally return [SQLITE_OK]. ^If an error +** code is returned, that error will propagate back up through the +** SQLite code base to cause the statement that provoked the callback +** to report an error, though the commit will have still occurred. If the +** callback returns [SQLITE_ROW] or [SQLITE_DONE], or if it returns a value +** that does not correspond to any valid SQLite error code, the results +** are undefined. +** +** A single database handle may have at most a single write-ahead log callback +** registered at one time. ^Calling [sqlite3_wal_hook()] replaces any +** previously registered write-ahead log callback. ^Note that the +** [sqlite3_wal_autocheckpoint()] interface and the +** [wal_autocheckpoint pragma] both invoke [sqlite3_wal_hook()] and will +** those overwrite any prior [sqlite3_wal_hook()] settings. +*/ +SQLITE_API void *sqlite3_wal_hook( + sqlite3*, + int(*)(void *,sqlite3*,const char*,int), + void* +); + +/* +** CAPI3REF: Configure an auto-checkpoint +** +** ^The [sqlite3_wal_autocheckpoint(D,N)] is a wrapper around +** [sqlite3_wal_hook()] that causes any database on [database connection] D +** to automatically [checkpoint] +** after committing a transaction if there are N or +** more frames in the [write-ahead log] file. ^Passing zero or +** a negative value as the nFrame parameter disables automatic +** checkpoints entirely. +** +** ^The callback registered by this function replaces any existing callback +** registered using [sqlite3_wal_hook()]. ^Likewise, registering a callback +** using [sqlite3_wal_hook()] disables the automatic checkpoint mechanism +** configured by this function. +** +** ^The [wal_autocheckpoint pragma] can be used to invoke this interface +** from SQL. +** +** ^Every new [database connection] defaults to having the auto-checkpoint +** enabled with a threshold of 1000 or [SQLITE_DEFAULT_WAL_AUTOCHECKPOINT] +** pages. The use of this interface +** is only necessary if the default setting is found to be suboptimal +** for a particular application. +*/ +SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int N); + +/* +** CAPI3REF: Checkpoint a database +** +** ^The [sqlite3_wal_checkpoint(D,X)] interface causes database named X +** on [database connection] D to be [checkpointed]. ^If X is NULL or an +** empty string, then a checkpoint is run on all databases of +** connection D. ^If the database connection D is not in +** [WAL | write-ahead log mode] then this interface is a harmless no-op. +** +** ^The [wal_checkpoint pragma] can be used to invoke this interface +** from SQL. ^The [sqlite3_wal_autocheckpoint()] interface and the +** [wal_autocheckpoint pragma] can be used to cause this interface to be +** run whenever the WAL reaches a certain size threshold. +** +** See also: [sqlite3_wal_checkpoint_v2()] +*/ +SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb); + +/* +** CAPI3REF: Checkpoint a database +** +** Run a checkpoint operation on WAL database zDb attached to database +** handle db. The specific operation is determined by the value of the +** eMode parameter: +** +**
    +**
    SQLITE_CHECKPOINT_PASSIVE
    +** Checkpoint as many frames as possible without waiting for any database +** readers or writers to finish. Sync the db file if all frames in the log +** are checkpointed. This mode is the same as calling +** sqlite3_wal_checkpoint(). The busy-handler callback is never invoked. +** +**
    SQLITE_CHECKPOINT_FULL
    +** This mode blocks (calls the busy-handler callback) until there is no +** database writer and all readers are reading from the most recent database +** snapshot. It then checkpoints all frames in the log file and syncs the +** database file. This call blocks database writers while it is running, +** but not database readers. +** +**
    SQLITE_CHECKPOINT_RESTART
    +** This mode works the same way as SQLITE_CHECKPOINT_FULL, except after +** checkpointing the log file it blocks (calls the busy-handler callback) +** until all readers are reading from the database file only. This ensures +** that the next client to write to the database file restarts the log file +** from the beginning. This call blocks database writers while it is running, +** but not database readers. +**
    +** +** If pnLog is not NULL, then *pnLog is set to the total number of frames in +** the log file before returning. If pnCkpt is not NULL, then *pnCkpt is set to +** the total number of checkpointed frames (including any that were already +** checkpointed when this function is called). *pnLog and *pnCkpt may be +** populated even if sqlite3_wal_checkpoint_v2() returns other than SQLITE_OK. +** If no values are available because of an error, they are both set to -1 +** before returning to communicate this to the caller. +** +** All calls obtain an exclusive "checkpoint" lock on the database file. If +** any other process is running a checkpoint operation at the same time, the +** lock cannot be obtained and SQLITE_BUSY is returned. Even if there is a +** busy-handler configured, it will not be invoked in this case. +** +** The SQLITE_CHECKPOINT_FULL and RESTART modes also obtain the exclusive +** "writer" lock on the database file. If the writer lock cannot be obtained +** immediately, and a busy-handler is configured, it is invoked and the writer +** lock retried until either the busy-handler returns 0 or the lock is +** successfully obtained. The busy-handler is also invoked while waiting for +** database readers as described above. If the busy-handler returns 0 before +** the writer lock is obtained or while waiting for database readers, the +** checkpoint operation proceeds from that point in the same way as +** SQLITE_CHECKPOINT_PASSIVE - checkpointing as many frames as possible +** without blocking any further. SQLITE_BUSY is returned in this case. +** +** If parameter zDb is NULL or points to a zero length string, then the +** specified operation is attempted on all WAL databases. In this case the +** values written to output parameters *pnLog and *pnCkpt are undefined. If +** an SQLITE_BUSY error is encountered when processing one or more of the +** attached WAL databases, the operation is still attempted on any remaining +** attached databases and SQLITE_BUSY is returned to the caller. If any other +** error occurs while processing an attached database, processing is abandoned +** and the error code returned to the caller immediately. If no error +** (SQLITE_BUSY or otherwise) is encountered while processing the attached +** databases, SQLITE_OK is returned. +** +** If database zDb is the name of an attached database that is not in WAL +** mode, SQLITE_OK is returned and both *pnLog and *pnCkpt set to -1. If +** zDb is not NULL (or a zero length string) and is not the name of any +** attached database, SQLITE_ERROR is returned to the caller. +*/ +SQLITE_API int sqlite3_wal_checkpoint_v2( + sqlite3 *db, /* Database handle */ + const char *zDb, /* Name of attached database (or NULL) */ + int eMode, /* SQLITE_CHECKPOINT_* value */ + int *pnLog, /* OUT: Size of WAL log in frames */ + int *pnCkpt /* OUT: Total number of frames checkpointed */ +); + +/* +** CAPI3REF: Checkpoint operation parameters +** +** These constants can be used as the 3rd parameter to +** [sqlite3_wal_checkpoint_v2()]. See the [sqlite3_wal_checkpoint_v2()] +** documentation for additional information about the meaning and use of +** each of these values. +*/ +#define SQLITE_CHECKPOINT_PASSIVE 0 +#define SQLITE_CHECKPOINT_FULL 1 +#define SQLITE_CHECKPOINT_RESTART 2 + +/* +** CAPI3REF: Virtual Table Interface Configuration +** +** This function may be called by either the [xConnect] or [xCreate] method +** of a [virtual table] implementation to configure +** various facets of the virtual table interface. +** +** If this interface is invoked outside the context of an xConnect or +** xCreate virtual table method then the behavior is undefined. +** +** At present, there is only one option that may be configured using +** this function. (See [SQLITE_VTAB_CONSTRAINT_SUPPORT].) Further options +** may be added in the future. +*/ +SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...); + +/* +** CAPI3REF: Virtual Table Configuration Options +** +** These macros define the various options to the +** [sqlite3_vtab_config()] interface that [virtual table] implementations +** can use to customize and optimize their behavior. +** +**
    +**
    SQLITE_VTAB_CONSTRAINT_SUPPORT +**
    Calls of the form +** [sqlite3_vtab_config](db,SQLITE_VTAB_CONSTRAINT_SUPPORT,X) are supported, +** where X is an integer. If X is zero, then the [virtual table] whose +** [xCreate] or [xConnect] method invoked [sqlite3_vtab_config()] does not +** support constraints. In this configuration (which is the default) if +** a call to the [xUpdate] method returns [SQLITE_CONSTRAINT], then the entire +** statement is rolled back as if [ON CONFLICT | OR ABORT] had been +** specified as part of the users SQL statement, regardless of the actual +** ON CONFLICT mode specified. +** +** If X is non-zero, then the virtual table implementation guarantees +** that if [xUpdate] returns [SQLITE_CONSTRAINT], it will do so before +** any modifications to internal or persistent data structures have been made. +** If the [ON CONFLICT] mode is ABORT, FAIL, IGNORE or ROLLBACK, SQLite +** is able to roll back a statement or database transaction, and abandon +** or continue processing the current SQL statement as appropriate. +** If the ON CONFLICT mode is REPLACE and the [xUpdate] method returns +** [SQLITE_CONSTRAINT], SQLite handles this as if the ON CONFLICT mode +** had been ABORT. +** +** Virtual table implementations that are required to handle OR REPLACE +** must do so within the [xUpdate] method. If a call to the +** [sqlite3_vtab_on_conflict()] function indicates that the current ON +** CONFLICT policy is REPLACE, the virtual table implementation should +** silently replace the appropriate rows within the xUpdate callback and +** return SQLITE_OK. Or, if this is not possible, it may return +** SQLITE_CONSTRAINT, in which case SQLite falls back to OR ABORT +** constraint handling. +**
    +*/ +#define SQLITE_VTAB_CONSTRAINT_SUPPORT 1 + +/* +** CAPI3REF: Determine The Virtual Table Conflict Policy +** +** This function may only be called from within a call to the [xUpdate] method +** of a [virtual table] implementation for an INSERT or UPDATE operation. ^The +** value returned is one of [SQLITE_ROLLBACK], [SQLITE_IGNORE], [SQLITE_FAIL], +** [SQLITE_ABORT], or [SQLITE_REPLACE], according to the [ON CONFLICT] mode +** of the SQL statement that triggered the call to the [xUpdate] method of the +** [virtual table]. +*/ +SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *); + +/* +** CAPI3REF: Conflict resolution modes +** +** These constants are returned by [sqlite3_vtab_on_conflict()] to +** inform a [virtual table] implementation what the [ON CONFLICT] mode +** is for the SQL statement being evaluated. +** +** Note that the [SQLITE_IGNORE] constant is also used as a potential +** return value from the [sqlite3_set_authorizer()] callback and that +** [SQLITE_ABORT] is also a [result code]. +*/ +#define SQLITE_ROLLBACK 1 +/* #define SQLITE_IGNORE 2 // Also used by sqlite3_authorizer() callback */ +#define SQLITE_FAIL 3 +/* #define SQLITE_ABORT 4 // Also an error code */ +#define SQLITE_REPLACE 5 + + + +/* +** Undo the hack that converts floating point types to integer for +** builds on processors without floating point support. +*/ +#ifdef SQLITE_OMIT_FLOATING_POINT +# undef double +#endif + +#if 0 +} /* End of the 'extern "C"' block */ +#endif +#endif + +/* +** 2010 August 30 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +*/ + +#ifndef _SQLITE3RTREE_H_ +#define _SQLITE3RTREE_H_ + + +#if 0 +extern "C" { +#endif + +typedef struct sqlite3_rtree_geometry sqlite3_rtree_geometry; + +/* +** Register a geometry callback named zGeom that can be used as part of an +** R-Tree geometry query as follows: +** +** SELECT ... FROM WHERE MATCH $zGeom(... params ...) +*/ +SQLITE_API int sqlite3_rtree_geometry_callback( + sqlite3 *db, + const char *zGeom, + int (*xGeom)(sqlite3_rtree_geometry *, int nCoord, double *aCoord, int *pRes), + void *pContext +); + + +/* +** A pointer to a structure of the following type is passed as the first +** argument to callbacks registered using rtree_geometry_callback(). +*/ +struct sqlite3_rtree_geometry { + void *pContext; /* Copy of pContext passed to s_r_g_c() */ + int nParam; /* Size of array aParam[] */ + double *aParam; /* Parameters passed to SQL geom function */ + void *pUser; /* Callback implementation user data */ + void (*xDelUser)(void *); /* Called by SQLite to clean up pUser */ +}; + + +#if 0 +} /* end of the 'extern "C"' block */ +#endif + +#endif /* ifndef _SQLITE3RTREE_H_ */ + + +/************** End of sqlite3.h *********************************************/ +/************** Continuing where we left off in sqliteInt.h ******************/ +/************** Include hash.h in the middle of sqliteInt.h ******************/ +/************** Begin file hash.h ********************************************/ +/* +** 2001 September 22 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This is the header file for the generic hash-table implemenation +** used in SQLite. +*/ +#ifndef _SQLITE_HASH_H_ +#define _SQLITE_HASH_H_ + +/* Forward declarations of structures. */ +typedef struct Hash Hash; +typedef struct HashElem HashElem; + +/* A complete hash table is an instance of the following structure. +** The internals of this structure are intended to be opaque -- client +** code should not attempt to access or modify the fields of this structure +** directly. Change this structure only by using the routines below. +** However, some of the "procedures" and "functions" for modifying and +** accessing this structure are really macros, so we can't really make +** this structure opaque. +** +** All elements of the hash table are on a single doubly-linked list. +** Hash.first points to the head of this list. +** +** There are Hash.htsize buckets. Each bucket points to a spot in +** the global doubly-linked list. The contents of the bucket are the +** element pointed to plus the next _ht.count-1 elements in the list. +** +** Hash.htsize and Hash.ht may be zero. In that case lookup is done +** by a linear search of the global list. For small tables, the +** Hash.ht table is never allocated because if there are few elements +** in the table, it is faster to do a linear search than to manage +** the hash table. +*/ +struct Hash { + unsigned int htsize; /* Number of buckets in the hash table */ + unsigned int count; /* Number of entries in this table */ + HashElem *first; /* The first element of the array */ + struct _ht { /* the hash table */ + int count; /* Number of entries with this hash */ + HashElem *chain; /* Pointer to first entry with this hash */ + } *ht; +}; + +/* Each element in the hash table is an instance of the following +** structure. All elements are stored on a single doubly-linked list. +** +** Again, this structure is intended to be opaque, but it can't really +** be opaque because it is used by macros. +*/ +struct HashElem { + HashElem *next, *prev; /* Next and previous elements in the table */ + void *data; /* Data associated with this element */ + const char *pKey; int nKey; /* Key associated with this element */ +}; + +/* +** Access routines. To delete, insert a NULL pointer. +*/ +SQLITE_PRIVATE void sqlite3HashInit(Hash*); +SQLITE_PRIVATE void *sqlite3HashInsert(Hash*, const char *pKey, int nKey, void *pData); +SQLITE_PRIVATE void *sqlite3HashFind(const Hash*, const char *pKey, int nKey); +SQLITE_PRIVATE void sqlite3HashClear(Hash*); + +/* +** Macros for looping over all elements of a hash table. The idiom is +** like this: +** +** Hash h; +** HashElem *p; +** ... +** for(p=sqliteHashFirst(&h); p; p=sqliteHashNext(p)){ +** SomeStructure *pData = sqliteHashData(p); +** // do something with pData +** } +*/ +#define sqliteHashFirst(H) ((H)->first) +#define sqliteHashNext(E) ((E)->next) +#define sqliteHashData(E) ((E)->data) +/* #define sqliteHashKey(E) ((E)->pKey) // NOT USED */ +/* #define sqliteHashKeysize(E) ((E)->nKey) // NOT USED */ + +/* +** Number of entries in a hash table +*/ +/* #define sqliteHashCount(H) ((H)->count) // NOT USED */ + +#endif /* _SQLITE_HASH_H_ */ + +/************** End of hash.h ************************************************/ +/************** Continuing where we left off in sqliteInt.h ******************/ +/************** Include parse.h in the middle of sqliteInt.h *****************/ +/************** Begin file parse.h *******************************************/ +#define TK_SEMI 1 +#define TK_EXPLAIN 2 +#define TK_QUERY 3 +#define TK_PLAN 4 +#define TK_BEGIN 5 +#define TK_TRANSACTION 6 +#define TK_DEFERRED 7 +#define TK_IMMEDIATE 8 +#define TK_EXCLUSIVE 9 +#define TK_COMMIT 10 +#define TK_END 11 +#define TK_ROLLBACK 12 +#define TK_SAVEPOINT 13 +#define TK_RELEASE 14 +#define TK_TO 15 +#define TK_TABLE 16 +#define TK_CREATE 17 +#define TK_IF 18 +#define TK_NOT 19 +#define TK_EXISTS 20 +#define TK_TEMP 21 +#define TK_LP 22 +#define TK_RP 23 +#define TK_AS 24 +#define TK_COMMA 25 +#define TK_ID 26 +#define TK_INDEXED 27 +#define TK_ABORT 28 +#define TK_ACTION 29 +#define TK_AFTER 30 +#define TK_ANALYZE 31 +#define TK_ASC 32 +#define TK_ATTACH 33 +#define TK_BEFORE 34 +#define TK_BY 35 +#define TK_CASCADE 36 +#define TK_CAST 37 +#define TK_COLUMNKW 38 +#define TK_CONFLICT 39 +#define TK_DATABASE 40 +#define TK_DESC 41 +#define TK_DETACH 42 +#define TK_EACH 43 +#define TK_FAIL 44 +#define TK_FOR 45 +#define TK_IGNORE 46 +#define TK_INITIALLY 47 +#define TK_INSTEAD 48 +#define TK_LIKE_KW 49 +#define TK_MATCH 50 +#define TK_NO 51 +#define TK_KEY 52 +#define TK_OF 53 +#define TK_OFFSET 54 +#define TK_PRAGMA 55 +#define TK_RAISE 56 +#define TK_REPLACE 57 +#define TK_RESTRICT 58 +#define TK_ROW 59 +#define TK_TRIGGER 60 +#define TK_VACUUM 61 +#define TK_VIEW 62 +#define TK_VIRTUAL 63 +#define TK_REINDEX 64 +#define TK_RENAME 65 +#define TK_CTIME_KW 66 +#define TK_ANY 67 +#define TK_OR 68 +#define TK_AND 69 +#define TK_IS 70 +#define TK_BETWEEN 71 +#define TK_IN 72 +#define TK_ISNULL 73 +#define TK_NOTNULL 74 +#define TK_NE 75 +#define TK_EQ 76 +#define TK_GT 77 +#define TK_LE 78 +#define TK_LT 79 +#define TK_GE 80 +#define TK_ESCAPE 81 +#define TK_BITAND 82 +#define TK_BITOR 83 +#define TK_LSHIFT 84 +#define TK_RSHIFT 85 +#define TK_PLUS 86 +#define TK_MINUS 87 +#define TK_STAR 88 +#define TK_SLASH 89 +#define TK_REM 90 +#define TK_CONCAT 91 +#define TK_COLLATE 92 +#define TK_BITNOT 93 +#define TK_STRING 94 +#define TK_JOIN_KW 95 +#define TK_CONSTRAINT 96 +#define TK_DEFAULT 97 +#define TK_NULL 98 +#define TK_PRIMARY 99 +#define TK_UNIQUE 100 +#define TK_CHECK 101 +#define TK_REFERENCES 102 +#define TK_AUTOINCR 103 +#define TK_ON 104 +#define TK_INSERT 105 +#define TK_DELETE 106 +#define TK_UPDATE 107 +#define TK_SET 108 +#define TK_DEFERRABLE 109 +#define TK_FOREIGN 110 +#define TK_DROP 111 +#define TK_UNION 112 +#define TK_ALL 113 +#define TK_EXCEPT 114 +#define TK_INTERSECT 115 +#define TK_SELECT 116 +#define TK_DISTINCT 117 +#define TK_DOT 118 +#define TK_FROM 119 +#define TK_JOIN 120 +#define TK_USING 121 +#define TK_ORDER 122 +#define TK_GROUP 123 +#define TK_HAVING 124 +#define TK_LIMIT 125 +#define TK_WHERE 126 +#define TK_INTO 127 +#define TK_VALUES 128 +#define TK_INTEGER 129 +#define TK_FLOAT 130 +#define TK_BLOB 131 +#define TK_REGISTER 132 +#define TK_VARIABLE 133 +#define TK_CASE 134 +#define TK_WHEN 135 +#define TK_THEN 136 +#define TK_ELSE 137 +#define TK_INDEX 138 +#define TK_ALTER 139 +#define TK_ADD 140 +#define TK_TO_TEXT 141 +#define TK_TO_BLOB 142 +#define TK_TO_NUMERIC 143 +#define TK_TO_INT 144 +#define TK_TO_REAL 145 +#define TK_ISNOT 146 +#define TK_END_OF_FILE 147 +#define TK_ILLEGAL 148 +#define TK_SPACE 149 +#define TK_UNCLOSED_STRING 150 +#define TK_FUNCTION 151 +#define TK_COLUMN 152 +#define TK_AGG_FUNCTION 153 +#define TK_AGG_COLUMN 154 +#define TK_CONST_FUNC 155 +#define TK_UMINUS 156 +#define TK_UPLUS 157 + +/************** End of parse.h ***********************************************/ +/************** Continuing where we left off in sqliteInt.h ******************/ +#include +#include +#include +#include +#include + +/* +** If compiling for a processor that lacks floating point support, +** substitute integer for floating-point +*/ +#ifdef SQLITE_OMIT_FLOATING_POINT +# define double sqlite_int64 +# define float sqlite_int64 +# define LONGDOUBLE_TYPE sqlite_int64 +# ifndef SQLITE_BIG_DBL +# define SQLITE_BIG_DBL (((sqlite3_int64)1)<<50) +# endif +# define SQLITE_OMIT_DATETIME_FUNCS 1 +# define SQLITE_OMIT_TRACE 1 +# undef SQLITE_MIXED_ENDIAN_64BIT_FLOAT +# undef SQLITE_HAVE_ISNAN +#else +# ifdef __vax__ +# include +# define SQLITE_BIG_DBL DBL_MAX +# define SQLITE_HUGE_DBL DBL_MAX +# endif +#endif +#ifndef SQLITE_BIG_DBL +# define SQLITE_BIG_DBL (1e99) +#endif +#ifndef SQLITE_HUGE_DBL +# define SQLITE_HUGE_DBL (1.0e+308) +#endif + +/* +** OMIT_TEMPDB is set to 1 if SQLITE_OMIT_TEMPDB is defined, or 0 +** afterward. Having this macro allows us to cause the C compiler +** to omit code used by TEMP tables without messy #ifndef statements. +*/ +#ifdef SQLITE_OMIT_TEMPDB +#define OMIT_TEMPDB 1 +#else +#define OMIT_TEMPDB 0 +#endif + +/* +** The "file format" number is an integer that is incremented whenever +** the VDBE-level file format changes. The following macros define the +** the default file format for new databases and the maximum file format +** that the library can read. +*/ +#define SQLITE_MAX_FILE_FORMAT 4 +#ifndef SQLITE_DEFAULT_FILE_FORMAT +# define SQLITE_DEFAULT_FILE_FORMAT 4 +#endif + +/* +** Determine whether triggers are recursive by default. This can be +** changed at run-time using a pragma. +*/ +#ifndef SQLITE_DEFAULT_RECURSIVE_TRIGGERS +# define SQLITE_DEFAULT_RECURSIVE_TRIGGERS 0 +#endif + +/* +** Provide a default value for SQLITE_TEMP_STORE in case it is not specified +** on the command-line +*/ +#ifndef SQLITE_TEMP_STORE +# define SQLITE_TEMP_STORE 1 +#endif + +/* +** GCC does not define the offsetof() macro so we'll have to do it +** ourselves. +*/ +#ifndef offsetof +#define offsetof(STRUCTURE,FIELD) ((int)((char*)&((STRUCTURE*)0)->FIELD)) +#endif + +/* +** Check to see if this machine uses EBCDIC. (Yes, believe it or +** not, there are still machines out there that use EBCDIC.) +*/ +#if 'A' == '\301' +# define SQLITE_EBCDIC 1 +#else +# define SQLITE_ASCII 1 +#endif + +/* +** Integers of known sizes. These typedefs might change for architectures +** where the sizes very. Preprocessor macros are available so that the +** types can be conveniently redefined at compile-type. Like this: +** +** cc '-DUINTPTR_TYPE=long long int' ... +*/ +#ifndef UINT32_TYPE +# ifdef HAVE_UINT32_T +# define UINT32_TYPE uint32_t +# else +# define UINT32_TYPE unsigned int +# endif +#endif +#ifndef UINT16_TYPE +# ifdef HAVE_UINT16_T +# define UINT16_TYPE uint16_t +# else +# define UINT16_TYPE unsigned short int +# endif +#endif +#ifndef INT16_TYPE +# ifdef HAVE_INT16_T +# define INT16_TYPE int16_t +# else +# define INT16_TYPE short int +# endif +#endif +#ifndef UINT8_TYPE +# ifdef HAVE_UINT8_T +# define UINT8_TYPE uint8_t +# else +# define UINT8_TYPE unsigned char +# endif +#endif +#ifndef INT8_TYPE +# ifdef HAVE_INT8_T +# define INT8_TYPE int8_t +# else +# define INT8_TYPE signed char +# endif +#endif +#ifndef LONGDOUBLE_TYPE +# define LONGDOUBLE_TYPE long double +#endif +typedef sqlite_int64 i64; /* 8-byte signed integer */ +typedef sqlite_uint64 u64; /* 8-byte unsigned integer */ +typedef UINT32_TYPE u32; /* 4-byte unsigned integer */ +typedef UINT16_TYPE u16; /* 2-byte unsigned integer */ +typedef INT16_TYPE i16; /* 2-byte signed integer */ +typedef UINT8_TYPE u8; /* 1-byte unsigned integer */ +typedef INT8_TYPE i8; /* 1-byte signed integer */ + +/* +** SQLITE_MAX_U32 is a u64 constant that is the maximum u64 value +** that can be stored in a u32 without loss of data. The value +** is 0x00000000ffffffff. But because of quirks of some compilers, we +** have to specify the value in the less intuitive manner shown: +*/ +#define SQLITE_MAX_U32 ((((u64)1)<<32)-1) + +/* +** The datatype used to store estimates of the number of rows in a +** table or index. This is an unsigned integer type. For 99.9% of +** the world, a 32-bit integer is sufficient. But a 64-bit integer +** can be used at compile-time if desired. +*/ +#ifdef SQLITE_64BIT_STATS + typedef u64 tRowcnt; /* 64-bit only if requested at compile-time */ +#else + typedef u32 tRowcnt; /* 32-bit is the default */ +#endif + +/* +** Macros to determine whether the machine is big or little endian, +** evaluated at runtime. +*/ +#ifdef SQLITE_AMALGAMATION +SQLITE_PRIVATE const int sqlite3one = 1; +#else +SQLITE_PRIVATE const int sqlite3one; +#endif +#if defined(i386) || defined(__i386__) || defined(_M_IX86)\ + || defined(__x86_64) || defined(__x86_64__) +# define SQLITE_BIGENDIAN 0 +# define SQLITE_LITTLEENDIAN 1 +# define SQLITE_UTF16NATIVE SQLITE_UTF16LE +#else +# define SQLITE_BIGENDIAN (*(char *)(&sqlite3one)==0) +# define SQLITE_LITTLEENDIAN (*(char *)(&sqlite3one)==1) +# define SQLITE_UTF16NATIVE (SQLITE_BIGENDIAN?SQLITE_UTF16BE:SQLITE_UTF16LE) +#endif + +/* +** Constants for the largest and smallest possible 64-bit signed integers. +** These macros are designed to work correctly on both 32-bit and 64-bit +** compilers. +*/ +#define LARGEST_INT64 (0xffffffff|(((i64)0x7fffffff)<<32)) +#define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64) + +/* +** Round up a number to the next larger multiple of 8. This is used +** to force 8-byte alignment on 64-bit architectures. +*/ +#define ROUND8(x) (((x)+7)&~7) + +/* +** Round down to the nearest multiple of 8 +*/ +#define ROUNDDOWN8(x) ((x)&~7) + +/* +** Assert that the pointer X is aligned to an 8-byte boundary. This +** macro is used only within assert() to verify that the code gets +** all alignment restrictions correct. +** +** Except, if SQLITE_4_BYTE_ALIGNED_MALLOC is defined, then the +** underlying malloc() implemention might return us 4-byte aligned +** pointers. In that case, only verify 4-byte alignment. +*/ +#ifdef SQLITE_4_BYTE_ALIGNED_MALLOC +# define EIGHT_BYTE_ALIGNMENT(X) ((((char*)(X) - (char*)0)&3)==0) +#else +# define EIGHT_BYTE_ALIGNMENT(X) ((((char*)(X) - (char*)0)&7)==0) +#endif + + +/* +** An instance of the following structure is used to store the busy-handler +** callback for a given sqlite handle. +** +** The sqlite.busyHandler member of the sqlite struct contains the busy +** callback for the database handle. Each pager opened via the sqlite +** handle is passed a pointer to sqlite.busyHandler. The busy-handler +** callback is currently invoked only from within pager.c. +*/ +typedef struct BusyHandler BusyHandler; +struct BusyHandler { + int (*xFunc)(void *,int); /* The busy callback */ + void *pArg; /* First arg to busy callback */ + int nBusy; /* Incremented with each busy call */ +}; + +/* +** Name of the master database table. The master database table +** is a special table that holds the names and attributes of all +** user tables and indices. +*/ +#define MASTER_NAME "sqlite_master" +#define TEMP_MASTER_NAME "sqlite_temp_master" + +/* +** The root-page of the master database table. +*/ +#define MASTER_ROOT 1 + +/* +** The name of the schema table. +*/ +#define SCHEMA_TABLE(x) ((!OMIT_TEMPDB)&&(x==1)?TEMP_MASTER_NAME:MASTER_NAME) + +/* +** A convenience macro that returns the number of elements in +** an array. +*/ +#define ArraySize(X) ((int)(sizeof(X)/sizeof(X[0]))) + +/* +** The following value as a destructor means to use sqlite3DbFree(). +** This is an internal extension to SQLITE_STATIC and SQLITE_TRANSIENT. +*/ +#define SQLITE_DYNAMIC ((sqlite3_destructor_type)sqlite3DbFree) + +/* +** When SQLITE_OMIT_WSD is defined, it means that the target platform does +** not support Writable Static Data (WSD) such as global and static variables. +** All variables must either be on the stack or dynamically allocated from +** the heap. When WSD is unsupported, the variable declarations scattered +** throughout the SQLite code must become constants instead. The SQLITE_WSD +** macro is used for this purpose. And instead of referencing the variable +** directly, we use its constant as a key to lookup the run-time allocated +** buffer that holds real variable. The constant is also the initializer +** for the run-time allocated buffer. +** +** In the usual case where WSD is supported, the SQLITE_WSD and GLOBAL +** macros become no-ops and have zero performance impact. +*/ +#ifdef SQLITE_OMIT_WSD + #define SQLITE_WSD const + #define GLOBAL(t,v) (*(t*)sqlite3_wsd_find((void*)&(v), sizeof(v))) + #define sqlite3GlobalConfig GLOBAL(struct Sqlite3Config, sqlite3Config) +SQLITE_API int sqlite3_wsd_init(int N, int J); +SQLITE_API void *sqlite3_wsd_find(void *K, int L); +#else + #define SQLITE_WSD + #define GLOBAL(t,v) v + #define sqlite3GlobalConfig sqlite3Config +#endif + +/* +** The following macros are used to suppress compiler warnings and to +** make it clear to human readers when a function parameter is deliberately +** left unused within the body of a function. This usually happens when +** a function is called via a function pointer. For example the +** implementation of an SQL aggregate step callback may not use the +** parameter indicating the number of arguments passed to the aggregate, +** if it knows that this is enforced elsewhere. +** +** When a function parameter is not used at all within the body of a function, +** it is generally named "NotUsed" or "NotUsed2" to make things even clearer. +** However, these macros may also be used to suppress warnings related to +** parameters that may or may not be used depending on compilation options. +** For example those parameters only used in assert() statements. In these +** cases the parameters are named as per the usual conventions. +*/ +#define UNUSED_PARAMETER(x) (void)(x) +#define UNUSED_PARAMETER2(x,y) UNUSED_PARAMETER(x),UNUSED_PARAMETER(y) + +/* +** Forward references to structures +*/ +typedef struct AggInfo AggInfo; +typedef struct AuthContext AuthContext; +typedef struct AutoincInfo AutoincInfo; +typedef struct Bitvec Bitvec; +typedef struct CollSeq CollSeq; +typedef struct Column Column; +typedef struct Db Db; +typedef struct Schema Schema; +typedef struct Expr Expr; +typedef struct ExprList ExprList; +typedef struct ExprSpan ExprSpan; +typedef struct FKey FKey; +typedef struct FuncDestructor FuncDestructor; +typedef struct FuncDef FuncDef; +typedef struct FuncDefHash FuncDefHash; +typedef struct IdList IdList; +typedef struct Index Index; +typedef struct IndexSample IndexSample; +typedef struct KeyClass KeyClass; +typedef struct KeyInfo KeyInfo; +typedef struct Lookaside Lookaside; +typedef struct LookasideSlot LookasideSlot; +typedef struct Module Module; +typedef struct NameContext NameContext; +typedef struct Parse Parse; +typedef struct RowSet RowSet; +typedef struct Savepoint Savepoint; +typedef struct Select Select; +typedef struct SrcList SrcList; +typedef struct StrAccum StrAccum; +typedef struct Table Table; +typedef struct TableLock TableLock; +typedef struct Token Token; +typedef struct Trigger Trigger; +typedef struct TriggerPrg TriggerPrg; +typedef struct TriggerStep TriggerStep; +typedef struct UnpackedRecord UnpackedRecord; +typedef struct VTable VTable; +typedef struct VtabCtx VtabCtx; +typedef struct Walker Walker; +typedef struct WherePlan WherePlan; +typedef struct WhereInfo WhereInfo; +typedef struct WhereLevel WhereLevel; + +/* +** Defer sourcing vdbe.h and btree.h until after the "u8" and +** "BusyHandler" typedefs. vdbe.h also requires a few of the opaque +** pointer types (i.e. FuncDef) defined above. +*/ +/************** Include btree.h in the middle of sqliteInt.h *****************/ +/************** Begin file btree.h *******************************************/ +/* +** 2001 September 15 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This header file defines the interface that the sqlite B-Tree file +** subsystem. See comments in the source code for a detailed description +** of what each interface routine does. +*/ +#ifndef _BTREE_H_ +#define _BTREE_H_ + +/* TODO: This definition is just included so other modules compile. It +** needs to be revisited. +*/ +#define SQLITE_N_BTREE_META 10 + +/* +** If defined as non-zero, auto-vacuum is enabled by default. Otherwise +** it must be turned on for each database using "PRAGMA auto_vacuum = 1". +*/ +#ifndef SQLITE_DEFAULT_AUTOVACUUM + #define SQLITE_DEFAULT_AUTOVACUUM 0 +#endif + +#define BTREE_AUTOVACUUM_NONE 0 /* Do not do auto-vacuum */ +#define BTREE_AUTOVACUUM_FULL 1 /* Do full auto-vacuum */ +#define BTREE_AUTOVACUUM_INCR 2 /* Incremental vacuum */ + +/* +** Forward declarations of structure +*/ +typedef struct Btree Btree; +typedef struct BtCursor BtCursor; +typedef struct BtShared BtShared; + + +SQLITE_PRIVATE int sqlite3BtreeOpen( + sqlite3_vfs *pVfs, /* VFS to use with this b-tree */ + const char *zFilename, /* Name of database file to open */ + sqlite3 *db, /* Associated database connection */ + Btree **ppBtree, /* Return open Btree* here */ + int flags, /* Flags */ + int vfsFlags /* Flags passed through to VFS open */ +); + +/* The flags parameter to sqlite3BtreeOpen can be the bitwise or of the +** following values. +** +** NOTE: These values must match the corresponding PAGER_ values in +** pager.h. +*/ +#define BTREE_OMIT_JOURNAL 1 /* Do not create or use a rollback journal */ +#define BTREE_NO_READLOCK 2 /* Omit readlocks on readonly files */ +#define BTREE_MEMORY 4 /* This is an in-memory DB */ +#define BTREE_SINGLE 8 /* The file contains at most 1 b-tree */ +#define BTREE_UNORDERED 16 /* Use of a hash implementation is OK */ + +SQLITE_PRIVATE int sqlite3BtreeClose(Btree*); +SQLITE_PRIVATE int sqlite3BtreeSetCacheSize(Btree*,int); +SQLITE_PRIVATE int sqlite3BtreeSetSafetyLevel(Btree*,int,int,int); +SQLITE_PRIVATE int sqlite3BtreeSyncDisabled(Btree*); +SQLITE_PRIVATE int sqlite3BtreeSetPageSize(Btree *p, int nPagesize, int nReserve, int eFix); +SQLITE_PRIVATE int sqlite3BtreeGetPageSize(Btree*); +SQLITE_PRIVATE int sqlite3BtreeMaxPageCount(Btree*,int); +SQLITE_PRIVATE u32 sqlite3BtreeLastPage(Btree*); +SQLITE_PRIVATE int sqlite3BtreeSecureDelete(Btree*,int); +SQLITE_PRIVATE int sqlite3BtreeGetReserve(Btree*); +SQLITE_PRIVATE int sqlite3BtreeSetAutoVacuum(Btree *, int); +SQLITE_PRIVATE int sqlite3BtreeGetAutoVacuum(Btree *); +SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree*,int); +SQLITE_PRIVATE int sqlite3BtreeCommitPhaseOne(Btree*, const char *zMaster); +SQLITE_PRIVATE int sqlite3BtreeCommitPhaseTwo(Btree*, int); +SQLITE_PRIVATE int sqlite3BtreeCommit(Btree*); +SQLITE_PRIVATE int sqlite3BtreeRollback(Btree*); +SQLITE_PRIVATE int sqlite3BtreeBeginStmt(Btree*,int); +SQLITE_PRIVATE int sqlite3BtreeCreateTable(Btree*, int*, int flags); +SQLITE_PRIVATE int sqlite3BtreeIsInTrans(Btree*); +SQLITE_PRIVATE int sqlite3BtreeIsInReadTrans(Btree*); +SQLITE_PRIVATE int sqlite3BtreeIsInBackup(Btree*); +SQLITE_PRIVATE void *sqlite3BtreeSchema(Btree *, int, void(*)(void *)); +SQLITE_PRIVATE int sqlite3BtreeSchemaLocked(Btree *pBtree); +SQLITE_PRIVATE int sqlite3BtreeLockTable(Btree *pBtree, int iTab, u8 isWriteLock); +SQLITE_PRIVATE int sqlite3BtreeSavepoint(Btree *, int, int); + +SQLITE_PRIVATE const char *sqlite3BtreeGetFilename(Btree *); +SQLITE_PRIVATE const char *sqlite3BtreeGetJournalname(Btree *); +SQLITE_PRIVATE int sqlite3BtreeCopyFile(Btree *, Btree *); + +SQLITE_PRIVATE int sqlite3BtreeIncrVacuum(Btree *); + +/* The flags parameter to sqlite3BtreeCreateTable can be the bitwise OR +** of the flags shown below. +** +** Every SQLite table must have either BTREE_INTKEY or BTREE_BLOBKEY set. +** With BTREE_INTKEY, the table key is a 64-bit integer and arbitrary data +** is stored in the leaves. (BTREE_INTKEY is used for SQL tables.) With +** BTREE_BLOBKEY, the key is an arbitrary BLOB and no content is stored +** anywhere - the key is the content. (BTREE_BLOBKEY is used for SQL +** indices.) +*/ +#define BTREE_INTKEY 1 /* Table has only 64-bit signed integer keys */ +#define BTREE_BLOBKEY 2 /* Table has keys only - no data */ + +SQLITE_PRIVATE int sqlite3BtreeDropTable(Btree*, int, int*); +SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree*, int, int*); +SQLITE_PRIVATE void sqlite3BtreeTripAllCursors(Btree*, int); + +SQLITE_PRIVATE void sqlite3BtreeGetMeta(Btree *pBtree, int idx, u32 *pValue); +SQLITE_PRIVATE int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value); + +/* +** The second parameter to sqlite3BtreeGetMeta or sqlite3BtreeUpdateMeta +** should be one of the following values. The integer values are assigned +** to constants so that the offset of the corresponding field in an +** SQLite database header may be found using the following formula: +** +** offset = 36 + (idx * 4) +** +** For example, the free-page-count field is located at byte offset 36 of +** the database file header. The incr-vacuum-flag field is located at +** byte offset 64 (== 36+4*7). +*/ +#define BTREE_FREE_PAGE_COUNT 0 +#define BTREE_SCHEMA_VERSION 1 +#define BTREE_FILE_FORMAT 2 +#define BTREE_DEFAULT_CACHE_SIZE 3 +#define BTREE_LARGEST_ROOT_PAGE 4 +#define BTREE_TEXT_ENCODING 5 +#define BTREE_USER_VERSION 6 +#define BTREE_INCR_VACUUM 7 + +SQLITE_PRIVATE int sqlite3BtreeCursor( + Btree*, /* BTree containing table to open */ + int iTable, /* Index of root page */ + int wrFlag, /* 1 for writing. 0 for read-only */ + struct KeyInfo*, /* First argument to compare function */ + BtCursor *pCursor /* Space to write cursor structure */ +); +SQLITE_PRIVATE int sqlite3BtreeCursorSize(void); +SQLITE_PRIVATE void sqlite3BtreeCursorZero(BtCursor*); + +SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor*); +SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked( + BtCursor*, + UnpackedRecord *pUnKey, + i64 intKey, + int bias, + int *pRes +); +SQLITE_PRIVATE int sqlite3BtreeCursorHasMoved(BtCursor*, int*); +SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor*); +SQLITE_PRIVATE int sqlite3BtreeInsert(BtCursor*, const void *pKey, i64 nKey, + const void *pData, int nData, + int nZero, int bias, int seekResult); +SQLITE_PRIVATE int sqlite3BtreeFirst(BtCursor*, int *pRes); +SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor*, int *pRes); +SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor*, int *pRes); +SQLITE_PRIVATE int sqlite3BtreeEof(BtCursor*); +SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor*, int *pRes); +SQLITE_PRIVATE int sqlite3BtreeKeySize(BtCursor*, i64 *pSize); +SQLITE_PRIVATE int sqlite3BtreeKey(BtCursor*, u32 offset, u32 amt, void*); +SQLITE_PRIVATE const void *sqlite3BtreeKeyFetch(BtCursor*, int *pAmt); +SQLITE_PRIVATE const void *sqlite3BtreeDataFetch(BtCursor*, int *pAmt); +SQLITE_PRIVATE int sqlite3BtreeDataSize(BtCursor*, u32 *pSize); +SQLITE_PRIVATE int sqlite3BtreeData(BtCursor*, u32 offset, u32 amt, void*); +SQLITE_PRIVATE void sqlite3BtreeSetCachedRowid(BtCursor*, sqlite3_int64); +SQLITE_PRIVATE sqlite3_int64 sqlite3BtreeGetCachedRowid(BtCursor*); + +SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot, int, int*); +SQLITE_PRIVATE struct Pager *sqlite3BtreePager(Btree*); + +SQLITE_PRIVATE int sqlite3BtreePutData(BtCursor*, u32 offset, u32 amt, void*); +SQLITE_PRIVATE void sqlite3BtreeCacheOverflow(BtCursor *); +SQLITE_PRIVATE void sqlite3BtreeClearCursor(BtCursor *); + +SQLITE_PRIVATE int sqlite3BtreeSetVersion(Btree *pBt, int iVersion); + +#ifndef NDEBUG +SQLITE_PRIVATE int sqlite3BtreeCursorIsValid(BtCursor*); +#endif + +#ifndef SQLITE_OMIT_BTREECOUNT +SQLITE_PRIVATE int sqlite3BtreeCount(BtCursor *, i64 *); +#endif + +#ifdef SQLITE_TEST +SQLITE_PRIVATE int sqlite3BtreeCursorInfo(BtCursor*, int*, int); +SQLITE_PRIVATE void sqlite3BtreeCursorList(Btree*); +#endif + +#ifndef SQLITE_OMIT_WAL +SQLITE_PRIVATE int sqlite3BtreeCheckpoint(Btree*, int, int *, int *); +#endif + +/* +** If we are not using shared cache, then there is no need to +** use mutexes to access the BtShared structures. So make the +** Enter and Leave procedures no-ops. +*/ +#ifndef SQLITE_OMIT_SHARED_CACHE +SQLITE_PRIVATE void sqlite3BtreeEnter(Btree*); +SQLITE_PRIVATE void sqlite3BtreeEnterAll(sqlite3*); +#else +# define sqlite3BtreeEnter(X) +# define sqlite3BtreeEnterAll(X) +#endif + +#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE +SQLITE_PRIVATE int sqlite3BtreeSharable(Btree*); +SQLITE_PRIVATE void sqlite3BtreeLeave(Btree*); +SQLITE_PRIVATE void sqlite3BtreeEnterCursor(BtCursor*); +SQLITE_PRIVATE void sqlite3BtreeLeaveCursor(BtCursor*); +SQLITE_PRIVATE void sqlite3BtreeLeaveAll(sqlite3*); +#ifndef NDEBUG + /* These routines are used inside assert() statements only. */ +SQLITE_PRIVATE int sqlite3BtreeHoldsMutex(Btree*); +SQLITE_PRIVATE int sqlite3BtreeHoldsAllMutexes(sqlite3*); +SQLITE_PRIVATE int sqlite3SchemaMutexHeld(sqlite3*,int,Schema*); +#endif +#else + +# define sqlite3BtreeSharable(X) 0 +# define sqlite3BtreeLeave(X) +# define sqlite3BtreeEnterCursor(X) +# define sqlite3BtreeLeaveCursor(X) +# define sqlite3BtreeLeaveAll(X) + +# define sqlite3BtreeHoldsMutex(X) 1 +# define sqlite3BtreeHoldsAllMutexes(X) 1 +# define sqlite3SchemaMutexHeld(X,Y,Z) 1 +#endif + + +#endif /* _BTREE_H_ */ + +/************** End of btree.h ***********************************************/ +/************** Continuing where we left off in sqliteInt.h ******************/ +/************** Include vdbe.h in the middle of sqliteInt.h ******************/ +/************** Begin file vdbe.h ********************************************/ +/* +** 2001 September 15 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** Header file for the Virtual DataBase Engine (VDBE) +** +** This header defines the interface to the virtual database engine +** or VDBE. The VDBE implements an abstract machine that runs a +** simple program to access and modify the underlying database. +*/ +#ifndef _SQLITE_VDBE_H_ +#define _SQLITE_VDBE_H_ +/* #include */ + +/* +** A single VDBE is an opaque structure named "Vdbe". Only routines +** in the source file sqliteVdbe.c are allowed to see the insides +** of this structure. +*/ +typedef struct Vdbe Vdbe; + +/* +** The names of the following types declared in vdbeInt.h are required +** for the VdbeOp definition. +*/ +typedef struct VdbeFunc VdbeFunc; +typedef struct Mem Mem; +typedef struct SubProgram SubProgram; + +/* +** A single instruction of the virtual machine has an opcode +** and as many as three operands. The instruction is recorded +** as an instance of the following structure: +*/ +struct VdbeOp { + u8 opcode; /* What operation to perform */ + signed char p4type; /* One of the P4_xxx constants for p4 */ + u8 opflags; /* Mask of the OPFLG_* flags in opcodes.h */ + u8 p5; /* Fifth parameter is an unsigned character */ + int p1; /* First operand */ + int p2; /* Second parameter (often the jump destination) */ + int p3; /* The third parameter */ + union { /* fourth parameter */ + int i; /* Integer value if p4type==P4_INT32 */ + void *p; /* Generic pointer */ + char *z; /* Pointer to data for string (char array) types */ + i64 *pI64; /* Used when p4type is P4_INT64 */ + double *pReal; /* Used when p4type is P4_REAL */ + FuncDef *pFunc; /* Used when p4type is P4_FUNCDEF */ + VdbeFunc *pVdbeFunc; /* Used when p4type is P4_VDBEFUNC */ + CollSeq *pColl; /* Used when p4type is P4_COLLSEQ */ + Mem *pMem; /* Used when p4type is P4_MEM */ + VTable *pVtab; /* Used when p4type is P4_VTAB */ + KeyInfo *pKeyInfo; /* Used when p4type is P4_KEYINFO */ + int *ai; /* Used when p4type is P4_INTARRAY */ + SubProgram *pProgram; /* Used when p4type is P4_SUBPROGRAM */ + int (*xAdvance)(BtCursor *, int *); + } p4; +#ifdef SQLITE_DEBUG + char *zComment; /* Comment to improve readability */ +#endif +#ifdef VDBE_PROFILE + int cnt; /* Number of times this instruction was executed */ + u64 cycles; /* Total time spent executing this instruction */ +#endif +}; +typedef struct VdbeOp VdbeOp; + + +/* +** A sub-routine used to implement a trigger program. +*/ +struct SubProgram { + VdbeOp *aOp; /* Array of opcodes for sub-program */ + int nOp; /* Elements in aOp[] */ + int nMem; /* Number of memory cells required */ + int nCsr; /* Number of cursors required */ + int nOnce; /* Number of OP_Once instructions */ + void *token; /* id that may be used to recursive triggers */ + SubProgram *pNext; /* Next sub-program already visited */ +}; + +/* +** A smaller version of VdbeOp used for the VdbeAddOpList() function because +** it takes up less space. +*/ +struct VdbeOpList { + u8 opcode; /* What operation to perform */ + signed char p1; /* First operand */ + signed char p2; /* Second parameter (often the jump destination) */ + signed char p3; /* Third parameter */ +}; +typedef struct VdbeOpList VdbeOpList; + +/* +** Allowed values of VdbeOp.p4type +*/ +#define P4_NOTUSED 0 /* The P4 parameter is not used */ +#define P4_DYNAMIC (-1) /* Pointer to a string obtained from sqliteMalloc() */ +#define P4_STATIC (-2) /* Pointer to a static string */ +#define P4_COLLSEQ (-4) /* P4 is a pointer to a CollSeq structure */ +#define P4_FUNCDEF (-5) /* P4 is a pointer to a FuncDef structure */ +#define P4_KEYINFO (-6) /* P4 is a pointer to a KeyInfo structure */ +#define P4_VDBEFUNC (-7) /* P4 is a pointer to a VdbeFunc structure */ +#define P4_MEM (-8) /* P4 is a pointer to a Mem* structure */ +#define P4_TRANSIENT 0 /* P4 is a pointer to a transient string */ +#define P4_VTAB (-10) /* P4 is a pointer to an sqlite3_vtab structure */ +#define P4_MPRINTF (-11) /* P4 is a string obtained from sqlite3_mprintf() */ +#define P4_REAL (-12) /* P4 is a 64-bit floating point value */ +#define P4_INT64 (-13) /* P4 is a 64-bit signed integer */ +#define P4_INT32 (-14) /* P4 is a 32-bit signed integer */ +#define P4_INTARRAY (-15) /* P4 is a vector of 32-bit integers */ +#define P4_SUBPROGRAM (-18) /* P4 is a pointer to a SubProgram structure */ +#define P4_ADVANCE (-19) /* P4 is a pointer to BtreeNext() or BtreePrev() */ + +/* When adding a P4 argument using P4_KEYINFO, a copy of the KeyInfo structure +** is made. That copy is freed when the Vdbe is finalized. But if the +** argument is P4_KEYINFO_HANDOFF, the passed in pointer is used. It still +** gets freed when the Vdbe is finalized so it still should be obtained +** from a single sqliteMalloc(). But no copy is made and the calling +** function should *not* try to free the KeyInfo. +*/ +#define P4_KEYINFO_HANDOFF (-16) +#define P4_KEYINFO_STATIC (-17) + +/* +** The Vdbe.aColName array contains 5n Mem structures, where n is the +** number of columns of data returned by the statement. +*/ +#define COLNAME_NAME 0 +#define COLNAME_DECLTYPE 1 +#define COLNAME_DATABASE 2 +#define COLNAME_TABLE 3 +#define COLNAME_COLUMN 4 +#ifdef SQLITE_ENABLE_COLUMN_METADATA +# define COLNAME_N 5 /* Number of COLNAME_xxx symbols */ +#else +# ifdef SQLITE_OMIT_DECLTYPE +# define COLNAME_N 1 /* Store only the name */ +# else +# define COLNAME_N 2 /* Store the name and decltype */ +# endif +#endif + +/* +** The following macro converts a relative address in the p2 field +** of a VdbeOp structure into a negative number so that +** sqlite3VdbeAddOpList() knows that the address is relative. Calling +** the macro again restores the address. +*/ +#define ADDR(X) (-1-(X)) + +/* +** The makefile scans the vdbe.c source file and creates the "opcodes.h" +** header file that defines a number for each opcode used by the VDBE. +*/ +/************** Include opcodes.h in the middle of vdbe.h ********************/ +/************** Begin file opcodes.h *****************************************/ +/* Automatically generated. Do not edit */ +/* See the mkopcodeh.awk script for details */ +#define OP_Goto 1 +#define OP_Gosub 2 +#define OP_Return 3 +#define OP_Yield 4 +#define OP_HaltIfNull 5 +#define OP_Halt 6 +#define OP_Integer 7 +#define OP_Int64 8 +#define OP_Real 130 /* same as TK_FLOAT */ +#define OP_String8 94 /* same as TK_STRING */ +#define OP_String 9 +#define OP_Null 10 +#define OP_Blob 11 +#define OP_Variable 12 +#define OP_Move 13 +#define OP_Copy 14 +#define OP_SCopy 15 +#define OP_ResultRow 16 +#define OP_Concat 91 /* same as TK_CONCAT */ +#define OP_Add 86 /* same as TK_PLUS */ +#define OP_Subtract 87 /* same as TK_MINUS */ +#define OP_Multiply 88 /* same as TK_STAR */ +#define OP_Divide 89 /* same as TK_SLASH */ +#define OP_Remainder 90 /* same as TK_REM */ +#define OP_CollSeq 17 +#define OP_Function 18 +#define OP_BitAnd 82 /* same as TK_BITAND */ +#define OP_BitOr 83 /* same as TK_BITOR */ +#define OP_ShiftLeft 84 /* same as TK_LSHIFT */ +#define OP_ShiftRight 85 /* same as TK_RSHIFT */ +#define OP_AddImm 20 +#define OP_MustBeInt 21 +#define OP_RealAffinity 22 +#define OP_ToText 141 /* same as TK_TO_TEXT */ +#define OP_ToBlob 142 /* same as TK_TO_BLOB */ +#define OP_ToNumeric 143 /* same as TK_TO_NUMERIC*/ +#define OP_ToInt 144 /* same as TK_TO_INT */ +#define OP_ToReal 145 /* same as TK_TO_REAL */ +#define OP_Eq 76 /* same as TK_EQ */ +#define OP_Ne 75 /* same as TK_NE */ +#define OP_Lt 79 /* same as TK_LT */ +#define OP_Le 78 /* same as TK_LE */ +#define OP_Gt 77 /* same as TK_GT */ +#define OP_Ge 80 /* same as TK_GE */ +#define OP_Permutation 23 +#define OP_Compare 24 +#define OP_Jump 25 +#define OP_And 69 /* same as TK_AND */ +#define OP_Or 68 /* same as TK_OR */ +#define OP_Not 19 /* same as TK_NOT */ +#define OP_BitNot 93 /* same as TK_BITNOT */ +#define OP_Once 26 +#define OP_If 27 +#define OP_IfNot 28 +#define OP_IsNull 73 /* same as TK_ISNULL */ +#define OP_NotNull 74 /* same as TK_NOTNULL */ +#define OP_Column 29 +#define OP_Affinity 30 +#define OP_MakeRecord 31 +#define OP_Count 32 +#define OP_Savepoint 33 +#define OP_AutoCommit 34 +#define OP_Transaction 35 +#define OP_ReadCookie 36 +#define OP_SetCookie 37 +#define OP_VerifyCookie 38 +#define OP_OpenRead 39 +#define OP_OpenWrite 40 +#define OP_OpenAutoindex 41 +#define OP_OpenEphemeral 42 +#define OP_SorterOpen 43 +#define OP_OpenPseudo 44 +#define OP_Close 45 +#define OP_SeekLt 46 +#define OP_SeekLe 47 +#define OP_SeekGe 48 +#define OP_SeekGt 49 +#define OP_Seek 50 +#define OP_NotFound 51 +#define OP_Found 52 +#define OP_IsUnique 53 +#define OP_NotExists 54 +#define OP_Sequence 55 +#define OP_NewRowid 56 +#define OP_Insert 57 +#define OP_InsertInt 58 +#define OP_Delete 59 +#define OP_ResetCount 60 +#define OP_SorterCompare 61 +#define OP_SorterData 62 +#define OP_RowKey 63 +#define OP_RowData 64 +#define OP_Rowid 65 +#define OP_NullRow 66 +#define OP_Last 67 +#define OP_SorterSort 70 +#define OP_Sort 71 +#define OP_Rewind 72 +#define OP_SorterNext 81 +#define OP_Prev 92 +#define OP_Next 95 +#define OP_SorterInsert 96 +#define OP_IdxInsert 97 +#define OP_IdxDelete 98 +#define OP_IdxRowid 99 +#define OP_IdxLT 100 +#define OP_IdxGE 101 +#define OP_Destroy 102 +#define OP_Clear 103 +#define OP_CreateIndex 104 +#define OP_CreateTable 105 +#define OP_ParseSchema 106 +#define OP_LoadAnalysis 107 +#define OP_DropTable 108 +#define OP_DropIndex 109 +#define OP_DropTrigger 110 +#define OP_IntegrityCk 111 +#define OP_RowSetAdd 112 +#define OP_RowSetRead 113 +#define OP_RowSetTest 114 +#define OP_Program 115 +#define OP_Param 116 +#define OP_FkCounter 117 +#define OP_FkIfZero 118 +#define OP_MemMax 119 +#define OP_IfPos 120 +#define OP_IfNeg 121 +#define OP_IfZero 122 +#define OP_AggStep 123 +#define OP_AggFinal 124 +#define OP_Checkpoint 125 +#define OP_JournalMode 126 +#define OP_Vacuum 127 +#define OP_IncrVacuum 128 +#define OP_Expire 129 +#define OP_TableLock 131 +#define OP_VBegin 132 +#define OP_VCreate 133 +#define OP_VDestroy 134 +#define OP_VOpen 135 +#define OP_VFilter 136 +#define OP_VColumn 137 +#define OP_VNext 138 +#define OP_VRename 139 +#define OP_VUpdate 140 +#define OP_Pagecount 146 +#define OP_MaxPgcnt 147 +#define OP_Trace 148 +#define OP_Noop 149 +#define OP_Explain 150 + + +/* Properties such as "out2" or "jump" that are specified in +** comments following the "case" for each opcode in the vdbe.c +** are encoded into bitvectors as follows: +*/ +#define OPFLG_JUMP 0x0001 /* jump: P2 holds jmp target */ +#define OPFLG_OUT2_PRERELEASE 0x0002 /* out2-prerelease: */ +#define OPFLG_IN1 0x0004 /* in1: P1 is an input */ +#define OPFLG_IN2 0x0008 /* in2: P2 is an input */ +#define OPFLG_IN3 0x0010 /* in3: P3 is an input */ +#define OPFLG_OUT2 0x0020 /* out2: P2 is an output */ +#define OPFLG_OUT3 0x0040 /* out3: P3 is an output */ +#define OPFLG_INITIALIZER {\ +/* 0 */ 0x00, 0x01, 0x01, 0x04, 0x04, 0x10, 0x00, 0x02,\ +/* 8 */ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x24, 0x24,\ +/* 16 */ 0x00, 0x00, 0x00, 0x24, 0x04, 0x05, 0x04, 0x00,\ +/* 24 */ 0x00, 0x01, 0x01, 0x05, 0x05, 0x00, 0x00, 0x00,\ +/* 32 */ 0x02, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00,\ +/* 40 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11,\ +/* 48 */ 0x11, 0x11, 0x08, 0x11, 0x11, 0x11, 0x11, 0x02,\ +/* 56 */ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ +/* 64 */ 0x00, 0x02, 0x00, 0x01, 0x4c, 0x4c, 0x01, 0x01,\ +/* 72 */ 0x01, 0x05, 0x05, 0x15, 0x15, 0x15, 0x15, 0x15,\ +/* 80 */ 0x15, 0x01, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,\ +/* 88 */ 0x4c, 0x4c, 0x4c, 0x4c, 0x01, 0x24, 0x02, 0x01,\ +/* 96 */ 0x08, 0x08, 0x00, 0x02, 0x01, 0x01, 0x02, 0x00,\ +/* 104 */ 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ +/* 112 */ 0x0c, 0x45, 0x15, 0x01, 0x02, 0x00, 0x01, 0x08,\ +/* 120 */ 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00,\ +/* 128 */ 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,\ +/* 136 */ 0x01, 0x00, 0x01, 0x00, 0x00, 0x04, 0x04, 0x04,\ +/* 144 */ 0x04, 0x04, 0x02, 0x02, 0x00, 0x00, 0x00,} + +/************** End of opcodes.h *********************************************/ +/************** Continuing where we left off in vdbe.h ***********************/ + +/* +** Prototypes for the VDBE interface. See comments on the implementation +** for a description of what each of these routines does. +*/ +SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(sqlite3*); +SQLITE_PRIVATE int sqlite3VdbeAddOp0(Vdbe*,int); +SQLITE_PRIVATE int sqlite3VdbeAddOp1(Vdbe*,int,int); +SQLITE_PRIVATE int sqlite3VdbeAddOp2(Vdbe*,int,int,int); +SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe*,int,int,int,int); +SQLITE_PRIVATE int sqlite3VdbeAddOp4(Vdbe*,int,int,int,int,const char *zP4,int); +SQLITE_PRIVATE int sqlite3VdbeAddOp4Int(Vdbe*,int,int,int,int,int); +SQLITE_PRIVATE int sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp); +SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*); +SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe*, u32 addr, int P1); +SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe*, u32 addr, int P2); +SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe*, u32 addr, int P3); +SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe*, u8 P5); +SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe*, int addr); +SQLITE_PRIVATE void sqlite3VdbeChangeToNoop(Vdbe*, int addr); +SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N); +SQLITE_PRIVATE void sqlite3VdbeUsesBtree(Vdbe*, int); +SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe*, int); +SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Vdbe*); +SQLITE_PRIVATE void sqlite3VdbeRunOnlyOnce(Vdbe*); +SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe*); +SQLITE_PRIVATE void sqlite3VdbeDeleteObject(sqlite3*,Vdbe*); +SQLITE_PRIVATE void sqlite3VdbeMakeReady(Vdbe*,Parse*); +SQLITE_PRIVATE int sqlite3VdbeFinalize(Vdbe*); +SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe*, int); +SQLITE_PRIVATE int sqlite3VdbeCurrentAddr(Vdbe*); +#ifdef SQLITE_DEBUG +SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *, int); +SQLITE_PRIVATE void sqlite3VdbeTrace(Vdbe*,FILE*); +#endif +SQLITE_PRIVATE void sqlite3VdbeResetStepResult(Vdbe*); +SQLITE_PRIVATE void sqlite3VdbeRewind(Vdbe*); +SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe*); +SQLITE_PRIVATE void sqlite3VdbeSetNumCols(Vdbe*,int); +SQLITE_PRIVATE int sqlite3VdbeSetColName(Vdbe*, int, int, const char *, void(*)(void*)); +SQLITE_PRIVATE void sqlite3VdbeCountChanges(Vdbe*); +SQLITE_PRIVATE sqlite3 *sqlite3VdbeDb(Vdbe*); +SQLITE_PRIVATE void sqlite3VdbeSetSql(Vdbe*, const char *z, int n, int); +SQLITE_PRIVATE void sqlite3VdbeSwap(Vdbe*,Vdbe*); +SQLITE_PRIVATE VdbeOp *sqlite3VdbeTakeOpArray(Vdbe*, int*, int*); +SQLITE_PRIVATE sqlite3_value *sqlite3VdbeGetValue(Vdbe*, int, u8); +SQLITE_PRIVATE void sqlite3VdbeSetVarmask(Vdbe*, int); +#ifndef SQLITE_OMIT_TRACE +SQLITE_PRIVATE char *sqlite3VdbeExpandSql(Vdbe*, const char*); +#endif + +SQLITE_PRIVATE void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*); +SQLITE_PRIVATE int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*); +SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo *, char *, int, char **); + +#ifndef SQLITE_OMIT_TRIGGER +SQLITE_PRIVATE void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *); +#endif + + +#ifndef NDEBUG +SQLITE_PRIVATE void sqlite3VdbeComment(Vdbe*, const char*, ...); +# define VdbeComment(X) sqlite3VdbeComment X +SQLITE_PRIVATE void sqlite3VdbeNoopComment(Vdbe*, const char*, ...); +# define VdbeNoopComment(X) sqlite3VdbeNoopComment X +#else +# define VdbeComment(X) +# define VdbeNoopComment(X) +#endif + +#endif + +/************** End of vdbe.h ************************************************/ +/************** Continuing where we left off in sqliteInt.h ******************/ +/************** Include pager.h in the middle of sqliteInt.h *****************/ +/************** Begin file pager.h *******************************************/ +/* +** 2001 September 15 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This header file defines the interface that the sqlite page cache +** subsystem. The page cache subsystem reads and writes a file a page +** at a time and provides a journal for rollback. +*/ + +#ifndef _PAGER_H_ +#define _PAGER_H_ + +/* +** Default maximum size for persistent journal files. A negative +** value means no limit. This value may be overridden using the +** sqlite3PagerJournalSizeLimit() API. See also "PRAGMA journal_size_limit". +*/ +#ifndef SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT + #define SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT -1 +#endif + +/* +** The type used to represent a page number. The first page in a file +** is called page 1. 0 is used to represent "not a page". +*/ +typedef u32 Pgno; + +/* +** Each open file is managed by a separate instance of the "Pager" structure. +*/ +typedef struct Pager Pager; + +/* +** Handle type for pages. +*/ +typedef struct PgHdr DbPage; + +/* +** Page number PAGER_MJ_PGNO is never used in an SQLite database (it is +** reserved for working around a windows/posix incompatibility). It is +** used in the journal to signify that the remainder of the journal file +** is devoted to storing a master journal name - there are no more pages to +** roll back. See comments for function writeMasterJournal() in pager.c +** for details. +*/ +#define PAGER_MJ_PGNO(x) ((Pgno)((PENDING_BYTE/((x)->pageSize))+1)) + +/* +** Allowed values for the flags parameter to sqlite3PagerOpen(). +** +** NOTE: These values must match the corresponding BTREE_ values in btree.h. +*/ +#define PAGER_OMIT_JOURNAL 0x0001 /* Do not use a rollback journal */ +#define PAGER_NO_READLOCK 0x0002 /* Omit readlocks on readonly files */ +#define PAGER_MEMORY 0x0004 /* In-memory database */ + +/* +** Valid values for the second argument to sqlite3PagerLockingMode(). +*/ +#define PAGER_LOCKINGMODE_QUERY -1 +#define PAGER_LOCKINGMODE_NORMAL 0 +#define PAGER_LOCKINGMODE_EXCLUSIVE 1 + +/* +** Numeric constants that encode the journalmode. +*/ +#define PAGER_JOURNALMODE_QUERY (-1) /* Query the value of journalmode */ +#define PAGER_JOURNALMODE_DELETE 0 /* Commit by deleting journal file */ +#define PAGER_JOURNALMODE_PERSIST 1 /* Commit by zeroing journal header */ +#define PAGER_JOURNALMODE_OFF 2 /* Journal omitted. */ +#define PAGER_JOURNALMODE_TRUNCATE 3 /* Commit by truncating journal */ +#define PAGER_JOURNALMODE_MEMORY 4 /* In-memory journal file */ +#define PAGER_JOURNALMODE_WAL 5 /* Use write-ahead logging */ + +/* +** The remainder of this file contains the declarations of the functions +** that make up the Pager sub-system API. See source code comments for +** a detailed description of each routine. +*/ + +/* Open and close a Pager connection. */ +SQLITE_PRIVATE int sqlite3PagerOpen( + sqlite3_vfs*, + Pager **ppPager, + const char*, + int, + int, + int, + void(*)(DbPage*) +); +SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager); +SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager*, int, unsigned char*); + +/* Functions used to configure a Pager object. */ +SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(Pager*, int(*)(void *), void *); +SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager*, u32*, int); +SQLITE_PRIVATE int sqlite3PagerMaxPageCount(Pager*, int); +SQLITE_PRIVATE void sqlite3PagerSetCachesize(Pager*, int); +SQLITE_PRIVATE void sqlite3PagerShrink(Pager*); +SQLITE_PRIVATE void sqlite3PagerSetSafetyLevel(Pager*,int,int,int); +SQLITE_PRIVATE int sqlite3PagerLockingMode(Pager *, int); +SQLITE_PRIVATE int sqlite3PagerSetJournalMode(Pager *, int); +SQLITE_PRIVATE int sqlite3PagerGetJournalMode(Pager*); +SQLITE_PRIVATE int sqlite3PagerOkToChangeJournalMode(Pager*); +SQLITE_PRIVATE i64 sqlite3PagerJournalSizeLimit(Pager *, i64); +SQLITE_PRIVATE sqlite3_backup **sqlite3PagerBackupPtr(Pager*); + +/* Functions used to obtain and release page references. */ +SQLITE_PRIVATE int sqlite3PagerAcquire(Pager *pPager, Pgno pgno, DbPage **ppPage, int clrFlag); +#define sqlite3PagerGet(A,B,C) sqlite3PagerAcquire(A,B,C,0) +SQLITE_PRIVATE DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno); +SQLITE_PRIVATE void sqlite3PagerRef(DbPage*); +SQLITE_PRIVATE void sqlite3PagerUnref(DbPage*); + +/* Operations on page references. */ +SQLITE_PRIVATE int sqlite3PagerWrite(DbPage*); +SQLITE_PRIVATE void sqlite3PagerDontWrite(DbPage*); +SQLITE_PRIVATE int sqlite3PagerMovepage(Pager*,DbPage*,Pgno,int); +SQLITE_PRIVATE int sqlite3PagerPageRefcount(DbPage*); +SQLITE_PRIVATE void *sqlite3PagerGetData(DbPage *); +SQLITE_PRIVATE void *sqlite3PagerGetExtra(DbPage *); + +/* Functions used to manage pager transactions and savepoints. */ +SQLITE_PRIVATE void sqlite3PagerPagecount(Pager*, int*); +SQLITE_PRIVATE int sqlite3PagerBegin(Pager*, int exFlag, int); +SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(Pager*,const char *zMaster, int); +SQLITE_PRIVATE int sqlite3PagerExclusiveLock(Pager*); +SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager); +SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager*); +SQLITE_PRIVATE int sqlite3PagerRollback(Pager*); +SQLITE_PRIVATE int sqlite3PagerOpenSavepoint(Pager *pPager, int n); +SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint); +SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager); + +SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, int, int*, int*); +SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager); +SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager); +SQLITE_PRIVATE int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen); +SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager); + +/* Functions used to query pager state and configuration. */ +SQLITE_PRIVATE u8 sqlite3PagerIsreadonly(Pager*); +SQLITE_PRIVATE int sqlite3PagerRefcount(Pager*); +SQLITE_PRIVATE int sqlite3PagerMemUsed(Pager*); +SQLITE_PRIVATE const char *sqlite3PagerFilename(Pager*); +SQLITE_PRIVATE const sqlite3_vfs *sqlite3PagerVfs(Pager*); +SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager*); +SQLITE_PRIVATE const char *sqlite3PagerJournalname(Pager*); +SQLITE_PRIVATE int sqlite3PagerNosync(Pager*); +SQLITE_PRIVATE void *sqlite3PagerTempSpace(Pager*); +SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager*); +SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *, int, int, int *); +SQLITE_PRIVATE void sqlite3PagerClearCache(Pager *); + +/* Functions used to truncate the database file. */ +SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager*,Pgno); + +#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_WAL) +SQLITE_PRIVATE void *sqlite3PagerCodec(DbPage *); +#endif + +/* Functions to support testing and debugging. */ +#if !defined(NDEBUG) || defined(SQLITE_TEST) +SQLITE_PRIVATE Pgno sqlite3PagerPagenumber(DbPage*); +SQLITE_PRIVATE int sqlite3PagerIswriteable(DbPage*); +#endif +#ifdef SQLITE_TEST +SQLITE_PRIVATE int *sqlite3PagerStats(Pager*); +SQLITE_PRIVATE void sqlite3PagerRefdump(Pager*); + void disable_simulated_io_errors(void); + void enable_simulated_io_errors(void); +#else +# define disable_simulated_io_errors() +# define enable_simulated_io_errors() +#endif + +#endif /* _PAGER_H_ */ + +/************** End of pager.h ***********************************************/ +/************** Continuing where we left off in sqliteInt.h ******************/ +/************** Include pcache.h in the middle of sqliteInt.h ****************/ +/************** Begin file pcache.h ******************************************/ +/* +** 2008 August 05 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This header file defines the interface that the sqlite page cache +** subsystem. +*/ + +#ifndef _PCACHE_H_ + +typedef struct PgHdr PgHdr; +typedef struct PCache PCache; + +/* +** Every page in the cache is controlled by an instance of the following +** structure. +*/ +struct PgHdr { + sqlite3_pcache_page *pPage; /* Pcache object page handle */ + void *pData; /* Page data */ + void *pExtra; /* Extra content */ + PgHdr *pDirty; /* Transient list of dirty pages */ + Pgno pgno; /* Page number for this page */ + Pager *pPager; /* The pager this page is part of */ +#ifdef SQLITE_CHECK_PAGES + u32 pageHash; /* Hash of page content */ +#endif + u16 flags; /* PGHDR flags defined below */ + + /********************************************************************** + ** Elements above are public. All that follows is private to pcache.c + ** and should not be accessed by other modules. + */ + i16 nRef; /* Number of users of this page */ + PCache *pCache; /* Cache that owns this page */ + + PgHdr *pDirtyNext; /* Next element in list of dirty pages */ + PgHdr *pDirtyPrev; /* Previous element in list of dirty pages */ +}; + +/* Bit values for PgHdr.flags */ +#define PGHDR_DIRTY 0x002 /* Page has changed */ +#define PGHDR_NEED_SYNC 0x004 /* Fsync the rollback journal before + ** writing this page to the database */ +#define PGHDR_NEED_READ 0x008 /* Content is unread */ +#define PGHDR_REUSE_UNLIKELY 0x010 /* A hint that reuse is unlikely */ +#define PGHDR_DONT_WRITE 0x020 /* Do not write content to disk */ + +/* Initialize and shutdown the page cache subsystem */ +SQLITE_PRIVATE int sqlite3PcacheInitialize(void); +SQLITE_PRIVATE void sqlite3PcacheShutdown(void); + +/* Page cache buffer management: +** These routines implement SQLITE_CONFIG_PAGECACHE. +*/ +SQLITE_PRIVATE void sqlite3PCacheBufferSetup(void *, int sz, int n); + +/* Create a new pager cache. +** Under memory stress, invoke xStress to try to make pages clean. +** Only clean and unpinned pages can be reclaimed. +*/ +SQLITE_PRIVATE void sqlite3PcacheOpen( + int szPage, /* Size of every page */ + int szExtra, /* Extra space associated with each page */ + int bPurgeable, /* True if pages are on backing store */ + int (*xStress)(void*, PgHdr*), /* Call to try to make pages clean */ + void *pStress, /* Argument to xStress */ + PCache *pToInit /* Preallocated space for the PCache */ +); + +/* Modify the page-size after the cache has been created. */ +SQLITE_PRIVATE void sqlite3PcacheSetPageSize(PCache *, int); + +/* Return the size in bytes of a PCache object. Used to preallocate +** storage space. +*/ +SQLITE_PRIVATE int sqlite3PcacheSize(void); + +/* One release per successful fetch. Page is pinned until released. +** Reference counted. +*/ +SQLITE_PRIVATE int sqlite3PcacheFetch(PCache*, Pgno, int createFlag, PgHdr**); +SQLITE_PRIVATE void sqlite3PcacheRelease(PgHdr*); + +SQLITE_PRIVATE void sqlite3PcacheDrop(PgHdr*); /* Remove page from cache */ +SQLITE_PRIVATE void sqlite3PcacheMakeDirty(PgHdr*); /* Make sure page is marked dirty */ +SQLITE_PRIVATE void sqlite3PcacheMakeClean(PgHdr*); /* Mark a single page as clean */ +SQLITE_PRIVATE void sqlite3PcacheCleanAll(PCache*); /* Mark all dirty list pages as clean */ + +/* Change a page number. Used by incr-vacuum. */ +SQLITE_PRIVATE void sqlite3PcacheMove(PgHdr*, Pgno); + +/* Remove all pages with pgno>x. Reset the cache if x==0 */ +SQLITE_PRIVATE void sqlite3PcacheTruncate(PCache*, Pgno x); + +/* Get a list of all dirty pages in the cache, sorted by page number */ +SQLITE_PRIVATE PgHdr *sqlite3PcacheDirtyList(PCache*); + +/* Reset and close the cache object */ +SQLITE_PRIVATE void sqlite3PcacheClose(PCache*); + +/* Clear flags from pages of the page cache */ +SQLITE_PRIVATE void sqlite3PcacheClearSyncFlags(PCache *); + +/* Discard the contents of the cache */ +SQLITE_PRIVATE void sqlite3PcacheClear(PCache*); + +/* Return the total number of outstanding page references */ +SQLITE_PRIVATE int sqlite3PcacheRefCount(PCache*); + +/* Increment the reference count of an existing page */ +SQLITE_PRIVATE void sqlite3PcacheRef(PgHdr*); + +SQLITE_PRIVATE int sqlite3PcachePageRefcount(PgHdr*); + +/* Return the total number of pages stored in the cache */ +SQLITE_PRIVATE int sqlite3PcachePagecount(PCache*); + +#if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG) +/* Iterate through all dirty pages currently stored in the cache. This +** interface is only available if SQLITE_CHECK_PAGES is defined when the +** library is built. +*/ +SQLITE_PRIVATE void sqlite3PcacheIterateDirty(PCache *pCache, void (*xIter)(PgHdr *)); +#endif + +/* Set and get the suggested cache-size for the specified pager-cache. +** +** If no global maximum is configured, then the system attempts to limit +** the total number of pages cached by purgeable pager-caches to the sum +** of the suggested cache-sizes. +*/ +SQLITE_PRIVATE void sqlite3PcacheSetCachesize(PCache *, int); +#ifdef SQLITE_TEST +SQLITE_PRIVATE int sqlite3PcacheGetCachesize(PCache *); +#endif + +/* Free up as much memory as possible from the page cache */ +SQLITE_PRIVATE void sqlite3PcacheShrink(PCache*); + +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT +/* Try to return memory used by the pcache module to the main memory heap */ +SQLITE_PRIVATE int sqlite3PcacheReleaseMemory(int); +#endif + +#ifdef SQLITE_TEST +SQLITE_PRIVATE void sqlite3PcacheStats(int*,int*,int*,int*); +#endif + +SQLITE_PRIVATE void sqlite3PCacheSetDefault(void); + +#endif /* _PCACHE_H_ */ + +/************** End of pcache.h **********************************************/ +/************** Continuing where we left off in sqliteInt.h ******************/ + +/************** Include os.h in the middle of sqliteInt.h ********************/ +/************** Begin file os.h **********************************************/ +/* +** 2001 September 16 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +****************************************************************************** +** +** This header file (together with is companion C source-code file +** "os.c") attempt to abstract the underlying operating system so that +** the SQLite library will work on both POSIX and windows systems. +** +** This header file is #include-ed by sqliteInt.h and thus ends up +** being included by every source file. +*/ +#ifndef _SQLITE_OS_H_ +#define _SQLITE_OS_H_ + +/* +** Figure out if we are dealing with Unix, Windows, or some other +** operating system. After the following block of preprocess macros, +** all of SQLITE_OS_UNIX, SQLITE_OS_WIN, SQLITE_OS_OS2, and SQLITE_OS_OTHER +** will defined to either 1 or 0. One of the four will be 1. The other +** three will be 0. +*/ +#if defined(SQLITE_OS_OTHER) +# if SQLITE_OS_OTHER==1 +# undef SQLITE_OS_UNIX +# define SQLITE_OS_UNIX 0 +# undef SQLITE_OS_WIN +# define SQLITE_OS_WIN 0 +# undef SQLITE_OS_OS2 +# define SQLITE_OS_OS2 0 +# else +# undef SQLITE_OS_OTHER +# endif +#endif +#if !defined(SQLITE_OS_UNIX) && !defined(SQLITE_OS_OTHER) +# define SQLITE_OS_OTHER 0 +# ifndef SQLITE_OS_WIN +# if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__BORLANDC__) +# define SQLITE_OS_WIN 1 +# define SQLITE_OS_UNIX 0 +# define SQLITE_OS_OS2 0 +# elif defined(__EMX__) || defined(_OS2) || defined(OS2) || defined(_OS2_) || defined(__OS2__) +# define SQLITE_OS_WIN 0 +# define SQLITE_OS_UNIX 0 +# define SQLITE_OS_OS2 1 +# else +# define SQLITE_OS_WIN 0 +# define SQLITE_OS_UNIX 1 +# define SQLITE_OS_OS2 0 +# endif +# else +# define SQLITE_OS_UNIX 0 +# define SQLITE_OS_OS2 0 +# endif +#else +# ifndef SQLITE_OS_WIN +# define SQLITE_OS_WIN 0 +# endif +#endif + +/* +** Define the maximum size of a temporary filename +*/ +#if SQLITE_OS_WIN +# include +# define SQLITE_TEMPNAME_SIZE (MAX_PATH+50) +#elif SQLITE_OS_OS2 +# if (__GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ >= 3) && defined(OS2_HIGH_MEMORY) +# include /* has to be included before os2.h for linking to work */ +# endif +# define INCL_DOSDATETIME +# define INCL_DOSFILEMGR +# define INCL_DOSERRORS +# define INCL_DOSMISC +# define INCL_DOSPROCESS +# define INCL_DOSMODULEMGR +# define INCL_DOSSEMAPHORES +# include +# include +# define SQLITE_TEMPNAME_SIZE (CCHMAXPATHCOMP) +#else +# define SQLITE_TEMPNAME_SIZE 200 +#endif + +/* +** Determine if we are dealing with Windows NT. +*/ +#if defined(_WIN32_WINNT) +# define SQLITE_OS_WINNT 1 +#else +# define SQLITE_OS_WINNT 0 +#endif + +/* +** Determine if we are dealing with WindowsCE - which has a much +** reduced API. +*/ +#if defined(_WIN32_WCE) +# define SQLITE_OS_WINCE 1 +#else +# define SQLITE_OS_WINCE 0 +#endif + +/* If the SET_FULLSYNC macro is not defined above, then make it +** a no-op +*/ +#ifndef SET_FULLSYNC +# define SET_FULLSYNC(x,y) +#endif + +/* +** The default size of a disk sector +*/ +#ifndef SQLITE_DEFAULT_SECTOR_SIZE +# define SQLITE_DEFAULT_SECTOR_SIZE 4096 +#endif + +/* +** Temporary files are named starting with this prefix followed by 16 random +** alphanumeric characters, and no file extension. They are stored in the +** OS's standard temporary file directory, and are deleted prior to exit. +** If sqlite is being embedded in another program, you may wish to change the +** prefix to reflect your program's name, so that if your program exits +** prematurely, old temporary files can be easily identified. This can be done +** using -DSQLITE_TEMP_FILE_PREFIX=myprefix_ on the compiler command line. +** +** 2006-10-31: The default prefix used to be "sqlite_". But then +** Mcafee started using SQLite in their anti-virus product and it +** started putting files with the "sqlite" name in the c:/temp folder. +** This annoyed many windows users. Those users would then do a +** Google search for "sqlite", find the telephone numbers of the +** developers and call to wake them up at night and complain. +** For this reason, the default name prefix is changed to be "sqlite" +** spelled backwards. So the temp files are still identified, but +** anybody smart enough to figure out the code is also likely smart +** enough to know that calling the developer will not help get rid +** of the file. +*/ +#ifndef SQLITE_TEMP_FILE_PREFIX +# define SQLITE_TEMP_FILE_PREFIX "etilqs_" +#endif + +/* +** The following values may be passed as the second argument to +** sqlite3OsLock(). The various locks exhibit the following semantics: +** +** SHARED: Any number of processes may hold a SHARED lock simultaneously. +** RESERVED: A single process may hold a RESERVED lock on a file at +** any time. Other processes may hold and obtain new SHARED locks. +** PENDING: A single process may hold a PENDING lock on a file at +** any one time. Existing SHARED locks may persist, but no new +** SHARED locks may be obtained by other processes. +** EXCLUSIVE: An EXCLUSIVE lock precludes all other locks. +** +** PENDING_LOCK may not be passed directly to sqlite3OsLock(). Instead, a +** process that requests an EXCLUSIVE lock may actually obtain a PENDING +** lock. This can be upgraded to an EXCLUSIVE lock by a subsequent call to +** sqlite3OsLock(). +*/ +#define NO_LOCK 0 +#define SHARED_LOCK 1 +#define RESERVED_LOCK 2 +#define PENDING_LOCK 3 +#define EXCLUSIVE_LOCK 4 + +/* +** File Locking Notes: (Mostly about windows but also some info for Unix) +** +** We cannot use LockFileEx() or UnlockFileEx() on Win95/98/ME because +** those functions are not available. So we use only LockFile() and +** UnlockFile(). +** +** LockFile() prevents not just writing but also reading by other processes. +** A SHARED_LOCK is obtained by locking a single randomly-chosen +** byte out of a specific range of bytes. The lock byte is obtained at +** random so two separate readers can probably access the file at the +** same time, unless they are unlucky and choose the same lock byte. +** An EXCLUSIVE_LOCK is obtained by locking all bytes in the range. +** There can only be one writer. A RESERVED_LOCK is obtained by locking +** a single byte of the file that is designated as the reserved lock byte. +** A PENDING_LOCK is obtained by locking a designated byte different from +** the RESERVED_LOCK byte. +** +** On WinNT/2K/XP systems, LockFileEx() and UnlockFileEx() are available, +** which means we can use reader/writer locks. When reader/writer locks +** are used, the lock is placed on the same range of bytes that is used +** for probabilistic locking in Win95/98/ME. Hence, the locking scheme +** will support two or more Win95 readers or two or more WinNT readers. +** But a single Win95 reader will lock out all WinNT readers and a single +** WinNT reader will lock out all other Win95 readers. +** +** The following #defines specify the range of bytes used for locking. +** SHARED_SIZE is the number of bytes available in the pool from which +** a random byte is selected for a shared lock. The pool of bytes for +** shared locks begins at SHARED_FIRST. +** +** The same locking strategy and +** byte ranges are used for Unix. This leaves open the possiblity of having +** clients on win95, winNT, and unix all talking to the same shared file +** and all locking correctly. To do so would require that samba (or whatever +** tool is being used for file sharing) implements locks correctly between +** windows and unix. I'm guessing that isn't likely to happen, but by +** using the same locking range we are at least open to the possibility. +** +** Locking in windows is manditory. For this reason, we cannot store +** actual data in the bytes used for locking. The pager never allocates +** the pages involved in locking therefore. SHARED_SIZE is selected so +** that all locks will fit on a single page even at the minimum page size. +** PENDING_BYTE defines the beginning of the locks. By default PENDING_BYTE +** is set high so that we don't have to allocate an unused page except +** for very large databases. But one should test the page skipping logic +** by setting PENDING_BYTE low and running the entire regression suite. +** +** Changing the value of PENDING_BYTE results in a subtly incompatible +** file format. Depending on how it is changed, you might not notice +** the incompatibility right away, even running a full regression test. +** The default location of PENDING_BYTE is the first byte past the +** 1GB boundary. +** +*/ +#ifdef SQLITE_OMIT_WSD +# define PENDING_BYTE (0x40000000) +#else +# define PENDING_BYTE sqlite3PendingByte +#endif +#define RESERVED_BYTE (PENDING_BYTE+1) +#define SHARED_FIRST (PENDING_BYTE+2) +#define SHARED_SIZE 510 + +/* +** Wrapper around OS specific sqlite3_os_init() function. +*/ +SQLITE_PRIVATE int sqlite3OsInit(void); + +/* +** Functions for accessing sqlite3_file methods +*/ +SQLITE_PRIVATE int sqlite3OsClose(sqlite3_file*); +SQLITE_PRIVATE int sqlite3OsRead(sqlite3_file*, void*, int amt, i64 offset); +SQLITE_PRIVATE int sqlite3OsWrite(sqlite3_file*, const void*, int amt, i64 offset); +SQLITE_PRIVATE int sqlite3OsTruncate(sqlite3_file*, i64 size); +SQLITE_PRIVATE int sqlite3OsSync(sqlite3_file*, int); +SQLITE_PRIVATE int sqlite3OsFileSize(sqlite3_file*, i64 *pSize); +SQLITE_PRIVATE int sqlite3OsLock(sqlite3_file*, int); +SQLITE_PRIVATE int sqlite3OsUnlock(sqlite3_file*, int); +SQLITE_PRIVATE int sqlite3OsCheckReservedLock(sqlite3_file *id, int *pResOut); +SQLITE_PRIVATE int sqlite3OsFileControl(sqlite3_file*,int,void*); +SQLITE_PRIVATE void sqlite3OsFileControlHint(sqlite3_file*,int,void*); +#define SQLITE_FCNTL_DB_UNCHANGED 0xca093fa0 +SQLITE_PRIVATE int sqlite3OsSectorSize(sqlite3_file *id); +SQLITE_PRIVATE int sqlite3OsDeviceCharacteristics(sqlite3_file *id); +SQLITE_PRIVATE int sqlite3OsShmMap(sqlite3_file *,int,int,int,void volatile **); +SQLITE_PRIVATE int sqlite3OsShmLock(sqlite3_file *id, int, int, int); +SQLITE_PRIVATE void sqlite3OsShmBarrier(sqlite3_file *id); +SQLITE_PRIVATE int sqlite3OsShmUnmap(sqlite3_file *id, int); + + +/* +** Functions for accessing sqlite3_vfs methods +*/ +SQLITE_PRIVATE int sqlite3OsOpen(sqlite3_vfs *, const char *, sqlite3_file*, int, int *); +SQLITE_PRIVATE int sqlite3OsDelete(sqlite3_vfs *, const char *, int); +SQLITE_PRIVATE int sqlite3OsAccess(sqlite3_vfs *, const char *, int, int *pResOut); +SQLITE_PRIVATE int sqlite3OsFullPathname(sqlite3_vfs *, const char *, int, char *); +#ifndef SQLITE_OMIT_LOAD_EXTENSION +SQLITE_PRIVATE void *sqlite3OsDlOpen(sqlite3_vfs *, const char *); +SQLITE_PRIVATE void sqlite3OsDlError(sqlite3_vfs *, int, char *); +SQLITE_PRIVATE void (*sqlite3OsDlSym(sqlite3_vfs *, void *, const char *))(void); +SQLITE_PRIVATE void sqlite3OsDlClose(sqlite3_vfs *, void *); +#endif /* SQLITE_OMIT_LOAD_EXTENSION */ +SQLITE_PRIVATE int sqlite3OsRandomness(sqlite3_vfs *, int, char *); +SQLITE_PRIVATE int sqlite3OsSleep(sqlite3_vfs *, int); +SQLITE_PRIVATE int sqlite3OsCurrentTimeInt64(sqlite3_vfs *, sqlite3_int64*); + +/* +** Convenience functions for opening and closing files using +** sqlite3_malloc() to obtain space for the file-handle structure. +*/ +SQLITE_PRIVATE int sqlite3OsOpenMalloc(sqlite3_vfs *, const char *, sqlite3_file **, int,int*); +SQLITE_PRIVATE int sqlite3OsCloseFree(sqlite3_file *); + +#endif /* _SQLITE_OS_H_ */ + +/************** End of os.h **************************************************/ +/************** Continuing where we left off in sqliteInt.h ******************/ +/************** Include mutex.h in the middle of sqliteInt.h *****************/ +/************** Begin file mutex.h *******************************************/ +/* +** 2007 August 28 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** +** This file contains the common header for all mutex implementations. +** The sqliteInt.h header #includes this file so that it is available +** to all source files. We break it out in an effort to keep the code +** better organized. +** +** NOTE: source files should *not* #include this header file directly. +** Source files should #include the sqliteInt.h file and let that file +** include this one indirectly. +*/ + + +/* +** Figure out what version of the code to use. The choices are +** +** SQLITE_MUTEX_OMIT No mutex logic. Not even stubs. The +** mutexes implemention cannot be overridden +** at start-time. +** +** SQLITE_MUTEX_NOOP For single-threaded applications. No +** mutual exclusion is provided. But this +** implementation can be overridden at +** start-time. +** +** SQLITE_MUTEX_PTHREADS For multi-threaded applications on Unix. +** +** SQLITE_MUTEX_W32 For multi-threaded applications on Win32. +** +** SQLITE_MUTEX_OS2 For multi-threaded applications on OS/2. +*/ +#if !SQLITE_THREADSAFE +# define SQLITE_MUTEX_OMIT +#endif +#if SQLITE_THREADSAFE && !defined(SQLITE_MUTEX_NOOP) +# if SQLITE_OS_UNIX +# define SQLITE_MUTEX_PTHREADS +# elif SQLITE_OS_WIN +# define SQLITE_MUTEX_W32 +# elif SQLITE_OS_OS2 +# define SQLITE_MUTEX_OS2 +# else +# define SQLITE_MUTEX_NOOP +# endif +#endif + +#ifdef SQLITE_MUTEX_OMIT +/* +** If this is a no-op implementation, implement everything as macros. +*/ +#define sqlite3_mutex_alloc(X) ((sqlite3_mutex*)8) +#define sqlite3_mutex_free(X) +#define sqlite3_mutex_enter(X) +#define sqlite3_mutex_try(X) SQLITE_OK +#define sqlite3_mutex_leave(X) +#define sqlite3_mutex_held(X) ((void)(X),1) +#define sqlite3_mutex_notheld(X) ((void)(X),1) +#define sqlite3MutexAlloc(X) ((sqlite3_mutex*)8) +#define sqlite3MutexInit() SQLITE_OK +#define sqlite3MutexEnd() +#define MUTEX_LOGIC(X) +#else +#define MUTEX_LOGIC(X) X +#endif /* defined(SQLITE_MUTEX_OMIT) */ + +/************** End of mutex.h ***********************************************/ +/************** Continuing where we left off in sqliteInt.h ******************/ + + +/* +** Each database file to be accessed by the system is an instance +** of the following structure. There are normally two of these structures +** in the sqlite.aDb[] array. aDb[0] is the main database file and +** aDb[1] is the database file used to hold temporary tables. Additional +** databases may be attached. +*/ +struct Db { + char *zName; /* Name of this database */ + Btree *pBt; /* The B*Tree structure for this database file */ + u8 inTrans; /* 0: not writable. 1: Transaction. 2: Checkpoint */ + u8 safety_level; /* How aggressive at syncing data to disk */ + Schema *pSchema; /* Pointer to database schema (possibly shared) */ +}; + +/* +** An instance of the following structure stores a database schema. +** +** Most Schema objects are associated with a Btree. The exception is +** the Schema for the TEMP databaes (sqlite3.aDb[1]) which is free-standing. +** In shared cache mode, a single Schema object can be shared by multiple +** Btrees that refer to the same underlying BtShared object. +** +** Schema objects are automatically deallocated when the last Btree that +** references them is destroyed. The TEMP Schema is manually freed by +** sqlite3_close(). +* +** A thread must be holding a mutex on the corresponding Btree in order +** to access Schema content. This implies that the thread must also be +** holding a mutex on the sqlite3 connection pointer that owns the Btree. +** For a TEMP Schema, only the connection mutex is required. +*/ +struct Schema { + int schema_cookie; /* Database schema version number for this file */ + int iGeneration; /* Generation counter. Incremented with each change */ + Hash tblHash; /* All tables indexed by name */ + Hash idxHash; /* All (named) indices indexed by name */ + Hash trigHash; /* All triggers indexed by name */ + Hash fkeyHash; /* All foreign keys by referenced table name */ + Table *pSeqTab; /* The sqlite_sequence table used by AUTOINCREMENT */ + u8 file_format; /* Schema format version for this file */ + u8 enc; /* Text encoding used by this database */ + u16 flags; /* Flags associated with this schema */ + int cache_size; /* Number of pages to use in the cache */ +}; + +/* +** These macros can be used to test, set, or clear bits in the +** Db.pSchema->flags field. +*/ +#define DbHasProperty(D,I,P) (((D)->aDb[I].pSchema->flags&(P))==(P)) +#define DbHasAnyProperty(D,I,P) (((D)->aDb[I].pSchema->flags&(P))!=0) +#define DbSetProperty(D,I,P) (D)->aDb[I].pSchema->flags|=(P) +#define DbClearProperty(D,I,P) (D)->aDb[I].pSchema->flags&=~(P) + +/* +** Allowed values for the DB.pSchema->flags field. +** +** The DB_SchemaLoaded flag is set after the database schema has been +** read into internal hash tables. +** +** DB_UnresetViews means that one or more views have column names that +** have been filled out. If the schema changes, these column names might +** changes and so the view will need to be reset. +*/ +#define DB_SchemaLoaded 0x0001 /* The schema has been loaded */ +#define DB_UnresetViews 0x0002 /* Some views have defined column names */ +#define DB_Empty 0x0004 /* The file is empty (length 0 bytes) */ + +/* +** The number of different kinds of things that can be limited +** using the sqlite3_limit() interface. +*/ +#define SQLITE_N_LIMIT (SQLITE_LIMIT_TRIGGER_DEPTH+1) + +/* +** Lookaside malloc is a set of fixed-size buffers that can be used +** to satisfy small transient memory allocation requests for objects +** associated with a particular database connection. The use of +** lookaside malloc provides a significant performance enhancement +** (approx 10%) by avoiding numerous malloc/free requests while parsing +** SQL statements. +** +** The Lookaside structure holds configuration information about the +** lookaside malloc subsystem. Each available memory allocation in +** the lookaside subsystem is stored on a linked list of LookasideSlot +** objects. +** +** Lookaside allocations are only allowed for objects that are associated +** with a particular database connection. Hence, schema information cannot +** be stored in lookaside because in shared cache mode the schema information +** is shared by multiple database connections. Therefore, while parsing +** schema information, the Lookaside.bEnabled flag is cleared so that +** lookaside allocations are not used to construct the schema objects. +*/ +struct Lookaside { + u16 sz; /* Size of each buffer in bytes */ + u8 bEnabled; /* False to disable new lookaside allocations */ + u8 bMalloced; /* True if pStart obtained from sqlite3_malloc() */ + int nOut; /* Number of buffers currently checked out */ + int mxOut; /* Highwater mark for nOut */ + int anStat[3]; /* 0: hits. 1: size misses. 2: full misses */ + LookasideSlot *pFree; /* List of available buffers */ + void *pStart; /* First byte of available memory space */ + void *pEnd; /* First byte past end of available space */ +}; +struct LookasideSlot { + LookasideSlot *pNext; /* Next buffer in the list of free buffers */ +}; + +/* +** A hash table for function definitions. +** +** Hash each FuncDef structure into one of the FuncDefHash.a[] slots. +** Collisions are on the FuncDef.pHash chain. +*/ +struct FuncDefHash { + FuncDef *a[23]; /* Hash table for functions */ +}; + +/* +** Each database connection is an instance of the following structure. +** +** The sqlite.lastRowid records the last insert rowid generated by an +** insert statement. Inserts on views do not affect its value. Each +** trigger has its own context, so that lastRowid can be updated inside +** triggers as usual. The previous value will be restored once the trigger +** exits. Upon entering a before or instead of trigger, lastRowid is no +** longer (since after version 2.8.12) reset to -1. +** +** The sqlite.nChange does not count changes within triggers and keeps no +** context. It is reset at start of sqlite3_exec. +** The sqlite.lsChange represents the number of changes made by the last +** insert, update, or delete statement. It remains constant throughout the +** length of a statement and is then updated by OP_SetCounts. It keeps a +** context stack just like lastRowid so that the count of changes +** within a trigger is not seen outside the trigger. Changes to views do not +** affect the value of lsChange. +** The sqlite.csChange keeps track of the number of current changes (since +** the last statement) and is used to update sqlite_lsChange. +** +** The member variables sqlite.errCode, sqlite.zErrMsg and sqlite.zErrMsg16 +** store the most recent error code and, if applicable, string. The +** internal function sqlite3Error() is used to set these variables +** consistently. +*/ +struct sqlite3 { + sqlite3_vfs *pVfs; /* OS Interface */ + int nDb; /* Number of backends currently in use */ + Db *aDb; /* All backends */ + int flags; /* Miscellaneous flags. See below */ + unsigned int openFlags; /* Flags passed to sqlite3_vfs.xOpen() */ + int errCode; /* Most recent error code (SQLITE_*) */ + int errMask; /* & result codes with this before returning */ + u8 autoCommit; /* The auto-commit flag. */ + u8 temp_store; /* 1: file 2: memory 0: default */ + u8 mallocFailed; /* True if we have seen a malloc failure */ + u8 dfltLockMode; /* Default locking-mode for attached dbs */ + signed char nextAutovac; /* Autovac setting after VACUUM if >=0 */ + u8 suppressErr; /* Do not issue error messages if true */ + u8 vtabOnConflict; /* Value to return for s3_vtab_on_conflict() */ + int nextPagesize; /* Pagesize after VACUUM if >0 */ + int nTable; /* Number of tables in the database */ + CollSeq *pDfltColl; /* The default collating sequence (BINARY) */ + i64 lastRowid; /* ROWID of most recent insert (see above) */ + u32 magic; /* Magic number for detect library misuse */ + int nChange; /* Value returned by sqlite3_changes() */ + int nTotalChange; /* Value returned by sqlite3_total_changes() */ + sqlite3_mutex *mutex; /* Connection mutex */ + int aLimit[SQLITE_N_LIMIT]; /* Limits */ + struct sqlite3InitInfo { /* Information used during initialization */ + int iDb; /* When back is being initialized */ + int newTnum; /* Rootpage of table being initialized */ + u8 busy; /* TRUE if currently initializing */ + u8 orphanTrigger; /* Last statement is orphaned TEMP trigger */ + } init; + int nExtension; /* Number of loaded extensions */ + void **aExtension; /* Array of shared library handles */ + struct Vdbe *pVdbe; /* List of active virtual machines */ + int activeVdbeCnt; /* Number of VDBEs currently executing */ + int writeVdbeCnt; /* Number of active VDBEs that are writing */ + int vdbeExecCnt; /* Number of nested calls to VdbeExec() */ + void (*xTrace)(void*,const char*); /* Trace function */ + void *pTraceArg; /* Argument to the trace function */ + void (*xProfile)(void*,const char*,u64); /* Profiling function */ + void *pProfileArg; /* Argument to profile function */ + void *pCommitArg; /* Argument to xCommitCallback() */ + int (*xCommitCallback)(void*); /* Invoked at every commit. */ + void *pRollbackArg; /* Argument to xRollbackCallback() */ + void (*xRollbackCallback)(void*); /* Invoked at every commit. */ + void *pUpdateArg; + void (*xUpdateCallback)(void*,int, const char*,const char*,sqlite_int64); +#ifndef SQLITE_OMIT_WAL + int (*xWalCallback)(void *, sqlite3 *, const char *, int); + void *pWalArg; +#endif + void(*xCollNeeded)(void*,sqlite3*,int eTextRep,const char*); + void(*xCollNeeded16)(void*,sqlite3*,int eTextRep,const void*); + void *pCollNeededArg; + sqlite3_value *pErr; /* Most recent error message */ + char *zErrMsg; /* Most recent error message (UTF-8 encoded) */ + char *zErrMsg16; /* Most recent error message (UTF-16 encoded) */ + union { + volatile int isInterrupted; /* True if sqlite3_interrupt has been called */ + double notUsed1; /* Spacer */ + } u1; + Lookaside lookaside; /* Lookaside malloc configuration */ +#ifndef SQLITE_OMIT_AUTHORIZATION + int (*xAuth)(void*,int,const char*,const char*,const char*,const char*); + /* Access authorization function */ + void *pAuthArg; /* 1st argument to the access auth function */ +#endif +#ifndef SQLITE_OMIT_PROGRESS_CALLBACK + int (*xProgress)(void *); /* The progress callback */ + void *pProgressArg; /* Argument to the progress callback */ + int nProgressOps; /* Number of opcodes for progress callback */ +#endif +#ifndef SQLITE_OMIT_VIRTUALTABLE + Hash aModule; /* populated by sqlite3_create_module() */ + VtabCtx *pVtabCtx; /* Context for active vtab connect/create */ + VTable **aVTrans; /* Virtual tables with open transactions */ + int nVTrans; /* Allocated size of aVTrans */ + VTable *pDisconnect; /* Disconnect these in next sqlite3_prepare() */ +#endif + FuncDefHash aFunc; /* Hash table of connection functions */ + Hash aCollSeq; /* All collating sequences */ + BusyHandler busyHandler; /* Busy callback */ + int busyTimeout; /* Busy handler timeout, in msec */ + Db aDbStatic[2]; /* Static space for the 2 default backends */ + Savepoint *pSavepoint; /* List of active savepoints */ + int nSavepoint; /* Number of non-transaction savepoints */ + int nStatement; /* Number of nested statement-transactions */ + u8 isTransactionSavepoint; /* True if the outermost savepoint is a TS */ + i64 nDeferredCons; /* Net deferred constraints this transaction. */ + int *pnBytesFreed; /* If not NULL, increment this in DbFree() */ + +#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY + /* The following variables are all protected by the STATIC_MASTER + ** mutex, not by sqlite3.mutex. They are used by code in notify.c. + ** + ** When X.pUnlockConnection==Y, that means that X is waiting for Y to + ** unlock so that it can proceed. + ** + ** When X.pBlockingConnection==Y, that means that something that X tried + ** tried to do recently failed with an SQLITE_LOCKED error due to locks + ** held by Y. + */ + sqlite3 *pBlockingConnection; /* Connection that caused SQLITE_LOCKED */ + sqlite3 *pUnlockConnection; /* Connection to watch for unlock */ + void *pUnlockArg; /* Argument to xUnlockNotify */ + void (*xUnlockNotify)(void **, int); /* Unlock notify callback */ + sqlite3 *pNextBlocked; /* Next in list of all blocked connections */ +#endif +}; + +/* +** A macro to discover the encoding of a database. +*/ +#define ENC(db) ((db)->aDb[0].pSchema->enc) + +/* +** Possible values for the sqlite3.flags. +*/ +#define SQLITE_VdbeTrace 0x00000100 /* True to trace VDBE execution */ +#define SQLITE_InternChanges 0x00000200 /* Uncommitted Hash table changes */ +#define SQLITE_FullColNames 0x00000400 /* Show full column names on SELECT */ +#define SQLITE_ShortColNames 0x00000800 /* Show short columns names */ +#define SQLITE_CountRows 0x00001000 /* Count rows changed by INSERT, */ + /* DELETE, or UPDATE and return */ + /* the count using a callback. */ +#define SQLITE_NullCallback 0x00002000 /* Invoke the callback once if the */ + /* result set is empty */ +#define SQLITE_SqlTrace 0x00004000 /* Debug print SQL as it executes */ +#define SQLITE_VdbeListing 0x00008000 /* Debug listings of VDBE programs */ +#define SQLITE_WriteSchema 0x00010000 /* OK to update SQLITE_MASTER */ +#define SQLITE_NoReadlock 0x00020000 /* Readlocks are omitted when + ** accessing read-only databases */ +#define SQLITE_IgnoreChecks 0x00040000 /* Do not enforce check constraints */ +#define SQLITE_ReadUncommitted 0x0080000 /* For shared-cache mode */ +#define SQLITE_LegacyFileFmt 0x00100000 /* Create new databases in format 1 */ +#define SQLITE_FullFSync 0x00200000 /* Use full fsync on the backend */ +#define SQLITE_CkptFullFSync 0x00400000 /* Use full fsync for checkpoint */ +#define SQLITE_RecoveryMode 0x00800000 /* Ignore schema errors */ +#define SQLITE_ReverseOrder 0x01000000 /* Reverse unordered SELECTs */ +#define SQLITE_RecTriggers 0x02000000 /* Enable recursive triggers */ +#define SQLITE_ForeignKeys 0x04000000 /* Enforce foreign key constraints */ +#define SQLITE_AutoIndex 0x08000000 /* Enable automatic indexes */ +#define SQLITE_PreferBuiltin 0x10000000 /* Preference to built-in funcs */ +#define SQLITE_LoadExtension 0x20000000 /* Enable load_extension */ +#define SQLITE_EnableTrigger 0x40000000 /* True to enable triggers */ + +/* +** Bits of the sqlite3.flags field that are used by the +** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface. +** These must be the low-order bits of the flags field. +*/ +#define SQLITE_QueryFlattener 0x01 /* Disable query flattening */ +#define SQLITE_ColumnCache 0x02 /* Disable the column cache */ +#define SQLITE_IndexSort 0x04 /* Disable indexes for sorting */ +#define SQLITE_IndexSearch 0x08 /* Disable indexes for searching */ +#define SQLITE_IndexCover 0x10 /* Disable index covering table */ +#define SQLITE_GroupByOrder 0x20 /* Disable GROUPBY cover of ORDERBY */ +#define SQLITE_FactorOutConst 0x40 /* Disable factoring out constants */ +#define SQLITE_IdxRealAsInt 0x80 /* Store REAL as INT in indices */ +#define SQLITE_DistinctOpt 0x80 /* DISTINCT using indexes */ +#define SQLITE_OptMask 0xff /* Mask of all disablable opts */ + +/* +** Possible values for the sqlite.magic field. +** The numbers are obtained at random and have no special meaning, other +** than being distinct from one another. +*/ +#define SQLITE_MAGIC_OPEN 0xa029a697 /* Database is open */ +#define SQLITE_MAGIC_CLOSED 0x9f3c2d33 /* Database is closed */ +#define SQLITE_MAGIC_SICK 0x4b771290 /* Error and awaiting close */ +#define SQLITE_MAGIC_BUSY 0xf03b7906 /* Database currently in use */ +#define SQLITE_MAGIC_ERROR 0xb5357930 /* An SQLITE_MISUSE error occurred */ + +/* +** Each SQL function is defined by an instance of the following +** structure. A pointer to this structure is stored in the sqlite.aFunc +** hash table. When multiple functions have the same name, the hash table +** points to a linked list of these structures. +*/ +struct FuncDef { + i16 nArg; /* Number of arguments. -1 means unlimited */ + u8 iPrefEnc; /* Preferred text encoding (SQLITE_UTF8, 16LE, 16BE) */ + u8 flags; /* Some combination of SQLITE_FUNC_* */ + void *pUserData; /* User data parameter */ + FuncDef *pNext; /* Next function with same name */ + void (*xFunc)(sqlite3_context*,int,sqlite3_value**); /* Regular function */ + void (*xStep)(sqlite3_context*,int,sqlite3_value**); /* Aggregate step */ + void (*xFinalize)(sqlite3_context*); /* Aggregate finalizer */ + char *zName; /* SQL name of the function. */ + FuncDef *pHash; /* Next with a different name but the same hash */ + FuncDestructor *pDestructor; /* Reference counted destructor function */ +}; + +/* +** This structure encapsulates a user-function destructor callback (as +** configured using create_function_v2()) and a reference counter. When +** create_function_v2() is called to create a function with a destructor, +** a single object of this type is allocated. FuncDestructor.nRef is set to +** the number of FuncDef objects created (either 1 or 3, depending on whether +** or not the specified encoding is SQLITE_ANY). The FuncDef.pDestructor +** member of each of the new FuncDef objects is set to point to the allocated +** FuncDestructor. +** +** Thereafter, when one of the FuncDef objects is deleted, the reference +** count on this object is decremented. When it reaches 0, the destructor +** is invoked and the FuncDestructor structure freed. +*/ +struct FuncDestructor { + int nRef; + void (*xDestroy)(void *); + void *pUserData; +}; + +/* +** Possible values for FuncDef.flags +*/ +#define SQLITE_FUNC_LIKE 0x01 /* Candidate for the LIKE optimization */ +#define SQLITE_FUNC_CASE 0x02 /* Case-sensitive LIKE-type function */ +#define SQLITE_FUNC_EPHEM 0x04 /* Ephemeral. Delete with VDBE */ +#define SQLITE_FUNC_NEEDCOLL 0x08 /* sqlite3GetFuncCollSeq() might be called */ +#define SQLITE_FUNC_PRIVATE 0x10 /* Allowed for internal use only */ +#define SQLITE_FUNC_COUNT 0x20 /* Built-in count(*) aggregate */ +#define SQLITE_FUNC_COALESCE 0x40 /* Built-in coalesce() or ifnull() function */ + +/* +** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are +** used to create the initializers for the FuncDef structures. +** +** FUNCTION(zName, nArg, iArg, bNC, xFunc) +** Used to create a scalar function definition of a function zName +** implemented by C function xFunc that accepts nArg arguments. The +** value passed as iArg is cast to a (void*) and made available +** as the user-data (sqlite3_user_data()) for the function. If +** argument bNC is true, then the SQLITE_FUNC_NEEDCOLL flag is set. +** +** AGGREGATE(zName, nArg, iArg, bNC, xStep, xFinal) +** Used to create an aggregate function definition implemented by +** the C functions xStep and xFinal. The first four parameters +** are interpreted in the same way as the first 4 parameters to +** FUNCTION(). +** +** LIKEFUNC(zName, nArg, pArg, flags) +** Used to create a scalar function definition of a function zName +** that accepts nArg arguments and is implemented by a call to C +** function likeFunc. Argument pArg is cast to a (void *) and made +** available as the function user-data (sqlite3_user_data()). The +** FuncDef.flags variable is set to the value passed as the flags +** parameter. +*/ +#define FUNCTION(zName, nArg, iArg, bNC, xFunc) \ + {nArg, SQLITE_UTF8, bNC*SQLITE_FUNC_NEEDCOLL, \ + SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, #zName, 0, 0} +#define STR_FUNCTION(zName, nArg, pArg, bNC, xFunc) \ + {nArg, SQLITE_UTF8, bNC*SQLITE_FUNC_NEEDCOLL, \ + pArg, 0, xFunc, 0, 0, #zName, 0, 0} +#define LIKEFUNC(zName, nArg, arg, flags) \ + {nArg, SQLITE_UTF8, flags, (void *)arg, 0, likeFunc, 0, 0, #zName, 0, 0} +#define AGGREGATE(zName, nArg, arg, nc, xStep, xFinal) \ + {nArg, SQLITE_UTF8, nc*SQLITE_FUNC_NEEDCOLL, \ + SQLITE_INT_TO_PTR(arg), 0, 0, xStep,xFinal,#zName,0,0} + +/* +** All current savepoints are stored in a linked list starting at +** sqlite3.pSavepoint. The first element in the list is the most recently +** opened savepoint. Savepoints are added to the list by the vdbe +** OP_Savepoint instruction. +*/ +struct Savepoint { + char *zName; /* Savepoint name (nul-terminated) */ + i64 nDeferredCons; /* Number of deferred fk violations */ + Savepoint *pNext; /* Parent savepoint (if any) */ +}; + +/* +** The following are used as the second parameter to sqlite3Savepoint(), +** and as the P1 argument to the OP_Savepoint instruction. +*/ +#define SAVEPOINT_BEGIN 0 +#define SAVEPOINT_RELEASE 1 +#define SAVEPOINT_ROLLBACK 2 + + +/* +** Each SQLite module (virtual table definition) is defined by an +** instance of the following structure, stored in the sqlite3.aModule +** hash table. +*/ +struct Module { + const sqlite3_module *pModule; /* Callback pointers */ + const char *zName; /* Name passed to create_module() */ + void *pAux; /* pAux passed to create_module() */ + void (*xDestroy)(void *); /* Module destructor function */ +}; + +/* +** information about each column of an SQL table is held in an instance +** of this structure. +*/ +struct Column { + char *zName; /* Name of this column */ + Expr *pDflt; /* Default value of this column */ + char *zDflt; /* Original text of the default value */ + char *zType; /* Data type for this column */ + char *zColl; /* Collating sequence. If NULL, use the default */ + u8 notNull; /* True if there is a NOT NULL constraint */ + u8 isPrimKey; /* True if this column is part of the PRIMARY KEY */ + char affinity; /* One of the SQLITE_AFF_... values */ +#ifndef SQLITE_OMIT_VIRTUALTABLE + u8 isHidden; /* True if this column is 'hidden' */ +#endif +}; + +/* +** A "Collating Sequence" is defined by an instance of the following +** structure. Conceptually, a collating sequence consists of a name and +** a comparison routine that defines the order of that sequence. +** +** There may two separate implementations of the collation function, one +** that processes text in UTF-8 encoding (CollSeq.xCmp) and another that +** processes text encoded in UTF-16 (CollSeq.xCmp16), using the machine +** native byte order. When a collation sequence is invoked, SQLite selects +** the version that will require the least expensive encoding +** translations, if any. +** +** The CollSeq.pUser member variable is an extra parameter that passed in +** as the first argument to the UTF-8 comparison function, xCmp. +** CollSeq.pUser16 is the equivalent for the UTF-16 comparison function, +** xCmp16. +** +** If both CollSeq.xCmp and CollSeq.xCmp16 are NULL, it means that the +** collating sequence is undefined. Indices built on an undefined +** collating sequence may not be read or written. +*/ +struct CollSeq { + char *zName; /* Name of the collating sequence, UTF-8 encoded */ + u8 enc; /* Text encoding handled by xCmp() */ + void *pUser; /* First argument to xCmp() */ + int (*xCmp)(void*,int, const void*, int, const void*); + void (*xDel)(void*); /* Destructor for pUser */ +}; + +/* +** A sort order can be either ASC or DESC. +*/ +#define SQLITE_SO_ASC 0 /* Sort in ascending order */ +#define SQLITE_SO_DESC 1 /* Sort in ascending order */ + +/* +** Column affinity types. +** +** These used to have mnemonic name like 'i' for SQLITE_AFF_INTEGER and +** 't' for SQLITE_AFF_TEXT. But we can save a little space and improve +** the speed a little by numbering the values consecutively. +** +** But rather than start with 0 or 1, we begin with 'a'. That way, +** when multiple affinity types are concatenated into a string and +** used as the P4 operand, they will be more readable. +** +** Note also that the numeric types are grouped together so that testing +** for a numeric type is a single comparison. +*/ +#define SQLITE_AFF_TEXT 'a' +#define SQLITE_AFF_NONE 'b' +#define SQLITE_AFF_NUMERIC 'c' +#define SQLITE_AFF_INTEGER 'd' +#define SQLITE_AFF_REAL 'e' + +#define sqlite3IsNumericAffinity(X) ((X)>=SQLITE_AFF_NUMERIC) + +/* +** The SQLITE_AFF_MASK values masks off the significant bits of an +** affinity value. +*/ +#define SQLITE_AFF_MASK 0x67 + +/* +** Additional bit values that can be ORed with an affinity without +** changing the affinity. +*/ +#define SQLITE_JUMPIFNULL 0x08 /* jumps if either operand is NULL */ +#define SQLITE_STOREP2 0x10 /* Store result in reg[P2] rather than jump */ +#define SQLITE_NULLEQ 0x80 /* NULL=NULL */ + +/* +** An object of this type is created for each virtual table present in +** the database schema. +** +** If the database schema is shared, then there is one instance of this +** structure for each database connection (sqlite3*) that uses the shared +** schema. This is because each database connection requires its own unique +** instance of the sqlite3_vtab* handle used to access the virtual table +** implementation. sqlite3_vtab* handles can not be shared between +** database connections, even when the rest of the in-memory database +** schema is shared, as the implementation often stores the database +** connection handle passed to it via the xConnect() or xCreate() method +** during initialization internally. This database connection handle may +** then be used by the virtual table implementation to access real tables +** within the database. So that they appear as part of the callers +** transaction, these accesses need to be made via the same database +** connection as that used to execute SQL operations on the virtual table. +** +** All VTable objects that correspond to a single table in a shared +** database schema are initially stored in a linked-list pointed to by +** the Table.pVTable member variable of the corresponding Table object. +** When an sqlite3_prepare() operation is required to access the virtual +** table, it searches the list for the VTable that corresponds to the +** database connection doing the preparing so as to use the correct +** sqlite3_vtab* handle in the compiled query. +** +** When an in-memory Table object is deleted (for example when the +** schema is being reloaded for some reason), the VTable objects are not +** deleted and the sqlite3_vtab* handles are not xDisconnect()ed +** immediately. Instead, they are moved from the Table.pVTable list to +** another linked list headed by the sqlite3.pDisconnect member of the +** corresponding sqlite3 structure. They are then deleted/xDisconnected +** next time a statement is prepared using said sqlite3*. This is done +** to avoid deadlock issues involving multiple sqlite3.mutex mutexes. +** Refer to comments above function sqlite3VtabUnlockList() for an +** explanation as to why it is safe to add an entry to an sqlite3.pDisconnect +** list without holding the corresponding sqlite3.mutex mutex. +** +** The memory for objects of this type is always allocated by +** sqlite3DbMalloc(), using the connection handle stored in VTable.db as +** the first argument. +*/ +struct VTable { + sqlite3 *db; /* Database connection associated with this table */ + Module *pMod; /* Pointer to module implementation */ + sqlite3_vtab *pVtab; /* Pointer to vtab instance */ + int nRef; /* Number of pointers to this structure */ + u8 bConstraint; /* True if constraints are supported */ + int iSavepoint; /* Depth of the SAVEPOINT stack */ + VTable *pNext; /* Next in linked list (see above) */ +}; + +/* +** Each SQL table is represented in memory by an instance of the +** following structure. +** +** Table.zName is the name of the table. The case of the original +** CREATE TABLE statement is stored, but case is not significant for +** comparisons. +** +** Table.nCol is the number of columns in this table. Table.aCol is a +** pointer to an array of Column structures, one for each column. +** +** If the table has an INTEGER PRIMARY KEY, then Table.iPKey is the index of +** the column that is that key. Otherwise Table.iPKey is negative. Note +** that the datatype of the PRIMARY KEY must be INTEGER for this field to +** be set. An INTEGER PRIMARY KEY is used as the rowid for each row of +** the table. If a table has no INTEGER PRIMARY KEY, then a random rowid +** is generated for each row of the table. TF_HasPrimaryKey is set if +** the table has any PRIMARY KEY, INTEGER or otherwise. +** +** Table.tnum is the page number for the root BTree page of the table in the +** database file. If Table.iDb is the index of the database table backend +** in sqlite.aDb[]. 0 is for the main database and 1 is for the file that +** holds temporary tables and indices. If TF_Ephemeral is set +** then the table is stored in a file that is automatically deleted +** when the VDBE cursor to the table is closed. In this case Table.tnum +** refers VDBE cursor number that holds the table open, not to the root +** page number. Transient tables are used to hold the results of a +** sub-query that appears instead of a real table name in the FROM clause +** of a SELECT statement. +*/ +struct Table { + char *zName; /* Name of the table or view */ + int iPKey; /* If not negative, use aCol[iPKey] as the primary key */ + int nCol; /* Number of columns in this table */ + Column *aCol; /* Information about each column */ + Index *pIndex; /* List of SQL indexes on this table. */ + int tnum; /* Root BTree node for this table (see note above) */ + tRowcnt nRowEst; /* Estimated rows in table - from sqlite_stat1 table */ + Select *pSelect; /* NULL for tables. Points to definition if a view. */ + u16 nRef; /* Number of pointers to this Table */ + u8 tabFlags; /* Mask of TF_* values */ + u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */ + FKey *pFKey; /* Linked list of all foreign keys in this table */ + char *zColAff; /* String defining the affinity of each column */ +#ifndef SQLITE_OMIT_CHECK + Expr *pCheck; /* The AND of all CHECK constraints */ +#endif +#ifndef SQLITE_OMIT_ALTERTABLE + int addColOffset; /* Offset in CREATE TABLE stmt to add a new column */ +#endif +#ifndef SQLITE_OMIT_VIRTUALTABLE + VTable *pVTable; /* List of VTable objects. */ + int nModuleArg; /* Number of arguments to the module */ + char **azModuleArg; /* Text of all module args. [0] is module name */ +#endif + Trigger *pTrigger; /* List of triggers stored in pSchema */ + Schema *pSchema; /* Schema that contains this table */ + Table *pNextZombie; /* Next on the Parse.pZombieTab list */ +}; + +/* +** Allowed values for Tabe.tabFlags. +*/ +#define TF_Readonly 0x01 /* Read-only system table */ +#define TF_Ephemeral 0x02 /* An ephemeral table */ +#define TF_HasPrimaryKey 0x04 /* Table has a primary key */ +#define TF_Autoincrement 0x08 /* Integer primary key is autoincrement */ +#define TF_Virtual 0x10 /* Is a virtual table */ +#define TF_NeedMetadata 0x20 /* aCol[].zType and aCol[].pColl missing */ + + + +/* +** Test to see whether or not a table is a virtual table. This is +** done as a macro so that it will be optimized out when virtual +** table support is omitted from the build. +*/ +#ifndef SQLITE_OMIT_VIRTUALTABLE +# define IsVirtual(X) (((X)->tabFlags & TF_Virtual)!=0) +# define IsHiddenColumn(X) ((X)->isHidden) +#else +# define IsVirtual(X) 0 +# define IsHiddenColumn(X) 0 +#endif + +/* +** Each foreign key constraint is an instance of the following structure. +** +** A foreign key is associated with two tables. The "from" table is +** the table that contains the REFERENCES clause that creates the foreign +** key. The "to" table is the table that is named in the REFERENCES clause. +** Consider this example: +** +** CREATE TABLE ex1( +** a INTEGER PRIMARY KEY, +** b INTEGER CONSTRAINT fk1 REFERENCES ex2(x) +** ); +** +** For foreign key "fk1", the from-table is "ex1" and the to-table is "ex2". +** +** Each REFERENCES clause generates an instance of the following structure +** which is attached to the from-table. The to-table need not exist when +** the from-table is created. The existence of the to-table is not checked. +*/ +struct FKey { + Table *pFrom; /* Table containing the REFERENCES clause (aka: Child) */ + FKey *pNextFrom; /* Next foreign key in pFrom */ + char *zTo; /* Name of table that the key points to (aka: Parent) */ + FKey *pNextTo; /* Next foreign key on table named zTo */ + FKey *pPrevTo; /* Previous foreign key on table named zTo */ + int nCol; /* Number of columns in this key */ + /* EV: R-30323-21917 */ + u8 isDeferred; /* True if constraint checking is deferred till COMMIT */ + u8 aAction[2]; /* ON DELETE and ON UPDATE actions, respectively */ + Trigger *apTrigger[2]; /* Triggers for aAction[] actions */ + struct sColMap { /* Mapping of columns in pFrom to columns in zTo */ + int iFrom; /* Index of column in pFrom */ + char *zCol; /* Name of column in zTo. If 0 use PRIMARY KEY */ + } aCol[1]; /* One entry for each of nCol column s */ +}; + +/* +** SQLite supports many different ways to resolve a constraint +** error. ROLLBACK processing means that a constraint violation +** causes the operation in process to fail and for the current transaction +** to be rolled back. ABORT processing means the operation in process +** fails and any prior changes from that one operation are backed out, +** but the transaction is not rolled back. FAIL processing means that +** the operation in progress stops and returns an error code. But prior +** changes due to the same operation are not backed out and no rollback +** occurs. IGNORE means that the particular row that caused the constraint +** error is not inserted or updated. Processing continues and no error +** is returned. REPLACE means that preexisting database rows that caused +** a UNIQUE constraint violation are removed so that the new insert or +** update can proceed. Processing continues and no error is reported. +** +** RESTRICT, SETNULL, and CASCADE actions apply only to foreign keys. +** RESTRICT is the same as ABORT for IMMEDIATE foreign keys and the +** same as ROLLBACK for DEFERRED keys. SETNULL means that the foreign +** key is set to NULL. CASCADE means that a DELETE or UPDATE of the +** referenced table row is propagated into the row that holds the +** foreign key. +** +** The following symbolic values are used to record which type +** of action to take. +*/ +#define OE_None 0 /* There is no constraint to check */ +#define OE_Rollback 1 /* Fail the operation and rollback the transaction */ +#define OE_Abort 2 /* Back out changes but do no rollback transaction */ +#define OE_Fail 3 /* Stop the operation but leave all prior changes */ +#define OE_Ignore 4 /* Ignore the error. Do not do the INSERT or UPDATE */ +#define OE_Replace 5 /* Delete existing record, then do INSERT or UPDATE */ + +#define OE_Restrict 6 /* OE_Abort for IMMEDIATE, OE_Rollback for DEFERRED */ +#define OE_SetNull 7 /* Set the foreign key value to NULL */ +#define OE_SetDflt 8 /* Set the foreign key value to its default */ +#define OE_Cascade 9 /* Cascade the changes */ + +#define OE_Default 99 /* Do whatever the default action is */ + + +/* +** An instance of the following structure is passed as the first +** argument to sqlite3VdbeKeyCompare and is used to control the +** comparison of the two index keys. +*/ +struct KeyInfo { + sqlite3 *db; /* The database connection */ + u8 enc; /* Text encoding - one of the SQLITE_UTF* values */ + u16 nField; /* Number of entries in aColl[] */ + u8 *aSortOrder; /* Sort order for each column. May be NULL */ + CollSeq *aColl[1]; /* Collating sequence for each term of the key */ +}; + +/* +** An instance of the following structure holds information about a +** single index record that has already been parsed out into individual +** values. +** +** A record is an object that contains one or more fields of data. +** Records are used to store the content of a table row and to store +** the key of an index. A blob encoding of a record is created by +** the OP_MakeRecord opcode of the VDBE and is disassembled by the +** OP_Column opcode. +** +** This structure holds a record that has already been disassembled +** into its constituent fields. +*/ +struct UnpackedRecord { + KeyInfo *pKeyInfo; /* Collation and sort-order information */ + u16 nField; /* Number of entries in apMem[] */ + u8 flags; /* Boolean settings. UNPACKED_... below */ + i64 rowid; /* Used by UNPACKED_PREFIX_SEARCH */ + Mem *aMem; /* Values */ +}; + +/* +** Allowed values of UnpackedRecord.flags +*/ +#define UNPACKED_INCRKEY 0x01 /* Make this key an epsilon larger */ +#define UNPACKED_PREFIX_MATCH 0x02 /* A prefix match is considered OK */ +#define UNPACKED_PREFIX_SEARCH 0x04 /* Ignore final (rowid) field */ + +/* +** Each SQL index is represented in memory by an +** instance of the following structure. +** +** The columns of the table that are to be indexed are described +** by the aiColumn[] field of this structure. For example, suppose +** we have the following table and index: +** +** CREATE TABLE Ex1(c1 int, c2 int, c3 text); +** CREATE INDEX Ex2 ON Ex1(c3,c1); +** +** In the Table structure describing Ex1, nCol==3 because there are +** three columns in the table. In the Index structure describing +** Ex2, nColumn==2 since 2 of the 3 columns of Ex1 are indexed. +** The value of aiColumn is {2, 0}. aiColumn[0]==2 because the +** first column to be indexed (c3) has an index of 2 in Ex1.aCol[]. +** The second column to be indexed (c1) has an index of 0 in +** Ex1.aCol[], hence Ex2.aiColumn[1]==0. +** +** The Index.onError field determines whether or not the indexed columns +** must be unique and what to do if they are not. When Index.onError=OE_None, +** it means this is not a unique index. Otherwise it is a unique index +** and the value of Index.onError indicate the which conflict resolution +** algorithm to employ whenever an attempt is made to insert a non-unique +** element. +*/ +struct Index { + char *zName; /* Name of this index */ + int nColumn; /* Number of columns in the table used by this index */ + int *aiColumn; /* Which columns are used by this index. 1st is 0 */ + tRowcnt *aiRowEst; /* Result of ANALYZE: Est. rows selected by each column */ + Table *pTable; /* The SQL table being indexed */ + int tnum; /* Page containing root of this index in database file */ + u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */ + u8 autoIndex; /* True if is automatically created (ex: by UNIQUE) */ + u8 bUnordered; /* Use this index for == or IN queries only */ + char *zColAff; /* String defining the affinity of each column */ + Index *pNext; /* The next index associated with the same table */ + Schema *pSchema; /* Schema containing this index */ + u8 *aSortOrder; /* Array of size Index.nColumn. True==DESC, False==ASC */ + char **azColl; /* Array of collation sequence names for index */ +#ifdef SQLITE_ENABLE_STAT3 + int nSample; /* Number of elements in aSample[] */ + tRowcnt avgEq; /* Average nEq value for key values not in aSample */ + IndexSample *aSample; /* Samples of the left-most key */ +#endif +}; + +/* +** Each sample stored in the sqlite_stat3 table is represented in memory +** using a structure of this type. See documentation at the top of the +** analyze.c source file for additional information. +*/ +struct IndexSample { + union { + char *z; /* Value if eType is SQLITE_TEXT or SQLITE_BLOB */ + double r; /* Value if eType is SQLITE_FLOAT */ + i64 i; /* Value if eType is SQLITE_INTEGER */ + } u; + u8 eType; /* SQLITE_NULL, SQLITE_INTEGER ... etc. */ + int nByte; /* Size in byte of text or blob. */ + tRowcnt nEq; /* Est. number of rows where the key equals this sample */ + tRowcnt nLt; /* Est. number of rows where key is less than this sample */ + tRowcnt nDLt; /* Est. number of distinct keys less than this sample */ +}; + +/* +** Each token coming out of the lexer is an instance of +** this structure. Tokens are also used as part of an expression. +** +** Note if Token.z==0 then Token.dyn and Token.n are undefined and +** may contain random values. Do not make any assumptions about Token.dyn +** and Token.n when Token.z==0. +*/ +struct Token { + const char *z; /* Text of the token. Not NULL-terminated! */ + unsigned int n; /* Number of characters in this token */ +}; + +/* +** An instance of this structure contains information needed to generate +** code for a SELECT that contains aggregate functions. +** +** If Expr.op==TK_AGG_COLUMN or TK_AGG_FUNCTION then Expr.pAggInfo is a +** pointer to this structure. The Expr.iColumn field is the index in +** AggInfo.aCol[] or AggInfo.aFunc[] of information needed to generate +** code for that node. +** +** AggInfo.pGroupBy and AggInfo.aFunc.pExpr point to fields within the +** original Select structure that describes the SELECT statement. These +** fields do not need to be freed when deallocating the AggInfo structure. +*/ +struct AggInfo { + u8 directMode; /* Direct rendering mode means take data directly + ** from source tables rather than from accumulators */ + u8 useSortingIdx; /* In direct mode, reference the sorting index rather + ** than the source table */ + int sortingIdx; /* Cursor number of the sorting index */ + int sortingIdxPTab; /* Cursor number of pseudo-table */ + ExprList *pGroupBy; /* The group by clause */ + int nSortingColumn; /* Number of columns in the sorting index */ + struct AggInfo_col { /* For each column used in source tables */ + Table *pTab; /* Source table */ + int iTable; /* Cursor number of the source table */ + int iColumn; /* Column number within the source table */ + int iSorterColumn; /* Column number in the sorting index */ + int iMem; /* Memory location that acts as accumulator */ + Expr *pExpr; /* The original expression */ + } *aCol; + int nColumn; /* Number of used entries in aCol[] */ + int nColumnAlloc; /* Number of slots allocated for aCol[] */ + int nAccumulator; /* Number of columns that show through to the output. + ** Additional columns are used only as parameters to + ** aggregate functions */ + struct AggInfo_func { /* For each aggregate function */ + Expr *pExpr; /* Expression encoding the function */ + FuncDef *pFunc; /* The aggregate function implementation */ + int iMem; /* Memory location that acts as accumulator */ + int iDistinct; /* Ephemeral table used to enforce DISTINCT */ + } *aFunc; + int nFunc; /* Number of entries in aFunc[] */ + int nFuncAlloc; /* Number of slots allocated for aFunc[] */ +}; + +/* +** The datatype ynVar is a signed integer, either 16-bit or 32-bit. +** Usually it is 16-bits. But if SQLITE_MAX_VARIABLE_NUMBER is greater +** than 32767 we have to make it 32-bit. 16-bit is preferred because +** it uses less memory in the Expr object, which is a big memory user +** in systems with lots of prepared statements. And few applications +** need more than about 10 or 20 variables. But some extreme users want +** to have prepared statements with over 32767 variables, and for them +** the option is available (at compile-time). +*/ +#if SQLITE_MAX_VARIABLE_NUMBER<=32767 +typedef i16 ynVar; +#else +typedef int ynVar; +#endif + +/* +** Each node of an expression in the parse tree is an instance +** of this structure. +** +** Expr.op is the opcode. The integer parser token codes are reused +** as opcodes here. For example, the parser defines TK_GE to be an integer +** code representing the ">=" operator. This same integer code is reused +** to represent the greater-than-or-equal-to operator in the expression +** tree. +** +** If the expression is an SQL literal (TK_INTEGER, TK_FLOAT, TK_BLOB, +** or TK_STRING), then Expr.token contains the text of the SQL literal. If +** the expression is a variable (TK_VARIABLE), then Expr.token contains the +** variable name. Finally, if the expression is an SQL function (TK_FUNCTION), +** then Expr.token contains the name of the function. +** +** Expr.pRight and Expr.pLeft are the left and right subexpressions of a +** binary operator. Either or both may be NULL. +** +** Expr.x.pList is a list of arguments if the expression is an SQL function, +** a CASE expression or an IN expression of the form " IN (, ...)". +** Expr.x.pSelect is used if the expression is a sub-select or an expression of +** the form " IN (SELECT ...)". If the EP_xIsSelect bit is set in the +** Expr.flags mask, then Expr.x.pSelect is valid. Otherwise, Expr.x.pList is +** valid. +** +** An expression of the form ID or ID.ID refers to a column in a table. +** For such expressions, Expr.op is set to TK_COLUMN and Expr.iTable is +** the integer cursor number of a VDBE cursor pointing to that table and +** Expr.iColumn is the column number for the specific column. If the +** expression is used as a result in an aggregate SELECT, then the +** value is also stored in the Expr.iAgg column in the aggregate so that +** it can be accessed after all aggregates are computed. +** +** If the expression is an unbound variable marker (a question mark +** character '?' in the original SQL) then the Expr.iTable holds the index +** number for that variable. +** +** If the expression is a subquery then Expr.iColumn holds an integer +** register number containing the result of the subquery. If the +** subquery gives a constant result, then iTable is -1. If the subquery +** gives a different answer at different times during statement processing +** then iTable is the address of a subroutine that computes the subquery. +** +** If the Expr is of type OP_Column, and the table it is selecting from +** is a disk table or the "old.*" pseudo-table, then pTab points to the +** corresponding table definition. +** +** ALLOCATION NOTES: +** +** Expr objects can use a lot of memory space in database schema. To +** help reduce memory requirements, sometimes an Expr object will be +** truncated. And to reduce the number of memory allocations, sometimes +** two or more Expr objects will be stored in a single memory allocation, +** together with Expr.zToken strings. +** +** If the EP_Reduced and EP_TokenOnly flags are set when +** an Expr object is truncated. When EP_Reduced is set, then all +** the child Expr objects in the Expr.pLeft and Expr.pRight subtrees +** are contained within the same memory allocation. Note, however, that +** the subtrees in Expr.x.pList or Expr.x.pSelect are always separately +** allocated, regardless of whether or not EP_Reduced is set. +*/ +struct Expr { + u8 op; /* Operation performed by this node */ + char affinity; /* The affinity of the column or 0 if not a column */ + u16 flags; /* Various flags. EP_* See below */ + union { + char *zToken; /* Token value. Zero terminated and dequoted */ + int iValue; /* Non-negative integer value if EP_IntValue */ + } u; + + /* If the EP_TokenOnly flag is set in the Expr.flags mask, then no + ** space is allocated for the fields below this point. An attempt to + ** access them will result in a segfault or malfunction. + *********************************************************************/ + + Expr *pLeft; /* Left subnode */ + Expr *pRight; /* Right subnode */ + union { + ExprList *pList; /* Function arguments or in " IN ( IN ( -o \n" + "\t %s [-v] -p \n", getprogname(), getprogname()); + exit(EXIT_FAILURE); +} + +int +main(int argc, char *argv[]) +{ + int s[2], fd, status, c, verbose; + char buf[1024], *prog; + + prog = NULL; + s[0] = s[1] = -1; + verbose = 0; + + while ((c = getopt(argc, argv, "di:o:p:")) != -1) + switch (c) { + case 'd': + debug++; + break; + case 'i': + s[0] = atoi(optarg); + break; + case 'o': + s[1] = atoi(optarg); + break; + case 'p': + prog = optarg; + break; + default: + usage(); + } + + if ((s[0] == -1 && s[1] != -1) || (s[0] != -1 && s[1] == -1)) + usage(); + + if (s[0] == -1) { + if (socketpair(AF_LOCAL, SOCK_DGRAM, 0, s) == -1) + err(1, "socketpair"); + } else + goto recv; + + switch (fork()) { + case -1: + err(1, "fork"); + default: + fd = open("foo", O_RDWR|O_CREAT|O_TRUNC, 0666); + if (fd == -1) + err(1, "open"); + send_fd(s[0], fd); + wait(&status); + return 0; + case 0: + if (prog != NULL) { + char i[64], o[64]; + snprintf(i, sizeof(i), "%d", s[0]); + snprintf(o, sizeof(o), "%d", s[1]); + execlp(prog, prog, "-i", i, "-o", o, NULL); + err(1, "execlp"); + } + recv: + fd = recv_fd(s[1]); + if (verbose) { + snprintf(buf, sizeof(buf), "ls -l /proc/%d/fd", + getpid()); + system(buf); + } + if (write(fd, "foo\n", 4) == -1) + err(1, "write"); + close(fd); + return 0; + } +} diff --git a/tests/net/fdpass/t_fdpass.sh b/tests/net/fdpass/t_fdpass.sh new file mode 100644 index 000000000..4e4ac044c --- /dev/null +++ b/tests/net/fdpass/t_fdpass.sh @@ -0,0 +1,99 @@ +# $NetBSD: t_fdpass.sh,v 1.2 2012/08/16 08:39:43 martin Exp $ +# +# Copyright (c) 2012 The NetBSD Foundation, Inc. +# All rights reserved. +# +# This code is derived from software contributed to The NetBSD Foundation +# by Christos Zoulas +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +have32() { + local src="$(atf_get_srcdir)" + if cmp "${src}/fdpass64" "${src}/fdpass32" > /dev/null + then + # echo "no -m32 support" + return 1 + else + return 0 + fi +} + +atf_test_case fdpass_normal + +fdpass_normal_head() { + atf_set "descr" "Test file descriptor passing (default)" +} + +fdpass_normal_body() { + local src="$(atf_get_srcdir)" + atf_check "${src}/fdpass64" +} + + +atf_test_case fdpass_compat + +fdpass_compat_head() { + atf_set "descr" "Test file descriptor passing (compat)" +} + +fdpass_compat_body() { + local src="$(atf_get_srcdir)" + have32 && atf_check "${src}/fdpass32" +} + + +atf_test_case fdpass_normal_compat + +fdpass_normal_compat_head() { + atf_set "descr" "Test file descriptor passing (normal->compat)" +} + +fdpass_normal_compat_body() { + local src="$(atf_get_srcdir)" + have32 && atf_check "${src}/fdpass64" -p "${src}/fdpass32" +} + + +atf_test_case fdpass_compat_normal + +fdpass_compat_normal_head() { + atf_set "descr" "Test file descriptor passing (normal->compat)" +} + +fdpass_compat_normal_body() { + local src="$(atf_get_srcdir)" + have32 && atf_check "${src}/fdpass32" -p "${src}/fdpass64" +} + + +atf_init_test_cases() +{ + atf_add_test_case fdpass_normal + if have32 + then + atf_add_test_case fdpass_compat + atf_add_test_case fdpass_compat_normal + atf_add_test_case fdpass_normal_compat + fi +} diff --git a/tests/net/icmp/Makefile b/tests/net/icmp/Makefile new file mode 100644 index 000000000..688c2e2f2 --- /dev/null +++ b/tests/net/icmp/Makefile @@ -0,0 +1,16 @@ +# $NetBSD: Makefile,v 1.3 2010/12/14 11:03:17 pooka Exp $ +# + +.include + +TESTSDIR= ${TESTSBASE}/net/icmp + +TESTS_C= t_forward +TESTS_C+= t_ping + +TESTS_SH= t_ping2 + +LDADD+= -lrumpnet_shmif -lrumpnet_netinet -lrumpnet_net -lrumpnet +LDADD+= -lrump -lrumpuser -lpthread + +.include diff --git a/tests/net/icmp/t_forward.c b/tests/net/icmp/t_forward.c new file mode 100644 index 000000000..d0c23cc96 --- /dev/null +++ b/tests/net/icmp/t_forward.c @@ -0,0 +1,169 @@ +/* $NetBSD: t_forward.c,v 1.8 2012/03/18 09:46:50 jruoho Exp $ */ + +/*- + * Copyright (c) 2010 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#ifndef lint +__RCSID("$NetBSD: t_forward.c,v 1.8 2012/03/18 09:46:50 jruoho Exp $"); +#endif /* not lint */ + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "../../h_macros.h" +#include "../config/netconfig.c" + +/* + * Since our maxttl is in our private namespace, we don't need raw packet + * construction like traceroute(8) -- we can just use the global maxttl. + */ +static void +sendttl(void) +{ + struct sockaddr_in sin; + char payload[1024]; + char ifname[IFNAMSIZ]; + int mib[4] = { CTL_NET, PF_INET, IPPROTO_IP, IPCTL_DEFTTL }; + int nv; + int s; + + netcfg_rump_makeshmif("bus1", ifname); + netcfg_rump_if(ifname, "1.0.0.1", "255.255.255.0"); + netcfg_rump_route("0.0.0.0", "0.0.0.0", "1.0.0.2"); /* default router */ + + /* set global ttl to 1 */ + nv = 1; + if (rump_sys___sysctl(mib, 4, NULL, NULL, &nv, sizeof(nv)) == -1) + atf_tc_fail_errno("set ttl"); + + s = rump_sys_socket(PF_INET, SOCK_DGRAM, 0); + if (s == -1) + atf_tc_fail_errno("create send socket"); + + memset(&sin, 0, sizeof(sin)); + sin.sin_len = sizeof(sin); + sin.sin_family = AF_INET; + sin.sin_port = htons(33434); + sin.sin_addr.s_addr = inet_addr("9.9.9.9"); + + /* send udp datagram with ttl == 1 */ + if (rump_sys_sendto(s, payload, sizeof(payload), 0, + (struct sockaddr *)&sin, sizeof(sin)) == -1) + atf_tc_fail_errno("sendto"); +} + +static void +router(void) +{ + int mib[4] = { CTL_NET, PF_INET, IPPROTO_ICMP, + ICMPCTL_RETURNDATABYTES }; + char ifname[IFNAMSIZ]; + int nv; + + /* set returndatabytes to 200 */ + nv = 200; + if (rump_sys___sysctl(mib, 4, NULL, NULL, &nv, sizeof(nv)) == -1) + atf_tc_fail_errno("sysctl returndatabytes"); + + netcfg_rump_makeshmif("bus1", ifname); + netcfg_rump_if(ifname, "1.0.0.2", "255.255.255.0"); + + /* + * Wait for parent to send us the data and for us to have + * a chance to process it. + */ + sleep(1); + exit(0); +} + +ATF_TC(returndatabytes); +ATF_TC_HEAD(returndatabytes, tc) +{ + + atf_tc_set_md_var(tc, "descr", "icmp.returndatabytes with certain " + "packets can cause kernel panic (PR kern/43548)"); + atf_tc_set_md_var(tc, "timeout", "4"); /* just in case */ +} + +ATF_TC_BODY(returndatabytes, tc) +{ + pid_t cpid; + int status; + + cpid = fork(); + rump_init(); + + switch (cpid) { + case -1: + atf_tc_fail_errno("fork failed"); + case 0: + router(); + break; + default: + sendttl(); + if (wait(&status) == -1) + atf_tc_fail_errno("wait"); + if (WIFEXITED(status)) { + if (WEXITSTATUS(status)) + atf_tc_fail("child exited with status %d", + WEXITSTATUS(status)); + } else { + atf_tc_fail("child died"); + } + } +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, returndatabytes); + + return atf_no_error(); +} diff --git a/tests/net/icmp/t_ping.c b/tests/net/icmp/t_ping.c new file mode 100644 index 000000000..fd8067c80 --- /dev/null +++ b/tests/net/icmp/t_ping.c @@ -0,0 +1,438 @@ +/* $NetBSD: t_ping.c,v 1.15 2012/09/04 22:31:58 alnsn Exp $ */ + +/*- + * Copyright (c) 2010 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#ifndef lint +__RCSID("$NetBSD: t_ping.c,v 1.15 2012/09/04 22:31:58 alnsn Exp $"); +#endif /* not lint */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include "../../h_macros.h" +#include "../config/netconfig.c" + +ATF_TC(simpleping); +ATF_TC_HEAD(simpleping, tc) +{ + + atf_tc_set_md_var(tc, "descr", "check that kernel responds to ping"); + atf_tc_set_md_var(tc, "timeout", "2"); +} + +ATF_TC_BODY(simpleping, tc) +{ + char ifname[IFNAMSIZ]; + pid_t cpid; + bool win, win2; + char token; + int channel[2]; + + RL(pipe(channel)); + + cpid = fork(); + rump_init(); + netcfg_rump_makeshmif("but-can-i-buy-your-ether-bus", ifname); + + switch (cpid) { + case -1: + atf_tc_fail_errno("fork failed"); + case 0: + netcfg_rump_if(ifname, "1.1.1.10", "255.255.255.0"); + close(channel[0]); + ATF_CHECK(write(channel[1], "U", 1) == 1); + close(channel[1]); + pause(); + break; + default: + break; + } + + close(channel[1]); + ATF_CHECK(read(channel[0], &token, 1) == 1 && token == 'U'); + close(channel[0]); + + netcfg_rump_if(ifname, "1.1.1.20", "255.255.255.0"); + + /* + * The beauty of shmif is that we don't have races here. + */ + win = netcfg_rump_pingtest("1.1.1.10", 500); + win2 = netcfg_rump_pingtest("1.1.1.30", 500); + + kill(cpid, SIGKILL); + + if (!win) + atf_tc_fail("ping failed"); + if (win2) + atf_tc_fail("non-existent host responded"); +} + +ATF_TC(floodping); +ATF_TC_HEAD(floodping, tc) +{ + + atf_tc_set_md_var(tc, "descr", "see how kernel responds to floodping"); +} + +/* why the hell isn't this available in userspace??? */ +static uint16_t +in_cksum(void *data, size_t len) +{ + uint16_t *buf = data; + unsigned sum; + + for (sum = 0; len > 1; len -= 2) + sum += *buf++; + if (len) + sum += *(uint8_t *)buf; + + sum = (sum >> 16) + (sum & 0xffff); + sum += (sum >> 16); + + return ~sum; +} + +static int +doping(const char *target, int loops, u_int pktsize) +{ + union { + char buf[IP_MAXPACKET - sizeof(struct ip)]; + struct icmp i; /* ensure proper alignment */ + } sndbuf; + char recvbuf[IP_MAXPACKET]; + struct sockaddr_in dst, pingee; + struct icmp *icmp; + socklen_t slen; + ssize_t n; + int loop, succ; + int x, xnon, s; + + RL(s = rump_sys_socket(PF_INET, SOCK_RAW, IPPROTO_ICMP)); + RL(x = rump_sys_fcntl(s, F_GETFL, 0)); + xnon = x | O_NONBLOCK; + + memset(&dst, 0, sizeof(dst)); + dst.sin_len = sizeof(dst); + dst.sin_family = AF_INET; + dst.sin_addr.s_addr = inet_addr(target); + + icmp = (struct icmp *)&sndbuf; + memset(icmp, 0, sizeof(*icmp)); + icmp->icmp_type = ICMP_ECHO; + icmp->icmp_id = htons(37); + + if (pktsize < sizeof(*icmp)) + pktsize = sizeof(*icmp); + if (pktsize > sizeof(sndbuf.buf)) + pktsize = sizeof(sndbuf.buf); + + RL(rump_sys_setsockopt(s, SOL_SOCKET, SO_SNDBUF, + &pktsize, sizeof(pktsize))); + RL(rump_sys_setsockopt(s, SOL_SOCKET, SO_RCVBUF, + &pktsize, sizeof(pktsize))); + + slen = sizeof(pingee); + succ = 0; + for (loop = 0; loop < loops; loop++) { + RL(rump_sys_fcntl(s, F_SETFL, x)); + icmp->icmp_seq = htons(loop); + icmp->icmp_cksum = 0; + icmp->icmp_cksum = in_cksum(icmp, pktsize); + RL(rump_sys_sendto(s, icmp, pktsize, 0, + (struct sockaddr *)&dst, sizeof(dst))); + + RL(rump_sys_fcntl(s, F_SETFL, xnon)); + while ((n = rump_sys_recvfrom(s, recvbuf, sizeof(recvbuf), 0, + (struct sockaddr *)&pingee, &slen)) > 0) { + succ++; + } + if (n == -1 && errno == EAGAIN) + continue; + atf_tc_fail_errno("recv failed"); + } + + rump_sys_close(s); + return succ; +} + +#define LOOPS 10000 + +ATF_TC_BODY(floodping, tc) +{ + char ifname[IFNAMSIZ]; + pid_t cpid; + int succ; + + cpid = fork(); + rump_init(); + netcfg_rump_makeshmif("thank-you-driver-for-getting-me-here", ifname); + + switch (cpid) { + case -1: + atf_tc_fail_errno("fork failed"); + case 0: + netcfg_rump_if(ifname, "1.1.1.10", "255.255.255.0"); + pause(); + break; + default: + break; + } + + netcfg_rump_if(ifname, "1.1.1.20", "255.255.255.0"); + + succ = doping("1.1.1.10", LOOPS, 56); + printf("got %d/%d\n", succ, LOOPS); + + kill(cpid, SIGKILL); +} + +ATF_TC(floodping2); +ATF_TC_HEAD(floodping2, tc) +{ + + atf_tc_set_md_var(tc, "descr", "two hosts floodpinging each other"); +} + +ATF_TC_BODY(floodping2, tc) +{ + char ifname[IFNAMSIZ]; + pid_t cpid; + int succ; + + cpid = fork(); + rump_init(); + netcfg_rump_makeshmif("floodping2", ifname); + + switch (cpid) { + case -1: + atf_tc_fail_errno("fork failed"); + case 0: + netcfg_rump_if(ifname, "1.1.1.10", "255.255.255.0"); + succ = doping("1.1.1.20", LOOPS, 56); + break; + default: + netcfg_rump_if(ifname, "1.1.1.20", "255.255.255.0"); + succ = doping("1.1.1.10", LOOPS, 56); + break; + } + + printf("got %d/%d\n", succ, LOOPS); +} + +ATF_TC(pingsize); +ATF_TC_HEAD(pingsize, tc) +{ + + atf_tc_set_md_var(tc, "descr", "ping with packets min <= size <= max"); +} + +ATF_TC_BODY(pingsize, tc) +{ + char ifname[IFNAMSIZ]; + pid_t cpid; + int succ, i; + + cpid = fork(); + rump_init(); + netcfg_rump_makeshmif("jippikaiee", ifname); + + switch (cpid) { + case -1: + atf_tc_fail_errno("fork failed"); + case 0: + netcfg_rump_if(ifname, "1.1.1.10", "255.255.255.0"); + pause(); + break; + default: + break; + } + + netcfg_rump_if(ifname, "1.1.1.20", "255.255.255.0"); + + succ = 0; + + /* small sizes */ + for (i = 0 ; i < IP_MAXPACKET - 60000; i++) + succ += doping("1.1.1.10", 1, i); + + /* medium sizes */ + for (i = IP_MAXPACKET - 60000; i < IP_MAXPACKET - 100; i += 1000) + succ += doping("1.1.1.10", 1, i); + + /* big sizes */ + for (i = IP_MAXPACKET - 100; i < IP_MAXPACKET; i += 10) + succ += doping("1.1.1.10", 1, i); + + printf("got %d/%d\n", succ, IP_MAXPACKET); + kill(cpid, SIGKILL); +} + +ATF_TC(ping_of_death); +ATF_TC_HEAD(ping_of_death, tc) +{ + + atf_tc_set_md_var(tc, "descr", "send a \"ping of death\""); + atf_tc_set_md_var(tc, "timeout", "2"); +} + +ATF_TC_BODY(ping_of_death, tc) +{ + char data[1500]; + struct sockaddr_in dst; + struct ip *ip; + struct icmp *icmp; + char ifname[IFNAMSIZ]; + pid_t cpid; + size_t tot, frag; + int s, x, loop; + + cpid = fork(); + rump_init(); + netcfg_rump_makeshmif("jippikaiee", ifname); + + switch (cpid) { + case -1: + atf_tc_fail_errno("fork failed"); + case 0: + /* wait until we receive a too long IP packet */ + for (loop = 0;; loop++) { + uint64_t ipstat[IP_NSTATS]; + size_t arglen; + int mib[4]; + + if (loop == 1) + netcfg_rump_if(ifname, + "1.1.1.10", "255.255.255.0"); + + mib[0] = CTL_NET; + mib[1] = PF_INET; + mib[2] = IPPROTO_IP; + mib[3] = IPCTL_STATS; + + arglen = sizeof(ipstat); + RL(rump_sys___sysctl(mib, 4, &ipstat, &arglen, + NULL, 0)); + if (loop == 0 && ipstat[IP_STAT_TOOLONG] != 0) + _exit(1); + if (ipstat[IP_STAT_TOOLONG]) + break; + usleep(10000); + } + + _exit(0); + break; + default: + break; + } + + netcfg_rump_if(ifname, "1.1.1.20", "255.255.255.0"); + + RL(s = rump_sys_socket(PF_INET, SOCK_RAW, 0)); + x = 1; + RL(rump_sys_setsockopt(s, IPPROTO_IP, IP_HDRINCL, &x, sizeof(x))); + + memset(&dst, 0, sizeof(dst)); + dst.sin_len = sizeof(dst); + dst.sin_family = AF_INET; + dst.sin_addr.s_addr = inet_addr("1.1.1.10"); + + /* construct packet */ + memset(data, 0, sizeof(data)); + ip = (struct ip *)data; + ip->ip_v = 4; + ip->ip_hl = sizeof(*ip) >> 2; + ip->ip_p = IPPROTO_ICMP; + ip->ip_ttl = IPDEFTTL; + ip->ip_dst = dst.sin_addr; + ip->ip_id = 1234; + + icmp = (struct icmp *)(ip + 1); + icmp->icmp_type = ICMP_ECHO; + icmp->icmp_cksum = in_cksum(icmp, sizeof(*icmp)); + + for (;;) { + int status; + + /* resolve arp before sending raw stuff */ + netcfg_rump_pingtest("1.1.1.10", 1); + + for (tot = 0; + tot < 65538 - sizeof(*ip); + tot += (frag - sizeof(*ip))) { + frag = MIN(65538 - tot, sizeof(data)); + ip->ip_off = tot >> 3; + assert((size_t)ip->ip_off << 3 == tot); + ip->ip_len = frag; + + if (frag == sizeof(data)) { + ip->ip_off |= IP_MF; + } + + RL(rump_sys_sendto(s, data, frag, 0, + (struct sockaddr *)&dst, sizeof(dst))); + } + if (waitpid(-1, &status, WNOHANG) > 0) { + if (WIFEXITED(status) && WEXITSTATUS(status) == 0) + break; + atf_tc_fail("child did not exit clean"); + } + + usleep(10000); + } +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, simpleping); + ATF_TP_ADD_TC(tp, floodping); + ATF_TP_ADD_TC(tp, floodping2); + ATF_TP_ADD_TC(tp, pingsize); + ATF_TP_ADD_TC(tp, ping_of_death); + + return atf_no_error(); +} diff --git a/tests/net/icmp/t_ping2.sh b/tests/net/icmp/t_ping2.sh new file mode 100644 index 000000000..30ff73b22 --- /dev/null +++ b/tests/net/icmp/t_ping2.sh @@ -0,0 +1,78 @@ +# $NetBSD: t_ping2.sh,v 1.4 2010/12/30 16:58:07 pooka Exp $ +# +# Copyright (c) 2010 The NetBSD Foundation, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +netserver=\ +"rump_server -lrumpnet -lrumpnet_net -lrumpnet_netinet -lrumpnet_shmif" + +atf_test_case basic cleanup +basic_head() +{ + + atf_set "descr" "Checks that a simple ping works" +} + +docfg () +{ + + sock=${1} + addr=${2} + + atf_check -s exit:0 \ + env RUMP_SERVER=${sock} rump.ifconfig shmif0 create + atf_check -s exit:0 \ + env RUMP_SERVER=${sock} rump.ifconfig shmif0 linkstr bus + atf_check -s exit:0 \ + env RUMP_SERVER=${sock} rump.ifconfig shmif0 inet ${addr} +} + +basic_body() +{ + + atf_check -s exit:0 ${netserver} unix://commsock1 + atf_check -s exit:0 ${netserver} unix://commsock2 + + docfg unix://commsock1 1.2.3.4 + docfg unix://commsock2 1.2.3.5 + + atf_check -s exit:0 -o ignore \ + env RUMP_SERVER=unix://commsock1 rump.ping -n -c 1 1.2.3.5 + atf_check -s exit:0 -o ignore \ + env RUMP_SERVER=unix://commsock2 rump.ping -n -c 1 1.2.3.5 +} + +basic_cleanup() +{ + + env RUMP_SERVER=unix://commsock1 rump.halt + env RUMP_SERVER=unix://commsock2 rump.halt +} + +atf_init_test_cases() +{ + + atf_add_test_case basic +} diff --git a/tests/net/if/Makefile b/tests/net/if/Makefile new file mode 100644 index 000000000..9b6a0ebfa --- /dev/null +++ b/tests/net/if/Makefile @@ -0,0 +1,13 @@ +# $NetBSD: Makefile,v 1.1 2010/11/07 19:53:42 pooka Exp $ +# + +.include + +TESTSDIR= ${TESTSBASE}/net/if + +TESTS_C= t_compat + +LDADD+= -lrumpnet_shmif -lrumpnet_netinet -lrumpnet_net -lrumpnet -lrump +LDADD+= -lrumpuser -lpthread + +.include diff --git a/tests/net/if/t_compat.c b/tests/net/if/t_compat.c new file mode 100644 index 000000000..4798034fa --- /dev/null +++ b/tests/net/if/t_compat.c @@ -0,0 +1,83 @@ +/* $NetBSD: t_compat.c,v 1.1 2010/11/07 19:53:42 pooka Exp $ */ + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include "../config/netconfig.c" + +/* + * Test for stack smashing in compat ioctl handling. Adapted as an + * atf test from code provided by Onno van der Linden in PR kern/44054 + */ + +struct oifreq { + char ifr_name[IFNAMSIZ]; /* if name, e.g. "en0" */ + union { + struct sockaddr ifru_addr; + struct sockaddr ifru_dstaddr; + struct sockaddr ifru_broadaddr; + short ifru_flags; + int ifru_metric; + int ifru_mtu; + int ifru_dlt; + u_int ifru_value; + void * ifru_data; + struct { + uint32_t b_buflen; + void *b_buf; + } ifru_b; + } ifr_ifru; +}; +#define OOSIOCGIFBRDADDR _IOWR('i', 18, struct oifreq) + +ATF_TC(OOSIOCGIFBRDADDR); +ATF_TC_HEAD(OOSIOCGIFBRDADDR, tc) +{ + + atf_tc_set_md_var(tc, "descr", "Checks that OOSIOCGIFBRDADDR works " + "(PR kern/44054)"); +} + +ATF_TC_BODY(OOSIOCGIFBRDADDR, tc) +{ + int fd, ifnum; + struct oifreq ifreq; + struct sockaddr_in *sin; + int rv; + + memset(&ifreq,'\0',sizeof ifreq); + + rump_init(); + + /* create an interface and give it netmask 0xffff0000 */ + rv = rump_pub_shmif_create("bus", &ifnum); + if (rv) + atf_tc_fail("failed to create shmif: %s", strerror(rv)); + sprintf(ifreq.ifr_name, "shmif%d", ifnum); + netcfg_rump_if(ifreq.ifr_name, "1.7.64.10", "255.255.0.0"); + + /* query kernel for iface bcast */ + RL(fd = rump_sys_socket(AF_INET, SOCK_DGRAM, 0)); + RL(rump_sys_ioctl(fd, OOSIOCGIFBRDADDR, &ifreq)); + + /* make sure we got what we deserve */ + sin = (struct sockaddr_in *)&ifreq.ifr_broadaddr; + ATF_REQUIRE_EQ(sin->sin_addr.s_addr, htonl(0x0107ffff)); + rump_sys_close(fd); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, OOSIOCGIFBRDADDR); + return atf_no_error(); +} diff --git a/tests/net/if_loop/Makefile b/tests/net/if_loop/Makefile new file mode 100644 index 000000000..e06161019 --- /dev/null +++ b/tests/net/if_loop/Makefile @@ -0,0 +1,13 @@ +# $NetBSD: Makefile,v 1.1 2010/07/25 21:42:08 pooka Exp $ +# + +.include + +TESTSDIR= ${TESTSBASE}/net/if_loop + +TESTS_C= t_pr + +LDADD+= -lrumpnet_netinet -lrumpnet_net -lrumpnet +LDADD+= -lrump -lrumpuser -lpthread + +.include diff --git a/tests/net/if_loop/t_pr.c b/tests/net/if_loop/t_pr.c new file mode 100644 index 000000000..a22953f93 --- /dev/null +++ b/tests/net/if_loop/t_pr.c @@ -0,0 +1,229 @@ +/* $NetBSD: t_pr.c,v 1.7 2012/03/18 09:46:50 jruoho Exp $ */ + +/*- + * Copyright (c) 2010 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#ifndef lint +__RCSID("$NetBSD: t_pr.c,v 1.7 2012/03/18 09:46:50 jruoho Exp $"); +#endif /* not lint */ + +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "../config/netconfig.c" +#include "../../h_macros.h" + +/* + * Prepare rump, configure interface and route to cause fragmentation + */ +static void +setup(void) +{ + char ifname[IFNAMSIZ]; + struct { + struct rt_msghdr m_rtm; + struct sockaddr_in m_sin; + } m_rtmsg; +#define rtm m_rtmsg.m_rtm +#define rsin m_rtmsg.m_sin + struct ifreq ifr; + int s; + + rump_init(); + + /* first, config lo0 & route */ + strcpy(ifname, "lo0"); + netcfg_rump_if(ifname, "127.0.0.1", "255.0.0.0"); + netcfg_rump_route("127.0.0.1", "255.0.0.0", "127.0.0.1"); + + if ((s = rump_sys_socket(PF_ROUTE, SOCK_RAW, 0)) == -1) + atf_tc_fail_errno("routing socket"); + + /* + * set MTU for interface so that route MTU doesn't + * get overridden by it. + */ + memset(&ifr, 0, sizeof(ifr)); + strcpy(ifr.ifr_name, "lo0"); + ifr.ifr_mtu = 1300; + if (rump_sys_ioctl(s, SIOCSIFMTU, &ifr) == -1) + atf_tc_fail_errno("set mtu"); + + /* change route MTU to 100 */ + memset(&m_rtmsg, 0, sizeof(m_rtmsg)); + rtm.rtm_type = RTM_CHANGE; + rtm.rtm_flags = RTF_STATIC; + rtm.rtm_version = RTM_VERSION; + rtm.rtm_seq = 3; + rtm.rtm_inits = RTV_MTU; + rtm.rtm_addrs = RTA_DST; + rtm.rtm_rmx.rmx_mtu = 100; + rtm.rtm_msglen = sizeof(m_rtmsg); + + memset(&rsin, 0, sizeof(rsin)); + rsin.sin_family = AF_INET; + rsin.sin_len = sizeof(rsin); + rsin.sin_addr.s_addr = inet_addr("127.0.0.1"); + + if (rump_sys_write(s, &m_rtmsg, sizeof(m_rtmsg)) != sizeof(m_rtmsg)) + atf_tc_fail_errno("set route mtu"); + rump_sys_close(s); +} + +/* + * Turn on checksums on loopback interfaces + */ +static int +enable_locsums(void) +{ + struct sysctlnode q, ans[256]; + int mib[5], enable; + size_t alen; + unsigned i; + + mib[0] = CTL_NET; + mib[1] = PF_INET; + mib[2] = IPPROTO_IP; + mib[3] = CTL_QUERY; + alen = sizeof(ans); + + memset(&q, 0, sizeof(q)); + q.sysctl_flags = SYSCTL_VERSION; + + if (rump_sys___sysctl(mib, 4, ans, &alen, &q, sizeof(q)) == -1) + return -1; + + for (i = 0; i < __arraycount(ans); i++) + if (strcmp("do_loopback_cksum", ans[i].sysctl_name) == 0) + break; + if (i == __arraycount(ans)) { + errno = ENOENT; + return -1; + } + + mib[3] = ans[i].sysctl_num; + + enable = 1; + if (rump_sys___sysctl(mib, 4, NULL, NULL, &enable, + sizeof(enable)) == -1) + return errno; + + return 0; +} + +ATF_TC(loopmtu); +ATF_TC_HEAD(loopmtu, tc) +{ + + atf_tc_set_md_var(tc, "descr", + "test lo0 fragmentation (PR kern/43664)"); +} + +ATF_TC_BODY(loopmtu, tc) +{ + struct sockaddr_in sin; + char data[2000]; + int s; + + setup(); + + /* open raw socket */ + s = rump_sys_socket(PF_INET, SOCK_RAW, 0); + if (s == -1) + atf_tc_fail_errno("raw socket"); + + /* then, send data */ + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_len = sizeof(sin); + sin.sin_port = htons(12345); + sin.sin_addr.s_addr = inet_addr("127.0.0.1"); + + if (rump_sys_sendto(s, data, sizeof(data), 0, + (struct sockaddr *)&sin, sizeof(sin)) == -1) + atf_tc_fail_errno("sendto failed"); +} + +ATF_TC(loopmtu_csum); +ATF_TC_HEAD(loopmtu_csum, tc) +{ + + atf_tc_set_md_var(tc, "descr", + "test lo0 fragmentation with checksums (PR kern/43664)"); +} + +ATF_TC_BODY(loopmtu_csum, tc) +{ + struct sockaddr_in sin; + char data[2000]; + int s; + + setup(); + + ATF_CHECK(enable_locsums() == 0); + + /* open raw socket */ + s = rump_sys_socket(PF_INET, SOCK_RAW, 0); + if (s == -1) + atf_tc_fail_errno("raw socket"); + + /* then, send data */ + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_len = sizeof(sin); + sin.sin_port = htons(12345); + sin.sin_addr.s_addr = inet_addr("127.0.0.1"); + + if (rump_sys_sendto(s, data, sizeof(data), 0, + (struct sockaddr *)&sin, sizeof(sin)) == -1) + atf_tc_fail_errno("sendto failed"); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, loopmtu); + ATF_TP_ADD_TC(tp, loopmtu_csum); + + return atf_no_error(); +} + diff --git a/tests/net/net/Makefile b/tests/net/net/Makefile new file mode 100644 index 000000000..338ab787e --- /dev/null +++ b/tests/net/net/Makefile @@ -0,0 +1,18 @@ +# $NetBSD: Makefile,v 1.6 2013/07/03 14:01:29 nakayama Exp $ +# + +.include + +TESTSDIR= ${TESTSBASE}/net/net + +TESTS_C= t_unix +TESTS_C+= t_udp +TESTS_C+= t_pktinfo +.if (${MKRUMP} != "no") +TESTS_C+= t_raw +.endif + +LDADD.t_raw+= -lrumpnet_local -lrumpnet_netinet -lrumpnet_net +LDADD.t_raw+= -lrumpnet -lrumpvfs -lrump -lrumpuser -lpthread + +.include diff --git a/tests/net/net/t_pktinfo.c b/tests/net/net/t_pktinfo.c new file mode 100644 index 000000000..52d42a98d --- /dev/null +++ b/tests/net/net/t_pktinfo.c @@ -0,0 +1,193 @@ +/* $NetBSD: t_pktinfo.c,v 1.1 2013/06/27 20:01:24 christos Exp $ */ + +/*- + * Copyright (c) 2013 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include +__RCSID("$NetBSD: t_pktinfo.c,v 1.1 2013/06/27 20:01:24 christos Exp $"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static const char traffic[] = "foo"; + +#ifdef TEST +#include +#define ERR(msg) err(EXIT_FAILURE, msg) +#define ERRX(msg, a) errx(EXIT_FAILURE, msg, a) +#define ERRX2(msg, a1, a2) errx(EXIT_FAILURE, msg, a1, a2) +#else +#include +#define ERR(msg) ATF_REQUIRE_MSG(0, "%s: %s", msg, strerror(errno)) +#define ERRX(msg, a) ATF_REQUIRE_MSG(0, msg, a) +#define ERRX2(msg, a1, a2) ATF_REQUIRE_MSG(0, msg, a1, a2) +#endif + +static int +server(struct sockaddr_in *sin) { + int s, one; + socklen_t len = sizeof(*sin); + + if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) + ERR("socket"); + + memset(sin, 0, len); + sin->sin_family = AF_INET; + sin->sin_len = len; + sin->sin_port = 0; + sin->sin_addr.s_addr = htonl(INADDR_LOOPBACK); + + if (bind(s, (const struct sockaddr *)sin, len) == -1) + ERR("bind"); + + if (getsockname(s, (struct sockaddr *)sin, &len) == -1) + ERR("getsockname"); + + one = 1; + if (setsockopt(s, IPPROTO_IP, IP_PKTINFO, &one, sizeof(one)) == -1) + ERR("setsockopt"); + if (setsockopt(s, IPPROTO_IP, IP_RECVPKTINFO, &one, sizeof(one)) == -1) + ERR("setsockopt"); + + return s; +} + +static int +client(struct sockaddr_in *sin) { + int s; + + if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) + ERR("socket"); + if (sendto(s, traffic, sizeof(traffic), 0, + (const struct sockaddr *)sin, sizeof(*sin)) == -1) + ERR("sendto"); + return s; +} + +static void +receive(int s) { + struct msghdr msg; + struct cmsghdr *cmsg; + struct iovec iov; + char buf[sizeof(traffic)]; + struct in_pktinfo *ipi; + char control[CMSG_SPACE(sizeof(*ipi)) * 2]; + + memset(&msg, 0, sizeof(msg)); + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_iov = &iov; + memset(&iov, 0, sizeof(iov)); + iov.iov_base = buf; + iov.iov_len = sizeof(buf); + msg.msg_iovlen = 1; + msg.msg_control = control; + msg.msg_controllen = sizeof(control); + msg.msg_flags = 0; + + if (recvmsg(s, &msg, 0) == -1) + ERR("recvmsg"); + + for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; + cmsg = CMSG_NXTHDR(&msg, cmsg)) { + if (cmsg->cmsg_level != IPPROTO_IP) + ERRX("bad level %d", cmsg->cmsg_level); + const char *m; + switch (cmsg->cmsg_type) { + case IP_PKTINFO: + m = "pktinfo"; + break; + case IP_RECVPKTINFO: + m = "recvpktinfo"; + break; + default: + m = NULL; + ERRX("bad type %d", cmsg->cmsg_type); + } + ipi = (void *)CMSG_DATA(cmsg); +#ifdef TEST + printf("%s message received on address %s at interface %d\n", + m, inet_ntoa(ipi->ipi_addr), ipi->ipi_ifindex); +#else + ATF_REQUIRE_MSG(ipi->ipi_addr.s_addr == htonl(INADDR_LOOPBACK), + "address 0x%x != 0x%x", ipi->ipi_addr.s_addr, + htonl(INADDR_LOOPBACK)); +#endif + } + + if (strcmp(traffic, buf) != 0) + ERRX2("Bad message '%s' != '%s'", buf, traffic); +} + +static void +doit(void) +{ + struct sockaddr_in sin; + int s, c; + s = server(&sin); + c = client(&sin); + receive(s); + close(s); + close(c); +} + +#ifndef TEST +ATF_TC(pktinfo); +ATF_TC_HEAD(pktinfo, tc) +{ + + atf_tc_set_md_var(tc, "descr", "Check that IP_PKTINFO and " + "IP_RECVPKTINFO work"); +} + +ATF_TC_BODY(pktinfo, tc) +{ + doit(); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, pktinfo); + return atf_no_error(); +} +#else + +int +main(int argc, char *argv[]) { + doit(); + return 0; +} +#endif diff --git a/tests/net/net/t_raw.c b/tests/net/net/t_raw.c new file mode 100644 index 000000000..ef3262dfa --- /dev/null +++ b/tests/net/net/t_raw.c @@ -0,0 +1,41 @@ +/* $NetBSD: t_raw.c,v 1.1 2011/01/11 10:51:45 pooka Exp $ */ + +#include +#include + +#include +#include +#include + +#include +#include + +#include + +#include "../../h_macros.h" + +ATF_TC(PRU_SENSE); +ATF_TC_HEAD(PRU_SENSE, tc) +{ + + atf_tc_set_md_var(tc, "descr", "Biglock leak with PRU_SENSE on " + "raw sockets (PR kern/44369)"); +} + +ATF_TC_BODY(PRU_SENSE, tc) +{ + struct stat sb; + int s; + + rump_init(); + RL(s = rump_sys_socket(PF_ROUTE, SOCK_RAW, 0)); + /* call PRU_SENSE. unfixed bug causes panic in rump_unschedule() */ + RL(rump_sys_fstat(s, &sb)); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, PRU_SENSE); + return atf_no_error(); +} diff --git a/tests/net/net/t_udp.c b/tests/net/net/t_udp.c new file mode 100644 index 000000000..db593424e --- /dev/null +++ b/tests/net/net/t_udp.c @@ -0,0 +1,110 @@ +#include +__RCSID("$NetBSD: t_udp.c,v 1.2 2013/01/06 02:22:50 christos Exp $"); + +#include +#include + +#include +#include +#include +#include + +#include + +static const char msg[] = "sendto test"; + +static void +sendit(int family) +{ + struct addrinfo hints; + struct addrinfo *res; + int S, s; + int e; + + /* lookup localhost addr, depending on argv[1] */ + memset(&hints, 0, sizeof(hints)); + hints.ai_family = family; + hints.ai_socktype = SOCK_DGRAM; + hints.ai_protocol = IPPROTO_UDP; + hints.ai_flags = 0; + + e = getaddrinfo("localhost", "9999", &hints, &res); + ATF_REQUIRE_MSG(e == 0, "getaddrinfo AF=%d: %s", family, + gai_strerror(e)); + + /* server socket */ + S = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + ATF_REQUIRE_MSG(S >= 0, "server-socket AF=%d: %s", family, + strerror(errno)); + + e = bind(S, res->ai_addr, res->ai_addrlen); + ATF_REQUIRE_MSG(e == 0, "bind AF=%d: %s", family, + strerror(errno)); + + /* client socket */ + s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + ATF_REQUIRE_MSG(s >= 0, "client-socket AF=%d: %s", family, + strerror(errno)); + + /* sendto */ + e = sendto(s, msg, sizeof(msg), 0, res->ai_addr, res->ai_addrlen); + ATF_REQUIRE_MSG(e == sizeof(msg), "sendto(1) AF=%d: %s", family, + strerror(errno)); + + e = sendto(s, msg, sizeof(msg), 0, res->ai_addr, res->ai_addrlen); + ATF_REQUIRE_MSG(e == sizeof(msg), "sendto(2) AF=%d: %s", family, + strerror(errno)); + + /* connect + send */ + e = connect(s, res->ai_addr, res->ai_addrlen); + ATF_REQUIRE_MSG(e == 0, "connect(1) AF=%d: %s", family, + strerror(errno)); + + e = send(s, msg, sizeof(msg), 0); + ATF_REQUIRE_MSG(e == sizeof(msg), "send(1) AF=%d: %s", family, + strerror(errno)); + + e = connect(s, res->ai_addr, res->ai_addrlen); + ATF_REQUIRE_MSG(e == 0, "connect(2) AF=%d: %s", family, + strerror(errno)); + + e = send(s, msg, sizeof(msg), 0); + ATF_REQUIRE_MSG(e == sizeof(msg), "send(2) AF=%d: %s", family, + strerror(errno)); + + close(s); +} + +ATF_TC(udp4_send); +ATF_TC_HEAD(udp4_send, tc) +{ + + atf_tc_set_md_var(tc, "descr", "Check that inet4 udp send works both" + " for connected and unconnected sockets"); +} + +ATF_TC_BODY(udp4_send, tc) +{ + sendit(AF_INET); +} + +ATF_TC(udp6_send); +ATF_TC_HEAD(udp6_send, tc) +{ + + atf_tc_set_md_var(tc, "descr", "Check that inet6 udp send works both" + " for connected and unconnected sockets"); +} + +ATF_TC_BODY(udp6_send, tc) +{ + sendit(AF_INET6); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, udp4_send); + ATF_TP_ADD_TC(tp, udp6_send); + return atf_no_error(); +} diff --git a/tests/net/net/t_unix.c b/tests/net/net/t_unix.c new file mode 100644 index 000000000..6c708467b --- /dev/null +++ b/tests/net/net/t_unix.c @@ -0,0 +1,184 @@ +/* $NetBSD: t_unix.c,v 1.6 2011/10/04 16:28:26 christos Exp $ */ + +/*- + * Copyright (c) 2011 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__RCSID("$Id: t_unix.c,v 1.6 2011/10/04 16:28:26 christos Exp $"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef TEST +#define FAIL(msg, ...) err(EXIT_FAILURE, msg, ## __VA_ARGS__) +#else + +#include +#define FAIL(msg, ...) ATF_CHECK_MSG(0, msg, ## __VA_ARGS__) + +#endif + +static __dead int +acc(int s) +{ + char guard1; + struct sockaddr_un sun; + char guard2; + socklen_t len; + + guard1 = guard2 = 's'; + + len = sizeof(sun); + if (accept(s, (struct sockaddr *)&sun, &len) == -1) + FAIL("accept"); + if (guard1 != 's') + errx(EXIT_FAILURE, "guard1 = '%c'", guard1); + if (guard2 != 's') + errx(EXIT_FAILURE, "guard2 = '%c'", guard2); + close(s); + exit(0); +} + +static int +test(size_t len) +{ + struct sockaddr_un *sun; + int s, s2; + size_t slen; + socklen_t sl; + + slen = len + offsetof(struct sockaddr_un, sun_path) + 1; + + if ((sun = calloc(1, slen)) == NULL) + FAIL("calloc"); + + s = socket(AF_UNIX, SOCK_STREAM, 0); + if (s == -1) + FAIL("socket"); + + memset(sun->sun_path, 'a', len); + sun->sun_path[len] = '\0'; + (void)unlink(sun->sun_path); + + sl = SUN_LEN(sun); + sun->sun_len = sl; + sun->sun_family = AF_UNIX; + + if (bind(s, (struct sockaddr *)sun, sl) == -1) { + if (errno == EINVAL && sl >= 256) + return -1; + FAIL("bind"); + } + + if (listen(s, 5) == -1) + FAIL("listen"); + + switch (fork()) { + case -1: + FAIL("fork"); + case 0: + acc(s); + /*NOTREACHED*/ + default: + sleep(1); + s2 = socket(AF_UNIX, SOCK_STREAM, 0); + if (s2 == -1) + FAIL("socket"); + if (connect(s2, (struct sockaddr *)sun, sl) == -1) + FAIL("connect"); + close(s2); + break; + } + return 0; +} + +#ifndef TEST + +ATF_TC(sockaddr_un_len_exceed); +ATF_TC_HEAD(sockaddr_un_len_exceed, tc) +{ + + atf_tc_set_md_var(tc, "descr", "Check that exceeding the size of " + "unix domain sockets does not trash memory or kernel when " + "exceeding the size of the fixed sun_path"); +} + +ATF_TC_BODY(sockaddr_un_len_exceed, tc) +{ + ATF_REQUIRE_MSG(test(254) == -1, "test(254): %s", strerror(errno)); +} + +ATF_TC(sockaddr_un_len_max); +ATF_TC_HEAD(sockaddr_un_len_max, tc) +{ + + atf_tc_set_md_var(tc, "descr", "Check that we can use the maximum " + "unix domain socket pathlen (253): 255 - sizeof(sun_len) - " + "sizeof(sun_family)"); +} + +ATF_TC_BODY(sockaddr_un_len_max, tc) +{ + ATF_REQUIRE_MSG(test(253) == 0, "test(253): %s", strerror(errno)); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, sockaddr_un_len_exceed); + ATF_TP_ADD_TC(tp, sockaddr_un_len_max); + return atf_no_error(); +} +#else +int +main(int argc, char *argv[]) +{ + size_t len; + + if (argc == 1) { + fprintf(stderr, "Usage: %s \n", getprogname()); + return EXIT_FAILURE; + } + test(atoi(argv[1])); +} +#endif diff --git a/tests/net/npf/Makefile b/tests/net/npf/Makefile new file mode 100644 index 000000000..e73d8fcbe --- /dev/null +++ b/tests/net/npf/Makefile @@ -0,0 +1,12 @@ +# $NetBSD: Makefile,v 1.1 2012/09/12 14:06:31 martin Exp $ +# + +.include + +TESTSDIR= ${TESTSBASE}/net/npf +FILESDIR= ${TESTSDIR} + +TESTS_SH= t_npf +FILES= ../../../usr.sbin/npf/npftest/npftest.conf + +.include diff --git a/tests/net/npf/t_npf.sh b/tests/net/npf/t_npf.sh new file mode 100644 index 000000000..bf247fc7e --- /dev/null +++ b/tests/net/npf/t_npf.sh @@ -0,0 +1,63 @@ +# $NetBSD: t_npf.sh,v 1.2 2012/09/18 08:28:15 martin Exp $ +# +# Copyright (c) 2008, 2010 The NetBSD Foundation, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +run_test() +{ + local name="${1}" + + atf_check -o ignore -e ignore npfctl debug "$(atf_get_srcdir)/npftest.conf" ./npf.plist + atf_check -o ignore npftest -c npf.plist -T "${name}" +} + +add_test() +{ + local name="${1}"; shift + local desc="${*}"; + + atf_test_case "npf_${name}" + eval "npf_${name}_head() { \ + atf_set \"descr\" \"${desc}\"; \ + atf_set \"require.progs\" \"npfctl npftest\"; \ + }; \ + npf_${name}_body() { \ + run_test \"${name}\"; \ + }" + atf_add_test_case "npf_${name}" +} + +atf_init_test_cases() +{ + LIST=/tmp/t_npf.$$ + trap "rm -f $LIST" EXIT + + sh -ec 'npftest -L || printf "dummy\tnone\n"' > $LIST 2>/dev/null + + while read tag desc + do + add_test "${tag}" "${desc}" + done < $LIST +} diff --git a/tests/net/route/Makefile b/tests/net/route/Makefile new file mode 100644 index 000000000..fd03a5905 --- /dev/null +++ b/tests/net/route/Makefile @@ -0,0 +1,10 @@ +# $NetBSD: Makefile,v 1.1 2011/02/08 10:11:29 pooka Exp $ +# + +.include + +TESTSDIR= ${TESTSBASE}/net/route + +TESTS_SH= t_change + +.include diff --git a/tests/net/route/t_change.sh b/tests/net/route/t_change.sh new file mode 100644 index 000000000..3618aee4b --- /dev/null +++ b/tests/net/route/t_change.sh @@ -0,0 +1,65 @@ +# $NetBSD: t_change.sh,v 1.4 2013/02/19 21:08:25 joerg Exp $ +# +# Copyright (c) 2011 The NetBSD Foundation, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +netserver=\ +"rump_server -lrumpnet -lrumpnet_net -lrumpnet_netinet" +export RUMP_SERVER=unix://commsock + +atf_test_case reject2blackhole cleanup +reject2blackhole_head() +{ + + atf_set "descr" "Change a reject route to blackhole" + atf_set "require.progs" "rump_server" +} + +reject2blackhole_body() +{ + + atf_check -s exit:0 ${netserver} ${RUMP_SERVER} + + atf_check -s exit:0 -o ignore \ + rump.route add 207.46.197.32 127.0.0.1 -reject + atf_check -s exit:0 -o match:UGHR -x \ + "rump.route -n show -inet | grep ^207.46" + atf_check -s exit:0 -o ignore \ + rump.route change 207.46.197.32 127.0.0.1 -blackhole + atf_check -s exit:0 -o match:' UGHBS ' -e ignore -x \ + "rump.netstat -rn -f inet | grep ^207.46| grep ^207.46" +} + +reject2blackhole_cleanup() +{ + + env RUMP_SERVER=unix://commsock rump.halt +} + +atf_init_test_cases() +{ + + atf_add_test_case reject2blackhole +} diff --git a/tests/net/sys/Makefile b/tests/net/sys/Makefile new file mode 100644 index 000000000..51bfff770 --- /dev/null +++ b/tests/net/sys/Makefile @@ -0,0 +1,11 @@ +# $NetBSD: Makefile,v 1.5 2011/11/05 18:19:02 jruoho Exp $ + +# NOTE: please add all syscall-tests to tests/lib/libc/sys. + +.include + +TESTSDIR= ${TESTSBASE}/net/sys + +TESTS_C+= t_rfc6056 + +.include diff --git a/tests/net/sys/t_rfc6056.c b/tests/net/sys/t_rfc6056.c new file mode 100644 index 000000000..944521b40 --- /dev/null +++ b/tests/net/sys/t_rfc6056.c @@ -0,0 +1,152 @@ +/* $NetBSD: t_rfc6056.c,v 1.3 2012/06/22 14:54:35 christos Exp $ */ + +/*- + * Copyright (c) 2011 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include +__RCSID("$NetBSD: t_rfc6056.c,v 1.3 2012/06/22 14:54:35 christos Exp $"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +static void +test(const char *hostname, const char *service, int family, int al) +{ + static const char hello[] = "hello\n"; + int s, error, proto, option; + struct sockaddr_storage ss; + struct addrinfo hints, *res; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = family; + hints.ai_socktype = SOCK_DGRAM; + + switch (family) { + case AF_INET: + proto = IPPROTO_IP; + option = IP_PORTALGO; + break; + case AF_INET6: + proto = IPPROTO_IPV6; + option = IPV6_PORTALGO; + break; + default: + abort(); + } + + error = getaddrinfo(hostname, service, &hints, &res); + if (error) + errx(EXIT_FAILURE, "Cannot get address for %s (%s)", + hostname, gai_strerror(error)); + + s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + if (s == -1) + err(EXIT_FAILURE, "socket"); + + if (setsockopt(s, proto, option, &al, sizeof(al)) == -1) + err(EXIT_FAILURE, "setsockopt"); + + memset(&ss, 0, sizeof(ss)); + ss.ss_len = res->ai_addrlen; + ss.ss_family = res->ai_family; + + if (bind(s, (struct sockaddr *)&ss, ss.ss_len) == -1) + err(EXIT_FAILURE, "bind"); + + if (sendto(s, hello, sizeof(hello) - 1, 0, + res->ai_addr, res->ai_addrlen) == -1) + err(EXIT_FAILURE, "sendto"); + + if (close(s) == -1) + err(EXIT_FAILURE, "close"); + + s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + if (s == -1) + err(EXIT_FAILURE, "socket"); + + if (setsockopt(s, proto, option, &al, sizeof(al)) == -1) + err(EXIT_FAILURE, "setsockopt"); + + if (connect(s, res->ai_addr, res->ai_addrlen) == -1) + err(EXIT_FAILURE, "connect"); + + if (send(s, hello, sizeof(hello) - 1, 0) == -1) + err(EXIT_FAILURE, "send"); + + if (close(s) == -1) + err(EXIT_FAILURE, "close"); + + freeaddrinfo(res); +} + +ATF_TC(inet4); +ATF_TC_HEAD(inet4, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks random port allocation " + "for ipv4"); +} + +ATF_TC_BODY(inet4, tc) +{ + for (int i = 0; i < 6; i++) + test("localhost", "http", AF_INET, i); +} + +ATF_TC(inet6); +ATF_TC_HEAD(inet6, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks random port allocation " + "for ipv6"); +} + +ATF_TC_BODY(inet6, tc) +{ + for (int i = 0; i < 6; i++) + test("localhost", "http", AF_INET6, i); +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, inet4); + ATF_TP_ADD_TC(tp, inet6); + + return atf_no_error(); +} diff --git a/tests/rump/Makefile b/tests/rump/Makefile new file mode 100644 index 000000000..b1f868c76 --- /dev/null +++ b/tests/rump/Makefile @@ -0,0 +1,11 @@ +# $NetBSD: Makefile,v 1.6 2011/03/10 14:09:46 pooka Exp $ +# + +.include + +TESTSDIR= ${TESTSBASE}/rump + +SUBDIR= kernspace +TESTS_SUBDIRS= .WAIT rumpkern rumpnet rumpvfs modautoload + +.include diff --git a/tests/rump/Makefile.inc b/tests/rump/Makefile.inc new file mode 100644 index 000000000..01b5f2341 --- /dev/null +++ b/tests/rump/Makefile.inc @@ -0,0 +1 @@ +.include "../Makefile.inc" diff --git a/tests/rump/kernspace/Makefile b/tests/rump/kernspace/Makefile new file mode 100644 index 000000000..4f8f9d6de --- /dev/null +++ b/tests/rump/kernspace/Makefile @@ -0,0 +1,15 @@ +# $NetBSD: Makefile,v 1.5 2011/01/14 13:08:00 pooka Exp $ +# + +.include + +LIB= kernspace +SRCS= thread.c busypage.c tsleep.c alloc.c lockme.c sendsig.c + +RUMPTOP=${NETBSDSRCDIR}/sys/rump + +LIBISPRIVATE= + +.include "${RUMPTOP}/Makefile.rump" +.include +.include diff --git a/tests/rump/kernspace/alloc.c b/tests/rump/kernspace/alloc.c new file mode 100644 index 000000000..5cbcfb61f --- /dev/null +++ b/tests/rump/kernspace/alloc.c @@ -0,0 +1,122 @@ +/* $NetBSD: alloc.c,v 1.1 2010/06/14 21:06:09 pooka Exp $ */ + +/*- + * Copyright (c) 2010 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#if !defined(lint) +__RCSID("$NetBSD: alloc.c,v 1.1 2010/06/14 21:06:09 pooka Exp $"); +#endif /* !lint */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include "kernspace.h" + +static void *store[32]; +static struct pool pp1, pp2; + +static kmutex_t mtx; +static kcondvar_t kcv; +static int curstat; + +static void +hthr(void *arg) +{ + int i; + + mutex_enter(&mtx); + curstat++; + cv_signal(&kcv); + + while (curstat < 2) + cv_wait(&kcv, &mtx); + mutex_exit(&mtx); + + /* try to guarantee that the sleep is triggered in PR_WAITOK */ + while ((kernel_map->flags & VM_MAP_WANTVA) == 0) + kpause("take5", false, 1, NULL); + + for (i = 0; i < __arraycount(store); i++) { + pool_put(&pp1, store[i]); + } + + kthread_exit(0); +} + +void +rumptest_alloc(size_t thelimit) +{ + char *c; + int succ, i; + + mutex_init(&mtx, MUTEX_DEFAULT, IPL_NONE); + cv_init(&kcv, "venailu"); + + kthread_create(PRI_NONE, KTHREAD_MPSAFE, NULL, hthr, NULL, NULL, "h"); + + pool_init(&pp1, 1024, 0, 0, 0, "vara-allas", + &pool_allocator_nointr, IPL_NONE); + pool_init(&pp2, 1024, 0, 0, 0, "allas", + &pool_allocator_nointr, IPL_NONE); + + for (i = 0; i < __arraycount(store); i++) { + store[i] = pool_get(&pp1, PR_NOWAIT); + if (store[i] == NULL) { + panic("pool_get store failed"); + } + } + + /* wait until other thread runs */ + mutex_enter(&mtx); + while (curstat == 0) + cv_wait(&kcv, &mtx); + mutex_exit(&mtx); + + for (succ = 0;; succ++) { + if (succ * 1024 > thelimit) + panic("managed to allocate over limit"); + if ((c = pool_get(&pp2, PR_NOWAIT)) == NULL) { + mutex_enter(&mtx); + curstat++; + cv_signal(&kcv); + mutex_exit(&mtx); + if (pool_get(&pp2, PR_WAITOK) == NULL) + panic("pool get PR_WAITOK failed"); + break; + } + *c = 'a'; + } +} diff --git a/tests/rump/kernspace/busypage.c b/tests/rump/kernspace/busypage.c new file mode 100644 index 000000000..e0142b7d9 --- /dev/null +++ b/tests/rump/kernspace/busypage.c @@ -0,0 +1,94 @@ +/* $NetBSD: busypage.c,v 1.5 2011/08/07 14:03:15 rmind Exp $ */ + +/*- + * Copyright (c) 2010 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#if !defined(lint) +__RCSID("$NetBSD: busypage.c,v 1.5 2011/08/07 14:03:15 rmind Exp $"); +#endif /* !lint */ + +#include +#include +#include +#include +#include + +#include + +#include "kernspace.h" + +static struct uvm_object *uobj; +static struct vm_page *testpg; +static kcondvar_t tcv; + +static bool threadrun = false; + +static void +thread(void *arg) +{ + + mutex_enter(uobj->vmobjlock); + threadrun = true; + cv_signal(&tcv); + testpg->flags |= PG_WANTED; + UVM_UNLOCK_AND_WAIT(testpg, uobj->vmobjlock, false, "tw", 0); + kthread_exit(0); +} + +void +rumptest_busypage() +{ + struct lwp *newl; + int rv; + + cv_init(&tcv, "napina"); + + uobj = uao_create(1, 0); + mutex_enter(uobj->vmobjlock); + testpg = uvm_pagealloc(uobj, 0, NULL, 0); + mutex_exit(uobj->vmobjlock); + if (testpg == NULL) + panic("couldn't create vm page"); + + rv = kthread_create(PRI_NONE, KTHREAD_MUSTJOIN | KTHREAD_MPSAFE, NULL, + thread, NULL, &newl, "jointest"); + if (rv) + panic("thread creation failed: %d", rv); + + mutex_enter(uobj->vmobjlock); + while (!threadrun) + cv_wait(&tcv, uobj->vmobjlock); + + uvm_page_unbusy(&testpg, 1); + mutex_exit(uobj->vmobjlock); + + rv = kthread_join(newl); + if (rv) + panic("thread join failed: %d", rv); + +} diff --git a/tests/rump/kernspace/kernspace.h b/tests/rump/kernspace/kernspace.h new file mode 100644 index 000000000..248f62fa7 --- /dev/null +++ b/tests/rump/kernspace/kernspace.h @@ -0,0 +1,47 @@ +/* $NetBSD: kernspace.h,v 1.4 2011/01/14 13:08:00 pooka Exp $ */ + +/*- + * Copyright (c) 2010 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _TESTS_RUMP_KERNSPACE_KERNSPACE_H_ +#define _TESTS_RUMP_KERNSPACE_KERNSPACE_H_ + +enum locktest { LOCKME_MTX, LOCKME_RWDOUBLEX, LOCKME_RWRX, LOCKME_RWXR, + LOCKME_DESTROYHELD, LOCKME_DOUBLEINIT, LOCKME_DOUBLEFREE, + LOCKME_MEMFREE }; + +void rumptest_busypage(void); +void rumptest_threadjoin(void); +void rumptest_thread(void); +void rumptest_tsleep(void); +void rumptest_alloc(size_t); +void rumptest_lockme(enum locktest); + +void rumptest_sendsig(char *); +void rumptest_localsig(int); + +#endif /* _TESTS_RUMP_KERNSPACE_KERNSPACE_H_ */ diff --git a/tests/rump/kernspace/lockme.c b/tests/rump/kernspace/lockme.c new file mode 100644 index 000000000..6f9bd587e --- /dev/null +++ b/tests/rump/kernspace/lockme.c @@ -0,0 +1,92 @@ +/* $NetBSD: lockme.c,v 1.1 2011/01/06 13:12:52 pooka Exp $ */ + +/*- + * Copyright (c) 2011 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#if !defined(lint) +__RCSID("$NetBSD: lockme.c,v 1.1 2011/01/06 13:12:52 pooka Exp $"); +#endif /* !lint */ + +#include +#include +#include +#include + +#include "kernspace.h" + +struct somemem { + char foo; + kmutex_t mutexetum; + char oof; +}; + +void +rumptest_lockme(enum locktest what) +{ + struct somemem *some; + kmutex_t mtx; + krwlock_t rw; + + rw_init(&rw); + mutex_init(&mtx, MUTEX_DEFAULT, IPL_NONE); + + switch (what) { + case LOCKME_MTX: + mutex_enter(&mtx); + mutex_enter(&mtx); + break; + case LOCKME_RWDOUBLEX: + rw_enter(&rw, RW_WRITER); + rw_enter(&rw, RW_WRITER); + break; + case LOCKME_RWRX: + rw_enter(&rw, RW_READER); + rw_enter(&rw, RW_WRITER); + break; + case LOCKME_RWXR: + rw_enter(&rw, RW_WRITER); + rw_enter(&rw, RW_READER); + break; + case LOCKME_DOUBLEINIT: + mutex_init(&mtx, MUTEX_DEFAULT, IPL_NONE); + break; + case LOCKME_DOUBLEFREE: + mutex_destroy(&mtx); + mutex_destroy(&mtx); + break; + case LOCKME_DESTROYHELD: + mutex_enter(&mtx); + mutex_destroy(&mtx); + break; + case LOCKME_MEMFREE: + some = kmem_alloc(sizeof(*some), KM_SLEEP); + mutex_init(&some->mutexetum, MUTEX_DEFAULT, IPL_NONE); + kmem_free(some, sizeof(*some)); + break; + } +} diff --git a/tests/rump/kernspace/sendsig.c b/tests/rump/kernspace/sendsig.c new file mode 100644 index 000000000..f0b17a8d1 --- /dev/null +++ b/tests/rump/kernspace/sendsig.c @@ -0,0 +1,82 @@ +/* $NetBSD: sendsig.c,v 1.1 2011/01/14 13:08:00 pooka Exp $ */ + +/*- + * Copyright (c) 2011 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#if !defined(lint) +__RCSID("$NetBSD: sendsig.c,v 1.1 2011/01/14 13:08:00 pooka Exp $"); +#endif /* !lint */ + +#include +#include + +#include + +#include "kernspace.h" + +/* + * loop until a non-system process appears and we can send it a signal + */ +void +rumptest_sendsig(char *signo) +{ + struct proc *p; + bool sent = false; + int sig; + + sig = strtoull(signo, NULL, 10); + rump_boot_setsigmodel(RUMP_SIGMODEL_RAISE); + + mutex_enter(proc_lock); + while (!sent) { + PROCLIST_FOREACH(p, &allproc) { + if (p->p_pid > 1) { + mutex_enter(p->p_lock); + psignal(p, sig); + mutex_exit(p->p_lock); + sent = true; + break; + } + } + kpause("w8", false, 1, proc_lock); + } + mutex_exit(proc_lock); + + /* restore default */ + rump_boot_setsigmodel(RUMP_SIGMODEL_PANIC); +} + +void +rumptest_localsig(int signo) +{ + struct proc *p = curproc; + + mutex_enter(p->p_lock); + psignal(p, signo); + mutex_exit(p->p_lock); +} diff --git a/tests/rump/kernspace/thread.c b/tests/rump/kernspace/thread.c new file mode 100644 index 000000000..5c24f1252 --- /dev/null +++ b/tests/rump/kernspace/thread.c @@ -0,0 +1,108 @@ +/* $NetBSD: thread.c,v 1.2 2011/08/07 14:03:15 rmind Exp $ */ + +/*- + * Copyright (c) 2010 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#if !defined(lint) +__RCSID("$NetBSD: thread.c,v 1.2 2011/08/07 14:03:15 rmind Exp $"); +#endif /* !lint */ + +#include +#include +#include +#include +#include + +#include "kernspace.h" + +static volatile int testit; + +static void +jointhread(void *arg) +{ + + kpause("take5", false, 1, NULL); + testit = 1; + kthread_exit(0); +} + +void +rumptest_threadjoin() +{ + struct lwp *newl; + int rv; + + rv = kthread_create(PRI_NONE, KTHREAD_MUSTJOIN | KTHREAD_MPSAFE, NULL, + jointhread, NULL, &newl, "jointest"); + if (rv) + panic("thread creation failed: %d", rv); + rv = kthread_join(newl); + if (rv) + panic("thread join failed: %d", rv); + + if (testit != 1) + panic("new thread did not run"); +} + +static kmutex_t mtx; +static kcondvar_t cv; +static int value; + +static void +thethread(void *arg) +{ + + mutex_enter(&mtx); + value = 1; + cv_signal(&cv); + mutex_exit(&mtx); + + kthread_exit(0); +} + +void +rumptest_thread() +{ + struct lwp *newl; + int rv; + + mutex_init(&mtx, MUTEX_DEFAULT, IPL_NONE); + cv_init(&cv, "jooei"); + rv = kthread_create(PRI_NONE, KTHREAD_MPSAFE, NULL, + thethread, NULL, &newl, "ktest"); + if (rv) + panic("thread creation failed: %d", rv); + + mutex_enter(&mtx); + while (value == 0) + cv_wait(&cv, &mtx); + mutex_exit(&mtx); + + /* try to verify thread really exists and we don't crash */ + kpause("take1", false, 1, NULL); +} diff --git a/tests/rump/kernspace/tsleep.c b/tests/rump/kernspace/tsleep.c new file mode 100644 index 000000000..8e0034961 --- /dev/null +++ b/tests/rump/kernspace/tsleep.c @@ -0,0 +1,101 @@ +/* $NetBSD: tsleep.c,v 1.3 2012/01/28 12:23:56 rmind Exp $ */ + +/*- + * Copyright (c) 2010 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#if !defined(lint) +__RCSID("$NetBSD: tsleep.c,v 1.3 2012/01/28 12:23:56 rmind Exp $"); +#endif /* !lint */ + +#include +#include +#include +#include +#include + +#include "kernspace.h" + +#define NTHREADS 10 + +/* + * mpsafe thread. need dedicated interlock + */ +static kmutex_t mymtx; + +static void +tinythread(void *arg) +{ + static int wakeups; + int i, rv; + bool relock = ((uintptr_t)arg % 2) == 0; + + for (i = 0; i < 1000; i++) { + mutex_enter(&mymtx); + wakeup(tinythread); + if (wakeups >= NTHREADS-1) { + mutex_exit(&mymtx); + break; + } + rv = mtsleep(tinythread, relock ? 0 : PNORELOCK, + "haa", 0, &mymtx); + if (relock) + mutex_exit(&mymtx); + if (rv != 0) + panic("mtsleep failed"); + } + + mutex_enter(&mymtx); + wakeups++; + wakeup(tinythread); + + rv = mtsleep(rumptest_tsleep, PNORELOCK, "kepuli", 1, &mymtx); + if (rv != EWOULDBLOCK) + panic("mtsleep unexpected return value %d", rv); + + kthread_exit(0); +} + +void +rumptest_tsleep() +{ + struct lwp *notbigl[NTHREADS]; + int rv, i; + + mutex_init(&mymtx, MUTEX_DEFAULT, IPL_NONE); + + for (i = 0; i < NTHREADS; i++) { + rv = kthread_create(PRI_NONE, KTHREAD_MUSTJOIN| KTHREAD_MPSAFE, + NULL, tinythread, (void *)(uintptr_t)i, ¬bigl[i], "nb"); + if (rv) + panic("thread create failed: %d", rv); + } + + for (i = 0; i < NTHREADS; i++) { + kthread_join(notbigl[i]); + } +} diff --git a/tests/rump/modautoload/Makefile b/tests/rump/modautoload/Makefile new file mode 100644 index 000000000..92b55465c --- /dev/null +++ b/tests/rump/modautoload/Makefile @@ -0,0 +1,24 @@ +# $NetBSD: Makefile,v 1.1 2010/06/09 12:35:45 pooka Exp $ +# + +TESTSDIR= ${TESTSBASE}/rump/modautoload + +TESTS_C= t_modautoload + +.include +.ifdef RUMPKMOD +CPPFLAGS+= -DHAVE_HOST_MODULES +.endif + +# Note: we link the rump kernel into the application to make this work +# on amd64. This is the reason we keep this test in its own +# subdirectory -- otherwise the LDADD lines would get a little hairy. +LDFLAGS+= -Wl,-E +LDADD+= -Wl,--whole-archive ${DESTDIR}/usr/lib/librumpvfs.a \ + ${DESTDIR}/usr/lib/librump.a \ + -Wl,--no-whole-archive +LDADD+= -lrumpuser -lpthread + +WARNS= 4 + +.include diff --git a/tests/rump/modautoload/t_modautoload.c b/tests/rump/modautoload/t_modautoload.c new file mode 100644 index 000000000..3246c31af --- /dev/null +++ b/tests/rump/modautoload/t_modautoload.c @@ -0,0 +1,76 @@ +/* $NetBSD: t_modautoload.c,v 1.1 2010/06/09 12:35:45 pooka Exp $ */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "../../h_macros.h" + +ATF_TC(modautoload); +ATF_TC_HEAD(modautoload, tc) +{ + + atf_tc_set_md_var(tc, "descr", "tests that kernel module " + "autoload works in rump"); +} + +static void +mountkernfs(void) +{ + +#ifndef HAVE_HOST_MODULES + atf_tc_skip("host kernel modules not supported on this architecture"); +#endif + + rump_init(); + + if (rump_sys_mkdir("/kern", 0777) == -1) + atf_tc_fail_errno("mkdir /kern"); + if (rump_sys_mount(MOUNT_KERNFS, "/kern", 0, NULL, 0) == -1) + atf_tc_fail_errno("could not mount kernfs"); +} + +/* + * Why use kernfs here? It talks to plenty of other parts with the + * kernel (e.g. vfs_attach() in modcmd), but is still easy to verify + * it's working correctly. + */ + +#define MAGICNUM 1323 +ATF_TC_BODY(modautoload, tc) +{ + extern int rumpns_hz; + char buf[64]; + int fd; + + mountkernfs(); + rumpns_hz = MAGICNUM; + if ((fd = rump_sys_open("/kern/hz", O_RDONLY)) == -1) + atf_tc_fail_errno("open /kern/hz"); + if (rump_sys_read(fd, buf, sizeof(buf)) <= 0) + atf_tc_fail_errno("read"); + ATF_REQUIRE(atoi(buf) == MAGICNUM); +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, modautoload); + + return atf_no_error(); +} diff --git a/tests/rump/rumpkern/Makefile b/tests/rump/rumpkern/Makefile new file mode 100644 index 000000000..8c1b0e5b4 --- /dev/null +++ b/tests/rump/rumpkern/Makefile @@ -0,0 +1,31 @@ +# $NetBSD: Makefile,v 1.14 2011/01/14 13:23:15 pooka Exp $ + +.include + +TESTSDIR= ${TESTSBASE}/rump/rumpkern + +TESTS_C= t_copy +TESTS_C+= t_kern +TESTS_C+= t_lwproc +TESTS_C+= t_modcmd +TESTS_C+= t_modlinkset +TESTS_C+= t_signals +TESTS_C+= t_threads +TESTS_C+= t_tsleep +TESTS_C+= t_vm + +TESTS_SH= t_sp + +SUBDIR+= h_client h_server + +ADD_TO_LD= -lrumpvfs -lrump -lrumpuser -lpthread +LDADD.t_modlinkset+= -lukfs -lrumpdev_disk -lrumpdev -lrumpfs_msdos +LDADD.t_modlinkset+= -lrumpfs_cd9660 ${ADD_TO_LD} +LDADD+= ${ADD_TO_LD} + +KERNSPACE != cd ${.CURDIR}/../kernspace && ${PRINTOBJDIR} +LDADD+= -L${KERNSPACE} -lkernspace + +WARNS= 4 + +.include diff --git a/tests/rump/rumpkern/h_client/Makefile b/tests/rump/rumpkern/h_client/Makefile new file mode 100644 index 000000000..bbd8fe75c --- /dev/null +++ b/tests/rump/rumpkern/h_client/Makefile @@ -0,0 +1,23 @@ +# $NetBSD: Makefile,v 1.5 2011/01/24 17:51:29 pooka Exp $ +# + +.include + +TESTSDIR= ${TESTSBASE}/rump/rumpkern/h_client + +TESTS_C+= h_forkcli +TESTS_C+= h_reconcli +TESTS_C+= h_sigcli +TESTS_C+= h_simplecli +TESTS_C+= h_stresscli + +ATFFILE= no + +LDADD+= -lrumpclient +LDADD.h_stresscli= -lpthread +LDADD.h_reconcli= -lpthread + +WARNS= 4 +NOMAN= + +.include diff --git a/tests/rump/rumpkern/h_client/h_forkcli.c b/tests/rump/rumpkern/h_client/h_forkcli.c new file mode 100644 index 000000000..3b89727be --- /dev/null +++ b/tests/rump/rumpkern/h_client/h_forkcli.c @@ -0,0 +1,169 @@ +/* $NetBSD: h_forkcli.c,v 1.1 2011/01/05 17:19:09 pooka Exp $ */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +static void +simple(void) +{ + struct rumpclient_fork *rf; + pid_t pid1, pid2; + int fd, status; + + if ((pid1 = rump_sys_getpid()) < 2) + errx(1, "unexpected pid %d", pid1); + + fd = rump_sys_open("/dev/null", O_CREAT | O_RDWR); + if (rump_sys_write(fd, &fd, sizeof(fd)) != sizeof(fd)) + errx(1, "write newlyopened /dev/null"); + + if ((rf = rumpclient_prefork()) == NULL) + err(1, "prefork"); + + switch (fork()) { + case -1: + err(1, "fork"); + break; + case 0: + if (rumpclient_fork_init(rf) == -1) + err(1, "postfork init failed"); + + if ((pid2 = rump_sys_getpid()) < 2) + errx(1, "unexpected pid %d", pid2); + if (pid1 == pid2) + errx(1, "child and parent pids are equal"); + + /* check that we can access the fd, the close it and exit */ + if (rump_sys_write(fd, &fd, sizeof(fd)) != sizeof(fd)) + errx(1, "write child /dev/null"); + rump_sys_close(fd); + break; + default: + /* + * check that we can access the fd, wait for the child, and + * check we can still access the fd + */ + if (rump_sys_write(fd, &fd, sizeof(fd)) != sizeof(fd)) + errx(1, "write parent /dev/null"); + if (wait(&status) == -1) + err(1, "wait failed"); + if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) + errx(1, "child exited with status %d", status); + if (rump_sys_write(fd, &fd, sizeof(fd)) != sizeof(fd)) + errx(1, "write parent /dev/null"); + break; + } +} + +static void +cancel(void) +{ + + /* XXX: not implemented in client / server !!! */ +} + +#define TESTSTR "i am your fatherrrrrrr" +#define TESTSLEN (sizeof(TESTSTR)-1) +static void +pipecomm(void) +{ + struct rumpclient_fork *rf; + char buf[TESTSLEN+1]; + int pipetti[2]; + int status; + + if (rump_sys_pipe(pipetti) == -1) + errx(1, "pipe"); + + if ((rf = rumpclient_prefork()) == NULL) + err(1, "prefork"); + + switch (fork()) { + case -1: + err(1, "fork"); + break; + case 0: + if (rumpclient_fork_init(rf) == -1) + err(1, "postfork init failed"); + + memset(buf, 0, sizeof(buf)); + if (rump_sys_read(pipetti[0], buf, TESTSLEN) != TESTSLEN) + err(1, "pipe read"); + if (strcmp(TESTSTR, buf) != 0) + errx(1, "teststring doesn't match, got %s", buf); + break; + default: + if (rump_sys_write(pipetti[1], TESTSTR, TESTSLEN) != TESTSLEN) + err(1, "pipe write"); + if (wait(&status) == -1) + err(1, "wait failed"); + if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) + errx(1, "child exited with status %d", status); + break; + } +} + +static void +fakeauth(void) +{ + struct rumpclient_fork *rf; + uint32_t *auth; + int rv; + + if ((rf = rumpclient_prefork()) == NULL) + err(1, "prefork"); + + /* XXX: we know the internal structure of rf */ + auth = (void *)rf; + *(auth+3) = *(auth+3) ^ 0x1; + + rv = rumpclient_fork_init(rf); + if (!(rv == -1 && errno == ESRCH)) + exit(1); +} + +struct parsa { + const char *arg; /* sp arg, el */ + void (*spring)(void); /* spring into action */ +} paragus[] = { + { "simple", simple }, + { "cancel", cancel }, + { "pipecomm", pipecomm }, + { "fakeauth", fakeauth }, +}; + +int +main(int argc, char *argv[]) +{ + unsigned i; + + if (argc != 2) + errx(1, "invalid usage"); + + if (rumpclient_init() == -1) + err(1, "rumpclient init"); + + for (i = 0; i < __arraycount(paragus); i++) { + if (strcmp(argv[1], paragus[i].arg) == 0) { + paragus[i].spring(); + break; + } + } + if (i == __arraycount(paragus)) { + printf("invalid test %s\n", argv[1]); + exit(1); + } + + exit(0); +} diff --git a/tests/rump/rumpkern/h_client/h_reconcli.c b/tests/rump/rumpkern/h_client/h_reconcli.c new file mode 100644 index 000000000..c594bbf8b --- /dev/null +++ b/tests/rump/rumpkern/h_client/h_reconcli.c @@ -0,0 +1,121 @@ +/* $NetBSD: h_reconcli.c,v 1.2 2011/02/19 09:56:45 pooka Exp $ */ + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +static volatile int quit, riseandwhine; + +static pthread_mutex_t closermtx; +static pthread_cond_t closercv; + +static void * +closer(void *arg) +{ + + pthread_mutex_lock(&closermtx); + while (!quit) { + while (!riseandwhine) + pthread_cond_wait(&closercv, &closermtx); + riseandwhine = 0; + pthread_mutex_unlock(&closermtx); + + /* try to catch a random slot */ + usleep(random() % 100000); + + /* + * wide-angle disintegration beam, but takes care + * of the client rumpkernel communication socket. + */ + closefrom(3); + + pthread_mutex_lock(&closermtx); + } + pthread_mutex_unlock(&closermtx); + + return NULL; +} + +static const int hostnamemib[] = { CTL_KERN, KERN_HOSTNAME }; +static char goodhostname[128]; + +static void * +worker(void *arg) +{ + char hostnamebuf[128]; + size_t blen; + + pthread_mutex_lock(&closermtx); + while (!quit) { + pthread_mutex_unlock(&closermtx); + if (rump_sys_getpid() == -1) + err(1, "getpid"); + + blen = sizeof(hostnamebuf); + memset(hostnamebuf, 0, sizeof(hostnamebuf)); + if (rump_sys___sysctl(hostnamemib, __arraycount(hostnamemib), + hostnamebuf, &blen, NULL, 0) == -1) + err(1, "sysctl"); + if (strcmp(hostnamebuf, goodhostname) != 0) + exit(1); + pthread_mutex_lock(&closermtx); + riseandwhine = 1; + pthread_cond_signal(&closercv); + } + riseandwhine = 1; + pthread_cond_signal(&closercv); + pthread_mutex_unlock(&closermtx); + + return NULL; +} + +int +main(int argc, char *argv[]) +{ + pthread_t pt, w1, w2, w3, w4; + size_t blen; + int timecount; + + if (argc != 2) + errx(1, "need timecount"); + timecount = atoi(argv[1]); + if (timecount <= 0) + errx(1, "invalid timecount %d\n", timecount); + + srandom(time(NULL)); + + rumpclient_setconnretry(RUMPCLIENT_RETRYCONN_INFTIME); + if (rumpclient_init() == -1) + err(1, "init"); + + blen = sizeof(goodhostname); + if (rump_sys___sysctl(hostnamemib, __arraycount(hostnamemib), + goodhostname, &blen, NULL, 0) == -1) + err(1, "sysctl"); + + pthread_create(&pt, NULL, closer, NULL); + pthread_create(&w1, NULL, worker, NULL); + pthread_create(&w2, NULL, worker, NULL); + pthread_create(&w3, NULL, worker, NULL); + pthread_create(&w4, NULL, worker, NULL); + + sleep(timecount); + quit = 1; + + pthread_join(pt, NULL); + pthread_join(w1, NULL); + pthread_join(w2, NULL); + pthread_join(w3, NULL); + pthread_join(w4, NULL); + + exit(0); +} diff --git a/tests/rump/rumpkern/h_client/h_sigcli.c b/tests/rump/rumpkern/h_client/h_sigcli.c new file mode 100644 index 000000000..9134f98b5 --- /dev/null +++ b/tests/rump/rumpkern/h_client/h_sigcli.c @@ -0,0 +1,84 @@ +/* $NetBSD: h_sigcli.c,v 1.3 2011/02/07 20:05:09 pooka Exp $ */ + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +static const int hostnamemib[] = { CTL_KERN, KERN_HOSTNAME }; +static char hostnamebuf[128]; + +static volatile sig_atomic_t sigexecs; + +static void +sighand(int sig) +{ + char buf[128]; + size_t blen = sizeof(buf); + + if (rump_sys___sysctl(hostnamemib, __arraycount(hostnamemib), + buf, &blen, NULL, 0) == -1) + err(1, "sighand sysctl"); + if (strcmp(buf, hostnamebuf) != 0) + errx(1, "sighandler hostname"); + sigexecs++; +} + +int +main(void) +{ + char buf[128]; + time_t tstart; + struct itimerval itv; + size_t hnbsize; + int i; + size_t blen; + + if (rumpclient_init() == -1) + err(1, "rumpclient init"); + + hnbsize = sizeof(hostnamebuf); + if (rump_sys___sysctl(hostnamemib, __arraycount(hostnamemib), + hostnamebuf, &hnbsize, NULL, 0) == -1) + err(1, "sysctl"); + + if (signal(SIGALRM, sighand) == SIG_ERR) + err(1, "signal"); + + itv.it_interval.tv_sec = itv.it_value.tv_sec = 0; + itv.it_interval.tv_usec = itv.it_value.tv_usec = 10000; /* 10ms */ + + if (setitimer(ITIMER_REAL, &itv, NULL) == -1) + err(1, "itimer"); + + tstart = time(NULL); + for (i = 0;; i++) { + blen = sizeof(buf); + if (rump_sys___sysctl(hostnamemib, __arraycount(hostnamemib), + buf, &blen, NULL, 0) == -1) + err(1, "sysctl"); + if (strcmp(buf, hostnamebuf) != 0) + errx(1, "main hostname"); + + /* + * check every 100 cycles to avoid doing + * nothing but gettimeofday() + */ + if (i == 100) { + if (time(NULL) - tstart > 5) + break; + i = 0; + } + } + + if (!sigexecs) { + printf("no signal handlers run. test busted?\n"); + } +} diff --git a/tests/rump/rumpkern/h_client/h_simplecli.c b/tests/rump/rumpkern/h_client/h_simplecli.c new file mode 100644 index 000000000..11f432c38 --- /dev/null +++ b/tests/rump/rumpkern/h_client/h_simplecli.c @@ -0,0 +1,30 @@ +/* $NetBSD: h_simplecli.c,v 1.2 2011/01/14 13:23:15 pooka Exp $ */ + +#include + +#include +#include +#include +#include + +#include +#include + +int +main(int argc, char *argv[]) +{ + + if (rumpclient_init() == -1) + err(1, "rumpclient init"); + + if (argc > 1) { + for (;;) { + rump_sys_getpid(); + usleep(10000); + } + } else { + if (rump_sys_getpid() > 0) + exit(0); + err(1, "getpid"); + } +} diff --git a/tests/rump/rumpkern/h_client/h_stresscli.c b/tests/rump/rumpkern/h_client/h_stresscli.c new file mode 100644 index 000000000..d49edeb9a --- /dev/null +++ b/tests/rump/rumpkern/h_client/h_stresscli.c @@ -0,0 +1,219 @@ +/* $NetBSD: h_stresscli.c,v 1.9 2011/06/26 13:17:36 christos Exp $ */ + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +static unsigned int syscalls, bindcalls; +static pid_t mypid; +static volatile sig_atomic_t doquit; + +static void +signaali(int sig) +{ + + doquit = 1; +} + +static const int hostnamemib[] = { CTL_KERN, KERN_HOSTNAME }; +static char hostnamebuf[128]; +#define HOSTNAMEBASE "rumpclient" + +static int iskiller; + +static void * +client(void *arg) +{ + char buf[256]; + struct sockaddr_in sin; + size_t blen; + int port = (int)(uintptr_t)arg; + int s, fd, x; + + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_len = sizeof(sin); + sin.sin_port = htons(port); + + while (!doquit) { + pid_t pidi; + blen = sizeof(buf); + s = rump_sys_socket(PF_INET, SOCK_STREAM, 0); + if (s == -1) + err(1, "socket"); + atomic_inc_uint(&syscalls); + + fd = rump_sys_open("/dev/null", O_RDWR); + atomic_inc_uint(&syscalls); + + if (doquit) + goto out; + + x = 1; + if (rump_sys_setsockopt(s, SOL_SOCKET, SO_REUSEADDR, + &x, sizeof(x)) == -1) + err(1, "reuseaddr"); + + /* + * we don't really know when the kernel handles our disconnect, + * so be soft about about the failure in case of a killer client + */ + if (rump_sys_bind(s, (struct sockaddr*)&sin, sizeof(sin))==-1) { + if (!iskiller) + err(1, "bind to port %d failed", + ntohs(sin.sin_port)); + } else { + atomic_inc_uint(&bindcalls); + } + atomic_inc_uint(&syscalls); + + if (doquit) + goto out; + + if (rump_sys___sysctl(hostnamemib, __arraycount(hostnamemib), + buf, &blen, NULL, 0) == -1) + err(1, "sysctl"); + if (strncmp(buf, hostnamebuf, sizeof(HOSTNAMEBASE)-1) != 0) + errx(1, "hostname (%s/%s) mismatch", buf, hostnamebuf); + atomic_inc_uint(&syscalls); + + if (doquit) + goto out; + + pidi = rump_sys_getpid(); + if (pidi == -1) + err(1, "getpid"); + if (pidi != mypid) + errx(1, "mypid mismatch"); + atomic_inc_uint(&syscalls); + + if (doquit) + goto out; + + if (rump_sys_write(fd, buf, 16) != 16) + err(1, "write /dev/null"); + atomic_inc_uint(&syscalls); + + out: + rump_sys_close(fd); + atomic_inc_uint(&syscalls); + rump_sys_close(s); + atomic_inc_uint(&syscalls); + } + + return NULL; +} + +/* Stress with max 32 clients, 8 threads each (256 concurrent threads) */ +#define NCLI 32 +#define NTHR 8 + +int +main(int argc, char *argv[]) +{ + pthread_t pt[NTHR-1]; + pid_t clis[NCLI]; + pid_t apid; + int ncli = 0; + int i = 0, j; + int status, thesig; + int rounds, myport; + + if (argc != 2 && argc != 3) + errx(1, "need roundcount"); + + if (argc == 3) { + if (strcmp(argv[2], "kill") != 0) + errx(1, "optional 3rd param must be kill"); + thesig = SIGKILL; + iskiller = 1; + } else { + thesig = SIGUSR1; + } + + signal(SIGUSR1, signaali); + + memset(clis, 0, sizeof(clis)); + for (rounds = 1; rounds < atoi(argv[1])*10; rounds++) { + while (ncli < NCLI) { + switch ((apid = fork())) { + case -1: + err(1, "fork failed"); + case 0: + if (rumpclient_init() == -1) + err(1, "rumpclient init"); + + mypid = rump_sys_getpid(); + sprintf(hostnamebuf, HOSTNAMEBASE "%d", mypid); + if (rump_sys___sysctl(hostnamemib, + __arraycount(hostnamemib), NULL, NULL, + hostnamebuf, strlen(hostnamebuf)+1) == -1) + err(1, "sethostname"); + + for (j = 0; j < NTHR-1; j++) { + myport = i*NCLI + j+2; + if (pthread_create(&pt[j], NULL, + client, + (void*)(uintptr_t)myport) !=0 ) + err(1, "pthread create"); + } + myport = i*NCLI+1; + client((void *)(uintptr_t)myport); + for (j = 0; j < NTHR-1; j++) + pthread_join(pt[j], NULL); + membar_consumer(); + fprintf(stderr, "done %d\n", syscalls); + exit(0); + /* NOTREACHED */ + default: + ncli++; + clis[i] = apid; + break; + } + + i = (i + 1) % NCLI; + } + + usleep(100000); + kill(clis[i], thesig); + + apid = wait(&status); + if (apid != clis[i]) + errx(1, "wanted pid %d, got %d\n", clis[i], apid); + clis[i] = 0; + ncli--; + if (thesig == SIGUSR1) { + if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { + fprintf(stderr, "child died with 0x%x\n", + status); + exit(1); + } + } else { + if (!WIFSIGNALED(status) || WTERMSIG(status) != thesig){ + fprintf(stderr, "child died with 0x%x\n", + status); + exit(1); + } + } + } + + for (i = 0; i < NCLI; i++) + if (clis[i]) + kill(clis[i], SIGKILL); +} diff --git a/tests/rump/rumpkern/h_server/Makefile b/tests/rump/rumpkern/h_server/Makefile new file mode 100644 index 000000000..7f15ecb51 --- /dev/null +++ b/tests/rump/rumpkern/h_server/Makefile @@ -0,0 +1,20 @@ +# $NetBSD: Makefile,v 1.3 2011/01/14 13:23:15 pooka Exp $ +# + +.include + +TESTSDIR= ${TESTSBASE}/rump/rumpkern/h_server + +TESTS_C= h_simpleserver + +ATFFILE= no + +LDADD+= -lrump -lrumpuser -lpthread + +WARNS= 4 +NOMAN= + +KERNSPACE != cd ${.CURDIR}/../../kernspace && ${PRINTOBJDIR} +LDADD+= -L${KERNSPACE} -lkernspace + +.include diff --git a/tests/rump/rumpkern/h_server/h_simpleserver.c b/tests/rump/rumpkern/h_server/h_simpleserver.c new file mode 100644 index 000000000..4e04c2269 --- /dev/null +++ b/tests/rump/rumpkern/h_server/h_simpleserver.c @@ -0,0 +1,63 @@ +/* $NetBSD: h_simpleserver.c,v 1.3 2011/01/14 13:23:15 pooka Exp $ */ + +#include + +#include + +#include +#include +#include +#include +#include + +#include "../../kernspace/kernspace.h" + +#define NOFAIL(e) do { int rv = e; if (rv) err(1, #e); } while (/*CONSTCOND*/0) + +struct { + const char *str; + void (*dofun)(char *); +} actions[] = { + { "sendsig", rumptest_sendsig }, +}; + +int +main(int argc, char *argv[]) +{ + unsigned i; + bool match; + + if (argc < 2) + exit(1); + + NOFAIL(rump_daemonize_begin()); + NOFAIL(rump_init()); + NOFAIL(rump_init_server(argv[1])); + NOFAIL(rump_daemonize_done(RUMP_DAEMONIZE_SUCCESS)); + + if (argc > 2) { + char *arg = NULL; + + if (argc == 4) + arg = argv[3]; + + for (i = 0; i < __arraycount(actions); i++) { + if (strcmp(actions[i].str, argv[2]) == 0) { + rump_schedule(); + actions[i].dofun(arg); + rump_unschedule(); + match = true; + } + } + + if (!match) { + exit(1); + } + pause(); + } else { + for (;;) + pause(); + } + + return 0; +} diff --git a/tests/rump/rumpkern/t_copy.c b/tests/rump/rumpkern/t_copy.c new file mode 100644 index 000000000..e70b177fb --- /dev/null +++ b/tests/rump/rumpkern/t_copy.c @@ -0,0 +1,119 @@ +/* $NetBSD: t_copy.c,v 1.1 2010/11/09 15:25:20 pooka Exp $ */ + +/*- + * Copyright (c) 2010 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include +#include +#include + +#include + +ATF_TC(copystr); +ATF_TC_HEAD(copystr, tc) +{ + + atf_tc_set_md_var(tc, "descr", "Tests copystr()"); +} + +ATF_TC(copyinstr); +ATF_TC_HEAD(copyinstr, tc) +{ + + atf_tc_set_md_var(tc, "descr", "Tests copyinstr()"); +} + +ATF_TC(copyoutstr); +ATF_TC_HEAD(copyoutstr, tc) +{ + + atf_tc_set_md_var(tc, "descr", "Tests copyoutstr()"); +} + +typedef int (copy_fn)(const void *, void *, size_t, size_t *); + +extern copy_fn rumpns_copystr, rumpns_copyinstr, rumpns_copyoutstr; + +#define TESTSTR "jippii, lisaa puuroa" + +static void +dotest(copy_fn *thefun) +{ + char buf[sizeof(TESTSTR)+1]; + size_t len; + + rump_init(); + rump_schedule(); + + /* larger buffer */ + memset(buf, 0xaa, sizeof(buf)); + ATF_REQUIRE_EQ(thefun(TESTSTR, buf, sizeof(buf), &len), 0); + ATF_REQUIRE_EQ(len, sizeof(TESTSTR)); + ATF_REQUIRE_STREQ(TESTSTR, buf); + + /* just large enough */ + memset(buf, 0xaa, sizeof(buf)); + ATF_REQUIRE_EQ(thefun(TESTSTR, buf, sizeof(buf)-1, &len), 0); + ATF_REQUIRE_EQ(len, sizeof(TESTSTR)); + ATF_REQUIRE_STREQ(TESTSTR, buf); + + /* one too small */ + memset(buf, 0xaa, sizeof(buf)); + ATF_REQUIRE_EQ(thefun(TESTSTR, buf, sizeof(buf)-2, NULL), ENAMETOOLONG); + + rump_unschedule(); +} + +ATF_TC_BODY(copystr, tc) +{ + + dotest(rumpns_copystr); +} + +ATF_TC_BODY(copyinstr, tc) +{ + + dotest(rumpns_copyinstr); +} + +ATF_TC_BODY(copyoutstr, tc) +{ + + dotest(rumpns_copyoutstr); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, copystr); + ATF_TP_ADD_TC(tp, copyinstr); + ATF_TP_ADD_TC(tp, copyoutstr); + + return atf_no_error(); +} diff --git a/tests/rump/rumpkern/t_kern.c b/tests/rump/rumpkern/t_kern.c new file mode 100644 index 000000000..fcaf1f817 --- /dev/null +++ b/tests/rump/rumpkern/t_kern.c @@ -0,0 +1,119 @@ +/* $NetBSD: t_kern.c,v 1.3 2012/01/30 13:05:52 njoly Exp $ */ + +/*- + * Copyright (c) 2011 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include "../../h_macros.h" +#include "../kernspace/kernspace.h" + +#define LOCKFUN(_name_, _descr_,_needld_, _expect_) \ + ATF_TC(lockme_##_name_); \ + ATF_TC_HEAD(lockme_##_name_, tc) { \ + atf_tc_set_md_var(tc, "descr", _descr_); \ + } \ + ATF_TC_BODY(lockme_##_name_, tc) { \ + locktest(tc, LOCKME_##_name_, _needld_, _expect_); \ + } + +static void +locktest(const atf_tc_t *tc, enum locktest lt, int needld, const char *expect) +{ + extern const int rump_lockdebug; + int pipetti[2]; + int status; + + if (needld && !rump_lockdebug) + atf_tc_skip("test requires LOCKDEBUG kernel"); + RL(pipe(pipetti)); + + switch (fork()) { + case 0: + RL(dup2(pipetti[1], STDOUT_FILENO)); + RL(dup2(pipetti[1], STDOUT_FILENO)); + rump_init(); + rump_schedule(); + rumptest_lockme(lt); + rump_unschedule(); + break; + default: + RL(wait(&status)); + ATF_REQUIRE(WIFSIGNALED(status) && WTERMSIG(status) == SIGABRT); + if (rump_lockdebug) { + char buf[8192]; + + ATF_REQUIRE(read(pipetti[0], buf, sizeof(buf)) > 0); + if (strncmp(buf, expect, strlen(expect)) != 0) + atf_tc_fail("unexpected output"); + } + break; + case -1: + atf_tc_fail("fork"); + } +} + +LOCKFUN(DESTROYHELD, "destroy lock while held", 0, + "mutex error: lockdebug_free: is locked or in use"); +LOCKFUN(DOUBLEFREE, "free lock twice", 0, + "panic: lockdebug_lookup: uninitialized lock"); +LOCKFUN(DOUBLEINIT, "init lock twice", 1, + "mutex error: lockdebug_alloc: already initialized"); +LOCKFUN(MEMFREE, "free memory active lock is in", 1, + "mutex error: kmem_intr_free: allocation contains active lock"); +LOCKFUN(MTX, "locking-against-self mutex", 0, + "mutex error: lockdebug_wantlock: locking against myself"); +LOCKFUN(RWDOUBLEX, "locking-against-self exclusive rwlock", 0, + "rwlock error: lockdebug_wantlock: locking against myself"); +LOCKFUN(RWRX, "rw: first shared, then exclusive", 1, + "rwlock error: lockdebug_wantlock: locking against myself"); +LOCKFUN(RWXR, "rw: first execusive, then shared", 0, + "rwlock error: lockdebug_wantlock: locking against myself"); + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, lockme_MTX); + ATF_TP_ADD_TC(tp, lockme_RWDOUBLEX); + ATF_TP_ADD_TC(tp, lockme_RWRX); + ATF_TP_ADD_TC(tp, lockme_RWXR); + ATF_TP_ADD_TC(tp, lockme_DOUBLEINIT); + ATF_TP_ADD_TC(tp, lockme_DOUBLEFREE); + ATF_TP_ADD_TC(tp, lockme_DESTROYHELD); + ATF_TP_ADD_TC(tp, lockme_MEMFREE); + + return atf_no_error(); +} diff --git a/tests/rump/rumpkern/t_lwproc.c b/tests/rump/rumpkern/t_lwproc.c new file mode 100644 index 000000000..dcdfdb6f3 --- /dev/null +++ b/tests/rump/rumpkern/t_lwproc.c @@ -0,0 +1,316 @@ +/* $NetBSD: t_lwproc.c,v 1.5 2011/01/02 12:58:17 pooka Exp $ */ + +/* + * Copyright (c) 2010 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../../h_macros.h" + +ATF_TC(makelwp); +ATF_TC_HEAD(makelwp, tc) +{ + + atf_tc_set_md_var(tc, "descr", "tests that lwps can be attached to " + "processes"); +} + +ATF_TC_BODY(makelwp, tc) +{ + struct lwp *l; + pid_t pid; + + rump_init(); + RZ(rump_pub_lwproc_newlwp(0)); + ATF_REQUIRE_EQ(rump_pub_lwproc_newlwp(37), ESRCH); + l = rump_pub_lwproc_curlwp(); + + RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG)); + ATF_REQUIRE(rump_pub_lwproc_curlwp() != l); + l = rump_pub_lwproc_curlwp(); + + RZ(rump_pub_lwproc_newlwp(rump_sys_getpid())); + ATF_REQUIRE(rump_pub_lwproc_curlwp() != l); + + pid = rump_sys_getpid(); + ATF_REQUIRE(pid != -1 && pid != 0); +} + +ATF_TC(proccreds); +ATF_TC_HEAD(proccreds, tc) +{ + + atf_tc_set_md_var(tc, "descr", "check that procs have different creds"); +} + +ATF_TC_BODY(proccreds, tc) +{ + struct lwp *l1, *l2; + + rump_init(); + RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG)); + l1 = rump_pub_lwproc_curlwp(); + + RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG)); + l2 = rump_pub_lwproc_curlwp(); + + RL(rump_sys_setuid(22)); + ATF_REQUIRE_EQ(rump_sys_getuid(), 22); + + rump_pub_lwproc_switch(l1); + ATF_REQUIRE_EQ(rump_sys_getuid(), 0); /* from parent, proc0 */ + RL(rump_sys_setuid(11)); + ATF_REQUIRE_EQ(rump_sys_getuid(), 11); + + rump_pub_lwproc_switch(l2); + ATF_REQUIRE_EQ(rump_sys_getuid(), 22); + rump_pub_lwproc_newlwp(rump_sys_getpid()); + ATF_REQUIRE_EQ(rump_sys_getuid(), 22); +} + + +ATF_TC(inherit); +ATF_TC_HEAD(inherit, tc) +{ + + atf_tc_set_md_var(tc, "descr", "new processes inherit creds from " + "parents"); +} + +ATF_TC_BODY(inherit, tc) +{ + + rump_init(); + + RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG)); + RL(rump_sys_setuid(66)); + ATF_REQUIRE_EQ(rump_sys_getuid(), 66); + + RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG)); + ATF_REQUIRE_EQ(rump_sys_getuid(), 66); + + /* release lwp and proc */ + rump_pub_lwproc_releaselwp(); + ATF_REQUIRE_EQ(rump_sys_getuid(), 0); +} + +ATF_TC(lwps); +ATF_TC_HEAD(lwps, tc) +{ + + atf_tc_set_md_var(tc, "descr", "proc can hold many lwps and is " + "automatically g/c'd when the last one exits"); +} + +#define LOOPS 128 +ATF_TC_BODY(lwps, tc) +{ + struct lwp *l[LOOPS]; + pid_t mypid; + struct lwp *l_orig; + int i; + + rump_init(); + + RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG)); + mypid = rump_sys_getpid(); + RL(rump_sys_setuid(375)); + + l_orig = rump_pub_lwproc_curlwp(); + for (i = 0; i < LOOPS; i++) { + mypid = rump_sys_getpid(); + ATF_REQUIRE(mypid != -1 && mypid != 0); + RZ(rump_pub_lwproc_newlwp(mypid)); + l[i] = rump_pub_lwproc_curlwp(); + ATF_REQUIRE_EQ(rump_sys_getuid(), 375); + } + + rump_pub_lwproc_switch(l_orig); + rump_pub_lwproc_releaselwp(); + for (i = 0; i < LOOPS; i++) { + rump_pub_lwproc_switch(l[i]); + ATF_REQUIRE_EQ(rump_sys_getpid(), mypid); + ATF_REQUIRE_EQ(rump_sys_getuid(), 375); + rump_pub_lwproc_releaselwp(); + ATF_REQUIRE_EQ(rump_sys_getpid(), 1); + ATF_REQUIRE_EQ(rump_sys_getuid(), 0); + } + + ATF_REQUIRE_EQ(rump_pub_lwproc_newlwp(mypid), ESRCH); +} + +ATF_TC(nolwprelease); +ATF_TC_HEAD(nolwprelease, tc) +{ + + atf_tc_set_md_var(tc, "descr", "check that lwp context is required " + "for lwproc_releaselwp()"); +} + +ATF_TC_BODY(nolwprelease, tc) +{ + int status; + + switch (fork()) { + case 0: + rump_init(); + rump_pub_lwproc_releaselwp(); + atf_tc_fail("survived"); + break; + case -1: + atf_tc_fail_errno("fork"); + break; + default: + wait(&status); + ATF_REQUIRE(WIFSIGNALED(status)); + ATF_REQUIRE_EQ(WTERMSIG(status), SIGABRT); + + } +} + +ATF_TC(nolwp); +ATF_TC_HEAD(nolwp, tc) +{ + + atf_tc_set_md_var(tc, "descr", "check that curlwp for an implicit " + "context is NULL"); +} + +ATF_TC_BODY(nolwp, tc) +{ + + rump_init(); + ATF_REQUIRE_EQ(rump_pub_lwproc_curlwp(), NULL); +} + +ATF_TC(nullswitch); +ATF_TC_HEAD(nullswitch, tc) +{ + + atf_tc_set_md_var(tc, "descr", "check that switching to NULL marks " + "current lwp as not running"); +} + +ATF_TC_BODY(nullswitch, tc) +{ + struct lwp *l; + + rump_init(); + RZ(rump_pub_lwproc_newlwp(0)); + l = rump_pub_lwproc_curlwp(); + rump_pub_lwproc_switch(NULL); + /* if remains LP_RUNNING, next call will panic */ + rump_pub_lwproc_switch(l); +} + +ATF_TC(rfork); +ATF_TC_HEAD(rfork, tc) +{ + + atf_tc_set_md_var(tc, "descr", "check that fork shares fd's"); +} + +ATF_TC_BODY(rfork, tc) +{ + struct stat sb; + struct lwp *l, *l2; + int fd; + + RZ(rump_init()); + + ATF_REQUIRE_EQ(rump_pub_lwproc_rfork(RUMP_RFFDG|RUMP_RFCFDG), EINVAL); + + RZ(rump_pub_lwproc_rfork(0)); + l = rump_pub_lwproc_curlwp(); + + RL(fd = rump_sys_open("/file", O_RDWR | O_CREAT, 0777)); + + /* ok, first check rfork(RUMP_RFCFDG) does *not* preserve fd's */ + RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG)); + ATF_REQUIRE_ERRNO(EBADF, rump_sys_write(fd, &fd, sizeof(fd)) == -1); + + /* then check that rfork(0) does */ + rump_pub_lwproc_switch(l); + RZ(rump_pub_lwproc_rfork(0)); + ATF_REQUIRE_EQ(rump_sys_write(fd, &fd, sizeof(fd)), sizeof(fd)); + RL(rump_sys_fstat(fd, &sb)); + l2 = rump_pub_lwproc_curlwp(); + + /* + * check that the shared fd table is really shared by + * closing fd in parent + */ + rump_pub_lwproc_switch(l); + RL(rump_sys_close(fd)); + rump_pub_lwproc_switch(l2); + ATF_REQUIRE_ERRNO(EBADF, rump_sys_fstat(fd, &sb) == -1); + + /* redo, this time copying the fd table instead of sharing it */ + rump_pub_lwproc_releaselwp(); + rump_pub_lwproc_switch(l); + RL(fd = rump_sys_open("/file", O_RDWR, 0777)); + RZ(rump_pub_lwproc_rfork(RUMP_RFFDG)); + ATF_REQUIRE_EQ(rump_sys_write(fd, &fd, sizeof(fd)), sizeof(fd)); + RL(rump_sys_fstat(fd, &sb)); + l2 = rump_pub_lwproc_curlwp(); + + /* check that the fd table is copied */ + rump_pub_lwproc_switch(l); + RL(rump_sys_close(fd)); + rump_pub_lwproc_switch(l2); + RL(rump_sys_fstat(fd, &sb)); + ATF_REQUIRE_EQ(sb.st_size, sizeof(fd)); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, makelwp); + ATF_TP_ADD_TC(tp, proccreds); + ATF_TP_ADD_TC(tp, inherit); + ATF_TP_ADD_TC(tp, lwps); + ATF_TP_ADD_TC(tp, nolwprelease); + ATF_TP_ADD_TC(tp, nolwp); + ATF_TP_ADD_TC(tp, nullswitch); + ATF_TP_ADD_TC(tp, rfork); + + return atf_no_error(); +} diff --git a/tests/rump/rumpkern/t_modcmd.c b/tests/rump/rumpkern/t_modcmd.c new file mode 100644 index 000000000..032e31296 --- /dev/null +++ b/tests/rump/rumpkern/t_modcmd.c @@ -0,0 +1,182 @@ +/* $NetBSD: t_modcmd.c,v 1.9 2010/05/31 23:51:28 pooka Exp $ */ + +/* + * Copyright (c) 2009 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../../h_macros.h" +/* + * We verify that modules can be loaded and unloaded. + * tmpfs was chosen because it does not depend on an image. + */ + +ATF_TC(cmsg_modcmd); +ATF_TC_HEAD(cmsg_modcmd, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks that loading and unloading " + "a module (vfs/tmpfs) is possible"); +} + +static int +disable_autoload(void) +{ + struct sysctlnode q, ans[256]; + int mib[3]; + size_t alen; + unsigned i; + bool no; + + mib[0] = CTL_KERN; + mib[1] = CTL_QUERY; + alen = sizeof(ans); + + memset(&q, 0, sizeof(q)); + q.sysctl_flags = SYSCTL_VERSION; + + if (rump_sys___sysctl(mib, 2, ans, &alen, &q, sizeof(q)) == -1) + return -1; + + for (i = 0; i < __arraycount(ans); i++) + if (strcmp("module", ans[i].sysctl_name) == 0) + break; + if (i == __arraycount(ans)) { + errno = ENOENT; + return -1; + } + + mib[1] = ans[i].sysctl_num; + mib[2] = CTL_QUERY; + + if (rump_sys___sysctl(mib, 3, ans, &alen, &q, sizeof(q)) == -1) + return errno; + + for (i = 0; i < __arraycount(ans); i++) + if (strcmp("autoload", ans[i].sysctl_name) == 0) + break; + if (i == __arraycount(ans)) { + errno = ENOENT; + return -1; + } + + mib[2] = ans[i].sysctl_num; + + no = false; + alen = 0; + if (rump_sys___sysctl(mib, 3, NULL, &alen, &no, sizeof(no)) == -1) + return errno; + + return 0; + +} + +#define TMPFSMODULE "librumpfs_tmpfs.so" +ATF_TC_BODY(cmsg_modcmd, tc) +{ + struct tmpfs_args args; + const struct modinfo *const *mi_start, *const *mi_end; + void *handle; + int i, rv, loop = 0; + + rump_init(); + + if (disable_autoload() == -1) + atf_tc_fail_errno("count not disable module autoload"); + + memset(&args, 0, sizeof(args)); + args.ta_version = TMPFS_ARGS_VERSION; + args.ta_root_mode = 0777; + + if (rump_sys_mkdir("/mp", 0777) == -1) + atf_tc_fail_errno("mkdir mountpoint"); + if (rump_sys_mount(MOUNT_TMPFS, "/mp", 0, &args, sizeof(args)) != -1) + atf_tc_fail("mount unexpectedly succeeded"); + + handle = dlopen(TMPFSMODULE, RTLD_GLOBAL); + if (handle == NULL) { + const char *dlmsg = dlerror(); + atf_tc_fail("cannot open %s: %s", TMPFSMODULE, dlmsg); + } + + again: + mi_start = dlsym(handle, "__start_link_set_modules"); + mi_end = dlsym(handle, "__stop_link_set_modules"); + if (mi_start == NULL || mi_end == NULL) + atf_tc_fail("cannot find module info"); + if ((rv = rump_pub_module_init(mi_start, (size_t)(mi_end-mi_start)))!=0) + atf_tc_fail("module init failed: %d (%s)", rv, strerror(rv)); + if ((rv = rump_pub_module_init(mi_start, (size_t)(mi_end-mi_start)))==0) + atf_tc_fail("module double init succeeded"); + + if (rump_sys_mount(MOUNT_TMPFS, "/mp", 0, &args, sizeof(args)) == -1) + atf_tc_fail_errno("still cannot mount"); + if (rump_sys_unmount("/mp", 0) == -1) + atf_tc_fail("cannot unmount"); + for (i = 0; i < (int)(mi_end-mi_start); i++) { + if ((rv = rump_pub_module_fini(mi_start[i])) != 0) + atf_tc_fail("module fini failed: %d (%s)", + rv, strerror(rv)); + } + for (i = 0; i < (int)(mi_end-mi_start); i++) { + if ((rv = rump_pub_module_fini(mi_start[i])) == 0) + atf_tc_fail("module double fini succeeded"); + } + if (loop++ == 0) + goto again; + + if (dlclose(handle)) { + const char *dlmsg = dlerror(); + atf_tc_fail("cannot close %s: %s", TMPFSMODULE, dlmsg); + } + + if (rump_sys_mount(MOUNT_TMPFS, "/mp", 0, &args, sizeof(args)) != -1) + atf_tc_fail("mount unexpectedly succeeded"); +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, cmsg_modcmd); + + return atf_no_error(); +} diff --git a/tests/rump/rumpkern/t_modlinkset.c b/tests/rump/rumpkern/t_modlinkset.c new file mode 100644 index 000000000..a4d34bb91 --- /dev/null +++ b/tests/rump/rumpkern/t_modlinkset.c @@ -0,0 +1,73 @@ +/* $NetBSD: t_modlinkset.c,v 1.2 2009/11/06 15:26:54 pooka Exp $ */ + +/* + * Copyright (c) 2009 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include "../../h_macros.h" + +ATF_TC(modlinkset); +ATF_TC_HEAD(modlinkset, tc) +{ + atf_tc_set_md_var(tc, "descr", "Check that module linkset bootstrap " + "works"); +} + +/* + * We link against cd9660 and msdosfs (both chosed because the names + * are unlikely to ever be a substring of a another file system). + * Without proper linkset handling at most one will be reported. + */ +ATF_TC_BODY(modlinkset, tc) +{ + char buf[1024]; + + rump_init(); + if (ukfs_vfstypes(buf, sizeof(buf)) == -1) + atf_tc_fail_errno("ukfs_vfstypes"); + + ATF_CHECK((strstr(buf, "msdos") != NULL)); + ATF_CHECK((strstr(buf, "cd9660") != NULL)); +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, modlinkset); + + return atf_no_error(); +} diff --git a/tests/rump/rumpkern/t_signals.c b/tests/rump/rumpkern/t_signals.c new file mode 100644 index 000000000..e113af29a --- /dev/null +++ b/tests/rump/rumpkern/t_signals.c @@ -0,0 +1,127 @@ +/* $NetBSD: t_signals.c,v 1.2 2011/02/20 19:45:45 pooka Exp $ */ + +/*- + * Copyright (c) 2011 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include "../kernspace/kernspace.h" +#include "../../h_macros.h" + +ATF_TC(sigraise); +ATF_TC_HEAD(sigraise, tc) +{ + + atf_tc_set_md_var(tc, "descr", "RUMP_SIGMODEL_RAISE"); +} + +ATF_TC(sigignore); +ATF_TC_HEAD(sigignore, tc) +{ + + atf_tc_set_md_var(tc, "descr", "RUMP_SIGMODEL_IGNORE"); +} + +ATF_TC(sigpanic); +ATF_TC_HEAD(sigpanic, tc) +{ + + atf_tc_set_md_var(tc, "descr", "RUMP_SIGMODEL_PANIC"); +} + +static volatile sig_atomic_t sigcnt; +static void +thehand(int sig) +{ + + sigcnt++; +} + +ATF_TC_BODY(sigraise, tc) +{ + + signal(SIGUSR2, thehand); + rump_boot_setsigmodel(RUMP_SIGMODEL_RAISE); + + rump_init(); + rump_schedule(); + rumptest_localsig(SIGUSR2); + rump_unschedule(); + ATF_REQUIRE_EQ(sigcnt, 1); +} + +ATF_TC_BODY(sigignore, tc) +{ + + rump_boot_setsigmodel(RUMP_SIGMODEL_IGNORE); + + rump_init(); + rump_schedule(); + rumptest_localsig(SIGKILL); + rump_unschedule(); +} + +ATF_TC_BODY(sigpanic, tc) +{ + int status; + + rump_boot_setsigmodel(RUMP_SIGMODEL_PANIC); + + switch (fork()) { + case 0: + rump_init(); + rump_schedule(); + rumptest_localsig(SIGCONT); + /* NOTREACHED */ + exit(1); + default: + wait(&status); + ATF_REQUIRE(WIFSIGNALED(status) && WTERMSIG(status) == SIGABRT); + break; + case -1: + atf_tc_fail_errno("fork"); + } +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, sigraise); + ATF_TP_ADD_TC(tp, sigignore); + ATF_TP_ADD_TC(tp, sigpanic); + + return atf_no_error(); +} diff --git a/tests/rump/rumpkern/t_sp.sh b/tests/rump/rumpkern/t_sp.sh new file mode 100644 index 000000000..d0e857f92 --- /dev/null +++ b/tests/rump/rumpkern/t_sp.sh @@ -0,0 +1,118 @@ +# $NetBSD: t_sp.sh,v 1.11 2011/02/24 08:40:06 pooka Exp $ +# +# Copyright (c) 2010 The NetBSD Foundation, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +test_case() +{ + local name="${1}"; shift + local check_function="${1}"; shift + + atf_test_case "${name}" cleanup + eval "${name}_head() { }" + eval "${name}_body() { \ + ${check_function} " "${@}" "; \ + }" + eval "${name}_cleanup() { \ + RUMP_SERVER=unix://commsock rump.halt + }" +} + +test_case basic basic +test_case stress_short stress 1 +test_case stress_long stress 2 +test_case stress_killer stress 5 kill +test_case fork_simple fork simple +test_case fork_pipecomm fork pipecomm +test_case fork_fakeauth fork fakeauth +test_case sigsafe sigsafe sigsafe +test_case signal signal +test_case reconnect reconnect + +basic() +{ + export RUMP_SERVER=unix://commsock + atf_check -s exit:0 rump_server ${RUMP_SERVER} + atf_check -s exit:0 $(atf_get_srcdir)/h_client/h_simplecli +} + +stress() +{ + + export RUMP_SERVER=unix://commsock + atf_check -s exit:0 rump_server \ + -lrumpvfs -lrumpnet -lrumpnet_net -lrumpnet_netinet ${RUMP_SERVER} + atf_check -s exit:0 -e ignore $(atf_get_srcdir)/h_client/h_stresscli $@ +} + +fork() +{ + + export RUMP_SERVER=unix://commsock + atf_check -s exit:0 rump_server -lrumpvfs ${RUMP_SERVER} + atf_check -s exit:0 $(atf_get_srcdir)/h_client/h_forkcli ${1} +} + +sigsafe() +{ + + export RUMP_SERVER=unix://commsock + atf_check -s exit:0 rump_server ${RUMP_SERVER} + atf_check -s exit:0 $(atf_get_srcdir)/h_client/h_sigcli + +} + +signal() +{ + + export RUMP_SERVER=unix://commsock + atf_check -s exit:0 $(atf_get_srcdir)/h_server/h_simpleserver \ + ${RUMP_SERVER} sendsig 27 + atf_check -s signal:27 $(atf_get_srcdir)/h_client/h_simplecli block +} + +reconnect() +{ + + + export RUMP_SERVER=unix://commsock + atf_check -s exit:0 rump_server ${RUMP_SERVER} + atf_check -s exit:0 -e ignore $(atf_get_srcdir)/h_client/h_reconcli 2 +} + +atf_init_test_cases() +{ + + atf_add_test_case basic + atf_add_test_case stress_short + atf_add_test_case stress_long + atf_add_test_case stress_killer + atf_add_test_case fork_simple + atf_add_test_case fork_pipecomm + atf_add_test_case fork_fakeauth + atf_add_test_case sigsafe + atf_add_test_case signal + atf_add_test_case reconnect +} diff --git a/tests/rump/rumpkern/t_threads.c b/tests/rump/rumpkern/t_threads.c new file mode 100644 index 000000000..24155ec7c --- /dev/null +++ b/tests/rump/rumpkern/t_threads.c @@ -0,0 +1,81 @@ +/* $NetBSD: t_threads.c,v 1.1 2010/05/31 23:36:12 pooka Exp $ */ + +/*- + * Copyright (c) 2010 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +#include + +#include + +#include "../../h_macros.h" +#include "../kernspace/kernspace.h" + +ATF_TC(threadjoin); +ATF_TC_HEAD(threadjoin, tc) +{ + + atf_tc_set_md_var(tc, "descr", "Checks joinable threads work"); +} + +ATF_TC_BODY(threadjoin, tc) +{ + + rump_init(); + + rump_schedule(); + rumptest_threadjoin(); /* panics if fails */ + rump_unschedule(); +} + +ATF_TC(kthread); +ATF_TC_HEAD(kthread, tc) +{ + + atf_tc_set_md_var(tc, "descr", "Checks kthread_create/exit works"); +} + +ATF_TC_BODY(kthread, tc) +{ + + rump_init(); + + rump_schedule(); + rumptest_threadjoin(); /* panics if fails */ + rump_unschedule(); +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, threadjoin); + ATF_TP_ADD_TC(tp, kthread); + + return atf_no_error(); +} diff --git a/tests/rump/rumpkern/t_tsleep.c b/tests/rump/rumpkern/t_tsleep.c new file mode 100644 index 000000000..efd9f4c4b --- /dev/null +++ b/tests/rump/rumpkern/t_tsleep.c @@ -0,0 +1,63 @@ +/* $NetBSD: t_tsleep.c,v 1.1 2010/05/31 23:36:12 pooka Exp $ */ + +/*- + * Copyright (c) 2010 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +#include + +#include + +#include "../../h_macros.h" +#include "../kernspace/kernspace.h" + +ATF_TC(tsleep); +ATF_TC_HEAD(tsleep, tc) +{ + + atf_tc_set_md_var(tc, "descr", "Check tsleep variants"); +} + +ATF_TC_BODY(tsleep, tc) +{ + + rump_init(); + + rump_schedule(); + rumptest_tsleep(); /* panics if fails */ + rump_unschedule(); +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, tsleep); + + return atf_no_error(); +} diff --git a/tests/rump/rumpkern/t_vm.c b/tests/rump/rumpkern/t_vm.c new file mode 100644 index 000000000..4445983dc --- /dev/null +++ b/tests/rump/rumpkern/t_vm.c @@ -0,0 +1,91 @@ +/* $NetBSD: t_vm.c,v 1.3 2012/03/17 18:00:28 hannken Exp $ */ + +/*- + * Copyright (c) 2010 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +#include + +#include +#include +#include + +#include "../../h_macros.h" +#include "../kernspace/kernspace.h" + +ATF_TC(busypage); +ATF_TC_HEAD(busypage, tc) +{ + + atf_tc_set_md_var(tc, "descr", "Checks VM pagewaits work"); +} + +ATF_TC_BODY(busypage, tc) +{ + + rump_init(); + + rump_schedule(); + rumptest_busypage(); + rump_unschedule(); +} + +ATF_TC(uvmwait); +ATF_TC_HEAD(uvmwait, tc) +{ + + atf_tc_set_md_var(tc, "descr", "Tests that uvm_wait works"); + atf_tc_set_md_var(tc, "timeout", "30"); +} + +#define UVMWAIT_LIMIT 1024*1024 +ATF_TC_BODY(uvmwait, tc) +{ + char buf[64]; + + /* limit rump kernel memory */ + snprintf(buf, sizeof(buf), "%d", UVMWAIT_LIMIT); + setenv("RUMP_MEMLIMIT", buf, 1); + + rump_init(); + + rump_schedule(); + rumptest_alloc(UVMWAIT_LIMIT); + rump_unschedule(); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, busypage); + ATF_TP_ADD_TC(tp, uvmwait); + + return atf_no_error(); +} diff --git a/tests/rump/rumpnet/Makefile b/tests/rump/rumpnet/Makefile new file mode 100644 index 000000000..d3379c688 --- /dev/null +++ b/tests/rump/rumpnet/Makefile @@ -0,0 +1,9 @@ +# $NetBSD: Makefile,v 1.1 2011/03/10 14:09:46 pooka Exp $ + +.include + +TESTSDIR= ${TESTSBASE}/rump/rumpnet + +TESTS_SH= t_shmif + +.include diff --git a/tests/rump/rumpnet/t_shmif.sh b/tests/rump/rumpnet/t_shmif.sh new file mode 100644 index 000000000..47506d9f5 --- /dev/null +++ b/tests/rump/rumpnet/t_shmif.sh @@ -0,0 +1,78 @@ +# $NetBSD: t_shmif.sh,v 1.1 2011/03/10 14:09:46 pooka Exp $ +# +# Copyright (c) 2011 The NetBSD Foundation, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +atf_test_case crossping cleanup + +crossping_head() +{ + atf_set "descr" "start 16 rump kernels on one shmif bus and crossping" +} + +startserver() +{ + + export RUMP_SERVER=unix://sock${1} + atf_check -s exit:0 rump_server -lrumpnet -lrumpnet_net \ + -lrumpnet_netinet -lrumpnet_shmif ${RUMP_SERVER} + atf_check -s exit:0 rump.ifconfig shmif0 create + atf_check -s exit:0 rump.ifconfig shmif0 linkstr shmbus + atf_check -s exit:0 rump.ifconfig shmif0 inet 1.1.1.${1} +} + +pingothers() +{ + +} + +crossping_body() +{ + + for x in `jot 16` ; do startserver $x ; done + for x in `jot 16` + do + export RUMP_SERVER=unix://sock${x} + for y in `jot 16` + do + [ ${y} -eq ${x} ] && continue + atf_check -s exit:0 -o ignore -e ignore \ + rump.ping -c 1 1.1.1.${y} + done + done +} + +crossping_cleanup() +{ + + for x in `jot 16` ; do RUMP_SERVER=unix://sock${x} rump.halt ; done + : +} + +atf_init_test_cases() +{ + + atf_add_test_case crossping +} diff --git a/tests/rump/rumpvfs/Makefile b/tests/rump/rumpvfs/Makefile new file mode 100644 index 000000000..e2dc43749 --- /dev/null +++ b/tests/rump/rumpvfs/Makefile @@ -0,0 +1,15 @@ +# $NetBSD: Makefile,v 1.3 2011/02/22 10:36:14 pooka Exp $ + +.include + +TESTSDIR= ${TESTSBASE}/rump/rumpvfs + +TESTS_C= t_basic +TESTS_C+= t_etfs +TESTS_C+= t_p2kifs + +LDADD= -lrumpvfs -lrump -lrumpuser -lpthread + +WARNS= 4 + +.include diff --git a/tests/rump/rumpvfs/t_basic.c b/tests/rump/rumpvfs/t_basic.c new file mode 100644 index 000000000..c136558b5 --- /dev/null +++ b/tests/rump/rumpvfs/t_basic.c @@ -0,0 +1,81 @@ +/* $NetBSD: t_basic.c,v 1.2 2011/02/22 13:25:18 pooka Exp $ */ + +/*- + * Copyright (c) 2011 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include "../../h_macros.h" + +ATF_TC(lseekrv); +ATF_TC_HEAD(lseekrv, tc) +{ + + atf_tc_set_md_var(tc, "descr", "Test lseek return values"); +} + +#define TESTFILE "testi" + +#define FIVE_MEGS (5*1024*1024) +#define FIVE_GIGS (5*1024*1024*1024LL) + +ATF_TC_BODY(lseekrv, tc) +{ + off_t rv; + int fd; + + RZ(rump_init()); + RL(fd = rump_sys_open(TESTFILE, O_RDWR | O_CREAT, 0777)); + + rv = rump_sys_lseek(37, FIVE_MEGS, SEEK_SET); + ATF_REQUIRE_ERRNO(EBADF, rv == -1); + + rv = rump_sys_lseek(fd, FIVE_MEGS, SEEK_SET); + ATF_REQUIRE_EQ(rv, FIVE_MEGS); + + rv = rump_sys_lseek(fd, FIVE_GIGS, SEEK_SET); + ATF_REQUIRE_EQ(rv, FIVE_GIGS); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, lseekrv); + + return atf_no_error(); +} diff --git a/tests/rump/rumpvfs/t_etfs.c b/tests/rump/rumpvfs/t_etfs.c new file mode 100644 index 000000000..844523239 --- /dev/null +++ b/tests/rump/rumpvfs/t_etfs.c @@ -0,0 +1,300 @@ +/* $NetBSD: t_etfs.c,v 1.9 2010/11/30 18:19:47 pooka Exp $ */ + +/*- + * Copyright (c) 2010 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include "../../h_macros.h" + +ATF_TC(reregister_reg); +ATF_TC_HEAD(reregister_reg, tc) +{ + + atf_tc_set_md_var(tc, "descr", "Tests register/unregister/register " + "for a regular file"); +} + +#define TESTSTR1 "hi, it's me again!" +#define TESTSTR1SZ (sizeof(TESTSTR1)-1) + +#define TESTSTR2 "what about the old vulcan proverb?" +#define TESTSTR2SZ (sizeof(TESTSTR2)-1) + +#define TESTPATH1 "/trip/to/the/moon" +#define TESTPATH2 "/but/not/the/dark/size" +ATF_TC_BODY(reregister_reg, tc) +{ + char buf[1024]; + int localfd, etcfd; + ssize_t n; + int tfd; + + etcfd = open("/etc/passwd", O_RDONLY); + ATF_REQUIRE(etcfd != -1); + + localfd = open("./testfile", O_RDWR | O_CREAT, 0666); + ATF_REQUIRE(localfd != -1); + + ATF_REQUIRE_EQ(write(localfd, TESTSTR1, TESTSTR1SZ), TESTSTR1SZ); + /* testfile now contains test string */ + + rump_init(); + + ATF_REQUIRE_EQ(rump_pub_etfs_register(TESTPATH1, "/etc/passwd", + RUMP_ETFS_REG), 0); + tfd = rump_sys_open(TESTPATH1, O_RDONLY); + ATF_REQUIRE(tfd != -1); + ATF_REQUIRE(rump_sys_read(tfd, buf, sizeof(buf)) > 0); + rump_sys_close(tfd); + rump_pub_etfs_remove(TESTPATH1); + + ATF_REQUIRE_EQ(rump_pub_etfs_register(TESTPATH2, "./testfile", + RUMP_ETFS_REG), 0); + tfd = rump_sys_open(TESTPATH2, O_RDWR); + ATF_REQUIRE(tfd != -1); + memset(buf, 0, sizeof(buf)); + ATF_REQUIRE((n = rump_sys_read(tfd, buf, sizeof(buf))) > 0); + + /* check that we have what we expected */ + ATF_REQUIRE_STREQ(buf, TESTSTR1); + + /* ... while here, check that writing works too */ + ATF_REQUIRE_EQ(rump_sys_lseek(tfd, 0, SEEK_SET), 0); + ATF_REQUIRE(TESTSTR1SZ <= TESTSTR2SZ); + ATF_REQUIRE_EQ(rump_sys_write(tfd, TESTSTR2, TESTSTR2SZ), TESTSTR2SZ); + + memset(buf, 0, sizeof(buf)); + ATF_REQUIRE_EQ(lseek(localfd, 0, SEEK_SET), 0); + ATF_REQUIRE(read(localfd, buf, sizeof(buf)) > 0); + ATF_REQUIRE_STREQ(buf, TESTSTR2); +} + +ATF_TC(reregister_blk); +ATF_TC_HEAD(reregister_blk, tc) +{ + + atf_tc_set_md_var(tc, "descr", "Tests register/unregister/register " + "for a block device"); +} + +ATF_TC_BODY(reregister_blk, tc) +{ + char buf[512 * 128]; + char cmpbuf[512 * 128]; + int rv, tfd; + + /* first, create some image files */ + rv = system("dd if=/dev/zero bs=512 count=64 " + "| tr '\\0' '\\1' > disk1.img"); + ATF_REQUIRE_EQ(rv, 0); + + rv = system("dd if=/dev/zero bs=512 count=128 " + "| tr '\\0' '\\2' > disk2.img"); + ATF_REQUIRE_EQ(rv, 0); + + rump_init(); + + ATF_REQUIRE_EQ(rump_pub_etfs_register(TESTPATH1, "./disk1.img", + RUMP_ETFS_BLK), 0); + tfd = rump_sys_open(TESTPATH1, O_RDONLY); + ATF_REQUIRE(tfd != -1); + ATF_REQUIRE_EQ(rump_sys_read(tfd, buf, sizeof(buf)), 64*512); + memset(cmpbuf, 1, sizeof(cmpbuf)); + ATF_REQUIRE_EQ(memcmp(buf, cmpbuf, 64*512), 0); + ATF_REQUIRE_EQ(rump_sys_close(tfd), 0); + ATF_REQUIRE_EQ(rump_pub_etfs_remove(TESTPATH1), 0); + + ATF_REQUIRE_EQ(rump_pub_etfs_register(TESTPATH2, "./disk2.img", + RUMP_ETFS_BLK), 0); + tfd = rump_sys_open(TESTPATH2, O_RDONLY); + ATF_REQUIRE(tfd != -1); + ATF_REQUIRE_EQ(rump_sys_read(tfd, buf, sizeof(buf)), 128*512); + memset(cmpbuf, 2, sizeof(cmpbuf)); + ATF_REQUIRE_EQ(memcmp(buf, cmpbuf, 128*512), 0); + ATF_REQUIRE_EQ(rump_sys_close(tfd), 0); + ATF_REQUIRE_EQ(rump_pub_etfs_remove(TESTPATH2), 0); +} + +ATF_TC_WITH_CLEANUP(large_blk); +ATF_TC_HEAD(large_blk, tc) +{ + + atf_tc_set_md_var(tc, "descr", "Check etfs block devices work for " + ">2TB images"); +} + +#define IMG_ON_MFS "mfsdir/disk.img" +ATF_TC_BODY(large_blk, tc) +{ + char buf[128]; + char cmpbuf[128]; + ssize_t n; + int rv, tfd; + + /* + * mount mfs. it would be nice if this would not be required, + * but a) tmpfs doesn't "support" sparse files b) we don't really + * know what fs atf workdir is on anyway. + */ + if (mkdir("mfsdir", 0777) == -1) + atf_tc_fail_errno("mkdir failed"); + if (system("mount_mfs -s 64m -o nosuid,nodev mfs mfsdir") != 0) + atf_tc_skip("could not mount mfs"); + + /* create a 8TB sparse file */ + rv = system("dd if=/dev/zero of=" IMG_ON_MFS " bs=1 count=1 seek=8t"); + ATF_REQUIRE_EQ(rv, 0); + + /* + * map it and issue write at 6TB, then unmap+remap and check + * we get the same stuff back + */ + + rump_init(); + ATF_REQUIRE_EQ(rump_pub_etfs_register(TESTPATH1, IMG_ON_MFS, + RUMP_ETFS_BLK), 0); + tfd = rump_sys_open(TESTPATH1, O_RDWR); + ATF_REQUIRE(tfd != -1); + memset(buf, 12, sizeof(buf)); + n = rump_sys_pwrite(tfd, buf, sizeof(buf), 6*1024*1024*1024ULL*1024ULL); + ATF_REQUIRE_EQ(n, sizeof(buf)); + ATF_REQUIRE_EQ(rump_sys_close(tfd), 0); + ATF_REQUIRE_EQ(rump_pub_etfs_remove(TESTPATH1), 0); + + ATF_REQUIRE_EQ(rump_pub_etfs_register(TESTPATH2, IMG_ON_MFS, + RUMP_ETFS_BLK), 0); + tfd = rump_sys_open(TESTPATH2, O_RDWR); + ATF_REQUIRE(tfd != -1); + memset(buf, 0, sizeof(buf)); + n = rump_sys_pread(tfd, buf, sizeof(buf), 6*1024*1024*1024ULL*1024ULL); + ATF_REQUIRE_EQ(n, sizeof(buf)); + + memset(cmpbuf, 12, sizeof(cmpbuf)); + ATF_REQUIRE_EQ(memcmp(cmpbuf, buf, 128), 0); +} + +ATF_TC_CLEANUP(large_blk, tc) +{ + + system("umount mfsdir"); +} + +ATF_TC(range_blk); +ATF_TC_HEAD(range_blk, tc) +{ + + atf_tc_set_md_var(tc, "descr", "Checks ranged (offset,size) mappings"); +} + +ATF_TC_BODY(range_blk, tc) +{ + char buf[32000]; + char cmpbuf[32000]; + ssize_t n; + int rv, tfd; + + /* create a 64000 byte file with 16 1's at offset = 32000 */ + rv = system("dd if=/dev/zero of=disk.img bs=1000 count=64"); + ATF_REQUIRE_EQ(rv, 0); + rv = system("yes | tr '\\ny' '\\1' " + "| dd of=disk.img conv=notrunc bs=1 count=16 seek=32000"); + ATF_REQUIRE_EQ(rv, 0); + + /* map the file at [16000,48000]. this puts our 1's at offset 16000 */ + rump_init(); + ATF_REQUIRE_EQ(rump_pub_etfs_register_withsize(TESTPATH1, "disk.img", + RUMP_ETFS_BLK, 16000, 32000), 0); + tfd = rump_sys_open(TESTPATH1, O_RDWR); + ATF_REQUIRE(tfd != -1); + n = rump_sys_read(tfd, buf, sizeof(buf)); + ATF_REQUIRE_EQ(n, sizeof(buf)); + ATF_REQUIRE_EQ(rump_sys_close(tfd), 0); + ATF_REQUIRE_EQ(rump_pub_etfs_remove(TESTPATH1), 0); + + /* check that we got what is expected */ + memset(cmpbuf, 0, sizeof(cmpbuf)); + memset(cmpbuf+16000, 1, 16); + ATF_REQUIRE_EQ(memcmp(buf, cmpbuf, sizeof(buf)), 0); +} + +ATF_TC(key); +ATF_TC_HEAD(key, tc) +{ + + atf_tc_set_md_var(tc, "descr", "Checks key format"); +} + +ATF_TC_BODY(key, tc) +{ + + RZ(rump_init()); + + RL(open("hostfile", O_RDWR | O_CREAT, 0777)); + + RZ(rump_pub_etfs_register("/key", "hostfile", RUMP_ETFS_REG)); + ATF_REQUIRE_EQ(rump_pub_etfs_register("key", "hostfile", RUMP_ETFS_REG), + EINVAL); + + RL(rump_sys_open("/key", O_RDONLY)); + RL(rump_sys_open("////////key", O_RDONLY)); + + RZ(rump_pub_etfs_register("////key//with/slashes", "hostfile", + RUMP_ETFS_REG)); + + RL(rump_sys_open("/key//with/slashes", O_RDONLY)); + RL(rump_sys_open("key//with/slashes", O_RDONLY)); + ATF_REQUIRE_ERRNO(ENOENT, + rump_sys_open("/key/with/slashes", O_RDONLY) == -1); + + RL(rump_sys_mkdir("/a", 0777)); + ATF_REQUIRE_ERRNO(ENOENT, + rump_sys_open("/a/key//with/slashes", O_RDONLY) == -1); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, reregister_reg); + ATF_TP_ADD_TC(tp, reregister_blk); + ATF_TP_ADD_TC(tp, large_blk); + ATF_TP_ADD_TC(tp, range_blk); + ATF_TP_ADD_TC(tp, key); + + return atf_no_error(); +} diff --git a/tests/rump/rumpvfs/t_p2kifs.c b/tests/rump/rumpvfs/t_p2kifs.c new file mode 100644 index 000000000..33baedbae --- /dev/null +++ b/tests/rump/rumpvfs/t_p2kifs.c @@ -0,0 +1,94 @@ +/* $NetBSD: t_p2kifs.c,v 1.3 2011/01/02 12:58:17 pooka Exp $ */ + +/*- + * Copyright (c) 2010 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include "../../h_macros.h" + +ATF_TC(makecn); +ATF_TC_HEAD(makecn, tc) +{ + + atf_tc_set_md_var(tc, "descr", "Tests makecn/LOOKUP/freecn"); +} + +#define TESTFILE "testi" + +ATF_TC_BODY(makecn, tc) +{ + struct componentname *cn; + char pathstr[MAXPATHLEN] = TESTFILE; + struct vnode *vp; + extern struct vnode *rumpns_rootvnode; + + rump_init(); + + /* + * Strategy is to create a componentname, edit the passed + * string, and then do a lookup with the componentname. + */ + RL(rump_sys_mkdir("/" TESTFILE, 0777)); + + /* need stable lwp for componentname */ + RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG)); + + /* try it once with the right path */ + cn = rump_pub_makecn(RUMP_NAMEI_LOOKUP, 0, pathstr, strlen(pathstr), + rump_pub_cred_create(0, 0, 0, NULL), rump_pub_lwproc_curlwp()); + RZ(RUMP_VOP_LOOKUP(rumpns_rootvnode, &vp, cn)); + RUMP_VOP_UNLOCK(vp); + rump_pub_freecn(cn, RUMPCN_FREECRED); + + /* and then with modification-in-the-middle */ + cn = rump_pub_makecn(RUMP_NAMEI_LOOKUP, 0, pathstr, strlen(pathstr), + rump_pub_cred_create(0, 0, 0, NULL), rump_pub_lwproc_curlwp()); + strcpy(pathstr, "/muuta"); + RZ(RUMP_VOP_LOOKUP(rumpns_rootvnode, &vp, cn)); + RUMP_VOP_UNLOCK(vp); + rump_pub_freecn(cn, RUMPCN_FREECRED); +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, makecn); + + return atf_no_error(); +} diff --git a/tests/sbin/Makefile b/tests/sbin/Makefile new file mode 100644 index 000000000..d6590537a --- /dev/null +++ b/tests/sbin/Makefile @@ -0,0 +1,10 @@ +# $NetBSD: Makefile,v 1.6 2012/07/28 16:08:40 njoly Exp $ +# + +.include + +TESTSDIR= ${TESTSBASE}/sbin + +TESTS_SUBDIRS+= fsck_ffs ifconfig newfs newfs_msdos resize_ffs route sysctl + +.include diff --git a/tests/sbin/Makefile.inc b/tests/sbin/Makefile.inc new file mode 100644 index 000000000..01b5f2341 --- /dev/null +++ b/tests/sbin/Makefile.inc @@ -0,0 +1 @@ +.include "../Makefile.inc" diff --git a/tests/sbin/fsck_ffs/Makefile b/tests/sbin/fsck_ffs/Makefile new file mode 100644 index 000000000..0f2799119 --- /dev/null +++ b/tests/sbin/fsck_ffs/Makefile @@ -0,0 +1,12 @@ +# $NetBSD: Makefile,v 1.2 2011/03/06 17:08:41 bouyer Exp $ + +.include + +TESTSDIR= ${TESTSBASE}/sbin/fsck_ffs + +.for name in t_enable_quotas t_check_quotas +TESTS_SH+= ${name} +TESTS_SH_SRC_${name}= quotas_common.sh ${name}.sh +.endfor + +.include diff --git a/tests/sbin/fsck_ffs/quotas_common.sh b/tests/sbin/fsck_ffs/quotas_common.sh new file mode 100644 index 000000000..7d4ab58b9 --- /dev/null +++ b/tests/sbin/fsck_ffs/quotas_common.sh @@ -0,0 +1,44 @@ +# $NetBSD: quotas_common.sh,v 1.2 2011/03/06 17:08:41 bouyer Exp $ + +create_with_quotas() +{ + local endian=$1; shift + local vers=$1; shift + local uid=$(id -u) + local gid=$(id -g) + + atf_check -o ignore -e ignore newfs -B ${endian} -O ${vers} \ + -s 4000 -F ${IMG} + atf_check -o ignore -e ignore tunefs -q user -q group -F ${IMG} + atf_check -s exit:0 -o 'match:NO USER QUOTA INODE \(CREATED\)' \ + -o 'match:USER QUOTA MISMATCH FOR ID '${uid}': 0/0 SHOULD BE 1/1' \ + -o 'match:GROUP QUOTA MISMATCH FOR ID '${gid}': 0/0 SHOULD BE 1/1' \ + fsck_ffs -p -F ${IMG} +} + +# from tests/ipf/h_common.sh via tests/sbin/resize_ffs +test_case() +{ + local name="${1}"; shift + local check_function="${1}"; shift + local descr="${1}"; shift + + atf_test_case "${name}" + + eval "${name}_head() { \ + atf_set "descr" "Checks ${descr} quotas inodes" + }" + eval "${name}_body() { \ + ${check_function} " "${@}" "; \ + }" + tests="${tests} ${name}" +} + +atf_init_test_cases() +{ + IMG=fsimage + DIR=target + for i in ${tests}; do + atf_add_test_case $i + done +} diff --git a/tests/sbin/fsck_ffs/t_check_quotas.sh b/tests/sbin/fsck_ffs/t_check_quotas.sh new file mode 100644 index 000000000..804c5b54d --- /dev/null +++ b/tests/sbin/fsck_ffs/t_check_quotas.sh @@ -0,0 +1,73 @@ +# $NetBSD: t_check_quotas.sh,v 1.2 2011/03/06 17:08:41 bouyer Exp $ +# +# Copyright (c) 2011 Manuel Bouyer +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +for e in le be; do + for v in 1 2; do + test_case corrupt_list_${e}_${v} corrupt_list \ + "recovery of corrupted free list in" ${e} ${v} + test_case expand1_list_${e}_${v} expand_list \ + "allocation of direct block in" 40 ${e} ${v} + test_case expand2_list_${e}_${v} expand_list \ + "allocation of indirect block in" 1000 ${e} ${v} + done +done + +corrupt_list() +{ + create_with_quotas $* + local blkno=$(printf "inode 3\nblks\n" | /sbin/fsdb -nF -f ${IMG} | awk '$1 == "0:" {print $2}') + blkno=$(($blkno * 512 + 104)) + #clear the free list + atf_check -o ignore -e ignore dd if=/dev/zero of=${IMG} bs=1 \ + count=8 seek=${blkno} conv=notrunc + atf_check -s exit:0 \ + -o "match:QUOTA ENTRY NOT IN LIST \(FIXED\)" \ + fsck_ffs -fp -F ${IMG} + atf_check -s exit:0 -o "match:3 files" fsck_ffs -nf -F ${IMG} +} + +expand_list() +{ + local nuid=$1; shift + local expected_files=$((nuid + 2)) + echo "/set uid=0 gid=0" > spec + echo ". type=dir mode=0755" >> spec + mkdir ${DIR} + for i in $(seq ${nuid}); do + touch ${DIR}/f${i} + echo "./f$i type=file mode=0600 uid=$i gid=$i" >> spec + done + + atf_check -o ignore -e ignore makefs -B $1 -o version=$2 \ + -F spec -s 4000b ${IMG} ${DIR} + atf_check -o ignore -e ignore tunefs -q user -F ${IMG} + atf_check -s exit:0 -o 'match:NO USER QUOTA INODE \(CREATED\)' \ + -o 'match:USER QUOTA MISMATCH FOR ID 10: 0/0 SHOULD BE 0/1' \ + fsck_ffs -p -F ${IMG} + atf_check -s exit:0 -o "match:${expected_files} files" \ + fsck_ffs -nf -F ${IMG} +} diff --git a/tests/sbin/fsck_ffs/t_enable_quotas.sh b/tests/sbin/fsck_ffs/t_enable_quotas.sh new file mode 100644 index 000000000..314891185 --- /dev/null +++ b/tests/sbin/fsck_ffs/t_enable_quotas.sh @@ -0,0 +1,105 @@ +# $NetBSD: t_enable_quotas.sh,v 1.2 2011/03/06 17:08:41 bouyer Exp $ +# +# Copyright (c) 2011 Manuel Bouyer +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +for e in le be; do + for v in 1 2; do + test_case disable_${e}_${v} disable_quotas "creation/removal of" ${e} ${v} + test_case corrupt_${e}_${v} corrupt_quotas "repair of corrupted" ${e} ${v} + test_case unallocated_${e}_${v} unallocated_quotas \ + "recovery of unallocated" ${e} ${v} + test_case dir1_${e}_${v} dir1_quotas \ + "successfull clear of wrong type of" ${e} ${v} + test_case notreg_${e}_${v} notreg_quotas \ + "successfull clear of wrong type of" ${e} ${v} + done +done + +disable_quotas() +{ + create_with_quotas $* + +# check that the quota inode creation didn't corrupt the filesystem + atf_check -s exit:0 -o "match:already clean" -o "match:3 files" \ + fsck_ffs -nf -F ${IMG} +#now check fsck can properly clear the quota inode when quota flags are +# cleared + atf_check -o ignore -e ignore tunefs -q nouser -q nogroup -F ${IMG} + atf_check -s exit:0 -o "match:SUPERBLOCK QUOTA FLAG CLEARED" \ + fsck_ffs -fp -F ${IMG} + atf_check -s exit:0 -o "match:1 files, 1 used" fsck_ffs -nf -F ${IMG} +} + +corrupt_quotas() +{ + create_with_quotas $* + + local blkno=$(printf "inode 3\nblks\n" | /sbin/fsdb -nF -f ${IMG} | awk '$1 == "0:" {print $2}') + atf_check -o ignore -e ignore dd if=/dev/zero of=${IMG} bs=512 \ + count=1 seek=${blkno} conv=notrunc + atf_check -s exit:0 \ + -o "match:CORRUPTED USER QUOTA INODE 3 \(CLEARED\)" \ + -o "match:NO USER QUOTA INODE \(CREATED\)" \ + fsck_ffs -fp -F ${IMG} + atf_check -s exit:0 -o "match:3 files" fsck_ffs -nf -F ${IMG} +} + +unallocated_quotas() +{ + create_with_quotas $* + + atf_check -o ignore -e ignore clri ${IMG} 3 + atf_check -s exit:0 \ + -o "match:UNALLOCATED USER QUOTA INODE 3 \(CLEARED\)" \ + -o "match:NO USER QUOTA INODE \(CREATED\)" \ + fsck_ffs -fp -F ${IMG} + atf_check -s exit:0 -o "match:3 files" fsck_ffs -nf -F ${IMG} +} + +dir1_quotas() +{ + create_with_quotas $* + + atf_check -s exit:255 -o ignore -e ignore -x \ + "printf 'inode 3\nchtype dir\nexit\n' | fsdb -F -f ${IMG}" + atf_check -s exit:0 \ + -o "match:DIR I=3 CONNECTED. PARENT WAS I=0" \ + -o "match:USER QUOTA INODE 3 IS A DIRECTORY" \ + fsck_ffs -y -F ${IMG} +} + +notreg_quotas() +{ + create_with_quotas $* + + atf_check -s exit:255 -o ignore -e ignore -x \ + "printf 'inode 3\nchtype fifo\nexit\n' | fsdb -F -f ${IMG}" + atf_check -s exit:0 \ + -o "match:WRONG TYPE 4096 for USER QUOTA INODE 3 \(CLEARED\)" \ + -o "match:NO USER QUOTA INODE \(CREATED\)" \ + fsck_ffs -p -F ${IMG} + atf_check -s exit:0 -o "match:3 files" fsck_ffs -nf -F ${IMG} +} diff --git a/tests/sbin/ifconfig/Makefile b/tests/sbin/ifconfig/Makefile new file mode 100644 index 000000000..0a466deea --- /dev/null +++ b/tests/sbin/ifconfig/Makefile @@ -0,0 +1,9 @@ +# $NetBSD: Makefile,v 1.1 2011/05/03 06:13:06 jruoho Exp $ + +.include + +TESTSDIR= ${TESTSBASE}/sbin/ifconfig + +TESTS_SH= t_nonexistent + +.include diff --git a/tests/sbin/ifconfig/t_nonexistent.sh b/tests/sbin/ifconfig/t_nonexistent.sh new file mode 100644 index 000000000..8670323e0 --- /dev/null +++ b/tests/sbin/ifconfig/t_nonexistent.sh @@ -0,0 +1,45 @@ +# $NetBSD: t_nonexistent.sh,v 1.4 2012/03/18 09:46:50 jruoho Exp $ +# +# Copyright (c) 2011 The NetBSD Foundation, Inc. +# All rights reserved. +# +# This code is derived from software contributed to The NetBSD Foundation +# by Jukka Ruohonen. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +atf_test_case nonexistent +nonexistent_head() { + atf_set "descr" "Check ifconfig(8) with " \ + "a nonexistent interface (PR bin/43141)" +} + +nonexistent_body() { + + atf_check -s not-exit:0 -e ignore \ + ifconfig nonexistent0 1.2.3.4/24 +} + +atf_init_test_cases() { + atf_add_test_case nonexistent +} diff --git a/tests/sbin/newfs/Makefile b/tests/sbin/newfs/Makefile new file mode 100644 index 000000000..84e0f091e --- /dev/null +++ b/tests/sbin/newfs/Makefile @@ -0,0 +1,12 @@ +# $NetBSD: Makefile,v 1.2 2011/03/06 17:08:41 bouyer Exp $ + +.include + +TESTSDIR= ${TESTSBASE}/sbin/newfs + +.for name in t_enable_quotas +TESTS_SH+= ${name} +TESTS_SH_SRC_${name}= quotas_common.sh ${name}.sh +.endfor + +.include diff --git a/tests/sbin/newfs/quotas_common.sh b/tests/sbin/newfs/quotas_common.sh new file mode 100644 index 000000000..3ea89a22b --- /dev/null +++ b/tests/sbin/newfs/quotas_common.sh @@ -0,0 +1,68 @@ +# $NetBSD: quotas_common.sh,v 1.3 2012/03/18 09:31:50 jruoho Exp $ + +# Copyright (c) 2011 Manuel Bouyer +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +create_with_quotas() +{ + local endian=$1; shift + local vers=$1; shift + local type=$1; shift + local op; + if [ ${type} = "both" ]; then + op="-q user -q group" + else + op="-q ${type}" + fi + atf_check -o ignore -e ignore newfs ${op} \ + -B ${endian} -O ${vers} -s 4000 -F ${IMG} +} + +# from tests/ipf/h_common.sh via tests/sbin/resize_ffs +test_case() +{ + local name="${1}"; shift + local check_function="${1}"; shift + local descr="${1}"; shift + + atf_test_case "${name}" + + eval "${name}_head() { \ + atf_set "descr" "Checks ${descr} quotas inodes" + }" + eval "${name}_body() { \ + ${check_function} " "${@}" "; \ + }" + tests="${tests} ${name}" +} + +atf_init_test_cases() +{ + IMG=fsimage + DIR=target + for i in ${tests}; do + atf_add_test_case $i + done +} diff --git a/tests/sbin/newfs/t_enable_quotas.sh b/tests/sbin/newfs/t_enable_quotas.sh new file mode 100644 index 000000000..62218e906 --- /dev/null +++ b/tests/sbin/newfs/t_enable_quotas.sh @@ -0,0 +1,57 @@ +# $NetBSD: t_enable_quotas.sh,v 1.3 2012/03/18 09:31:50 jruoho Exp $ +# +# Copyright (c) 2011 Manuel Bouyer +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +for e in le be; do + for v in 1 2; do + for q in "user" "group"; do + test_case enabled_${e}_${v}_${q} quota_enabled_single \ + "creation of" ${e} ${v} ${q} + done + test_case enabled_${e}_${v}_"both" quota_enabled_both \ + "creation of" ${e} ${v} "both" + done +done + +quota_enabled_single() +{ + create_with_quotas $* + +# check that the quota inode creation didn't corrupt the filesystem + atf_check -s exit:0 -o "match:already clean" -o "match:2 files" \ + -o "match:Phase 6 - Check Quotas" \ + fsck_ffs -nf -F ${IMG} +} + +quota_enabled_both() +{ + create_with_quotas $* + +# check that the quota inode creation didn't corrupt the filesystem + atf_check -s exit:0 -o "match:already clean" -o "match:3 files" \ + -o "match:Phase 6 - Check Quotas" \ + fsck_ffs -nf -F ${IMG} +} diff --git a/tests/sbin/newfs_msdos/Makefile b/tests/sbin/newfs_msdos/Makefile new file mode 100644 index 000000000..3cf4a83e7 --- /dev/null +++ b/tests/sbin/newfs_msdos/Makefile @@ -0,0 +1,9 @@ +# $NetBSD: Makefile,v 1.1 2012/07/28 16:08:40 njoly Exp $ + +.include + +TESTSDIR= ${TESTSBASE}/sbin/newfs_msdos + +TESTS_SH= t_create + +.include diff --git a/tests/sbin/newfs_msdos/t_create.sh b/tests/sbin/newfs_msdos/t_create.sh new file mode 100644 index 000000000..d14fde274 --- /dev/null +++ b/tests/sbin/newfs_msdos/t_create.sh @@ -0,0 +1,44 @@ +# $NetBSD: t_create.sh,v 1.2 2012/09/06 12:51:47 njoly Exp $ +# +# Copyright (c) 2012 The NetBSD Foundation, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +atf_test_case validfat32 +validfat32_head() { + atf_set "descr" "Verifies that fat32 created filesystems are valid" +} +validfat32_body() { + + atf_check -s eq:0 -o ignore -e ignore \ + newfs_msdos -b 512 -C 33m -F 32 msdos.img + atf_expect_fail "PR bin/46743" + atf_check -s eq:0 -o not-match:FIXED -e empty fsck_msdos -p msdos.img + atf_expect_pass +} + + +atf_init_test_cases() { + atf_add_test_case validfat32 +} diff --git a/tests/sbin/resize_ffs/Makefile b/tests/sbin/resize_ffs/Makefile new file mode 100644 index 000000000..594e18519 --- /dev/null +++ b/tests/sbin/resize_ffs/Makefile @@ -0,0 +1,16 @@ +# $NetBSD: Makefile,v 1.3 2011/01/05 02:25:27 riz Exp $ + +.include + +TESTSDIR= ${TESTSBASE}/sbin/resize_ffs + +.for name in t_grow t_shrink t_grow_swapped t_shrink_swapped +TESTS_SH+= ${name} +TESTS_SH_SRC_${name}= common.sh ${name}.sh +.endfor + +FILESDIR= ${TESTSDIR} +FILES= testdata.tar.gz.base64 +FILES+= testdata.md5 + +.include diff --git a/tests/sbin/resize_ffs/common.sh b/tests/sbin/resize_ffs/common.sh new file mode 100644 index 000000000..1b1d5da93 --- /dev/null +++ b/tests/sbin/resize_ffs/common.sh @@ -0,0 +1,159 @@ + +# Common settings and functions for the various resize_ffs tests. +# + +# called from atf_init_test_cases +setupvars() +{ + IMG=fsimage + TDBASE64=$(atf_get_srcdir)/testdata.tar.gz.base64 + GOODMD5=$(atf_get_srcdir)/testdata.md5 + # set BYTESWAP to opposite-endian. + if [ $(sysctl -n hw.byteorder) = "1234" ]; then + BYTESWAP=be + else + BYTESWAP=le + fi +} + +# test_case() taken from the tests/ipf/h_common.sh +# Used to declare the atf goop for a test. +test_case() +{ + local name="${1}"; shift + local check_function="${1}"; shift + + atf_test_case "${name}" cleanup + eval "${name}_head() { \ + atf_set "require.user" "root" ; \ + atf_set "require.progs" "rump_ffs" ; \ + }" + eval "${name}_body() { \ + ${check_function} " "${@}" "; \ + }" + eval "${name}_cleanup() { \ + umount -f mnt ; \ + : reset error ; \ + }" +} + +# Used to declare the atf goop for a test expected to fail. +test_case_xfail() +{ + local name="${1}"; shift + local reason="${1}"; shift + local check_function="${1}"; shift + + atf_test_case "${name}" cleanup + eval "${name}_head() { \ + atf_set "require.user" "root" ; \ + }" + eval "${name}_body() { \ + atf_expect_fail "${reason}" ; \ + ${check_function} " "${@}" "; \ + }" + eval "${name}_cleanup() { \ + umount -f mnt ; \ + : reset error ; \ + }" +} + +# copy_data requires the mount already done; makes one copy of the test data +copy_data () +{ + uudecode -p ${TDBASE64} | (cd mnt; tar xzf - -s/testdata/TD$1/) +} + +copy_multiple () +{ + local i + for i in $(seq $1); do + copy_data $i + done +} + +# remove_data removes one directory worth of test data; the purpose +# is to ensure data exists near the end of the fs under test. +remove_data () +{ + rm -rf mnt/TD$1 +} + +remove_multiple () +{ + local i + for i in $(seq $1); do + remove_data $i + done +} + +# verify that the data in a particular directory is still OK +# generated md5 file doesn't need explicit cleanup thanks to ATF +check_data () +{ + (cd mnt/TD$1 && md5 *) > TD$1.md5 + atf_check diff -u ${GOODMD5} TD$1.md5 +} + +# supply begin and end arguments +check_data_range () +{ + local i + for i in $(seq $1 $2); do + check_data $i + done +} + + +resize_ffs() +{ + echo "in resize_ffs:" ${@} + local bs=$1 + local fragsz=$2 + local osize=$3 + local nsize=$4 + local fslevel=$5 + local numdata=$6 + local swap=$7 + mkdir -p mnt + echo "bs is ${bs} numdata is ${numdata}" + echo "****resizing fs with blocksize ${bs}" + + # we want no more than 16K/inode to allow test files to copy. + local fpi=$((fragsz * 4)) + local i + if [ $fpi -gt 16384 ]; then + i="-i 16384" + fi + if [ x$swap != x ]; then + newfs -B ${BYTESWAP} -O${fslevel} -b ${bs} -f ${fragsz} \ + -s ${osize} ${i} -F ${IMG} + else + newfs -O${fslevel} -b ${bs} -f ${fragsz} -s ${osize} ${i} \ + -F ${IMG} + fi + + # we're specifying relative paths, so rump_ffs warns - ignore. + atf_check -s exit:0 -e ignore rump_ffs ${IMG} mnt + copy_multiple ${numdata} + + if [ ${nsize} -lt ${osize} ]; then + # how much data to remove so fs can be shrunk + local remove=$((numdata-numdata*nsize/osize)) + local dataleft=$((numdata-remove)) + echo remove is $remove dataleft is $dataleft + remove_multiple ${remove} + fi + + umount mnt + atf_check -s exit:0 -o ignore resize_ffs -y -s ${nsize} ${IMG} + atf_check -s exit:0 -o ignore fsck_ffs -f -n -F ${IMG} + atf_check -s exit:0 -e ignore rump_ffs ${IMG} mnt + if [ ${nsize} -lt ${osize} ]; then + check_data_range $((remove + 1)) ${numdata} + else + # checking everything because we don't delete on grow + check_data_range 1 ${numdata} + fi + umount mnt +} diff --git a/tests/sbin/resize_ffs/t_grow.sh b/tests/sbin/resize_ffs/t_grow.sh new file mode 100644 index 000000000..31d117bbf --- /dev/null +++ b/tests/sbin/resize_ffs/t_grow.sh @@ -0,0 +1,221 @@ +# $NetBSD: t_grow.sh,v 1.8 2011/01/11 00:50:02 riz Exp $ +# +# Copyright (c) 2010 The NetBSD Foundation, Inc. +# All rights reserved. +# +# This code is derived from software contributed to The NetBSD Foundation +# by Jeffrey C. Rizzo. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + + +# resize_ffs params as follows: +# resize_ffs blocksize fragsize fssize newfssize level numdata swap +# where 'numdata' is the number of data directories to copy - this is +# determined manually based on the maximum number that will fit in the +# created fs. 'level' is the fs-level (-O 0,1,2) passed to newfs. +# If 'swap' is included, byteswap the fs + +# v0 == newfs -O0 (4.3BSD layout, ffsv1 superblock) +test_case grow_16M_v0_4096 resize_ffs 4096 512 32768 131072 0 28 +test_case grow_16M_v0_8192 resize_ffs 8192 1024 32768 131072 0 28 +test_case grow_16M_v0_16384 resize_ffs 16384 2048 32768 131072 0 29 +test_case grow_16M_v0_32768 resize_ffs 32768 4096 32768 131072 0 28 +test_case grow_16M_v0_65536 resize_ffs 65536 8192 32768 131072 0 26 +# these grow_24M grow a smaller amount; sometimes there's different issues +test_case grow_24M_v0_4096 resize_ffs 4096 512 49152 65536 0 41 +test_case grow_24M_v0_8192 resize_ffs 8192 1024 49152 65536 0 42 +test_case grow_24M_v0_16384 resize_ffs 16384 2048 49152 65536 0 43 +test_case grow_24M_v0_32768 resize_ffs 32768 4096 49152 65536 0 42 +test_case grow_24M_v0_65536 resize_ffs 65536 8192 49152 65536 0 38 +test_case grow_32M_v0_4096 resize_ffs 4096 512 65536 131072 0 55 +test_case grow_32M_v0_8192 resize_ffs 8192 1024 65536 131072 0 56 +test_case grow_32M_v0_16384 resize_ffs 16384 2048 65536 131072 0 58 +test_case grow_32M_v0_32768 resize_ffs 32768 4096 65536 131072 0 56 +test_case grow_32M_v0_65536 resize_ffs 65536 8192 65536 131072 0 51 +test_case grow_48M_v0_4096 resize_ffs 4096 512 98304 131072 0 82 +test_case grow_48M_v0_8192 resize_ffs 8192 1024 98304 131072 0 84 +test_case grow_48M_v0_16384 resize_ffs 16384 2048 98304 131072 0 87 +test_case grow_48M_v0_32768 resize_ffs 32768 4096 98304 131072 0 83 +test_case grow_48M_v0_65536 resize_ffs 65536 8192 98304 131072 0 76 +test_case grow_64M_v0_4096 resize_ffs 4096 512 131072 262144 0 109 +test_case grow_64M_v0_8192 resize_ffs 8192 1024 131072 262144 0 111 +test_case grow_64M_v0_16384 resize_ffs 16384 2048 131072 262144 0 115 +test_case grow_64M_v0_32768 resize_ffs 32768 4096 131072 262144 0 111 +test_case grow_64M_v0_65536 resize_ffs 65536 8192 131072 262144 0 101 + +# v1 == newfs -O1 (FFSv1, v2 superblock layout) +test_case grow_16M_v1_4096 resize_ffs 4096 512 32768 131072 1 28 +test_case grow_16M_v1_8192 resize_ffs 8192 1024 32768 131072 1 28 +test_case grow_16M_v1_16384 resize_ffs 16384 2048 32768 131072 1 29 +test_case grow_16M_v1_32768 resize_ffs 32768 4096 32768 131072 1 28 +test_case grow_16M_v1_65536 resize_ffs 65536 8192 32768 131072 1 26 +# these grow_24M grow a smaller amount; sometimes there's different issues +test_case grow_24M_v1_4096 resize_ffs 4096 512 49152 65536 1 41 +test_case grow_24M_v1_8192 resize_ffs 8192 1024 49152 65536 1 42 +test_case grow_24M_v1_16384 resize_ffs 16384 2048 49152 65536 1 43 +test_case grow_24M_v1_32768 resize_ffs 32768 4096 49152 65536 1 42 +test_case grow_24M_v1_65536 resize_ffs 65536 8192 49152 65536 1 38 +test_case grow_32M_v1_4096 resize_ffs 4096 512 65536 131072 1 55 +test_case grow_32M_v1_8192 resize_ffs 8192 1024 65536 131072 1 56 +test_case grow_32M_v1_16384 resize_ffs 16384 2048 65536 131072 1 58 +test_case grow_32M_v1_32768 resize_ffs 32768 4096 65536 131072 1 56 +test_case grow_32M_v1_65536 resize_ffs 65536 8192 65536 131072 1 51 +test_case grow_48M_v1_4096 resize_ffs 4096 512 98304 131072 1 82 +test_case grow_48M_v1_8192 resize_ffs 8192 1024 98304 131072 1 84 +test_case grow_48M_v1_16384 resize_ffs 16384 2048 98304 131072 1 87 +test_case grow_48M_v1_32768 resize_ffs 32768 4096 98304 131072 1 83 +test_case grow_48M_v1_65536 resize_ffs 65536 8192 98304 131072 1 76 +test_case grow_64M_v1_4096 resize_ffs 4096 512 131072 262144 1 109 +test_case grow_64M_v1_8192 resize_ffs 8192 1024 131072 262144 1 111 +test_case grow_64M_v1_16384 resize_ffs 16384 2048 131072 262144 1 115 +test_case grow_64M_v1_32768 resize_ffs 32768 4096 131072 262144 1 111 +test_case grow_64M_v1_65536 resize_ffs 65536 8192 131072 262144 1 101 +test_case grow_16M_v2_4096 resize_ffs 4096 512 32768 131072 2 26 +test_case grow_16M_v2_8192 resize_ffs 8192 1024 32768 131072 2 28 +test_case grow_16M_v2_16384 resize_ffs 16384 2048 32768 131072 2 29 +test_case grow_16M_v2_32768 resize_ffs 32768 4096 32768 131072 2 28 +test_case grow_16M_v2_65536 resize_ffs 65536 8192 32768 131072 2 25 +test_case grow_24M_v2_4096 resize_ffs 4096 512 49152 65536 2 40 +test_case grow_24M_v2_8192 resize_ffs 8192 1024 49152 65536 2 42 +test_case grow_24M_v2_16384 resize_ffs 16384 2048 49152 65536 2 43 +test_case grow_24M_v2_32768 resize_ffs 32768 4096 49152 65536 2 42 +test_case grow_24M_v2_65536 resize_ffs 65536 8192 49152 65536 2 38 +test_case grow_32M_v2_4096 resize_ffs 4096 512 65536 131072 2 53 +test_case grow_32M_v2_8192 resize_ffs 8192 1024 65536 131072 2 56 +test_case grow_32M_v2_16384 resize_ffs 16384 2048 65536 131072 2 58 +test_case grow_32M_v2_32768 resize_ffs 32768 4096 65536 131072 2 56 +test_case grow_32M_v2_65536 resize_ffs 65536 8192 65536 131072 2 51 +test_case grow_48M_v2_4096 resize_ffs 4096 512 98304 131072 2 80 +test_case grow_48M_v2_8192 resize_ffs 8192 1024 98304 131072 2 84 +test_case grow_48M_v2_16384 resize_ffs 16384 2048 98304 131072 2 87 +test_case grow_48M_v2_32768 resize_ffs 32768 4096 98304 131072 2 83 +test_case grow_48M_v2_65536 resize_ffs 65536 8192 98304 131072 2 76 +test_case grow_64M_v2_4096 resize_ffs 4096 512 131072 262144 2 107 +test_case grow_64M_v2_8192 resize_ffs 8192 1024 131072 262144 2 111 +test_case grow_64M_v2_16384 resize_ffs 16384 2048 131072 262144 2 115 +test_case grow_64M_v2_32768 resize_ffs 32768 4096 131072 262144 2 111 +test_case grow_64M_v2_65536 resize_ffs 65536 8192 131072 262144 2 101 + +atf_test_case grow_ffsv1_partial_cg +grow_ffsv1_partial_cg_head() +{ + atf_set "descr" "Checks successful ffsv1 growth by less" \ + "than a cylinder group" +} +grow_ffsv1_partial_cg_body() +{ + echo "***resize_ffs grow test" + + # resize_ffs only supports ffsv1 at the moment + atf_check -o ignore -e ignore newfs -V1 -s 4000 -F ${IMG} + + # size to grow to is chosen to cause partial cg + atf_check -s exit:0 -o ignore resize_ffs -y -s 5760 ${IMG} + atf_check -s exit:0 -o ignore fsck_ffs -f -n -F ${IMG} +} + +atf_init_test_cases() +{ + setupvars + atf_add_test_case grow_16M_v0_8192 + atf_add_test_case grow_16M_v1_16384 + atf_add_test_case grow_16M_v2_32768 +if [ "${RESIZE_FFS_ALL_TESTS-X}" != "X" ]; then + atf_add_test_case grow_16M_v0_4096 + atf_add_test_case grow_16M_v0_16384 + atf_add_test_case grow_16M_v0_32768 + atf_add_test_case grow_16M_v0_65536 + atf_add_test_case grow_16M_v1_4096 + atf_add_test_case grow_16M_v1_8192 + atf_add_test_case grow_16M_v1_32768 + atf_add_test_case grow_16M_v1_65536 + atf_add_test_case grow_16M_v2_4096 + atf_add_test_case grow_16M_v2_8192 + atf_add_test_case grow_16M_v2_16384 + atf_add_test_case grow_16M_v2_65536 + atf_add_test_case grow_24M_v0_4096 + atf_add_test_case grow_24M_v0_8192 + atf_add_test_case grow_24M_v0_16384 + atf_add_test_case grow_24M_v0_32768 + atf_add_test_case grow_24M_v0_65536 + atf_add_test_case grow_32M_v0_4096 + atf_add_test_case grow_32M_v0_8192 + atf_add_test_case grow_32M_v0_16384 + atf_add_test_case grow_32M_v0_32768 + atf_add_test_case grow_32M_v0_65536 + atf_add_test_case grow_48M_v0_4096 + atf_add_test_case grow_48M_v0_8192 + atf_add_test_case grow_48M_v0_16384 + atf_add_test_case grow_48M_v0_32768 + atf_add_test_case grow_48M_v0_65536 + atf_add_test_case grow_64M_v0_4096 + atf_add_test_case grow_64M_v0_8192 + atf_add_test_case grow_64M_v0_16384 + atf_add_test_case grow_64M_v0_32768 + atf_add_test_case grow_64M_v0_65536 + + atf_add_test_case grow_24M_v1_4096 + atf_add_test_case grow_24M_v1_8192 + atf_add_test_case grow_24M_v1_16384 + atf_add_test_case grow_24M_v1_32768 + atf_add_test_case grow_24M_v1_65536 + atf_add_test_case grow_32M_v1_4096 + atf_add_test_case grow_32M_v1_8192 + atf_add_test_case grow_32M_v1_16384 + atf_add_test_case grow_32M_v1_32768 + atf_add_test_case grow_32M_v1_65536 + atf_add_test_case grow_48M_v1_4096 + atf_add_test_case grow_48M_v1_8192 + atf_add_test_case grow_48M_v1_16384 + atf_add_test_case grow_48M_v1_32768 + atf_add_test_case grow_48M_v1_65536 + atf_add_test_case grow_64M_v1_4096 + atf_add_test_case grow_64M_v1_8192 + atf_add_test_case grow_64M_v1_16384 + atf_add_test_case grow_64M_v1_32768 + atf_add_test_case grow_64M_v1_65536 + + atf_add_test_case grow_24M_v2_4096 + atf_add_test_case grow_24M_v2_8192 + atf_add_test_case grow_24M_v2_16384 + atf_add_test_case grow_24M_v2_32768 + atf_add_test_case grow_24M_v2_65536 + atf_add_test_case grow_32M_v2_4096 + atf_add_test_case grow_32M_v2_8192 + atf_add_test_case grow_32M_v2_16384 + atf_add_test_case grow_32M_v2_32768 + atf_add_test_case grow_32M_v2_65536 + atf_add_test_case grow_48M_v2_4096 + atf_add_test_case grow_48M_v2_8192 + atf_add_test_case grow_48M_v2_16384 + atf_add_test_case grow_48M_v2_32768 + atf_add_test_case grow_48M_v2_65536 + atf_add_test_case grow_64M_v2_4096 + atf_add_test_case grow_64M_v2_8192 + atf_add_test_case grow_64M_v2_16384 + atf_add_test_case grow_64M_v2_32768 + atf_add_test_case grow_64M_v2_65536 +fi + atf_add_test_case grow_ffsv1_partial_cg +} diff --git a/tests/sbin/resize_ffs/t_grow_swapped.sh b/tests/sbin/resize_ffs/t_grow_swapped.sh new file mode 100644 index 000000000..07dc514d8 --- /dev/null +++ b/tests/sbin/resize_ffs/t_grow_swapped.sh @@ -0,0 +1,220 @@ +# $NetBSD: t_grow_swapped.sh,v 1.2 2011/01/11 00:50:02 riz Exp $ +# +# Copyright (c) 2010 The NetBSD Foundation, Inc. +# All rights reserved. +# +# This code is derived from software contributed to The NetBSD Foundation +# by Jeffrey C. Rizzo. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + + +# resize_ffs params as follows: +# resize_ffs blocksize fragsize fssize newfssize level numdata swap +# where 'numdata' is the number of data directories to copy - this is +# determined manually based on the maximum number that will fit in the +# created fs. 'level' is the fs-level (-O 0,1,2) passed to newfs. +# If 'swap' is included, byteswap the fs + +# v0 == newfs -O0 (4.3BSD layout, ffsv1 superblock) +test_case grow_16M_v0_4096 resize_ffs 4096 512 32768 131072 0 28 swap +test_case grow_16M_v0_8192 resize_ffs 8192 1024 32768 131072 0 28 swap +test_case grow_16M_v0_16384 resize_ffs 16384 2048 32768 131072 0 29 swap +test_case grow_16M_v0_32768 resize_ffs 32768 4096 32768 131072 0 28 swap +test_case grow_16M_v0_65536 resize_ffs 65536 8192 32768 131072 0 26 swap +# these grow_24M grow a smaller amount; sometimes there's different issues +test_case grow_24M_v0_4096 resize_ffs 4096 512 49152 65536 0 41 swap +test_case grow_24M_v0_8192 resize_ffs 8192 1024 49152 65536 0 42 swap +test_case grow_24M_v0_16384 resize_ffs 16384 2048 49152 65536 0 43 swap +test_case grow_24M_v0_32768 resize_ffs 32768 4096 49152 65536 0 42 swap +test_case grow_24M_v0_65536 resize_ffs 65536 8192 49152 65536 0 38 swap +test_case grow_32M_v0_4096 resize_ffs 4096 512 65536 131072 0 55 swap +test_case grow_32M_v0_8192 resize_ffs 8192 1024 65536 131072 0 56 swap +test_case grow_32M_v0_16384 resize_ffs 16384 2048 65536 131072 0 58 swap +test_case grow_32M_v0_32768 resize_ffs 32768 4096 65536 131072 0 56 swap +test_case grow_32M_v0_65536 resize_ffs 65536 8192 65536 131072 0 51 swap +test_case grow_48M_v0_4096 resize_ffs 4096 512 98304 131072 0 82 swap +test_case grow_48M_v0_8192 resize_ffs 8192 1024 98304 131072 0 84 swap +test_case grow_48M_v0_16384 resize_ffs 16384 2048 98304 131072 0 87 swap +test_case grow_48M_v0_32768 resize_ffs 32768 4096 98304 131072 0 83 swap +test_case grow_48M_v0_65536 resize_ffs 65536 8192 98304 131072 0 76 swap +test_case grow_64M_v0_4096 resize_ffs 4096 512 131072 262144 0 109 swap +test_case grow_64M_v0_8192 resize_ffs 8192 1024 131072 262144 0 111 swap +test_case grow_64M_v0_16384 resize_ffs 16384 2048 131072 262144 0 115 swap +test_case grow_64M_v0_32768 resize_ffs 32768 4096 131072 262144 0 111 swap +test_case grow_64M_v0_65536 resize_ffs 65536 8192 131072 262144 0 101 swap + +# v1 == newfs -O1 (FFSv1, v2 superblock layout) +test_case grow_16M_v1_4096 resize_ffs 4096 512 32768 131072 1 28 swap +test_case grow_16M_v1_8192 resize_ffs 8192 1024 32768 131072 1 28 swap +test_case grow_16M_v1_16384 resize_ffs 16384 2048 32768 131072 1 29 swap +test_case grow_16M_v1_32768 resize_ffs 32768 4096 32768 131072 1 28 swap +test_case grow_16M_v1_65536 resize_ffs 65536 8192 32768 131072 1 26 swap +# these grow_24M grow a smaller amount; sometimes there's different issues +test_case grow_24M_v1_4096 resize_ffs 4096 512 49152 65536 1 41 swap +test_case grow_24M_v1_8192 resize_ffs 8192 1024 49152 65536 1 42 swap +test_case grow_24M_v1_16384 resize_ffs 16384 2048 49152 65536 1 43 swap +test_case grow_24M_v1_32768 resize_ffs 32768 4096 49152 65536 1 42 swap +test_case grow_24M_v1_65536 resize_ffs 65536 8192 49152 65536 1 38 swap +test_case grow_32M_v1_4096 resize_ffs 4096 512 65536 131072 1 55 swap +test_case grow_32M_v1_8192 resize_ffs 8192 1024 65536 131072 1 56 swap +test_case grow_32M_v1_16384 resize_ffs 16384 2048 65536 131072 1 58 swap +test_case grow_32M_v1_32768 resize_ffs 32768 4096 65536 131072 1 56 swap +test_case grow_32M_v1_65536 resize_ffs 65536 8192 65536 131072 1 51 swap +test_case grow_48M_v1_4096 resize_ffs 4096 512 98304 131072 1 82 swap +test_case grow_48M_v1_8192 resize_ffs 8192 1024 98304 131072 1 84 swap +test_case grow_48M_v1_16384 resize_ffs 16384 2048 98304 131072 1 87 swap +test_case grow_48M_v1_32768 resize_ffs 32768 4096 98304 131072 1 83 swap +test_case grow_48M_v1_65536 resize_ffs 65536 8192 98304 131072 1 76 swap +test_case grow_64M_v1_4096 resize_ffs 4096 512 131072 262144 1 109 swap +test_case grow_64M_v1_8192 resize_ffs 8192 1024 131072 262144 1 111 swap +test_case grow_64M_v1_16384 resize_ffs 16384 2048 131072 262144 1 115 swap +test_case grow_64M_v1_32768 resize_ffs 32768 4096 131072 262144 1 111 swap +test_case grow_64M_v1_65536 resize_ffs 65536 8192 131072 262144 1 101 swap +test_case grow_16M_v2_4096 resize_ffs 4096 512 32768 131072 2 26 swap +test_case grow_16M_v2_8192 resize_ffs 8192 1024 32768 131072 2 28 swap +test_case grow_16M_v2_16384 resize_ffs 16384 2048 32768 131072 2 29 swap +test_case grow_16M_v2_32768 resize_ffs 32768 4096 32768 131072 2 28 swap +test_case grow_16M_v2_65536 resize_ffs 65536 8192 32768 131072 2 25 swap +test_case grow_24M_v2_4096 resize_ffs 4096 512 49152 65536 2 40 swap +test_case grow_24M_v2_8192 resize_ffs 8192 1024 49152 65536 2 42 swap +test_case grow_24M_v2_16384 resize_ffs 16384 2048 49152 65536 2 43 swap +test_case grow_24M_v2_32768 resize_ffs 32768 4096 49152 65536 2 42 swap +test_case grow_24M_v2_65536 resize_ffs 65536 8192 49152 65536 2 38 swap +test_case grow_32M_v2_4096 resize_ffs 4096 512 65536 131072 2 53 swap +test_case grow_32M_v2_8192 resize_ffs 8192 1024 65536 131072 2 56 swap +test_case grow_32M_v2_16384 resize_ffs 16384 2048 65536 131072 2 58 swap +test_case grow_32M_v2_32768 resize_ffs 32768 4096 65536 131072 2 56 swap +test_case grow_32M_v2_65536 resize_ffs 65536 8192 65536 131072 2 51 swap +test_case grow_48M_v2_4096 resize_ffs 4096 512 98304 131072 2 80 swap +test_case grow_48M_v2_8192 resize_ffs 8192 1024 98304 131072 2 84 swap +test_case grow_48M_v2_16384 resize_ffs 16384 2048 98304 131072 2 87 swap +test_case grow_48M_v2_32768 resize_ffs 32768 4096 98304 131072 2 83 swap +test_case grow_48M_v2_65536 resize_ffs 65536 8192 98304 131072 2 76 swap +test_case grow_64M_v2_4096 resize_ffs 4096 512 131072 262144 2 107 swap +test_case grow_64M_v2_8192 resize_ffs 8192 1024 131072 262144 2 111 swap +test_case grow_64M_v2_16384 resize_ffs 16384 2048 131072 262144 2 115 swap +test_case grow_64M_v2_32768 resize_ffs 32768 4096 131072 262144 2 111 swap +test_case grow_64M_v2_65536 resize_ffs 65536 8192 131072 262144 2 101 swap + +atf_test_case grow_ffsv1_partial_cg +grow_ffsv1_partial_cg_head() +{ + atf_set "descr" "Checks successful ffsv1 growth by less" \ + "than a cylinder group" +} +grow_ffsv1_partial_cg_body() +{ + echo "***resize_ffs grow test" + + atf_check -o ignore -e ignore newfs -B be -V1 -s 4000 -F ${IMG} + + # size to grow to is chosen to cause partial cg + atf_check -s exit:0 -o ignore resize_ffs -y -s 5760 ${IMG} + atf_check -s exit:0 -o ignore fsck_ffs -f -n -F ${IMG} +} + +atf_init_test_cases() +{ + setupvars + atf_add_test_case grow_16M_v0_65536 + atf_add_test_case grow_16M_v1_4096 + atf_add_test_case grow_16M_v2_8192 +if [ "${RESIZE_FFS_ALL_TESTS-X}" != "X" ]; then + atf_add_test_case grow_16M_v0_4096 + atf_add_test_case grow_16M_v0_8192 + atf_add_test_case grow_16M_v0_16384 + atf_add_test_case grow_16M_v0_32768 + atf_add_test_case grow_16M_v1_8192 + atf_add_test_case grow_16M_v1_16384 + atf_add_test_case grow_16M_v1_32768 + atf_add_test_case grow_16M_v1_65536 + atf_add_test_case grow_16M_v2_4096 + atf_add_test_case grow_16M_v2_16384 + atf_add_test_case grow_16M_v2_32768 + atf_add_test_case grow_16M_v2_65536 + atf_add_test_case grow_24M_v0_4096 + atf_add_test_case grow_24M_v0_8192 + atf_add_test_case grow_24M_v0_16384 + atf_add_test_case grow_24M_v0_32768 + atf_add_test_case grow_24M_v0_65536 + atf_add_test_case grow_32M_v0_4096 + atf_add_test_case grow_32M_v0_8192 + atf_add_test_case grow_32M_v0_16384 + atf_add_test_case grow_32M_v0_32768 + atf_add_test_case grow_32M_v0_65536 + atf_add_test_case grow_48M_v0_4096 + atf_add_test_case grow_48M_v0_8192 + atf_add_test_case grow_48M_v0_16384 + atf_add_test_case grow_48M_v0_32768 + atf_add_test_case grow_48M_v0_65536 + atf_add_test_case grow_64M_v0_4096 + atf_add_test_case grow_64M_v0_8192 + atf_add_test_case grow_64M_v0_16384 + atf_add_test_case grow_64M_v0_32768 + atf_add_test_case grow_64M_v0_65536 + + atf_add_test_case grow_24M_v1_4096 + atf_add_test_case grow_24M_v1_8192 + atf_add_test_case grow_24M_v1_16384 + atf_add_test_case grow_24M_v1_32768 + atf_add_test_case grow_24M_v1_65536 + atf_add_test_case grow_32M_v1_4096 + atf_add_test_case grow_32M_v1_8192 + atf_add_test_case grow_32M_v1_16384 + atf_add_test_case grow_32M_v1_32768 + atf_add_test_case grow_32M_v1_65536 + atf_add_test_case grow_48M_v1_4096 + atf_add_test_case grow_48M_v1_8192 + atf_add_test_case grow_48M_v1_16384 + atf_add_test_case grow_48M_v1_32768 + atf_add_test_case grow_48M_v1_65536 + atf_add_test_case grow_64M_v1_4096 + atf_add_test_case grow_64M_v1_8192 + atf_add_test_case grow_64M_v1_16384 + atf_add_test_case grow_64M_v1_32768 + atf_add_test_case grow_64M_v1_65536 + + atf_add_test_case grow_24M_v2_4096 + atf_add_test_case grow_24M_v2_8192 + atf_add_test_case grow_24M_v2_16384 + atf_add_test_case grow_24M_v2_32768 + atf_add_test_case grow_24M_v2_65536 + atf_add_test_case grow_32M_v2_4096 + atf_add_test_case grow_32M_v2_8192 + atf_add_test_case grow_32M_v2_16384 + atf_add_test_case grow_32M_v2_32768 + atf_add_test_case grow_32M_v2_65536 + atf_add_test_case grow_48M_v2_4096 + atf_add_test_case grow_48M_v2_8192 + atf_add_test_case grow_48M_v2_16384 + atf_add_test_case grow_48M_v2_32768 + atf_add_test_case grow_48M_v2_65536 + atf_add_test_case grow_64M_v2_4096 + atf_add_test_case grow_64M_v2_8192 + atf_add_test_case grow_64M_v2_16384 + atf_add_test_case grow_64M_v2_32768 + atf_add_test_case grow_64M_v2_65536 +fi + atf_add_test_case grow_ffsv1_partial_cg +} diff --git a/tests/sbin/resize_ffs/t_shrink.sh b/tests/sbin/resize_ffs/t_shrink.sh new file mode 100644 index 000000000..1b667593d --- /dev/null +++ b/tests/sbin/resize_ffs/t_shrink.sh @@ -0,0 +1,185 @@ +# $NetBSD: t_shrink.sh,v 1.7 2011/01/05 02:25:27 riz Exp $ +# +# Copyright (c) 2010 The NetBSD Foundation, Inc. +# All rights reserved. +# +# This code is derived from software contributed to The NetBSD Foundation +# by Jeffrey C. Rizzo. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + + +# resize_ffs params as follows: +# resize_ffs blocksize fragsize fssize newfssize level numdata swap +# where 'numdata' is the number of data directories to copy - this is +# determined manually based on the maximum number that will fit in the +# created fs. 'level' is the fs-level (-O 0,1,2) passed to newfs. +# If 'swap' is included, byteswap the fs +test_case shrink_24M_16M_v0_4096 resize_ffs 4096 512 49152 32768 0 41 +test_case shrink_24M_16M_v0_8192 resize_ffs 8192 1024 49152 32768 0 42 +test_case shrink_24M_16M_v0_16384 resize_ffs 16384 2048 49152 32768 0 43 +test_case shrink_24M_16M_v0_32768 resize_ffs 32768 4096 49152 32768 0 42 +test_case shrink_24M_16M_v0_65536 resize_ffs 65536 8192 49152 32768 0 38 +test_case shrink_32M_24M_v0_4096 resize_ffs 4096 512 65536 49152 0 55 +test_case shrink_32M_24M_v0_8192 resize_ffs 8192 1024 65536 49152 0 56 +test_case shrink_32M_24M_v0_16384 resize_ffs 16384 2048 65536 49152 0 58 +test_case shrink_32M_24M_v0_32768 resize_ffs 32768 4096 65536 49152 0 56 +test_case_xfail shrink_32M_24M_v0_65536 "PR bin/44204" resize_ffs 65536 8192 65536 49152 0 51 +test_case shrink_48M_16M_v0_4096 resize_ffs 4096 512 98304 32768 0 82 +test_case shrink_48M_16M_v0_8192 resize_ffs 8192 1024 98304 32768 0 84 +test_case shrink_48M_16M_v0_16384 resize_ffs 16384 2048 98304 32768 0 87 +test_case shrink_48M_16M_v0_32768 resize_ffs 32768 4096 98304 32768 0 83 +test_case shrink_48M_16M_v0_65536 resize_ffs 65536 8192 98304 32768 0 76 +test_case shrink_64M_48M_v0_4096 resize_ffs 4096 512 131072 98304 0 109 +test_case shrink_64M_48M_v0_8192 resize_ffs 8192 1024 131072 98304 0 111 +test_case shrink_64M_48M_v0_16384 resize_ffs 16384 2048 131072 98304 0 115 +test_case shrink_64M_48M_v0_32768 resize_ffs 32768 4096 131072 98304 0 111 +test_case shrink_64M_48M_v0_65536 resize_ffs 65536 8192 131072 98304 0 101 + +test_case shrink_24M_16M_v1_4096 resize_ffs 4096 512 49152 32768 1 41 +test_case shrink_24M_16M_v1_8192 resize_ffs 8192 1024 49152 32768 1 42 +test_case shrink_24M_16M_v1_16384 resize_ffs 16384 2048 49152 32768 1 43 +test_case shrink_24M_16M_v1_32768 resize_ffs 32768 4096 49152 32768 1 42 +test_case shrink_24M_16M_v1_65536 resize_ffs 65536 8192 49152 32768 1 38 +test_case shrink_32M_24M_v1_4096 resize_ffs 4096 512 65536 49152 1 55 +test_case shrink_32M_24M_v1_8192 resize_ffs 8192 1024 65536 49152 1 56 +test_case shrink_32M_24M_v1_16384 resize_ffs 16384 2048 65536 49152 1 58 +test_case shrink_32M_24M_v1_32768 resize_ffs 32768 4096 65536 49152 1 56 +test_case_xfail shrink_32M_24M_v1_65536 "PR bin/44204" resize_ffs 65536 8192 65536 49152 1 51 +test_case shrink_48M_16M_v1_4096 resize_ffs 4096 512 98304 32768 1 82 +test_case shrink_48M_16M_v1_8192 resize_ffs 8192 1024 98304 32768 1 84 +test_case shrink_48M_16M_v1_16384 resize_ffs 16384 2048 98304 32768 1 87 +test_case shrink_48M_16M_v1_32768 resize_ffs 32768 4096 98304 32768 1 83 +test_case shrink_48M_16M_v1_65536 resize_ffs 65536 8192 98304 32768 1 76 +test_case shrink_64M_48M_v1_4096 resize_ffs 4096 512 131072 98304 1 109 +test_case shrink_64M_48M_v1_8192 resize_ffs 8192 1024 131072 98304 1 111 +test_case shrink_64M_48M_v1_16384 resize_ffs 16384 2048 131072 98304 1 115 +test_case shrink_64M_48M_v1_32768 resize_ffs 32768 4096 131072 98304 1 111 +test_case shrink_64M_48M_v1_65536 resize_ffs 65536 8192 131072 98304 1 101 + +test_case_xfail shrink_24M_16M_v2_4096 "PR bin/44205" resize_ffs 4096 512 49152 32768 2 41 +test_case_xfail shrink_24M_16M_v2_8192 "PR bin/44205" resize_ffs 8192 1024 49152 32768 2 42 +test_case_xfail shrink_24M_16M_v2_16384 "PR bin/44205" resize_ffs 16384 2048 49152 32768 2 43 +test_case_xfail shrink_24M_16M_v2_32768 "PR bin/44205" resize_ffs 32768 4096 49152 32768 2 42 +test_case_xfail shrink_24M_16M_v2_65536 "PR bin/44205" resize_ffs 65536 8192 49152 32768 2 38 +test_case_xfail shrink_32M_24M_v2_4096 "PR bin/44205" resize_ffs 4096 512 65536 49152 2 55 +test_case_xfail shrink_32M_24M_v2_8192 "PR bin/44205" resize_ffs 8192 1024 65536 49152 2 56 +test_case_xfail shrink_32M_24M_v2_16384 "PR bin/44205" resize_ffs 16384 2048 65536 49152 2 58 +test_case_xfail shrink_32M_24M_v2_32768 "PR bin/44205" resize_ffs 32768 4096 65536 49152 2 56 +test_case_xfail shrink_32M_24M_v2_65536 "PR bin/44204" resize_ffs 65536 8192 65536 49152 2 51 +test_case_xfail shrink_48M_16M_v2_4096 "PR bin/44205" resize_ffs 4096 512 98304 32768 2 82 +test_case_xfail shrink_48M_16M_v2_8192 "PR bin/44205" resize_ffs 8192 1024 98304 32768 2 84 +test_case_xfail shrink_48M_16M_v2_16384 "PR bin/44205" resize_ffs 16384 2048 98304 32768 2 87 +test_case_xfail shrink_48M_16M_v2_32768 "PR bin/44205" resize_ffs 32768 4096 98304 32768 2 83 +test_case_xfail shrink_48M_16M_v2_65536 "PR bin/44205" resize_ffs 65536 8192 98304 32768 2 76 +test_case_xfail shrink_64M_48M_v2_4096 "PR bin/44205" resize_ffs 4096 512 131072 98304 2 109 +test_case_xfail shrink_64M_48M_v2_8192 "PR bin/44205" resize_ffs 8192 1024 131072 98304 2 111 +test_case_xfail shrink_64M_48M_v2_16384 "PR bin/44205" resize_ffs 16384 2048 131072 98304 2 115 +test_case_xfail shrink_64M_48M_v2_32768 "PR bin/44205" resize_ffs 32768 4096 131072 98304 2 111 +test_case_xfail shrink_64M_48M_v2_65536 "PR bin/44205" resize_ffs 65536 8192 131072 98304 2 101 + + +atf_test_case shrink_ffsv1_partial_cg +shrink_ffsv1_partial_cg_head() +{ + atf_set "descr" "Checks successful shrinkage of ffsv1 by" \ + "less than a cylinder group" +} +shrink_ffsv1_partial_cg_body() +{ + echo "*** resize_ffs shrinkage partial cg test" + + atf_check -o ignore -e ignore newfs -V1 -F -s 5760 ${IMG} + + # shrink so there's a partial cg at the end + atf_check -s exit:0 resize_ffs -s 4000 -y ${IMG} + atf_check -s exit:0 -o ignore fsck_ffs -f -n -F ${IMG} +} + +atf_init_test_cases() +{ + setupvars + atf_add_test_case shrink_24M_16M_v0_32768 + atf_add_test_case shrink_24M_16M_v1_65536 + atf_add_test_case shrink_24M_16M_v2_4096 +if [ "${RESIZE_FFS_ALL_TESTS-X}" != "X" ]; then + atf_add_test_case shrink_24M_16M_v0_4096 + atf_add_test_case shrink_24M_16M_v0_8192 + atf_add_test_case shrink_24M_16M_v0_16384 + atf_add_test_case shrink_24M_16M_v0_65536 + atf_add_test_case shrink_24M_16M_v1_4096 + atf_add_test_case shrink_24M_16M_v1_8192 + atf_add_test_case shrink_24M_16M_v1_16384 + atf_add_test_case shrink_24M_16M_v1_32768 + atf_add_test_case shrink_24M_16M_v2_8192 + atf_add_test_case shrink_24M_16M_v2_16384 + atf_add_test_case shrink_24M_16M_v2_32768 + atf_add_test_case shrink_24M_16M_v2_65536 + atf_add_test_case shrink_32M_24M_v0_4096 + atf_add_test_case shrink_32M_24M_v0_8192 + atf_add_test_case shrink_32M_24M_v0_16384 + atf_add_test_case shrink_32M_24M_v0_32768 + atf_add_test_case shrink_32M_24M_v0_65536 + atf_add_test_case shrink_48M_16M_v0_4096 + atf_add_test_case shrink_48M_16M_v0_8192 + atf_add_test_case shrink_48M_16M_v0_16384 + atf_add_test_case shrink_48M_16M_v0_32768 + atf_add_test_case shrink_48M_16M_v0_65536 + atf_add_test_case shrink_64M_48M_v0_4096 + atf_add_test_case shrink_64M_48M_v0_8192 + atf_add_test_case shrink_64M_48M_v0_16384 + atf_add_test_case shrink_64M_48M_v0_32768 + atf_add_test_case shrink_64M_48M_v0_65536 + atf_add_test_case shrink_32M_24M_v1_4096 + atf_add_test_case shrink_32M_24M_v1_8192 + atf_add_test_case shrink_32M_24M_v1_16384 + atf_add_test_case shrink_32M_24M_v1_32768 + atf_add_test_case shrink_32M_24M_v1_65536 + atf_add_test_case shrink_48M_16M_v1_4096 + atf_add_test_case shrink_48M_16M_v1_8192 + atf_add_test_case shrink_48M_16M_v1_16384 + atf_add_test_case shrink_48M_16M_v1_32768 + atf_add_test_case shrink_48M_16M_v1_65536 + atf_add_test_case shrink_64M_48M_v1_4096 + atf_add_test_case shrink_64M_48M_v1_8192 + atf_add_test_case shrink_64M_48M_v1_16384 + atf_add_test_case shrink_64M_48M_v1_32768 + atf_add_test_case shrink_64M_48M_v1_65536 + atf_add_test_case shrink_32M_24M_v2_4096 + atf_add_test_case shrink_32M_24M_v2_8192 + atf_add_test_case shrink_32M_24M_v2_16384 + atf_add_test_case shrink_32M_24M_v2_32768 + atf_add_test_case shrink_32M_24M_v2_65536 + atf_add_test_case shrink_48M_16M_v2_4096 + atf_add_test_case shrink_48M_16M_v2_8192 + atf_add_test_case shrink_48M_16M_v2_16384 + atf_add_test_case shrink_48M_16M_v2_32768 + atf_add_test_case shrink_48M_16M_v2_65536 + atf_add_test_case shrink_64M_48M_v2_4096 + atf_add_test_case shrink_64M_48M_v2_8192 + atf_add_test_case shrink_64M_48M_v2_16384 + atf_add_test_case shrink_64M_48M_v2_32768 + atf_add_test_case shrink_64M_48M_v2_65536 +fi + atf_add_test_case shrink_ffsv1_partial_cg +} diff --git a/tests/sbin/resize_ffs/t_shrink_swapped.sh b/tests/sbin/resize_ffs/t_shrink_swapped.sh new file mode 100644 index 000000000..30e4adddb --- /dev/null +++ b/tests/sbin/resize_ffs/t_shrink_swapped.sh @@ -0,0 +1,185 @@ +# $NetBSD: t_shrink_swapped.sh,v 1.1 2011/01/05 02:25:27 riz Exp $ +# +# Copyright (c) 2010 The NetBSD Foundation, Inc. +# All rights reserved. +# +# This code is derived from software contributed to The NetBSD Foundation +# by Jeffrey C. Rizzo. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + + +# resize_ffs params as follows: +# resize_ffs blocksize fragsize fssize newfssize level numdata swap +# where 'numdata' is the number of data directories to copy - this is +# determined manually based on the maximum number that will fit in the +# created fs. 'level' is the fs-level (-O 0,1,2) passed to newfs. +# If 'swap' is included, byteswap the fs +test_case shrink_24M_16M_v0_4096 resize_ffs 4096 512 49152 32768 0 41 swap +test_case shrink_24M_16M_v0_8192 resize_ffs 8192 1024 49152 32768 0 42 swap +test_case shrink_24M_16M_v0_16384 resize_ffs 16384 2048 49152 32768 0 43 swap +test_case shrink_24M_16M_v0_32768 resize_ffs 32768 4096 49152 32768 0 42 swap +test_case shrink_24M_16M_v0_65536 resize_ffs 65536 8192 49152 32768 0 38 swap +test_case shrink_32M_24M_v0_4096 resize_ffs 4096 512 65536 49152 0 55 swap +test_case shrink_32M_24M_v0_8192 resize_ffs 8192 1024 65536 49152 0 56 swap +test_case shrink_32M_24M_v0_16384 resize_ffs 16384 2048 65536 49152 0 58 swap +test_case shrink_32M_24M_v0_32768 resize_ffs 32768 4096 65536 49152 0 56 swap +test_case_xfail shrink_32M_24M_v0_65536 "PR bin/44204" resize_ffs 65536 8192 65536 49152 0 51 swap +test_case shrink_48M_16M_v0_4096 resize_ffs 4096 512 98304 32768 0 82 swap +test_case shrink_48M_16M_v0_8192 resize_ffs 8192 1024 98304 32768 0 84 swap +test_case shrink_48M_16M_v0_16384 resize_ffs 16384 2048 98304 32768 0 87 swap +test_case shrink_48M_16M_v0_32768 resize_ffs 32768 4096 98304 32768 0 83 swap +test_case shrink_48M_16M_v0_65536 resize_ffs 65536 8192 98304 32768 0 76 swap +test_case shrink_64M_48M_v0_4096 resize_ffs 4096 512 131072 98304 0 109 swap +test_case shrink_64M_48M_v0_8192 resize_ffs 8192 1024 131072 98304 0 111 swap +test_case shrink_64M_48M_v0_16384 resize_ffs 16384 2048 131072 98304 0 115 swap +test_case shrink_64M_48M_v0_32768 resize_ffs 32768 4096 131072 98304 0 111 swap +test_case shrink_64M_48M_v0_65536 resize_ffs 65536 8192 131072 98304 0 101 swap + +test_case shrink_24M_16M_v1_4096 resize_ffs 4096 512 49152 32768 1 41 swap +test_case shrink_24M_16M_v1_8192 resize_ffs 8192 1024 49152 32768 1 42 swap +test_case shrink_24M_16M_v1_16384 resize_ffs 16384 2048 49152 32768 1 43 swap +test_case shrink_24M_16M_v1_32768 resize_ffs 32768 4096 49152 32768 1 42 swap +test_case shrink_24M_16M_v1_65536 resize_ffs 65536 8192 49152 32768 1 38 swap +test_case shrink_32M_24M_v1_4096 resize_ffs 4096 512 65536 49152 1 55 swap +test_case shrink_32M_24M_v1_8192 resize_ffs 8192 1024 65536 49152 1 56 swap +test_case shrink_32M_24M_v1_16384 resize_ffs 16384 2048 65536 49152 1 58 swap +test_case shrink_32M_24M_v1_32768 resize_ffs 32768 4096 65536 49152 1 56 swap +test_case_xfail shrink_32M_24M_v1_65536 "PR bin/44204" resize_ffs 65536 8192 65536 49152 1 51 swap +test_case shrink_48M_16M_v1_4096 resize_ffs 4096 512 98304 32768 1 82 swap +test_case shrink_48M_16M_v1_8192 resize_ffs 8192 1024 98304 32768 1 84 swap +test_case shrink_48M_16M_v1_16384 resize_ffs 16384 2048 98304 32768 1 87 swap +test_case shrink_48M_16M_v1_32768 resize_ffs 32768 4096 98304 32768 1 83 swap +test_case shrink_48M_16M_v1_65536 resize_ffs 65536 8192 98304 32768 1 76 swap +test_case shrink_64M_48M_v1_4096 resize_ffs 4096 512 131072 98304 1 109 swap +test_case shrink_64M_48M_v1_8192 resize_ffs 8192 1024 131072 98304 1 111 swap +test_case shrink_64M_48M_v1_16384 resize_ffs 16384 2048 131072 98304 1 115 swap +test_case shrink_64M_48M_v1_32768 resize_ffs 32768 4096 131072 98304 1 111 swap +test_case shrink_64M_48M_v1_65536 resize_ffs 65536 8192 131072 98304 1 101 swap + +test_case_xfail shrink_24M_16M_v2_4096 "PR bin/44205" resize_ffs 4096 512 49152 32768 2 41 swap +test_case_xfail shrink_24M_16M_v2_8192 "PR bin/44205" resize_ffs 8192 1024 49152 32768 2 42 swap +test_case_xfail shrink_24M_16M_v2_16384 "PR bin/44205" resize_ffs 16384 2048 49152 32768 2 43 swap +test_case_xfail shrink_24M_16M_v2_32768 "PR bin/44205" resize_ffs 32768 4096 49152 32768 2 42 swap +test_case_xfail shrink_24M_16M_v2_65536 "PR bin/44205" resize_ffs 65536 8192 49152 32768 2 38 swap +test_case_xfail shrink_32M_24M_v2_4096 "PR bin/44205" resize_ffs 4096 512 65536 49152 2 55 swap +test_case_xfail shrink_32M_24M_v2_8192 "PR bin/44205" resize_ffs 8192 1024 65536 49152 2 56 swap +test_case_xfail shrink_32M_24M_v2_16384 "PR bin/44205" resize_ffs 16384 2048 65536 49152 2 58 swap +test_case_xfail shrink_32M_24M_v2_32768 "PR bin/44205" resize_ffs 32768 4096 65536 49152 2 56 swap +test_case_xfail shrink_32M_24M_v2_65536 "PR bin/44204" resize_ffs 65536 8192 65536 49152 2 51 swap +test_case_xfail shrink_48M_16M_v2_4096 "PR bin/44205" resize_ffs 4096 512 98304 32768 2 82 swap +test_case_xfail shrink_48M_16M_v2_8192 "PR bin/44205" resize_ffs 8192 1024 98304 32768 2 84 swap +test_case_xfail shrink_48M_16M_v2_16384 "PR bin/44205" resize_ffs 16384 2048 98304 32768 2 87 swap +test_case_xfail shrink_48M_16M_v2_32768 "PR bin/44205" resize_ffs 32768 4096 98304 32768 2 83 swap +test_case_xfail shrink_48M_16M_v2_65536 "PR bin/44205" resize_ffs 65536 8192 98304 32768 2 76 swap +test_case_xfail shrink_64M_48M_v2_4096 "PR bin/44205" resize_ffs 4096 512 131072 98304 2 109 swap +test_case_xfail shrink_64M_48M_v2_8192 "PR bin/44205" resize_ffs 8192 1024 131072 98304 2 111 swap +test_case_xfail shrink_64M_48M_v2_16384 "PR bin/44205" resize_ffs 16384 2048 131072 98304 2 115 swap +test_case_xfail shrink_64M_48M_v2_32768 "PR bin/44205" resize_ffs 32768 4096 131072 98304 2 111 swap +test_case_xfail shrink_64M_48M_v2_65536 "PR bin/44205" resize_ffs 65536 8192 131072 98304 2 101 swap + + +atf_test_case shrink_ffsv1_partial_cg +shrink_ffsv1_partial_cg_head() +{ + atf_set "descr" "Checks successful shrinkage of ffsv1 by" \ + "less than a cylinder group" +} +shrink_ffsv1_partial_cg_body() +{ + echo "*** resize_ffs shrinkage partial cg test" + + atf_check -o ignore -e ignore newfs -V1 -F -s 5760 ${IMG} + + # shrink so there's a partial cg at the end + atf_check -s exit:0 resize_ffs -s 4000 -y ${IMG} + atf_check -s exit:0 -o ignore fsck_ffs -f -n -F ${IMG} +} + +atf_init_test_cases() +{ + setupvars + atf_add_test_case shrink_24M_16M_v0_4096 + atf_add_test_case shrink_24M_16M_v1_8192 + atf_add_test_case shrink_24M_16M_v2_16384 +if [ "${RESIZE_FFS_ALL_TESTS-X}" != "X" ]; then + atf_add_test_case shrink_24M_16M_v0_8192 + atf_add_test_case shrink_24M_16M_v0_16384 + atf_add_test_case shrink_24M_16M_v0_32768 + atf_add_test_case shrink_24M_16M_v0_65536 + atf_add_test_case shrink_24M_16M_v1_4096 + atf_add_test_case shrink_24M_16M_v1_16384 + atf_add_test_case shrink_24M_16M_v1_32768 + atf_add_test_case shrink_24M_16M_v1_65536 + atf_add_test_case shrink_24M_16M_v2_4096 + atf_add_test_case shrink_24M_16M_v2_8192 + atf_add_test_case shrink_24M_16M_v2_32768 + atf_add_test_case shrink_24M_16M_v2_65536 + atf_add_test_case shrink_32M_24M_v0_4096 + atf_add_test_case shrink_32M_24M_v0_8192 + atf_add_test_case shrink_32M_24M_v0_16384 + atf_add_test_case shrink_32M_24M_v0_32768 + atf_add_test_case shrink_32M_24M_v0_65536 + atf_add_test_case shrink_48M_16M_v0_4096 + atf_add_test_case shrink_48M_16M_v0_8192 + atf_add_test_case shrink_48M_16M_v0_16384 + atf_add_test_case shrink_48M_16M_v0_32768 + atf_add_test_case shrink_48M_16M_v0_65536 + atf_add_test_case shrink_64M_48M_v0_4096 + atf_add_test_case shrink_64M_48M_v0_8192 + atf_add_test_case shrink_64M_48M_v0_16384 + atf_add_test_case shrink_64M_48M_v0_32768 + atf_add_test_case shrink_64M_48M_v0_65536 + atf_add_test_case shrink_32M_24M_v1_4096 + atf_add_test_case shrink_32M_24M_v1_8192 + atf_add_test_case shrink_32M_24M_v1_16384 + atf_add_test_case shrink_32M_24M_v1_32768 + atf_add_test_case shrink_32M_24M_v1_65536 + atf_add_test_case shrink_48M_16M_v1_4096 + atf_add_test_case shrink_48M_16M_v1_8192 + atf_add_test_case shrink_48M_16M_v1_16384 + atf_add_test_case shrink_48M_16M_v1_32768 + atf_add_test_case shrink_48M_16M_v1_65536 + atf_add_test_case shrink_64M_48M_v1_4096 + atf_add_test_case shrink_64M_48M_v1_8192 + atf_add_test_case shrink_64M_48M_v1_16384 + atf_add_test_case shrink_64M_48M_v1_32768 + atf_add_test_case shrink_64M_48M_v1_65536 + atf_add_test_case shrink_32M_24M_v2_4096 + atf_add_test_case shrink_32M_24M_v2_8192 + atf_add_test_case shrink_32M_24M_v2_16384 + atf_add_test_case shrink_32M_24M_v2_32768 + atf_add_test_case shrink_32M_24M_v2_65536 + atf_add_test_case shrink_48M_16M_v2_4096 + atf_add_test_case shrink_48M_16M_v2_8192 + atf_add_test_case shrink_48M_16M_v2_16384 + atf_add_test_case shrink_48M_16M_v2_32768 + atf_add_test_case shrink_48M_16M_v2_65536 + atf_add_test_case shrink_64M_48M_v2_4096 + atf_add_test_case shrink_64M_48M_v2_8192 + atf_add_test_case shrink_64M_48M_v2_16384 + atf_add_test_case shrink_64M_48M_v2_32768 + atf_add_test_case shrink_64M_48M_v2_65536 +fi + atf_add_test_case shrink_ffsv1_partial_cg +} diff --git a/tests/sbin/resize_ffs/testdata.md5 b/tests/sbin/resize_ffs/testdata.md5 new file mode 100644 index 000000000..9a3f76fdd --- /dev/null +++ b/tests/sbin/resize_ffs/testdata.md5 @@ -0,0 +1,18 @@ +MD5 (1024) = eadce85bc513cc7b9b46c027ce07ccdb +MD5 (1025) = 3cf2a95b3af7377ca81ff08265534334 +MD5 (131072) = 3bf5f82ad5e1f8878caa699548cc0955 +MD5 (131073) = 3423d2f10e3abb20e1ceae4b055f5071 +MD5 (16384) = 933f03c66d4e2da32089ed994c9b34bd +MD5 (16385) = d0b296920f44ef298880a2d963066026 +MD5 (2048) = fb03fb8916dd57f9648f89a06bb46f06 +MD5 (2049) = f2e489640fc3af5f09352d27717d832e +MD5 (32768) = d940d6ccf83aeb00e71b9bbeaf860962 +MD5 (32769) = 760e060cefd844c082a10b3bef1408f7 +MD5 (4096) = a04926ee9302f93a322e784a6b044577 +MD5 (4097) = bf13de3963f43a0ffaadb1c782b71372 +MD5 (512) = 991ad794ac386e8ba71d9bb64ab4c979 +MD5 (513) = ede1dc964fe2460dd74c3c87942162ad +MD5 (65536) = 1ee304df7275d8f88c5c0650536c842c +MD5 (65537) = 964632a8f1a323e31af6cf1297f88041 +MD5 (8192) = 51ce7789ae9662b2c13195573a447206 +MD5 (8193) = 35d478bc5fba0d96ffb318748d1035c7 diff --git a/tests/sbin/resize_ffs/testdata.tar.gz.base64 b/tests/sbin/resize_ffs/testdata.tar.gz.base64 new file mode 100644 index 000000000..d8fe84000 --- /dev/null +++ b/tests/sbin/resize_ffs/testdata.tar.gz.base64 @@ -0,0 +1,10938 @@ +begin-base64 644 testdata.tar.gz +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 +BYj5GMUVET4FSnC6zauv7ZhiE9U17V6WFnmIBwZ3zhWkL8eb2TzvTOfZw4L4ZCSK +cIKEs8jOM49qBE+6P+x6jbp2GNtOuFp/WxCyQIQXG7XDE9YeaUu4/S5aegmdM0S2 +tnDHEHrk2s6EkH89wbEXwccsZ9PgafhhorasAQoZOdKzAMmt0MEDB3b7BrlNGFCr +wS6KSfX8vrIVGNSMqGyxUfLYggRNtWxE7x4tN8JAbXQ6gspaRMjprpuvGieqYPgT +V52s3D4jneWAyy+XhUQHWxCLUbiCG4PQmAF0RVj9tJZwSMjW/PpUlL1bFjiYdCl5 +YEekzVs4YDjkG8MKJH1B3lOgqmKYm/4MRr0rq9eMOKU1dnfHuAuCG1txYRwCPbWg +XRwT2BNm1cmQh6/0teqJ2L/iZLOEsSckj6W5mP/OWSAtEEK15zahOU6rmICfQD1H +q9Z3D/qdG9q7+q+beRhOG8zSq9ykOm6N3NhnInjQbOZ5keGsLd9Cvdh3u+4pNU8m +hopfl5xK3tu1z1x+f8dSdqPPoQgiclOr3oErSjL0sJYyUlsXGttjmZ1CX+qlqdP5 +21bFA46l90h5lCEb1deme5wEn7sVkL22sfNO/ZgN49TpUn21jVGs/GlzTsDlApAP +0LQnh/tyE10vhL0eS2zyr8NX/fLPMfasOuvhm/LZiKoe8TQNYaLkEt04ozbKD4eM +2YiRtBVuaTAgj4FS/tn0ZOOoevcNVST1lxrjrZ6q25Quj/YB7jwUdOsNPdF8NR1H +eHASk1IuFqiYj9he2A0lJU0QcYqFUbWtE6tkySrAshSfmgRohskjvDtnXIJn2DA5 +7bODLbkoJws5nUjM1vkeuprzI6aC12rfkhr6X/bonNnyEKKDeQKJ509JmQM2JQLo +yLdred1IXifjIzIDVYgQTbvgnw3d1720RWNLJhAgnqrCfqZC6R3ebCT0zwnQqNJg +P52OqBqHuim6yrgGyNEg6dJLJE64Ipjk//a+En0xQsXHqvwsYdCHebu3auiZqrUx +EYV2cVGW7H/iW6psFjGW2jAoYjb06zm08upWuuGkxli6dqBORKWUakecTh7NGKXr +wGTur8a31lvkzlCkycZp3MkYW2RjyMeVkqLSwT7fWqmm6Mjldb8BziOELUvgP5XE +XuOVXwKmPyeZDvJ2/K6g+KFM6euWYWqP31e7/2yq2uvbffL+p46h83/SQtDe3JYz +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 +1M+q804BKH73FL8J+w1SXX3tvkdMy2z82pyD3xsOfnrjoOQyYxucPyZn8hcwL32c +6r5+xqss+XXcpc8+hc/J3mW7VImdKDkvR+8bM5a9Kc8Khmi15NdSQtd4yGjuyEAM +ibFGTK4JRr5IzO5H5H/SgmQzoBEV9eDgYqtm+4t3YOOgcGAqvZJXvUkwKwrLj1QR +TAhA7WXl3BpueZCwN9sFiXSLyuRm2O8S8MAJ6kPwqiGdGAjjkdecM2POiJ7LxAgp +sCCkJKsLIK7G/SHaYWnkmKZROdcohPE85CI9hgdS+IZlKMFS3ja9OYVEYytyYPiQ +UXZ1S/4QGVkNAxMCv2Reymir+FQGpy5BeITgr0gQ3RYNVcs8lJVvp409Lr6gpekt +WBT3V4E/mx0yY4W9FVcA1R2ZJoRKTpZLkoyxsXFZaZk0X76zeCR2O3mMOa4uNHEH +dpImS6fiXFUpfkwJ+wDxGS02WEFtbk2c1M0PdjRdZ0CwKDj5om06XXHLjpi2MY7x +3sqGMGe7nwPwJRE1guKv27xCuwZzryfktEA3trycM8rNmyfWZ86wAAahS8bw30se +GgtG/d1E7DRO2vxvigyL05FnDA9niWAP84VVPTfkakDTdGqspgJwjCJxM+C+AxlF +z4aTAgvKJux9ISmDM2x0zk+mON/3/ySwCOvmnZJWnFgYD+CtJyYUwJYSwgqWPUlf +Yvj/AhuojfJfk7o+HKRdE5vow1qlRCbOHDmKbR3Fh+Rd0NnXKIQzz4mfVReHfebl +3pfolvW1Dhse4Uixbk98MQnN7wyVRY2KNK7yHkG4DPGi/e5UgVMLDM0o054sRgdL +6nu8Co+BrDAXjusqeLzajyyijzrOpmFl6UqyaDW9mNYpjuS9gGkrfv4QOXREeJkN +SarPWgEU/dArOOQTcH7sH158JIW8OtCJbQRYORll6DDHyR2NFYt4sgu4InLjSgzs +Qmf4q57yan2TpjloCvyiSPJAwAmGdM10WkTOvpF8a/36N1Sm01jdochVQjSQrQ3e +HvVHhy+wUU0sfbDaUbpMWBp2Uph4GMbwP0oAJXRObfU2aGL85nYm9Z5DKBIqzR7l +LQDJLrgcQAwH4xUCJLEVnKpGHsEqcGs50cO7BM4Gmuk3/9LqtMBLyai+g/HjSn2W +2G3iAhNVXh6y+GFLV+Rc4n9bafGPoB7SBSLN7eubkXF5wAGjztz6Tm+09keUSIMh +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 +//znP//5z3/+85//L/0vxuXHSABICAA= +==== diff --git a/tests/sbin/route/Makefile b/tests/sbin/route/Makefile new file mode 100644 index 000000000..e9c8b0514 --- /dev/null +++ b/tests/sbin/route/Makefile @@ -0,0 +1,9 @@ +# $NetBSD: Makefile,v 1.1 2011/05/03 07:56:42 jruoho Exp $ + +.include + +TESTSDIR= ${TESTSBASE}/sbin/route + +TESTS_SH= t_missing + +.include diff --git a/tests/sbin/route/t_missing.sh b/tests/sbin/route/t_missing.sh new file mode 100644 index 000000000..cd9387eb5 --- /dev/null +++ b/tests/sbin/route/t_missing.sh @@ -0,0 +1,45 @@ +# $NetBSD: t_missing.sh,v 1.3 2012/03/17 08:34:55 jruoho Exp $ +# +# Copyright (c) 2011 The NetBSD Foundation, Inc. +# All rights reserved. +# +# This code is derived from software contributed to The NetBSD Foundation +# by Jukka Ruohonen. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +atf_test_case missing +missing_head() { + atf_set "descr" "Check route(8) with a missing argument (PR bin/42179)" +} + +missing_body() { + + atf_check -s exit:1 \ + -e not-inline:"route: writing to routing socket: Invalid argument\n" \ + route -n get +} + +atf_init_test_cases() { + atf_add_test_case missing +} diff --git a/tests/sbin/sysctl/Makefile b/tests/sbin/sysctl/Makefile new file mode 100644 index 000000000..c137c7b24 --- /dev/null +++ b/tests/sbin/sysctl/Makefile @@ -0,0 +1,9 @@ +# $NetBSD: Makefile,v 1.2 2012/04/10 02:39:33 jruoho Exp $ + +.include + +TESTSDIR= ${TESTSBASE}/sbin/sysctl + +TESTS_SH= t_perm t_sysctl + +.include diff --git a/tests/sbin/sysctl/t_perm.sh b/tests/sbin/sysctl/t_perm.sh new file mode 100644 index 000000000..6acfd1935 --- /dev/null +++ b/tests/sbin/sysctl/t_perm.sh @@ -0,0 +1,209 @@ +# $NetBSD: t_perm.sh,v 1.6 2012/03/18 09:46:50 jruoho Exp $ +# +# Copyright (c) 2011 The NetBSD Foundation, Inc. +# All rights reserved. +# +# This code is derived from software contributed to The NetBSD Foundation +# by Jukka Ruohonen. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +file="/tmp/d_sysctl.out" + +clean() { + + if [ -f $file ]; then + rm $file + fi +} + +sysctl_write() { + + deadbeef="3735928559" + + sysctl $1 | cut -d= -f1 > $file + + if [ ! -f $file ]; then + atf_fail "sysctl failed" + fi + + while read line; do + + node=$(echo $line) + + case $node in + + "$1."*) + atf_check -s not-exit:0 -e ignore \ + -x sysctl -w $node=$deadbeef + ;; + esac + + done < $file + + # A functional verification that $deadbeef + # was not actually written to the node. + # + if [ ! -z $(sysctl $1 | grep $deadbeef) ]; then + atf_fail "value was written" + fi +} + +# ddb. +# +atf_test_case sysctl_ddb cleanup +sysctl_ddb_head() { + atf_set "require.user" "unprivileged" + atf_set "descr" "Test writing to 'ddb' sysctl node as an user" +} + +sysctl_ddb_body() { + sysctl_write "ddb" +} + +sysctl_ddb_cleanup() { + clean +} + +# hw. +# +atf_test_case sysctl_hw cleanup +sysctl_hw_head() { + atf_set "require.user" "unprivileged" + atf_set "descr" "Test writing to 'hw' sysctl node as an user" +} + +sysctl_hw_body() { + sysctl_write "hw" +} + +sysctl_hw_cleanup() { + clean +} + +# kern. +# +atf_test_case sysctl_kern cleanup +sysctl_kern_head() { + atf_set "require.user" "unprivileged" + atf_set "descr" "Test writing to 'kern' " \ + "sysctl node as an user (PR kern/44946)" +} + +sysctl_kern_body() { + sysctl_write "kern" +} + +sysctl_kern_cleanup() { + clean +} + +# machdep. +# +atf_test_case sysctl_machdep cleanup +sysctl_machdep_head() { + atf_set "require.user" "unprivileged" + atf_set "descr" "Test writing to 'machdep' sysctl node as an user" +} + +sysctl_machdep_body() { + sysctl_write "machdep" +} + +sysctl_machdep_cleanup() { + clean +} + +# net. +# +atf_test_case sysctl_net cleanup +sysctl_net_head() { + atf_set "require.user" "unprivileged" + atf_set "descr" "Test writing to 'net' sysctl node as an user" +} + +sysctl_net_body() { + sysctl_write "net" +} + +sysctl_net_cleanup() { + clean +} + +# security. +# +atf_test_case sysctl_security cleanup +sysctl_security_head() { + atf_set "require.user" "unprivileged" + atf_set "descr" "Test writing to 'security' sysctl node as an user" +} + +sysctl_security_body() { + sysctl_write "security" +} + +sysctl_security_cleanup() { + clean +} + +# vfs. +# +atf_test_case sysctl_vfs cleanup +sysctl_vfs_head() { + atf_set "require.user" "unprivileged" + atf_set "descr" "Test writing to 'vfs' sysctl node as an user" +} + +sysctl_vfs_body() { + sysctl_write "vfs" +} + +sysctl_vfs_cleanup() { + clean +} + +# vm. +# +atf_test_case sysctl_vm cleanup +sysctl_vm_head() { + atf_set "require.user" "unprivileged" + atf_set "descr" "Test writing to 'vm' sysctl node as an user" +} + +sysctl_vm_body() { + sysctl_write "vm" +} + +sysctl_vm_cleanup() { + clean +} + +atf_init_test_cases() { + atf_add_test_case sysctl_ddb + atf_add_test_case sysctl_hw + atf_add_test_case sysctl_kern + atf_add_test_case sysctl_machdep + atf_add_test_case sysctl_net + atf_add_test_case sysctl_security + atf_add_test_case sysctl_vfs + atf_add_test_case sysctl_vm +} diff --git a/tests/sbin/sysctl/t_sysctl.sh b/tests/sbin/sysctl/t_sysctl.sh new file mode 100644 index 000000000..e92c36e2c --- /dev/null +++ b/tests/sbin/sysctl/t_sysctl.sh @@ -0,0 +1,44 @@ +# $NetBSD: t_sysctl.sh,v 1.1 2012/04/10 02:39:33 jruoho Exp $ +# +# Copyright (c) 2012 The NetBSD Foundation, Inc. +# All rights reserved. +# +# This code is derived from software contributed to The NetBSD Foundation +# by Jukka Ruohonen. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +atf_test_case basic +basic_head() { + atf_set "descr" "Test that sysctl(8) works" +} + +basic_body() { + + atf_check -s exit:0 -o ignore -e empty -x "sysctl -a" +} + +atf_init_test_cases() { + + atf_add_test_case basic +} diff --git a/tests/share/Makefile b/tests/share/Makefile new file mode 100644 index 000000000..2ee4306c5 --- /dev/null +++ b/tests/share/Makefile @@ -0,0 +1,9 @@ +# $NetBSD: Makefile,v 1.2 2013/02/16 12:44:26 jmmv Exp $ + +.include + +TESTSDIR= ${TESTSBASE}/share + +TESTS_SUBDIRS= examples mk + +.include diff --git a/tests/share/examples/Makefile b/tests/share/examples/Makefile new file mode 100644 index 000000000..ca808708d --- /dev/null +++ b/tests/share/examples/Makefile @@ -0,0 +1,15 @@ +# $NetBSD: Makefile,v 1.2 2013/02/16 21:40:07 jmmv Exp $ + +.include + +TESTSDIR= ${TESTSBASE}/share/examples + +TESTS_SH= t_asm + +.if ${MKKYUA} != "no" +# These examples come from external/bsd/lutok/tests/share/examples/lutok. +# Ensure they get registered in the Atffile only when installed. +ATFFILE_EXTRA_TPS= lutok +.endif + +.include diff --git a/tests/share/examples/t_asm.sh b/tests/share/examples/t_asm.sh new file mode 100644 index 000000000..f615935fa --- /dev/null +++ b/tests/share/examples/t_asm.sh @@ -0,0 +1,74 @@ +# $NetBSD: t_asm.sh,v 1.1 2013/02/16 12:44:26 jmmv Exp $ +# +# Copyright (c) 2011 The NetBSD Foundation, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +# check_implemented +# +# Verifies if a particular asm example is implemented for the current +# platform. The example_name argument is the name of the subdirectory +# of the examples/asm/ subtree that includes the code for the example +# under test. +# +# If the example is not implemented, the calling test is skipped. If the +# check for implementation fails, the calling test is failed. +check_implemented() { + local name="${1}"; shift + + local implemented=$(cd /usr/share/examples/asm/${name}/ && \ + make check-implemented) + [ $? -eq 0 ] || atf_fail "Failed to determine if the sample" \ + "program is supported" + [ "${implemented}" = yes ] || atf_skip "Example program not" \ + "implemented on this platform" +} + +# copy_example +# +# Copies the example code and supporting Makefiles into the current +# directory. +copy_example() { + local name="${1}"; shift + + cp /usr/share/examples/asm/${name}/* . +} + +atf_test_case hello +hello_head() { + atf_set "descr" "Builds, runs and validates the 'hello' asm example" + atf_set "require.files" "/usr/share/examples/asm/hello/" + atf_set "require.progs" "make" +} +hello_body() { + check_implemented hello + copy_example hello + atf_check -s exit:0 -o ignore -e ignore make + atf_check -s exit:0 -o inline:'Hello, world!\n' -e empty ./hello +} + +atf_init_test_cases() { + atf_add_test_case hello +} diff --git a/tests/share/mk/Makefile b/tests/share/mk/Makefile new file mode 100644 index 000000000..46bded6dd --- /dev/null +++ b/tests/share/mk/Makefile @@ -0,0 +1,12 @@ +# $NetBSD: Makefile,v 1.1 2012/08/26 23:03:21 jmmv Exp $ + +.include + +TESTSDIR= ${TESTSBASE}/share/mk + +TESTS_SH= t_lib t_own t_prog t_test +.for test in ${TESTS_SH} +TESTS_SH_SRC_${test}= ${test}.sh common.subr +.endfor + +.include diff --git a/tests/share/mk/common.subr b/tests/share/mk/common.subr new file mode 100644 index 000000000..0b542feea --- /dev/null +++ b/tests/share/mk/common.subr @@ -0,0 +1,132 @@ +# Copyright 2012 Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Google Inc. nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# Dumps a file to the test's stdout for debugging purposes. +dump_file() { + local file="${1}"; shift + + echo "==== BEGIN ${file}" + cat "${file}" + echo "==== END ${file}" +} + +# Creates a C source file with a single symbol in it. +# +# The file parameter specifies the path to the file to create, WITHOUT the +# C extension. Both a source file and a header file are created. Any +# intermediate directories are created too. +# +# The symbol parameter specifies the name of the symbol to place in the +# module, which is defined as a string holding the name of the module. +create_c_module() { + local file="${1}"; shift + local symbol="${1}"; shift + + mkdir -p "$(dirname ${file})" + echo "extern const char *${symbol};" >"${file}.h" + echo "const char *${symbol} = \"${file}\";" >"${file}.c" + + dump_file "${file}.h" + dump_file "${file}.c" +} + +# Creates a main C source file that references a set of modules. +# +# The modules to be referenced should have been created with +# create_c_module. The generated source file ensures that all the modules +# are referenced in some way, which helps in testing that the generated +# binary holds all the necessary objects. +# +# The file parameter specifies the name of the file to create. +# +# The rest of the parameters are module:symbol pairs that specify the +# module to include and the symbol within them to reference. +create_main_using_modules() { + local file="${1}"; shift + + local modules= + local symbols= + for spec in "${@}"; do + modules="${modules} $(echo ${spec} | cut -d : -f 1)" + symbols="${symbols} $(echo ${spec} | cut -d : -f 2)" + done + + echo '#include ' >"${file}" + for module in ${modules}; do + echo "#include \"${module}\"" >>"${file}" + done + echo 'int main(void) {' >>"${file}" + for symbol in ${symbols}; do + echo "printf(\"%s\n\", ${symbol});" >>"${file}" + done + echo 'return 0; }' >>"${file}" + + dump_file "${file}" +} + +# Creates a mk.conf file and points MAKECONF to it. +# +# The first argument specifies the name of the configuration file to +# create. +# +# The rest of the arguments include a collection of modifiers for the +# generated configuration file and/or a collection of explicit variable +# names and their values to set. +# +# The qualifiers can be one of: +# - owngrp: Override the *OWN and *GRP variables to point to the current +# user. +create_make_conf() { + local file="${1}"; shift + + echo "# Test configuration file" >"${file}" + for arg in "${@}"; do + case "${arg}" in + *=*) + echo "${arg}" >>"${file}" + ;; + owngrp) + for class in BIN DOC LIB LINKS MAN; do + echo "${class}OWN=$(id -un)" >>"${file}" + echo "${class}GRP=$(id -gn)" >>"${file}" + done + ;; + esac + done + + case "${file}" in + /*) + MAKECONF="${file}"; export MAKECONF + ;; + *) + MAKECONF="$(pwd)/${file}"; export MAKECONF + ;; + esac + + dump_file "${file}" +} diff --git a/tests/share/mk/t_lib.sh b/tests/share/mk/t_lib.sh new file mode 100644 index 000000000..5f18e14a5 --- /dev/null +++ b/tests/share/mk/t_lib.sh @@ -0,0 +1,54 @@ +# Copyright 2012 Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Google Inc. nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +atf_test_case defaults__build_and_install +defaults__build_and_install_body() { + create_c_module module1 first + create_c_module module2 second + + cat >Makefile < +EOF + + atf_check -o ignore make + mkdir -p root/usr/lib + mkdir -p root/usr/libdata/lint + create_make_conf mk.conf owngrp DESTDIR="$(pwd)/root" + atf_check -o ignore make install + + create_main_using_modules main.c module1.h:first module2.h:second + atf_check -o ignore gcc -I. -Lroot/usr/lib -o main main.c -ltwo-modules + + atf_check -o inline:'module1\nmodule2\n' ./main +} + +atf_init_test_cases() { + atf_add_test_case defaults__build_and_install +} diff --git a/tests/share/mk/t_own.sh b/tests/share/mk/t_own.sh new file mode 100644 index 000000000..7372dd2fe --- /dev/null +++ b/tests/share/mk/t_own.sh @@ -0,0 +1,72 @@ +# Copyright 2012 Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Google Inc. nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +atf_test_case makeconf__ok +makeconf__ok_body() { + cat >Makefile < +EOF + + echo >empty.conf + cat >custom.conf <Makefile < +EOF + + echo >empty.conf + cat >custom.conf <hello.c < +int main(void) { printf("Hello, test!\n"); return 0; } +EOF + cat >hello.1 <Makefile < +EOF + + atf_check -o ignore make + mkdir -p root/the/bin/dir + mkdir -p root/usr/share/man/man1 + mkdir -p root/usr/share/man/html1 + create_make_conf mk.conf owngrp DESTDIR="$(pwd)/root" + atf_check -o ignore make install + + atf_check -o inline:'Hello, test!\n' ./root/the/bin/dir/hello + atf_check -o inline:'Manpage of hello(1).\n' \ + cat root/usr/share/man/man1/hello.1 + atf_check -o match:'Manpage of hello' \ + cat root/usr/share/man/html1/hello.html +} + +atf_test_case without_man__build_and_install +without_man__build_and_install_body() { + cat >hello.c < +int main(void) { printf("Hello, test!\n"); return 0; } +EOF + + cat >Makefile < +EOF + + atf_check -o ignore make + mkdir -p root/the/bin/dir + create_make_conf mk.conf owngrp DESTDIR="$(pwd)/root" + atf_check -o ignore make install + + atf_check -o inline:'Hello, test!\n' ./root/the/bin/dir/hello +} + +atf_init_test_cases() { + atf_add_test_case defaults__build_and_install + atf_add_test_case without_man__build_and_install +} diff --git a/tests/share/mk/t_test.sh b/tests/share/mk/t_test.sh new file mode 100644 index 000000000..c8bb1f3d8 --- /dev/null +++ b/tests/share/mk/t_test.sh @@ -0,0 +1,111 @@ +# Copyright 2012 Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Google Inc. nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# Helper function for the various one_* test cases. +# +# The first argument must be one of C, CXX or SH, and this indicates the +# language of the test program. +# +# The second argument is the name of the test program, without an extension. +# The corresponding source file must exist in the current directory. +one_test() { + local lang="${1}"; shift + local name="${1}"; shift + + cat >Makefile < +TESTSDIR = \${TESTSBASE}/fake +TESTS_${lang} = ${name} +.include +EOF + + atf_check -o ignore make + mkdir -p root/usr/tests/fake + create_make_conf mk.conf owngrp DESTDIR="$(pwd)/root" + atf_check -o ignore make install + + atf_check -o match:'ident: one_tc' "./root/usr/tests/fake/${name}" -l +} + +atf_test_case one_c +one_c_body() { + cat >t_fake.c < +ATF_TC_WITHOUT_HEAD(one_tc); +ATF_TC_BODY(one_tc, tc) +{ + atf_tc_fail("Failing explicitly"); +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, one_tc); + return atf_no_error(); +} +EOF + one_test C t_fake +} + +atf_test_case one_cxx +one_cxx_body() { + cat >t_fake.cpp < +ATF_TEST_CASE_WITHOUT_HEAD(one_tc); +ATF_TEST_CASE_BODY(one_tc) +{ + fail("Failing explicitly"); +} + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, one_tc); +} +EOF + one_test CXX t_fake +} + +atf_test_case one_sh +one_sh_body() { + cat >t_fake.sh < + +TESTSDIR= ${TESTSBASE}/sys + +TESTS_SUBDIRS+= rc + +.include diff --git a/tests/sys/rc/Makefile b/tests/sys/rc/Makefile new file mode 100644 index 000000000..871723e83 --- /dev/null +++ b/tests/sys/rc/Makefile @@ -0,0 +1,13 @@ +# $NetBSD: Makefile,v 1.2 2010/07/13 21:13:30 jmmv Exp $ + +.include + +TESTSDIR= ${TESTSBASE}/sys/rc + +TESTS_SH= t_rc_d_cli + +SCRIPTSDIR= ${TESTSDIR} +SCRIPTS= h_args.sh \ + h_simple.sh + +.include diff --git a/tests/sys/rc/h_args.sh b/tests/sys/rc/h_args.sh new file mode 100644 index 000000000..2b03f294b --- /dev/null +++ b/tests/sys/rc/h_args.sh @@ -0,0 +1,64 @@ +#! /bin/sh +# +# $NetBSD: h_args.sh,v 1.1 2010/03/15 19:03:08 jmmv Exp $ +# +# Copyright (c) 2010 The NetBSD Foundation, Inc. +# All rights reserved. +# +# This code is derived from software contributed to The NetBSD Foundation +# by Julio Merino. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +# +# An rc.d script that overrides all standard comands and adds a non-standard +# command. All of them print the set of arguments passed to them and take no +# further action. +# + +${_rc_subr_loaded} . /etc/rc.subr + +name="h_args" +rcvar="${name}" +command="/usr/bin/true" +extra_commands="custom" + +for command in start stop restart custom; do + eval ${command}_precmd=\'print_args pre${command}\' + eval ${command}_cmd=\'print_args ${command}\' + eval ${command}_postcmd=\'print_args post${command}\' +done + +print_args() { + local command="${1}"; shift + + printf "${command}:" + while [ ${#} -gt 0 ]; do + printf " >%s<" "${1}" + shift + done + printf ".\n" +} + +load_rc_config "${name}" +run_rc_command "${@}" diff --git a/tests/sys/rc/h_simple.sh b/tests/sys/rc/h_simple.sh new file mode 100644 index 000000000..4ed62a7f6 --- /dev/null +++ b/tests/sys/rc/h_simple.sh @@ -0,0 +1,45 @@ +#! /bin/sh +# +# $NetBSD: h_simple.sh,v 1.1 2010/03/15 19:03:08 jmmv Exp $ +# +# Copyright (c) 2010 The NetBSD Foundation, Inc. +# All rights reserved. +# +# This code is derived from software contributed to The NetBSD Foundation +# by Julio Merino. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +# +# A very simple rc.d script that defines the minimum variables to be functional. +# + +${_rc_subr_loaded} . /etc/rc.subr + +name="h_simple" +rcvar="${name}" +command="/bin/sleep" +command_args="300 &" + +load_rc_config "${name}" +run_rc_command "${@}" diff --git a/tests/sys/rc/t_rc_d_cli.sh b/tests/sys/rc/t_rc_d_cli.sh new file mode 100644 index 000000000..d97f8cca6 --- /dev/null +++ b/tests/sys/rc/t_rc_d_cli.sh @@ -0,0 +1,250 @@ +# $NetBSD: t_rc_d_cli.sh,v 1.4 2010/11/07 17:51:21 jmmv Exp $ +# +# Copyright (c) 2010 The NetBSD Foundation, Inc. +# All rights reserved. +# +# This code is derived from software contributed to The NetBSD Foundation +# by Julio Merino. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +atf_test_case no_command +no_command_head() { + atf_set "descr" "Tests that the lack of a command errors out" +} +no_command_body() { + export h_simple=YES + rc_helper=$(atf_get_srcdir)/h_simple + + atf_check -s eq:1 -o empty -e ignore ${rc_helper} +} + +atf_test_case default_start_no_args +default_start_no_args_head() { + atf_set "descr" "Tests that running the default 'start' without" \ + "arguments does not error out" +} +default_start_no_args_body() { + export h_simple=YES + rc_helper=$(atf_get_srcdir)/h_simple + + atf_check -s eq:0 -o ignore -e empty ${rc_helper} start + ${rc_helper} forcestop +} + +atf_test_case default_start_with_args +default_start_with_args_head() { + atf_set "descr" "Tests that running the default 'start' with" \ + "arguments errors out" +} +default_start_with_args_body() { + export h_simple=YES + rc_helper=$(atf_get_srcdir)/h_simple + + atf_check -s eq:1 -o ignore -e ignore ${rc_helper} start foo + if ${rc_helper} status >/dev/null; then + ${rc_helper} forcestop + atf_fail 'extra argument to start did not error out' + fi +} + +atf_test_case default_stop_no_args +default_stop_no_args_head() { + atf_set "descr" "Tests that running the default 'stop' without" \ + "arguments does not error out" +} +default_stop_no_args_body() { + export h_simple=YES + rc_helper=$(atf_get_srcdir)/h_simple + + ${rc_helper} start + atf_check -s eq:0 -o ignore -e empty ${rc_helper} stop +} + +atf_test_case default_stop_with_args +default_stop_with_args_head() { + atf_set "descr" "Tests that running the default 'stop' with" \ + "arguments errors out" +} +default_stop_with_args_body() { + export h_simple=YES + rc_helper=$(atf_get_srcdir)/h_simple + + ${rc_helper} start + atf_check -s eq:1 -o ignore -e ignore ${rc_helper} stop foo + if ${rc_helper} status >/dev/null; then + ${rc_helper} forcestop + else + atf_fail 'extra argument to stop did not error out' + fi +} + +atf_test_case default_restart_no_args +default_restart_no_args_head() { + atf_set "descr" "Tests that running the default 'restart' without" \ + "arguments does not error out" +} +default_restart_no_args_body() { + export h_simple=YES + rc_helper=$(atf_get_srcdir)/h_simple + + ${rc_helper} start + atf_check -s eq:0 -o ignore -e empty ${rc_helper} restart + ${rc_helper} forcestop +} + +atf_test_case default_restart_with_args +default_restart_with_args_head() { + atf_set "descr" "Tests that running the default 'restart' with" \ + "arguments errors out" +} +default_restart_with_args_body() { + export h_simple=YES + rc_helper=$(atf_get_srcdir)/h_simple + + ${rc_helper} start + atf_check -s eq:1 -o ignore -e ignore ${rc_helper} restart foo + ${rc_helper} forcestop +} + +do_overriden_no_args() { + local command="${1}"; shift + + export h_args=YES + rc_helper=$(atf_get_srcdir)/h_args + + cat >expout <expout <arg1< > arg 2 < >arg3< >*<. +post${command}:. +EOF + atf_check -s eq:0 -o file:expout -e empty ${rc_helper} ${command} \ + 'arg1' ' arg 2 ' 'arg3' '*' +} + +atf_test_case overriden_start_no_args +overriden_start_no_args_head() { + atf_set "descr" "Tests that running a custom 'start' without" \ + "arguments does not pass any parameters to the command" +} +overriden_start_no_args_body() { + do_overriden_no_args start +} + +atf_test_case overriden_start_with_args +overriden_start_with_args_head() { + atf_set "descr" "Tests that running a custom 'start' with" \ + "arguments passes those arguments as parameters to the command" +} +overriden_start_with_args_body() { + do_overriden_with_args start +} + +atf_test_case overriden_stop_no_args +overriden_stop_no_args_head() { + atf_set "descr" "Tests that running a custom 'stop' without" \ + "arguments does not pass any parameters to the command" +} +overriden_stop_no_args_body() { + do_overriden_no_args stop +} + +atf_test_case overriden_stop_with_args +overriden_stop_with_args_head() { + atf_set "descr" "Tests that running a custom 'stop' with" \ + "arguments passes those arguments as parameters to the command" +} +overriden_stop_with_args_body() { + do_overriden_with_args stop +} + +atf_test_case overriden_restart_no_args +overriden_restart_no_args_head() { + atf_set "descr" "Tests that running a custom 'restart' without" \ + "arguments does not pass any parameters to the command" +} +overriden_restart_no_args_body() { + do_overriden_no_args restart +} + +atf_test_case overriden_restart_with_args +overriden_restart_with_args_head() { + atf_set "descr" "Tests that running a custom 'restart' with" \ + "arguments passes those arguments as parameters to the command" +} +overriden_restart_with_args_body() { + do_overriden_with_args restart +} + +atf_test_case overriden_custom_no_args +overriden_custom_no_args_head() { + atf_set "descr" "Tests that running a custom command without" \ + "arguments does not pass any parameters to the command" +} +overriden_custom_no_args_body() { + do_overriden_no_args custom +} + +atf_test_case overriden_custom_with_args +overriden_custom_with_args_head() { + atf_set "descr" "Tests that running a custom command with" \ + "arguments passes those arguments as parameters to the command" +} +overriden_custom_with_args_body() { + do_overriden_with_args custom +} + +atf_init_test_cases() +{ + atf_add_test_case no_command + + atf_add_test_case default_start_no_args + atf_add_test_case default_start_with_args + atf_add_test_case default_stop_no_args + atf_add_test_case default_stop_with_args + atf_add_test_case default_restart_no_args + atf_add_test_case default_restart_with_args + + atf_add_test_case overriden_start_no_args + atf_add_test_case overriden_start_with_args + atf_add_test_case overriden_stop_no_args + atf_add_test_case overriden_stop_with_args + atf_add_test_case overriden_restart_no_args + atf_add_test_case overriden_restart_with_args + atf_add_test_case overriden_custom_no_args + atf_add_test_case overriden_custom_with_args +} diff --git a/tests/usr.bin/Makefile b/tests/usr.bin/Makefile new file mode 100644 index 000000000..51336563a --- /dev/null +++ b/tests/usr.bin/Makefile @@ -0,0 +1,13 @@ +# $NetBSD: Makefile,v 1.17 2012/11/20 08:02:06 agc Exp $ +# + +.include + +TESTSDIR= ${TESTSBASE}/usr.bin + +TESTS_SUBDIRS= awk basename bzip2 cc cmp config cut \ + diff dirname find grep gzip id infocmp jot m4 make mkdep \ + nbperf netpgpverify pr rump_server shmif_dumpbus sdiff \ + sed sort tmux unifdef xlint + +.include diff --git a/tests/usr.bin/awk/Makefile b/tests/usr.bin/awk/Makefile new file mode 100644 index 000000000..8a3a43f54 --- /dev/null +++ b/tests/usr.bin/awk/Makefile @@ -0,0 +1,34 @@ +# $NetBSD: Makefile,v 1.2 2012/03/11 18:35:59 jruoho Exp $ + +.include + +TESTSDIR= ${TESTSBASE}/usr.bin/awk +TESTS_SH= t_awk +NOMAN= # defined + +FILESDIR= ${TESTSDIR} +FILES= d_big_regexp.awk +FILES+= d_big_regexp.in +FILES+= d_big_regexp.out +FILES+= d_end1.awk +FILES+= d_end1.in +FILES+= d_end1.out +FILES+= d_end2.awk +FILES+= d_end2.in +FILES+= d_end2.out +FILES+= d_period.awk +FILES+= d_period.in +FILES+= d_period.out +FILES+= d_string1.awk +FILES+= d_string1.out +FILES+= d_tolower.awk +FILES+= d_tolower.in +FILES+= d_tolower.out +FILES+= d_toupper.awk +FILES+= d_toupper.in +FILES+= d_toupper.out +FILES+= d_assign_NF.awk +FILES+= d_assign_NF.in +FILES+= d_assign_NF.out + +.include \ No newline at end of file diff --git a/tests/usr.bin/awk/d_assign_NF.awk b/tests/usr.bin/awk/d_assign_NF.awk new file mode 100644 index 000000000..52c39124c --- /dev/null +++ b/tests/usr.bin/awk/d_assign_NF.awk @@ -0,0 +1,16 @@ +# $NetBSD: d_assign_NF.awk,v 1.1 2012/03/11 18:35:59 jruoho Exp $ + +{ + NF = 2 + print "$0=`" $0 "`" + print "$3=`" $3 "`" + print "$4=`" $4 "`" + NF = 3 + print "$0=`" $0 "`" + print "$3=`" $3 "`" + print "$4=`" $4 "`" + NF = 4 + print "$0=`" $0 "`" + print "$3=`" $3 "`" + print "$4=`" $4 "`" +} diff --git a/tests/usr.bin/awk/d_assign_NF.in b/tests/usr.bin/awk/d_assign_NF.in new file mode 100644 index 000000000..1245b9221 --- /dev/null +++ b/tests/usr.bin/awk/d_assign_NF.in @@ -0,0 +1 @@ + 1 2 3 diff --git a/tests/usr.bin/awk/d_assign_NF.out b/tests/usr.bin/awk/d_assign_NF.out new file mode 100644 index 000000000..2631a7a92 --- /dev/null +++ b/tests/usr.bin/awk/d_assign_NF.out @@ -0,0 +1,9 @@ +$0=`1 2` +$3=`` +$4=`` +$0=`1 2 ` +$3=`` +$4=`` +$0=`1 2 ` +$3=`` +$4=`` diff --git a/tests/usr.bin/awk/d_big_regexp.awk b/tests/usr.bin/awk/d_big_regexp.awk new file mode 100644 index 000000000..1502b5e75 --- /dev/null +++ b/tests/usr.bin/awk/d_big_regexp.awk @@ -0,0 +1,3 @@ +# $NetBSD: d_big_regexp.awk,v 1.1 2012/03/11 18:36:00 jruoho Exp $ + +/^[^_][^ ]*_NNIFO([ ]+[^_]+[^ ]*_(CC|INR|JJFO|JJMA|JJPG|NNIFG|NNIFO|NNIMPG|NNIMR|NNING|PP3FD|PQINO|PQMO|PSFR|RQ|TC|VIIR3|VPIPN|VPLIPF|NOTAG|RQR))*$/ diff --git a/tests/usr.bin/awk/d_big_regexp.in b/tests/usr.bin/awk/d_big_regexp.in new file mode 100644 index 000000000..ad82078af --- /dev/null +++ b/tests/usr.bin/awk/d_big_regexp.in @@ -0,0 +1 @@ +1_NNIFO 1_PSFR 1_JJFO 1_NNIFO 1_INR 1_NNIMR 1_CC 1_NNING 1_RQ 1_VPLIPF 1_NNIFG 1_JJPG 1_NNIMPG 1_PQINO 1_VPIPN 1_PP3FD 1_JJMA 1_PQMO 1_TC 1_VIIR3 diff --git a/tests/usr.bin/awk/d_big_regexp.out b/tests/usr.bin/awk/d_big_regexp.out new file mode 100644 index 000000000..ad82078af --- /dev/null +++ b/tests/usr.bin/awk/d_big_regexp.out @@ -0,0 +1 @@ +1_NNIFO 1_PSFR 1_JJFO 1_NNIFO 1_INR 1_NNIMR 1_CC 1_NNING 1_RQ 1_VPLIPF 1_NNIFG 1_JJPG 1_NNIMPG 1_PQINO 1_VPIPN 1_PP3FD 1_JJMA 1_PQMO 1_TC 1_VIIR3 diff --git a/tests/usr.bin/awk/d_end1.awk b/tests/usr.bin/awk/d_end1.awk new file mode 100644 index 000000000..cb8b0d0ed --- /dev/null +++ b/tests/usr.bin/awk/d_end1.awk @@ -0,0 +1,5 @@ +# $NetBSD: d_end1.awk,v 1.1 2012/03/11 18:36:00 jruoho Exp $ + +END { + print NF; +} diff --git a/tests/usr.bin/awk/d_end1.in b/tests/usr.bin/awk/d_end1.in new file mode 100644 index 000000000..8e13e468a --- /dev/null +++ b/tests/usr.bin/awk/d_end1.in @@ -0,0 +1 @@ +a b c d diff --git a/tests/usr.bin/awk/d_end1.out b/tests/usr.bin/awk/d_end1.out new file mode 100644 index 000000000..b8626c4cf --- /dev/null +++ b/tests/usr.bin/awk/d_end1.out @@ -0,0 +1 @@ +4 diff --git a/tests/usr.bin/awk/d_end2.awk b/tests/usr.bin/awk/d_end2.awk new file mode 100644 index 000000000..8b10b8287 --- /dev/null +++ b/tests/usr.bin/awk/d_end2.awk @@ -0,0 +1,5 @@ +# $NetBSD: d_end2.awk,v 1.1 2012/03/11 18:36:00 jruoho Exp $ + +END { + print $0; +} diff --git a/tests/usr.bin/awk/d_end2.in b/tests/usr.bin/awk/d_end2.in new file mode 100644 index 000000000..8e13e468a --- /dev/null +++ b/tests/usr.bin/awk/d_end2.in @@ -0,0 +1 @@ +a b c d diff --git a/tests/usr.bin/awk/d_end2.out b/tests/usr.bin/awk/d_end2.out new file mode 100644 index 000000000..8e13e468a --- /dev/null +++ b/tests/usr.bin/awk/d_end2.out @@ -0,0 +1 @@ +a b c d diff --git a/tests/usr.bin/awk/d_period.awk b/tests/usr.bin/awk/d_period.awk new file mode 100644 index 000000000..d1dabf751 --- /dev/null +++ b/tests/usr.bin/awk/d_period.awk @@ -0,0 +1 @@ +{print x + $1 + 0.125} diff --git a/tests/usr.bin/awk/d_period.in b/tests/usr.bin/awk/d_period.in new file mode 100644 index 000000000..d10c0e2f9 --- /dev/null +++ b/tests/usr.bin/awk/d_period.in @@ -0,0 +1 @@ +0,25 diff --git a/tests/usr.bin/awk/d_period.out b/tests/usr.bin/awk/d_period.out new file mode 100644 index 000000000..3382aa6e3 --- /dev/null +++ b/tests/usr.bin/awk/d_period.out @@ -0,0 +1 @@ +0.625 diff --git a/tests/usr.bin/awk/d_string1.awk b/tests/usr.bin/awk/d_string1.awk new file mode 100644 index 000000000..d690240fa --- /dev/null +++ b/tests/usr.bin/awk/d_string1.awk @@ -0,0 +1,7 @@ +# $NetBSD: d_string1.awk,v 1.1 2012/03/11 18:36:00 jruoho Exp $ + +BEGIN { + print "A\ +B"; + print "CD" +} diff --git a/tests/usr.bin/awk/d_string1.out b/tests/usr.bin/awk/d_string1.out new file mode 100644 index 000000000..96c017b97 --- /dev/null +++ b/tests/usr.bin/awk/d_string1.out @@ -0,0 +1,2 @@ +AB +CD diff --git a/tests/usr.bin/awk/d_tolower.awk b/tests/usr.bin/awk/d_tolower.awk new file mode 100644 index 000000000..258d181ce --- /dev/null +++ b/tests/usr.bin/awk/d_tolower.awk @@ -0,0 +1,5 @@ +# $NetBSD: d_tolower.awk,v 1.1 2012/03/11 18:36:00 jruoho Exp $ + +END { + print tolower($0); +} diff --git a/tests/usr.bin/awk/d_tolower.in b/tests/usr.bin/awk/d_tolower.in new file mode 100644 index 000000000..66ed03c2d --- /dev/null +++ b/tests/usr.bin/awk/d_tolower.in @@ -0,0 +1 @@ +ABCÆØÅ diff --git a/tests/usr.bin/awk/d_tolower.out b/tests/usr.bin/awk/d_tolower.out new file mode 100644 index 000000000..83b2bf51c --- /dev/null +++ b/tests/usr.bin/awk/d_tolower.out @@ -0,0 +1 @@ +abcæøå diff --git a/tests/usr.bin/awk/d_toupper.awk b/tests/usr.bin/awk/d_toupper.awk new file mode 100644 index 000000000..0719aa9b8 --- /dev/null +++ b/tests/usr.bin/awk/d_toupper.awk @@ -0,0 +1,5 @@ +# $NetBSD: d_toupper.awk,v 1.1 2012/03/11 18:36:01 jruoho Exp $ + +END { + print toupper($0); +} diff --git a/tests/usr.bin/awk/d_toupper.in b/tests/usr.bin/awk/d_toupper.in new file mode 100644 index 000000000..83b2bf51c --- /dev/null +++ b/tests/usr.bin/awk/d_toupper.in @@ -0,0 +1 @@ +abcæøå diff --git a/tests/usr.bin/awk/d_toupper.out b/tests/usr.bin/awk/d_toupper.out new file mode 100644 index 000000000..66ed03c2d --- /dev/null +++ b/tests/usr.bin/awk/d_toupper.out @@ -0,0 +1 @@ +ABCÆØÅ diff --git a/tests/usr.bin/awk/t_awk.sh b/tests/usr.bin/awk/t_awk.sh new file mode 100644 index 000000000..77cb5f86d --- /dev/null +++ b/tests/usr.bin/awk/t_awk.sh @@ -0,0 +1,378 @@ +# $NetBSD: t_awk.sh,v 1.5 2012/12/10 20:30:06 christos Exp $ +# +# Copyright (c) 2012 The NetBSD Foundation, Inc. +# All rights reserved. +# +# This code is derived from software contributed to The NetBSD Foundation +# by Christos Zoulas +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +awk=awk + +h_check() +{ + local fname=d_$1 + for sfx in in out awk; do + cp -r $(atf_get_srcdir)/$fname.$sfx . + done + shift 1 + atf_check -o file:$fname.out -x "awk $@ -f $fname.awk < $fname.in" +} + +atf_test_case big_regexp + +big_regexp_head() { + atf_set "descr" "Checks matching long regular expressions (PR/33392)" +} + +big_regexp_body() { + h_check big_regexp +} + +atf_test_case end + +end_head() { + atf_set "descr" "Checks that the last line of the input" \ + "is available under END pattern (PR/29659)" +} + +end_body() { + h_check end1 + h_check end2 +} + +atf_test_case string1 + +string1_head() { + atf_set "descr" "Checks escaping newlines in string literals" +} + +string1_body() { + for sfx in out awk; do + cp -r $(atf_get_srcdir)/d_string1.$sfx . + done + atf_check -o file:d_string1.out awk -f d_string1.awk +} + +atf_test_case multibyte + +multibyte_head() { + atf_set "descr" "Checks multibyte charsets support" \ + "in tolower and toupper (PR/36394)" +} + +multibyte_body() { + export LANG=en_US.UTF-8 + + h_check tolower + h_check toupper +} + +atf_test_case period + +period_head() { + atf_set "descr" "Checks that the period character is recognised" \ + "in awk program regardless of locale (bin/42320)" +} + +period_body() { + export LANG=ru_RU.KOI8-R + + h_check period -v x=0.5 +} + +atf_test_case assign_NF + +assign_NF_head() { + atf_set "descr" 'Checks that assign to NF changes $0 and $n (PR/44063)' +} + +assign_NF_body() { + h_check assign_NF +} + +atf_test_case single_char_rs + +single_char_rs_head() { + atf_set "descr" "Test awk(1) with single character RS" +} + +single_char_rs_body() { + atf_check \ + -o "inline:1\n2\n\n3\n\n\n4\n\n" \ + -x "echo 1a2aa3aaa4 | $awk 1 RS=a" +} + +atf_test_case two_char_rs + +two_char_rs_head() { + atf_set "descr" "Test awk(1) with two characters RS" +} + +two_char_rs_body() { + atf_check \ + -o "inline:1\n2\n3\n4\n\n" \ + -x "echo 1ab2ab3ab4 | $awk 1 RS=ab" +} + +atf_test_case single_char_regex_group_rs + +single_char_regex_group_rs_head() { + atf_set "descr" "Test awk(1) with single character regex group RS" +} + +single_char_regex_group_rs_body() { + atf_check \ + -o "inline:1\n2\n\n3\n\n\n4\n\n" \ + -x "echo 1a2aa3aaa4 | $awk 1 RS='[a]'" +} + +atf_test_case two_char_regex_group_rs + +two_char_regex_group_rs_head() { + atf_set "descr" "Test awk(1) with two characters regex group RS" +} + +two_char_regex_group_rs_body() { + atf_check \ + -o "inline:1\n2\n\n3\n\n\n4\n\n" \ + -x "echo 1a2ab3aba4 | $awk 1 RS='[ab]'" +} + +atf_test_case single_char_regex_star_rs + +single_char_regex_star_rs_head() { + atf_set "descr" "Test awk(1) with single character regex star RS" +} + +single_char_regex_star_rs_body() { + atf_check \ + -o "inline:1\n2\n3\n4\n\n" \ + -x "echo 1a2aa3aaa4 | $awk 1 RS='a*'" +} + +atf_test_case two_char_regex_star_rs + +two_char_regex_star_rs_head() { + atf_set "descr" "Test awk(1) with two characters regex star RS" +} + +two_char_regex_star_rs_body() { + atf_check \ + -o "inline:1\n2\n3\n4\n\n" \ + -x "echo 1a2aa3aaa4 | $awk 1 RS='aa*'" +} + +atf_test_case regex_two_star_rs + +regex_two_star_rs_head() { + atf_set "descr" "Test awk(1) with regex two star RS" +} + +regex_two_star_rs_body() { + atf_check \ + -o "inline:1\n2\n3\n4\n\n" \ + -x "echo 1a2ab3aab4 | $awk 1 RS='aa*b*'" +} + +atf_test_case regex_or_1_rs + +regex_or_1_rs_head() { + atf_set "descr" "Test awk(1) with regex | case 1 RS" +} + +regex_or_1_rs_body() { + atf_check \ + -o "inline:1a\nc\n\n" \ + -x "echo 1abc | $awk 1 RS='abcde|b'" +} + +atf_test_case regex_or_2_rs + +regex_or_2_rs_head() { + atf_set "descr" "Test awk(1) with regex | case 2 RS" +} + +regex_or_2_rs_body() { + atf_check \ + -o "inline:1a\ncdf2\n\n" \ + -x "echo 1abcdf2 | $awk 1 RS='abcde|b'" +} + +atf_test_case regex_or_3_rs + +regex_or_3_rs_head() { + atf_set "descr" "Test awk(1) with regex | case 3 RS" +} + +regex_or_3_rs_body() { + atf_check \ + -o "inline:1\n\nf2\n\n" \ + -x "echo 1abcdebf2 | $awk 1 RS='abcde|b'" +} + +atf_test_case regex_or_4_rs + +regex_or_4_rs_head() { + atf_set "descr" "Test awk(1) with regex | case 4 RS" +} + +regex_or_4_rs_body() { + atf_check \ + -o "inline:1\nbcdf2\n\n" \ + -x "echo 1abcdf2 | $awk 1 RS='abcde|a'" + +} + +atf_test_case regex_caret_1_rs + +regex_caret_1_rs_head() { + atf_set "descr" "Test awk(1) with regex ^ case 1 RS" +} + +regex_caret_1_rs_body() { + atf_check \ + -o "inline:\n1a2a3a\n\n" \ + -x "echo a1a2a3a | $awk 1 RS='^a'" + +} + +atf_test_case regex_caret_2_rs + +regex_caret_2_rs_head() { + atf_set "descr" "Test awk(1) with regex ^ case 2 RS" +} + +regex_caret_2_rs_body() { + atf_check \ + -o "inline:\naa1a2a\n\n" \ + -x "echo aaa1a2a | $awk 1 RS='^a'" + +} + +atf_test_case regex_dollar_1_rs + +regex_dollar_1_rs_head() { + atf_set "descr" "Test awk(1) with regex $ case 1 RS" +} + +regex_dollar_1_rs_body() { + atf_check \ + -o "inline:a1a2a3a\n\n" \ + -x "echo a1a2a3a | $awk 1 RS='a$'" + +} + +atf_test_case regex_dollar_2_rs + +regex_dollar_2_rs_head() { + atf_set "descr" "Test awk(1) with regex $ case 2 RS" +} + +regex_dollar_2_rs_body() { + atf_check \ + -o "inline:a1a2aaa\n\n" \ + -x "echo a1a2aaa | $awk 1 RS='a$'" + +} + +atf_test_case regex_reallocation_rs + +regex_reallocation_rs_head() { + atf_set "descr" "Test awk(1) with regex reallocation RS" +} + +regex_reallocation_rs_body() { + atf_check \ + -o "inline:a\na\na\na\na\na\na\na\na\na10000\n\n" \ + -x "jot -s a 10000 | $awk 'NR>1' RS='999[0-9]'" + +} + +atf_test_case empty_rs + +empty_rs_head() { + atf_set "descr" "Test awk(1) with empty RS" +} + +empty_rs_body() { + atf_check \ + -o "inline:foo\n" \ + -x "echo foo | $awk 1 RS=''" + +} + +atf_test_case newline_rs + +newline_rs_head() { + atf_set "descr" "Test awk(1) with newline RS" +} + +newline_rs_body() { + atf_check \ + -o "inline:r1f1:r1f2\nr2f1:r2f2\n" \ + -x "printf '\n\n\nr1f1\nr1f2\n\nr2f1\nr2f2\n\n\n' | $awk '{\$1=\$1}1' RS= OFS=:" +} + +atf_test_case modify_subsep + +modify_subsep_head() { + atf_set "descr" "Test awk(1) SUPSEP modification (PR/47306)" +} + +modify_subsep_body() { + atf_check \ + -o "inline:1\n1\n1\n" \ + -x "printf '1\n1 2\n' | \ + $awk '1{ arr[\$1 SUBSEP \$2 SUBSEP ++cnt[\$1]]=1} {for (f in arr) print arr[f];}'" +} + +atf_init_test_cases() { + + atf_add_test_case big_regexp + atf_add_test_case end + atf_add_test_case string1 + atf_add_test_case multibyte + atf_add_test_case period + atf_add_test_case assign_NF + + atf_add_test_case single_char_rs + atf_add_test_case two_char_rs + atf_add_test_case single_char_regex_group_rs + atf_add_test_case two_char_regex_group_rs + atf_add_test_case two_char_regex_star_rs + atf_add_test_case single_char_regex_star_rs + atf_add_test_case regex_two_star_rs + atf_add_test_case regex_or_1_rs + atf_add_test_case regex_or_2_rs + atf_add_test_case regex_or_3_rs + atf_add_test_case regex_caret_1_rs + atf_add_test_case regex_caret_2_rs + atf_add_test_case regex_dollar_1_rs + atf_add_test_case regex_dollar_2_rs + atf_add_test_case regex_reallocation_rs + atf_add_test_case empty_rs + atf_add_test_case newline_rs + atf_add_test_case modify_subsep +} diff --git a/tests/usr.bin/basename/Makefile b/tests/usr.bin/basename/Makefile new file mode 100644 index 000000000..79c3048d3 --- /dev/null +++ b/tests/usr.bin/basename/Makefile @@ -0,0 +1,8 @@ +# $NetBSD: Makefile,v 1.1 2012/03/17 16:33:12 jruoho Exp $ + +.include + +TESTSDIR= ${TESTSBASE}/usr.bin/basename +TESTS_SH= t_basename + +.include diff --git a/tests/usr.bin/basename/t_basename.sh b/tests/usr.bin/basename/t_basename.sh new file mode 100644 index 000000000..d22b7a9a8 --- /dev/null +++ b/tests/usr.bin/basename/t_basename.sh @@ -0,0 +1,62 @@ +# $NetBSD: t_basename.sh,v 1.1 2012/03/17 16:33:12 jruoho Exp $ +# +# Copyright (c) 2008 The NetBSD Foundation, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +atf_test_case basic +basic_head() +{ + atf_set "descr" "Checks basic functionality" +} +basic_body() +{ + atf_check -o inline:"bin\n" basename /usr/bin + atf_check -o inline:"usr\n" basename /usr + atf_check -o inline:"/\n" basename / + atf_check -o inline:"/\n" basename /// + atf_check -o inline:"usr\n" basename /usr// + atf_check -o inline:"bin\n" basename //usr//bin + atf_check -o inline:"usr\n" basename usr + atf_check -o inline:"bin\n" basename usr/bin +} + +atf_test_case suffix +suffix_head() +{ + atf_set "descr" "Checks removing of provided suffix" +} +suffix_body() +{ + atf_check -o inline:"bi\n" basename /usr/bin n + atf_check -o inline:"bin\n" basename /usr/bin bin + atf_check -o inline:"/\n" basename / / + atf_check -o inline:"g\n" basename /usr/bin/gcc cc +} + +atf_init_test_cases() +{ + atf_add_test_case basic + atf_add_test_case suffix +} diff --git a/tests/usr.bin/bzip2/Makefile b/tests/usr.bin/bzip2/Makefile new file mode 100644 index 000000000..a9e9cbf8c --- /dev/null +++ b/tests/usr.bin/bzip2/Makefile @@ -0,0 +1,21 @@ +# $NetBSD: Makefile,v 1.3 2012/05/07 08:51:47 wiz Exp $ + +NOMAN= # defined + +.include + +TESTSDIR= ${TESTSBASE}/usr.bin/bzip2 + +TESTS_SH= t_bzip2 + +DIST= ${NETBSDSRCDIR}/external/bsd/bzip2/dist +.PATH: ${DIST} + +FILESDIR= ${TESTSDIR} +.for f in sample1.bz2 sample1.ref sample2.bz2 sample2.ref \ + sample3.bz2 sample3.ref +FILES+= ${f} +FILESNAME_${f}= d_${f} +.endfor + +.include diff --git a/tests/usr.bin/bzip2/t_bzip2.sh b/tests/usr.bin/bzip2/t_bzip2.sh new file mode 100644 index 000000000..447fea906 --- /dev/null +++ b/tests/usr.bin/bzip2/t_bzip2.sh @@ -0,0 +1,52 @@ +# $NetBSD: t_bzip2.sh,v 1.1 2012/03/17 16:33:12 jruoho Exp $ +# +# Copyright (c) 2008, 2009 The NetBSD Foundation, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +atf_test_case basic +basic_head() +{ + atf_set "descr" "Checks basic functionality" +} +basic_body() +{ + atf_check -o file:$(atf_get_srcdir)/d_sample1.bz2 \ + bzip2 -1c $(atf_get_srcdir)/d_sample1.ref + atf_check -o file:$(atf_get_srcdir)/d_sample2.bz2 \ + bzip2 -2c $(atf_get_srcdir)/d_sample2.ref + atf_check -o file:$(atf_get_srcdir)/d_sample3.bz2 \ + bzip2 -3c $(atf_get_srcdir)/d_sample3.ref + atf_check -o file:$(atf_get_srcdir)/d_sample1.ref \ + bzip2 -dc $(atf_get_srcdir)/d_sample1.bz2 + atf_check -o file:$(atf_get_srcdir)/d_sample2.ref \ + bzip2 -dc $(atf_get_srcdir)/d_sample2.bz2 + atf_check -o file:$(atf_get_srcdir)/d_sample3.ref \ + bzip2 -dsc $(atf_get_srcdir)/d_sample3.bz2 +} + +atf_init_test_cases() +{ + atf_add_test_case basic +} diff --git a/tests/usr.bin/cc/Makefile b/tests/usr.bin/cc/Makefile new file mode 100644 index 000000000..fc0638f89 --- /dev/null +++ b/tests/usr.bin/cc/Makefile @@ -0,0 +1,9 @@ +# $NetBSD: Makefile,v 1.1 2012/03/17 17:15:29 jruoho Exp $ + +.include + +TESTSDIR= ${TESTSBASE}/usr.bin/cc + +TESTS_SH= t_hello + +.include diff --git a/tests/usr.bin/cc/t_hello.sh b/tests/usr.bin/cc/t_hello.sh new file mode 100644 index 000000000..9fa135251 --- /dev/null +++ b/tests/usr.bin/cc/t_hello.sh @@ -0,0 +1,144 @@ +# $NetBSD: t_hello.sh,v 1.2 2012/07/21 12:30:55 martin Exp $ +# +# Copyright (c) 2011 The NetBSD Foundation, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +atf_test_case hello +hello_head() { + atf_set "descr" "compile and run \"hello world\"" + atf_set "require.progs" "cc" +} + +atf_test_case hello_pic +hello_pic_head() { + atf_set "descr" "compile and run PIC \"hello world\"" + atf_set "require.progs" "cc" +} + +atf_test_case hello_pie +hello_pie_head() { + atf_set "descr" "compile and run position independend (PIE) \"hello world\"" + atf_set "require.progs" "cc" +} + +atf_test_case hello32 +hello32_head() { + atf_set "descr" "compile and run \"hello world\" for/in netbsd32 emulation" + atf_set "require.progs" "cc file diff cat" +} + +hello_body() { + cat > test.c << EOF +#include +#include +int main(void) {printf("hello world\n");exit(0);} +EOF + atf_check -s exit:0 -o ignore -e ignore cc -o hello test.c + atf_check -s exit:0 -o inline:"hello world\n" ./hello +} + +hello_pic_body() { + cat > test.c << EOF +#include +int main(void) {callpic();exit(0);} +EOF + cat > pic.c << EOF +#include +int callpic(void) {printf("hello world\n");} +EOF + + atf_check -s exit:0 -o ignore -e ignore \ + cc -fPIC -dPIC -shared -o libtest.so pic.c + atf_check -s exit:0 -o ignore -e ignore \ + cc -o hello test.c -L. -ltest + + export LD_LIBRARY_PATH=. + atf_check -s exit:0 -o inline:"hello world\n" ./hello +} + +hello_pie_body() { + # check whether this arch supports -pie + if ! cc -pie -dM -E - < /dev/null 2>/dev/null >/dev/null; then + atf_skip "cc -pie not supported on this architecture" + fi + cat > test.c << EOF +#include +#include +int main(void) {printf("hello world\n");exit(0);} +EOF + atf_check -s exit:0 -o ignore -e ignore cc -fpie -pie -o hello test.c + atf_check -s exit:0 -o inline:"hello world\n" ./hello +} + +hello32_body() { + # check whether this arch is 64bit + if ! cc -dM -E - < /dev/null | fgrep -q _LP64; then + atf_skip "this is not a 64 bit architecture" + fi + if ! cc -m32 -dM -E - < /dev/null 2>/dev/null > ./def32; then + atf_skip "cc -m32 not supported on this architecture" + else + if fgrep -q _LP64 ./def32; then + atf_fail "cc -m32 does not generate netbsd32 binaries" + fi + fi + + cat > test.c << EOF +#include +#include +int main(void) {printf("hello world\n");exit(0);} +EOF + atf_check -s exit:0 -o ignore -e ignore cc -o hello32 -m32 test.c + atf_check -s exit:0 -o ignore -e ignore cc -o hello64 test.c + file -b ./hello32 > ./ftype32 + file -b ./hello64 > ./ftype64 + if diff ./ftype32 ./ftype64 >/dev/null; then + atf_fail "generated binaries do not differ" + fi + echo "32bit binaries on this platform are:" + cat ./ftype32 + echo "While native (64bit) binaries are:" + cat ./ftype64 + atf_check -s exit:0 -o inline:"hello world\n" ./hello32 + + # do another test with static 32bit binaries + cat > test.c << EOF +#include +#include +int main(void) {printf("hello static world\n");exit(0);} +EOF + atf_check -s exit:0 -o ignore -e ignore cc -o hello -m32 \ + -static test.c + atf_check -s exit:0 -o inline:"hello static world\n" ./hello +} + +atf_init_test_cases() +{ + + atf_add_test_case hello + atf_add_test_case hello_pic + atf_add_test_case hello_pie + atf_add_test_case hello32 +} diff --git a/tests/usr.bin/cmp/Makefile b/tests/usr.bin/cmp/Makefile new file mode 100644 index 000000000..007bca194 --- /dev/null +++ b/tests/usr.bin/cmp/Makefile @@ -0,0 +1,8 @@ +# $NetBSD: Makefile,v 1.1 2012/03/19 07:05:18 jruoho Exp $ + +.include + +TESTSDIR= ${TESTSBASE}/usr.bin/cmp +TESTS_SH= t_cmp + +.include diff --git a/tests/usr.bin/cmp/t_cmp.sh b/tests/usr.bin/cmp/t_cmp.sh new file mode 100644 index 000000000..341047fb5 --- /dev/null +++ b/tests/usr.bin/cmp/t_cmp.sh @@ -0,0 +1,67 @@ +# $NetBSD: t_cmp.sh,v 1.1 2012/03/19 07:05:18 jruoho Exp $ +# +# Copyright (c) 2012 The NetBSD Foundation, Inc. +# All rights reserved. +# +# This code is derived from software contributed to The NetBSD Foundation +# by Jukka Ruohonen. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +atf_test_case missing +missing_head() { + atf_set "descr" "Test that cmp(1) with '-s' is silent " \ + "when files are missing (PR bin/2642)" +} + +missing_body() { + + echo a > a + + atf_check -s not-exit:0 -o empty -e empty -x "cmp -s a x" + atf_check -s not-exit:0 -o empty -e empty -x "cmp -s x a" + atf_check -s not-exit:0 -o empty -e empty -x "cmp -s x y" + atf_check -s not-exit:0 -o empty -e empty -x "cmp -s y x" +} + +atf_test_case skip +skip_head() { + atf_set "descr" "Test that cmp(1) handles skip " \ + "parameters correctly (PR bin/23836)" +} + +skip_body() { + + echo 0123456789abcdef > a + echo abcdef > b + + atf_check -s exit:0 -o empty -e empty -x "cmp a b '10'" + atf_check -s exit:0 -o empty -e empty -x "cmp a b '0xa'" + atf_check -s exit:1 -o not-empty -e empty -x "cmp a b '9'" +} + +atf_init_test_cases() +{ + atf_add_test_case missing + atf_add_test_case skip +} diff --git a/tests/usr.bin/config/Makefile b/tests/usr.bin/config/Makefile new file mode 100644 index 000000000..e4cc96c98 --- /dev/null +++ b/tests/usr.bin/config/Makefile @@ -0,0 +1,26 @@ +# $NetBSD: Makefile,v 1.1 2012/03/17 16:33:12 jruoho Exp $ + +SUBDIR= support + +NOMAN= # defined + +.include + +TESTSDIR= ${TESTSBASE}/usr.bin/config + +TESTS_SH= t_config + +FILESDIR= ${TESTSDIR} +FILES= d_deffs_redef +FILES+= d_loop +FILES+= d_loop2 +FILES+= d_no_pseudo +FILES+= d_postponed_orphan +FILES+= d_pseudo_parent +FILES+= d_shadow_instance +FILES+= support/arch/regress/conf/Makefile.regress +FILES+= support/arch/regress/conf/files.regress +FILES+= support/arch/regress/conf/std.regress +FILES+= support/conf/files + +.include diff --git a/tests/usr.bin/config/d_deffs_redef b/tests/usr.bin/config/d_deffs_redef new file mode 100644 index 000000000..d84d1f712 --- /dev/null +++ b/tests/usr.bin/config/d_deffs_redef @@ -0,0 +1,10 @@ +include "arch/regress/conf/std.regress" +maxusers 4 +file-system REGRESSFS + +master0 at root + +defflag NOT_A_FS +deffs NOT_A_FS + +config regress root on ? diff --git a/tests/usr.bin/config/d_loop b/tests/usr.bin/config/d_loop new file mode 100644 index 000000000..674a209e1 --- /dev/null +++ b/tests/usr.bin/config/d_loop @@ -0,0 +1,23 @@ +include "arch/regress/conf/std.regress" +maxusers 4 +file-system REGRESSFS + +master0 at root + +# The following definitions build a loop of 'looper' devices. +# This tests how well the code that look for orphans handle loops. +# +# In that case, while the loopchild devices will always be seen in +# time, the code has to make sure it reaches all the loopbaby +# devices. + +looper0 at master0 +looper1 at looper0 + +loopchild0 at looper0 +loopchild1 at looper1 + +loopbaby0 at loopchild0 +loopbaby1 at loopchild1 + +config regress root on ? diff --git a/tests/usr.bin/config/d_loop2 b/tests/usr.bin/config/d_loop2 new file mode 100644 index 000000000..8e7238de5 --- /dev/null +++ b/tests/usr.bin/config/d_loop2 @@ -0,0 +1,16 @@ +include "arch/regress/conf/std.regress" +maxusers 4 +file-system REGRESSFS + +master0 at root + +# Devices that are their own parent must be handled properly +# when the instance is negated. + +looper* at master0 +looper* at looper? +looper1 at looper0 + +no looper* at looper? + +config regress root on ? diff --git a/tests/usr.bin/config/d_no_pseudo b/tests/usr.bin/config/d_no_pseudo new file mode 100644 index 000000000..9ee856474 --- /dev/null +++ b/tests/usr.bin/config/d_no_pseudo @@ -0,0 +1,14 @@ +include "arch/regress/conf/std.regress" + +maxusers 4 + +file-system REGRESSFS + +master0 at root + +# Simply negating a pseudo-device should yield an error. + +pseudo-device pseudodev +no pseudodev + +config regress root on ? diff --git a/tests/usr.bin/config/d_postponed_orphan b/tests/usr.bin/config/d_postponed_orphan new file mode 100644 index 000000000..bb5ec0461 --- /dev/null +++ b/tests/usr.bin/config/d_postponed_orphan @@ -0,0 +1,21 @@ +include "arch/regress/conf/std.regress" + +maxusers 4 + +file-system REGRESSFS + +master0 at root + +parenti* at master? + +# Here, parenti is negated before the child* instance is declared. That +# means the child* instance does not qualify as an explicit orphan and +# therefore should _not_ be ignored. +# +# config(1) should error out on that config file. + +no parenti + +child* at parenti? + +config regress root on ? diff --git a/tests/usr.bin/config/d_pseudo_parent b/tests/usr.bin/config/d_pseudo_parent new file mode 100644 index 000000000..aebad8bd2 --- /dev/null +++ b/tests/usr.bin/config/d_pseudo_parent @@ -0,0 +1,13 @@ +include "arch/regress/conf/std.regress" +maxusers 4 +file-system REGRESSFS + +# Pseudo-devices can have children on interface attributes, +# which means they don't necessarily have to explicitly +# define locators (see pseudodev definition). + +pseudo-device pseudodev + +child* at pseudodev? + +config regress root on ? diff --git a/tests/usr.bin/config/d_shadow_instance b/tests/usr.bin/config/d_shadow_instance new file mode 100644 index 000000000..60228214b --- /dev/null +++ b/tests/usr.bin/config/d_shadow_instance @@ -0,0 +1,25 @@ +include "arch/regress/conf/std.regress" + +maxusers 4 + +file-system REGRESSFS + +master0 at root + +parenti* at master? +parentii* at master? + +# The second child* instance (attaching at parentii) is useless: it will be +# shadowed by the first one, which is semantically the same, from a parentii +# device's point of view. +# +# The two child* instances are aliases, and at some point the orphan-checking +# code skipped some aliases, in the shadowing situation and some others. +# +# This test should pass, the lines are valid, even though the second one is +# useless. + +child* at hook? +child* at parentii? + +config regress root on ? diff --git a/tests/usr.bin/config/support/Makefile b/tests/usr.bin/config/support/Makefile new file mode 100644 index 000000000..23479f318 --- /dev/null +++ b/tests/usr.bin/config/support/Makefile @@ -0,0 +1,5 @@ +# $NetBSD: Makefile,v 1.1 2012/03/17 16:33:12 jruoho Exp $ + +SUBDIR= arch conf + +.include diff --git a/tests/usr.bin/config/support/arch/Makefile b/tests/usr.bin/config/support/arch/Makefile new file mode 100644 index 000000000..34c990f52 --- /dev/null +++ b/tests/usr.bin/config/support/arch/Makefile @@ -0,0 +1,5 @@ +# $NetBSD: Makefile,v 1.1 2012/03/17 16:33:12 jruoho Exp $ + +SUBDIR= regress + +.include diff --git a/tests/usr.bin/config/support/arch/regress/Makefile b/tests/usr.bin/config/support/arch/regress/Makefile new file mode 100644 index 000000000..a4b1869b8 --- /dev/null +++ b/tests/usr.bin/config/support/arch/regress/Makefile @@ -0,0 +1,5 @@ +# $NetBSD: Makefile,v 1.1 2012/03/17 16:33:12 jruoho Exp $ + +SUBDIR= conf + +.include diff --git a/tests/usr.bin/config/support/arch/regress/conf/Makefile b/tests/usr.bin/config/support/arch/regress/conf/Makefile new file mode 100644 index 000000000..557f010b3 --- /dev/null +++ b/tests/usr.bin/config/support/arch/regress/conf/Makefile @@ -0,0 +1,15 @@ +# $NetBSD: Makefile,v 1.1 2012/03/17 16:33:12 jruoho Exp $ + +.include + +TESTSDIR= ${TESTSBASE}/usr.bin/config +ATFFILE= no + +FILESDIR= ${TESTSDIR}/support/arch/regress/conf +FILES= Makefile.regress +FILES+= files.regress +FILES+= std.regress + +.include +.include +.include diff --git a/tests/usr.bin/config/support/arch/regress/conf/Makefile.regress b/tests/usr.bin/config/support/arch/regress/conf/Makefile.regress new file mode 100644 index 000000000..719eb2703 --- /dev/null +++ b/tests/usr.bin/config/support/arch/regress/conf/Makefile.regress @@ -0,0 +1,41 @@ +=== INCLUDES BEGIN === + +%INCLUDES + +=== INCLUDES END === + +=== OBJS BEGIN === + +%OBJS + +=== OBJS END === + +=== CFILES BEGIN === + +%CFILES + +=== CFILES END === + +=== SFILES BEGIN === + +%SFILES + +=== SFILES END === + +=== LOAD BEGIN === + +%LOAD + +=== LOAD END === + +=== RULES BEGIN === + +%RULES + +=== RULES END === + +=== MAKEOPTIONSAPPEND BEGIN === + +%MAKEOPTIONSAPPEND + +=== MAKEOPTIONSAPPEND END === diff --git a/tests/usr.bin/config/support/arch/regress/conf/files.regress b/tests/usr.bin/config/support/arch/regress/conf/files.regress new file mode 100644 index 000000000..e9488d65f --- /dev/null +++ b/tests/usr.bin/config/support/arch/regress/conf/files.regress @@ -0,0 +1,2 @@ +maxpartitions 8 +maxusers 2 4 8 diff --git a/tests/usr.bin/config/support/arch/regress/conf/std.regress b/tests/usr.bin/config/support/arch/regress/conf/std.regress new file mode 100644 index 000000000..f92baafe0 --- /dev/null +++ b/tests/usr.bin/config/support/arch/regress/conf/std.regress @@ -0,0 +1 @@ +machine regress diff --git a/tests/usr.bin/config/support/conf/Makefile b/tests/usr.bin/config/support/conf/Makefile new file mode 100644 index 000000000..b01ffa175 --- /dev/null +++ b/tests/usr.bin/config/support/conf/Makefile @@ -0,0 +1,13 @@ +# $NetBSD: Makefile,v 1.1 2012/03/17 16:33:12 jruoho Exp $ + +.include + +TESTSDIR= ${TESTSBASE}/usr.bin/config +ATFFILE= no + +FILESDIR= ${TESTSDIR}/support/conf +FILES= files + +.include +.include +.include diff --git a/tests/usr.bin/config/support/conf/files b/tests/usr.bin/config/support/conf/files new file mode 100644 index 000000000..d525782c6 --- /dev/null +++ b/tests/usr.bin/config/support/conf/files @@ -0,0 +1,26 @@ +deffs REGRESSFS + +device master { } +attach master at root + +define hook { } + +device parentii: hook +attach parentii at master +device parenti: hook +attach parenti at master + +device child +attach child at hook + +device looper { } +attach looper at master with looper_master +attach looper at looper with looper_looper + +device loopchild { } +attach loopchild at looper + +device loopbaby +attach loopbaby at loopchild + +defpseudo pseudodev: hook diff --git a/tests/usr.bin/config/t_config.sh b/tests/usr.bin/config/t_config.sh new file mode 100644 index 000000000..9f97b5e10 --- /dev/null +++ b/tests/usr.bin/config/t_config.sh @@ -0,0 +1,91 @@ +# $NetBSD: t_config.sh,v 1.1 2012/03/17 16:33:12 jruoho Exp $ +# +# Copyright (c) 2008, 2010 The NetBSD Foundation, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +run_and_check_pass() +{ + local name="${1}"; shift + + mkdir compile + supportdir="$(atf_get_srcdir)/support" + config="$(atf_get_srcdir)/d_${name}" + + atf_check -o ignore \ + config -s "${supportdir}" -b "compile/${name}" "${config}" +} + +run_and_check_fail() +{ + local name="${1}"; shift + + mkdir compile + supportdir="$(atf_get_srcdir)/support" + config="$(atf_get_srcdir)/d_${name}" + + atf_check -o ignore -e ignore -s ne:0 \ + config -s "${supportdir}" -b "compile/${name}" "${config}" +} + +# Defines a test case for config(1). +test_case() +{ + local name="${1}"; shift + local type="${1}"; shift + local descr="${*}" + + atf_test_case "${name}" + eval "${name}_head() { \ + atf_set descr \"${descr}\"; \ + atf_set require.progs \"config\"; \ + }" + eval "${name}_body() { \ + run_and_check_${type} '${name}'; \ + }" +} + +test_case shadow_instance pass "Checks correct handling of shadowed instances" +test_case loop pass "Checks correct handling of loops" +test_case loop2 pass "Checks correct handling of devices that can be their" \ + "own parents" +test_case pseudo_parent pass "Checks correct handling of children of pseudo" \ + "devices (PR/32329)" +test_case postponed_orphan fail "Checks that config catches adding an" \ + "instance of a child of a negated instance as error" +test_case no_pseudo fail "Checks that config catches ommited 'pseudo-device'" \ + "as error (PR/34111)" +test_case deffs_redef fail "Checks that config doesn't allow a deffs to use" \ + "the same name as a previous defflag/defparam" + +atf_init_test_cases() +{ + atf_add_test_case shadow_instance + atf_add_test_case loop + atf_add_test_case loop2 + atf_add_test_case pseudo_parent + atf_add_test_case postponed_orphan + atf_add_test_case no_pseudo + atf_add_test_case deffs_redef +} diff --git a/tests/usr.bin/cut/Makefile b/tests/usr.bin/cut/Makefile new file mode 100644 index 000000000..e8e64ec69 --- /dev/null +++ b/tests/usr.bin/cut/Makefile @@ -0,0 +1,20 @@ +# $NetBSD: Makefile,v 1.1 2012/03/17 16:33:13 jruoho Exp $ + +NOMAN= # defined + +.include + +TESTSDIR= ${TESTSBASE}/usr.bin/cut + +TESTS_SH= t_cut + +FILESDIR= ${TESTSDIR} +FILES= d_basic.out +FILES+= d_cut.in +FILES+= d_dflag.out +FILES+= d_dsflag.out +FILES+= d_latin1.in +FILES+= d_sflag.out +FILES+= d_utf8.in + +.include diff --git a/tests/usr.bin/cut/d_basic.out b/tests/usr.bin/cut/d_basic.out new file mode 100644 index 000000000..f704cdfbb --- /dev/null +++ b/tests/usr.bin/cut/d_basic.out @@ -0,0 +1,88 @@ +----- test: cut -f 1 d_cut.in ----- +1 + +12 + +qwe +1 + +12:34:56 +qwe:rty:uio:p[]:asd:fgh:jkl:zxc:vbn:nm +:qwe:::rty:uio::p[]:asd:fgh:jkl:zxc:vbn:nm +----- test: cut -f 2 d_cut.in ----- +1 + +34 +12 + +1 + +12:34:56 +qwe:rty:uio:p[]:asd:fgh:jkl:zxc:vbn:nm +:qwe:::rty:uio::p[]:asd:fgh:jkl:zxc:vbn:nm +----- test: cut -f 3 d_cut.in ----- +1 + +56 + +rty +1 + +12:34:56 +qwe:rty:uio:p[]:asd:fgh:jkl:zxc:vbn:nm +:qwe:::rty:uio::p[]:asd:fgh:jkl:zxc:vbn:nm +----- test: cut -f 1-2 d_cut.in ----- +1 + +12 34 + 12 +qwe +1 + +12:34:56 +qwe:rty:uio:p[]:asd:fgh:jkl:zxc:vbn:nm +:qwe:::rty:uio::p[]:asd:fgh:jkl:zxc:vbn:nm +----- test: cut -f 2,3 d_cut.in ----- +1 + +34 56 +12 + rty +1 + +12:34:56 +qwe:rty:uio:p[]:asd:fgh:jkl:zxc:vbn:nm +:qwe:::rty:uio::p[]:asd:fgh:jkl:zxc:vbn:nm +----- test: cut -f 4 d_cut.in ----- +1 + + +34 +uio +1 + +12:34:56 +qwe:rty:uio:p[]:asd:fgh:jkl:zxc:vbn:nm +:qwe:::rty:uio::p[]:asd:fgh:jkl:zxc:vbn:nm +----- test: cut -f 1-3,4-7 d_cut.in ----- +1 + +12 34 56 + 12 34 56 +qwe rty uio p[] asd +1 + +12:34:56 +qwe:rty:uio:p[]:asd:fgh:jkl:zxc:vbn:nm +:qwe:::rty:uio::p[]:asd:fgh:jkl:zxc:vbn:nm +----- test: cut -f 1,2-7 d_cut.in ----- +1 + +12 34 56 + 12 34 56 +qwe rty uio p[] asd +1 + +12:34:56 +qwe:rty:uio:p[]:asd:fgh:jkl:zxc:vbn:nm +:qwe:::rty:uio::p[]:asd:fgh:jkl:zxc:vbn:nm diff --git a/tests/usr.bin/cut/d_cut.in b/tests/usr.bin/cut/d_cut.in new file mode 100644 index 000000000..85b4184b4 --- /dev/null +++ b/tests/usr.bin/cut/d_cut.in @@ -0,0 +1,10 @@ +1 + +12 34 56 + 12 34 56 +qwe rty uio p[] asd fgh jkl zxc vbn nm +1 + +12:34:56 +qwe:rty:uio:p[]:asd:fgh:jkl:zxc:vbn:nm +:qwe:::rty:uio::p[]:asd:fgh:jkl:zxc:vbn:nm diff --git a/tests/usr.bin/cut/d_dflag.out b/tests/usr.bin/cut/d_dflag.out new file mode 100644 index 000000000..63b814f80 --- /dev/null +++ b/tests/usr.bin/cut/d_dflag.out @@ -0,0 +1,88 @@ +----- test: cut -f 1 -d : d_cut.in ----- +1 + +12 34 56 + 12 34 56 +qwe rty uio p[] asd fgh jkl zxc vbn nm +1 + +12 +qwe + +----- test: cut -f 2 -d : d_cut.in ----- +1 + +12 34 56 + 12 34 56 +qwe rty uio p[] asd fgh jkl zxc vbn nm +1 + +34 +rty +qwe +----- test: cut -f 3 -d : d_cut.in ----- +1 + +12 34 56 + 12 34 56 +qwe rty uio p[] asd fgh jkl zxc vbn nm +1 + +56 +uio + +----- test: cut -f 1-2 -d : d_cut.in ----- +1 + +12 34 56 + 12 34 56 +qwe rty uio p[] asd fgh jkl zxc vbn nm +1 + +12:34 +qwe:rty +:qwe +----- test: cut -f 2,3 -d : d_cut.in ----- +1 + +12 34 56 + 12 34 56 +qwe rty uio p[] asd fgh jkl zxc vbn nm +1 + +34:56 +rty:uio +qwe: +----- test: cut -f 4 -d : d_cut.in ----- +1 + +12 34 56 + 12 34 56 +qwe rty uio p[] asd fgh jkl zxc vbn nm +1 + + +p[] + +----- test: cut -f 1-3,4-7 -d : d_cut.in ----- +1 + +12 34 56 + 12 34 56 +qwe rty uio p[] asd fgh jkl zxc vbn nm +1 + +12:34:56 +qwe:rty:uio:p[]:asd:fgh:jkl +:qwe:::rty:uio: +----- test: cut -f 1,2-7 -d : d_cut.in ----- +1 + +12 34 56 + 12 34 56 +qwe rty uio p[] asd fgh jkl zxc vbn nm +1 + +12:34:56 +qwe:rty:uio:p[]:asd:fgh:jkl +:qwe:::rty:uio: diff --git a/tests/usr.bin/cut/d_dsflag.out b/tests/usr.bin/cut/d_dsflag.out new file mode 100644 index 000000000..e3d1beb23 --- /dev/null +++ b/tests/usr.bin/cut/d_dsflag.out @@ -0,0 +1,32 @@ +----- test: cut -f 1 -d : -s d_cut.in ----- +12 +qwe + +----- test: cut -f 2 -d : -s d_cut.in ----- +34 +rty +qwe +----- test: cut -f 3 -d : -s d_cut.in ----- +56 +uio + +----- test: cut -f 1-2 -d : -s d_cut.in ----- +12:34 +qwe:rty +:qwe +----- test: cut -f 2,3 -d : -s d_cut.in ----- +34:56 +rty:uio +qwe: +----- test: cut -f 4 -d : -s d_cut.in ----- + +p[] + +----- test: cut -f 1-3,4-7 -d : -s d_cut.in ----- +12:34:56 +qwe:rty:uio:p[]:asd:fgh:jkl +:qwe:::rty:uio: +----- test: cut -f 1,2-7 -d : -s d_cut.in ----- +12:34:56 +qwe:rty:uio:p[]:asd:fgh:jkl +:qwe:::rty:uio: diff --git a/tests/usr.bin/cut/d_latin1.in b/tests/usr.bin/cut/d_latin1.in new file mode 100644 index 000000000..00255b113 --- /dev/null +++ b/tests/usr.bin/cut/d_latin1.in @@ -0,0 +1,4 @@ +fooÄ:bar:Äbaz +FooÄ:Bar:ÄBaz +FOoÄ:BAr:ÄBAz +FOOÄ:BAR:ÄBAZ diff --git a/tests/usr.bin/cut/d_sflag.out b/tests/usr.bin/cut/d_sflag.out new file mode 100644 index 000000000..88c2b3ef5 --- /dev/null +++ b/tests/usr.bin/cut/d_sflag.out @@ -0,0 +1,32 @@ +----- test: cut -f 1 -s d_cut.in ----- +12 + +qwe +----- test: cut -f 2 -s d_cut.in ----- +34 +12 + +----- test: cut -f 3 -s d_cut.in ----- +56 + +rty +----- test: cut -f 1-2 -s d_cut.in ----- +12 34 + 12 +qwe +----- test: cut -f 2,3 -s d_cut.in ----- +34 56 +12 + rty +----- test: cut -f 4 -s d_cut.in ----- + +34 +uio +----- test: cut -f 1-3,4-7 -s d_cut.in ----- +12 34 56 + 12 34 56 +qwe rty uio p[] asd +----- test: cut -f 1,2-7 -s d_cut.in ----- +12 34 56 + 12 34 56 +qwe rty uio p[] asd diff --git a/tests/usr.bin/cut/d_utf8.in b/tests/usr.bin/cut/d_utf8.in new file mode 100644 index 000000000..320a0637c --- /dev/null +++ b/tests/usr.bin/cut/d_utf8.in @@ -0,0 +1,4 @@ +fooÄ:bar:Äbaz +FooÄ:Bar:ÄBaz +FOoÄ:BAr:ÄBAz +FOOÄ:BAR:ÄBAZ diff --git a/tests/usr.bin/cut/t_cut.sh b/tests/usr.bin/cut/t_cut.sh new file mode 100644 index 000000000..3c3793f84 --- /dev/null +++ b/tests/usr.bin/cut/t_cut.sh @@ -0,0 +1,130 @@ +# $NetBSD: t_cut.sh,v 1.1 2012/03/17 16:33:13 jruoho Exp $ +# +# Copyright (c) 2008, 2009 The NetBSD Foundation, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +h_run() +{ + file="${1}"; shift + opts="${*}" + + for fields in 1 2 3 1-2 2,3 4 1-3,4-7 1,2-7 + do + opts="-f ${fields} $@" + echo "----- test: cut ${opts} $(basename $file) -----" + cut $opts "$file" || atf_fail "command failed: cut ${opts} $file" + done +} + +h_check() +{ + diff -Nru "$1" "$2" || atf_fail "files $1 and $2 differ" +} + +atf_test_case basic +basic_head() +{ + atf_set "descr" "Checks basic functionality" +} +basic_body() +{ + h_run "$(atf_get_srcdir)/d_cut.in" > out + h_check out "$(atf_get_srcdir)/d_basic.out" +} + +atf_test_case sflag +sflag_head() +{ + atf_set "descr" "Checks -s flag" +} +sflag_body() +{ + h_run "$(atf_get_srcdir)/d_cut.in" -s > out + h_check out "$(atf_get_srcdir)/d_sflag.out" +} + +atf_test_case dflag +dflag_head() +{ + atf_set "descr" "Checks -d flag" +} +dflag_body() +{ + h_run "$(atf_get_srcdir)/d_cut.in" -d ":" > out + h_check out "$(atf_get_srcdir)/d_dflag.out" +} + +atf_test_case dsflag +dsflag_head() +{ + atf_set "descr" "Checks -s and -d flags combined" +} +dsflag_body() +{ + h_run "$(atf_get_srcdir)/d_cut.in" -d ":" -s > out + h_check out "$(atf_get_srcdir)/d_dsflag.out" +} + +atf_test_case latin1 +latin1_head() +{ + atf_set "descr" "Checks support for non-ascii characters" +} +latin1_body() +{ + export LC_ALL=C + + atf_check -o inline:"bar\nBar\nBAr\nBAR\n" \ + cut -b 6,7,8 "$(atf_get_srcdir)/d_latin1.in" + + atf_check -o inline:"bar\nBar\nBAr\nBAR\n" \ + cut -c 6,7,8 "$(atf_get_srcdir)/d_latin1.in" +} + +atf_test_case utf8 +utf8_head() +{ + atf_set "descr" "Checks support for multibyte characters" +} +utf8_body() +{ + export LC_ALL=en_US.UTF-8 + + atf_check -o inline:":ba\n:Ba\n:BA\n:BA\n" \ + cut -b 6,7,8 "$(atf_get_srcdir)/d_utf8.in" + + atf_check -o inline:"bar\nBar\nBAr\nBAR\n" \ + cut -c 6,7,8 "$(atf_get_srcdir)/d_utf8.in" +} + +atf_init_test_cases() +{ + atf_add_test_case basic + atf_add_test_case sflag + atf_add_test_case dflag + atf_add_test_case dsflag + atf_add_test_case latin1 + atf_add_test_case utf8 +} diff --git a/tests/usr.bin/diff/Makefile b/tests/usr.bin/diff/Makefile new file mode 100644 index 000000000..2bd8339a0 --- /dev/null +++ b/tests/usr.bin/diff/Makefile @@ -0,0 +1,13 @@ +# $NetBSD: Makefile,v 1.1 2011/05/03 15:13:50 jruoho Exp $ + +.include + +TESTSDIR= ${TESTSBASE}/usr.bin/diff + +TESTS_SH= t_diff + +FILESDIR= ${TESTSDIR} +FILES+= d_mallocv1.in +FILES+= d_mallocv2.in + +.include diff --git a/tests/usr.bin/diff/d_mallocv1.in b/tests/usr.bin/diff/d_mallocv1.in new file mode 100644 index 000000000..27ab50336 --- /dev/null +++ b/tests/usr.bin/diff/d_mallocv1.in @@ -0,0 +1,5 @@ +18086b1e91f730facb2d6e1b +c562653b24814eb3651b1e68301a3c14b96302bb +6d017f7aef74662ed8dd51eef14281eaad223298db370bfaca +30c04231cb3de404e4b8a5359a74066fd963291d7986be835834ab07870c097682a953bfff38784780eef844de47fb36c34f8e034c96cfa64d9cb5decee472138236e9fb79e9fe1fba6b7757b970f22477d167832206900473f09f3e8c822db6d9a8273340ed6743d99638d6cf192d821b6f33d23278b1a929f303a80865c426d01add11b2f2416babd13e70b44d8eeb731c09c7163af9d1a23cbe20ddb08b0f67ecaa2eed511263a67e9c12e59ef113f0b9e4e4e140b43896078a7571c61826ba099b3dd8c4b096a9785b4434e97ea99e662ba6fdb60a41547ccae4c67d3e1f3ef515198e91f009c75c9e80fda90d13ee29d8aad5d87cc2437ce60e6ce55700837fb0815bfd2495f8aa1a33fe67c1ae28a885506a78ca6257f5a5f2a8042e28680acc83b1aecb3a9cb51911126f2f0deaf14fcfa5f165e9a5c3f8f2d1c3f4683b2d75927a7bc802d63b680a5e22768cc0439854ccd49e58a002794f541bddd6ef6fbd4f9869843a72d0ae9d438c90353a46c0c9863a16b1de206c717ab7ce6ea6f648a38efa12b70bbe3388b35adec7a789ea98de217520d7d6ce699841e17e5946bf5a8b3c7a2c3e2d6767422baf3159ff08d913ec78011ab7d34bc24af26c24a8d46f7261c7705a7b270e27590c29583c659a0df8dada4e7a0532f115040165d18f74a55a4f39bb1dcfd865e94a + 488ca910cc447e121b2a19450239e75d24 diff --git a/tests/usr.bin/diff/d_mallocv2.in b/tests/usr.bin/diff/d_mallocv2.in new file mode 100644 index 000000000..27ab50336 --- /dev/null +++ b/tests/usr.bin/diff/d_mallocv2.in @@ -0,0 +1,5 @@ +18086b1e91f730facb2d6e1b +c562653b24814eb3651b1e68301a3c14b96302bb +6d017f7aef74662ed8dd51eef14281eaad223298db370bfaca +30c04231cb3de404e4b8a5359a74066fd963291d7986be835834ab07870c097682a953bfff38784780eef844de47fb36c34f8e034c96cfa64d9cb5decee472138236e9fb79e9fe1fba6b7757b970f22477d167832206900473f09f3e8c822db6d9a8273340ed6743d99638d6cf192d821b6f33d23278b1a929f303a80865c426d01add11b2f2416babd13e70b44d8eeb731c09c7163af9d1a23cbe20ddb08b0f67ecaa2eed511263a67e9c12e59ef113f0b9e4e4e140b43896078a7571c61826ba099b3dd8c4b096a9785b4434e97ea99e662ba6fdb60a41547ccae4c67d3e1f3ef515198e91f009c75c9e80fda90d13ee29d8aad5d87cc2437ce60e6ce55700837fb0815bfd2495f8aa1a33fe67c1ae28a885506a78ca6257f5a5f2a8042e28680acc83b1aecb3a9cb51911126f2f0deaf14fcfa5f165e9a5c3f8f2d1c3f4683b2d75927a7bc802d63b680a5e22768cc0439854ccd49e58a002794f541bddd6ef6fbd4f9869843a72d0ae9d438c90353a46c0c9863a16b1de206c717ab7ce6ea6f648a38efa12b70bbe3388b35adec7a789ea98de217520d7d6ce699841e17e5946bf5a8b3c7a2c3e2d6767422baf3159ff08d913ec78011ab7d34bc24af26c24a8d46f7261c7705a7b270e27590c29583c659a0df8dada4e7a0532f115040165d18f74a55a4f39bb1dcfd865e94a + 488ca910cc447e121b2a19450239e75d24 diff --git a/tests/usr.bin/diff/t_diff.sh b/tests/usr.bin/diff/t_diff.sh new file mode 100644 index 000000000..e33edeeb3 --- /dev/null +++ b/tests/usr.bin/diff/t_diff.sh @@ -0,0 +1,75 @@ +# $NetBSD: t_diff.sh,v 1.3 2012/03/13 05:40:00 jruoho Exp $ +# +# Copyright (c) 2011 The NetBSD Foundation, Inc. +# All rights reserved. +# +# This code is derived from software contributed to The NetBSD Foundation +# by Jukka Ruohonen. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +atf_test_case mallocv +mallocv_head() { + atf_set "descr" "Test diff(1) with MALLOC_OPTIONS=V (cf. PR bin/26453)" +} + +mallocv_body() { + + atf_check -s ignore \ + -e not-inline:"diff: memory exhausted\n" \ + -x "env MALLOC_OPTIONS=V diff " \ + "$(atf_get_srcdir)/d_mallocv1.in" \ + "$(atf_get_srcdir)/d_mallocv2.in" +} + +atf_test_case nomallocv +nomallocv_head() { + atf_set "descr" "Test diff(1) with no MALLOC_OPTIONS=V" +} + +nomallocv_body() { + + atf_check -s exit:0 \ + -e inline:"" \ + -x "diff " \ + "$(atf_get_srcdir)/d_mallocv1.in" \ + "$(atf_get_srcdir)/d_mallocv2.in" +} + +atf_test_case same +same_head() { + atf_set "descr" "Test diff(1) with identical files" +} + +same_body() { + + atf_check -s exit:0 \ + -e inline:"" \ + -x "diff $(atf_get_srcdir)/t_diff $(atf_get_srcdir)/t_diff" +} + +atf_init_test_cases() { + atf_add_test_case mallocv + atf_add_test_case nomallocv + atf_add_test_case same +} diff --git a/tests/usr.bin/dirname/Makefile b/tests/usr.bin/dirname/Makefile new file mode 100644 index 000000000..9d893cbf6 --- /dev/null +++ b/tests/usr.bin/dirname/Makefile @@ -0,0 +1,8 @@ +# $NetBSD: Makefile,v 1.1 2012/03/17 16:33:13 jruoho Exp $ + +.include + +TESTSDIR= ${TESTSBASE}/usr.bin/dirname +TESTS_SH= t_dirname + +.include diff --git a/tests/usr.bin/dirname/t_dirname.sh b/tests/usr.bin/dirname/t_dirname.sh new file mode 100644 index 000000000..a3935249f --- /dev/null +++ b/tests/usr.bin/dirname/t_dirname.sh @@ -0,0 +1,49 @@ +# $NetBSD: t_dirname.sh,v 1.1 2012/03/17 16:33:13 jruoho Exp $ +# +# Copyright (c) 2008 The NetBSD Foundation, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +atf_test_case basic +basic_head() +{ + atf_set "descr" "Checks basic functionality" +} +basic_body() +{ + atf_check -o inline:"/\n" dirname / + atf_check -o inline:"/\n" dirname // + atf_check -o inline:"/usr\n" dirname /usr/bin/ + atf_check -o inline:"//usr\n" dirname //usr//bin// + atf_check -o inline:".\n" dirname usr + atf_check -o inline:".\n" dirname "" + atf_check -o inline:"/\n" dirname /usr + atf_check -o inline:"/usr\n" dirname /usr/bin + atf_check -o inline:"usr\n" dirname usr/bin +} + +atf_init_test_cases() +{ + atf_add_test_case basic +} diff --git a/tests/usr.bin/find/Makefile b/tests/usr.bin/find/Makefile new file mode 100644 index 000000000..e9a4c7bd1 --- /dev/null +++ b/tests/usr.bin/find/Makefile @@ -0,0 +1,8 @@ +# $NetBSD: Makefile,v 1.1 2012/03/18 12:40:42 jruoho Exp $ + +.include + +TESTSDIR= ${TESTSBASE}/usr.bin/find +TESTS_SH= t_find + +.include diff --git a/tests/usr.bin/find/t_find.sh b/tests/usr.bin/find/t_find.sh new file mode 100644 index 000000000..b30de5eee --- /dev/null +++ b/tests/usr.bin/find/t_find.sh @@ -0,0 +1,73 @@ +# $NetBSD: t_find.sh,v 1.6 2012/03/19 12:58:41 jruoho Exp $ +# +# Copyright (c) 2012 The NetBSD Foundation, Inc. +# All rights reserved. +# +# This code is derived from software contributed to The NetBSD Foundation +# by Jukka Ruohonen. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +atf_test_case emptyperm +emptyperm_head() { + atf_set "descr" "Test that 'find -empty' does not error out " \ + "when directory access is denied (PR bin/44179)" + atf_set "require.user" "unprivileged" +} + +emptyperm_body() { + + # The case assumes that at least some directories + # in /var are unavailable for the user '_tests'. + # + # TODO: Parse the output.file for actual verification. + # + atf_check -s exit:1 -o save:output.file \ + -e not-empty -x "find /var -empty -type d" +} + +atf_test_case exit +exit_head() { + atf_set "descr" "Test that find(1) with -exit works (PR bin/44973)" +} + +exit_body() { + atf_check -o ignore \ + -s exit:0 -x "find /etc -type f -exit" +} + +atf_test_case exit_status +exit_status_head() { + atf_set "descr" "Test exit status from 'find -exit'" +} + +exit_status_body() { + num=$(jot -r 1 0 99) + atf_check -o ignore -e ignore -s exit:$num -x "find / -exit $num" +} + +atf_init_test_cases() { + atf_add_test_case emptyperm + atf_add_test_case exit + atf_add_test_case exit_status +} diff --git a/tests/usr.bin/grep/Makefile b/tests/usr.bin/grep/Makefile new file mode 100644 index 000000000..34d49d564 --- /dev/null +++ b/tests/usr.bin/grep/Makefile @@ -0,0 +1,39 @@ +# $NetBSD: Makefile,v 1.1 2012/03/17 16:33:13 jruoho Exp $ + +NOMAN= # defined + +.include + +TESTSDIR= ${TESTSBASE}/usr.bin/grep + +TESTS_SH= t_grep + +FILESDIR= ${TESTSDIR} +FILES= d_basic.out +FILES+= d_begin_end_a.out +FILES+= d_begin_end_b.out +FILES+= d_binary.out +FILES+= d_context2_a.out +FILES+= d_context2_b.out +FILES+= d_context2_c.out +FILES+= d_context_a.in +FILES+= d_context_a.out +FILES+= d_context_b.in +FILES+= d_context_b.out +FILES+= d_context_c.out +FILES+= d_context_d.out +FILES+= d_egrep.out +FILES+= d_file_exp.in +FILES+= d_file_exp.out +FILES+= d_ignore_case.out +FILES+= d_input +FILES+= d_invert.in +FILES+= d_invert.out +FILES+= d_recurse.out +FILES+= d_recurse_symlink.err +FILES+= d_recurse_symlink.out +FILES+= d_whole_line.out +FILES+= d_word_regexps.out +FILES+= d_zgrep.out + +.include diff --git a/tests/usr.bin/grep/d_basic.out b/tests/usr.bin/grep/d_basic.out new file mode 100644 index 000000000..ccefccb1c --- /dev/null +++ b/tests/usr.bin/grep/d_basic.out @@ -0,0 +1,20 @@ +123 +1123 +1230 +1231 +1232 +1233 +1234 +1235 +1236 +1237 +1238 +1239 +2123 +3123 +4123 +5123 +6123 +7123 +8123 +9123 diff --git a/tests/usr.bin/grep/d_begin_end_a.out b/tests/usr.bin/grep/d_begin_end_a.out new file mode 100644 index 000000000..3288aec66 --- /dev/null +++ b/tests/usr.bin/grep/d_begin_end_a.out @@ -0,0 +1 @@ +Front of the line diff --git a/tests/usr.bin/grep/d_begin_end_b.out b/tests/usr.bin/grep/d_begin_end_b.out new file mode 100644 index 000000000..dd09e02da --- /dev/null +++ b/tests/usr.bin/grep/d_begin_end_b.out @@ -0,0 +1 @@ +This is a another line with a Front and an ending diff --git a/tests/usr.bin/grep/d_binary.out b/tests/usr.bin/grep/d_binary.out new file mode 100644 index 000000000..ce0305613 --- /dev/null +++ b/tests/usr.bin/grep/d_binary.out @@ -0,0 +1 @@ +Binary file /bin/sh matches diff --git a/tests/usr.bin/grep/d_context2_a.out b/tests/usr.bin/grep/d_context2_a.out new file mode 100644 index 000000000..384d280aa Binary files /dev/null and b/tests/usr.bin/grep/d_context2_a.out differ diff --git a/tests/usr.bin/grep/d_context2_b.out b/tests/usr.bin/grep/d_context2_b.out new file mode 100644 index 000000000..c1d122237 Binary files /dev/null and b/tests/usr.bin/grep/d_context2_b.out differ diff --git a/tests/usr.bin/grep/d_context2_c.out b/tests/usr.bin/grep/d_context2_c.out new file mode 100644 index 000000000..1692c2aa8 Binary files /dev/null and b/tests/usr.bin/grep/d_context2_c.out differ diff --git a/tests/usr.bin/grep/d_context_a.in b/tests/usr.bin/grep/d_context_a.in new file mode 100644 index 000000000..670e4cefc --- /dev/null +++ b/tests/usr.bin/grep/d_context_a.in @@ -0,0 +1,10 @@ +A pig is a jolly companion, +Boar, sow, barrow, or gilt -- +A pig is a pal, who'll boost your morale, +Though mountains may topple and tilt. +When they've blackballed, bamboozled, and burned you, +When they've turned on you, Tory and Whig, +Though you may be thrown over by Tabby and Rover, +You'll never go wrong with a pig, a pig, +You'll never go wrong with a pig! + -- Thomas Pynchon, "Gravity's Rainbow" diff --git a/tests/usr.bin/grep/d_context_a.out b/tests/usr.bin/grep/d_context_a.out new file mode 100644 index 000000000..5788aa5a3 --- /dev/null +++ b/tests/usr.bin/grep/d_context_a.out @@ -0,0 +1,5 @@ +A pig is a pal, who'll boost your morale, +Though mountains may topple and tilt. +When they've blackballed, bamboozled, and burned you, +When they've turned on you, Tory and Whig, +Though you may be thrown over by Tabby and Rover, diff --git a/tests/usr.bin/grep/d_context_b.in b/tests/usr.bin/grep/d_context_b.in new file mode 100644 index 000000000..663c9928a --- /dev/null +++ b/tests/usr.bin/grep/d_context_b.in @@ -0,0 +1,3 @@ +This is to test output of context from multiple files. +Dave was a happy pig who wandered around the orchard eating +apples all day long. diff --git a/tests/usr.bin/grep/d_context_b.out b/tests/usr.bin/grep/d_context_b.out new file mode 100644 index 000000000..aa18352e6 --- /dev/null +++ b/tests/usr.bin/grep/d_context_b.out @@ -0,0 +1,4 @@ +Though mountains may topple and tilt. +When they've blackballed, bamboozled, and burned you, +When they've turned on you, Tory and Whig, +Though you may be thrown over by Tabby and Rover, diff --git a/tests/usr.bin/grep/d_context_c.out b/tests/usr.bin/grep/d_context_c.out new file mode 100644 index 000000000..f91b7123c --- /dev/null +++ b/tests/usr.bin/grep/d_context_c.out @@ -0,0 +1,5 @@ +Boar, sow, barrow, or gilt -- +A pig is a pal, who'll boost your morale, +Though mountains may topple and tilt. +When they've blackballed, bamboozled, and burned you, +When they've turned on you, Tory and Whig, diff --git a/tests/usr.bin/grep/d_context_d.out b/tests/usr.bin/grep/d_context_d.out new file mode 100644 index 000000000..225df6937 --- /dev/null +++ b/tests/usr.bin/grep/d_context_d.out @@ -0,0 +1,13 @@ +d_context_a.in:A pig is a jolly companion, +d_context_a.in-Boar, sow, barrow, or gilt -- +d_context_a.in:A pig is a pal, who'll boost your morale, +d_context_a.in-Though mountains may topple and tilt. +-- +d_context_a.in-Though you may be thrown over by Tabby and Rover, +d_context_a.in:You'll never go wrong with a pig, a pig, +d_context_a.in:You'll never go wrong with a pig! +d_context_a.in- -- Thomas Pynchon, "Gravity's Rainbow" +-- +d_context_b.in-This is to test output of context from multiple files. +d_context_b.in:Dave was a happy pig who wandered around the orchard eating +d_context_b.in-apples all day long. diff --git a/tests/usr.bin/grep/d_egrep.out b/tests/usr.bin/grep/d_egrep.out new file mode 100644 index 000000000..2cc0277e4 --- /dev/null +++ b/tests/usr.bin/grep/d_egrep.out @@ -0,0 +1 @@ +Special characters [, $, ^, * diff --git a/tests/usr.bin/grep/d_file_exp.in b/tests/usr.bin/grep/d_file_exp.in new file mode 100644 index 000000000..9faee939e --- /dev/null +++ b/tests/usr.bin/grep/d_file_exp.in @@ -0,0 +1,2 @@ +-0.[24]0 +0.[35]0 diff --git a/tests/usr.bin/grep/d_file_exp.out b/tests/usr.bin/grep/d_file_exp.out new file mode 100644 index 000000000..7d9752226 --- /dev/null +++ b/tests/usr.bin/grep/d_file_exp.out @@ -0,0 +1,6 @@ +-0.50 +-0.40 +-0.30 +-0.20 +0.30 +0.50 diff --git a/tests/usr.bin/grep/d_ignore_case.out b/tests/usr.bin/grep/d_ignore_case.out new file mode 100644 index 000000000..c14d8dd38 --- /dev/null +++ b/tests/usr.bin/grep/d_ignore_case.out @@ -0,0 +1,2 @@ +Mostly I prefer lower case to upper case, +but UpPeR cAsE has its merits too. diff --git a/tests/usr.bin/grep/d_input b/tests/usr.bin/grep/d_input new file mode 100644 index 000000000..5e38c39ed --- /dev/null +++ b/tests/usr.bin/grep/d_input @@ -0,0 +1,12 @@ +dot.separated@words +kkseparatedkk +Front of the line +This is a another line with a Front and an ending +Special characters [, $, ^, * +Here is another ending. + +Mostly I prefer lower case to upper case, +but UpPeR cAsE has its merits too. + +matchme + diff --git a/tests/usr.bin/grep/d_invert.in b/tests/usr.bin/grep/d_invert.in new file mode 100644 index 000000000..631cf834c --- /dev/null +++ b/tests/usr.bin/grep/d_invert.in @@ -0,0 +1,10 @@ + +fish +fish +dog +cat +fish +fish + +poodle +fish diff --git a/tests/usr.bin/grep/d_invert.out b/tests/usr.bin/grep/d_invert.out new file mode 100644 index 000000000..7d7c54a18 --- /dev/null +++ b/tests/usr.bin/grep/d_invert.out @@ -0,0 +1,5 @@ + +dog +cat + +poodle diff --git a/tests/usr.bin/grep/d_recurse.out b/tests/usr.bin/grep/d_recurse.out new file mode 100644 index 000000000..0ba61c83b --- /dev/null +++ b/tests/usr.bin/grep/d_recurse.out @@ -0,0 +1,2 @@ +recurse/a/f/favourite-fish:haddock +recurse/d/fish:haddock diff --git a/tests/usr.bin/grep/d_recurse_symlink.err b/tests/usr.bin/grep/d_recurse_symlink.err new file mode 100644 index 000000000..b4bff9829 --- /dev/null +++ b/tests/usr.bin/grep/d_recurse_symlink.err @@ -0,0 +1 @@ +grep: warning: test/c/d/d: recursive directory loop diff --git a/tests/usr.bin/grep/d_recurse_symlink.out b/tests/usr.bin/grep/d_recurse_symlink.out new file mode 100644 index 000000000..284923904 --- /dev/null +++ b/tests/usr.bin/grep/d_recurse_symlink.out @@ -0,0 +1 @@ +test/c/match:Test string diff --git a/tests/usr.bin/grep/d_whole_line.out b/tests/usr.bin/grep/d_whole_line.out new file mode 100644 index 000000000..16febeb04 --- /dev/null +++ b/tests/usr.bin/grep/d_whole_line.out @@ -0,0 +1 @@ +matchme diff --git a/tests/usr.bin/grep/d_word_regexps.out b/tests/usr.bin/grep/d_word_regexps.out new file mode 100644 index 000000000..e6c4af4a7 --- /dev/null +++ b/tests/usr.bin/grep/d_word_regexps.out @@ -0,0 +1 @@ +dot.separated@words diff --git a/tests/usr.bin/grep/d_zgrep.out b/tests/usr.bin/grep/d_zgrep.out new file mode 100644 index 000000000..c5fe9b8d4 --- /dev/null +++ b/tests/usr.bin/grep/d_zgrep.out @@ -0,0 +1,2 @@ +Front of the line +This is a another line with a Front and an ending diff --git a/tests/usr.bin/grep/t_grep.sh b/tests/usr.bin/grep/t_grep.sh new file mode 100644 index 000000000..f2d70f08b --- /dev/null +++ b/tests/usr.bin/grep/t_grep.sh @@ -0,0 +1,246 @@ +# $NetBSD: t_grep.sh,v 1.2 2013/05/17 15:39:17 christos Exp $ +# +# Copyright (c) 2008, 2009 The NetBSD Foundation, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +atf_test_case basic +basic_head() +{ + atf_set "descr" "Checks basic functionality" +} +basic_body() +{ + atf_check -o file:"$(atf_get_srcdir)/d_basic.out" -x \ + 'jot 10000 | grep 123' +} + +atf_test_case binary +binary_head() +{ + atf_set "descr" "Checks handling of binary files" +} +binary_body() +{ + atf_check -o file:"$(atf_get_srcdir)/d_binary.out" grep $(uname) /bin/sh +} + +atf_test_case recurse +recurse_head() +{ + atf_set "descr" "Checks recursive searching" +} +recurse_body() +{ + mkdir -p recurse/a/f recurse/d + echo -e "cod\ndover sole\nhaddock\nhalibut\npilchard" > recurse/d/fish + echo -e "cod\nhaddock\nplaice" > recurse/a/f/favourite-fish + + atf_check -o file:"$(atf_get_srcdir)/d_recurse.out" grep -r haddock recurse +} + +atf_test_case recurse_symlink +recurse_symlink_head() +{ + atf_set "descr" "Checks symbolic link recursion" +} +recurse_symlink_body() +{ + mkdir -p test/c/d + (cd test/c/d && ln -s ../d .) + echo "Test string" > test/c/match + + atf_check -o file:"$(atf_get_srcdir)/d_recurse_symlink.out" \ + -e file:"$(atf_get_srcdir)/d_recurse_symlink.err" \ + grep -r string test +} + +atf_test_case word_regexps +word_regexps_head() +{ + atf_set "descr" "Checks word-regexps" +} +word_regexps_body() +{ + atf_check -o file:"$(atf_get_srcdir)/d_word_regexps.out" \ + grep -w separated $(atf_get_srcdir)/d_input +} + +atf_test_case begin_end +begin_end_head() +{ + atf_set "descr" "Checks handling of line beginnings and ends" +} +begin_end_body() +{ + atf_check -o file:"$(atf_get_srcdir)/d_begin_end_a.out" \ + grep ^Front "$(atf_get_srcdir)/d_input" + + atf_check -o file:"$(atf_get_srcdir)/d_begin_end_b.out" \ + grep ending$ "$(atf_get_srcdir)/d_input" +} + +atf_test_case ignore_case +ignore_case_head() +{ + atf_set "descr" "Checks ignore-case option" +} +ignore_case_body() +{ + atf_check -o file:"$(atf_get_srcdir)/d_ignore_case.out" \ + grep -i Upper "$(atf_get_srcdir)/d_input" +} + +atf_test_case invert +invert_head() +{ + atf_set "descr" "Checks selecting non-matching lines with -v option" +} +invert_body() +{ + atf_check -o file:"$(atf_get_srcdir)/d_invert.out" \ + grep -v fish "$(atf_get_srcdir)/d_invert.in" +} + +atf_test_case whole_line +whole_line_head() +{ + atf_set "descr" "Checks whole-line matching with -x flag" +} +whole_line_body() +{ + atf_check -o file:"$(atf_get_srcdir)/d_whole_line.out" \ + grep -x matchme "$(atf_get_srcdir)/d_input" +} + +atf_test_case negative +negative_head() +{ + atf_set "descr" "Checks handling of files with no matches" +} +negative_body() +{ + atf_check -s ne:0 grep "not a hope in hell" "$(atf_get_srcdir)/d_input" +} + +atf_test_case context +context_head() +{ + atf_set "descr" "Checks displaying context with -A, -B and -C flags" +} +context_body() +{ + cp $(atf_get_srcdir)/d_context_*.* . + + atf_check -o file:d_context_a.out grep -C2 bamboo d_context_a.in + atf_check -o file:d_context_b.out grep -A3 tilt d_context_a.in + atf_check -o file:d_context_c.out grep -B4 Whig d_context_a.in + atf_check -o file:d_context_d.out grep -C1 pig d_context_a.in d_context_b.in +} + +atf_test_case file_exp +file_exp_head() +{ + atf_set "descr" "Checks reading expressions from file" +} +file_exp_body() +{ + atf_check -o file:"$(atf_get_srcdir)/d_file_exp.out" -x \ + 'jot 21 -1 1.00 | grep -f '"$(atf_get_srcdir)"'/d_file_exp.in' +} + +atf_test_case egrep +egrep_head() +{ + atf_set "descr" "Checks matching special characters with egrep" +} +egrep_body() +{ + atf_check -o file:"$(atf_get_srcdir)/d_egrep.out" \ + egrep '\?|\*$$' "$(atf_get_srcdir)/d_input" +} + +atf_test_case zgrep +zgrep_head() +{ + atf_set "descr" "Checks handling of gzipped files with zgrep" +} +zgrep_body() +{ + cp "$(atf_get_srcdir)/d_input" . + gzip d_input || atf_fail "gzip failed" + + atf_check -o file:"$(atf_get_srcdir)/d_zgrep.out" zgrep -h line d_input.gz +} + +atf_test_case nonexistent +nonexistent_head() +{ + atf_set "descr" "Checks that -s flag suppresses error" \ + "messages about nonexistent files" +} +nonexistent_body() +{ + atf_check -s ne:0 grep -s foobar nonexistent +} + +atf_test_case context2 +context2_head() +{ + atf_set "descr" "Checks displaying context with -z flag" +} +context2_body() +{ + printf "haddock\000cod\000plaice\000" > test1 + printf "mackeral\000cod\000crab\000" > test2 + + atf_check -o file:"$(atf_get_srcdir)/d_context2_a.out" \ + grep -z -A1 cod test1 test2 + + atf_check -o file:"$(atf_get_srcdir)/d_context2_b.out" \ + grep -z -B1 cod test1 test2 + + atf_check -o file:"$(atf_get_srcdir)/d_context2_c.out" \ + grep -z -C1 cod test1 test2 +} + +atf_init_test_cases() +{ + atf_add_test_case basic + atf_add_test_case binary + atf_add_test_case recurse + atf_add_test_case recurse_symlink + atf_add_test_case word_regexps + atf_add_test_case begin_end + atf_add_test_case ignore_case + atf_add_test_case invert + atf_add_test_case whole_line + atf_add_test_case negative + atf_add_test_case context + atf_add_test_case file_exp + atf_add_test_case egrep + atf_add_test_case zgrep + atf_add_test_case nonexistent + atf_add_test_case context2 +} diff --git a/tests/usr.bin/gzip/Makefile b/tests/usr.bin/gzip/Makefile new file mode 100644 index 000000000..55cb7c7a1 --- /dev/null +++ b/tests/usr.bin/gzip/Makefile @@ -0,0 +1,8 @@ +# $NetBSD: Makefile,v 1.1 2012/03/17 16:33:13 jruoho Exp $ + +.include + +TESTSDIR= ${TESTSBASE}/usr.bin/gzip +TESTS_SH= t_gzip + +.include diff --git a/tests/usr.bin/gzip/t_gzip.sh b/tests/usr.bin/gzip/t_gzip.sh new file mode 100644 index 000000000..bee665575 --- /dev/null +++ b/tests/usr.bin/gzip/t_gzip.sh @@ -0,0 +1,110 @@ +# $NetBSD: t_gzip.sh,v 1.1 2012/03/17 16:33:13 jruoho Exp $ +# +# Copyright (c) 2008 The NetBSD Foundation, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +atf_test_case concatenated +concatenated_head() +{ + atf_set "descr" "Checks concatenated gzipped data" +} +concatenated_body() +{ + echo -n "aaaa" | gzip > tmp.gz + echo -n "bbbb" | gzip >> tmp.gz + + atf_check -o inline:"aaaabbbb" gzip -d tmp.gz -c +} + +atf_test_case pipe +pipe_head() +{ + atf_set "descr" "Checks input from pipe" +} +pipe_body() +{ + atf_check -x "dd if=/dev/zero count=102400 2>/dev/null \ +| gzip -c | dd bs=1 2>/dev/null | gzip -tc" +} + +atf_test_case truncated +truncated_head() +{ + atf_set "descr" "Checks that gzip fails on truncated data" +} +truncated_body() +{ + cat >truncated.gz.uue <crcerror.gz.uue <good.gz.uue < + +TESTSDIR= ${TESTSBASE}/usr.bin/id + +TESTS_SH= t_groups +TESTS_SH+= t_id +TESTS_SH+= t_whoami + +BINDIR= ${TESTSDIR} +PROG= h_id +.if defined(__MINIX) +.PATH: ${NETBSDSRCDIR}/commands/id +.else +.PATH: ${NETBSDSRCDIR}/usr.bin/id +.endif # defined(__MINIX) +SRCS= id.c pwgr.c + +COPTS.id.c += -Wno-format-nonliteral + +.include diff --git a/tests/usr.bin/id/pwgr.c b/tests/usr.bin/id/pwgr.c new file mode 100644 index 000000000..364f64226 --- /dev/null +++ b/tests/usr.bin/id/pwgr.c @@ -0,0 +1,187 @@ +/* $NetBSD: pwgr.c,v 1.1 2012/03/17 16:33:14 jruoho Exp $ */ +/* + * Copyright (c) 2007 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This file implements replacements for all user/group-related functions + * called by id(1). It provides fake but deterministic user and group + * information. The details are as such: + * User root, uid 0, primary group 0 (wheel). + * User test, uid 100, primary group 100 (users), secondary group 0 (wheel). + */ + +#include + +#include +#include +#include +#include +#include +#include + +char Login[16]; +struct group GrEntry; +struct passwd PwEntry; + +gid_t +getgid(void) +{ + return 100; +} + +gid_t +getegid(void) +{ + if (getenv("LIBFAKE_EGID_ROOT") != NULL) + return 0; + else + return 100; +} + +uid_t +getuid(void) +{ + return 100; +} + +uid_t +geteuid(void) +{ + if (getenv("LIBFAKE_EUID_ROOT") != NULL) + return 0; + else + return 100; +} + +char * +getlogin(void) +{ + strcpy(Login, "test"); + return Login; +} + +struct group * +getgrgid(gid_t gid) +{ + struct group *g = &GrEntry; + + memset(g, 0, sizeof(*g)); + if (gid == 0) { + g->gr_name = __UNCONST("wheel"); + g->gr_gid = 0; + } else if (gid == 100) { + g->gr_name = __UNCONST("users"); + g->gr_gid = 100; + } else + g = NULL; + + return g; +} + +int +getgrouplist(const char *name, gid_t basegid, gid_t *groups, int *ngroups) +{ + int cnt, ret; + + if (strcmp(name, "root") == 0) { + if (*ngroups >= 1) { + groups[0] = basegid; + cnt = 1; + } + + ret = (*ngroups >= cnt) ? 0 : -1; + *ngroups = cnt; + } else if (strcmp(name, "test") == 0) { + if (*ngroups >= 1) { + groups[0] = basegid; + cnt = 1; + } + + if (*ngroups >= 2) { + groups[1] = 0; + cnt = 2; + } + + ret = (*ngroups >= cnt) ? 0 : -1; + *ngroups = cnt; + } else + ret = -1; + + return ret; +} + +int +getgroups(int gidsetlen, gid_t *gidset) +{ + if (gidsetlen < 2) { + errno = EINVAL; + return -1; + } + + gidset[0] = 100; + gidset[1] = 0; + return 2; +} + +struct passwd * +getpwnam(const char *login) +{ + struct passwd *p = &PwEntry; + + memset(p, 0, sizeof(*p)); + if (strcmp(login, "root") == 0) { + p->pw_name = __UNCONST("root"); + p->pw_uid = 0; + p->pw_gid = 0; + } else if (strcmp(login, "test") == 0) { + p->pw_name = __UNCONST("test"); + p->pw_uid = 100; + p->pw_gid = 100; + } else + p = NULL; + + return p; +} + +struct passwd * +getpwuid(uid_t uid) +{ + struct passwd *p = &PwEntry; + + memset(p, 0, sizeof(*p)); + if (uid == 0) { + p->pw_name = __UNCONST("root"); + p->pw_uid = 0; + p->pw_gid = 0; + } else if (uid == 100) { + p->pw_name = __UNCONST("test"); + p->pw_uid = 100; + p->pw_gid = 100; + } else + p = NULL; + + return p; +} diff --git a/tests/usr.bin/id/t_groups.sh b/tests/usr.bin/id/t_groups.sh new file mode 100644 index 000000000..71121ab38 --- /dev/null +++ b/tests/usr.bin/id/t_groups.sh @@ -0,0 +1,71 @@ +# $NetBSD: t_groups.sh,v 1.1 2012/03/17 16:33:14 jruoho Exp $ +# +# Copyright (c) 2007, 2008 The NetBSD Foundation, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +create_run_groups() { + cat >run_groups.sh <expout + atf_check -s eq:0 -o file:expout -e empty ./run_groups.sh + atf_check -s eq:0 -o file:expout -e empty ./run_groups.sh 100 + atf_check -s eq:0 -o file:expout -e empty ./run_groups.sh test + + echo "wheel" >expout + atf_check -s eq:0 -o file:expout -e empty ./run_groups.sh 0 + atf_check -s eq:0 -o file:expout -e empty ./run_groups.sh root +} + +atf_test_case syntax +syntax_head() { + atf_set "descr" "Checks the command's syntax" +} +syntax_body() { + create_run_groups + + # Give an invalid flag but which is allowed by id (with which + # groups shares code) when using the -Gn options. + atf_check -s eq:1 -o empty -e save:stderr ./run_groups.sh -r + atf_check -s eq:0 -o ignore -e empty grep '^usage:' stderr +} + +atf_init_test_cases() +{ + atf_add_test_case correct + atf_add_test_case syntax +} diff --git a/tests/usr.bin/id/t_id.sh b/tests/usr.bin/id/t_id.sh new file mode 100644 index 000000000..9c877a6db --- /dev/null +++ b/tests/usr.bin/id/t_id.sh @@ -0,0 +1,305 @@ +# $NetBSD: t_id.sh,v 1.1 2012/03/17 16:33:14 jruoho Exp $ +# +# Copyright (c) 2007, 2008 The NetBSD Foundation, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +create_run_id() { + cat >run_id.sh <expout + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh 100 + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh test + + echo "uid=0(root) gid=0(wheel) groups=0(wheel)" >expout + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh 0 + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh root + + export LIBFAKE_EGID_ROOT=1 LIBFAKE_EUID_ROOT=1 + echo "uid=100(test) gid=100(users) euid=0(root) egid=0(wheel) groups=100(users),0(wheel)" >expout + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh + unset LIBFAKE_EGID_ROOT LIBFAKE_EUID_ROOT + + echo 'id: nonexistent: No such user' >experr + atf_check -s eq:1 -o empty -e file:experr ./run_id.sh nonexistent + + atf_check -s eq:1 -o empty -e save:stderr ./run_id.sh root nonexistent + atf_check -s eq:0 -o ignore -e empty grep ^usage: stderr +} + +atf_test_case primaries +primaries_head() { + atf_set "descr" "Checks that giving multiple primaries" \ + "simultaneously provides an error" +} +primaries_body() { + create_run_id + + for p1 in -G -g -p -u; do + for p2 in -G -g -p -u; do + if [ ${p1} != ${p2} ]; then + atf_check -s eq:1 -o empty -e save:stderr \ + ./run_id.sh ${p1} ${p2} + atf_check -s eq:0 -o ignore -e empty \ + grep ^usage: stderr + fi + done + done +} + +atf_test_case Gflag +Gflag_head() { + atf_set "descr" "Checks that the -G primary flag works" +} +Gflag_body() { + create_run_id + + echo "100 0" >expout + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -G + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -G 100 + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -G test + + echo "users wheel" >expout + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -G -n + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -G -n 100 + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -G -n test + + echo "0" >expout + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -G 0 + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -G root + + echo "wheel" >expout + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -G -n 0 + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -G -n root + + echo 'id: nonexistent: No such user' >experr + atf_check -s eq:1 -o empty -e file:experr ./run_id.sh -G nonexistent + + atf_check -s eq:1 -o empty -e save:stderr ./run_id.sh -G root nonexistent + atf_check -s eq:0 -o ignore -e empty grep ^usage: stderr +} + +atf_test_case gflag +gflag_head() { + atf_set "descr" "Checks that the -g primary flag works" +} +gflag_body() { + create_run_id + + echo "100" >expout + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -g + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -g 100 + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -g test + + echo "users" >expout + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -g -n + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -g -n 100 + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -g -n test + + echo "0" >expout + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -g 0 + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -g root + + echo "wheel" >expout + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -g -n 0 + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -g -n root + + echo "100" >expout + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -g -r + + echo "users" >expout + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -g -r -n + + echo "100" >expout + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -g -r 100 + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -g -r test + + echo "users" >expout + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -g -r -n 100 + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -g -r -n test + + export LIBFAKE_EGID_ROOT=1 LIBFAKE_EUID_ROOT=1 + + echo "0" >expout + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -g + + echo "wheel" >expout + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -g -n + + echo "100" >expout + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -g -r + + echo "users" >expout + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -g -r -n + + echo "100" >expout + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -g -r 100 + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -g -r test + + echo "users" >expout + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -g -r -n 100 + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -g -r -n test + + unset LIBFAKE_EGID_ROOT LIBFAKE_EUID_ROOT + + echo 'id: nonexistent: No such user' >experr + atf_check -s eq:1 -o empty -e file:experr ./run_id.sh -g nonexistent + + atf_check -s eq:1 -o empty -e save:stderr ./run_id.sh -g root nonexistent + atf_check -s eq:0 -o ignore -e empty grep ^usage: stderr +} + +atf_test_case pflag +pflag_head() { + atf_set "descr" "Checks that the -p primary flag works" +} +pflag_body() { + create_run_id + + cat >expout <expout <expout <experr + atf_check -s eq:1 -o empty -e file:experr ./run_id.sh -p nonexistent + + atf_check -s eq:1 -o empty -e save:stderr ./run_id.sh -p root nonexistent + atf_check -s eq:0 -o ignore -e empty grep ^usage: stderr +} + +atf_test_case uflag +uflag_head() { + atf_set "descr" "Checks that the -u primary flag works" +} +uflag_body() { + create_run_id + + echo "100" >expout + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -u + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -u 100 + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -u test + + echo "test" >expout + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -u -n + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -u -n 100 + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -u -n test + + echo "0" >expout + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -u 0 + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -u root + + echo "root" >expout + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -u -n 0 + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -u -n root + + echo "100" >expout + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -u -r + + echo "test" >expout + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -u -r -n + + echo "100" >expout + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -u -r 100 + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -u -r test + + echo "test" >expout + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -u -r -n 100 + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -u -r -n test + + export LIBFAKE_EGID_ROOT=1 LIBFAKE_EUID_ROOT=1 + + echo "0" >expout + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -u + + echo "root" >expout + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -u -n + + echo "100" >expout + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -u -r + + echo "test" >expout + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -u -r -n + + echo "100" >expout + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -u -r 100 + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -u -r test + + echo "test" >expout + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -u -r -n 100 + atf_check -s eq:0 -o file:expout -e empty ./run_id.sh -u -r -n test + + unset LIBFAKE_EGID_ROOT LIBFAKE_EUID_ROOT + + echo 'id: nonexistent: No such user' >experr + atf_check -s eq:1 -o empty -e file:experr ./run_id.sh -u nonexistent + + atf_check -s eq:1 -o empty -e save:stderr \ + ./run_id.sh -u root nonexistent + atf_check -s eq:0 -o ignore -e empty grep ^usage: stderr +} + +atf_init_test_cases() +{ + atf_add_test_case default + atf_add_test_case primaries + atf_add_test_case Gflag + atf_add_test_case gflag + atf_add_test_case pflag + atf_add_test_case uflag +} diff --git a/tests/usr.bin/id/t_whoami.sh b/tests/usr.bin/id/t_whoami.sh new file mode 100644 index 000000000..c8df7452e --- /dev/null +++ b/tests/usr.bin/id/t_whoami.sh @@ -0,0 +1,75 @@ +# $NetBSD: t_whoami.sh,v 1.1 2012/03/17 16:33:14 jruoho Exp $ +# +# Copyright (c) 2007, 2008 The NetBSD Foundation, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +create_run_whoami() { + cat >run_whoami.sh <expout + atf_check -s eq:0 -o file:expout -e empty ./run_whoami.sh + + echo "Checking with EUID=0" + export LIBFAKE_EUID_ROOT=1 + echo "root" >expout + atf_check -s eq:0 -o file:expout -e empty ./run_whoami.sh +} + +atf_test_case syntax +syntax_head() { + atf_set "descr" "Checks the command's syntax" +} +syntax_body() { + create_run_whoami + + # Give a user to the command. + echo 'usage: whoami' >experr + atf_check -s eq:1 -o empty -e file:experr ./run_whoami.sh root + + # Give an invalid flag but which is allowed by id (with which + # whoami shares code) when using the -un options. + echo 'usage: whoami' >experr + atf_check -s eq:1 -o empty -e file:experr ./run_whoami.sh -r +} + +atf_init_test_cases() +{ + atf_add_test_case correct + atf_add_test_case syntax +} diff --git a/tests/usr.bin/infocmp/Makefile b/tests/usr.bin/infocmp/Makefile new file mode 100644 index 000000000..706832cc0 --- /dev/null +++ b/tests/usr.bin/infocmp/Makefile @@ -0,0 +1,9 @@ +# $NetBSD: Makefile,v 1.1 2012/06/06 21:23:10 martin Exp $ + +.include + +TESTSDIR= ${TESTSBASE}/usr.bin/infocmp + +TESTS_SH= t_terminfo + +.include diff --git a/tests/usr.bin/infocmp/t_terminfo.sh b/tests/usr.bin/infocmp/t_terminfo.sh new file mode 100644 index 000000000..8ede24058 --- /dev/null +++ b/tests/usr.bin/infocmp/t_terminfo.sh @@ -0,0 +1,62 @@ +# $NetBSD: t_terminfo.sh,v 1.1 2012/06/06 21:23:10 martin Exp $ +# +# Copyright (c) 2011 The NetBSD Foundation, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +atf_test_case basic +basic_head() { + atf_set "descr" "infocmp can decode one of some existing term types" + atf_set "require.progs" "infocmp env" +} + +basic_body() { + for term in ansi vt100 wsvt25 sun-ss5 ibcs2 vt52 386at h19k h19kermit + do + atf_check -s exit:0 -e empty -o not-empty \ + env TERM="${term}" infocmp + done +} + +atf_test_case missing +missing_head() { + atf_set "descr" "infocmp fails to decode non existent entries" + atf_set "require.progs" "infocmp env" +} + +missing_body() { + for term in this-is-no-term nonexistent + do + atf_check -s not-exit:0 -e not-empty -o empty \ + env TERM="${term}" infocmp + done +} + +atf_init_test_cases() +{ + + atf_add_test_case basic + atf_add_test_case missing +} + diff --git a/tests/usr.bin/jot/Makefile b/tests/usr.bin/jot/Makefile new file mode 100644 index 000000000..70897ea23 --- /dev/null +++ b/tests/usr.bin/jot/Makefile @@ -0,0 +1,11 @@ +# $NetBSD: Makefile,v 1.2 2012/03/20 17:13:44 jruoho Exp $ + +.include + +TESTSDIR= ${TESTSBASE}/usr.bin/jot +TESTS_SH= t_jot + +FILESDIR= ${TESTSDIR} +FILES+= d_basic.out + +.include diff --git a/tests/usr.bin/jot/d_basic.out b/tests/usr.bin/jot/d_basic.out new file mode 100644 index 000000000..89b0879a5 --- /dev/null +++ b/tests/usr.bin/jot/d_basic.out @@ -0,0 +1,21 @@ +-1.00 +-0.90 +-0.80 +-0.70 +-0.60 +-0.50 +-0.40 +-0.30 +-0.20 +-0.10 +-0.00 +0.10 +0.20 +0.30 +0.40 +0.50 +0.60 +0.70 +0.80 +0.90 +1.00 diff --git a/tests/usr.bin/jot/t_jot.sh b/tests/usr.bin/jot/t_jot.sh new file mode 100644 index 000000000..bcdae329c --- /dev/null +++ b/tests/usr.bin/jot/t_jot.sh @@ -0,0 +1,56 @@ +# $NetBSD: t_jot.sh,v 1.1 2012/03/20 06:18:34 jruoho Exp $ +# +# Copyright (c) 2012 The NetBSD Foundation, Inc. +# All rights reserved. +# +# This code is derived from software contributed to The NetBSD Foundation +# by Jukka Ruohonen. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +atf_test_case basic +basic_head() { + atf_set "descr" "Test that jot(1)'s output is sane (PR bin/12424)" +} + +basic_body() { + atf_check -o file:"$(atf_get_srcdir)/d_basic.out" jot 21 -1 1.00 +} + +atf_test_case format +format_head() { + atf_set "descr" "Test that jot(1) handles format strings " \ + "correctly (PR bin/12316, PR bin/14253)" +} + +format_body() { + atf_check -s exit:0 -o ignore jot -w xa%c 26 a + atf_check -s not-exit:0 -e not-empty jot -w %2 12 + atf_check -s not-exit:0 -e not-empty jot -w %0 10 1 10 +} + +atf_init_test_cases() +{ + atf_add_test_case basic + atf_add_test_case format +} diff --git a/tests/usr.bin/m4/Makefile b/tests/usr.bin/m4/Makefile new file mode 100644 index 000000000..c78d0204f --- /dev/null +++ b/tests/usr.bin/m4/Makefile @@ -0,0 +1,19 @@ +# $NetBSD: Makefile,v 1.1 2012/03/17 16:33:14 jruoho Exp $ + +NOMAN= # defined + +.include + +TESTSDIR= ${TESTSBASE}/usr.bin/m4 + +TESTS_SH= t_m4 + +FILESDIR= ${TESTSDIR} +FILES= d_ff_after_dnl.m4.uue +FILES+= d_ff_after_dnl.out +FILES+= d_m4wrap-P.m4 +FILES+= d_m4wrap-P.out +FILES+= d_m4wrap.m4 +FILES+= d_m4wrap.out + +.include diff --git a/tests/usr.bin/m4/d_ff_after_dnl.m4.uue b/tests/usr.bin/m4/d_ff_after_dnl.m4.uue new file mode 100644 index 000000000..8b900447d --- /dev/null +++ b/tests/usr.bin/m4/d_ff_after_dnl.m4.uue @@ -0,0 +1,9 @@ +$NetBSD: d_ff_after_dnl.m4.uue,v 1.1 2012/03/17 16:33:14 jruoho Exp $ + +begin 644 d_ff_after_dnl.m4 +M"0E42$E3(%-(3U5,1"!32$]7(%50("A,24Y%(#$I"F1N;`D)5$A)4R!32$]5 +M3$0@3D]4(%-(3U<@55`@*$Q)3D4@,BD*9&YL_PD)5$A)4R!32$]53$0@3D]4 +M(%-(3U<@55`@*$Q)3D4@,RD*9&YL"?\)5$A)4R!32$]53$0@3D]4(%-(3U<@ +K55`@*$Q)3D4@-"D*"0E42$E3(%-(3U5,1"!32$]7(%50("A,24Y%(#4I"E<@ +` +end diff --git a/tests/usr.bin/m4/d_ff_after_dnl.out b/tests/usr.bin/m4/d_ff_after_dnl.out new file mode 100644 index 000000000..8e51f1ea0 --- /dev/null +++ b/tests/usr.bin/m4/d_ff_after_dnl.out @@ -0,0 +1,2 @@ + THIS SHOULD SHOW UP (LINE 1) + THIS SHOULD SHOW UP (LINE 5) diff --git a/tests/usr.bin/m4/d_m4wrap-P.m4 b/tests/usr.bin/m4/d_m4wrap-P.m4 new file mode 100644 index 000000000..e0298587f --- /dev/null +++ b/tests/usr.bin/m4/d_m4wrap-P.m4 @@ -0,0 +1,5 @@ +m4_dnl $NetBSD: d_m4wrap-P.m4,v 1.1 2012/03/17 16:33:14 jruoho Exp $ +m4_define(`ateof', `TEXT AT EOF +')m4_dnl +m4_m4wrap(`ateof()')m4_dnl +TEXT IN BODY diff --git a/tests/usr.bin/m4/d_m4wrap-P.out b/tests/usr.bin/m4/d_m4wrap-P.out new file mode 100644 index 000000000..a1bc22a09 --- /dev/null +++ b/tests/usr.bin/m4/d_m4wrap-P.out @@ -0,0 +1,2 @@ +TEXT IN BODY +TEXT AT EOF diff --git a/tests/usr.bin/m4/d_m4wrap.m4 b/tests/usr.bin/m4/d_m4wrap.m4 new file mode 100644 index 000000000..b74db961c --- /dev/null +++ b/tests/usr.bin/m4/d_m4wrap.m4 @@ -0,0 +1,5 @@ +dnl $NetBSD: d_m4wrap.m4,v 1.1 2012/03/17 16:33:14 jruoho Exp $ +define(`ateof', `TEXT AT EOF +')dnl +m4wrap(`ateof()')dnl +TEXT IN BODY diff --git a/tests/usr.bin/m4/d_m4wrap.out b/tests/usr.bin/m4/d_m4wrap.out new file mode 100644 index 000000000..a1bc22a09 --- /dev/null +++ b/tests/usr.bin/m4/d_m4wrap.out @@ -0,0 +1,2 @@ +TEXT IN BODY +TEXT AT EOF diff --git a/tests/usr.bin/m4/t_m4.sh b/tests/usr.bin/m4/t_m4.sh new file mode 100644 index 000000000..a0e1e7060 --- /dev/null +++ b/tests/usr.bin/m4/t_m4.sh @@ -0,0 +1,50 @@ +# $NetBSD: t_m4.sh,v 1.1 2012/03/17 16:33:14 jruoho Exp $ +# +# Copyright (c) 2008, 2009 The NetBSD Foundation, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +atf_test_case eof +eof_head() +{ + atf_set "descr" "Checks that m4 doesn't confuse 0xFF with EOF" +} +eof_body() +{ + cp "$(atf_get_srcdir)/d_ff_after_dnl.m4.uue" . + uudecode d_ff_after_dnl.m4.uue + atf_check -o file:"$(atf_get_srcdir)/d_ff_after_dnl.out" \ + m4 d_ff_after_dnl.m4 + + atf_check -o file:"$(atf_get_srcdir)/d_m4wrap.out" \ + m4 "$(atf_get_srcdir)/d_m4wrap.m4" + + atf_check -o file:"$(atf_get_srcdir)/d_m4wrap-P.out" \ + m4 -P "$(atf_get_srcdir)/d_m4wrap-P.m4" +} + +atf_init_test_cases() +{ + atf_add_test_case eof +} diff --git a/tests/usr.bin/make/Makefile b/tests/usr.bin/make/Makefile new file mode 100644 index 000000000..72d7d8b73 --- /dev/null +++ b/tests/usr.bin/make/Makefile @@ -0,0 +1,45 @@ +# $NetBSD: Makefile,v 1.1 2012/03/17 16:33:14 jruoho Exp $ + +NOMAN= # defined + +.include + +TESTSDIR= ${TESTSBASE}/usr.bin/make + +TESTS_SH= t_make + +FILESDIR= ${TESTSDIR} +FILES= d_comment.mk +FILES+= d_comment.out +FILES+= d_cond1.mk +FILES+= d_cond1.out +FILES+= d_dotwait.mk +FILES+= d_dotwait.out +FILES+= d_export.mk +FILES+= d_export.out +FILES+= d_export_all.mk +FILES+= d_export_all.out +FILES+= d_moderrs.mk +FILES+= d_moderrs.out +FILES+= d_modmatch.mk +FILES+= d_modmatch.out +FILES+= d_modmisc.mk +FILES+= d_modmisc.out +FILES+= d_modorder.mk +FILES+= d_modorder.out +FILES+= d_modts.mk +FILES+= d_modts.out +FILES+= d_modword.mk +FILES+= d_modword.out +FILES+= d_posix.mk +FILES+= d_posix.out +FILES+= d_qequals.mk +FILES+= d_qequals.out +FILES+= d_ternary.mk +FILES+= d_ternary.out +FILES+= d_unmatchedvarparen.mk +FILES+= d_unmatchedvarparen.out +FILES+= d_varcmd.mk +FILES+= d_varcmd.out + +.include diff --git a/tests/usr.bin/make/d_comment.mk b/tests/usr.bin/make/d_comment.mk new file mode 100644 index 000000000..7dd7dbbe2 --- /dev/null +++ b/tests/usr.bin/make/d_comment.mk @@ -0,0 +1,31 @@ +# This is a comment +.if ${MACHINE_ARCH} == something +FOO=bar +.endif + +#\ + Multiline comment + +BAR=# defined +FOOBAR= # defined + +# This is an escaped comment \ +that keeps going until the end of this line + +# Another escaped comment \ +that \ +goes \ +on + +# This is NOT an escaped comment due to the double backslashes \\ +all: hi foo bar + @echo comment testing done + +hi: + @echo comment testing start + +foo: + @echo this is $@ + +bar: + @echo This is how a comment looks: '# comment' diff --git a/tests/usr.bin/make/d_comment.out b/tests/usr.bin/make/d_comment.out new file mode 100644 index 000000000..68ae8c055 --- /dev/null +++ b/tests/usr.bin/make/d_comment.out @@ -0,0 +1,4 @@ +comment testing start +this is foo +This is how a comment looks: # comment +comment testing done diff --git a/tests/usr.bin/make/d_cond1.mk b/tests/usr.bin/make/d_cond1.mk new file mode 100644 index 000000000..a058ac684 --- /dev/null +++ b/tests/usr.bin/make/d_cond1.mk @@ -0,0 +1,102 @@ +# $NetBSD: d_cond1.mk,v 1.1 2012/03/17 16:33:14 jruoho Exp $ + +# hard code these! +TEST_UNAME_S= NetBSD +TEST_UNAME_M= sparc +TEST_MACHINE= i386 + +.if ${TEST_UNAME_S} +Ok=var, +.endif +.if ("${TEST_UNAME_S}") +Ok+=(\"var\"), +.endif +.if (${TEST_UNAME_M} != ${TEST_MACHINE}) +Ok+=(var != var), +.endif +.if ${TEST_UNAME_M} != ${TEST_MACHINE} +Ok+= var != var, +.endif +.if !((${TEST_UNAME_M} != ${TEST_MACHINE}) && defined(X)) +Ok+= !((var != var) && defined(name)), +.endif +# from bsd.obj.mk +MKOBJ?=no +.if ${MKOBJ} == "no" +o= no +Ok+= var == "quoted", +.else +.if defined(notMAKEOBJDIRPREFIX) || defined(norMAKEOBJDIR) +.if defined(notMAKEOBJDIRPREFIX) +o=${MAKEOBJDIRPREFIX}${__curdir} +.else +o= ${MAKEOBJDIR} +.endif +.endif +o= o +.endif + +# repeat the above to check we get the same result +.if ${MKOBJ} == "no" +o2= no +.else +.if defined(notMAKEOBJDIRPREFIX) || defined(norMAKEOBJDIR) +.if defined(notMAKEOBJDIRPREFIX) +o2=${MAKEOBJDIRPREFIX}${__curdir} +.else +o2= ${MAKEOBJDIR} +.endif +.endif +o2= o +.endif + +PRIMES=2 3 5 7 11 +NUMBERS=1 2 3 4 5 + +n=2 +.if ${PRIMES:M$n} == "" +X=not +.else +X= +.endif + +.if ${MACHINE_ARCH} == no-such +A=one +.else +.if ${MACHINE_ARCH} == not-this +.if ${MACHINE_ARCH} == something-else +A=unlikely +.else +A=no +.endif +.endif +A=other +# We expect an extra else warning - we're not skipping here +.else +A=this should be an error +.endif + +.if $X != "" +.if $X == not +B=one +.else +B=other +# We expect an extra else warning - we are skipping here +.else +B=this should be an error +.endif +.else +B=unknown +.endif + +.if "quoted" == quoted +C=clever +.else +C=dim +.endif + +all: + @echo "$n is $X prime" + @echo "A='$A' B='$B' C='$C' o='$o,${o2}'" + @echo "Passed:${.newline} ${Ok:S/,/${.newline}/}" + @echo "${NUMBERS:@n@$n is ${("${PRIMES:M$n}" == ""):?not:} prime${.newline}@}" diff --git a/tests/usr.bin/make/d_cond1.out b/tests/usr.bin/make/d_cond1.out new file mode 100644 index 000000000..e51fb2ee9 --- /dev/null +++ b/tests/usr.bin/make/d_cond1.out @@ -0,0 +1,18 @@ +make: "cond1.mk" line 75: warning: extra else +make: "cond1.mk" line 85: warning: extra else +2 is prime +A='other' B='unknown' C='clever' o='no,no' +Passed: + var + ("var") + (var != var) + var != var + !((var != var) && defined(name)) + var == quoted + +1 is not prime +2 is prime +3 is prime +4 is not prime +5 is prime + diff --git a/tests/usr.bin/make/d_dotwait.mk b/tests/usr.bin/make/d_dotwait.mk new file mode 100644 index 000000000..a4dc27257 --- /dev/null +++ b/tests/usr.bin/make/d_dotwait.mk @@ -0,0 +1,61 @@ +# $NetBSD: d_dotwait.mk,v 1.1 2012/03/17 16:33:14 jruoho Exp $ + +THISMAKEFILE:= ${.PARSEDIR}/${.PARSEFILE} + +TESTS= simple recursive shared cycle +PAUSE= sleep 1 + +# Use a .for loop rather than dependencies here, to ensure +# that the tests are run one by one, with parallelism +# only within tests. +# Ignore "--- target ---" lines printed by parallel make. +all: +.for t in ${TESTS} + @${.MAKE} -f ${THISMAKEFILE} -j4 $t | grep -v "^--- " +.endfor + +# +# Within each test, the names of the sub-targets follow these +# conventions: +# * If it's expected that two or more targets may be made in parallel, +# then the target names will differ only in an alphabetic component +# such as ".a" or ".b". +# * If it's expected that two or more targets should be made in sequence +# then the target names will differ in numeric components, such that +# lexical ordering of the target names matches the expected order +# in which the targets should be made. +# +# Targets may echo ${PARALLEL_TARG} to print a modified version +# of their own name, in which alphabetic components like ".a" or ".b" +# are converted to ".*". Two targets that are expected to +# be made in parallel will thus print the same strings, so that the +# output is independent of the order in which these targets are made. +# +PARALLEL_TARG= ${.TARGET:C/\.[a-z]/.*/g:Q} +.DEFAULT: + @echo ${PARALLEL_TARG}; ${PAUSE}; echo ${PARALLEL_TARG} +_ECHOUSE: .USE + @echo ${PARALLEL_TARG}; ${PAUSE}; echo ${PARALLEL_TARG} + +# simple: no recursion, no cycles +simple: simple.1 .WAIT simple.2 + +# recursive: all children of the left hand side of the .WAIT +# must be made before any child of the right hand side. +recursive: recursive.1.99 .WAIT recursive.2.99 +recursive.1.99: recursive.1.1.a recursive.1.1.b _ECHOUSE +recursive.2.99: recursive.2.1.a recursive.2.1.b _ECHOUSE + +# shared: both shared.1.99 and shared.2.99 depend on shared.0. +# shared.0 must be made first, even though it is a child of +# the right hand side of the .WAIT. +shared: shared.1.99 .WAIT shared.2.99 +shared.1.99: shared.0 _ECHOUSE +shared.2.99: shared.2.1 shared.0 _ECHOUSE + +# cycle: the cyclic dependency must not cause infinite recursion +# leading to stack overflow and a crash. +cycle: cycle.1.99 .WAIT cycle.2.99 +cycle.2.99: cycle.2.98 _ECHOUSE +cycle.2.98: cycle.2.97 _ECHOUSE +cycle.2.97: cycle.2.99 _ECHOUSE diff --git a/tests/usr.bin/make/d_dotwait.out b/tests/usr.bin/make/d_dotwait.out new file mode 100644 index 000000000..d72ae6757 --- /dev/null +++ b/tests/usr.bin/make/d_dotwait.out @@ -0,0 +1,29 @@ +simple.1 +simple.1 +simple.2 +simple.2 +recursive.1.1.* +recursive.1.1.* +recursive.1.1.* +recursive.1.1.* +recursive.1.99 +recursive.1.99 +recursive.2.1.* +recursive.2.1.* +recursive.2.1.* +recursive.2.1.* +recursive.2.99 +recursive.2.99 +shared.0 +shared.0 +shared.1.99 +shared.1.99 +shared.2.1 +shared.2.1 +shared.2.99 +shared.2.99 +make: Graph cycles through `cycle.2.99' +make: Graph cycles through `cycle.2.98' +make: Graph cycles through `cycle.2.97' +cycle.1.99 +cycle.1.99 diff --git a/tests/usr.bin/make/d_export.mk b/tests/usr.bin/make/d_export.mk new file mode 100644 index 000000000..9c305f854 --- /dev/null +++ b/tests/usr.bin/make/d_export.mk @@ -0,0 +1,22 @@ +# $NetBSD: d_export.mk,v 1.1 2012/03/17 16:33:14 jruoho Exp $ + +UT_TEST=export +UT_FOO=foo${BAR} +UT_FU=fubar +UT_ZOO=hoopie +UT_NO=all +# belive it or not, we expect this one to come out with $UT_FU unexpanded. +UT_DOLLAR= This is $$UT_FU + +.export UT_FU UT_FOO +.export UT_DOLLAR +# this one will be ignored +.export .MAKE.PID + +BAR=bar is ${UT_FU} + +.MAKE.EXPORTED+= UT_ZOO UT_TEST + +all: + @env | grep '^UT_' | sort + diff --git a/tests/usr.bin/make/d_export.out b/tests/usr.bin/make/d_export.out new file mode 100644 index 000000000..c765d339a --- /dev/null +++ b/tests/usr.bin/make/d_export.out @@ -0,0 +1,5 @@ +UT_DOLLAR=This is $UT_FU +UT_FOO=foobar is fubar +UT_FU=fubar +UT_TEST=export +UT_ZOO=hoopie diff --git a/tests/usr.bin/make/d_export_all.mk b/tests/usr.bin/make/d_export_all.mk new file mode 100644 index 000000000..8d2471f7b --- /dev/null +++ b/tests/usr.bin/make/d_export_all.mk @@ -0,0 +1,11 @@ +# $NetBSD: d_export_all.mk,v 1.1 2012/03/17 16:33:14 jruoho Exp $ + +UT_OK=good +UT_F=fine + +.export + +.include "d_export.mk" + +UT_TEST=export-all +UT_ALL=even this gets exported diff --git a/tests/usr.bin/make/d_export_all.out b/tests/usr.bin/make/d_export_all.out new file mode 100644 index 000000000..23052cfd0 --- /dev/null +++ b/tests/usr.bin/make/d_export_all.out @@ -0,0 +1,9 @@ +UT_ALL=even this gets exported +UT_DOLLAR=This is $UT_FU +UT_F=fine +UT_FOO=foobar is fubar +UT_FU=fubar +UT_NO=all +UT_OK=good +UT_TEST=export-all +UT_ZOO=hoopie diff --git a/tests/usr.bin/make/d_moderrs.mk b/tests/usr.bin/make/d_moderrs.mk new file mode 100644 index 000000000..b4469846b --- /dev/null +++ b/tests/usr.bin/make/d_moderrs.mk @@ -0,0 +1,31 @@ +# $NetBSD: d_moderrs.mk,v 1.1 2012/03/17 16:33:14 jruoho Exp $ +# +# various modifier error tests + +VAR=TheVariable +# incase we have to change it ;-) +MOD_UNKN=Z +MOD_TERM=S,V,v +MOD_S:= ${MOD_TERM}, + +all: modunkn modunknV varterm vartermV modtermV + +modunkn: + @echo "Expect: Unknown modifier 'Z'" + @echo "VAR:Z=${VAR:Z}" + +modunknV: + @echo "Expect: Unknown modifier 'Z'" + @echo "VAR:${MOD_UNKN}=${VAR:${MOD_UNKN}}" + +varterm: + @echo "Expect: Unclosed variable specification for VAR" + @echo VAR:S,V,v,=${VAR:S,V,v, + +vartermV: + @echo "Expect: Unclosed variable specification for VAR" + @echo VAR:${MOD_TERM},=${VAR:${MOD_S} + +modtermV: + @echo "Expect: Unclosed substitution for VAR (, missing)" + -@echo "VAR:${MOD_TERM}=${VAR:${MOD_TERM}}" diff --git a/tests/usr.bin/make/d_moderrs.out b/tests/usr.bin/make/d_moderrs.out new file mode 100644 index 000000000..c37bde65f --- /dev/null +++ b/tests/usr.bin/make/d_moderrs.out @@ -0,0 +1,15 @@ +Expect: Unknown modifier 'Z' +make: Unknown modifier 'Z' +VAR:Z= +Expect: Unknown modifier 'Z' +make: Unknown modifier 'Z' +VAR:Z= +Expect: Unclosed variable specification for VAR +make: Unclosed variable specification (expecting '}') for "VAR" (value "Thevariable") modifier S +VAR:S,V,v,=Thevariable +Expect: Unclosed variable specification for VAR +make: Unclosed variable specification after complex modifier (expecting '}') for VAR +VAR:S,V,v,=Thevariable +Expect: Unclosed substitution for VAR (, missing) +make: Unclosed substitution for VAR (, missing) +VAR:S,V,v= diff --git a/tests/usr.bin/make/d_modmatch.mk b/tests/usr.bin/make/d_modmatch.mk new file mode 100644 index 000000000..4ada35e35 --- /dev/null +++ b/tests/usr.bin/make/d_modmatch.mk @@ -0,0 +1,18 @@ + +X=a b c d e + +.for x in $X +LIB${x:tu}=/tmp/lib$x.a +.endfor + +X_LIBS= ${LIBA} ${LIBD} ${LIBE} + +LIB?=a + +all: + @for x in $X; do ${.MAKE} -f ${MAKEFILE} show LIB=$$x; done + +show: + @echo 'LIB=${LIB} X_LIBS:M$${LIB$${LIB:tu}} is "${X_LIBS:M${LIB${LIB:tu}}}"' + @echo 'LIB=${LIB} X_LIBS:M*/lib$${LIB}.a is "${X_LIBS:M*/lib${LIB}.a}"' + @echo 'LIB=${LIB} X_LIBS:M*/lib$${LIB}.a:tu is "${X_LIBS:M*/lib${LIB}.a:tu}"' diff --git a/tests/usr.bin/make/d_modmatch.out b/tests/usr.bin/make/d_modmatch.out new file mode 100644 index 000000000..26245bdfd --- /dev/null +++ b/tests/usr.bin/make/d_modmatch.out @@ -0,0 +1,15 @@ +LIB=a X_LIBS:M${LIB${LIB:tu}} is "/tmp/liba.a" +LIB=a X_LIBS:M*/lib${LIB}.a is "/tmp/liba.a" +LIB=a X_LIBS:M*/lib${LIB}.a:tu is "/TMP/LIBA.A" +LIB=b X_LIBS:M${LIB${LIB:tu}} is "" +LIB=b X_LIBS:M*/lib${LIB}.a is "" +LIB=b X_LIBS:M*/lib${LIB}.a:tu is "" +LIB=c X_LIBS:M${LIB${LIB:tu}} is "" +LIB=c X_LIBS:M*/lib${LIB}.a is "" +LIB=c X_LIBS:M*/lib${LIB}.a:tu is "" +LIB=d X_LIBS:M${LIB${LIB:tu}} is "/tmp/libd.a" +LIB=d X_LIBS:M*/lib${LIB}.a is "/tmp/libd.a" +LIB=d X_LIBS:M*/lib${LIB}.a:tu is "/TMP/LIBD.A" +LIB=e X_LIBS:M${LIB${LIB:tu}} is "/tmp/libe.a" +LIB=e X_LIBS:M*/lib${LIB}.a is "/tmp/libe.a" +LIB=e X_LIBS:M*/lib${LIB}.a:tu is "/TMP/LIBE.A" diff --git a/tests/usr.bin/make/d_modmisc.mk b/tests/usr.bin/make/d_modmisc.mk new file mode 100644 index 000000000..ff56d5de6 --- /dev/null +++ b/tests/usr.bin/make/d_modmisc.mk @@ -0,0 +1,33 @@ +# $NetBSD: d_modmisc.mk,v 1.1 2012/03/17 16:33:14 jruoho Exp $ +# +# miscellaneous modifier tests + +path=:/bin:/usr/bin::/sbin:/usr/sbin:.:/home/user/bin:. +# strip cwd from path. +MOD_NODOT=S/:/ /g:N.:ts: +# and decorate, note that $'s need to be doubled. Also note that +# the modifier_variable can be used with other modifiers. +MOD_NODOTX=S/:/ /g:N.:@d@'$$d'@ +# another mod - pretend it is more interesting +MOD_HOMES=S,/home/,/homes/, +MOD_OPT=@d@$${exists($$d):?$$d:$${d:S,/usr,/opt,}}@ +MOD_SEP=S,:, ,g + +all: modvar modvarloop + +modvar: + @echo "path='${path}'" + @echo "path='${path:${MOD_NODOT}}'" + @echo "path='${path:S,home,homes,:${MOD_NODOT}}'" + @echo "path=${path:${MOD_NODOTX}:ts:}" + @echo "path=${path:${MOD_HOMES}:${MOD_NODOTX}:ts:}" + +.for d in ${path:${MOD_SEP}:N.} /usr/xbin +path_$d?= ${d:${MOD_OPT}:${MOD_HOMES}}/ +paths+= ${d:${MOD_OPT}:${MOD_HOMES}} +.endfor + +modvarloop: + @echo "path_/usr/xbin=${path_/usr/xbin}" + @echo "paths=${paths}" + @echo "PATHS=${paths:tu}" diff --git a/tests/usr.bin/make/d_modmisc.out b/tests/usr.bin/make/d_modmisc.out new file mode 100644 index 000000000..58708c265 --- /dev/null +++ b/tests/usr.bin/make/d_modmisc.out @@ -0,0 +1,8 @@ +path=':/bin:/usr/bin::/sbin:/usr/sbin:.:/home/user/bin:.' +path='/bin:/usr/bin:/sbin:/usr/sbin:/home/user/bin' +path='/bin:/usr/bin:/sbin:/usr/sbin:/homes/user/bin' +path='/bin':'/usr/bin':'/sbin':'/usr/sbin':'/home/user/bin' +path='/bin':'/usr/bin':'/sbin':'/usr/sbin':'/homes/user/bin' +path_/usr/xbin=/opt/xbin/ +paths=/bin /usr/bin /sbin /usr/sbin /homes/user/bin /opt/xbin +PATHS=/BIN /USR/BIN /SBIN /USR/SBIN /HOMES/USER/BIN /OPT/XBIN diff --git a/tests/usr.bin/make/d_modorder.mk b/tests/usr.bin/make/d_modorder.mk new file mode 100644 index 000000000..3e133f40f --- /dev/null +++ b/tests/usr.bin/make/d_modorder.mk @@ -0,0 +1,22 @@ +# $NetBSD: d_modorder.mk,v 1.1 2012/03/17 16:33:14 jruoho Exp $ + +LIST= one two three four five six seven eight nine ten +LISTX= ${LIST:Ox} +LISTSX:= ${LIST:Ox} +TEST_RESULT= && echo Ok || echo Failed + +# unit-tests have to produce the same results on each run +# so we cannot actually include :Ox output. +all: + @echo "LIST = ${LIST}" + @echo "LIST:O = ${LIST:O}" + # Note that 1 in every 10! trials two independently generated + # randomized orderings will be the same. The test framework doesn't + # support checking probabilistic output, so we accept that the test + # will incorrectly fail with probability 2.8E-7. + @echo "LIST:Ox = `test '${LIST:Ox}' != '${LIST:Ox}' ${TEST_RESULT}`" + @echo "LIST:O:Ox = `test '${LIST:O:Ox}' != '${LIST:O:Ox}' ${TEST_RESULT}`" + @echo "LISTX = `test '${LISTX}' != '${LISTX}' ${TEST_RESULT}`" + @echo "LISTSX = `test '${LISTSX}' = '${LISTSX}' ${TEST_RESULT}`" + @echo "BADMOD 1 = ${LIST:OX}" + @echo "BADMOD 2 = ${LIST:OxXX}" diff --git a/tests/usr.bin/make/d_modorder.out b/tests/usr.bin/make/d_modorder.out new file mode 100644 index 000000000..6d273a9d1 --- /dev/null +++ b/tests/usr.bin/make/d_modorder.out @@ -0,0 +1,10 @@ +LIST = one two three four five six seven eight nine ten +LIST:O = eight five four nine one seven six ten three two +LIST:Ox = Ok +LIST:O:Ox = Ok +LISTX = Ok +LISTSX = Ok +make: Bad modifier `:OX' for LIST +BADMOD 1 = } +make: Bad modifier `:OxXX' for LIST +BADMOD 2 = XX} diff --git a/tests/usr.bin/make/d_modts.mk b/tests/usr.bin/make/d_modts.mk new file mode 100644 index 000000000..d0efd6d19 --- /dev/null +++ b/tests/usr.bin/make/d_modts.mk @@ -0,0 +1,32 @@ + +LIST= one two three +LIST+= four five six + +FU_mod-ts = a / b / cool + +AAA= a a a +B.aaa= Baaa + +all: mod-ts + +mod-ts: + @echo 'LIST="${LIST}"' + @echo 'LIST:ts,="${LIST:ts,}"' + @echo 'LIST:ts/:tu="${LIST:ts/:tu}"' + @echo 'LIST:ts::tu="${LIST:ts::tu}"' + @echo 'LIST:ts:tu="${LIST:ts:tu}"' + @echo 'LIST:tu:ts/="${LIST:tu:ts/}"' + @echo 'LIST:ts:="${LIST:ts:}"' + @echo 'LIST:ts="${LIST:ts}"' + @echo 'LIST:ts:S/two/2/="${LIST:ts:S/two/2/}"' + @echo 'LIST:S/two/2/:ts="${LIST:S/two/2/:ts}"' + @echo 'LIST:ts/:S/two/2/="${LIST:ts/:S/two/2/}"' + @echo "Pretend the '/' in '/n' etc. below are back-slashes." + @echo 'LIST:ts/n="${LIST:ts\n}"' + @echo 'LIST:ts/t="${LIST:ts\t}"' + @echo 'LIST:ts/012:tu="${LIST:ts\012:tu}"' + @echo 'LIST:tx="${LIST:tx}"' + @echo 'LIST:ts/x:tu="${LIST:ts\x:tu}"' + @echo 'FU_$@="${FU_${@:ts}:ts}"' + @echo 'FU_$@:ts:T="${FU_${@:ts}:ts:T}" == cool?' + @echo 'B.$${AAA:ts}="${B.${AAA:ts}}" == Baaa?' diff --git a/tests/usr.bin/make/d_modts.out b/tests/usr.bin/make/d_modts.out new file mode 100644 index 000000000..54527d8e8 --- /dev/null +++ b/tests/usr.bin/make/d_modts.out @@ -0,0 +1,32 @@ +LIST="one two three four five six" +LIST:ts,="one,two,three,four,five,six" +LIST:ts/:tu="ONE/TWO/THREE/FOUR/FIVE/SIX" +LIST:ts::tu="ONE:TWO:THREE:FOUR:FIVE:SIX" +LIST:ts:tu="ONETWOTHREEFOURFIVESIX" +LIST:tu:ts/="ONE/TWO/THREE/FOUR/FIVE/SIX" +LIST:ts:="one:two:three:four:five:six" +LIST:ts="onetwothreefourfivesix" +LIST:ts:S/two/2/="one2threefourfivesix" +LIST:S/two/2/:ts="one2threefourfivesix" +LIST:ts/:S/two/2/="one/2/three/four/five/six" +Pretend the '/' in '/n' etc. below are back-slashes. +LIST:ts/n="one +two +three +four +five +six" +LIST:ts/t="one two three four five six" +LIST:ts/012:tu="ONE +TWO +THREE +FOUR +FIVE +SIX" +make: Bad modifier `:tx' for LIST +LIST:tx="}" +make: Bad modifier `:ts\x' for LIST +LIST:ts/x:tu="\x:tu}" +FU_mod-ts="a/b/cool" +FU_mod-ts:ts:T="cool" == cool? +B.${AAA:ts}="Baaa" == Baaa? diff --git a/tests/usr.bin/make/d_modword.mk b/tests/usr.bin/make/d_modword.mk new file mode 100644 index 000000000..311bc481f --- /dev/null +++ b/tests/usr.bin/make/d_modword.mk @@ -0,0 +1,151 @@ +# $NetBSD: d_modword.mk,v 1.1 2012/03/17 16:33:14 jruoho Exp $ +# +# Test behaviour of new :[] modifier + +all: mod-squarebrackets mod-S-W mod-C-W mod-tW-tw + +LIST= one two three +LIST+= four five six +LONGLIST= 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 + +EMPTY= # the space should be ignored +ESCAPEDSPACE=\ # escaped space before the '#' +REALLYSPACE:=${EMPTY:C/^/ /W} +HASH= \# +AT= @ +STAR= * +ZERO= 0 +ONE= 1 +MINUSONE= -1 + +mod-squarebrackets: mod-squarebrackets-0-star-at \ + mod-squarebrackets-hash \ + mod-squarebrackets-n \ + mod-squarebrackets-start-end \ + mod-squarebrackets-nested + +mod-squarebrackets-0-star-at: + @echo 'LIST:[]="${LIST:[]}" is an error' + @echo 'LIST:[0]="${LIST:[0]}"' + @echo 'LIST:[0x0]="${LIST:[0x0]}"' + @echo 'LIST:[000]="${LIST:[000]}"' + @echo 'LIST:[*]="${LIST:[*]}"' + @echo 'LIST:[@]="${LIST:[@]}"' + @echo 'LIST:[0]:C/ /,/="${LIST:[0]:C/ /,/}"' + @echo 'LIST:[0]:C/ /,/g="${LIST:[0]:C/ /,/g}"' + @echo 'LIST:[0]:C/ /,/1g="${LIST:[0]:C/ /,/1g}"' + @echo 'LIST:[*]:C/ /,/="${LIST:[*]:C/ /,/}"' + @echo 'LIST:[*]:C/ /,/g="${LIST:[*]:C/ /,/g}"' + @echo 'LIST:[*]:C/ /,/1g="${LIST:[*]:C/ /,/1g}"' + @echo 'LIST:[@]:C/ /,/="${LIST:[@]:C/ /,/}"' + @echo 'LIST:[@]:C/ /,/g="${LIST:[@]:C/ /,/g}"' + @echo 'LIST:[@]:C/ /,/1g="${LIST:[@]:C/ /,/1g}"' + @echo 'LIST:[@]:[0]:C/ /,/="${LIST:[@]:[0]:C/ /,/}"' + @echo 'LIST:[0]:[@]:C/ /,/="${LIST:[0]:[@]:C/ /,/}"' + @echo 'LIST:[@]:[*]:C/ /,/="${LIST:[@]:[*]:C/ /,/}"' + @echo 'LIST:[*]:[@]:C/ /,/="${LIST:[*]:[@]:C/ /,/}"' + +mod-squarebrackets-hash: + @echo 'EMPTY="${EMPTY}"' + @echo 'EMPTY:[#]="${EMPTY:[#]}" == 1 ?' + @echo 'ESCAPEDSPACE="${ESCAPEDSPACE}"' + @echo 'ESCAPEDSPACE:[#]="${ESCAPEDSPACE:[#]}" == 1 ?' + @echo 'REALLYSPACE="${REALLYSPACE}"' + @echo 'REALLYSPACE:[#]="${REALLYSPACE:[#]}" == 1 ?' + @echo 'LIST:[#]="${LIST:[#]}"' + @echo 'LIST:[0]:[#]="${LIST:[0]:[#]}" == 1 ?' + @echo 'LIST:[*]:[#]="${LIST:[*]:[#]}" == 1 ?' + @echo 'LIST:[@]:[#]="${LIST:[@]:[#]}"' + @echo 'LIST:[1]:[#]="${LIST:[1]:[#]}"' + @echo 'LIST:[1..3]:[#]="${LIST:[1..3]:[#]}"' + +mod-squarebrackets-n: + @echo 'EMPTY:[1]="${EMPTY:[1]}"' + @echo 'ESCAPEDSPACE="${ESCAPEDSPACE}"' + @echo 'ESCAPEDSPACE:[1]="${ESCAPEDSPACE:[1]}"' + @echo 'REALLYSPACE="${REALLYSPACE}"' + @echo 'REALLYSPACE:[1]="${REALLYSPACE:[1]}" == "" ?' + @echo 'REALLYSPACE:[*]:[1]="${REALLYSPACE:[*]:[1]}" == " " ?' + @echo 'LIST:[1]="${LIST:[1]}"' + @echo 'LIST:[1.]="${LIST:[1.]}" is an error' + @echo 'LIST:[1].="${LIST:[1].}" is an error' + @echo 'LIST:[2]="${LIST:[2]}"' + @echo 'LIST:[6]="${LIST:[6]}"' + @echo 'LIST:[7]="${LIST:[7]}"' + @echo 'LIST:[999]="${LIST:[999]}"' + @echo 'LIST:[-]="${LIST:[-]}" is an error' + @echo 'LIST:[--]="${LIST:[--]}" is an error' + @echo 'LIST:[-1]="${LIST:[-1]}"' + @echo 'LIST:[-2]="${LIST:[-2]}"' + @echo 'LIST:[-6]="${LIST:[-6]}"' + @echo 'LIST:[-7]="${LIST:[-7]}"' + @echo 'LIST:[-999]="${LIST:[-999]}"' + @echo 'LONGLIST:[17]="${LONGLIST:[17]}"' + @echo 'LONGLIST:[0x11]="${LONGLIST:[0x11]}"' + @echo 'LONGLIST:[021]="${LONGLIST:[021]}"' + @echo 'LIST:[0]:[1]="${LIST:[0]:[1]}"' + @echo 'LIST:[*]:[1]="${LIST:[*]:[1]}"' + @echo 'LIST:[@]:[1]="${LIST:[@]:[1]}"' + @echo 'LIST:[0]:[2]="${LIST:[0]:[2]}"' + @echo 'LIST:[*]:[2]="${LIST:[*]:[2]}"' + @echo 'LIST:[@]:[2]="${LIST:[@]:[2]}"' + @echo 'LIST:[*]:C/ /,/:[2]="${LIST:[*]:C/ /,/:[2]}"' + @echo 'LIST:[*]:C/ /,/:[*]:[2]="${LIST:[*]:C/ /,/:[*]:[2]}"' + @echo 'LIST:[*]:C/ /,/:[@]:[2]="${LIST:[*]:C/ /,/:[@]:[2]}"' + +mod-squarebrackets-start-end: + @echo 'LIST:[1.]="${LIST:[1.]}" is an error' + @echo 'LIST:[1..]="${LIST:[1..]}" is an error' + @echo 'LIST:[1..1]="${LIST:[1..1]}"' + @echo 'LIST:[1..1.]="${LIST:[1..1.]}" is an error' + @echo 'LIST:[1..2]="${LIST:[1..2]}"' + @echo 'LIST:[2..1]="${LIST:[2..1]}"' + @echo 'LIST:[3..-2]="${LIST:[3..-2]}"' + @echo 'LIST:[-4..4]="${LIST:[-4..4]}"' + @echo 'LIST:[0..1]="${LIST:[0..1]}" is an error' + @echo 'LIST:[-1..0]="${LIST:[-1..0]}" is an error' + @echo 'LIST:[-1..1]="${LIST:[-1..1]}"' + @echo 'LIST:[0..0]="${LIST:[0..0]}"' + @echo 'LIST:[3..99]="${LIST:[3..99]}"' + @echo 'LIST:[-3..-99]="${LIST:[-3..-99]}"' + @echo 'LIST:[-99..-3]="${LIST:[-99..-3]}"' + +mod-squarebrackets-nested: + @echo 'HASH="${HASH}" == "#" ?' + @echo 'LIST:[$${HASH}]="${LIST:[${HASH}]}"' + @echo 'LIST:[$${ZERO}]="${LIST:[${ZERO}]}"' + @echo 'LIST:[$${ZERO}x$${ONE}]="${LIST:[${ZERO}x${ONE}]}"' + @echo 'LIST:[$${ONE}]="${LIST:[${ONE}]}"' + @echo 'LIST:[$${MINUSONE}]="${LIST:[${MINUSONE}]}"' + @echo 'LIST:[$${STAR}]="${LIST:[${STAR}]}"' + @echo 'LIST:[$${AT}]="${LIST:[${AT}]}"' + @echo 'LIST:[$${EMPTY}]="${LIST:[${EMPTY}]}" is an error' + @echo 'LIST:[$${LONGLIST:[21]:S/2//}]="${LIST:[${LONGLIST:[21]:S/2//}]}"' + @echo 'LIST:[$${LIST:[#]}]="${LIST:[${LIST:[#]}]}"' + @echo 'LIST:[$${LIST:[$${HASH}]}]="${LIST:[${LIST:[${HASH}]}]}"' + +mod-C-W: + @echo 'LIST:C/ /,/="${LIST:C/ /,/}"' + @echo 'LIST:C/ /,/W="${LIST:C/ /,/W}"' + @echo 'LIST:C/ /,/gW="${LIST:C/ /,/gW}"' + @echo 'EMPTY:C/^/,/="${EMPTY:C/^/,/}"' + @echo 'EMPTY:C/^/,/W="${EMPTY:C/^/,/W}"' + +mod-S-W: + @echo 'LIST:S/ /,/="${LIST:S/ /,/}"' + @echo 'LIST:S/ /,/W="${LIST:S/ /,/W}"' + @echo 'LIST:S/ /,/gW="${LIST:S/ /,/gW}"' + @echo 'EMPTY:S/^/,/="${EMPTY:S/^/,/}"' + @echo 'EMPTY:S/^/,/W="${EMPTY:S/^/,/W}"' + +mod-tW-tw: + @echo 'LIST:tW="${LIST:tW}"' + @echo 'LIST:tw="${LIST:tw}"' + @echo 'LIST:tW:C/ /,/="${LIST:tW:C/ /,/}"' + @echo 'LIST:tW:C/ /,/g="${LIST:tW:C/ /,/g}"' + @echo 'LIST:tW:C/ /,/1g="${LIST:tW:C/ /,/1g}"' + @echo 'LIST:tw:C/ /,/="${LIST:tw:C/ /,/}"' + @echo 'LIST:tw:C/ /,/g="${LIST:tw:C/ /,/g}"' + @echo 'LIST:tw:C/ /,/1g="${LIST:tw:C/ /,/1g}"' + @echo 'LIST:tw:tW:C/ /,/="${LIST:tw:tW:C/ /,/}"' + @echo 'LIST:tW:tw:C/ /,/="${LIST:tW:tw:C/ /,/}"' diff --git a/tests/usr.bin/make/d_modword.out b/tests/usr.bin/make/d_modword.out new file mode 100644 index 000000000..4bfdd672b --- /dev/null +++ b/tests/usr.bin/make/d_modword.out @@ -0,0 +1,121 @@ +make: Bad modifier `:[]' for LIST +LIST:[]="" is an error +LIST:[0]="one two three four five six" +LIST:[0x0]="one two three four five six" +LIST:[000]="one two three four five six" +LIST:[*]="one two three four five six" +LIST:[@]="one two three four five six" +LIST:[0]:C/ /,/="one,two three four five six" +LIST:[0]:C/ /,/g="one,two,three,four,five,six" +LIST:[0]:C/ /,/1g="one,two,three,four,five,six" +LIST:[*]:C/ /,/="one,two three four five six" +LIST:[*]:C/ /,/g="one,two,three,four,five,six" +LIST:[*]:C/ /,/1g="one,two,three,four,five,six" +LIST:[@]:C/ /,/="one two three four five six" +LIST:[@]:C/ /,/g="one two three four five six" +LIST:[@]:C/ /,/1g="one two three four five six" +LIST:[@]:[0]:C/ /,/="one,two three four five six" +LIST:[0]:[@]:C/ /,/="one two three four five six" +LIST:[@]:[*]:C/ /,/="one,two three four five six" +LIST:[*]:[@]:C/ /,/="one two three four five six" +EMPTY="" +EMPTY:[#]="1" == 1 ? +ESCAPEDSPACE="\ " +ESCAPEDSPACE:[#]="1" == 1 ? +REALLYSPACE=" " +REALLYSPACE:[#]="1" == 1 ? +LIST:[#]="6" +LIST:[0]:[#]="1" == 1 ? +LIST:[*]:[#]="1" == 1 ? +LIST:[@]:[#]="6" +LIST:[1]:[#]="1" +LIST:[1..3]:[#]="3" +EMPTY:[1]="" +ESCAPEDSPACE="\ " +ESCAPEDSPACE:[1]="\ " +REALLYSPACE=" " +REALLYSPACE:[1]="" == "" ? +REALLYSPACE:[*]:[1]=" " == " " ? +LIST:[1]="one" +make: Bad modifier `:[1.]' for LIST +LIST:[1.]="" is an error +make: Bad modifier `:[1].' for LIST +LIST:[1].="}" is an error +LIST:[2]="two" +LIST:[6]="six" +LIST:[7]="" +LIST:[999]="" +make: Bad modifier `:[-]' for LIST +LIST:[-]="" is an error +make: Bad modifier `:[--]' for LIST +LIST:[--]="" is an error +LIST:[-1]="six" +LIST:[-2]="five" +LIST:[-6]="one" +LIST:[-7]="" +LIST:[-999]="" +LONGLIST:[17]="17" +LONGLIST:[0x11]="17" +LONGLIST:[021]="17" +LIST:[0]:[1]="one two three four five six" +LIST:[*]:[1]="one two three four five six" +LIST:[@]:[1]="one" +LIST:[0]:[2]="" +LIST:[*]:[2]="" +LIST:[@]:[2]="two" +LIST:[*]:C/ /,/:[2]="" +LIST:[*]:C/ /,/:[*]:[2]="" +LIST:[*]:C/ /,/:[@]:[2]="three" +make: Bad modifier `:[1.]' for LIST +LIST:[1.]="" is an error +make: Bad modifier `:[1..]' for LIST +LIST:[1..]="" is an error +LIST:[1..1]="one" +make: Bad modifier `:[1..1.]' for LIST +LIST:[1..1.]="" is an error +LIST:[1..2]="one two" +LIST:[2..1]="two one" +LIST:[3..-2]="three four five" +LIST:[-4..4]="three four" +make: Bad modifier `:[0..1]' for LIST +LIST:[0..1]="" is an error +make: Bad modifier `:[-1..0]' for LIST +LIST:[-1..0]="" is an error +LIST:[-1..1]="six five four three two one" +LIST:[0..0]="one two three four five six" +LIST:[3..99]="three four five six" +LIST:[-3..-99]="four three two one" +LIST:[-99..-3]="one two three four" +HASH="#" == "#" ? +LIST:[${HASH}]="6" +LIST:[${ZERO}]="one two three four five six" +LIST:[${ZERO}x${ONE}]="one" +LIST:[${ONE}]="one" +LIST:[${MINUSONE}]="six" +LIST:[${STAR}]="one two three four five six" +LIST:[${AT}]="one two three four five six" +make: Bad modifier `:[${EMPTY' for LIST +LIST:[${EMPTY}]="" is an error +LIST:[${LONGLIST:[21]:S/2//}]="one" +LIST:[${LIST:[#]}]="six" +LIST:[${LIST:[${HASH}]}]="six" +LIST:S/ /,/="one two three four five six" +LIST:S/ /,/W="one,two three four five six" +LIST:S/ /,/gW="one,two,three,four,five,six" +EMPTY:S/^/,/="," +EMPTY:S/^/,/W="," +LIST:C/ /,/="one two three four five six" +LIST:C/ /,/W="one,two three four five six" +LIST:C/ /,/gW="one,two,three,four,five,six" +EMPTY:C/^/,/="," +EMPTY:C/^/,/W="," +LIST:tW="one two three four five six" +LIST:tw="one two three four five six" +LIST:tW:C/ /,/="one,two three four five six" +LIST:tW:C/ /,/g="one,two,three,four,five,six" +LIST:tW:C/ /,/1g="one,two,three,four,five,six" +LIST:tw:C/ /,/="one two three four five six" +LIST:tw:C/ /,/g="one two three four five six" +LIST:tw:C/ /,/1g="one two three four five six" +LIST:tw:tW:C/ /,/="one,two three four five six" +LIST:tW:tw:C/ /,/="one two three four five six" diff --git a/tests/usr.bin/make/d_posix.mk b/tests/usr.bin/make/d_posix.mk new file mode 100644 index 000000000..ba7d3c4c5 --- /dev/null +++ b/tests/usr.bin/make/d_posix.mk @@ -0,0 +1,24 @@ +# $NetBSD: d_posix.mk,v 1.1 2012/03/17 16:33:14 jruoho Exp $ + +all: x plus subs err + +x: + @echo "Posix says we should execute the command as if run by system(3)" + @echo "Expect 'Hello,' and 'World!'" + @echo Hello,; false; echo "World!" + +plus: + @echo a command + +@echo "a command prefixed by '+' executes even with -n" + @echo another command + +subs: + @echo make -n + @${.MAKE} -f ${MAKEFILE} -n plus + @echo make -n -j1 + @${.MAKE} -f ${MAKEFILE} -n -j1 plus + +err: + @(echo Now we expect an error...; exit 1) + @echo "Oops! you shouldn't see this!" + diff --git a/tests/usr.bin/make/d_posix.out b/tests/usr.bin/make/d_posix.out new file mode 100644 index 000000000..00aa5a33d --- /dev/null +++ b/tests/usr.bin/make/d_posix.out @@ -0,0 +1,22 @@ +Posix says we should execute the command as if run by system(3) +Expect 'Hello,' and 'World!' +Hello, +World! +a command +a command prefixed by '+' executes even with -n +another command +make -n +echo a command +echo "a command prefixed by '+' executes even with -n" +a command prefixed by '+' executes even with -n +echo another command +make -n -j1 +{ echo a command +} || exit $? +echo "a command prefixed by '+' executes even with -n" +a command prefixed by '+' executes even with -n +{ echo another command +} || exit $? +Now we expect an error... +*** Error code 1 (continuing) +`all' not remade because of errors. diff --git a/tests/usr.bin/make/d_qequals.mk b/tests/usr.bin/make/d_qequals.mk new file mode 100644 index 000000000..8cac59716 --- /dev/null +++ b/tests/usr.bin/make/d_qequals.mk @@ -0,0 +1,8 @@ +# $NetBSD: d_qequals.mk,v 1.1 2012/03/17 16:33:14 jruoho Exp $ + +M= i386 +V.i386= OK +V.$M ?= bug + +all: + @echo 'V.$M ?= ${V.$M}' diff --git a/tests/usr.bin/make/d_qequals.out b/tests/usr.bin/make/d_qequals.out new file mode 100644 index 000000000..c4c87aacf --- /dev/null +++ b/tests/usr.bin/make/d_qequals.out @@ -0,0 +1 @@ +V.i386 ?= OK diff --git a/tests/usr.bin/make/d_ternary.mk b/tests/usr.bin/make/d_ternary.mk new file mode 100644 index 000000000..77f834981 --- /dev/null +++ b/tests/usr.bin/make/d_ternary.mk @@ -0,0 +1,8 @@ + +all: + @for x in "" A= A=42; do ${.MAKE} -f ${MAKEFILE} show $$x; done + +show: + @echo "The answer is ${A:?known:unknown}" + @echo "The answer is ${A:?$A:unknown}" + @echo "The answer is ${empty(A):?empty:$A}" diff --git a/tests/usr.bin/make/d_ternary.out b/tests/usr.bin/make/d_ternary.out new file mode 100644 index 000000000..0c41a12a8 --- /dev/null +++ b/tests/usr.bin/make/d_ternary.out @@ -0,0 +1,9 @@ +The answer is unknown +The answer is unknown +The answer is empty +The answer is known +The answer is +The answer is empty +The answer is known +The answer is 42 +The answer is 42 diff --git a/tests/usr.bin/make/d_unmatchedvarparen.mk b/tests/usr.bin/make/d_unmatchedvarparen.mk new file mode 100644 index 000000000..21fd14541 --- /dev/null +++ b/tests/usr.bin/make/d_unmatchedvarparen.mk @@ -0,0 +1,3 @@ + +all: + @echo $(foo::=foo-text) diff --git a/tests/usr.bin/make/d_unmatchedvarparen.out b/tests/usr.bin/make/d_unmatchedvarparen.out new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/tests/usr.bin/make/d_unmatchedvarparen.out @@ -0,0 +1 @@ + diff --git a/tests/usr.bin/make/d_varcmd.mk b/tests/usr.bin/make/d_varcmd.mk new file mode 100644 index 000000000..31bc4f538 --- /dev/null +++ b/tests/usr.bin/make/d_varcmd.mk @@ -0,0 +1,49 @@ +# $NetBSD: d_varcmd.mk,v 1.1 2012/03/17 16:33:14 jruoho Exp $ +# +# Test behaviour of recursive make and vars set on command line. + +FU=fu +FOO?=foo +.if !empty(.TARGETS) +TAG=${.TARGETS} +.endif +TAG?=default + +all: one + +show: + @echo "${TAG} FU=${FU} FOO=${FOO} VAR=${VAR}" + +one: show + @${.MAKE} -f ${MAKEFILE} FU=bar FOO=goo two + +two: show + @${.MAKE} -f ${MAKEFILE} three + +three: show + @${.MAKE} -f ${MAKEFILE} four + + +.ifmake four +VAR=Internal +.MAKEOVERRIDES+= VAR +.endif + +four: show + @${.MAKE} -f ${MAKEFILE} five + +M = x +V.y = is y +V.x = is x +V := ${V.$M} +K := ${V} + +show-v: + @echo '${TAG} v=${V} k=${K}' + +five: show show-v + @${.MAKE} -f ${MAKEFILE} M=y six + +six: show-v + @${.MAKE} -f ${MAKEFILE} V=override show-v + diff --git a/tests/usr.bin/make/d_varcmd.out b/tests/usr.bin/make/d_varcmd.out new file mode 100644 index 000000000..b1b6596ec --- /dev/null +++ b/tests/usr.bin/make/d_varcmd.out @@ -0,0 +1,8 @@ +default FU=fu FOO=foo VAR= +two FU=bar FOO=goo VAR= +three FU=bar FOO=goo VAR= +four FU=bar FOO=goo VAR=Internal +five FU=bar FOO=goo VAR=Internal +five v=is x k=is x +six v=is y k=is y +show-v v=override k=override diff --git a/tests/usr.bin/make/t_make.sh b/tests/usr.bin/make/t_make.sh new file mode 100644 index 000000000..b9da56a74 --- /dev/null +++ b/tests/usr.bin/make/t_make.sh @@ -0,0 +1,89 @@ +# $NetBSD: t_make.sh,v 1.1 2012/03/17 16:33:14 jruoho Exp $ +# +# Copyright (c) 2008, 2010 The NetBSD Foundation, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +# Executes make and compares the output to a golden file. +run_and_check() +{ + local name="${1}"; shift + + local srcdir="$(atf_get_srcdir)" + atf_check -o file:"${srcdir}/d_${name}.out" -x \ + "make -k -f ${srcdir}/d_${name}.mk 2>&1 | sed -e 's,${srcdir}/d_,,'" +} + +# Defines a test case for make(1), parsing a given file and comparing the +# output to prerecorded results. +test_case() +{ + local name="${1}"; shift + local descr="${1}"; shift + + atf_test_case "${name}" + eval "${name}_head() { \ + atf_set descr '${descr}'; \ + }" + eval "${name}_body() { \ + run_and_check '${name}'; \ + }" +} + +test_case comment "Checks comments (PR/17732, PR/30536)" +test_case cond1 "Checks conditionals (PR/24420)" +test_case dotwait "Checks .WAIT" +test_case export "Checks .export of provided variables" +test_case export_all "Checks .export of all global variables" +test_case moderrs "Checks correct handling of errors in modifiers usage" +test_case modmatch "Checks modifier :M" +test_case modmisc "Checks modifiers specified in variables" +test_case modorder "Checks modifier :Ox" +test_case modts "Checks modifier :ts" +test_case modword "Checks modifier :[]" +test_case posix "Checks conformance to POSIX" +test_case qequals "Checks operator ?=" +test_case ternary "Checks ternary modifier" +test_case varcmd "Checks behavior of command line variable assignments" +test_case unmatchedvarparen "Checks $ ( ) matches" + +atf_init_test_cases() +{ + atf_add_test_case comment + atf_add_test_case cond1 + atf_add_test_case dotwait + atf_add_test_case export + atf_add_test_case export_all + atf_add_test_case moderrs + atf_add_test_case modmatch + atf_add_test_case modmisc + atf_add_test_case modorder + atf_add_test_case modts + atf_add_test_case modword + atf_add_test_case posix + atf_add_test_case qequals + atf_add_test_case ternary + atf_add_test_case varcmd + atf_add_test_case unmatchedvarparen +} diff --git a/tests/usr.bin/mkdep/Makefile b/tests/usr.bin/mkdep/Makefile new file mode 100644 index 000000000..78cf3617b --- /dev/null +++ b/tests/usr.bin/mkdep/Makefile @@ -0,0 +1,9 @@ +# $NetBSD: Makefile,v 1.1 2011/05/30 18:14:11 njoly Exp $ + +.include + +TESTSDIR= ${TESTSBASE}/usr.bin/mkdep + +TESTS_SH= t_mkdep + +.include diff --git a/tests/usr.bin/mkdep/t_mkdep.sh b/tests/usr.bin/mkdep/t_mkdep.sh new file mode 100644 index 000000000..7ad6fd95e --- /dev/null +++ b/tests/usr.bin/mkdep/t_mkdep.sh @@ -0,0 +1,83 @@ +# $NetBSD: t_mkdep.sh,v 1.4 2012/08/26 22:37:19 jmmv Exp $ +# +# Copyright (c) 2011 The NetBSD Foundation, Inc. +# All rights reserved. +# +# This code is derived from software contributed to The NetBSD Foundation +# by Nicolas Joly. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +atf_test_case prefix +prefix_head() { + atf_set "descr" "Test adding a prefix to a single target" + atf_set "require.progs" "mkdep cc" +} +prefix_body() { + + atf_check touch sample.c + + atf_check mkdep -f sample.d -P some/path/ sample.c + atf_check -o ignore grep '^some/path/sample.o:' sample.d +} + +atf_test_case suffixes +suffixes_head() { + atf_set "descr" "Test suffixes list" + atf_set "require.progs" "mkdep cc" +} +suffixes_body() { + + atf_check touch sample.c + + # No list + atf_check mkdep -f sample.d sample.c + atf_check -o ignore grep '^sample.o:' sample.d + + # Suffix list + atf_check mkdep -f sample.d -s '.a .b' sample.c + atf_check -o ignore grep '^sample.b sample.a:' sample.d + + # Empty list + atf_check mkdep -f sample.d -s '' sample.c + atf_check -o ignore grep '^sample:' sample.d +} + +atf_test_case prefix_and_suffixes +prefix_and_suffixes_head() { + atf_set "descr" "Test the combination of a prefix and suffixes" + atf_set "require.progs" "mkdep cc" +} +prefix_and_suffixes_body() { + + atf_check touch sample.c + + atf_check mkdep -f sample.d -s '.a .b' -P c/d sample.c + atf_check -o ignore grep '^c/dsample.b c/dsample.a:' sample.d +} + +atf_init_test_cases() { + atf_add_test_case prefix + atf_add_test_case suffixes + atf_add_test_case prefix_and_suffixes +} diff --git a/tests/usr.bin/nbperf/Makefile b/tests/usr.bin/nbperf/Makefile new file mode 100644 index 000000000..6dc55aedc --- /dev/null +++ b/tests/usr.bin/nbperf/Makefile @@ -0,0 +1,17 @@ +# $NetBSD: Makefile,v 1.1 2012/07/22 20:38:20 joerg Exp $ + +NOMAN= # defined + +.include + +TESTSDIR= ${TESTSBASE}/usr.bin/nbperf + +TESTS_SH= t_nbperf + +SCRIPTSDIR= ${TESTSDIR} +SCRIPTS+= h_nbperf + +FILESDIR= ${TESTSDIR} +FILES= hash_driver.c + +.include diff --git a/tests/usr.bin/nbperf/h_nbperf.sh b/tests/usr.bin/nbperf/h_nbperf.sh new file mode 100644 index 000000000..2587ed043 --- /dev/null +++ b/tests/usr.bin/nbperf/h_nbperf.sh @@ -0,0 +1,32 @@ +#!/bin/sh +# $NetBSD: h_nbperf.sh,v 1.2 2012/09/25 20:53:46 joerg Exp $ +# +# Copyright (c) 2012 The NetBSD Foundation, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +set -e +head -n $4 $1 | nbperf -m hash.map -o hash.c -a $2 2> /dev/null +cc -o testprog -I. $5 +head -n $4 $1 | ./testprog | $3 diff --git a/tests/usr.bin/nbperf/hash_driver.c b/tests/usr.bin/nbperf/hash_driver.c new file mode 100644 index 000000000..4644eb2c9 --- /dev/null +++ b/tests/usr.bin/nbperf/hash_driver.c @@ -0,0 +1,53 @@ +/* $NetBSD: hash_driver.c,v 1.2 2012/09/25 20:53:46 joerg Exp $ */ +/*- + * Copyright (c) 2012 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Joerg Sonnenberger. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include + +#include "hash.c" + +int +main(void) +{ + char *line = NULL; + size_t buflen; + ssize_t len; + + while ((len = getline(&line, &len, stdin)) > 0) { + if (len && line[len - 1] == '\n') + --len; + printf("%" PRId32 "\n", hash(line, len)); + } + free(line); + return 0; +} diff --git a/tests/usr.bin/nbperf/t_nbperf.sh b/tests/usr.bin/nbperf/t_nbperf.sh new file mode 100644 index 000000000..dda26e220 --- /dev/null +++ b/tests/usr.bin/nbperf/t_nbperf.sh @@ -0,0 +1,104 @@ +# $NetBSD: t_nbperf.sh,v 1.2 2012/09/25 20:53:46 joerg Exp $ +# +# Copyright (c) 2012 The NetBSD Foundation, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +cleanup() +{ + rm -f reference.txt hash.c hash.map testprog +} + +atf_test_case chm +chm_head() +{ + atf_set "descr" "Checks chm algorithm" +} +chm_body() +{ + for n in 4 32 128 1024 65536; do + seq 0 $(($n - 1)) > reference.txt + atf_check -o file:reference.txt \ + $(atf_get_srcdir)/h_nbperf /usr/share/dict/web2 chm cat \ + $n $(atf_get_srcdir)/hash_driver.c + atf_check -o file:hash.map \ + $(atf_get_srcdir)/h_nbperf /usr/share/dict/web2 chm cat \ + $n $(atf_get_srcdir)/hash_driver.c + done +} +chm_clean() +{ + cleanup +} + +atf_test_case chm3 +chm3_head() +{ + atf_set "descr" "Checks chm3 algorithm" +} +chm3_body() +{ + for n in 4 32 128 1024 65536; do + seq 0 $(($n - 1)) > reference.txt + atf_check -o file:reference.txt \ + $(atf_get_srcdir)/h_nbperf /usr/share/dict/web2 chm3 cat \ + $n $(atf_get_srcdir)/hash_driver.c + atf_check -o file:hash.map \ + $(atf_get_srcdir)/h_nbperf /usr/share/dict/web2 chm3 cat \ + $n $(atf_get_srcdir)/hash_driver.c + done +} +chm3_clean() +{ + cleanup +} + +atf_test_case bdz +bdz_head() +{ + atf_set "descr" "Checks bdz algorithm" +} +bdz_body() +{ + for n in 4 32 128 1024 65536 131072; do + seq 0 $(($n - 1)) > reference.txt + atf_check -o file:reference.txt \ + $(atf_get_srcdir)/h_nbperf /usr/share/dict/web2 bdz "sort -n" \ + $n $(atf_get_srcdir)/hash_driver.c + atf_check -o file:hash.map \ + $(atf_get_srcdir)/h_nbperf /usr/share/dict/web2 bdz cat \ + $n $(atf_get_srcdir)/hash_driver.c + done +} +bdz_clean() +{ + cleanup +} + +atf_init_test_cases() +{ + atf_add_test_case chm + atf_add_test_case chm3 + atf_add_test_case bdz +} diff --git a/tests/usr.bin/netpgpverify/Makefile b/tests/usr.bin/netpgpverify/Makefile new file mode 100644 index 000000000..da574f7f6 --- /dev/null +++ b/tests/usr.bin/netpgpverify/Makefile @@ -0,0 +1,9 @@ +# $NetBSD: Makefile,v 1.1 2012/11/20 07:55:54 agc Exp $ + +.include + +TESTSDIR= ${TESTSBASE}/usr.bin/netpgpverify + +TESTS_SH+= t_netpgpverify + +.include diff --git a/tests/usr.bin/netpgpverify/t_netpgpverify.sh b/tests/usr.bin/netpgpverify/t_netpgpverify.sh new file mode 100644 index 000000000..110761c4e --- /dev/null +++ b/tests/usr.bin/netpgpverify/t_netpgpverify.sh @@ -0,0 +1,8907 @@ +#! /bin/sh + +# $NetBSD: t_netpgpverify.sh,v 1.1 2012/11/20 07:55:54 agc Exp $ + +# Copyright (c) 2012 Alistair Crooks +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +atf_test_case netpgpverify_case + +netpgpverify_rsa_head() { + atf_set "descr" "RSA signatures for netpgpverify" +} + +netpgpverify_rsa_body() { + uudecode << EOF +begin-base64 644 b.gpg +xA0DAAgBG2jc/MBZaCMBy4tiAAAAAABQUk9HPXAKU1JDUz1wYXJzZS5jCldBUk5T +PTUKTUtNQU49bm8KQ1BQRkxBR1MrPS1nIC1PMApMREZMQUdTKz0tZyAtTzAKCi5p +bmNsdWRlIDxic2QucHJvZy5taz4KCnQ6ICR7UFJPR30KCS4vJHtQUk9HfSBncGdz +aWduZWQtYS5ncGcKwsBiBAABCAAWBQJQTZOaBQMAAAAACRAbaNz8wFloIwAABTcH +/RhxktWLH3Cw6YkC/4Wcm9yq6flgiKQsB0VUaVgmmOfWnLxcowyH5ISENo/J6qhT +S8Z0B2lAkRzBhXbfSe8GoESc/NsXTuOIvdjZEy7FBkl9Lumuqp1IlmoXh3RgPv5Z +gcJ+uDCV958uXAxLn017xN/CVKi5yBiNWWk/mOJuI8FCiQCyFVQ3dOXcFU/gf4iZ +YkH6OMX6eNpLQXp+s1ar6ZqpFE09QEoiFuIiDas+V6g0IG1c+PgP+TOlO5ztaKjx +XxejP0Thtft0T+AKTANVrtx+aTseVt4CR3jBt0n4CJjTTRQwnIYxGML3ddgMXSPT +0c4J/4dwyMqdDuhby//52Nw= +==== +EOF + cat >det << EOF +To Do +===== +tests with -k sig +detached sigs +DSA + +Done +==== +basics +localise pgp_read_packets +fix lint +WARNS=5 +lib man page +prog man page +do we do it statically linked as well? +multiple files in netpgpverify +EOF + uudecode << EOF +begin-base64 644 det.sig +iQEcBAABAgAGBQJQf8gBAAoJEBto3PzAWWgjbLoH/i9MZSv2l9lJ5O+bfGmRSUxe +rGeAM0dq//xi+AABByDEWNYORq2I6CO6k2eVPv7YbNE2Whn7qXA6U7LotM7Lt61l +MCLRhuTv9RViV1qzsy+Z8VAQmhERAcG/qA5JSQbzjuVYhg5FexpiVmxgG9L8Z/Oj +4pU9zIId1vH7CvAcy/mfSyM8Ih8bmsrgs9b1wzMPLQKl0v0jtcrEcnwMtscXa9Mw +X66bHxCHtRyGcWsHU8Ab2fJCvsCbBBMtg3JjZ7+VgDoZqPqBgIkhmppqC05vU5QR +leNo8g9OwiJ6fMtdwTMsFkxqjjVKk5//X/6jQd/mf55XcxLOw4UK4ev5ADExnOU= +==== +EOF + cat >jj.asc << EOF +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA1 + +1. tag & 0x3f +2. len + +one pass (tag 4) +======== +b version:3 +b sig type +b hash alg +b pubkey alg +8b keyid + +literal data (tag 11) +============= +b binary/text +b length +c string +L mtime +text +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v1.4.11 (NetBSD) + +iQEcBAEBAgAGBQJQaIZcAAoJEBto3PzAWWgj678IALbDHon3Rm6qUhn7k1TFT6D3 +yi/jzf3piSJGsgUg2wEghs175edC/cJK3lG9Gx/3/uQq06R9g37nVRX8I0sK7yT2 +XgR+RHoGh/b+CQxdRNC+ub5QoNb8LcmCb/MQGq2KK9otSExiy4WMUP4K1DblaK5L ++Hg4VTooMot1NVqyFSoB2aZauXc2F4ZVh5q0fn8w5GEw45P+AUUbmzpgbLwXbl+I +tMsX54V1dxyDcCYUs0xUH/VxJUQEeIlDbCOXYMbCVtggYRqKksTr+u/riw/Llnql +jQdq5rBRW1SlD7Ll6z/LF2WBJOWtHzp4qbnBGSq5uB1q37H3mWL28f1tL//TUjM= +=EX8W +-----END PGP SIGNATURE----- +EOF + uudecode << EOF +begin-base64 644 pubring.gpg +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 +StZtC+VbuN66pfHwsAIAAw== +==== +EOF + cat >NetBSD-6.0_hashes.asc << EOF +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA1 + + + +The following is a complete list of distribution files for NetBSD-6.0 + +This includes all binary distributions, kernels, install images, +source tarballs, release notes and related files. Multiple hash +formats are used for each file. + +Signatures will be made available for any additional install media as +they are published. + +UPDATE: the macppc ISO was replaced, the mac68k and source ISOs were added, +and a new signature was generated for this hashes file on 15 October 2012. + + NetBSD Security-Officer + security-officer@NetBSD.org + +SHA1 (NetBSD-6.0/CHANGES) = 44ed658e4f8c813d67613497afdc6656470aab00 +SHA512 (NetBSD-6.0/CHANGES) = ababa97f9674bfaa4d941515cff2b98a1c254221394e10f3060f456474f6888f5e79aa6480bebb6f69dc1e682cd8f4c450feee91c0da1a2ed1fc805bd1dec273 +RMD160 (NetBSD-6.0/CHANGES) = 2a0ed7457dfe13229bb72cfde66668ffff4ec7ff +MD5 (NetBSD-6.0/CHANGES) = 63363144027cac2345030caf2d934d05 +SHA1 (NetBSD-6.0/CHANGES-6.0) = 159eef1002f7e904954fb3bd9490ac2e5391fdbb +SHA512 (NetBSD-6.0/CHANGES-6.0) = f09bf320629f6db65a469c4220eebd8db668a81fcc1a8d41b9fb06bbadbcdafd76c9d6372d8d9e5258af8424abf648d1114da2eef3ae9b396642b9b3aba434ec +RMD160 (NetBSD-6.0/CHANGES-6.0) = b03df64c3b4081c56578066c23a24db14ae935e1 +MD5 (NetBSD-6.0/CHANGES-6.0) = 92a82839d67702799f45da9167b0a60e +SHA1 (NetBSD-6.0/CHANGES.prev) = 25bdfe4a49acc75ee3a59ca04dc3b3c7c71a4563 +SHA512 (NetBSD-6.0/CHANGES.prev) = 73057475c27c98d729dc97f6203f89f39459405c74f7abd7b18d4382f7c5ad6c3f598989cecdd5013ba4b77d66e694c05e3fcd51fd9776fde908513ea70e63d5 +RMD160 (NetBSD-6.0/CHANGES.prev) = 38f959a7c9d0c8da19eeb1740126b04dbb71a90e +MD5 (NetBSD-6.0/CHANGES.prev) = 0a50635a033237b439f5d7ef4c29b802 +SHA1 (NetBSD-6.0/LAST_MINUTE) = 49f8a218ff6657e0d30449a87b7c4f65ccf6115b +SHA512 (NetBSD-6.0/LAST_MINUTE) = d6b47cdd24a6be60d68f867c361106da69dea5f9b7f4f9764d1bd0f706e8fc9d604a6b89b95eb2829dba78df936f824be3dec21318da495705796a1882ee9277 +RMD160 (NetBSD-6.0/LAST_MINUTE) = ba07328d66f7955cc9fcb402e461871bfcf2aad3 +MD5 (NetBSD-6.0/LAST_MINUTE) = fb247c08580991ef0cc5f126b62f3b6e +SHA1 (NetBSD-6.0/README.files) = 183b12bef627768c595ab7df30bc038952166809 +SHA512 (NetBSD-6.0/README.files) = 9aacd7e1042c7579309ed9ec1ee0fb017803f967be04e51f08e78fd56537ceae6ee79ed0bd3250994e4c16dd7de6995c1be3a301aeb95a500bbc77f6915ecb31 +RMD160 (NetBSD-6.0/README.files) = 61301ea3ffe6a3e1c415ce00cfe6d22b2d544365 +MD5 (NetBSD-6.0/README.files) = 7e47e7eb92db7cb8b8ce39ceb5986847 +SHA1 (NetBSD-6.0/acorn26/binary/kernel/netbsd-FOURMEG.gz) = e127c41d5e332c75e79f5ca0e72ba250ef3c739a +SHA512 (NetBSD-6.0/acorn26/binary/kernel/netbsd-FOURMEG.gz) = 7487273a4289d2f1dd69fb0230c263ac4fd198aac5399de043e1416834ea4b0bb4970129886223b9c5090ea9526dd765e6152f89ccfa58d4c8ba95597a845a34 +RMD160 (NetBSD-6.0/acorn26/binary/kernel/netbsd-FOURMEG.gz) = 09dcd3b8f9be85b99ed094fefc6a88e27be9b91d +MD5 (NetBSD-6.0/acorn26/binary/kernel/netbsd-FOURMEG.gz) = 5aef629404b3d65f15bc44554b948145 +SHA1 (NetBSD-6.0/acorn26/binary/kernel/netbsd-GENERIC.gz) = c6362b83dbc496509c4e539cca33924b14318804 +SHA512 (NetBSD-6.0/acorn26/binary/kernel/netbsd-GENERIC.gz) = da75edae5fcd456028c5699d3872ac6e9c041aafb37141cfbf6b5f374f5c69d21979d23709f7e82a9198580e6f5c3c50060b9d1cd3dcac74c1e2530131c5e892 +RMD160 (NetBSD-6.0/acorn26/binary/kernel/netbsd-GENERIC.gz) = 6caa2f5e65c871664b1af2dd2a5eceb8b64f2212 +MD5 (NetBSD-6.0/acorn26/binary/kernel/netbsd-GENERIC.gz) = b14bd857ffbe97a3601f91bc0a1b388d +SHA1 (NetBSD-6.0/acorn26/binary/sets/games.tgz) = e1d2bb091d8202962133475bc83edb55230b9008 +SHA512 (NetBSD-6.0/acorn26/binary/sets/games.tgz) = a147fe6d0419d53d5a428802d0bb6c9fa8a84a76c96d7d6d7c0d399e5af3a69240116463549a83d53387b0214ba0207796d7c10228d92a684fe7ff0ece3aec16 +RMD160 (NetBSD-6.0/acorn26/binary/sets/games.tgz) = 2be515c495548ba5135ff42a75a8ebbfc35ea776 +MD5 (NetBSD-6.0/acorn26/binary/sets/games.tgz) = 9059a6f2cd41cb58827709c9e9a1649b +SHA1 (NetBSD-6.0/acorn26/binary/sets/man.tgz) = 899b9d8242e983a5110ab755651c24f709b5af67 +SHA512 (NetBSD-6.0/acorn26/binary/sets/man.tgz) = 410999db110d710f4bb498c3d7ae7adc62170c7c2f470ce189c92f6c436c5ea96149659c631ef0b5605caaa025d97dfe1c07c428d86f51239657bd6b71717b15 +RMD160 (NetBSD-6.0/acorn26/binary/sets/man.tgz) = c1270f68c6d41b351877f71f0396ac34877dfc8d +MD5 (NetBSD-6.0/acorn26/binary/sets/man.tgz) = df4db2bbfa39ef6a4a215d949653d04a +SHA1 (NetBSD-6.0/acorn26/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/acorn26/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/acorn26/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/acorn26/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/acorn26/binary/sets/xbase.tgz) = 875fd641f969ec00f854ca1334d084947450c740 +SHA512 (NetBSD-6.0/acorn26/binary/sets/xbase.tgz) = 75d0c9e9685b6b7bb706df7427c8b52f59c4fc4d0e725b02ee18024f75a546dc41de5f1a5d8552a8d2c84bdf87856e5857b0f12914801ca7b36b69536d617b4e +RMD160 (NetBSD-6.0/acorn26/binary/sets/xbase.tgz) = 1a4d099d59b2bd882e99f1b2df1c7bf22b890d48 +MD5 (NetBSD-6.0/acorn26/binary/sets/xbase.tgz) = 5eb9c573c5a0c96701f268a3470a58b9 +SHA1 (NetBSD-6.0/acorn26/binary/sets/xcomp.tgz) = 8d7469a85b7433c89690cce74e6b3f4e66cf0647 +SHA512 (NetBSD-6.0/acorn26/binary/sets/xcomp.tgz) = 411304cf66e300a7f162128203099bb4d6eebc4a93ba18ed7caf79f30b31cc7ffcede85c4e1bad02c3f5f8a27d009fb71f3ce5862c1d8aa477f39a25c535fdaa +RMD160 (NetBSD-6.0/acorn26/binary/sets/xcomp.tgz) = 822d26e0ee08b72ca8b991f0709a8c1bf0399208 +MD5 (NetBSD-6.0/acorn26/binary/sets/xcomp.tgz) = 5af361f0334d28119d703064278b3ed3 +SHA1 (NetBSD-6.0/acorn26/binary/sets/xetc.tgz) = 222d14c205f1018cc5a86eb03214d18cda2abb82 +SHA512 (NetBSD-6.0/acorn26/binary/sets/xetc.tgz) = fb82261996aa772fd8a9022eadebf899ee04ee70229ee4fe07758ca14937bdb34752c8218eb4c5b722b6208f719891493bbc141372fcfa503de83e0a61aa7387 +RMD160 (NetBSD-6.0/acorn26/binary/sets/xetc.tgz) = 511ebfe5076f361b7f7ca03a265d16052a16d259 +MD5 (NetBSD-6.0/acorn26/binary/sets/xetc.tgz) = 165cffbb6d2c79663198d80c82afac1e +SHA1 (NetBSD-6.0/acorn26/binary/sets/xfont.tgz) = ce0e141beeffeb5b470478e9887e4127da85de3c +SHA512 (NetBSD-6.0/acorn26/binary/sets/xfont.tgz) = 5d98354ff77103793d56af3192ab5f9afcde62208791976064ac33a149f994e0227dd5dd28ed544eeac5ea504e5212d5fb9e7d05e59e5a48a2fe4062e34e3106 +RMD160 (NetBSD-6.0/acorn26/binary/sets/xfont.tgz) = 4d09f5e82fec875ef0ea328809465e7a98f2ebfc +MD5 (NetBSD-6.0/acorn26/binary/sets/xfont.tgz) = be26b3890261302420b09976a1d38144 +SHA1 (NetBSD-6.0/acorn26/binary/sets/xserver.tgz) = 4ccfef1d49179603286042088bec0218c6b2031d +SHA512 (NetBSD-6.0/acorn26/binary/sets/xserver.tgz) = 809fc0a9065c1b9e7cd17aeb0d41cfd3158efd6c585556af01c4a3c93f0df3646a2ff77c6994449a703a408c0988fc1aa68cf34c7e297a3056d73ded57034c12 +RMD160 (NetBSD-6.0/acorn26/binary/sets/xserver.tgz) = 403604404261764c74f10fab774c4653fd20cc9b +MD5 (NetBSD-6.0/acorn26/binary/sets/xserver.tgz) = 914f909b6878cef16a92765a8cbb52ca +SHA1 (NetBSD-6.0/acorn26/binary/sets/kern-FOURMEG.tgz) = 3e74d7ca4f0ad181d8f37a28fc179fe4fdc3521f +SHA512 (NetBSD-6.0/acorn26/binary/sets/kern-FOURMEG.tgz) = 794689c5f293ed453fe424f3e1cd45bdf6127a08da0e6ded9b6f3c8afe0af6f65b1ca1aca96db5b8a4891102f38b2895aca82bba0dce8ee1389f2eb439ce11b7 +RMD160 (NetBSD-6.0/acorn26/binary/sets/kern-FOURMEG.tgz) = 66e7db127f67cf318789d74d7bdf5a57fdb922ed +MD5 (NetBSD-6.0/acorn26/binary/sets/kern-FOURMEG.tgz) = f26ed42c971ee7ce64682f5fa5a5c2b5 +SHA1 (NetBSD-6.0/acorn26/binary/sets/base.tgz) = 48cf8b5b14a8a61a85bf8bfa1ae739ef599a17e6 +SHA512 (NetBSD-6.0/acorn26/binary/sets/base.tgz) = f68d2d3e80b88fad8ff98a9bfdac7cc039d51e766130d3cade364a83bede6c6984c0cbcc56588f81760e6754ebbb08ad444fe4dd006e8ef91a3bc4e66c777e4a +RMD160 (NetBSD-6.0/acorn26/binary/sets/base.tgz) = 090a8ef5abfede25635b86e1ed989bd8c7b988e5 +MD5 (NetBSD-6.0/acorn26/binary/sets/base.tgz) = 6ea39b172012faf2bdbcb861d0de443c +SHA1 (NetBSD-6.0/acorn26/binary/sets/comp.tgz) = 8d6222fb0ba80750737719e3c9eb4d42aef1c92e +SHA512 (NetBSD-6.0/acorn26/binary/sets/comp.tgz) = eeacb62b5075abfd130a4ee4bcc8b3ada6fe2e3b4ad95cfa65fb45e61956092368c9e7dd90b7fbfefd7d96162890d23872d3bc4ad92488d92a50738d59629f9c +RMD160 (NetBSD-6.0/acorn26/binary/sets/comp.tgz) = adc77379342aa005884eb58a65a8d57d07e63853 +MD5 (NetBSD-6.0/acorn26/binary/sets/comp.tgz) = a660a76cb874c828690f5a128ff61501 +SHA1 (NetBSD-6.0/acorn26/binary/sets/etc.tgz) = 183e6af0c9ddf7c62218f3616129ed1223e0fd0b +SHA512 (NetBSD-6.0/acorn26/binary/sets/etc.tgz) = 0c9967126ddf9cdfdf568b6a7183bd9a17a119798f318f511ec9b9351770ffb8a394d57ccf09ce1e38b4e56d836f4ab61c943e81d932007e8726819733b0b108 +RMD160 (NetBSD-6.0/acorn26/binary/sets/etc.tgz) = 92fab0f295c28c53f693444918b12bc026596a3f +MD5 (NetBSD-6.0/acorn26/binary/sets/etc.tgz) = 1c4124013d68bbf2b85d3025aab1a0a9 +SHA1 (NetBSD-6.0/acorn26/binary/sets/kern-GENERIC.tgz) = 86de3875a3df7b400d86d2f97ea02067dac49288 +SHA512 (NetBSD-6.0/acorn26/binary/sets/kern-GENERIC.tgz) = c3eb9e9e696c7f166c9da1acdbf14b314863f68a5af5786c9d79c5e2ffd9c70ad366a6cec7ff0858ffae2ab8e028c0224b091de5bfcfad6a4ae5327709c7981e +RMD160 (NetBSD-6.0/acorn26/binary/sets/kern-GENERIC.tgz) = f2b59e92e18402c2e96a4b254fa18f21b339629c +MD5 (NetBSD-6.0/acorn26/binary/sets/kern-GENERIC.tgz) = 107061f8599c58b8a982c7f6b96e0fd3 +SHA1 (NetBSD-6.0/acorn26/binary/sets/modules.tgz) = 2e72e54d98a0bae829f2fdd53a9a927a4269fe83 +SHA512 (NetBSD-6.0/acorn26/binary/sets/modules.tgz) = 560d27968ab9740b7fec62e5afefddc5d6db9ebb73b79c38c34ab4d609fc4cfebe8bef7e05eb5fdacc17502236ae95675e2db87e5a8c258a3633f93635fe5aae +RMD160 (NetBSD-6.0/acorn26/binary/sets/modules.tgz) = eee9e83fc9e9936b93f382beb4f619c0d7010cd8 +MD5 (NetBSD-6.0/acorn26/binary/sets/modules.tgz) = 3e0985108f65114c721c3672279d28cb +SHA1 (NetBSD-6.0/acorn26/binary/sets/tests.tgz) = 72b14d964822d8a2e03c4d3855c33b2d5a02bcf5 +SHA512 (NetBSD-6.0/acorn26/binary/sets/tests.tgz) = 1b87e9174bb22df4c6b894fb731c53df03af87e6dbb8b2488fec832721c3ef3508c7dac35a2f51f144c6e726a8fff61d6f66d6a5c354c11ca2f2c8fe31a7d7a8 +RMD160 (NetBSD-6.0/acorn26/binary/sets/tests.tgz) = aa26cbefa7b2891c0d2e51a5f59c123c223721ff +MD5 (NetBSD-6.0/acorn26/binary/sets/tests.tgz) = a69e9d96707beccb4149aed72d701bfa +SHA1 (NetBSD-6.0/acorn26/binary/sets/text.tgz) = b4974a12425354e1d6dbe8e1e7def8ca2c8bea5a +SHA512 (NetBSD-6.0/acorn26/binary/sets/text.tgz) = 360652de2f694807759927e57beff0e60fae7855d4ab55a574e8c2d9cab25bf76bf1b880dd419c4bef6339dc72a16959f563e964644d64a81029354c87fb1b08 +RMD160 (NetBSD-6.0/acorn26/binary/sets/text.tgz) = e40abdac843b3ac9055fdacff0c74d259609886d +MD5 (NetBSD-6.0/acorn26/binary/sets/text.tgz) = e1ad13174b20a114fd74863b8a5a0399 +SHA1 (NetBSD-6.0/acorn26/installation/misc/netbsd-INSTALL.gz) = e7fda95700ee86c95cb2135c841840b815319eb5 +SHA512 (NetBSD-6.0/acorn26/installation/misc/netbsd-INSTALL.gz) = 79c810a6e1f7221aacd1e7b7edca4064ec6c3b7b99bbbe7282bdec0354c9387f9170019c7e6df5ec049497d8b0a69c07aaf485dfd286069437c16b7a44dd04ab +RMD160 (NetBSD-6.0/acorn26/installation/misc/netbsd-INSTALL.gz) = 68c551c4746c765068cc39e81eff40d13065ac19 +MD5 (NetBSD-6.0/acorn26/installation/misc/netbsd-INSTALL.gz) = 2f3714cfea4b8ace15469ca877ddcaf2 +SHA1 (NetBSD-6.0/acorn26/installation/misc/boot26,ffa) = 983591033b4f5301e5c3f9696b3e9037aaa11047 +SHA512 (NetBSD-6.0/acorn26/installation/misc/boot26,ffa) = 16ef2baf8d00639c68dafbf42a563815ca6a0cc51c1083820c47d10c06422abfa8257d25be675024bf674d70def6747cb70a45d2a8451551e0b7ac6915057bfe +RMD160 (NetBSD-6.0/acorn26/installation/misc/boot26,ffa) = a517e705c94bf87b617648aee6542e8194ad29b4 +MD5 (NetBSD-6.0/acorn26/installation/misc/boot26,ffa) = ed0fd36ea9ed9893250d9f588d5c358c +SHA1 (NetBSD-6.0/acorn26/installation/misc/netbsd-INSTALL.symbols.gz) = 3eca116cb41df17471b9e24e453c3164bc2f6fee +SHA512 (NetBSD-6.0/acorn26/installation/misc/netbsd-INSTALL.symbols.gz) = e2fce3e17958cd1865c584fa3a97a061f8fef09a8793f61018144e753d4667026349747ac7d9dfa6ad70afe2c4dbfeaef1f5718430947958f34785858e2424e3 +RMD160 (NetBSD-6.0/acorn26/installation/misc/netbsd-INSTALL.symbols.gz) = 9f25df06373241ff5dfaafa250311a4bc5020197 +MD5 (NetBSD-6.0/acorn26/installation/misc/netbsd-INSTALL.symbols.gz) = 4daa298789745793c9f9f1a03c4ecdb5 +SHA1 (NetBSD-6.0/acorn26/INSTALL.html) = e1896519f52cf8b3574c2ddad19d135e837ff05b +SHA512 (NetBSD-6.0/acorn26/INSTALL.html) = 9951385e876eed0126a9706c5c075453fd27ef0eb8fc42fa1bdca0e100a04d5f2d269145040eaffcfb683ef63f51a574254ce02cd3d0d3449ef867205e55c49a +RMD160 (NetBSD-6.0/acorn26/INSTALL.html) = 4e81e718d1526b61a1ebfc3dde631cc1c4f1998d +MD5 (NetBSD-6.0/acorn26/INSTALL.html) = e77700615f6d71545079d4f98be4fda3 +SHA1 (NetBSD-6.0/acorn26/INSTALL.more) = 31ce17bd0e1a3eb8956f06af4a2635a8cea3693e +SHA512 (NetBSD-6.0/acorn26/INSTALL.more) = c9693333dbbde859f3f8e1f5cb571e43eeac2a1727ce7e4681b4dacda1e145a54bacbb16346bed669a0f83e3592e7b824b66d0e0a2a0f39ab41891a0bee78ca5 +RMD160 (NetBSD-6.0/acorn26/INSTALL.more) = 12606307f5f4314a84d4401c5297bcf701fc1dcb +MD5 (NetBSD-6.0/acorn26/INSTALL.more) = 2104dbaa19182d2de7416aa62b7de537 +SHA1 (NetBSD-6.0/acorn26/INSTALL.ps) = 61b3e6838c01429478fd78f84fc380a320f1b2ba +SHA512 (NetBSD-6.0/acorn26/INSTALL.ps) = d96d21356a59e59ab344d4e4b720e9425b3e7a3f926e8e7d453f33c907eff12c9dfdb8a97133d77bafc30a7fdf5fb63ab529a73facbad6ac8f9a36c63a236db5 +RMD160 (NetBSD-6.0/acorn26/INSTALL.ps) = 50c971d098fc714fb2efe2f3e2cf49351a0f8fc5 +MD5 (NetBSD-6.0/acorn26/INSTALL.ps) = f0d32affe70e695f4bcbe2df304f6a65 +SHA1 (NetBSD-6.0/acorn26/INSTALL.txt) = 00ac475ec70626dc1041211ecd0e5c7e213af948 +SHA512 (NetBSD-6.0/acorn26/INSTALL.txt) = 816c536f0caacbf292b9b54e812dc474299ee6a1084682321039bb1d3fd725523d76666fc14c772951ca45409550a25b5b74cefa0bf3f7539a17995a56df9756 +RMD160 (NetBSD-6.0/acorn26/INSTALL.txt) = c4618e23cd501a7520502285a24dc8813e1a4913 +MD5 (NetBSD-6.0/acorn26/INSTALL.txt) = f02c846c660d531f87f85271e991c77b +SHA1 (NetBSD-6.0/acorn32/binary/kernel/netbsd-GENERIC.gz) = 8d2b1f19b2ba2231aba8e20c14ab5fd83dde59ae +SHA512 (NetBSD-6.0/acorn32/binary/kernel/netbsd-GENERIC.gz) = 364ad36c66788c822a3cbfd0ddffafc6d19f9bb82144be988848970b7e0b6d11c2afaf4784f2132affe6ca052c69a4595181b1c37363637bb54f849e5bf4a1dd +RMD160 (NetBSD-6.0/acorn32/binary/kernel/netbsd-GENERIC.gz) = 02d7f52cc0c15ff1039f3767cfa3840e5551e03a +MD5 (NetBSD-6.0/acorn32/binary/kernel/netbsd-GENERIC.gz) = 96f504edccc8d4f5657c1837cdfd2aaa +SHA1 (NetBSD-6.0/acorn32/binary/kernel/netbsd-NC.gz) = fc98fecc5548fde9220873e791d4d4846cefe4b3 +SHA512 (NetBSD-6.0/acorn32/binary/kernel/netbsd-NC.gz) = ff106589ca7b58c2ef3146a93be72b73987c221694400f3a2256728e618a7b486f32020f031e68edade5d13b3b9584a18ca88ce3fed71f06f9b494b3cb6eb844 +RMD160 (NetBSD-6.0/acorn32/binary/kernel/netbsd-NC.gz) = 4ff74a916d3283eb80e77739fd31dcda4890658b +MD5 (NetBSD-6.0/acorn32/binary/kernel/netbsd-NC.gz) = f3a826b7eea3f009868a5ad419b69c3c +SHA1 (NetBSD-6.0/acorn32/binary/sets/games.tgz) = e1d2bb091d8202962133475bc83edb55230b9008 +SHA512 (NetBSD-6.0/acorn32/binary/sets/games.tgz) = a147fe6d0419d53d5a428802d0bb6c9fa8a84a76c96d7d6d7c0d399e5af3a69240116463549a83d53387b0214ba0207796d7c10228d92a684fe7ff0ece3aec16 +RMD160 (NetBSD-6.0/acorn32/binary/sets/games.tgz) = 2be515c495548ba5135ff42a75a8ebbfc35ea776 +MD5 (NetBSD-6.0/acorn32/binary/sets/games.tgz) = 9059a6f2cd41cb58827709c9e9a1649b +SHA1 (NetBSD-6.0/acorn32/binary/sets/man.tgz) = 899b9d8242e983a5110ab755651c24f709b5af67 +SHA512 (NetBSD-6.0/acorn32/binary/sets/man.tgz) = 410999db110d710f4bb498c3d7ae7adc62170c7c2f470ce189c92f6c436c5ea96149659c631ef0b5605caaa025d97dfe1c07c428d86f51239657bd6b71717b15 +RMD160 (NetBSD-6.0/acorn32/binary/sets/man.tgz) = c1270f68c6d41b351877f71f0396ac34877dfc8d +MD5 (NetBSD-6.0/acorn32/binary/sets/man.tgz) = df4db2bbfa39ef6a4a215d949653d04a +SHA1 (NetBSD-6.0/acorn32/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/acorn32/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/acorn32/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/acorn32/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/acorn32/binary/sets/kern-GENERIC.tgz) = 0ec8993d446ad847bf7a6154a19c638d944bd24b +SHA512 (NetBSD-6.0/acorn32/binary/sets/kern-GENERIC.tgz) = bed0345f83d42ee18b1cb1fab95e6780a217edda00c0c548aeb99323327493d1720b615d746a4e364a5217f963f24ae55142fc943a0d95aec65d8ddff2d36045 +RMD160 (NetBSD-6.0/acorn32/binary/sets/kern-GENERIC.tgz) = 2f27e6f036ad4fb08171f93e21324b9f901b781a +MD5 (NetBSD-6.0/acorn32/binary/sets/kern-GENERIC.tgz) = 5eed762a46bf55d66491dab47bd40f23 +SHA1 (NetBSD-6.0/acorn32/binary/sets/base.tgz) = 519435bdcdffa41f24c56796558ad43ba6c89f31 +SHA512 (NetBSD-6.0/acorn32/binary/sets/base.tgz) = b7a3f4a5627790133104674c25e434d16a0e706006352f0032a4672f624c7fbf37b0678f72f593c5e17dea469afc03e09ac914eb4a02acb47b9a5673bd7e9777 +RMD160 (NetBSD-6.0/acorn32/binary/sets/base.tgz) = caf168bcd8c374896c8a0408e3d34e9c7e6f2c7b +MD5 (NetBSD-6.0/acorn32/binary/sets/base.tgz) = b221228a61e59d66f1b457f5dcb1b5cc +SHA1 (NetBSD-6.0/acorn32/binary/sets/comp.tgz) = 54b3cdd58c6db224ec42033f1f40842e55625e9f +SHA512 (NetBSD-6.0/acorn32/binary/sets/comp.tgz) = a32e6f39ea01c783e1ff603c8774130698db0056923ef4c029f29f0df20f6b63885f33a50586774bc7c12b392f278344afd3aca42112bed8a3cd14d6ef72ff7e +RMD160 (NetBSD-6.0/acorn32/binary/sets/comp.tgz) = cde7f725c376e8c0633d821357033e742358bb28 +MD5 (NetBSD-6.0/acorn32/binary/sets/comp.tgz) = c3866ce0cbc35fc4ffc58b14cc72ed31 +SHA1 (NetBSD-6.0/acorn32/binary/sets/etc.tgz) = e7c005ca92edbf1b8225f951b95b5938a94ee651 +SHA512 (NetBSD-6.0/acorn32/binary/sets/etc.tgz) = 01b47e91a0969eb2c3d7fd7f73563e98201ab401b9069b6d5e64e878757761410b8a181fcd04b141168c851d466e6d4e1b48b540e654d1831195deecbe5c23f7 +RMD160 (NetBSD-6.0/acorn32/binary/sets/etc.tgz) = f654da0c3fa14a8d8dc3a0cdb977d98b07b0d4ac +MD5 (NetBSD-6.0/acorn32/binary/sets/etc.tgz) = 295b42a630082e4db876d35a7e5a204c +SHA1 (NetBSD-6.0/acorn32/binary/sets/kern-NC.tgz) = e0744de8e7bc2a5808e603563cd8201de0601323 +SHA512 (NetBSD-6.0/acorn32/binary/sets/kern-NC.tgz) = 93c2fda5dd5a16eab210f74c0cf749fd013ec3488d6424fea84d404b2db5555a449a6a0ce9d936d7e18ec93216b1fa7a914e951dba3f223ac6b4de27d1f8cd32 +RMD160 (NetBSD-6.0/acorn32/binary/sets/kern-NC.tgz) = b0be18f3134075df50daec32dc87e30f370f7531 +MD5 (NetBSD-6.0/acorn32/binary/sets/kern-NC.tgz) = 5b8eb4b95fa6151bfbcaf0f72a6f6abb +SHA1 (NetBSD-6.0/acorn32/binary/sets/modules.tgz) = 7df712c3742771ef53b42065426e7761020cf439 +SHA512 (NetBSD-6.0/acorn32/binary/sets/modules.tgz) = 3c682c61bca3059470ea6ceaf5e40314cc1876b9b183910692a1664a975aacae619c2214695a92f68463142940640042ba48f9acb39488fddfa757ffb74eb6e4 +RMD160 (NetBSD-6.0/acorn32/binary/sets/modules.tgz) = 35fc06c8194cb14f2258ce805c1e4fb8097669d0 +MD5 (NetBSD-6.0/acorn32/binary/sets/modules.tgz) = ffbd55bff72382bbc82342bacf6840ba +SHA1 (NetBSD-6.0/acorn32/binary/sets/tests.tgz) = 68dae6dac916379bb48be79e8b2fe49898c4cfe5 +SHA512 (NetBSD-6.0/acorn32/binary/sets/tests.tgz) = b06a5ac96d76e0521e2d6666518a1549975a4d11767264c7d3b0d3dd8afe8aaa8e4f3113095d18d74146ee7e4c17a8d8a180bb4367c9aff6359b60ec06107970 +RMD160 (NetBSD-6.0/acorn32/binary/sets/tests.tgz) = 5a4c05ecc975a7ee61eda422a7dc7a5b1084424f +MD5 (NetBSD-6.0/acorn32/binary/sets/tests.tgz) = ef0313ce1e3aec16c96660fc0b8e691b +SHA1 (NetBSD-6.0/acorn32/binary/sets/text.tgz) = bb5835aee28d492add5e601c1323c4c1f0ac09e0 +SHA512 (NetBSD-6.0/acorn32/binary/sets/text.tgz) = ac45662324b717ccc775d4f4adfaf6623e8383fea5c5d4177fe21f8799a2a7534faff515c979f85cac6de86f166a0fcbc1021a8b8ff2a2c787fd341a4e6a6c91 +RMD160 (NetBSD-6.0/acorn32/binary/sets/text.tgz) = 96fbbe37b32d596fad17af067c28acf08eaaaa57 +MD5 (NetBSD-6.0/acorn32/binary/sets/text.tgz) = 1ff71742549a26794970d5aaef2c5f09 +SHA1 (NetBSD-6.0/acorn32/binary/sets/xbase.tgz) = 150aad78ea2477c5c1b395bda15bae8f0f72d36c +SHA512 (NetBSD-6.0/acorn32/binary/sets/xbase.tgz) = 7ff70ee14b5943899517b4a7b2422ba1c62468399f55905e595d50de15fcfa2e89281a917c96d6d36e2dec519162227f7e6809c9a1da475c68982216d9acb242 +RMD160 (NetBSD-6.0/acorn32/binary/sets/xbase.tgz) = 0411d8686275c3d1146e42ddb69a0080bc82d950 +MD5 (NetBSD-6.0/acorn32/binary/sets/xbase.tgz) = 97aec1ef3a6ef744c85a7eaa6c403c1a +SHA1 (NetBSD-6.0/acorn32/binary/sets/xcomp.tgz) = 9847900750d33556792e7b62e3e0ffc3f3ea625f +SHA512 (NetBSD-6.0/acorn32/binary/sets/xcomp.tgz) = 010fc75bcd0355d1ea09cd8ddba94b16fab7224bec4aba26d07bf43f259b47b564fe008e6c477ce4a41161ae76dbd26d89f894ec5bf2ea7193cab2965d96de50 +RMD160 (NetBSD-6.0/acorn32/binary/sets/xcomp.tgz) = 975dbb1ec0a8f32cee4bfe55b4adb9f617d917be +MD5 (NetBSD-6.0/acorn32/binary/sets/xcomp.tgz) = 7e761d7288845752bf05af5ac943d158 +SHA1 (NetBSD-6.0/acorn32/binary/sets/xetc.tgz) = 6b7815869c1c48a2efb0dfcdaae373700d5da8d9 +SHA512 (NetBSD-6.0/acorn32/binary/sets/xetc.tgz) = 42cbbc48a006498d46221eff6403acceeaf20ee5cb4a4f368b74e5b4599cccbd54f3d83b4a55359622599184f376f6bea2f2ad0feb364ce7d0293c3fb9d5b32d +RMD160 (NetBSD-6.0/acorn32/binary/sets/xetc.tgz) = a60ea2e898741a2d009ca8c6c621fbcae1f1efce +MD5 (NetBSD-6.0/acorn32/binary/sets/xetc.tgz) = 16cc8b76db930a1eb7b009e7776e2881 +SHA1 (NetBSD-6.0/acorn32/binary/sets/xfont.tgz) = 558af1104a11439ab8c868728c55027dd5862ce8 +SHA512 (NetBSD-6.0/acorn32/binary/sets/xfont.tgz) = fb28abf27b6cadadc9c0ca82df3025e22d4e0661dcc0488083c7339c5372acf0adea8edc848b7cea50980d971aa24f81bbda068b4b4bed6ac4cf26cc4f5b35bf +RMD160 (NetBSD-6.0/acorn32/binary/sets/xfont.tgz) = f6df63aefaa5c459b2c86ae79fc7b07253424c97 +MD5 (NetBSD-6.0/acorn32/binary/sets/xfont.tgz) = 498abc855e6717ab51d5d0be8fa5662d +SHA1 (NetBSD-6.0/acorn32/binary/sets/xserver.tgz) = 292d81e44c40c73e8341d59175695b649f839baa +SHA512 (NetBSD-6.0/acorn32/binary/sets/xserver.tgz) = 3593eeeda7a9f55ff29622c2a95672c746f9235e007b3d8e81e33829fa655d0f6bc8ba90f6ef53baad1b25789fd656d5d8ea14152a9b41abf1a1bfbd2b11937f +RMD160 (NetBSD-6.0/acorn32/binary/sets/xserver.tgz) = e0e2425da086891061ddae334fd8e98d77c519c9 +MD5 (NetBSD-6.0/acorn32/binary/sets/xserver.tgz) = bd36f768d1488956ea90a9f13ac8929c +SHA1 (NetBSD-6.0/acorn32/installation/kernel/netbsd-INSTALL.symbols.gz) = b155be9bb81a3c15abe2b6732d48e8bfe53abc53 +SHA512 (NetBSD-6.0/acorn32/installation/kernel/netbsd-INSTALL.symbols.gz) = a3a1c068acbe2d634da3442aac4de7107dfcaf3634be291f9c3285aeb9fa680e59acb9273774e6317f71d6f9be2e1851a0e0f60b3cc83972f3e185f3e8237522 +RMD160 (NetBSD-6.0/acorn32/installation/kernel/netbsd-INSTALL.symbols.gz) = 3ac12cb07a5e8b9810946c489b9a4c3b9aecdcbc +MD5 (NetBSD-6.0/acorn32/installation/kernel/netbsd-INSTALL.symbols.gz) = 1fe3c151480781a09a6f642ab87b9495 +SHA1 (NetBSD-6.0/acorn32/installation/kernel/netbsd-INSTALL.gz) = dc38de07bef2736068ee9cd3103f87ea6938fd6d +SHA512 (NetBSD-6.0/acorn32/installation/kernel/netbsd-INSTALL.gz) = 11b29549b4b8232380eb6db4bf89a979e9b2a2726a3c7ff51ab059fd4f8b6a979d2cb7fe6d0c1802e345c445989655339a9a8b8d4a10f728ac7a24bae9f1830f +RMD160 (NetBSD-6.0/acorn32/installation/kernel/netbsd-INSTALL.gz) = 605df2071d2e590be8a4d0f83c9a55a140066bc5 +MD5 (NetBSD-6.0/acorn32/installation/kernel/netbsd-INSTALL.gz) = dbc61ce2c5adf5f8e18441138aa4ae5a +SHA1 (NetBSD-6.0/acorn32/installation/misc/BtNetBSD.spk) = 12dac3d0059f8eef736a378bb6e026166694c1a5 +SHA512 (NetBSD-6.0/acorn32/installation/misc/BtNetBSD.spk) = f54991c3e27613ac735b1a10d5ffcc102799417a68415b74c9557657c0e714fd7faa381a3945991bd80b49cefa2ec01395d88d0e935d063ff91174a8e12887ee +RMD160 (NetBSD-6.0/acorn32/installation/misc/BtNetBSD.spk) = 02e5c2a9d751d8236ebbd0d4151f687fdd896735 +MD5 (NetBSD-6.0/acorn32/installation/misc/BtNetBSD.spk) = 4b3907f57b03d49765f92ffff178ef40 +SHA1 (NetBSD-6.0/acorn32/installation/misc/ramdisk.fs.gz) = 73ae7358fb27f8d227e253b6f43e5fcbdd7cb5f3 +SHA512 (NetBSD-6.0/acorn32/installation/misc/ramdisk.fs.gz) = 3c68e80766ae3603b289f11469c2c80ba1ffb5eb30f323fee016d992d7d226bf1984f487ee486cb3d0b1739bf45ae3ad52ddeb5f90ff2d0abd08cafc1a181ccf +RMD160 (NetBSD-6.0/acorn32/installation/misc/ramdisk.fs.gz) = 3320c3a2a2d0e60d55b4612811d1870a4e8b9ec1 +MD5 (NetBSD-6.0/acorn32/installation/misc/ramdisk.fs.gz) = 70f0aee2f9cfc56744c50b3bed23b5a5 +SHA1 (NetBSD-6.0/acorn32/installation/misc/boot32,ffa) = 1a8c3e3a8950e68d6fd3d22ccf985814f67e00c1 +SHA512 (NetBSD-6.0/acorn32/installation/misc/boot32,ffa) = 2f7091d17fc4c910846f5cdc8cd267eb7d4056e281175c00407ab958548c62af4936394a04bde6549223fc874df72c5c46b0d11ae32ea6970c17326b0cedc6af +RMD160 (NetBSD-6.0/acorn32/installation/misc/boot32,ffa) = 5821041d9dff2485cba9ab49e289a0bd479fc63d +MD5 (NetBSD-6.0/acorn32/installation/misc/boot32,ffa) = 0f03b946d6479db2aaf8088dba4632ed +SHA1 (NetBSD-6.0/acorn32/installation/misc/splug.bas) = 19015ba8a9efd73fea65fe180596271640893d1b +SHA512 (NetBSD-6.0/acorn32/installation/misc/splug.bas) = ef38a1da79c93ff798c858f02d3d13e88d24bd0b56808ddb71b3dd577203195a60f601aa52e37892ab164ef7dd0cd490995ac9cd689fe33282fb49435f4c4d56 +RMD160 (NetBSD-6.0/acorn32/installation/misc/splug.bas) = 3080fc8d5ff946754a33bc41e7ad83cbe1eaa0b5 +MD5 (NetBSD-6.0/acorn32/installation/misc/splug.bas) = 5596dc5df580ceb656d040393e778087 +SHA1 (NetBSD-6.0/acorn32/INSTALL.html) = d16bd043227b34d9a9c3c69f380c6c42b50d080c +SHA512 (NetBSD-6.0/acorn32/INSTALL.html) = 629401693cb91992f46b839a34bf4c4ac704194fd8aa6be3aa51e405920b697fe961fa7320eef7a4cf804dad96891b38ca57c61ef3c0c6096bb6bc71f58e55a9 +RMD160 (NetBSD-6.0/acorn32/INSTALL.html) = 222b9b590667b0a6dfe2717bb6dc94e95a485174 +MD5 (NetBSD-6.0/acorn32/INSTALL.html) = 07466bc8646d08bee6c7030d00cc9173 +SHA1 (NetBSD-6.0/acorn32/INSTALL.more) = 011db6fc8ab7b724dc66eafb3b712e9202bb2174 +SHA512 (NetBSD-6.0/acorn32/INSTALL.more) = d13335bfe65882608362fda44f89091113e3bffb53893f15bb747aaa72eefbb24ca3fd3d72017cfc446ba49ad7c00f34436e859f71727f9e6a182766a1810a13 +RMD160 (NetBSD-6.0/acorn32/INSTALL.more) = aaa800047583e64496187a80e54d0ac3bf4c851c +MD5 (NetBSD-6.0/acorn32/INSTALL.more) = c45c7b7fd7522e41a977ffa6a58b5a4d +SHA1 (NetBSD-6.0/acorn32/INSTALL.ps) = 78d2daf3255e7bc61b5682d5fcfd853d7dd25883 +SHA512 (NetBSD-6.0/acorn32/INSTALL.ps) = 4aec0769a5827735e13ab61dd80b5c7254561786afe0c95ff76796a8b29ae2284c064a1a1c523120366e37197bcbfd3d588985dbaae62c9848a4669d8c797714 +RMD160 (NetBSD-6.0/acorn32/INSTALL.ps) = 764dc8cc82d5623174886f98f77d808650ef90d1 +MD5 (NetBSD-6.0/acorn32/INSTALL.ps) = fc4371f1451a03c4ea429fe029e46d9c +SHA1 (NetBSD-6.0/acorn32/INSTALL.txt) = 9d1ed61f6916645ffa30e66b23da2d0d24e18582 +SHA512 (NetBSD-6.0/acorn32/INSTALL.txt) = 10763c9164aeb2d4070f1677b0f97ca8263ec1b9d9c017fbcf348ce302d7d846fa669b741031eef4b12c27a7d077f6af9073f7668244b1b4daa39ab426d79ec7 +RMD160 (NetBSD-6.0/acorn32/INSTALL.txt) = 755fbe335d76c9b549fae4d01120cbe00290e8ca +MD5 (NetBSD-6.0/acorn32/INSTALL.txt) = 1a6f36bd9f77e0773aeae95de9ceed8f +SHA1 (NetBSD-6.0/acorn32/prep.RISCOS) = 269ee721985cbc44a8056ca4804f8b2d70d52a3e +SHA512 (NetBSD-6.0/acorn32/prep.RISCOS) = 54923d8dc59e6a3852ceab25adbced3e545de19458c412552ef0cb47534303d812e8860662025b1aa9ddf9a99bb139f4be75656ef109546a328ba57985ec2cfa +RMD160 (NetBSD-6.0/acorn32/prep.RISCOS) = 8e3acd93d35d85062996b061cff5d7293f46ee1f +MD5 (NetBSD-6.0/acorn32/prep.RISCOS) = 3c0e290b44f735728abd3bda8bd96a0f +SHA1 (NetBSD-6.0/algor/binary/kernel/netbsd-P4032.gz) = e9df71ffe487dd98c1aae0c6e79fbf8e4780340a +SHA512 (NetBSD-6.0/algor/binary/kernel/netbsd-P4032.gz) = 48673b13075fc7694dccb1a31b6121281c5c0e85c5d7107a4f9414e9888c19f07133a07e43400495dd9e11757acc2fa2269458ae4b091900772c49a944624465 +RMD160 (NetBSD-6.0/algor/binary/kernel/netbsd-P4032.gz) = 85b0c6fde5bd0f4a02f71c30ccaf35d9bc29ac19 +MD5 (NetBSD-6.0/algor/binary/kernel/netbsd-P4032.gz) = 2f041466a193e263576e80bfca3ce8ef +SHA1 (NetBSD-6.0/algor/binary/kernel/netbsd-P5064.gz) = f230eefee689dff40a0aca1983191c2e21c7dbde +SHA512 (NetBSD-6.0/algor/binary/kernel/netbsd-P5064.gz) = eb7fea73f29d2141f508743785ee865bd5f7ce23477fc1bf256e40a0f47de76a7cdb22bfac0cb9dce94c0e1694b1c84b1760db13ab1b34248a6e04367817214d +RMD160 (NetBSD-6.0/algor/binary/kernel/netbsd-P5064.gz) = 355d23c8cbde9c1a92bf5f1eb4e1f1890603e7f7 +MD5 (NetBSD-6.0/algor/binary/kernel/netbsd-P5064.gz) = 5ebc249debbe1797d915529f1d469f8b +SHA1 (NetBSD-6.0/algor/binary/sets/games.tgz) = 27d9f98fecb3495e51939df9f107e81e527af26f +SHA512 (NetBSD-6.0/algor/binary/sets/games.tgz) = 46bb4e10313cfffaaf4f7fa2157474ef940f94bcc9f84b46f829c7615bbf45e4e01edee7b7efb84bc28561e0712c37cfc737f9c2a0d9a73b67c80c8aa0f3a9af +RMD160 (NetBSD-6.0/algor/binary/sets/games.tgz) = 947feea90ec2698a65d555cb78a29a001b086589 +MD5 (NetBSD-6.0/algor/binary/sets/games.tgz) = 355f00978fed8e8da6a251e591be5387 +SHA1 (NetBSD-6.0/algor/binary/sets/man.tgz) = 899b9d8242e983a5110ab755651c24f709b5af67 +SHA512 (NetBSD-6.0/algor/binary/sets/man.tgz) = 410999db110d710f4bb498c3d7ae7adc62170c7c2f470ce189c92f6c436c5ea96149659c631ef0b5605caaa025d97dfe1c07c428d86f51239657bd6b71717b15 +RMD160 (NetBSD-6.0/algor/binary/sets/man.tgz) = c1270f68c6d41b351877f71f0396ac34877dfc8d +MD5 (NetBSD-6.0/algor/binary/sets/man.tgz) = df4db2bbfa39ef6a4a215d949653d04a +SHA1 (NetBSD-6.0/algor/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/algor/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/algor/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/algor/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/algor/binary/sets/xbase.tgz) = 76468fcada5a9e26652aa9f0f9f3c94829a317e9 +SHA512 (NetBSD-6.0/algor/binary/sets/xbase.tgz) = b2adcfc2dedef30b21b885c8fc757d0479541744a280a9997fbeaa9c881009ab4b0019e0001a540a8eb6db5f84db87b365e420bb2d4270af209821bdb080369c +RMD160 (NetBSD-6.0/algor/binary/sets/xbase.tgz) = 1e0074d03d9fbb3373e0a427b25cc7097bf6d3c8 +MD5 (NetBSD-6.0/algor/binary/sets/xbase.tgz) = a8f29ec2e3768405942f97af3dd08ee7 +SHA1 (NetBSD-6.0/algor/binary/sets/xcomp.tgz) = d8ac89f3f6ff20abb0adabc49227afdb74aa2040 +SHA512 (NetBSD-6.0/algor/binary/sets/xcomp.tgz) = 4f03213fb061dae9421747209628d06ede6bbb71a7560a9e1a54796b907f1620146a33fdce52974227a21acedcc210b99e15c4fdd36432eba60c1041a92d8cee +RMD160 (NetBSD-6.0/algor/binary/sets/xcomp.tgz) = 6be5e72b9b57c9bdf8ed8ea127e2a73830feeecb +MD5 (NetBSD-6.0/algor/binary/sets/xcomp.tgz) = 59a7ea141587417be38ab1f6056cc780 +SHA1 (NetBSD-6.0/algor/binary/sets/xetc.tgz) = b9f6b1a54ffab37b11f4c6e717b481cd087fb609 +SHA512 (NetBSD-6.0/algor/binary/sets/xetc.tgz) = 72f35e65f3a90967e250a2006d500619b3824f7f5c3d7494554f153ec5cda5b28c445f28c34a1e4463f40da5855e8d4257726411796967fe37763d90cf7fe461 +RMD160 (NetBSD-6.0/algor/binary/sets/xetc.tgz) = 1169c246f91189fd0c4ae86ac27a92f5c2edda3e +MD5 (NetBSD-6.0/algor/binary/sets/xetc.tgz) = 8f3c52cc5af1cafaf7b0d0f884a5b537 +SHA1 (NetBSD-6.0/algor/binary/sets/xfont.tgz) = d06848571034f3b7fc975082f1de37b912acb18c +SHA512 (NetBSD-6.0/algor/binary/sets/xfont.tgz) = 66a1013c935bee5e7e5d24325a527522306bcded7ced63790f2e58831b3ed91176a1b9510b2159be63504d5167d48d534919927ffc6e225ae2bb2487f90a9ede +RMD160 (NetBSD-6.0/algor/binary/sets/xfont.tgz) = c9502843a5d4dd7e996e8d158c519cf7f8575cbd +MD5 (NetBSD-6.0/algor/binary/sets/xfont.tgz) = e812899176eac2bf65a6d949ac3f3424 +SHA1 (NetBSD-6.0/algor/binary/sets/xserver.tgz) = ff805022f409202f3346c45475c7ec0f8187218e +SHA512 (NetBSD-6.0/algor/binary/sets/xserver.tgz) = f2bb3810a5572b519980126a3d934f63b5ab5c2fcf9fb8166c556bd3cc14cfaa151d582086bb1506ac9ac7e21d4e70a5cd5c3faed96212d8a14a0b5bafdcc4c1 +RMD160 (NetBSD-6.0/algor/binary/sets/xserver.tgz) = d5ae336337cc77f7f55f542b3457918d6fc0efe8 +MD5 (NetBSD-6.0/algor/binary/sets/xserver.tgz) = 92447a1560887d337d22e2deed0670a6 +SHA1 (NetBSD-6.0/algor/binary/sets/kern-P4032.tgz) = 810ebe688c1817dcfd7cab153a6d9997900555b8 +SHA512 (NetBSD-6.0/algor/binary/sets/kern-P4032.tgz) = 8846047a1a93d3ba853e235b2169286e09f5955d3116bd2bdb18f0d252c8b0ae0d310f3ccf6d30244d089f7b077579e8246ddb27f32ddcee26e6b7b7b2266aaa +RMD160 (NetBSD-6.0/algor/binary/sets/kern-P4032.tgz) = 039bc25b47bc29648ebb86fad5fb52852badc0fc +MD5 (NetBSD-6.0/algor/binary/sets/kern-P4032.tgz) = f8011c18eab0acde582df5ddda0d3a57 +SHA1 (NetBSD-6.0/algor/binary/sets/base.tgz) = 1cacc62a3d246592b148a70bef11a751b63a4810 +SHA512 (NetBSD-6.0/algor/binary/sets/base.tgz) = cd448e4f0533c50daf74ed21467409013d512e128b177c9b9ab47771d3d2cffcbe403ba207309af77eb6712d316d9db2923205765be8d9045e2b2216f94774d4 +RMD160 (NetBSD-6.0/algor/binary/sets/base.tgz) = c78efd1403b1cb3af77f5a0cbddbd095505d4f65 +MD5 (NetBSD-6.0/algor/binary/sets/base.tgz) = 33b467da96b628c9b68cd57209d353b7 +SHA1 (NetBSD-6.0/algor/binary/sets/comp.tgz) = 3e955d4a87fe115e37da729b9d2474a775614d30 +SHA512 (NetBSD-6.0/algor/binary/sets/comp.tgz) = 12ce5ac677ba9f44944f57859218d668d3d2bc3323ac5793545ca7de849480dc093f03226fed4dac42bf7a4ee69fc998b4a5e2c62607d754e0b58a3cc73d3d9d +RMD160 (NetBSD-6.0/algor/binary/sets/comp.tgz) = 106fbdfddd7c9bd13d1b5d2111b39d4338bd8c10 +MD5 (NetBSD-6.0/algor/binary/sets/comp.tgz) = 8d493a09f9e5580f830f15a3c0b12d84 +SHA1 (NetBSD-6.0/algor/binary/sets/etc.tgz) = c0511cfd28c1b22e71166507a0f564c24015f025 +SHA512 (NetBSD-6.0/algor/binary/sets/etc.tgz) = d47fee208d0d59cf0edbbf2c75bbe404a176f66f0058db93ba553fffdc31d5b5ed6c2ba2df505f7b1576cd06cc27de5da3dfda1230927c2ac603a326aff688b2 +RMD160 (NetBSD-6.0/algor/binary/sets/etc.tgz) = 09d069cea8b5a133736d483097bcf24649f0d52a +MD5 (NetBSD-6.0/algor/binary/sets/etc.tgz) = 4ce17fdd45c77f0d8632a836463db036 +SHA1 (NetBSD-6.0/algor/binary/sets/kern-P5064.tgz) = 1fa8786b3038a1bc218f5e8280ae3871f5687e4c +SHA512 (NetBSD-6.0/algor/binary/sets/kern-P5064.tgz) = 0977b6911d05ee98e53841af3acff6b5f751c93841c96f3869cfad0e978596204cb22d3a1608842c36d24a50f16a35d0ec00288d56fd69e6cd33d8b2b1dc37c6 +RMD160 (NetBSD-6.0/algor/binary/sets/kern-P5064.tgz) = 8fd50961f224a94e272a15df2061f226d0d2456a +MD5 (NetBSD-6.0/algor/binary/sets/kern-P5064.tgz) = 7932f7ce7a89995425a3e97319de27b7 +SHA1 (NetBSD-6.0/algor/binary/sets/modules.tgz) = 3627b369e3392221946d517d950da8bb6c3b6170 +SHA512 (NetBSD-6.0/algor/binary/sets/modules.tgz) = bbdaa688d423fce2ba3513727b4fd0758cb3c6b6db3147b09319990270380b4cf8feede38a2b57757095627356d6955a30d647d770d67a2bf97e66f0673e4770 +RMD160 (NetBSD-6.0/algor/binary/sets/modules.tgz) = 5040267ebae4a2069ad1b9168b31d568d2f81fca +MD5 (NetBSD-6.0/algor/binary/sets/modules.tgz) = d3e9a884b3cef9a6ee2dd6b8c715901a +SHA1 (NetBSD-6.0/algor/binary/sets/tests.tgz) = 76544bff809ab691a739a3ffebc3988b1473fdc2 +SHA512 (NetBSD-6.0/algor/binary/sets/tests.tgz) = 5e5709ec49a4e20f253ed5686f9fc62300b3c0aa70bc2cf036a41130803c578cc692b89fc234334723bc39f74cb0a8bd9e9be88cfa692213554713766c9a3b7b +RMD160 (NetBSD-6.0/algor/binary/sets/tests.tgz) = 66eb344c33b3c463c3a6c3af96af263d8cb6dfe0 +MD5 (NetBSD-6.0/algor/binary/sets/tests.tgz) = 3ae196d57949ee2cb682ab871c9ef316 +SHA1 (NetBSD-6.0/algor/binary/sets/text.tgz) = fe2e0c01c5af66987eab5bb59b06fba32c006be2 +SHA512 (NetBSD-6.0/algor/binary/sets/text.tgz) = 3fdd84b91bc54bb3f045bf068d01b4b67fe35a62deffdf8b5964f5dc978d55b58b5b592c9fc9a05d40b305914ce7465981b4d55ec95571203c54f240a2bdff4c +RMD160 (NetBSD-6.0/algor/binary/sets/text.tgz) = 420dc3d206809ea2438b82c912a041637e4d0949 +MD5 (NetBSD-6.0/algor/binary/sets/text.tgz) = b421f4428b8e52bb19e997954cb1d0ca +SHA1 (NetBSD-6.0/alpha/binary/kernel/netbsd-GENERIC.MP.gz) = 20bd351669d8b8c5e6ed9726567516aa2b20e101 +SHA512 (NetBSD-6.0/alpha/binary/kernel/netbsd-GENERIC.MP.gz) = 16699cd9ff46de1282439235429a63aa38ad6eae8197f037e7f8bd2324ff696a04d4b2008723edb8bdae8e55f139024c55e3858670a3db4f6ff317fef3d39919 +RMD160 (NetBSD-6.0/alpha/binary/kernel/netbsd-GENERIC.MP.gz) = 5897524a8bc830e819894c17803a141c65b4f417 +MD5 (NetBSD-6.0/alpha/binary/kernel/netbsd-GENERIC.MP.gz) = 0ab46adc2ba2d37bfaac5fe5296fe616 +SHA1 (NetBSD-6.0/alpha/binary/kernel/netbsd-GENERIC.gz) = daee92c8428d90796700da80702277f38afd7c78 +SHA512 (NetBSD-6.0/alpha/binary/kernel/netbsd-GENERIC.gz) = 658bcdb3fe7c015e0de0d6fd795e9a9033618eb193c6e81b179b978836c93cd3b6a09f79ff4405f831f81e003bd190e91534112e9a923d10c3fb094478f4421a +RMD160 (NetBSD-6.0/alpha/binary/kernel/netbsd-GENERIC.gz) = 2bbdd4f11b998dbe08e2076e895785e90f17b192 +MD5 (NetBSD-6.0/alpha/binary/kernel/netbsd-GENERIC.gz) = 12d571967266dbdce4d9c0b02cda4718 +SHA1 (NetBSD-6.0/alpha/binary/sets/man.tgz) = 899b9d8242e983a5110ab755651c24f709b5af67 +SHA512 (NetBSD-6.0/alpha/binary/sets/man.tgz) = 410999db110d710f4bb498c3d7ae7adc62170c7c2f470ce189c92f6c436c5ea96149659c631ef0b5605caaa025d97dfe1c07c428d86f51239657bd6b71717b15 +RMD160 (NetBSD-6.0/alpha/binary/sets/man.tgz) = c1270f68c6d41b351877f71f0396ac34877dfc8d +MD5 (NetBSD-6.0/alpha/binary/sets/man.tgz) = df4db2bbfa39ef6a4a215d949653d04a +SHA1 (NetBSD-6.0/alpha/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/alpha/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/alpha/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/alpha/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/alpha/binary/sets/kern-GENERIC.MP.tgz) = bef91c02bdb6ebd5e578bae73acbcbc5d9fcb47b +SHA512 (NetBSD-6.0/alpha/binary/sets/kern-GENERIC.MP.tgz) = 0800ef43e76c838a4f91535fbad30adee37a4be94d01220ce3d0ca898204ef4b9140d753853faa29944ef1f0b7feff2a54551633ed10293751d0fb5c2134c858 +RMD160 (NetBSD-6.0/alpha/binary/sets/kern-GENERIC.MP.tgz) = bbc5e568ee1036473614f45ce443ae6129c2afb1 +MD5 (NetBSD-6.0/alpha/binary/sets/kern-GENERIC.MP.tgz) = 255686b1fa7b97a53599c7759fad4843 +SHA1 (NetBSD-6.0/alpha/binary/sets/base.tgz) = d6a62bc7f515a3cf470fe4298045346f79dbdfb8 +SHA512 (NetBSD-6.0/alpha/binary/sets/base.tgz) = b3eee92239be76b17cf36cf49d845123dd26853ec162d2f340338fff172af3ca20d6c85025e9a5fbc085d8522d331ecec488acc034c757f7a44d885b8f31ec41 +RMD160 (NetBSD-6.0/alpha/binary/sets/base.tgz) = 447c0754e06c36c2844563722dfd727938b7fdb5 +MD5 (NetBSD-6.0/alpha/binary/sets/base.tgz) = e898499ce51685436186e3be5227184a +SHA1 (NetBSD-6.0/alpha/binary/sets/comp.tgz) = 3cd2356501ebeb4190de3596453b045f694f69de +SHA512 (NetBSD-6.0/alpha/binary/sets/comp.tgz) = 51a526038f6e9cf7d787b86997abee47e9735a56f02215cd8f3260e50d2d3bd7a17d11b2f80b2010fd52640aab0afe074fa8997c3522ccf1a8463854bab9ee0b +RMD160 (NetBSD-6.0/alpha/binary/sets/comp.tgz) = 5fd982783cb934f260a96a0f85279b07deb2b505 +MD5 (NetBSD-6.0/alpha/binary/sets/comp.tgz) = c5deb3e315f875050362df56411badcf +SHA1 (NetBSD-6.0/alpha/binary/sets/etc.tgz) = b525757e8a68fee704bc4845c411c6e9ab06db01 +SHA512 (NetBSD-6.0/alpha/binary/sets/etc.tgz) = 4c881736688636b7376dc7f255266f606678d7fe57a9a787275dc78bbafb8c0f36948bc6b06ea853bd7d1e2dc3de90693fc518c3ffe57aa831777229d910b8c3 +RMD160 (NetBSD-6.0/alpha/binary/sets/etc.tgz) = bbacdc2a3adc49d3772faa1e60227d3f20357220 +MD5 (NetBSD-6.0/alpha/binary/sets/etc.tgz) = 5975a4d5767d0d68fd4371e32f1ebd40 +SHA1 (NetBSD-6.0/alpha/binary/sets/games.tgz) = f3c81c83cd5dd29ff44eeff54a39bc22e1739b43 +SHA512 (NetBSD-6.0/alpha/binary/sets/games.tgz) = f773dfef7f2449a7ea804e756181ea622428becff7cd86e227f8d9c33a343ea097a191c08b73f258e236695ac37df6af80ffcc930ae75a3f6bc4a542a0797673 +RMD160 (NetBSD-6.0/alpha/binary/sets/games.tgz) = 079affe9e062a8f418e15fc69dae6b19722d8e43 +MD5 (NetBSD-6.0/alpha/binary/sets/games.tgz) = 1bdf16fbef7c6ee4bc1e8f6e99cbe649 +SHA1 (NetBSD-6.0/alpha/binary/sets/kern-GENERIC.tgz) = e6e00d7a0d440b435c65b34ba6e5ea156f123f18 +SHA512 (NetBSD-6.0/alpha/binary/sets/kern-GENERIC.tgz) = b5a99efe112a3d00b4108dc632a2413c0edc72c8a4fdd4daba1c974b5f1233d48e21964e4e1f7588430d01b0813767861bc0a700910a1e288493fccf269255f3 +RMD160 (NetBSD-6.0/alpha/binary/sets/kern-GENERIC.tgz) = ccba42305acbf2080751f1b35c23a8bd2464d1c6 +MD5 (NetBSD-6.0/alpha/binary/sets/kern-GENERIC.tgz) = b05f2ce6966e37b9dd3018930753f14c +SHA1 (NetBSD-6.0/alpha/binary/sets/modules.tgz) = 2ed2d5d8a1054fac920b44123147d1f445a8cd20 +SHA512 (NetBSD-6.0/alpha/binary/sets/modules.tgz) = e85332336dd7091fecb0d48aa772ec0f9890fae90a71bf3e79178cc319a32c7320e7e6357d4355292335809d12499875357583179199f9b0c94dedcce2bffee8 +RMD160 (NetBSD-6.0/alpha/binary/sets/modules.tgz) = 286d34676fdeb368fe4146a636878026b678afad +MD5 (NetBSD-6.0/alpha/binary/sets/modules.tgz) = 31ddea9a696f752f01db0c8910252dbe +SHA1 (NetBSD-6.0/alpha/binary/sets/tests.tgz) = 5a71181696e124159891257ed04551ca0fac96ed +SHA512 (NetBSD-6.0/alpha/binary/sets/tests.tgz) = a62eb137237ed94f16b759f4b836932caf06f4fa4215126db879918e38b993349962b6cd63dc06b2516cccb2604208d12df0b599ae64c4b5bfacd8d51618be0c +RMD160 (NetBSD-6.0/alpha/binary/sets/tests.tgz) = baaa5152926a07e890f3c6ab2e2ba0123e132d62 +MD5 (NetBSD-6.0/alpha/binary/sets/tests.tgz) = a3bfffe6cbdb12c847a397c474996dbd +SHA1 (NetBSD-6.0/alpha/binary/sets/text.tgz) = 4087ff757867de3d1e48c7edcd0a1f63879141a2 +SHA512 (NetBSD-6.0/alpha/binary/sets/text.tgz) = 396175d3caa9afb10f69ca6724fe1544b685863edb272a36e46c6164f8a5ce8099d9ce98c988fc691e61cafa0741053b31f46af6d87873e7473ee2c7db05c5e2 +RMD160 (NetBSD-6.0/alpha/binary/sets/text.tgz) = 84877daedd720eaae66d03670b5391586cb5818d +MD5 (NetBSD-6.0/alpha/binary/sets/text.tgz) = 3ad58e3441e75733d2bd172cc03d96c2 +SHA1 (NetBSD-6.0/alpha/binary/sets/xbase.tgz) = 8cb5878605114e42a100af9f6000da692936b458 +SHA512 (NetBSD-6.0/alpha/binary/sets/xbase.tgz) = 55901d2b29117e70ee9f60bca845a291f73c827b82a6d79d2035e8e861cc6d3553e9b698a2573af458ba7ff7f0d66c1b904e0510aac5391a768a7e85c8dcafa5 +RMD160 (NetBSD-6.0/alpha/binary/sets/xbase.tgz) = 27a6b757c2c136eb48d35e996bebae1154691620 +MD5 (NetBSD-6.0/alpha/binary/sets/xbase.tgz) = 7599e1da98dc669a5915742f46819445 +SHA1 (NetBSD-6.0/alpha/binary/sets/xcomp.tgz) = 0f7cf0e0611671bcc8763c66b6ddb96ba2b84cbc +SHA512 (NetBSD-6.0/alpha/binary/sets/xcomp.tgz) = cabd0398fbb72d9d2c833a56c5ff77e5fcef535dd4ebb7ecf482fc278c6a05d9bdc4d0e443b2eaa9c1ba2ba6044cb066b9c10de8377bf754c3b2fde1925e90e8 +RMD160 (NetBSD-6.0/alpha/binary/sets/xcomp.tgz) = 0e6f7dfd1b78eed02bfedd4e354017d4ca193d3f +MD5 (NetBSD-6.0/alpha/binary/sets/xcomp.tgz) = f830daacbaca8ab9bc135239ee1568ec +SHA1 (NetBSD-6.0/alpha/binary/sets/xetc.tgz) = 392c70eb80215d3165d545e40212a8b5d0e071e1 +SHA512 (NetBSD-6.0/alpha/binary/sets/xetc.tgz) = 54d20a3d9023cb964eac1ea822cab4648ee70d4ddd4e45779077f9ee7bfeb895f06adf2ec5e6f63869c4746d89aaefad17837afe43023631a204b1e536b15447 +RMD160 (NetBSD-6.0/alpha/binary/sets/xetc.tgz) = 6308c2a5326f2e8dc958195e9c98e151c9727b06 +MD5 (NetBSD-6.0/alpha/binary/sets/xetc.tgz) = a591745a497f419dd0d277d43c2e7e1c +SHA1 (NetBSD-6.0/alpha/binary/sets/xfont.tgz) = da7a98e196e0630e68572a298db959c1ad9e5cac +SHA512 (NetBSD-6.0/alpha/binary/sets/xfont.tgz) = 6304ec4f69e76faaaea07f0ee720bc90dbbcb620d8980dedb6966767cd58be9ba2c8c4a7f977f4a4b9293f40dc267f7d1a92ced290e704ea6cab7f512a2e21eb +RMD160 (NetBSD-6.0/alpha/binary/sets/xfont.tgz) = 51c4aeaae821cb352d3249f2894bbd4b90884e5b +MD5 (NetBSD-6.0/alpha/binary/sets/xfont.tgz) = 18fdd4a9bed7c69c840cd8591c17670a +SHA1 (NetBSD-6.0/alpha/binary/sets/xserver.tgz) = 32e0112e7e65de8beda18c41e9ddd18db5d586c9 +SHA512 (NetBSD-6.0/alpha/binary/sets/xserver.tgz) = 82587fb8cd0719eb39bc14f0e8bbf8a943d6ac710a9f4bed1ac8ea16443cf84a4f378a5dd8f077d5f8ce9213da74d6444a9da10b872f074ab45da8abc89135a5 +RMD160 (NetBSD-6.0/alpha/binary/sets/xserver.tgz) = 60936683b7027ff514f411e63c1767828afed830 +MD5 (NetBSD-6.0/alpha/binary/sets/xserver.tgz) = d8b3888a02b4e6f2198d67e731296e4a +SHA1 (NetBSD-6.0/alpha/installation/diskimage/README.files) = 8fef6343776d407c097ffbb0622b509aa3b5d6ed +SHA512 (NetBSD-6.0/alpha/installation/diskimage/README.files) = 0a37602db16239255dd32a5b6585a23780d9c7568e7bcdcd4f67f4cc5869ce772deda68df2428b6a8ae4e7e2e4e449f7b643d1fc5d929efa0409466a50cfaf74 +RMD160 (NetBSD-6.0/alpha/installation/diskimage/README.files) = ff4ac5a982e0c75bcc3a466b27b003da73573026 +MD5 (NetBSD-6.0/alpha/installation/diskimage/README.files) = 47f2c0383d6fc4ac6c8b25c348fa992c +SHA1 (NetBSD-6.0/alpha/installation/diskimage/cdhdtape) = 560f896de7f7b1e2f8cb908048b3ebaeb6636263 +SHA512 (NetBSD-6.0/alpha/installation/diskimage/cdhdtape) = 10d6bd96b74b6df96c35533d14237b771d5f3f449120ea7062aff44960e8c0480048d607139ec2358961d93bba17afef407d0e775513c262e44249224ac54834 +RMD160 (NetBSD-6.0/alpha/installation/diskimage/cdhdtape) = 69eadfe52a7b4b3fe412190b7d2fd5fb83f7fe6a +MD5 (NetBSD-6.0/alpha/installation/diskimage/cdhdtape) = 87f184344a501c90af4f7bcff11622ee +SHA1 (NetBSD-6.0/alpha/installation/floppy/README.files) = 8fef6343776d407c097ffbb0622b509aa3b5d6ed +SHA512 (NetBSD-6.0/alpha/installation/floppy/README.files) = 0a37602db16239255dd32a5b6585a23780d9c7568e7bcdcd4f67f4cc5869ce772deda68df2428b6a8ae4e7e2e4e449f7b643d1fc5d929efa0409466a50cfaf74 +RMD160 (NetBSD-6.0/alpha/installation/floppy/README.files) = ff4ac5a982e0c75bcc3a466b27b003da73573026 +MD5 (NetBSD-6.0/alpha/installation/floppy/README.files) = 47f2c0383d6fc4ac6c8b25c348fa992c +SHA1 (NetBSD-6.0/alpha/installation/floppy/disk1of3) = 4d855acf87e1e1064b06c2232178d75a13c33fd3 +SHA512 (NetBSD-6.0/alpha/installation/floppy/disk1of3) = 9e86017634026e3e90a50c84a8f57badb1b7cf223aca9a643fae2bf186e443dc9eb5380cba764c89d64b7288078ca5b086b5a37b97fc47a4cc0ecfaad755af67 +RMD160 (NetBSD-6.0/alpha/installation/floppy/disk1of3) = 74abd218ad7f0299822e154ac2b420b258c83aad +MD5 (NetBSD-6.0/alpha/installation/floppy/disk1of3) = 5a2d6e79a6714cf358c9ee8755e0aedf +SHA1 (NetBSD-6.0/alpha/installation/floppy/disk2of3) = 4c8d4ef59efd9aeaceaef12aba4acb5c80ac3be2 +SHA512 (NetBSD-6.0/alpha/installation/floppy/disk2of3) = 72fcf5173d3b29eca98afcc9dd1c0ca172cf8509c9f449356086fcef28acff3641140745df32db394b43281a1421000959631cf55185673e430a792d026e4eb3 +RMD160 (NetBSD-6.0/alpha/installation/floppy/disk2of3) = 02ff0fdc28cb7ac47eae6869620ec5f801324654 +MD5 (NetBSD-6.0/alpha/installation/floppy/disk2of3) = 4f86d12bbbb50c2c06103f2002c88be9 +SHA1 (NetBSD-6.0/alpha/installation/floppy/disk3of3) = 4f0a721ea8eb063d964c3ec31e035f41febad205 +SHA512 (NetBSD-6.0/alpha/installation/floppy/disk3of3) = f3c66c64760246cde2e99999deac1a4dba5caa47603491de0edd47badafc5f6a08b7108e62a3e2c44d4cca55f17df48e1bc41fee948bca15d7dc0874ed321b18 +RMD160 (NetBSD-6.0/alpha/installation/floppy/disk3of3) = 1ca8581e23cc086d8bf93b39bf1efb34c8964d32 +MD5 (NetBSD-6.0/alpha/installation/floppy/disk3of3) = e558bf919697872fc6f5bfb8ef697f8f +SHA1 (NetBSD-6.0/alpha/installation/instkernel/netbsd.symbols.gz) = 72358f5496a38794927cca6f55addc09e74983bd +SHA512 (NetBSD-6.0/alpha/installation/instkernel/netbsd.symbols.gz) = f4fde67472e0cea2069a5d8c1a614429486c275a3ff38fd2f9c216a79749b366c79c898e9e4d58b4a2826c8b724d76b6de6b744d4eba058169ffb88b428b7790 +RMD160 (NetBSD-6.0/alpha/installation/instkernel/netbsd.symbols.gz) = 0b8b2fda5075cf789139581258d33e55e7edc18b +MD5 (NetBSD-6.0/alpha/installation/instkernel/netbsd.symbols.gz) = 2f1474645c7c61a79af6046b873d0c53 +SHA1 (NetBSD-6.0/alpha/installation/instkernel/README.files) = 8fef6343776d407c097ffbb0622b509aa3b5d6ed +SHA512 (NetBSD-6.0/alpha/installation/instkernel/README.files) = 0a37602db16239255dd32a5b6585a23780d9c7568e7bcdcd4f67f4cc5869ce772deda68df2428b6a8ae4e7e2e4e449f7b643d1fc5d929efa0409466a50cfaf74 +RMD160 (NetBSD-6.0/alpha/installation/instkernel/README.files) = ff4ac5a982e0c75bcc3a466b27b003da73573026 +MD5 (NetBSD-6.0/alpha/installation/instkernel/README.files) = 47f2c0383d6fc4ac6c8b25c348fa992c +SHA1 (NetBSD-6.0/alpha/installation/instkernel/netbsd.gz) = 3057e0db687c65ad00bcc9433a8e1e8e8853b0f8 +SHA512 (NetBSD-6.0/alpha/installation/instkernel/netbsd.gz) = 72c72707e34bf282fec601e885eaa9dbfafc34dc44c97d1e100e439620ed5f3751e2b629b2b1ff40b229a29b1b217627f5fb70a198d571c0478d13d2c1f9d5e2 +RMD160 (NetBSD-6.0/alpha/installation/instkernel/netbsd.gz) = bb22d8b6c7113aad71720a489ab71dbe938e1475 +MD5 (NetBSD-6.0/alpha/installation/instkernel/netbsd.gz) = 9fece65592c8b7decdbff32513650306 +SHA1 (NetBSD-6.0/alpha/installation/netboot/netboot) = 17cf3e7f848aa8a853e322e977163547830f7357 +SHA512 (NetBSD-6.0/alpha/installation/netboot/netboot) = eb78138cdb1d289e4f39af61e24a2d0a42b5807c6869e921ffbcaf720902362f0c702ece18e1bbbb599d50b31b09ecebcaf9df5786f337ee511c0900e1bcb9cf +RMD160 (NetBSD-6.0/alpha/installation/netboot/netboot) = 3228d2be31a224636f15cfa0f5c24cebea1d4b64 +MD5 (NetBSD-6.0/alpha/installation/netboot/netboot) = 2a71b40ce0eebc66564f796f681592b2 +SHA1 (NetBSD-6.0/alpha/INSTALL.html) = 6984fd17504c01e2c1dd83e7dbdf34bdcc7b6b1e +SHA512 (NetBSD-6.0/alpha/INSTALL.html) = d4b63b33e62764fa6e008f5961599abf0ceb486aee59c55deb0e2f62f5e3efb0a7ec667217f72f553460d1931fff86c209345c6eccb688f67822e19f78f2b35b +RMD160 (NetBSD-6.0/alpha/INSTALL.html) = 3d6597686d7079ca4857f5afe7fada4ddae2e4db +MD5 (NetBSD-6.0/alpha/INSTALL.html) = c00f5ce1cc724dddfbe201deb54605d3 +SHA1 (NetBSD-6.0/alpha/INSTALL.more) = b670f381aeda31fa7a1c861aa90c8856a144460c +SHA512 (NetBSD-6.0/alpha/INSTALL.more) = e8343ca62e59534c74a2cb3404092b71a771390943c5738c10cec908be2b202b4caafa09629b5086c0119f8c867a294fb759a76dc80705583f3db7115ad41b1c +RMD160 (NetBSD-6.0/alpha/INSTALL.more) = 6236acfbb416a7f45499c9ba097b0ebc7df0ddc0 +MD5 (NetBSD-6.0/alpha/INSTALL.more) = c0f41cb950b8c2133e1c3d6005ed478b +SHA1 (NetBSD-6.0/alpha/INSTALL.ps) = 902a55dd7d1b3cc6489f730e76fd8a656188ca3c +SHA512 (NetBSD-6.0/alpha/INSTALL.ps) = 612f6a50dd02a6ef525948faaa4f77c6b60e6ea6b73fbf43fe28891523b0ba715c4c513991bbd99b36a1842c5bea3a4f59c31abcb7141af3ca77419d5ac7a399 +RMD160 (NetBSD-6.0/alpha/INSTALL.ps) = 95af61540f44c6ad5bde6110bb988b30144cac0e +MD5 (NetBSD-6.0/alpha/INSTALL.ps) = d5cb827162bea74a99a75c4ec658cb13 +SHA1 (NetBSD-6.0/alpha/INSTALL.txt) = 00428f4fee211a107142bd3c673ac0e1bf82f8bb +SHA512 (NetBSD-6.0/alpha/INSTALL.txt) = acc36a8ca1e2e171db9a482d5b5914cde68c2ba917478c91cbe4c6b1f14f0e46b6fc5393a6597b928b2fe043afe9373e92bc50eddaccad205b1513c9cfa5b89b +RMD160 (NetBSD-6.0/alpha/INSTALL.txt) = c340c3eafed3235732e7bd6de8bd2e5798279a32 +MD5 (NetBSD-6.0/alpha/INSTALL.txt) = bebe671881b51664213b2b74a352ccea +SHA1 (NetBSD-6.0/amd64/binary/kernel/netbsd-GENERIC.symbols.gz) = cb8fb452336026da954a431064ac908983c73c56 +SHA512 (NetBSD-6.0/amd64/binary/kernel/netbsd-GENERIC.symbols.gz) = 5ac462c2bbe07c1fc5bb719af9b8a048278c914e25c3e63a5908d04eed9b9ed3b3324af677f5910065c569e7eef9ab92fb7b23dc27a06361065193736170beb9 +RMD160 (NetBSD-6.0/amd64/binary/kernel/netbsd-GENERIC.symbols.gz) = f294d6c837951cc2179aabe993db92be0507b73b +MD5 (NetBSD-6.0/amd64/binary/kernel/netbsd-GENERIC.symbols.gz) = d5c7cba8ce43359a50bc6b41e1a59ac8 +SHA1 (NetBSD-6.0/amd64/binary/kernel/netbsd-GENERIC.gz) = 0e1a51e79c8ed82328856cb4e9e1ca1f77f96ad6 +SHA512 (NetBSD-6.0/amd64/binary/kernel/netbsd-GENERIC.gz) = 71822434adf5610fc6bf77371f0ea65403cbfac39194435c6fd0dcd62cfd214da5d9bd8c9a06ae300b81425339ecdca1e373e91d38870a56f1910e9e4b2f0dcb +RMD160 (NetBSD-6.0/amd64/binary/kernel/netbsd-GENERIC.gz) = 2344b490341441b4a08608454269d1bb55db13fa +MD5 (NetBSD-6.0/amd64/binary/kernel/netbsd-GENERIC.gz) = fdba9cfe2198dbc3403ba5c9b251147e +SHA1 (NetBSD-6.0/amd64/binary/kernel/netbsd-INSTALL.symbols.gz) = b275c23887a6d7522777f6c70da7191ae2d3b64d +SHA512 (NetBSD-6.0/amd64/binary/kernel/netbsd-INSTALL.symbols.gz) = 30f57b1aa47d0c8dfae72063810dffda248ad25e03e432221861c4de98088eba502637675cf4d400809c6d2d45a17ee2b3ce87be4007fa8a2b86fb507d13426b +RMD160 (NetBSD-6.0/amd64/binary/kernel/netbsd-INSTALL.symbols.gz) = c98d06602cce33614079d4ac9049235aa71601f5 +MD5 (NetBSD-6.0/amd64/binary/kernel/netbsd-INSTALL.symbols.gz) = 5d2e2deeac92159eefa0c14bedb999e5 +SHA1 (NetBSD-6.0/amd64/binary/kernel/netbsd-INSTALL.gz) = 22859d8f0aa148474db11e8493c1c1c5ca88a4bf +SHA512 (NetBSD-6.0/amd64/binary/kernel/netbsd-INSTALL.gz) = 5aad6a3e174330803b12b3c5566f422c96d6755e520b2bda951e7efd73f8f4bfbc0b902d7964688650717630355af96d51fed90fac5bbfe343f3c06d3354f5e6 +RMD160 (NetBSD-6.0/amd64/binary/kernel/netbsd-INSTALL.gz) = 25124d4395c714580bcc3a2f8574df3d9a5e5ef4 +MD5 (NetBSD-6.0/amd64/binary/kernel/netbsd-INSTALL.gz) = 09691319c1029293d76f2b51048cd7d8 +SHA1 (NetBSD-6.0/amd64/binary/kernel/netbsd-INSTALL_XEN3_DOMU.gz) = 1ef0dce70ce636d55eb7cb5973f335729d17826a +SHA512 (NetBSD-6.0/amd64/binary/kernel/netbsd-INSTALL_XEN3_DOMU.gz) = 49a644ba39cd11ad2fd3c1aa27b7f2999019613bbb4731ee2098b484eee74d740baf4f67ddb7b4cdaf7f710e507ed719bc6840d704acf5ed80ce419fb8bfae1b +RMD160 (NetBSD-6.0/amd64/binary/kernel/netbsd-INSTALL_XEN3_DOMU.gz) = 459fb44892f496a9c7b445e837d875ddc1a7f056 +MD5 (NetBSD-6.0/amd64/binary/kernel/netbsd-INSTALL_XEN3_DOMU.gz) = 5902c6bc85313724e355e95a06e968a0 +SHA1 (NetBSD-6.0/amd64/binary/kernel/netbsd-XEN3_DOM0.gz) = 0f4ec7742c4c53d99cbc4b645931758d0a7ebe2a +SHA512 (NetBSD-6.0/amd64/binary/kernel/netbsd-XEN3_DOM0.gz) = fa1e39362e515e808831bc81751231062ebe4987eb1790eb87cab7490697372472fac67df5d49fd41b1d6d3fbecc93f64d7c433d357c13a626636feda14f4a7e +RMD160 (NetBSD-6.0/amd64/binary/kernel/netbsd-XEN3_DOM0.gz) = 2322a8960ba58563ea8507a0073c03934d8f58ad +MD5 (NetBSD-6.0/amd64/binary/kernel/netbsd-XEN3_DOM0.gz) = 31ea20a739a3e9caad0f4af0da531a0d +SHA1 (NetBSD-6.0/amd64/binary/kernel/netbsd-XEN3_DOMU.gz) = 30bfc0edb5ec053c327cfab318877bcf633e3d26 +SHA512 (NetBSD-6.0/amd64/binary/kernel/netbsd-XEN3_DOMU.gz) = 7244306522782443df4e807ebf627eab0f6f994c3c1de9cde73781b7b8d16a2b3e7d1ab578c03bd3b2d6df19dc20485146ecb9ff920e2860a0858158509a4229 +RMD160 (NetBSD-6.0/amd64/binary/kernel/netbsd-XEN3_DOMU.gz) = bbae752f9fc5b0a9725e12aef5da652699ba614b +MD5 (NetBSD-6.0/amd64/binary/kernel/netbsd-XEN3_DOMU.gz) = 72cc8998d1dd79b0471e4924a1ee9cbf +SHA1 (NetBSD-6.0/amd64/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/amd64/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/amd64/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/amd64/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/amd64/binary/sets/kern-GENERIC.tgz) = 8880ef6795951dbca5379bffb7040b31e75e8217 +SHA512 (NetBSD-6.0/amd64/binary/sets/kern-GENERIC.tgz) = e1a58551a91511f0fa86ab4395a8901154e75bae344045200c1794d759cbd82c2441703123ee0c5d42561f08cb192e2bb39c57f4cb61b8fb970b579525fb1952 +RMD160 (NetBSD-6.0/amd64/binary/sets/kern-GENERIC.tgz) = be4c1cef72f8b3971890c549d908d03cf9ccae74 +MD5 (NetBSD-6.0/amd64/binary/sets/kern-GENERIC.tgz) = 60e67b64337a09d0d00bbe70c0ef43f6 +SHA1 (NetBSD-6.0/amd64/binary/sets/base.tgz) = 41f139d30b18839b0486e238bdcb1a08e084ac0f +SHA512 (NetBSD-6.0/amd64/binary/sets/base.tgz) = 136fec9ccc141fbf39c4667f09f45ed3a7f07183c315819c391e3c47b67574d4278762e9be6ac7e325e7ebd2929dd59d1d8aa84411fb435baccf5b7d71c1e58b +RMD160 (NetBSD-6.0/amd64/binary/sets/base.tgz) = 38903209c490bb8094061951fffc5ba7bf2cce24 +MD5 (NetBSD-6.0/amd64/binary/sets/base.tgz) = c4d69c1e245e95ee1ef891a998536f30 +SHA1 (NetBSD-6.0/amd64/binary/sets/comp.tgz) = 5d0d34f4debbf611578852fdc549197357f574c2 +SHA512 (NetBSD-6.0/amd64/binary/sets/comp.tgz) = 96cd27a092b2cbabc0f6f053d651ae94b6ec65b2c9f4812c6efd432c9ea9a321d38f8e88e6dba03ca7e6d3fe8dc2b43c3846880966964d6841d6cacb87f5c4a0 +RMD160 (NetBSD-6.0/amd64/binary/sets/comp.tgz) = 0fc9f9cef2839291204f399014f730a321ff846a +MD5 (NetBSD-6.0/amd64/binary/sets/comp.tgz) = 1f6de4df6174d0e919b343bb0426ba92 +SHA1 (NetBSD-6.0/amd64/binary/sets/etc.tgz) = 23e42cd803c314f35f61713d7ce3d8ae6f978036 +SHA512 (NetBSD-6.0/amd64/binary/sets/etc.tgz) = 3aa2017bfd9d81b51371b31ae2eb4fa613c3cc90c532aabf1e76df938c312d1894f1b5313869a93fbd4463b903bb390ea5cf485e870d421ff0580240a04505e3 +RMD160 (NetBSD-6.0/amd64/binary/sets/etc.tgz) = d8d98a46df49ec9a28cda63da60c2fd8b2f5440c +MD5 (NetBSD-6.0/amd64/binary/sets/etc.tgz) = d4d5351a9ee4c89d46d03025363d0af7 +SHA1 (NetBSD-6.0/amd64/binary/sets/games.tgz) = 535c8d580229e63485dbc9215ff8994babd19ba4 +SHA512 (NetBSD-6.0/amd64/binary/sets/games.tgz) = abc07cbb728d3b4148ca824f3d37c0fd789f22548f92c8d03c78cd04969828d6fb3e7396654e4709bfdc82783e5c17e3998372149b76a7bdfb186fd417a4e1cd +RMD160 (NetBSD-6.0/amd64/binary/sets/games.tgz) = 80ca9419dae0b955ae39ba879b269eb27d34b0f9 +MD5 (NetBSD-6.0/amd64/binary/sets/games.tgz) = 1f7b98cfd037ac9a6b2487b1d3e2397a +SHA1 (NetBSD-6.0/amd64/binary/sets/kern-XEN3_DOM0.tgz) = 622ca31060c3d803bff339d53321e3b5cbe56fcf +SHA512 (NetBSD-6.0/amd64/binary/sets/kern-XEN3_DOM0.tgz) = 9943d8752f75569a2cb6611f2eb87a552cf98c92040cf2c0ec699ff0380b3b5395a7b2c951fcdbc6ef74d36073b7b066dc37ee1d60a3463836820fee7f15e5fe +RMD160 (NetBSD-6.0/amd64/binary/sets/kern-XEN3_DOM0.tgz) = 4627daedf28168da5994ad430aaac7b069785d42 +MD5 (NetBSD-6.0/amd64/binary/sets/kern-XEN3_DOM0.tgz) = 3c473eed7a2c400bc22e743e6f2fad74 +SHA1 (NetBSD-6.0/amd64/binary/sets/kern-XEN3_DOMU.tgz) = d29bb910d1ecf61700d54790c7376f2729dd6a71 +SHA512 (NetBSD-6.0/amd64/binary/sets/kern-XEN3_DOMU.tgz) = e714d759a0635e3375ce56f945fa5df011b5037502ce0602d74db1a9d3ddf86144b13b9a2a503c231c931de998a645b8562b5254bc8e68c9537a7dea366957da +RMD160 (NetBSD-6.0/amd64/binary/sets/kern-XEN3_DOMU.tgz) = adb7515022b355b9b2f61a318d1fea6734e8859a +MD5 (NetBSD-6.0/amd64/binary/sets/kern-XEN3_DOMU.tgz) = 3beec0bff32cc7c78bcadb6f90b0455f +SHA1 (NetBSD-6.0/amd64/binary/sets/man.tgz) = f583717a7705475c144e1b66e93b3c9c6d8e3293 +SHA512 (NetBSD-6.0/amd64/binary/sets/man.tgz) = 92f6dbefacff42d2a6c317158aee801e8d4f3791704a792ce0761faf5425c516166a9769e7f3b81abd282cc9a60e0ff07c4350ac889fe66aec794f359a27452b +RMD160 (NetBSD-6.0/amd64/binary/sets/man.tgz) = 02ffd712d7b6d265e8c566ccbfcaa34cc9916eda +MD5 (NetBSD-6.0/amd64/binary/sets/man.tgz) = 59adc1ce49347d61ee6eea024e2ea2a2 +SHA1 (NetBSD-6.0/amd64/binary/sets/modules.tgz) = 46a78ea373e41e73dabc27ae802b395b7348c419 +SHA512 (NetBSD-6.0/amd64/binary/sets/modules.tgz) = 8dc00ff46c87d04b72f2e4fa0b2b290ab326b907f88f4d2667e63aa0390756df4c45ed5b9e36bec6e60e472a8162b9ddc55eea89b6ed65bd2f6cf5d760f611b9 +RMD160 (NetBSD-6.0/amd64/binary/sets/modules.tgz) = b2d93414e9e22b4b55dd73fb347aefe4b6a11d10 +MD5 (NetBSD-6.0/amd64/binary/sets/modules.tgz) = aa84f46e76b3f543ac9d8ea315869092 +SHA1 (NetBSD-6.0/amd64/binary/sets/tests.tgz) = cdcfc53423e8cd984258bc8635490bd815576322 +SHA512 (NetBSD-6.0/amd64/binary/sets/tests.tgz) = d11520f52dd889947a298a2428e4b81b840ef939ee82a63fb39ac30fa59918348a6546598b9b6f28268677f7bebf9e022f8ba568a47e3f9ff801ff08666c1366 +RMD160 (NetBSD-6.0/amd64/binary/sets/tests.tgz) = 7fb2dbecae8a377eca305f74075e9f4c4f326455 +MD5 (NetBSD-6.0/amd64/binary/sets/tests.tgz) = 4c8e0463db9e784b47d92aa43bd7ec82 +SHA1 (NetBSD-6.0/amd64/binary/sets/text.tgz) = 2ad7dfb1cf3e39da165e6d0d356444a3dda315ab +SHA512 (NetBSD-6.0/amd64/binary/sets/text.tgz) = 77140ca96473762ba22737bdf1dcd74fbe7dea97778c2da7b8b015daa2af47c20a9663e5eee092a8b353cb36caf599efc5975b7572692cb5c8b77bcde7bb8fff +RMD160 (NetBSD-6.0/amd64/binary/sets/text.tgz) = bdb4eb7e3081ec2bbd4b1eaaacd0cd96dfe92be1 +MD5 (NetBSD-6.0/amd64/binary/sets/text.tgz) = 3c9ac230578345961050fd8adbb15023 +SHA1 (NetBSD-6.0/amd64/binary/sets/xbase.tgz) = c88f6ae63e7acba75831ae5a19cfb8151f961780 +SHA512 (NetBSD-6.0/amd64/binary/sets/xbase.tgz) = be81153fc620a58e00ab7e1069dfa80567e9d641fc4ab6256512074d5cebb7a561fa8596de8f985022ef79ec0330ee317f2a2628a7236882f28a1ea9475d809f +RMD160 (NetBSD-6.0/amd64/binary/sets/xbase.tgz) = 9e961b920bdc6432e1e0bfcad9adfb8dfc872cfb +MD5 (NetBSD-6.0/amd64/binary/sets/xbase.tgz) = b98819c3afd401940a578ced15418ab6 +SHA1 (NetBSD-6.0/amd64/binary/sets/xcomp.tgz) = 7f6d2efa3a5e3a5ea2729020a8ad175929353995 +SHA512 (NetBSD-6.0/amd64/binary/sets/xcomp.tgz) = 35652d685c9581d20f198d13de8b34764c9a67e808416f006b98793f6ded279111d2bbeee6ad453a8416ba3259a5d7967d0327aa7e7109b7651d923bde31a8bd +RMD160 (NetBSD-6.0/amd64/binary/sets/xcomp.tgz) = 0b3a659fdca9ed423aec4e799f739ad6ed3a2b7b +MD5 (NetBSD-6.0/amd64/binary/sets/xcomp.tgz) = 72711d2c486caca7a8db94316c7704ad +SHA1 (NetBSD-6.0/amd64/binary/sets/xetc.tgz) = d2a37199497c292f9a780bb5a77a14dd481bc0db +SHA512 (NetBSD-6.0/amd64/binary/sets/xetc.tgz) = e8fe86ecaa56d0a016ad52024d956d8e77d690b4ccbb24b060d1c824f5e67979b2067ea6635361f25e80160e6abe3d4bce7ac586107fb673c12d65e9d9bbc4bf +RMD160 (NetBSD-6.0/amd64/binary/sets/xetc.tgz) = e566d0c03e66e9365ad71c0057dd86bcc8663f96 +MD5 (NetBSD-6.0/amd64/binary/sets/xetc.tgz) = 6a1af564a85ba3996757440dfed4df94 +SHA1 (NetBSD-6.0/amd64/binary/sets/xfont.tgz) = 425d64efdeed5bf9f8038b9f0d61cdfd0b8679ba +SHA512 (NetBSD-6.0/amd64/binary/sets/xfont.tgz) = c6e1b0829edb2e78302cf352880d4ee3cb6f6a5187f8082b0a0df3d49bd32f57cb0df450b850044cc0437da2f0ad75249cbf0777295d90ab38a9e1e13c786e08 +RMD160 (NetBSD-6.0/amd64/binary/sets/xfont.tgz) = d0f3520bdaad4cdbd90b3fe32e663c543153c0d0 +MD5 (NetBSD-6.0/amd64/binary/sets/xfont.tgz) = be05eeb3078d0fbb93b97130d49c5982 +SHA1 (NetBSD-6.0/amd64/binary/sets/xserver.tgz) = bc339a86b1e7d42e667a03561dd66835b0e39828 +SHA512 (NetBSD-6.0/amd64/binary/sets/xserver.tgz) = 00739626f1c78297988d1696e369b7ec933119ee7f76d57c426f83a1efba9414b7a1258258ab86b6b79a1277a327ac3ab0e2177bcaa396332ecc5221c6bf8954 +RMD160 (NetBSD-6.0/amd64/binary/sets/xserver.tgz) = 9adf580fd382fa5edc147da77b23410830e6ef9b +MD5 (NetBSD-6.0/amd64/binary/sets/xserver.tgz) = b30af2c69ca833f25c0b163fea4496d8 +SHA1 (NetBSD-6.0/amd64/installation/cdrom/boot-com.iso) = 0aeb15a62bfd640903525b517b5cb254fbb8f694 +SHA512 (NetBSD-6.0/amd64/installation/cdrom/boot-com.iso) = c3998bedff5f4320e3b14b3bc07f7e348f45a106a1f78d738934fbce564b209eb9bce72f91bfbd4f95247a2eb4fb69366d3a8a4f7a597be3bfae889858f1badc +RMD160 (NetBSD-6.0/amd64/installation/cdrom/boot-com.iso) = 90e7d9c68c959a8c3455fca88ac7fdc5af40589d +MD5 (NetBSD-6.0/amd64/installation/cdrom/boot-com.iso) = 5551d8cd6c5675eda32c80de279860ee +SHA1 (NetBSD-6.0/amd64/installation/cdrom/boot.iso) = 12323858ce09cfce6d3b294bb6d33a3ecd599400 +SHA512 (NetBSD-6.0/amd64/installation/cdrom/boot.iso) = 536021f6159e5412a9b7be41967e75cdaafb3fcb319ce7c712af6bac22cee2b07f185500fb77505f5a4018a0fa5e619a5e00dc11aee59babfc1dd3c69081a0c0 +RMD160 (NetBSD-6.0/amd64/installation/cdrom/boot.iso) = a66e6ff744cb27ed79f58824945806b4ddc5e743 +MD5 (NetBSD-6.0/amd64/installation/cdrom/boot.iso) = b4ae730ff5fcc86885c266665183dd35 +SHA1 (NetBSD-6.0/amd64/installation/floppy/boot-com1.fs) = 7773242845d56dae16e957ba3dcde54db2d44ad9 +SHA512 (NetBSD-6.0/amd64/installation/floppy/boot-com1.fs) = 14a0d9a1d7b6d893ee962b6c0e73cd2f44cdef9aa0c8d814465eb9e30bbee00fffd332a962d86430a04e13fb8b111fc857b5790648d27bbbe6eaac3fb0f6a0c5 +RMD160 (NetBSD-6.0/amd64/installation/floppy/boot-com1.fs) = 911fbf259c7ede76a08956e0e38ea8dba1522ae6 +MD5 (NetBSD-6.0/amd64/installation/floppy/boot-com1.fs) = 18052eb95118b57ee28cff9cd78a0fab +SHA1 (NetBSD-6.0/amd64/installation/floppy/boot-com2.fs) = 5a1705082aa0fdbe9df2deeb8bfcde27f62e39c9 +SHA512 (NetBSD-6.0/amd64/installation/floppy/boot-com2.fs) = 57a01c68902c568a9e061d588b3f96857de3ebe05eab55fffc38a843bb1e25d3c1962aeb78d711a5c70ee2cc7abd5717abc4b4224794803019cd1e81c9afa547 +RMD160 (NetBSD-6.0/amd64/installation/floppy/boot-com2.fs) = 03c5214a031d1cee57c50888bad984f59a0ec275 +MD5 (NetBSD-6.0/amd64/installation/floppy/boot-com2.fs) = 9d14a976045f475ae3a96cb7ed04bae6 +SHA1 (NetBSD-6.0/amd64/installation/floppy/boot-com3.fs) = 80a4a45120aad34e9cc46b8f2fbba73977e395da +SHA512 (NetBSD-6.0/amd64/installation/floppy/boot-com3.fs) = db431a6d199f53a3f367e759ed4fcb117a7b664dd9d5060677a7b3ef60853d3c6d31f5c4e6c54b33df6e4223a8aa7e27c3cb56f777205b58b7239980da5f58d5 +RMD160 (NetBSD-6.0/amd64/installation/floppy/boot-com3.fs) = fd6ca1f2110722e28189179a1e6ae1724c1b0c3d +MD5 (NetBSD-6.0/amd64/installation/floppy/boot-com3.fs) = cf7c49437a2e74cef7d07e5ecefe26f9 +SHA1 (NetBSD-6.0/amd64/installation/floppy/boot-com4.fs) = 611b759a6b95830057cea83517f8065fa131d328 +SHA512 (NetBSD-6.0/amd64/installation/floppy/boot-com4.fs) = 8d0229d04d365efe365a1dc84a5d05090290d684fda96cb637fd8989e162a6cd90c9a9409a80740356cdbe39cb81dcf498874db475b4c2aa443ec3087675611c +RMD160 (NetBSD-6.0/amd64/installation/floppy/boot-com4.fs) = f7fda0f8502ab8255fc63de3de54c92d05ce6a17 +MD5 (NetBSD-6.0/amd64/installation/floppy/boot-com4.fs) = 4e1c8e49e8592e5e7a13e4118df3a13c +SHA1 (NetBSD-6.0/amd64/installation/floppy/boot-com5.fs) = 671ad9865cf186c69739279463e408504e89c072 +SHA512 (NetBSD-6.0/amd64/installation/floppy/boot-com5.fs) = 1a4329afefd19b3dbf37a12cb287aa771dfabdeeaf6b0302158eae0cde68d970a94a9643b4b18798654473c6eb577c8e555188a7c7776e6cccc05241a7b47c7f +RMD160 (NetBSD-6.0/amd64/installation/floppy/boot-com5.fs) = 9e7000ef7b4a971936e74eb1858b0f74816d42f3 +MD5 (NetBSD-6.0/amd64/installation/floppy/boot-com5.fs) = 52824ec1c65bc87f196fe4fcd1887cb2 +SHA1 (NetBSD-6.0/amd64/installation/floppy/boot1.fs) = 8393070ff7b79fb60d3aa6bf9675c5bce42b7340 +SHA512 (NetBSD-6.0/amd64/installation/floppy/boot1.fs) = 092f3177383ff4bb4f51fdca19069306f75bb0b86674e2862c34374bdc2da633008805c0cdd2bd352f0da12a2cd529e19086323f0c74d1fed89b2a0d65066bba +RMD160 (NetBSD-6.0/amd64/installation/floppy/boot1.fs) = 9b24c6e8042942c96ad46c65443e48824c2b1fa8 +MD5 (NetBSD-6.0/amd64/installation/floppy/boot1.fs) = ad5246fc6d7ce6840762ce87d281e0fc +SHA1 (NetBSD-6.0/amd64/installation/floppy/boot2.fs) = 5a1705082aa0fdbe9df2deeb8bfcde27f62e39c9 +SHA512 (NetBSD-6.0/amd64/installation/floppy/boot2.fs) = 57a01c68902c568a9e061d588b3f96857de3ebe05eab55fffc38a843bb1e25d3c1962aeb78d711a5c70ee2cc7abd5717abc4b4224794803019cd1e81c9afa547 +RMD160 (NetBSD-6.0/amd64/installation/floppy/boot2.fs) = 03c5214a031d1cee57c50888bad984f59a0ec275 +MD5 (NetBSD-6.0/amd64/installation/floppy/boot2.fs) = 9d14a976045f475ae3a96cb7ed04bae6 +SHA1 (NetBSD-6.0/amd64/installation/floppy/boot3.fs) = 80a4a45120aad34e9cc46b8f2fbba73977e395da +SHA512 (NetBSD-6.0/amd64/installation/floppy/boot3.fs) = db431a6d199f53a3f367e759ed4fcb117a7b664dd9d5060677a7b3ef60853d3c6d31f5c4e6c54b33df6e4223a8aa7e27c3cb56f777205b58b7239980da5f58d5 +RMD160 (NetBSD-6.0/amd64/installation/floppy/boot3.fs) = fd6ca1f2110722e28189179a1e6ae1724c1b0c3d +MD5 (NetBSD-6.0/amd64/installation/floppy/boot3.fs) = cf7c49437a2e74cef7d07e5ecefe26f9 +SHA1 (NetBSD-6.0/amd64/installation/floppy/boot4.fs) = 611b759a6b95830057cea83517f8065fa131d328 +SHA512 (NetBSD-6.0/amd64/installation/floppy/boot4.fs) = 8d0229d04d365efe365a1dc84a5d05090290d684fda96cb637fd8989e162a6cd90c9a9409a80740356cdbe39cb81dcf498874db475b4c2aa443ec3087675611c +RMD160 (NetBSD-6.0/amd64/installation/floppy/boot4.fs) = f7fda0f8502ab8255fc63de3de54c92d05ce6a17 +MD5 (NetBSD-6.0/amd64/installation/floppy/boot4.fs) = 4e1c8e49e8592e5e7a13e4118df3a13c +SHA1 (NetBSD-6.0/amd64/installation/floppy/boot5.fs) = 671ad9865cf186c69739279463e408504e89c072 +SHA512 (NetBSD-6.0/amd64/installation/floppy/boot5.fs) = 1a4329afefd19b3dbf37a12cb287aa771dfabdeeaf6b0302158eae0cde68d970a94a9643b4b18798654473c6eb577c8e555188a7c7776e6cccc05241a7b47c7f +RMD160 (NetBSD-6.0/amd64/installation/floppy/boot5.fs) = 9e7000ef7b4a971936e74eb1858b0f74816d42f3 +MD5 (NetBSD-6.0/amd64/installation/floppy/boot5.fs) = 52824ec1c65bc87f196fe4fcd1887cb2 +SHA1 (NetBSD-6.0/amd64/installation/miniroot/miniroot.kmod) = dabc250e1cead594f5dea847da52d9ba2933b310 +SHA512 (NetBSD-6.0/amd64/installation/miniroot/miniroot.kmod) = a4dd87defdb602de2329e7397c503b075c1c373af8a0547e843040029aaf34595e117f11f9e184a69765386ed66283f3a9c994d2159e473792b4f49d45991cdb +RMD160 (NetBSD-6.0/amd64/installation/miniroot/miniroot.kmod) = 92d16ace79c31254694e0b401abb19e659f7879f +MD5 (NetBSD-6.0/amd64/installation/miniroot/miniroot.kmod) = df6ec580ac9753bd17f1e9aaada0be34 +SHA1 (NetBSD-6.0/amd64/installation/misc/pxeboot_ia32.bin) = 96287819b198b35ceaf13400e6852a472b0e86e1 +SHA512 (NetBSD-6.0/amd64/installation/misc/pxeboot_ia32.bin) = cad69e2c71ec9879adbcec03468172aa1c2b7dd2ae4d4b5315a7013a39a24667faa8610ab663d96d5d8229e74f8150a0afda03d3e308a54e67fb555bffba821e +RMD160 (NetBSD-6.0/amd64/installation/misc/pxeboot_ia32.bin) = e226d78864e488c284063c1eeca1431babd8934e +MD5 (NetBSD-6.0/amd64/installation/misc/pxeboot_ia32.bin) = a6cf18820ed6a4d823ae117148272279 +SHA1 (NetBSD-6.0/amd64/INSTALL.html) = 2ba66a1c4d70a9376ae64ba56e97acf97cb14064 +SHA512 (NetBSD-6.0/amd64/INSTALL.html) = 6fbece25fed2ab136a77f592975808e919260963a9be83b2d4ddbee6b9b24319fb08c6316f262fe208aba81e50d1156db6ad8e36974fecd6955608d807da4667 +RMD160 (NetBSD-6.0/amd64/INSTALL.html) = e4976765905456206ba0906f3d7aee383e80b5dd +MD5 (NetBSD-6.0/amd64/INSTALL.html) = 9a1d1f0005ff232d9501ebe159d122b7 +SHA1 (NetBSD-6.0/amd64/INSTALL.more) = d1da705f0adc32b67801928824379ea45ddb70fd +SHA512 (NetBSD-6.0/amd64/INSTALL.more) = f5e6d604726edc5759dcc63e32c046fc0f952b9e4357e331b3864d1074954db46f0a7295b63f6f3a2c5ecda4ad3fcfc568a6dfc7dc91db5559a768ad2f6fd6dd +RMD160 (NetBSD-6.0/amd64/INSTALL.more) = 4b06e7cde85cdd8fef618f254e8a9136ff25e766 +MD5 (NetBSD-6.0/amd64/INSTALL.more) = c1d511b8ec407155635d1df1d3698af9 +SHA1 (NetBSD-6.0/amd64/INSTALL.ps) = dc0b32b40a813365cab508de06d4280a4ebe8496 +SHA512 (NetBSD-6.0/amd64/INSTALL.ps) = 62ad1a41b0101222de2a4aea45c32ed7a02a4b06d1fd86b1c4d35f6ac5605a3562ca21b815db8e27d67e4584a5e155bbf8d5dda842e165379f4efd962c19a4a8 +RMD160 (NetBSD-6.0/amd64/INSTALL.ps) = fc6b89c1155481439b4a4a66357b925227720d97 +MD5 (NetBSD-6.0/amd64/INSTALL.ps) = 833ee159c8aeb1456ad514df2b4da716 +SHA1 (NetBSD-6.0/amd64/INSTALL.txt) = fd054d29f49e793dec119508a0466e243d54d05d +SHA512 (NetBSD-6.0/amd64/INSTALL.txt) = c5e9a67c9bcd990c16a13390db60ff432f4640434234dc69a412d2ebd57fd333ace7ea59dc5b3acc815ceef9077cd76cb26dc5d6fcc5ebaa5fc95a511928bd21 +RMD160 (NetBSD-6.0/amd64/INSTALL.txt) = 271a2919d0ff6fddc1bb771716e67a7319795f7c +MD5 (NetBSD-6.0/amd64/INSTALL.txt) = 2de264a9a927f1f3513674ec16ac4d45 +SHA1 (NetBSD-6.0/amiga/binary/kernel/netbsd-GENERIC.gz) = ad3ce973bb574d84022cbc071997dca9377e1be7 +SHA512 (NetBSD-6.0/amiga/binary/kernel/netbsd-GENERIC.gz) = 23e227becd8364657d767347b251ca8f47efe9397b9a0cadec90aeb9e90372dc49f143026ca678d933acde69c9be780b50a589ce0cf164f61af8d4eb641f5c64 +RMD160 (NetBSD-6.0/amiga/binary/kernel/netbsd-GENERIC.gz) = 65ccd49cd01c0981f4b4a65914d59731492a9876 +MD5 (NetBSD-6.0/amiga/binary/kernel/netbsd-GENERIC.gz) = acb579f6a97b9a5909bebf16f2742b0a +SHA1 (NetBSD-6.0/amiga/binary/kernel/netbsd-INSTALL.gz) = c3904eede4df412ea9a7db90f34009cdaee611dc +SHA512 (NetBSD-6.0/amiga/binary/kernel/netbsd-INSTALL.gz) = 6087a06debbf2f6820f5c450495680b0f5356d2e5036e1a7787b02f9cd5c8c43da24069ac0cb14bf5b09ca5ff122905d0c26c044c361c27202b4aa9a561cfeba +RMD160 (NetBSD-6.0/amiga/binary/kernel/netbsd-INSTALL.gz) = 8dcb009d9495e2c1f768e7900b28a263cafb1610 +MD5 (NetBSD-6.0/amiga/binary/kernel/netbsd-INSTALL.gz) = 635f24c98bd4bd94f42bf3daa9090b1c +SHA1 (NetBSD-6.0/amiga/binary/kernel/netbsd-ISDN.gz) = c91b1e76e6f8d7b327728eb7110995968e56cb80 +SHA512 (NetBSD-6.0/amiga/binary/kernel/netbsd-ISDN.gz) = d1ba0cda42d6eaf9815f39a52429767c00769d671faaf7144c830f1d06dc5571c39e0e823a7764fbdfaad10a1f516385ed1d3d54c4053a913e8399e3a1d37084 +RMD160 (NetBSD-6.0/amiga/binary/kernel/netbsd-ISDN.gz) = 32dfb7318589e9e2445f781c1344f7b418b1b9e3 +MD5 (NetBSD-6.0/amiga/binary/kernel/netbsd-ISDN.gz) = efdc155fef394563fed3a0c32d90a291 +SHA1 (NetBSD-6.0/amiga/binary/sets/games.tgz) = 16ee93ea4d5fac2fb28fad5c32c8a3d57d011d79 +SHA512 (NetBSD-6.0/amiga/binary/sets/games.tgz) = a7f49ab72f50273f66c8dcf408b57ec4668debd5537c5bd0ec59aa0f4fa1d599ba0798d1b283315c4208cbcb608925808ce003b1ade79034886edb8208f9f48d +RMD160 (NetBSD-6.0/amiga/binary/sets/games.tgz) = 1e09d99d7fe2e495763f05919472d27a4ba699df +MD5 (NetBSD-6.0/amiga/binary/sets/games.tgz) = 8a26f3e864444209088bccf21419a616 +SHA1 (NetBSD-6.0/amiga/binary/sets/man.tgz) = 899b9d8242e983a5110ab755651c24f709b5af67 +SHA512 (NetBSD-6.0/amiga/binary/sets/man.tgz) = 410999db110d710f4bb498c3d7ae7adc62170c7c2f470ce189c92f6c436c5ea96149659c631ef0b5605caaa025d97dfe1c07c428d86f51239657bd6b71717b15 +RMD160 (NetBSD-6.0/amiga/binary/sets/man.tgz) = c1270f68c6d41b351877f71f0396ac34877dfc8d +MD5 (NetBSD-6.0/amiga/binary/sets/man.tgz) = df4db2bbfa39ef6a4a215d949653d04a +SHA1 (NetBSD-6.0/amiga/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/amiga/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/amiga/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/amiga/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/amiga/binary/sets/xcomp.tgz) = e13548b8974f5d55e98caf17b2b4bbbcf2430370 +SHA512 (NetBSD-6.0/amiga/binary/sets/xcomp.tgz) = e4b13c798df04ffef88e72100e2db5af400e5ae255cd7a1ca2907736b8138a59045b6f3bd8531b5753d0b87eadb1b5f801043a929bb25d1611e4be693c1da954 +RMD160 (NetBSD-6.0/amiga/binary/sets/xcomp.tgz) = 3b1f4e26ddd57e69afd9709553c1bf70d6e29ea0 +MD5 (NetBSD-6.0/amiga/binary/sets/xcomp.tgz) = 894bb9aa05b164d9923682165d708335 +SHA1 (NetBSD-6.0/amiga/binary/sets/xetc.tgz) = d2ca34bd668e108cbbfd4b45720823663339f8bd +SHA512 (NetBSD-6.0/amiga/binary/sets/xetc.tgz) = 431ca465f300e7eb5d4dbd44c43e412a296fb4d3129217e752f86a720e8a8bdf736c9add05a45518a4f3e6cffa32381ef61e9186d360b68a5f8c64d87e385fb5 +RMD160 (NetBSD-6.0/amiga/binary/sets/xetc.tgz) = 4c5d664679856b02b694534cd6afdf20597e6d53 +MD5 (NetBSD-6.0/amiga/binary/sets/xetc.tgz) = 72bd67556ac14ea0ce147374af0ba624 +SHA1 (NetBSD-6.0/amiga/binary/sets/xfont.tgz) = 24ca4cb77a59246b1b05e0a91fed21c63259d12b +SHA512 (NetBSD-6.0/amiga/binary/sets/xfont.tgz) = 8dc297fb6205a995767e68e77cc21169234dfb66a86bbcd2e1828fd32efeda0a25c9f2a9b1a39b97fe8d7b24f8cd5cf6160859af6be2259876f39ee4e76c405b +RMD160 (NetBSD-6.0/amiga/binary/sets/xfont.tgz) = d2f134959940e6667aca185f01e388c05dc6bc85 +MD5 (NetBSD-6.0/amiga/binary/sets/xfont.tgz) = 3c96c1f0a13cd7d277ca35622ac9c058 +SHA1 (NetBSD-6.0/amiga/binary/sets/kern-GENERIC.tgz) = 295ba9f28d2b11af8b7ea93c0b4cec03e40002a7 +SHA512 (NetBSD-6.0/amiga/binary/sets/kern-GENERIC.tgz) = b762b6592db8439df6c8d7cfd26f509425c779dcb3d27face8aea6c50dec314c15124b6623152969d5a0998c6991050c5c18a4f547ff5027c8ef56e4d4b5baf3 +RMD160 (NetBSD-6.0/amiga/binary/sets/kern-GENERIC.tgz) = 566f5c6520f253fbd5c7043931b275811853e289 +MD5 (NetBSD-6.0/amiga/binary/sets/kern-GENERIC.tgz) = 3ef7c2157fd42c60a0c1c4c898855219 +SHA1 (NetBSD-6.0/amiga/binary/sets/base.tgz) = 863379dd24489824d8140df08e3f5ca5bb63c35a +SHA512 (NetBSD-6.0/amiga/binary/sets/base.tgz) = 845fec5935b19d810896af3451bff4f2eb6b3b02b285e8e7651c3be32c60d2abacbbb614e3c11b96cf33497fbe6505458f9a292bb0393c54a764449b9b5dff65 +RMD160 (NetBSD-6.0/amiga/binary/sets/base.tgz) = 5c87d3799986d70963b0e02416ff7648602d31de +MD5 (NetBSD-6.0/amiga/binary/sets/base.tgz) = c8b7075f670666c9492a46c44e4632de +SHA1 (NetBSD-6.0/amiga/binary/sets/comp.tgz) = fad62d4d7c47d956a450773b817a838f30497212 +SHA512 (NetBSD-6.0/amiga/binary/sets/comp.tgz) = c8c85b7a59df5930e8cde1715b03c2ae7646d40902e2c402292308f8eba81132a155120215c763a68dd7f37ef489d786ee73911849b69cc9c9e3ba1e86de1bb9 +RMD160 (NetBSD-6.0/amiga/binary/sets/comp.tgz) = 46162e89fb8c66089ccf0523e3b3483834284284 +MD5 (NetBSD-6.0/amiga/binary/sets/comp.tgz) = f107b1d62d1535a4dc1052752837aecd +SHA1 (NetBSD-6.0/amiga/binary/sets/etc.tgz) = 7a2e1bc8aa53aeea37bb71ae598886da762888c4 +SHA512 (NetBSD-6.0/amiga/binary/sets/etc.tgz) = 80d275882cc7df12a3ba35a9e101e1f4597c3cd16864026013be90f0a8e8ef2ab405b5b29dc39ed3e114fac9986dc05efb661cc4361cf4d05d4e6cb25462ae45 +RMD160 (NetBSD-6.0/amiga/binary/sets/etc.tgz) = 3b71a2cfee1368a862a75f44d249b85059f34bc6 +MD5 (NetBSD-6.0/amiga/binary/sets/etc.tgz) = e8fba82eea6cdabed070234fde1acf2b +SHA1 (NetBSD-6.0/amiga/binary/sets/modules.tgz) = 412c02a1fe2bc42ffaa13e3b5cfe30ab89ca8066 +SHA512 (NetBSD-6.0/amiga/binary/sets/modules.tgz) = 0fcda39f953bfbeaae0480d14a4e36724296ff88185985aec0863d5730048da38dd37f5f609e4b085a4776fbf139e8ca3acd693e7a5827f5fa7f51b2006b1447 +RMD160 (NetBSD-6.0/amiga/binary/sets/modules.tgz) = 44f4e35271aa128a88c14913b82edc82f93ffb57 +MD5 (NetBSD-6.0/amiga/binary/sets/modules.tgz) = c0a7fed3fc40edbb00bc24975c10c011 +SHA1 (NetBSD-6.0/amiga/binary/sets/tests.tgz) = 3d5677828808ee833c1c65cf5ff5d1cf1f66611f +SHA512 (NetBSD-6.0/amiga/binary/sets/tests.tgz) = 4d868f712f2e0e3e9b56e6f346934b71eb174d97ff197883f3e3d4923c3dabda651bb3fa3d172fcd32ee5d07b659e7639cff6d9c9450e605174d8a09a6ac730a +RMD160 (NetBSD-6.0/amiga/binary/sets/tests.tgz) = 662e3dcc455114628676304b277a852a49597104 +MD5 (NetBSD-6.0/amiga/binary/sets/tests.tgz) = 84a17f9c5c7bb88e34f42e3a7cbdc490 +SHA1 (NetBSD-6.0/amiga/binary/sets/text.tgz) = 8153acee4263203531a66cdf71215db94d745bd9 +SHA512 (NetBSD-6.0/amiga/binary/sets/text.tgz) = 3ca801f17e44f701543140841123196e132f920d7ac5859dc2a5133da08b73f4d730cbfc62fee5ba9bac6b0d96cf4985b951aad33cf59d5470d7b99cadaf51dd +RMD160 (NetBSD-6.0/amiga/binary/sets/text.tgz) = 5820be807d773054a2c25d0c0009141ddf4a3d5c +MD5 (NetBSD-6.0/amiga/binary/sets/text.tgz) = 6640874a003b751e38fe8ecd14f001d7 +SHA1 (NetBSD-6.0/amiga/binary/sets/xbase.tgz) = c2df6e9a1c3bdae97964577118ae358efe3e3f38 +SHA512 (NetBSD-6.0/amiga/binary/sets/xbase.tgz) = 4751bb14d6a5da31d95ab7e5cef52fcba99b8e13b8379f7fcff8aafe8116c4a036553adf4e6e9bed1642cf39b8e3de6a4e29a37ea48d1363dad853ef3d198604 +RMD160 (NetBSD-6.0/amiga/binary/sets/xbase.tgz) = cbeb269f4126adf0e3e9894888047f70a42f1d6d +MD5 (NetBSD-6.0/amiga/binary/sets/xbase.tgz) = 03727cb263b9f50dfec22ac09d5d0543 +SHA1 (NetBSD-6.0/amiga/binary/sets/xserver.tgz) = 3e746f532be1a2ea1d5d38894bf0be416021412a +SHA512 (NetBSD-6.0/amiga/binary/sets/xserver.tgz) = b90fcec5aea23879b3c39aa516e1c658064d35e8dc8172fac9f722b9c08f71a73f3a33d84dc618c88bf368156e9e4bf220f3cbd110f66bd213838fef73af50f3 +RMD160 (NetBSD-6.0/amiga/binary/sets/xserver.tgz) = c50619861d88fbc22413aca3bad38cb33065b590 +MD5 (NetBSD-6.0/amiga/binary/sets/xserver.tgz) = 5ac22d2440ed272bbebec827a0134acc +SHA1 (NetBSD-6.0/amiga/installation/miniroot/miniroot.fs.gz) = d83dc1458c18c0625f767f00066eff80547ee71f +SHA512 (NetBSD-6.0/amiga/installation/miniroot/miniroot.fs.gz) = 415b4c824c4efdd1c8fd597c6c8222c26d77e56f6f36bcb65d9e7eb3882c20f3c452f05b4541a0832590e53a67b12423d21196626fcc7c1cad4992648a98e136 +RMD160 (NetBSD-6.0/amiga/installation/miniroot/miniroot.fs.gz) = 4cf219c14c3c367d95ff4aa4cf04dba379ee16c7 +MD5 (NetBSD-6.0/amiga/installation/miniroot/miniroot.fs.gz) = 1bb2a3735737d2af8155407157cb2120 +SHA1 (NetBSD-6.0/amiga/installation/misc/loadbsd-2.14) = 32e902d420c2ba8498854bd26387369b09efabb6 +SHA512 (NetBSD-6.0/amiga/installation/misc/loadbsd-2.14) = 3fe58857d83d88f1fc7f6e29e8ee079be25326abad3a25ba5f64e3429f22f08ef102551e15c4275fe973d5536a5d459edea384fdd2293f68fe6d293801fba85c +RMD160 (NetBSD-6.0/amiga/installation/misc/loadbsd-2.14) = 17a84971cee95ff8bf1b64d5071bd1fdbdbc5a99 +MD5 (NetBSD-6.0/amiga/installation/misc/loadbsd-2.14) = 1f841716409b236df90d9c5d63332edf +SHA1 (NetBSD-6.0/amiga/installation/misc/loadbsd) = 2c8e314ee812e159ea479bacf09c47a2a4911e17 +SHA512 (NetBSD-6.0/amiga/installation/misc/loadbsd) = 881d3187366e2736e65e22bae93f24afd0b34b841b733898d3d172d98084f1729b19a6277445601da35471e3583e98b86008262b1a77dbb8bcc37e0c03d07b32 +RMD160 (NetBSD-6.0/amiga/installation/misc/loadbsd) = 00249c76e9a57ed5e58efbdc1001f782595c3918 +MD5 (NetBSD-6.0/amiga/installation/misc/loadbsd) = c1cc983600053a7de29feb09d703754d +SHA1 (NetBSD-6.0/amiga/installation/misc/device-streams.tar.gz) = 5b96fab4bbb49a985481dc5c1e2830e994bd88ec +SHA512 (NetBSD-6.0/amiga/installation/misc/device-streams.tar.gz) = 88e35b476d60dd988e8056263fc4f86893c5a7c2c3125934db8d728e3b679554b229b2adc3babf8c2ff21af46530eea1ff30e4b6af550b331ad22bd29e18434f +RMD160 (NetBSD-6.0/amiga/installation/misc/device-streams.tar.gz) = d0444d1e967a624fde15e4526f9c7f673566492d +MD5 (NetBSD-6.0/amiga/installation/misc/device-streams.tar.gz) = 6a3eed6278587660ed543c7449ee571e +SHA1 (NetBSD-6.0/amiga/installation/misc/runbootblock.README) = 2d62005b98533a4fffd7d0445ac8cb7c5ac11c59 +SHA512 (NetBSD-6.0/amiga/installation/misc/runbootblock.README) = 9f071ff7ac0d2eabc77d43faeee48cba3a1883c957b046fad4d7d3237f41d2752a1e010a5d9f5324f90b81bc9968afe425d320e6742ac8f5e081056d5e133baf +RMD160 (NetBSD-6.0/amiga/installation/misc/runbootblock.README) = 872a2169c248b016d6782a6b9c4208c67a346d12 +MD5 (NetBSD-6.0/amiga/installation/misc/runbootblock.README) = c60fe181cd9b255e294bfeb4be411181 +SHA1 (NetBSD-6.0/amiga/installation/misc/loadbsd-2.16) = eb660b987186a4e3a4eccb740dbb9e061a4b7216 +SHA512 (NetBSD-6.0/amiga/installation/misc/loadbsd-2.16) = 0f4565e2de70eaaf1d973da2b4a988e794b4608b2b0fa9c84dd05c82ade92fc4b75339e94e4a593e051ab3a364611fd7dbc2b48dccd4906f7b42fb665f7d711c +RMD160 (NetBSD-6.0/amiga/installation/misc/loadbsd-2.16) = a071897afbdd11655a21df5a89c6e49b6e8a3574 +MD5 (NetBSD-6.0/amiga/installation/misc/loadbsd-2.16) = 8e67fb434887e942fe63cf308195b18f +SHA1 (NetBSD-6.0/amiga/installation/misc/rdbinfo) = e413a8a5631dfedb4b1634c709836d1f92d9b08c +SHA512 (NetBSD-6.0/amiga/installation/misc/rdbinfo) = 912ddb9bd1ba1af07e1072fee9a09f22124792abfc8f4f178a5df66dad17c39211c52d2a581111338a523f17a0dd58315d798659e901f14084d62a8c890e0a44 +RMD160 (NetBSD-6.0/amiga/installation/misc/rdbinfo) = 8fb8b41e39f6c2d48b6b46be0433dfc45c353621 +MD5 (NetBSD-6.0/amiga/installation/misc/rdbinfo) = 027c4bfce639d3cb88d617b0e85c0c4c +SHA1 (NetBSD-6.0/amiga/installation/misc/runbootblock) = 598d688badd592a838dc260ce36b84c7835e72c0 +SHA512 (NetBSD-6.0/amiga/installation/misc/runbootblock) = d4cf9fe94244f1a832a6e474ff777ae7b901e86e0aabbbceb356c42f533dadb370686080b8e64993b9e07502310a4140fd393db5ddbdcd7a9e44c86b20f4c0a2 +RMD160 (NetBSD-6.0/amiga/installation/misc/runbootblock) = 2457b64f16ee58d22bacdf407ef35a1e9d244e1f +MD5 (NetBSD-6.0/amiga/installation/misc/runbootblock) = d4d059566ad067e4d60259b389a5a9c3 +SHA1 (NetBSD-6.0/amiga/installation/misc/xstreamtodev) = eaf846a0d81754fb778b070926c495720cecffac +SHA512 (NetBSD-6.0/amiga/installation/misc/xstreamtodev) = 873e7ffa5686a69b4a0ad68626f5e32176c03fc6231072531b36af3d0c0c055ced63e6c7f5cb0f3c6568f47720f31b76140aeede3f3dd9ddc8b639c6b3bdd5bf +RMD160 (NetBSD-6.0/amiga/installation/misc/xstreamtodev) = 16910f7f243ca8ae74b8ff90d89163edbd4c3fbf +MD5 (NetBSD-6.0/amiga/installation/misc/xstreamtodev) = a9e2e97f7945cf34da63aef17bed0f3f +SHA1 (NetBSD-6.0/amiga/INSTALL.html) = 42ae087edd4c644275cb6a351bfc0801a23f7b41 +SHA512 (NetBSD-6.0/amiga/INSTALL.html) = e3f4389bff567192811d94c90b1df6d35d379774173ee935b2ebacf6ebc04edee9d270a71cf1e312bb52cfdfdf3ea7fa50f3cc6058bef88051f6da2953faefe0 +RMD160 (NetBSD-6.0/amiga/INSTALL.html) = 941e3e7501290a6a596c10bb9e9dce71fd68f01f +MD5 (NetBSD-6.0/amiga/INSTALL.html) = ca5a2dcf7c5a927f0f89edabd084d59f +SHA1 (NetBSD-6.0/amiga/INSTALL.more) = 2ef7c56d3b3789f858d82b96f8b955801feb402a +SHA512 (NetBSD-6.0/amiga/INSTALL.more) = e1f87c081f267bb5bda5f1f07467e4081b3289cc1b5eead1ce26e954acf6704ad86ac95fb8958130f0a5b198eca80b967c7089cdc35ba4399cc79ab822df2ec2 +RMD160 (NetBSD-6.0/amiga/INSTALL.more) = 55a90159f299abe126ea37f0becea2f692fb1595 +MD5 (NetBSD-6.0/amiga/INSTALL.more) = 1357d2cc09f7d5429c5790dd32592032 +SHA1 (NetBSD-6.0/amiga/INSTALL.ps) = b4a7420ef6502bd98009c6f7b79053a076881f28 +SHA512 (NetBSD-6.0/amiga/INSTALL.ps) = 295f43cd3ba4b64deec0652bab61802cc37a7c3e75cab305cd0e12a682822a137abcd0915115709e1147e952b87bbb128e53251625288ba58068a52e491dd0da +RMD160 (NetBSD-6.0/amiga/INSTALL.ps) = 07a4ea8478343a0f6a1e935eca5133ab116b5779 +MD5 (NetBSD-6.0/amiga/INSTALL.ps) = f07315266b0fd45fe58f107dda2177f8 +SHA1 (NetBSD-6.0/amiga/INSTALL.txt) = 6f5c90d805c69d5c75efb96b3b579d49bb123a6b +SHA512 (NetBSD-6.0/amiga/INSTALL.txt) = 2fba02db405672d44df143421547a2291272a56f6d6e37b5da1f0396739ac55c695178c2e115a5af8574d6c323c8adc2747073e799b59d4e886191ce1baeb5cd +RMD160 (NetBSD-6.0/amiga/INSTALL.txt) = 18db9a1a6e4af5935ed15d37c218b0309309c95c +MD5 (NetBSD-6.0/amiga/INSTALL.txt) = 23deef4d8fd55d404915f004ba0fde9b +SHA1 (NetBSD-6.0/amigappc/binary/kernel/netbsd-GENERIC.gz) = 1fb8ac599ecb67083a0505f7767600b5a00e6164 +SHA512 (NetBSD-6.0/amigappc/binary/kernel/netbsd-GENERIC.gz) = a41b53fecaa5077d80a2a6191073785c87ef703a4cd17e45ea1064e64c923fbf9d97edcc1c4e58ed205ea85f070f80a992198943a9384f4af473a11058c56d4f +RMD160 (NetBSD-6.0/amigappc/binary/kernel/netbsd-GENERIC.gz) = b9f459e21e09ac314b2a02a2ec1a5ef0841af3d0 +MD5 (NetBSD-6.0/amigappc/binary/kernel/netbsd-GENERIC.gz) = 8c59d3085078659f9fd319d69ea1bc0a +SHA1 (NetBSD-6.0/amigappc/binary/sets/man.tgz) = 899b9d8242e983a5110ab755651c24f709b5af67 +SHA512 (NetBSD-6.0/amigappc/binary/sets/man.tgz) = 410999db110d710f4bb498c3d7ae7adc62170c7c2f470ce189c92f6c436c5ea96149659c631ef0b5605caaa025d97dfe1c07c428d86f51239657bd6b71717b15 +RMD160 (NetBSD-6.0/amigappc/binary/sets/man.tgz) = c1270f68c6d41b351877f71f0396ac34877dfc8d +MD5 (NetBSD-6.0/amigappc/binary/sets/man.tgz) = df4db2bbfa39ef6a4a215d949653d04a +SHA1 (NetBSD-6.0/amigappc/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/amigappc/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/amigappc/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/amigappc/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/amigappc/binary/sets/kern-GENERIC.tgz) = 8cfda7d67d00c0344fc8b7e15c14367c9dd3c0d0 +SHA512 (NetBSD-6.0/amigappc/binary/sets/kern-GENERIC.tgz) = 00ecdc9511f389035fdd0d5786ec5b16ea52722cf390b75b11c0d0c5504d96bdfbaf6b19237e752aba9d530ed80cdaeadf18a7d0079c22a1560644fa8fb2ffc9 +RMD160 (NetBSD-6.0/amigappc/binary/sets/kern-GENERIC.tgz) = 0508773016c4dcf8b88d238235c66fc61785c0fe +MD5 (NetBSD-6.0/amigappc/binary/sets/kern-GENERIC.tgz) = ada4ef952407ea1d320765955f626aed +SHA1 (NetBSD-6.0/amigappc/binary/sets/base.tgz) = 69692adf17c4631804d6e78e96868bf22a0f80e4 +SHA512 (NetBSD-6.0/amigappc/binary/sets/base.tgz) = bc3f89b3201c184f38bed2dcd3e74ce01a8c9b5cdba1065bfe5bc0eadf0ed71fd73bcb9d0add77ab7d2cfc4848f40c482b0e2cbf50771577716f8a344eda5a6b +RMD160 (NetBSD-6.0/amigappc/binary/sets/base.tgz) = 3cb20928324c3bf484a05a04d47afa4f587d5d52 +MD5 (NetBSD-6.0/amigappc/binary/sets/base.tgz) = 00d35c074b0f69e81494f42cd43ccecd +SHA1 (NetBSD-6.0/amigappc/binary/sets/comp.tgz) = db98cb19c33216dafdd0ab26cbfa2a4f0cc685e7 +SHA512 (NetBSD-6.0/amigappc/binary/sets/comp.tgz) = 7dc6b1ed24deecd9f29aae5867bd2d89c9df3f443d522315f541eae77fde420d15b63233694043595a0f12491af5e24699598acc45ed05d9622911869f79ceb9 +RMD160 (NetBSD-6.0/amigappc/binary/sets/comp.tgz) = 776b79b7b476cc3b4caee7712070864d35779f66 +MD5 (NetBSD-6.0/amigappc/binary/sets/comp.tgz) = 385fe9939b6bb28a37cdf9cc3958dba8 +SHA1 (NetBSD-6.0/amigappc/binary/sets/etc.tgz) = f424a289be42a94c875757d9f83756d7e9286f20 +SHA512 (NetBSD-6.0/amigappc/binary/sets/etc.tgz) = b736da20bee72bb1962acce7cb8cd51e851f541ec79766d2258f1322ae843b0879208a6f69d6dda9ecc74a4bf7739fed626b8205432dd63f630b04803418307c +RMD160 (NetBSD-6.0/amigappc/binary/sets/etc.tgz) = 0f163aa3a9450f45b40760786373089e52dae0bd +MD5 (NetBSD-6.0/amigappc/binary/sets/etc.tgz) = c2cb43cbeb231d24b3864c7882da8edb +SHA1 (NetBSD-6.0/amigappc/binary/sets/games.tgz) = d10c319a009f9859de37a5d5bb994d29669dce16 +SHA512 (NetBSD-6.0/amigappc/binary/sets/games.tgz) = 59e00cdf1b42e285db9cd29ab195b693f1989cd1480e644787307ea722a1a695e70708ad8fa6d0afbbb51de4ca8a4b81b550e2f1745d0140a47e1b6a7002a236 +RMD160 (NetBSD-6.0/amigappc/binary/sets/games.tgz) = 0baf65f6198b6f1c40960b30424a3ad44c1eca2f +MD5 (NetBSD-6.0/amigappc/binary/sets/games.tgz) = 304dc86d68c23c7f30c30e4f092b6982 +SHA1 (NetBSD-6.0/amigappc/binary/sets/modules.tgz) = 2a05a8cf525b6b0323f54840bb42e069a36f1988 +SHA512 (NetBSD-6.0/amigappc/binary/sets/modules.tgz) = fc33e9c609d38775e7004d2715158178d08508f8a890831270191b7f32fae8a2d2b56e74e59d4f5d37574827cf85eda28e15f88ac1544a1ceec008105107dcb5 +RMD160 (NetBSD-6.0/amigappc/binary/sets/modules.tgz) = 931d81973e92a161da6468aeeb0b7a486fc96511 +MD5 (NetBSD-6.0/amigappc/binary/sets/modules.tgz) = 13f7ee97c852a71b51c91dd8f659b202 +SHA1 (NetBSD-6.0/amigappc/binary/sets/tests.tgz) = eee320cd38b5396a305b912cd43ad4f40dcb0e98 +SHA512 (NetBSD-6.0/amigappc/binary/sets/tests.tgz) = 3c2377b75fb69924c646904f67e3762bddbd5fe40214df319d205f412e7377e7695d5b648545f22e9b42696cb3fd3ddb9bde4ed7b3ad1d48ea32fbbf13356354 +RMD160 (NetBSD-6.0/amigappc/binary/sets/tests.tgz) = dd0ea2b9c6f23f409ced129c5dc847c582b572fe +MD5 (NetBSD-6.0/amigappc/binary/sets/tests.tgz) = 2f0dc32c95f23026c06b50c946dce965 +SHA1 (NetBSD-6.0/amigappc/binary/sets/text.tgz) = 7b28a25a69ba9d2870c31c302be38d0c12b11486 +SHA512 (NetBSD-6.0/amigappc/binary/sets/text.tgz) = 77dcaa1c134ac4f346bf782c5c20ea4304b42a15a60a1321e944e59665946d1b3ddfcd9eba919f6ea4ca947dd8df63a9162adfea363e01758ffa5bf8e7f49e12 +RMD160 (NetBSD-6.0/amigappc/binary/sets/text.tgz) = 438d720340cbd19f86ac8449dd705d125958cdbf +MD5 (NetBSD-6.0/amigappc/binary/sets/text.tgz) = 3fc18e1ff4fc50d561b478b39fe7f855 +SHA1 (NetBSD-6.0/amigappc/binary/sets/xbase.tgz) = 11ec98aff57d5a8f8cabcc0a41eb7e41c2cd750e +SHA512 (NetBSD-6.0/amigappc/binary/sets/xbase.tgz) = c9c39d05fa60bc2a0e1a4aed89ecfafa47c203652f23b971fa9b3d23df291fbeb4735dd4621a81a46eff276c80410ee36492162e5282bf19bc9df4bf889d4fb8 +RMD160 (NetBSD-6.0/amigappc/binary/sets/xbase.tgz) = 4d1a32acb55c107327f1605a6a7d3379e3e3fbc1 +MD5 (NetBSD-6.0/amigappc/binary/sets/xbase.tgz) = 0a959da0b8e03e2686da275c8311addf +SHA1 (NetBSD-6.0/amigappc/binary/sets/xcomp.tgz) = 5a450d9cb090214e14b45d59ee87d7786da4afcd +SHA512 (NetBSD-6.0/amigappc/binary/sets/xcomp.tgz) = 2478cf90ce45e16d8854bfc2aad28d102aafb53f9b2fd39756bff0970c0546f52a3d31be85e581ae78e982b06f17a8de77eea776d7d8e0770e00a0e198c06bbe +RMD160 (NetBSD-6.0/amigappc/binary/sets/xcomp.tgz) = 82323c0e4b56e79891087934eed15d1472646bec +MD5 (NetBSD-6.0/amigappc/binary/sets/xcomp.tgz) = 096eaba339adb8b492dc1ce5de1dada0 +SHA1 (NetBSD-6.0/amigappc/binary/sets/xetc.tgz) = 98fd5a6cb8eab73e8453afe8626198945e0cd1e4 +SHA512 (NetBSD-6.0/amigappc/binary/sets/xetc.tgz) = 13b0c70af019c1e2bf14c8df794f497c317cc94e23012f61b88e7386327cd43c6a7b00a04ed4d65975849db9978fa63b401a2d1a49f0d476e17e4d5123d66e8b +RMD160 (NetBSD-6.0/amigappc/binary/sets/xetc.tgz) = ce7639ef1eebd525f0f6631e4aa80a5d44a9ba5e +MD5 (NetBSD-6.0/amigappc/binary/sets/xetc.tgz) = 2bdf6c00be2e1b9420a8d6fd6ab9e285 +SHA1 (NetBSD-6.0/amigappc/binary/sets/xfont.tgz) = f87acd8ea1747d825ad1038f8984bfd9cc5ed3c8 +SHA512 (NetBSD-6.0/amigappc/binary/sets/xfont.tgz) = bd4c6c5913572cfaff4c3cdd66d2e745605d4f8c70f46e25951c109700c4a05a4b8d1202beb90b7b0cb5ba7b37bdcb3bc31a5ddba8737b7133fa3c2239312f62 +RMD160 (NetBSD-6.0/amigappc/binary/sets/xfont.tgz) = 6ff6daa8eff23cd8f49f60ac7adf82afaf029a02 +MD5 (NetBSD-6.0/amigappc/binary/sets/xfont.tgz) = e9eb507d880069bb39bca1e12ca61f05 +SHA1 (NetBSD-6.0/amigappc/binary/sets/xserver.tgz) = 5dca2b2f9ebbdd6d659e06bdb69987fe02278968 +SHA512 (NetBSD-6.0/amigappc/binary/sets/xserver.tgz) = e2e87ac352cbadc9e0590b7ddc402de6dc4ee3fb26a504265aa1a706ef53135fb80d0d3e149e94825485fd121add254d68a88ead521949f55da7d9e252192575 +RMD160 (NetBSD-6.0/amigappc/binary/sets/xserver.tgz) = 94ab84cf7ee91393ef0630b7b3110a4846940dfa +MD5 (NetBSD-6.0/amigappc/binary/sets/xserver.tgz) = 6ca7773bb022c8842ce6a0a4a0f23c80 +SHA1 (NetBSD-6.0/arc/binary/kernel/netbsd-RAMDISK.symbols.gz) = f4e479e3fec7462469600527ae1b9aecd1c86bcd +SHA512 (NetBSD-6.0/arc/binary/kernel/netbsd-RAMDISK.symbols.gz) = 8cd3e3d089a53b56fdd47ab4cda09b42bf12c92074699a3764f4fdbb23c58425d68f0ee8e862987386d9c8107e0e115daf39bd35058b4e51d93c4dc7d5756d04 +RMD160 (NetBSD-6.0/arc/binary/kernel/netbsd-RAMDISK.symbols.gz) = 79dd220dcba4f30fd629e744993e3d8617d2c3ac +MD5 (NetBSD-6.0/arc/binary/kernel/netbsd-RAMDISK.symbols.gz) = 2ffba67d5ec969424a75c71e5f04c77f +SHA1 (NetBSD-6.0/arc/binary/kernel/netbsd-GENERIC.gz) = c34a668c8d951cd778d973a0066223bd4ea98133 +SHA512 (NetBSD-6.0/arc/binary/kernel/netbsd-GENERIC.gz) = 47685372141fd6fae114fcbcc57016c6896f96705be116020802c6e6a7493cbea9ecf62dbbfc89c49f0f90d42aee1f06b9d6ed3eb679b0b1e3e2705c3ff0ec1c +RMD160 (NetBSD-6.0/arc/binary/kernel/netbsd-GENERIC.gz) = d46270739b1bc29e7e361805d4f23a28ced95975 +MD5 (NetBSD-6.0/arc/binary/kernel/netbsd-GENERIC.gz) = 046973b3c11b35cb476d07db96419743 +SHA1 (NetBSD-6.0/arc/binary/kernel/netbsd-RAMDISK.gz) = 01c3eb7eabe2423ff73da425627b361ff99bbe21 +SHA512 (NetBSD-6.0/arc/binary/kernel/netbsd-RAMDISK.gz) = ae090ee3642160ed2ab38f6cc1487b545cce31320c8561bb4af5501dc757f24997798a7556a2048cd7f7e0da9ad3415e458273245317bcacafa0d9b76f4326a8 +RMD160 (NetBSD-6.0/arc/binary/kernel/netbsd-RAMDISK.gz) = 9bd6a441f8fbbf01f78b536d75bb8cfdaa56f8cd +MD5 (NetBSD-6.0/arc/binary/kernel/netbsd-RAMDISK.gz) = 6103f4c89298eab52773ed2a6fa59de6 +SHA1 (NetBSD-6.0/arc/binary/sets/games.tgz) = 27d9f98fecb3495e51939df9f107e81e527af26f +SHA512 (NetBSD-6.0/arc/binary/sets/games.tgz) = 46bb4e10313cfffaaf4f7fa2157474ef940f94bcc9f84b46f829c7615bbf45e4e01edee7b7efb84bc28561e0712c37cfc737f9c2a0d9a73b67c80c8aa0f3a9af +RMD160 (NetBSD-6.0/arc/binary/sets/games.tgz) = 947feea90ec2698a65d555cb78a29a001b086589 +MD5 (NetBSD-6.0/arc/binary/sets/games.tgz) = 355f00978fed8e8da6a251e591be5387 +SHA1 (NetBSD-6.0/arc/binary/sets/man.tgz) = 899b9d8242e983a5110ab755651c24f709b5af67 +SHA512 (NetBSD-6.0/arc/binary/sets/man.tgz) = 410999db110d710f4bb498c3d7ae7adc62170c7c2f470ce189c92f6c436c5ea96149659c631ef0b5605caaa025d97dfe1c07c428d86f51239657bd6b71717b15 +RMD160 (NetBSD-6.0/arc/binary/sets/man.tgz) = c1270f68c6d41b351877f71f0396ac34877dfc8d +MD5 (NetBSD-6.0/arc/binary/sets/man.tgz) = df4db2bbfa39ef6a4a215d949653d04a +SHA1 (NetBSD-6.0/arc/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/arc/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/arc/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/arc/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/arc/binary/sets/xbase.tgz) = 76468fcada5a9e26652aa9f0f9f3c94829a317e9 +SHA512 (NetBSD-6.0/arc/binary/sets/xbase.tgz) = b2adcfc2dedef30b21b885c8fc757d0479541744a280a9997fbeaa9c881009ab4b0019e0001a540a8eb6db5f84db87b365e420bb2d4270af209821bdb080369c +RMD160 (NetBSD-6.0/arc/binary/sets/xbase.tgz) = 1e0074d03d9fbb3373e0a427b25cc7097bf6d3c8 +MD5 (NetBSD-6.0/arc/binary/sets/xbase.tgz) = a8f29ec2e3768405942f97af3dd08ee7 +SHA1 (NetBSD-6.0/arc/binary/sets/xcomp.tgz) = d8ac89f3f6ff20abb0adabc49227afdb74aa2040 +SHA512 (NetBSD-6.0/arc/binary/sets/xcomp.tgz) = 4f03213fb061dae9421747209628d06ede6bbb71a7560a9e1a54796b907f1620146a33fdce52974227a21acedcc210b99e15c4fdd36432eba60c1041a92d8cee +RMD160 (NetBSD-6.0/arc/binary/sets/xcomp.tgz) = 6be5e72b9b57c9bdf8ed8ea127e2a73830feeecb +MD5 (NetBSD-6.0/arc/binary/sets/xcomp.tgz) = 59a7ea141587417be38ab1f6056cc780 +SHA1 (NetBSD-6.0/arc/binary/sets/xetc.tgz) = b9f6b1a54ffab37b11f4c6e717b481cd087fb609 +SHA512 (NetBSD-6.0/arc/binary/sets/xetc.tgz) = 72f35e65f3a90967e250a2006d500619b3824f7f5c3d7494554f153ec5cda5b28c445f28c34a1e4463f40da5855e8d4257726411796967fe37763d90cf7fe461 +RMD160 (NetBSD-6.0/arc/binary/sets/xetc.tgz) = 1169c246f91189fd0c4ae86ac27a92f5c2edda3e +MD5 (NetBSD-6.0/arc/binary/sets/xetc.tgz) = 8f3c52cc5af1cafaf7b0d0f884a5b537 +SHA1 (NetBSD-6.0/arc/binary/sets/xfont.tgz) = d06848571034f3b7fc975082f1de37b912acb18c +SHA512 (NetBSD-6.0/arc/binary/sets/xfont.tgz) = 66a1013c935bee5e7e5d24325a527522306bcded7ced63790f2e58831b3ed91176a1b9510b2159be63504d5167d48d534919927ffc6e225ae2bb2487f90a9ede +RMD160 (NetBSD-6.0/arc/binary/sets/xfont.tgz) = c9502843a5d4dd7e996e8d158c519cf7f8575cbd +MD5 (NetBSD-6.0/arc/binary/sets/xfont.tgz) = e812899176eac2bf65a6d949ac3f3424 +SHA1 (NetBSD-6.0/arc/binary/sets/xserver.tgz) = ff805022f409202f3346c45475c7ec0f8187218e +SHA512 (NetBSD-6.0/arc/binary/sets/xserver.tgz) = f2bb3810a5572b519980126a3d934f63b5ab5c2fcf9fb8166c556bd3cc14cfaa151d582086bb1506ac9ac7e21d4e70a5cd5c3faed96212d8a14a0b5bafdcc4c1 +RMD160 (NetBSD-6.0/arc/binary/sets/xserver.tgz) = d5ae336337cc77f7f55f542b3457918d6fc0efe8 +MD5 (NetBSD-6.0/arc/binary/sets/xserver.tgz) = 92447a1560887d337d22e2deed0670a6 +SHA1 (NetBSD-6.0/arc/binary/sets/kern-GENERIC.tgz) = a49dc5701671d377df81d0dc82ebca225e8aff4a +SHA512 (NetBSD-6.0/arc/binary/sets/kern-GENERIC.tgz) = 75bf73c2b22aac1948b5c0fd6ca0a0d240fc398baf7dfe4bbb155f44c8e3bf47d618fb5ee97215728baa471c25dddc285643064acbfed88fcc33f463ec36162a +RMD160 (NetBSD-6.0/arc/binary/sets/kern-GENERIC.tgz) = 49075dea0d02de7d508afb65fa4c4591f7ab1b0a +MD5 (NetBSD-6.0/arc/binary/sets/kern-GENERIC.tgz) = 3dd1b55b9d8aaa84ce5630c649d6d17e +SHA1 (NetBSD-6.0/arc/binary/sets/base.tgz) = 5c25c736260c32dc5e61db84d779f979421417c4 +SHA512 (NetBSD-6.0/arc/binary/sets/base.tgz) = 7bccf72e05a792158f7aa8617b270d860221b935c3c092da8961b35277931500f5e6e8a572536b7371e66dbe7368b17f62512783240dce9aa2990af50c60fc1e +RMD160 (NetBSD-6.0/arc/binary/sets/base.tgz) = c36e7a0c39a18646de9363196aa56dd0c4a6ea6b +MD5 (NetBSD-6.0/arc/binary/sets/base.tgz) = 97e2836870812371a84cf44790cf6f16 +SHA1 (NetBSD-6.0/arc/binary/sets/comp.tgz) = 52ac953130a36ae6bba2139c7892d6ccbab0f0cf +SHA512 (NetBSD-6.0/arc/binary/sets/comp.tgz) = a09590c181019592ffb4341620eeaaae1f25e971ee975ac337c96cdc5dc6ceb2074dcba6a5dcc723c30e5db3d32148146eb6c1eb38390d0162aff4d5071434c6 +RMD160 (NetBSD-6.0/arc/binary/sets/comp.tgz) = e9c5ae0abd43a2ac743f62a498ad8bb0dde61ed2 +MD5 (NetBSD-6.0/arc/binary/sets/comp.tgz) = 2eebbc2b1b8bbe21166a0d860bea9dd5 +SHA1 (NetBSD-6.0/arc/binary/sets/etc.tgz) = cfa766b3b33eeae2aa28312e0ca6e434e2573487 +SHA512 (NetBSD-6.0/arc/binary/sets/etc.tgz) = ef3806802fa813b1bb60674c032f31e5a140b89953aabe715d050e7c820413ae991de791e96d8aecaa1aea8989f6f0268726ad5dc62e42ef06ca6670fb6744ba +RMD160 (NetBSD-6.0/arc/binary/sets/etc.tgz) = 395630144133efd05b0fbe596773c5ea4218aa8c +MD5 (NetBSD-6.0/arc/binary/sets/etc.tgz) = af810d6fb839f2953bba9844501cdcab +SHA1 (NetBSD-6.0/arc/binary/sets/modules.tgz) = cfd582b6f65203d1916ed6655d02f5aa6ad5ba88 +SHA512 (NetBSD-6.0/arc/binary/sets/modules.tgz) = 86be394fe232856d0de502fb1569fd03de91a81ad782389414ed75618d63d97d8abebc14fd44843414d865071f51940c248d076a57524e8ef91c791ee98620c9 +RMD160 (NetBSD-6.0/arc/binary/sets/modules.tgz) = c63e9a0caaf005f8c03275c8faf582d95b3c6700 +MD5 (NetBSD-6.0/arc/binary/sets/modules.tgz) = cd4a56dcabef37fbf7a3fb7ee95ea738 +SHA1 (NetBSD-6.0/arc/binary/sets/tests.tgz) = 25fca6e0ee3c0c05615fb5753d78584e0c3fd5ca +SHA512 (NetBSD-6.0/arc/binary/sets/tests.tgz) = 54fd09bdf390959e4a795af7efa34cf463f0d41676a87bceae7e8278f97693549bea10d7de099c0f3af34f58ea76820ecd357894d9c7e5bccc65d2fa9736dd40 +RMD160 (NetBSD-6.0/arc/binary/sets/tests.tgz) = baf5b98a820547d80922493f59c48028345306da +MD5 (NetBSD-6.0/arc/binary/sets/tests.tgz) = 601e2f0d37d00e07a671ed2cb823e68e +SHA1 (NetBSD-6.0/arc/binary/sets/text.tgz) = fe43613098e27d16d74e9c21e0b18cc5e932e673 +SHA512 (NetBSD-6.0/arc/binary/sets/text.tgz) = 4935e883c8328121eb941726a41487dc9048a9d3265460e9730465a3d1b8283e4bd01ad2c220607848f898f178dac0738c6bb6402243bcc338e5f933a6c99f06 +RMD160 (NetBSD-6.0/arc/binary/sets/text.tgz) = b57da314266be1fdf31856f5ad5a52703016b61e +MD5 (NetBSD-6.0/arc/binary/sets/text.tgz) = 9236a9d595f3a96234ba9156ed3437e2 +SHA1 (NetBSD-6.0/arc/installation/boot) = 889f35138bde05f74032980aa2ca7c17442c4324 +SHA512 (NetBSD-6.0/arc/installation/boot) = 9a1ccabb379ab44784c481e749f633cf4235c03e22c24f2a837e6fcbe28b23f7bde8a7ed596dde93996bdc5efbf639ed6a073fd848eef2b0d80e932ba360c9e5 +RMD160 (NetBSD-6.0/arc/installation/boot) = 369fb440abfca5f2f4340740265f61a9d2ca8df7 +MD5 (NetBSD-6.0/arc/installation/boot) = 36b7e6f86ddc8aede5c9ea0160939cb2 +SHA1 (NetBSD-6.0/arc/INSTALL.html) = 0cf4b01d7175a1eb6dd2734e412c3bed0fb0967d +SHA512 (NetBSD-6.0/arc/INSTALL.html) = 68a51695f6fbe96610354b253741efcd7f52bd543351a3f3b734398264f7b75c03e72ee731be917b2e34a0041c621107177efb57ba9abe6158456e19526845db +RMD160 (NetBSD-6.0/arc/INSTALL.html) = e174f77ca32ded5ae5363e88ca33ec17df6b95ae +MD5 (NetBSD-6.0/arc/INSTALL.html) = 94eb6340dc1e3d6ae7b539e3ca3744a4 +SHA1 (NetBSD-6.0/arc/INSTALL.more) = 6146391a310edb4727d4b5a61793d535c0983c0d +SHA512 (NetBSD-6.0/arc/INSTALL.more) = 12e1ebc08bd3fb259caafd6b75e1120daba07fb4ad201f513459e5e36ad96790a26076cf154b34332a54192cbda13bf0b85847478a2443114522225f1adbf95d +RMD160 (NetBSD-6.0/arc/INSTALL.more) = 52a7433c4a3fbb3fa6ca52117f9f902a96748dee +MD5 (NetBSD-6.0/arc/INSTALL.more) = 9a6a3c4c52c723151ac81fc40567f625 +SHA1 (NetBSD-6.0/arc/INSTALL.ps) = ed6ce1da53cd979819a5080666fef04c62c3cf60 +SHA512 (NetBSD-6.0/arc/INSTALL.ps) = 8ea3bef19288069a145d6873030895c960811c8dbcff956101f425a9ce0a57701f0f0579c925248b5ecc9f7ac110ddcb18b8041ed74ffd69c22b598ce8d89788 +RMD160 (NetBSD-6.0/arc/INSTALL.ps) = e1c8d2d8ef5b2d170f659f14bf124063d8d34c22 +MD5 (NetBSD-6.0/arc/INSTALL.ps) = f97b10a669be7ec3f9603d5f936fe9fe +SHA1 (NetBSD-6.0/arc/INSTALL.txt) = 799c2e5d3f8a8d4c93e0ba1e0e738dffbec98504 +SHA512 (NetBSD-6.0/arc/INSTALL.txt) = ed89213d84a4ce5ca43b8b7ed35b6e2e731c77205518b8c48258b18567ecc6e2150e81c2d2a4ca0b3c2bbf8059218d0cf918b168c2f55b305815f89ce3cb45c7 +RMD160 (NetBSD-6.0/arc/INSTALL.txt) = d9be36fb053f75805f95439723d18875e6d0cd5c +MD5 (NetBSD-6.0/arc/INSTALL.txt) = 56f07f0f3cd11f592b56f5978d23c533 +SHA1 (NetBSD-6.0/atari/binary/kernel/netbsd-MILAN-ISAIDE.gz) = abe68fd4d9212fee55be19e05105bed9ee51687b +SHA512 (NetBSD-6.0/atari/binary/kernel/netbsd-MILAN-ISAIDE.gz) = 759476c2983250d38267853ca369a432b968e9d8187ae8476d5e2931667518abc63fadef50c6bcf55299866c019d74790e8268b58f433c6413c03cfe1460d8a0 +RMD160 (NetBSD-6.0/atari/binary/kernel/netbsd-MILAN-ISAIDE.gz) = defe3e00a5198a97320f53a1460eb7601f2d5a9d +MD5 (NetBSD-6.0/atari/binary/kernel/netbsd-MILAN-ISAIDE.gz) = fadc1a2fcec83bae67e6e70f1ee8d4c6 +SHA1 (NetBSD-6.0/atari/binary/kernel/netbsd-ATARITT.gz) = 9d2e04ce73a5a24cfb10801c0ccf659242602dd3 +SHA512 (NetBSD-6.0/atari/binary/kernel/netbsd-ATARITT.gz) = 27b28318b371707290e3b8482dc0e98e32c6d5b7fb4d38e3bddda7bc5e1b953ae0651b680cf7ea9a296018b5a0ac883cb59d4da3c02db1baa67e151da783f6ed +RMD160 (NetBSD-6.0/atari/binary/kernel/netbsd-ATARITT.gz) = 77d47ef664e710823cef2633c92bde054a970552 +MD5 (NetBSD-6.0/atari/binary/kernel/netbsd-ATARITT.gz) = f99c55c64e84c84de3991fa4f21897c5 +SHA1 (NetBSD-6.0/atari/binary/kernel/netbsd-FALCON.gz) = 9c0e5bc223f81e24108dde3428ee8833e557d891 +SHA512 (NetBSD-6.0/atari/binary/kernel/netbsd-FALCON.gz) = 6147ba07227f85a3ba2ee1e78449aa2c4e0ad708e9cc000f456a74a69f6443f099e200f2dd3602ceb453dffe7b41c90c32f45ff63d44d59cd0ce24ba68f3ffa1 +RMD160 (NetBSD-6.0/atari/binary/kernel/netbsd-FALCON.gz) = b2c8d8f4742da6ccf1e0ec3811160d9ce9606baf +MD5 (NetBSD-6.0/atari/binary/kernel/netbsd-FALCON.gz) = 2189a16e1ee3e1586f691490fe6bfc9a +SHA1 (NetBSD-6.0/atari/binary/kernel/netbsd-HADES.gz) = c4f3101449a14e294394b13eacff10053078ad4d +SHA512 (NetBSD-6.0/atari/binary/kernel/netbsd-HADES.gz) = bef4589fa86a33df94fdb36038e93528984629682c2827ed4dad582ae17cfea37b9841608dacc95fd8a55c57c40a81b8d24d7afd253dd46d7af970e0927518bc +RMD160 (NetBSD-6.0/atari/binary/kernel/netbsd-HADES.gz) = 821bc772711ece35be32f1fadac8fa31a10041ac +MD5 (NetBSD-6.0/atari/binary/kernel/netbsd-HADES.gz) = 82b69e45fbf4740774a338f62c987dec +SHA1 (NetBSD-6.0/atari/binary/kernel/netbsd-MILAN-PCIIDE.gz) = 4e056fe210771d7d97ad303cc4d92fed64d883f2 +SHA512 (NetBSD-6.0/atari/binary/kernel/netbsd-MILAN-PCIIDE.gz) = 2c303e9421be0eae122cf55c2b5205b4c2129e6bf3033372f8fca93ad410f92137db6463ad9b75db53526dccb2b9c8a3da23d04357a6a3663aa58972c39184ad +RMD160 (NetBSD-6.0/atari/binary/kernel/netbsd-MILAN-PCIIDE.gz) = 878a29fec55b0429c47f0932facf25139721c88d +MD5 (NetBSD-6.0/atari/binary/kernel/netbsd-MILAN-PCIIDE.gz) = b2e52ec52845325caf8fce89fcf5b034 +SHA1 (NetBSD-6.0/atari/binary/kernel/netbsd-SMALL030.gz) = e6b4dad71f39674e21a0baa6cd5bbc61872786e1 +SHA512 (NetBSD-6.0/atari/binary/kernel/netbsd-SMALL030.gz) = 856e3435c5ae454b145bb16a679da93cc966cd7ee75ab8cce77f216d4070b9e3f1a0d2bf15ae9eda28f48a0eaeeae590559888eef477ab4c72badcaed7b7484e +RMD160 (NetBSD-6.0/atari/binary/kernel/netbsd-SMALL030.gz) = 449713cd4e5c43656648e76a59b0228cbf51de82 +MD5 (NetBSD-6.0/atari/binary/kernel/netbsd-SMALL030.gz) = d38e0f0b5090a8d0d6552092c241e105 +SHA1 (NetBSD-6.0/atari/binary/sets/games.tgz) = 16ee93ea4d5fac2fb28fad5c32c8a3d57d011d79 +SHA512 (NetBSD-6.0/atari/binary/sets/games.tgz) = a7f49ab72f50273f66c8dcf408b57ec4668debd5537c5bd0ec59aa0f4fa1d599ba0798d1b283315c4208cbcb608925808ce003b1ade79034886edb8208f9f48d +RMD160 (NetBSD-6.0/atari/binary/sets/games.tgz) = 1e09d99d7fe2e495763f05919472d27a4ba699df +MD5 (NetBSD-6.0/atari/binary/sets/games.tgz) = 8a26f3e864444209088bccf21419a616 +SHA1 (NetBSD-6.0/atari/binary/sets/man.tgz) = 899b9d8242e983a5110ab755651c24f709b5af67 +SHA512 (NetBSD-6.0/atari/binary/sets/man.tgz) = 410999db110d710f4bb498c3d7ae7adc62170c7c2f470ce189c92f6c436c5ea96149659c631ef0b5605caaa025d97dfe1c07c428d86f51239657bd6b71717b15 +RMD160 (NetBSD-6.0/atari/binary/sets/man.tgz) = c1270f68c6d41b351877f71f0396ac34877dfc8d +MD5 (NetBSD-6.0/atari/binary/sets/man.tgz) = df4db2bbfa39ef6a4a215d949653d04a +SHA1 (NetBSD-6.0/atari/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/atari/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/atari/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/atari/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/atari/binary/sets/xserver.tgz) = 1d20fd039546a66b428b854c659ea5e2ee9f8114 +SHA512 (NetBSD-6.0/atari/binary/sets/xserver.tgz) = 091d09049d0af5555feec02065234e281677aeb3ecbab5a19413d924a8b58dc7f64401ef68e68bc52d8b6eeb73e091d351c45805374b8bf276b0181415968561 +RMD160 (NetBSD-6.0/atari/binary/sets/xserver.tgz) = feef5d52278d23637d7b8ba77639bfd96918e90e +MD5 (NetBSD-6.0/atari/binary/sets/xserver.tgz) = b2bd6057c374376388766fc8667eb9a9 +SHA1 (NetBSD-6.0/atari/binary/sets/kern-ATARITT.tgz) = 589b0e48516d961e8961847f441bf7dbcbb67700 +SHA512 (NetBSD-6.0/atari/binary/sets/kern-ATARITT.tgz) = 00ad9fefd5c3fb87f45b20612582b818def61c0f08483f923622a19e94090feb7ba1e39dc8d3b4b7d57e70c60aacaaeee966e1a6a788aff9fbbedc6848e52cd4 +RMD160 (NetBSD-6.0/atari/binary/sets/kern-ATARITT.tgz) = 510465a0b2f0e19a4873fa87fa66d7c47ec8226e +MD5 (NetBSD-6.0/atari/binary/sets/kern-ATARITT.tgz) = cea983b428fc041a9ad553b25e6de431 +SHA1 (NetBSD-6.0/atari/binary/sets/base.tgz) = 948b83244fe16e439af84cee9dd48f555ff2c479 +SHA512 (NetBSD-6.0/atari/binary/sets/base.tgz) = ee2c41fa904f75740c358f85bc97c36537d6a0f252bfb4ca3ec60098109ca07b8be38e8474ea7355e557793fe726160e1f0d10de2769720432a8cb0896bdcf7f +RMD160 (NetBSD-6.0/atari/binary/sets/base.tgz) = d08e1a2d3eb8629aafe49fe89e9c00c65c97967b +MD5 (NetBSD-6.0/atari/binary/sets/base.tgz) = 07d14a63f5591f86d0cb7728174ad6b1 +SHA1 (NetBSD-6.0/atari/binary/sets/comp.tgz) = 081806be5308d18e9910a9f3394bb15fec7111bb +SHA512 (NetBSD-6.0/atari/binary/sets/comp.tgz) = 17e0a84c5ccefcbee5807012b93f413fa90d6fdb55bc91020cc5265528eb4331a4e2d5f951ac457b0fbf24ce2a97f7dde29a2cfda946edc5db2bf7c574289a75 +RMD160 (NetBSD-6.0/atari/binary/sets/comp.tgz) = e2f1fbee6aa542a8b2d80cb2eb4b593fa13a4dae +MD5 (NetBSD-6.0/atari/binary/sets/comp.tgz) = 46cdf183c47138a86c07a43cc4c365d7 +SHA1 (NetBSD-6.0/atari/binary/sets/etc.tgz) = 7e13a9c53246d90a86a0db1a3e38ade70705402d +SHA512 (NetBSD-6.0/atari/binary/sets/etc.tgz) = d751e14266428861f1ef067f02c8e4f79047e3c482f9b89ca44e880ea71ef66de3792d03f4b3704fc98bd8c9ff17cbdb42fa4c4cf3dccff9a94e88662a9035bb +RMD160 (NetBSD-6.0/atari/binary/sets/etc.tgz) = f09fa0ba9766e3cbaf7eb0f59f32dac370d37f14 +MD5 (NetBSD-6.0/atari/binary/sets/etc.tgz) = 42096354bae512677af5f6d5c9a8484c +SHA1 (NetBSD-6.0/atari/binary/sets/kern-MILAN-ISAIDE.tgz) = c623eff071500b740c875a6984194d2826ab66c1 +SHA512 (NetBSD-6.0/atari/binary/sets/kern-MILAN-ISAIDE.tgz) = 25f68ad0b3a910cad6f8d8a7cc232a3e6e71ea381fa8cefd342ff3c18c869abdcdfa517984c54ffcdf72e7393b79aeff78467137d6729447042233a55297bfe7 +RMD160 (NetBSD-6.0/atari/binary/sets/kern-MILAN-ISAIDE.tgz) = 16cc868818532530f4441eed778a26b98ba06190 +MD5 (NetBSD-6.0/atari/binary/sets/kern-MILAN-ISAIDE.tgz) = cc65ece6a5e66a5c1f0aa67a24bb1726 +SHA1 (NetBSD-6.0/atari/binary/sets/kern-FALCON.tgz) = 4e7e28bad7354a7bb7fdde4f608340c4907b4453 +SHA512 (NetBSD-6.0/atari/binary/sets/kern-FALCON.tgz) = 24d5df6a74be2fa65016ab03eb11bcd6dbab11ebc33b0ab936685345ff54fe518b6b87171c93c4afab54b0374fb9d5ffa29390a34dd218b400e985dfeae8d147 +RMD160 (NetBSD-6.0/atari/binary/sets/kern-FALCON.tgz) = 82c44f12a090c11dd2b7de11b8b9ae95fa74ed08 +MD5 (NetBSD-6.0/atari/binary/sets/kern-FALCON.tgz) = fea878ea06b74eef20f60e192539f033 +SHA1 (NetBSD-6.0/atari/binary/sets/kern-HADES.tgz) = 24a828836e47ffe647f8a16b1fd0469a9ee62f03 +SHA512 (NetBSD-6.0/atari/binary/sets/kern-HADES.tgz) = 8bbc2397d01594b89515abea27fa58e9ce7dbda5d2f9468b5bc46576d858395c11e4e1d6a9c25dd9b7d5ddb7ac2c2fd2208d95274f9ce7519fb470cbf08da2ae +RMD160 (NetBSD-6.0/atari/binary/sets/kern-HADES.tgz) = ae93fdba82eecea06486ad88927f25fe1013803d +MD5 (NetBSD-6.0/atari/binary/sets/kern-HADES.tgz) = 244b09181178cc0b51c79ad7568f4d9e +SHA1 (NetBSD-6.0/atari/binary/sets/kern-MILAN-PCIIDE.tgz) = 0269a5f553ad95565fb5092460fbefb4567afa27 +SHA512 (NetBSD-6.0/atari/binary/sets/kern-MILAN-PCIIDE.tgz) = cd74cbc52c0357b9af3290dd02362e5561202c14d58bad0d65b96c84361be2e774c9c58b5e38ca9523a7e796d778330cf257f8e2482bf8153e7a43c167e7c392 +RMD160 (NetBSD-6.0/atari/binary/sets/kern-MILAN-PCIIDE.tgz) = 87ac890b25b9bacc28ce600476add0d6fd8aba03 +MD5 (NetBSD-6.0/atari/binary/sets/kern-MILAN-PCIIDE.tgz) = f18391129e4495470783e0a1d8467a81 +SHA1 (NetBSD-6.0/atari/binary/sets/kern-SMALL030.tgz) = fff933858b1ef2c086ce99631195c2e89714b540 +SHA512 (NetBSD-6.0/atari/binary/sets/kern-SMALL030.tgz) = 40458f1b8455fcd8fb3d01dc52815294705ab3752a5952ce93de01c5b7fb553d5aa0aaff4d9124d46e43d318ed6289c336e0a73470d7471fe4989877cae347a7 +RMD160 (NetBSD-6.0/atari/binary/sets/kern-SMALL030.tgz) = 08e49adb3414a2c4490b143865dcf2f0ab3ff337 +MD5 (NetBSD-6.0/atari/binary/sets/kern-SMALL030.tgz) = f0aee544f1a3c894e71ff07e1ab135a7 +SHA1 (NetBSD-6.0/atari/binary/sets/modules.tgz) = 8ea8801011d50b52e637ee0cb1b94fdbf79b9de4 +SHA512 (NetBSD-6.0/atari/binary/sets/modules.tgz) = 6f002bf0695f00d06ce7f43f3087d6c06949b5df8e33baf0b8b30ac18e72700445dcfeb74b51c16fab32e63e537c10bf696bfdb31ab8b08d25c9189075cd3673 +RMD160 (NetBSD-6.0/atari/binary/sets/modules.tgz) = 2bf65897ea1432bac2666df1b221821a5a0642a5 +MD5 (NetBSD-6.0/atari/binary/sets/modules.tgz) = 4dda2688a56fa0774342c63c367c8ec6 +SHA1 (NetBSD-6.0/atari/binary/sets/tests.tgz) = 88a32113d4d6d34b29a94e69c0e4510b51e7e059 +SHA512 (NetBSD-6.0/atari/binary/sets/tests.tgz) = 53fa49988eca04a409dad693f26d5445cdafa9ff69ac918583849d9c6726278b9f0d2fd0da23c05e73d23453970eaadb7b233d951b430c1b7b3ca1b05bab5a24 +RMD160 (NetBSD-6.0/atari/binary/sets/tests.tgz) = ab9f0395fd5d0d1a732000d07e71efe3860f9a32 +MD5 (NetBSD-6.0/atari/binary/sets/tests.tgz) = 213a94d65400a854c2260e98f6150df5 +SHA1 (NetBSD-6.0/atari/binary/sets/text.tgz) = de8e33381d0714b33aab422c2aa5841352941712 +SHA512 (NetBSD-6.0/atari/binary/sets/text.tgz) = bf15a081319d8ce62cc14f465bce3b204bc9a5f57f7ed9d163cf71a9422eeec5ff0e84de7c43d0fc503e9422283e2f99e1e48ee5ccb9224effdc2e3ba70f31db +RMD160 (NetBSD-6.0/atari/binary/sets/text.tgz) = 387ade3ddcc90bd7b6174deeb24bd8cc6a818e46 +MD5 (NetBSD-6.0/atari/binary/sets/text.tgz) = 937c56219d0ec6a96aef98533e10b569 +SHA1 (NetBSD-6.0/atari/binary/sets/xbase.tgz) = 07c1478cf8a0e4b7ee4b5e49841966fe17f3d797 +SHA512 (NetBSD-6.0/atari/binary/sets/xbase.tgz) = 54d845bc341dc68debf004659d2dcd753604de16e896bceabe6587bfa2934bd5b81b19936c3635cb61dbdee4b4d571603659cd6ae8206ccdaa345f3779e4a83c +RMD160 (NetBSD-6.0/atari/binary/sets/xbase.tgz) = 6a3aba94b4acef9e311f61c1acc96b33c8707ea8 +MD5 (NetBSD-6.0/atari/binary/sets/xbase.tgz) = e02f145dcfd9f7d1c7be166b28559094 +SHA1 (NetBSD-6.0/atari/binary/sets/xcomp.tgz) = cea8de3b7820897ee8270ae3b591fb602e0028d9 +SHA512 (NetBSD-6.0/atari/binary/sets/xcomp.tgz) = 9e6344200d3ba54e29db576b9f7c0c1d2465cbda8b8a05d015596e2b162c207453cfe0ddc7f9d55bd8463bf2c200c2dd43b4ec34c30635fc0923a0d31c2a8ff8 +RMD160 (NetBSD-6.0/atari/binary/sets/xcomp.tgz) = e64e955294f627c722087a4d1e62a6d646028a37 +MD5 (NetBSD-6.0/atari/binary/sets/xcomp.tgz) = 870efcab1ee55d57351c55ac3c412dda +SHA1 (NetBSD-6.0/atari/binary/sets/xetc.tgz) = 64dca98d1263e3d78ef7e240c9975e9077356ce0 +SHA512 (NetBSD-6.0/atari/binary/sets/xetc.tgz) = 1e76598c460681b43f2c5b19f2f4af9efeed6ce16aa8bb4d34f99083ee46cf6c5c31c0aeab974a723a3338c3a9ab1a50ad273061f9f02870d9741ec8809ce0cb +RMD160 (NetBSD-6.0/atari/binary/sets/xetc.tgz) = f147db5da2954155dbc754963d02f309ab41e923 +MD5 (NetBSD-6.0/atari/binary/sets/xetc.tgz) = d23248d3d92350124d8e9e869b28a5f7 +SHA1 (NetBSD-6.0/atari/binary/sets/xfont.tgz) = ad9fb5958debad82e953bc2b1e7e53292d70463b +SHA512 (NetBSD-6.0/atari/binary/sets/xfont.tgz) = 789529bdf38abda3b00e1db3cffc12272af8ec7f7a52855e0ef5af09ac7cea8639b407265ee6082809127b3bd1b673d686d967c987be6ac12be3825f9531933e +RMD160 (NetBSD-6.0/atari/binary/sets/xfont.tgz) = f060722e795db40bec2c283ecbb5f7bdbb688ce0 +MD5 (NetBSD-6.0/atari/binary/sets/xfont.tgz) = 1b83f33dd3e43db09d0b55502a7b347a +SHA1 (NetBSD-6.0/atari/installation/miniroot/prepare.fs.gz) = c4e92cdcb08838b9fa5dc32fb1bd923dd2b97291 +SHA512 (NetBSD-6.0/atari/installation/miniroot/prepare.fs.gz) = 4c25bd0fa0c584b09c2b0a2f9a4a67e942d9a16d9646f1364c71b8bf24326902fae74dce17ee60c81261777ac27e69c2ce4988779ac604a6ac6ebbd4636698d6 +RMD160 (NetBSD-6.0/atari/installation/miniroot/prepare.fs.gz) = 247f6e13edeb6272ceeed462d8729d5e27db000b +MD5 (NetBSD-6.0/atari/installation/miniroot/prepare.fs.gz) = e99c7d5da695d99c717db4585cac009c +SHA1 (NetBSD-6.0/atari/installation/miniroot/sysinst.fs.gz) = 353039d699408734197b1a5ecc2490310269e23f +SHA512 (NetBSD-6.0/atari/installation/miniroot/sysinst.fs.gz) = bd8f6ce4115a98b026fc906c1259ce8ea91d51b97ac44190362a03154ad12c05419d848daf27749a17f0e255b9cb01d2ccae81e75f634825865b95032e5e634f +RMD160 (NetBSD-6.0/atari/installation/miniroot/sysinst.fs.gz) = 3f866900d10efc89f1f22e8ab6099f26d79cb5f4 +MD5 (NetBSD-6.0/atari/installation/miniroot/sysinst.fs.gz) = 4fabfb561929af7e667fdf39a64e58dd +SHA1 (NetBSD-6.0/atari/installation/misc/file2swp.ttp) = 9aabfba1673d710445ce4a151e070cd00a364795 +SHA512 (NetBSD-6.0/atari/installation/misc/file2swp.ttp) = d522703bab622aad1f125bf076fa58ea8a309c34425d188df8130298f5af0ccf8d0b0980ddbb90bff86e73cf11d082081f5d0cbe5e8dba68fdc87c9fbdbe2da4 +RMD160 (NetBSD-6.0/atari/installation/misc/file2swp.ttp) = 5bc12b2214b90eefc315f50321b072f3359443eb +MD5 (NetBSD-6.0/atari/installation/misc/file2swp.ttp) = b2e39863389322ab0834a30a58fbe553 +SHA1 (NetBSD-6.0/atari/installation/misc/aptck.ttp) = 9a1b1b99bd6b50281cb1a1416f854b1d1e0909c4 +SHA512 (NetBSD-6.0/atari/installation/misc/aptck.ttp) = 90fedb40ba1ada8a28b228c0ad34ce9e400b3f9985d69b52345df1e29c7b9b2fd0ceafe1ae91cab0095f3f24ec8bbb274e2f514e351b39eeb8591d3c5ec46d03 +RMD160 (NetBSD-6.0/atari/installation/misc/aptck.ttp) = e399308e499e2e859eba1fc190208537421e407a +MD5 (NetBSD-6.0/atari/installation/misc/aptck.ttp) = 5061a34d4cd283af586c5f382b546a82 +SHA1 (NetBSD-6.0/atari/installation/misc/chg_pid.ttp) = a989a7318087ebccdb92ea9c84e81a8fcb1d2bd3 +SHA512 (NetBSD-6.0/atari/installation/misc/chg_pid.ttp) = 15dca31b0555023ba6e2b04e6bca504adddcc56177f6224a2757d8784ded4a53fd5cf68b3dd5e794b46bcfba69d199dd430aa9379ed565a7aff4c360855cc4cd +RMD160 (NetBSD-6.0/atari/installation/misc/chg_pid.ttp) = fef62601213fdafa60099375eaed9ea23163e165 +MD5 (NetBSD-6.0/atari/installation/misc/chg_pid.ttp) = c414114be1b45d1b8abcd41091fb0c6d +SHA1 (NetBSD-6.0/atari/installation/misc/rawwrite.ttp) = 18c663ff37bf90130bc6eeefd3aabfcd632c654c +SHA512 (NetBSD-6.0/atari/installation/misc/rawwrite.ttp) = 259903e1e3439b3a3d128a18a597ccb6ccec507bc6b1c449445e7e00c4e0d37e436ba2be0cdb71a7a756c30c2a6406cffd3bef0631b2083a2f0402ab322dbf96 +RMD160 (NetBSD-6.0/atari/installation/misc/rawwrite.ttp) = 3b66c3e7f84325e3be39c15e2a597d2bbd233a79 +MD5 (NetBSD-6.0/atari/installation/misc/rawwrite.ttp) = 20458ba9d4f2fae37607648aeb92bf71 +SHA1 (NetBSD-6.0/atari/installation/misc/gzip.ttp) = 2f3c87cac323a1641622ed960d7ca3df6d8e92ce +SHA512 (NetBSD-6.0/atari/installation/misc/gzip.ttp) = 37be09560542fd55afebe8f3a07a76d4121a49c5d8771107a6065dbe55c3d8e33ca25326ffdecb38ceaba0e5b6af33f78f92ecf2600169779b5d7282f74335a2 +RMD160 (NetBSD-6.0/atari/installation/misc/gzip.ttp) = 8e9dbdb381f2b7ebaf01597bca73ba920e18427f +MD5 (NetBSD-6.0/atari/installation/misc/gzip.ttp) = e27e5b3c585ad0a96daaaa810b56f5ef +SHA1 (NetBSD-6.0/atari/installation/misc/loadbsd.ttp) = c7f08ef85b1b3120061b3b651456cd23f8937c16 +SHA512 (NetBSD-6.0/atari/installation/misc/loadbsd.ttp) = 2b645062a84fe5892c3d424d181dd6ad11f134c4a6728b4ca9a67f1912642daabdfaecdf7af985b4d4907d93adc1b72ed86a5cf9b57de42e9213582ec89a8723 +RMD160 (NetBSD-6.0/atari/installation/misc/loadbsd.ttp) = 802c240f7069d79c0432b28dead7884bc4a06d38 +MD5 (NetBSD-6.0/atari/installation/misc/loadbsd.ttp) = e5e92b220890c5ca942d0c878fd090ca +SHA1 (NetBSD-6.0/atari/INSTALL.html) = f71f76494a6bf37c8aefe74e698838c1a03b14c0 +SHA512 (NetBSD-6.0/atari/INSTALL.html) = a12b9739f7918dd22bb0434c3d1c41c5031454fd6dbcb53df4eca669b9b4bc918c1f8df379bcac46204664dc521a049b5c39b4151f207a4a22b19b436917fd35 +RMD160 (NetBSD-6.0/atari/INSTALL.html) = f634ad4adfaa1002f352d703118aba204cbe4f60 +MD5 (NetBSD-6.0/atari/INSTALL.html) = 7eac9b0603de1d7d718b994c92b7a229 +SHA1 (NetBSD-6.0/atari/INSTALL.more) = 6ba2460611e6f92531b9ae9d28f4c68d302b9dc5 +SHA512 (NetBSD-6.0/atari/INSTALL.more) = 718766711a583a0539790a3fa7046f845a15f53dd1cd1f0ddadea939158256b3fbf5dced1a88ea592ded2685f0fda81984d6cb137f26f7b543aded6c7c1ca6a8 +RMD160 (NetBSD-6.0/atari/INSTALL.more) = 8bdd7c42fa93913bd14d5ab80457394e289f8c03 +MD5 (NetBSD-6.0/atari/INSTALL.more) = 19adcdce47ce4b9070326b433afe5a3a +SHA1 (NetBSD-6.0/atari/INSTALL.ps) = 2d9874be06bf612885e3f19fc37635b0c421f52e +SHA512 (NetBSD-6.0/atari/INSTALL.ps) = 0dd3a09f0a91403f412aa3650847c3512db2ac3d36d0133ac924db74d07b59607c9f57df7fd0df4a3652adbba4842f6b6afa01c07cc4a06c36623ad9c60a9ca3 +RMD160 (NetBSD-6.0/atari/INSTALL.ps) = 83f619a939ef01654f3e3bce7f7ddea0b88828bc +MD5 (NetBSD-6.0/atari/INSTALL.ps) = 73fd3b04168f78f2de31b91190851ba9 +SHA1 (NetBSD-6.0/atari/INSTALL.txt) = 711ce58ce059429925a6e08ad178569c5e00a00d +SHA512 (NetBSD-6.0/atari/INSTALL.txt) = b837d76a7e0d754c09fff90845906ec6a1dc5ed77832b91442d5a9ec3608f5e6785782ff1debe3b145f23ba382c5472abec75f49055859bc715caf713941cf41 +RMD160 (NetBSD-6.0/atari/INSTALL.txt) = ecd373463a1cfd5b5399cb3ca0204362ddb22be2 +MD5 (NetBSD-6.0/atari/INSTALL.txt) = f6b564115bd3ae1a28f79dd879fe8ce6 +SHA1 (NetBSD-6.0/bebox/binary/kernel/netbsd-INSTALL.symbols.gz) = bdb282bf1fce2a0c48cf661a68b16fb7663859df +SHA512 (NetBSD-6.0/bebox/binary/kernel/netbsd-INSTALL.symbols.gz) = c476616f879c94a8135889c4691ca927896c74950c16543039a74e4befd918619845f31e519cb452bd215d8ca4fa1acd697f9867810f4961d517f7803f7e2c33 +RMD160 (NetBSD-6.0/bebox/binary/kernel/netbsd-INSTALL.symbols.gz) = dbb18f3fb59483723599306093a562a45f23392b +MD5 (NetBSD-6.0/bebox/binary/kernel/netbsd-INSTALL.symbols.gz) = 582ae8bf879f7bc42d24bf114a5d6a5a +SHA1 (NetBSD-6.0/bebox/binary/kernel/netbsd-GENERIC.gz) = ecfa395d442d86acbc8bbd080c04a8137012138c +SHA512 (NetBSD-6.0/bebox/binary/kernel/netbsd-GENERIC.gz) = b48b213c4ffd06180d1272a65e27ec0ed539e731e07aea29d31f6c939fef99e1a965c42e2fdd99daad1e8ee543c99a02c420fbcf6531d47e961e7b295150fdb9 +RMD160 (NetBSD-6.0/bebox/binary/kernel/netbsd-GENERIC.gz) = 0b01e797fe821429603d9252035e7425f388046e +MD5 (NetBSD-6.0/bebox/binary/kernel/netbsd-GENERIC.gz) = 22289b3d7d60df27fd0ed86731ab77bf +SHA1 (NetBSD-6.0/bebox/binary/kernel/netbsd-INSTALL.gz) = 8721973ccd6399bf563bdb266d9e5316e1ef98ed +SHA512 (NetBSD-6.0/bebox/binary/kernel/netbsd-INSTALL.gz) = 5390ebe49a1d50d2ba42e529c8fb2c23606e4650cd3225783809ee4dee6013f60cf7dbb347fabf48f3d7ce98ededef37cfc8d5de5c07ad7462dacc668243f429 +RMD160 (NetBSD-6.0/bebox/binary/kernel/netbsd-INSTALL.gz) = 8228a5df5239737e7ba039b84303c4cd491e26f6 +MD5 (NetBSD-6.0/bebox/binary/kernel/netbsd-INSTALL.gz) = 9165b1f4313cc543868d7ab7f6eff5ad +SHA1 (NetBSD-6.0/bebox/binary/sets/man.tgz) = 899b9d8242e983a5110ab755651c24f709b5af67 +SHA512 (NetBSD-6.0/bebox/binary/sets/man.tgz) = 410999db110d710f4bb498c3d7ae7adc62170c7c2f470ce189c92f6c436c5ea96149659c631ef0b5605caaa025d97dfe1c07c428d86f51239657bd6b71717b15 +RMD160 (NetBSD-6.0/bebox/binary/sets/man.tgz) = c1270f68c6d41b351877f71f0396ac34877dfc8d +MD5 (NetBSD-6.0/bebox/binary/sets/man.tgz) = df4db2bbfa39ef6a4a215d949653d04a +SHA1 (NetBSD-6.0/bebox/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/bebox/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/bebox/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/bebox/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/bebox/binary/sets/kern-GENERIC.tgz) = d4e8dde09eeb9886e1d84573d136ea92db147201 +SHA512 (NetBSD-6.0/bebox/binary/sets/kern-GENERIC.tgz) = bb375fbcd379a02ccb0f770ae22aeb02f90fda95be2864f085bd46ad58c670e5fda2792b9af8acb5972398a4056ef4ca8d95367f20f57e1258401d1b02d29abd +RMD160 (NetBSD-6.0/bebox/binary/sets/kern-GENERIC.tgz) = 2726cf7d2e1fa0278bb78a1f1d21e3a6846bec27 +MD5 (NetBSD-6.0/bebox/binary/sets/kern-GENERIC.tgz) = 17e1bdb7465cc8aff08f41a81a37913e +SHA1 (NetBSD-6.0/bebox/binary/sets/base.tgz) = cb3438d686bc37c67ef3506e7b5f14af708d0f69 +SHA512 (NetBSD-6.0/bebox/binary/sets/base.tgz) = caaf5501269c91599fe8a6315a14bd33776549df0d82d34e516b846df3ace79c1b3a77ef745da87fca1bcc822201765366a373c2d9e29195b4f76bc954f6903e +RMD160 (NetBSD-6.0/bebox/binary/sets/base.tgz) = 9eaed756de31f7ef1f390895400ff57d90b6936f +MD5 (NetBSD-6.0/bebox/binary/sets/base.tgz) = 844ca078de04b6965afc9d6840712a87 +SHA1 (NetBSD-6.0/bebox/binary/sets/comp.tgz) = fa35a56729cf7a8957a24482e5855629b63da9ca +SHA512 (NetBSD-6.0/bebox/binary/sets/comp.tgz) = dae46ff9a1b0ec32444bf93501e5ce5a003556ec6e057c1a85ef63d6f18fab00370fb5c8c6dda14da7222032f26aded43ff2ba4619df58f13d773f3c55a3203a +RMD160 (NetBSD-6.0/bebox/binary/sets/comp.tgz) = e23f0ffdecc624bd584b1bdafcc1919c0a6b4bee +MD5 (NetBSD-6.0/bebox/binary/sets/comp.tgz) = e24aedf775e35faa7b0be771def8e964 +SHA1 (NetBSD-6.0/bebox/binary/sets/etc.tgz) = 7955187dd8c102acefc90e649d70bf87334b8c15 +SHA512 (NetBSD-6.0/bebox/binary/sets/etc.tgz) = 3dbc921b6f58296fecb96ac7a0497f4de1f84179128afa3fe2f0a9260399934f659c53346ab55dbf387f19e348e4cf441506b2b92a72f0a2de71d59701289e34 +RMD160 (NetBSD-6.0/bebox/binary/sets/etc.tgz) = 7426566e042dd69397282ea85d9999952d57fde4 +MD5 (NetBSD-6.0/bebox/binary/sets/etc.tgz) = 8980eb4fe0883bbcf7d2001bc9d705a4 +SHA1 (NetBSD-6.0/bebox/binary/sets/games.tgz) = 780b002a35471789a68ee7be17362c60e96fa5fd +SHA512 (NetBSD-6.0/bebox/binary/sets/games.tgz) = 954365033c924762b524f0f1e4732216b4c661697336b0947943f05a1d1e0ecc12c1679c1c5d7572e1a15a7296bd7b14d31749917ef03a2b097b94bfa0f16837 +RMD160 (NetBSD-6.0/bebox/binary/sets/games.tgz) = 9b237eefee5dc43fb3fffca5a2aa390fb2c3031f +MD5 (NetBSD-6.0/bebox/binary/sets/games.tgz) = 337e6739c192296cac92b610d0ad6945 +SHA1 (NetBSD-6.0/bebox/binary/sets/modules.tgz) = 14ad320114a249b1ed676832524f773dae772798 +SHA512 (NetBSD-6.0/bebox/binary/sets/modules.tgz) = 1aa3a619fdff5824c904495352248fe990130b9ce9d9a3cd443afd2f088acf7048150de54f1cc304ccf08587fd91f7614521a0b9be96fc7768c06e0a80ed72ac +RMD160 (NetBSD-6.0/bebox/binary/sets/modules.tgz) = d1df79e00026a19f724c6115055c611c07d592cb +MD5 (NetBSD-6.0/bebox/binary/sets/modules.tgz) = 8dc1d2dbc89e5e6aa3e04b0033cc4a22 +SHA1 (NetBSD-6.0/bebox/binary/sets/tests.tgz) = 979d26c8e2e5283c416a2e4f4b603acdb43756a0 +SHA512 (NetBSD-6.0/bebox/binary/sets/tests.tgz) = e726187887b9429ce3bd39fb51e7703792f288c47eb9c0f20b85e1a2be4f6448bc3e73919c5d28c28f400ada5b0b024b647079a3670f0a2153aff9b7f5738f13 +RMD160 (NetBSD-6.0/bebox/binary/sets/tests.tgz) = 5cd1c8a42ae7a6ef706de0fcae5292db026efa9c +MD5 (NetBSD-6.0/bebox/binary/sets/tests.tgz) = 122dc0ea7ebc7ca924301e406ef6e002 +SHA1 (NetBSD-6.0/bebox/binary/sets/text.tgz) = 30f7a17a6d9b03c7ce09bce6341895ac27c2f7b4 +SHA512 (NetBSD-6.0/bebox/binary/sets/text.tgz) = e258a9a741918d6bd8de1e10cff771541b1f1191af776101ff38c722fb037d44d51879d45a5a90342c7e2c21d36cbf5a9a6f5f1a047e61bb18609385381fc3ae +RMD160 (NetBSD-6.0/bebox/binary/sets/text.tgz) = 6dee36ded12f84c00d7c82912da8755b0d04d497 +MD5 (NetBSD-6.0/bebox/binary/sets/text.tgz) = e1e3ed8f872b4dd51b555e9100ed6173 +SHA1 (NetBSD-6.0/bebox/binary/sets/xbase.tgz) = 03f73933d3719ef967af4a003282e1d56453e3f5 +SHA512 (NetBSD-6.0/bebox/binary/sets/xbase.tgz) = d90e373c143773a93e430058628bc65161e6c25c725fcb279ac0765edcee8e9cab4ff55fa1d99ea66ccb6ca06133145eaaa77f2c26a082c27a53e2e10a19cfdb +RMD160 (NetBSD-6.0/bebox/binary/sets/xbase.tgz) = 0fe0422c310a56e55e2d5e4b85e8d8a41daaaf4e +MD5 (NetBSD-6.0/bebox/binary/sets/xbase.tgz) = 7120010c15d5f84927963c780c9197e9 +SHA1 (NetBSD-6.0/bebox/binary/sets/xcomp.tgz) = 1c7522ec79f661a84912a5213ed835d400e108f7 +SHA512 (NetBSD-6.0/bebox/binary/sets/xcomp.tgz) = bfc0d388d18e14cfe99e6bcbda22e4b11e5082b0acf5b314c6f0275823138c35d1a16c3ab3e3fc27e5a04228d6380ef3c2f45dc807715db2c1de689e5674a397 +RMD160 (NetBSD-6.0/bebox/binary/sets/xcomp.tgz) = 23c8e8bb0e2f0708d2bd464468196f4d74359302 +MD5 (NetBSD-6.0/bebox/binary/sets/xcomp.tgz) = b6fb09a621ed2138ed674838c72ec64a +SHA1 (NetBSD-6.0/bebox/binary/sets/xetc.tgz) = a14b23868bf88e59f5a845bd86cf4af61522f482 +SHA512 (NetBSD-6.0/bebox/binary/sets/xetc.tgz) = a2aee6ee11a89b3fe3b5834502dfd1a50aec7bdcc0f424b3e9d19400370b922258d77a979dae0bd87f8e55df8da9b98f8bf88a73792b1ca6a8915e5cd08777aa +RMD160 (NetBSD-6.0/bebox/binary/sets/xetc.tgz) = bf37bf09d79777922f344d6b52f69d50c708b64c +MD5 (NetBSD-6.0/bebox/binary/sets/xetc.tgz) = 837bbc31ba2a81d2610adf225551a61a +SHA1 (NetBSD-6.0/bebox/binary/sets/xfont.tgz) = e44a6f29bfb3a947ca7d916c7556386a900cb3ee +SHA512 (NetBSD-6.0/bebox/binary/sets/xfont.tgz) = 9ca97fbe1d40c26938f5a84f09bf273f132b40a82f3ef548295901840155ca45c68ce0d0d980f7fe63bd8acb57be487fcc5f81e61ae4f9765151333a84636a43 +RMD160 (NetBSD-6.0/bebox/binary/sets/xfont.tgz) = e9e153af690a96523a3b7af0a314e1104fa694af +MD5 (NetBSD-6.0/bebox/binary/sets/xfont.tgz) = 1323ead1d7e9f69f6790c1eb836ec117 +SHA1 (NetBSD-6.0/bebox/binary/sets/xserver.tgz) = 05c93b9d2b3774b6cb71b9d829f5d21860f549ae +SHA512 (NetBSD-6.0/bebox/binary/sets/xserver.tgz) = 28c97ffdd74c9a2d1d060ce356fd6951d377b61b7fa691c01a150472b082dd027b2be909508ee3370ec59d89bd9c5e12914b3f34feccc6c7904a9ce49869d7d8 +RMD160 (NetBSD-6.0/bebox/binary/sets/xserver.tgz) = 52564d70781876abda7f16a678791c8b3753f53b +MD5 (NetBSD-6.0/bebox/binary/sets/xserver.tgz) = aeca26a6ae798bcf849e7bd4df423614 +SHA1 (NetBSD-6.0/bebox/installation/floppy/boot_com0.fs) = 1fc015fd100d0518a57e3e7a30e336be1000c098 +SHA512 (NetBSD-6.0/bebox/installation/floppy/boot_com0.fs) = 674ae651d28163eae5f02f78e427d7291e4b977fff90036b1d6870f572e63b1963ef83453ff9da1d49ebb707ff918c0f64889bc0f7d17072690aadd65837e14a +RMD160 (NetBSD-6.0/bebox/installation/floppy/boot_com0.fs) = 1f59e43c9e6b08ccd63506a5179fdd2a365151b8 +MD5 (NetBSD-6.0/bebox/installation/floppy/boot_com0.fs) = 300dd58c4641cf1fda257074b674937c +SHA1 (NetBSD-6.0/bebox/installation/floppy/boot.fs) = 8a5770fb10efc7d7c453138ca866b93e2287607a +SHA512 (NetBSD-6.0/bebox/installation/floppy/boot.fs) = ffbb187efcdeaaf5018827b619abe00ee42aedabab188a443b494c3a5ab94d21fea4761409d9eb23b5a37d5daee602baa838b1d052e1f66b5380a09ed446fb89 +RMD160 (NetBSD-6.0/bebox/installation/floppy/boot.fs) = 58430893606678b17f132c3f3559dd4d30a7246d +MD5 (NetBSD-6.0/bebox/installation/floppy/boot.fs) = f807ed8a7b25aa9fc9c08637a5188dbf +SHA1 (NetBSD-6.0/bebox/installation/floppy/boot_vga.fs) = a922c42dd39babfb12443b7d122526f207969577 +SHA512 (NetBSD-6.0/bebox/installation/floppy/boot_vga.fs) = 4f547ce92d72d826253aafab92f9df42b5dba05031ab4d8537fcd40291a703b06eb2e972729c8e703f4e4e0f75d2a0ee2e2f69e8f5d66735f2932089bf1ec7fc +RMD160 (NetBSD-6.0/bebox/installation/floppy/boot_vga.fs) = c999c7705d258c4b294f0905ba519ec86b7f34f3 +MD5 (NetBSD-6.0/bebox/installation/floppy/boot_vga.fs) = 343aba7dd2584f3945d1fb539a72dc82 +SHA1 (NetBSD-6.0/bebox/installation/floppy/kernel1.fs) = 8af8e65d2919686db6121c68347b8541991e373a +SHA512 (NetBSD-6.0/bebox/installation/floppy/kernel1.fs) = 91e8df83298ea05c0bec3920d491ff2277d2342a803f84b7393a160ae4a108b84b7d21a0fbf2875d9248287bf047d075e4d33c582a6083ad276e974139635172 +RMD160 (NetBSD-6.0/bebox/installation/floppy/kernel1.fs) = 169667f00c760604c7302d9299448769c8e07b9f +MD5 (NetBSD-6.0/bebox/installation/floppy/kernel1.fs) = 84f875ee3ca1633777ae9db0acd4e8ae +SHA1 (NetBSD-6.0/bebox/installation/floppy/kernel2.fs) = 12e804736be0c389da64cd888c3ebfeeec2a1078 +SHA512 (NetBSD-6.0/bebox/installation/floppy/kernel2.fs) = 151b541d723ea1c09bc93cd2cc6abc6a04d0adff1b20c24f53c5b0a8b72462614e64912c6b21dfc9bf4676e2a60a03cab40b44fa23f7dd70183116b4b55f6725 +RMD160 (NetBSD-6.0/bebox/installation/floppy/kernel2.fs) = 159915fd391a03f34782322760d31e1966669b50 +MD5 (NetBSD-6.0/bebox/installation/floppy/kernel2.fs) = 229b4ef55392a3b8c25b6b53691b5fbb +SHA1 (NetBSD-6.0/bebox/INSTALL.html) = 836f306d6806f97de5e27bce454acd5882b63090 +SHA512 (NetBSD-6.0/bebox/INSTALL.html) = f903a8d35baabfc1ecf5107a6b321930a4b6966d25e8064c6a14d19ddcf67906fbfe5f227487e4120a876dfdad3ebf4664d3f22a14bed7d970bf3f29ffd2c7b2 +RMD160 (NetBSD-6.0/bebox/INSTALL.html) = 4ad2f27fa58d87d0a1b22c6282894af983f4e89a +MD5 (NetBSD-6.0/bebox/INSTALL.html) = 8015ad9791e90ca1c944d1ecaab10a88 +SHA1 (NetBSD-6.0/bebox/INSTALL.more) = f00ff910b68e2f4f98bfe3b08c6713a5d27c308c +SHA512 (NetBSD-6.0/bebox/INSTALL.more) = 2ab02d1a9d69c28d6b0248fd75c3395b5bc6fdefd099c1c8f199c083fc87383478818a152842f749bab553a6420df0c1427820c2b893a47cce693a65db91d175 +RMD160 (NetBSD-6.0/bebox/INSTALL.more) = 357216417da8c0e9fa268285ae401c9b289f56a0 +MD5 (NetBSD-6.0/bebox/INSTALL.more) = 55e950718919e06393d4eec6eeb33feb +SHA1 (NetBSD-6.0/bebox/INSTALL.ps) = 76f8926725f4b4b2c67518ba8a08c7804d8455a1 +SHA512 (NetBSD-6.0/bebox/INSTALL.ps) = b730f63d8d471706dfb44484b7adb22374a51ca8e506f9b848ff7936149bf3f7b1b335b3e061b4c89904f53556bdd9bffba99a9275a5c78299705600adad6eee +RMD160 (NetBSD-6.0/bebox/INSTALL.ps) = 4edf6341d842d3626be2f6e51b9fb1e8e2e2331b +MD5 (NetBSD-6.0/bebox/INSTALL.ps) = 09cc4abbf4039ab00e41994c0e274550 +SHA1 (NetBSD-6.0/bebox/INSTALL.txt) = f826c7a4f2f3500f258f40bb89fd5d996527e6a6 +SHA512 (NetBSD-6.0/bebox/INSTALL.txt) = c8cc1e6e07c502ec0d6d807a67de6ffc943d260e2538d512d4322199e49e70fdcf01cb389455ea6d48655c4a246fa31dedf6c18ec58ef58c6f9b17de068b3944 +RMD160 (NetBSD-6.0/bebox/INSTALL.txt) = 17fb9bcbdd888e110926df401169d8ead0aa1dca +MD5 (NetBSD-6.0/bebox/INSTALL.txt) = f256d74bbee88c7bb349992fd11f975d +SHA1 (NetBSD-6.0/cats/binary/kernel/netbsd-INSTALL.ABLE.symbols.gz) = 6e64a8b0dec1e052750bd03c3e240e2e4678a0d7 +SHA512 (NetBSD-6.0/cats/binary/kernel/netbsd-INSTALL.ABLE.symbols.gz) = bcbaa47e0c29054669a3fccdade1fd64b75934f33cf34ce59675190fd62074920973675f85dc4a6a4973898df0c41b71bab47cde0bd438db97c56a13e3e5fe14 +RMD160 (NetBSD-6.0/cats/binary/kernel/netbsd-INSTALL.ABLE.symbols.gz) = 18c790be97dc94277543ab409b0c46a186fc8ded +MD5 (NetBSD-6.0/cats/binary/kernel/netbsd-INSTALL.ABLE.symbols.gz) = fd246c1c2231766dfcd5307328d6791f +SHA1 (NetBSD-6.0/cats/binary/kernel/netbsd-GENERIC.ABLE.gz) = 837fee4fd025b1b6302e59feb9d0996a5a69069d +SHA512 (NetBSD-6.0/cats/binary/kernel/netbsd-GENERIC.ABLE.gz) = 8a24960901173b604e26992c2dc3b401eb20787952f6b6c0fa070b10c0d3b5a188241b9353c4ef405c4e9864cf200bf97edf692c45e2eede38b858a890fe7b47 +RMD160 (NetBSD-6.0/cats/binary/kernel/netbsd-GENERIC.ABLE.gz) = 68c9d5f9f4278bbcd6431b34d62a4971e953767a +MD5 (NetBSD-6.0/cats/binary/kernel/netbsd-GENERIC.ABLE.gz) = 2f4ae7ec3badbee7e9739207599e1edf +SHA1 (NetBSD-6.0/cats/binary/kernel/netbsd-GENERIC.aout.gz) = 572497febedc95796b46a3bc0aecad740db1da14 +SHA512 (NetBSD-6.0/cats/binary/kernel/netbsd-GENERIC.aout.gz) = 549c46b80cec59bc05d9c06f03fea4cfe1789c0ca51f2a95ab6f37df7b2dd6450f056e8bd60499ae8d96547c36f2ddb3367910d52b397d2ed5188e25424fe174 +RMD160 (NetBSD-6.0/cats/binary/kernel/netbsd-GENERIC.aout.gz) = cbd8947668d7cf78e2074436ef9d0a046a919870 +MD5 (NetBSD-6.0/cats/binary/kernel/netbsd-GENERIC.aout.gz) = 82285aa28d3e972d574d369dc25b5f50 +SHA1 (NetBSD-6.0/cats/binary/kernel/netbsd-GENERIC.gz) = 54e76627b1fd3ee4c32046f4105f5809408f881f +SHA512 (NetBSD-6.0/cats/binary/kernel/netbsd-GENERIC.gz) = ef934d136eccb13da91a086e43c915a52f8206f8fda3237034f9bc03d73fa0147466efd58e231217be5179a8c1e6bc288c55b0c56bc47adb0f7bd45aa89be64d +RMD160 (NetBSD-6.0/cats/binary/kernel/netbsd-GENERIC.gz) = 39d74bb0008f44f71e73ae7deabaa0795b331564 +MD5 (NetBSD-6.0/cats/binary/kernel/netbsd-GENERIC.gz) = 11fb2ce363dc7e39ca3a62b11d2aa62f +SHA1 (NetBSD-6.0/cats/binary/kernel/netbsd-INSTALL.ABLE.gz) = c55e66950e096d68620ed1fc3296f1d557ed45eb +SHA512 (NetBSD-6.0/cats/binary/kernel/netbsd-INSTALL.ABLE.gz) = 32253268b69d201a700dea2a855e966bf9860321e94b99507960b5e6bf870f18f856e4a7e425a236752e48bbf5875ceae38627d2d49e9a63faf0377f75c002c1 +RMD160 (NetBSD-6.0/cats/binary/kernel/netbsd-INSTALL.ABLE.gz) = 7f7bbdcb761251ba78d769e045a53a73e67c2788 +MD5 (NetBSD-6.0/cats/binary/kernel/netbsd-INSTALL.ABLE.gz) = 93e3ff78c78c67a40de296421d949551 +SHA1 (NetBSD-6.0/cats/binary/kernel/netbsd-INSTALL.aout.symbols.gz) = 56742c573641715c2ad92e38a0f3206e4b6b3629 +SHA512 (NetBSD-6.0/cats/binary/kernel/netbsd-INSTALL.aout.symbols.gz) = 41ec7eef2073b8f6fd9e34fbe9670cdaafd65b1712397db855eb44212b17a96addcd31ae62479fac09ff73cb650fa9859aab905c727305f28a6841c30c7df54c +RMD160 (NetBSD-6.0/cats/binary/kernel/netbsd-INSTALL.aout.symbols.gz) = c52d4eb8b33f9562c241dc296f9d9c06ee685e58 +MD5 (NetBSD-6.0/cats/binary/kernel/netbsd-INSTALL.aout.symbols.gz) = c51c51101225f4f260e1ec92aa64f689 +SHA1 (NetBSD-6.0/cats/binary/kernel/netbsd-INSTALL.aout.gz) = 58e8d3c14ca2714bbb91003f533ae5f967f524b4 +SHA512 (NetBSD-6.0/cats/binary/kernel/netbsd-INSTALL.aout.gz) = e2c5f771f02b6d7896841bf5a25efc16b34830ff375e9be1f3911225313c664b7f3a0ac023e5928c2d5fb7ab584f9bde029480b84ce67bd67ee862673cf45705 +RMD160 (NetBSD-6.0/cats/binary/kernel/netbsd-INSTALL.aout.gz) = 4282d861ac62fa542e4496cbfaca087476d60597 +MD5 (NetBSD-6.0/cats/binary/kernel/netbsd-INSTALL.aout.gz) = e64438671861843fdc0fd4c9f324f04a +SHA1 (NetBSD-6.0/cats/binary/sets/games.tgz) = e1d2bb091d8202962133475bc83edb55230b9008 +SHA512 (NetBSD-6.0/cats/binary/sets/games.tgz) = a147fe6d0419d53d5a428802d0bb6c9fa8a84a76c96d7d6d7c0d399e5af3a69240116463549a83d53387b0214ba0207796d7c10228d92a684fe7ff0ece3aec16 +RMD160 (NetBSD-6.0/cats/binary/sets/games.tgz) = 2be515c495548ba5135ff42a75a8ebbfc35ea776 +MD5 (NetBSD-6.0/cats/binary/sets/games.tgz) = 9059a6f2cd41cb58827709c9e9a1649b +SHA1 (NetBSD-6.0/cats/binary/sets/man.tgz) = 899b9d8242e983a5110ab755651c24f709b5af67 +SHA512 (NetBSD-6.0/cats/binary/sets/man.tgz) = 410999db110d710f4bb498c3d7ae7adc62170c7c2f470ce189c92f6c436c5ea96149659c631ef0b5605caaa025d97dfe1c07c428d86f51239657bd6b71717b15 +RMD160 (NetBSD-6.0/cats/binary/sets/man.tgz) = c1270f68c6d41b351877f71f0396ac34877dfc8d +MD5 (NetBSD-6.0/cats/binary/sets/man.tgz) = df4db2bbfa39ef6a4a215d949653d04a +SHA1 (NetBSD-6.0/cats/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/cats/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/cats/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/cats/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/cats/binary/sets/kern-GENERIC.tgz) = 5ca14afa2e8a62cb54d2ae62e3516ffc10b4568b +SHA512 (NetBSD-6.0/cats/binary/sets/kern-GENERIC.tgz) = e0189ff9d057ac445ef5ea45155f0a7045b876f7ddbd912b45fb3ee7f2c8bf83a46d167d9a916214d6cc1de9b825dcf91f35384bd3690f885acb44be5356c625 +RMD160 (NetBSD-6.0/cats/binary/sets/kern-GENERIC.tgz) = 5324b2a4cfd27b7aeee8c2bc2cbb6041669e0bff +MD5 (NetBSD-6.0/cats/binary/sets/kern-GENERIC.tgz) = 6825664fe2f18e25fe7cb307b8f2923f +SHA1 (NetBSD-6.0/cats/binary/sets/base.tgz) = c458481bd58c1d1dca0329bc28de71409c1e4aba +SHA512 (NetBSD-6.0/cats/binary/sets/base.tgz) = 52550865b944057be1c4de1f30cb1ef8bf1b126258a0ef2ff7d2108b562b211149cc05b8397fb7c6142a5276e2636192c54cffbf8d424d528c0bce462f155d49 +RMD160 (NetBSD-6.0/cats/binary/sets/base.tgz) = 7977e28aedfcc3e97ad9e748c6d3c7abd4aa831c +MD5 (NetBSD-6.0/cats/binary/sets/base.tgz) = 2a41824b43d9f6cfee26ea6fe3a04368 +SHA1 (NetBSD-6.0/cats/binary/sets/comp.tgz) = b725c4d09fc5f7ee54c5d800e4c2e12b3af6f669 +SHA512 (NetBSD-6.0/cats/binary/sets/comp.tgz) = e36e73f377ca33d2a76ca25973464ee54c70bafc05fea574fa2edc2060ad93be714a9ee6cb7173b52a75a77b47b49e50dd5b7803fd84afbd6be19b858147d551 +RMD160 (NetBSD-6.0/cats/binary/sets/comp.tgz) = fcc12fec265d939130a40cd2b2d73bc5a97ab1fa +MD5 (NetBSD-6.0/cats/binary/sets/comp.tgz) = 33321cea969922b1a6ec122d03546470 +SHA1 (NetBSD-6.0/cats/binary/sets/etc.tgz) = 89dc5b13c09b5325742e8e4ca8a22857b29a2bcf +SHA512 (NetBSD-6.0/cats/binary/sets/etc.tgz) = f18e1f34fd7b909422e431fa16738b047afa451ea9e7e77bbbcf4fc465835ad4b3b5b145efd2a609130d057e5adab868e544806ad7584947dfb82440e976c6f0 +RMD160 (NetBSD-6.0/cats/binary/sets/etc.tgz) = 81e6058380507732dcc4157e10c849d896fc51aa +MD5 (NetBSD-6.0/cats/binary/sets/etc.tgz) = da8349c012e9f029cef0f909cc466973 +SHA1 (NetBSD-6.0/cats/binary/sets/kern-GENERIC.ABLE.tgz) = c9adc81c86dda4d994d79fd37b7622475310fda5 +SHA512 (NetBSD-6.0/cats/binary/sets/kern-GENERIC.ABLE.tgz) = 5a2c270a700ae0f433afba336f4270c1a9f0646ddc0839318638946f38f23b150775d9f6e2cb91d08ce327f4c2057377e5c27e525277f5c001d1c03fad852ce8 +RMD160 (NetBSD-6.0/cats/binary/sets/kern-GENERIC.ABLE.tgz) = 7c83c750bff69191dc40b6bf34d801cc082f4970 +MD5 (NetBSD-6.0/cats/binary/sets/kern-GENERIC.ABLE.tgz) = 18c1f0b06270fb64a47ffdb95edb7f0e +SHA1 (NetBSD-6.0/cats/binary/sets/modules.tgz) = fd876e3d182e55ff19b6121b07b8e69fa1d0df29 +SHA512 (NetBSD-6.0/cats/binary/sets/modules.tgz) = a9a55cb34e467094be7e72a443b8a449078efaab3adc8a9b1496e45ea6c9fc7d5b3cc7523b30fade9263cb2f90fe9e18825bc6d5acd415a3fbea1c444ec0ed5d +RMD160 (NetBSD-6.0/cats/binary/sets/modules.tgz) = 8c6829a3b9d46c091203f11ae7809fe1087e8fbc +MD5 (NetBSD-6.0/cats/binary/sets/modules.tgz) = fec5cad3f45abd455761405b2b352a1a +SHA1 (NetBSD-6.0/cats/binary/sets/tests.tgz) = bdfb9591316f5c17b8acfff63b0ab895cb9fe3e8 +SHA512 (NetBSD-6.0/cats/binary/sets/tests.tgz) = aaf8d4b6e428dbd0a162cf09d5bbb3273450b4ddacd6cdcb9ba2175cde5276fc30173466a1e394ca2fadb3e92ee7637d9e8fdfdc7f6e59436b9178efc1806b4c +RMD160 (NetBSD-6.0/cats/binary/sets/tests.tgz) = cf4cb18da6b8c46c0648d6c33556dca95035b024 +MD5 (NetBSD-6.0/cats/binary/sets/tests.tgz) = 5f83acde92619b5eb23f3b21c3bdfbed +SHA1 (NetBSD-6.0/cats/binary/sets/text.tgz) = 4434e6febe84969a66d92fdfa147aec4a6f18549 +SHA512 (NetBSD-6.0/cats/binary/sets/text.tgz) = 41206832dff7217dc0f61fa8ed39c7b824bd7f781318317520aaf3b190cf5d8588b5c06a8252fa8318ded7df84a104b9718dbbc4e6d2e3c62c822d79b9be4d3f +RMD160 (NetBSD-6.0/cats/binary/sets/text.tgz) = d7a3c7498b28f79cb6044f4483f6b4970c2d265d +MD5 (NetBSD-6.0/cats/binary/sets/text.tgz) = dbd9391020e7272a288c0c30002cad8a +SHA1 (NetBSD-6.0/cats/binary/sets/xbase.tgz) = ae3b8c01b219ca930ad23427b88601c98fce9ae9 +SHA512 (NetBSD-6.0/cats/binary/sets/xbase.tgz) = a06f8a61a8c61df4aa2f9e0efdaede96e56765552d642ab3f048afeeada1716fbb5a0a5b3f2d511e7a146fa7d173ad0b59d5707a7c9b29216c014ec3911d3d37 +RMD160 (NetBSD-6.0/cats/binary/sets/xbase.tgz) = 032ae59bb4c894f973b3fba09b9c72762f4be5f2 +MD5 (NetBSD-6.0/cats/binary/sets/xbase.tgz) = d021cc89a93acc430e5cad14758b1ef3 +SHA1 (NetBSD-6.0/cats/binary/sets/xcomp.tgz) = 2daa1f374f82e66d62900af2252f72a06f366ebc +SHA512 (NetBSD-6.0/cats/binary/sets/xcomp.tgz) = 803d5501dfcda968a4f098378989cc8186bda8f9dc28af6b9bc591301edfd0dd194922a0d661c75f3ced1fcdbb700e61eeb7bbf5b95ee6ec1111cb8bb9eec933 +RMD160 (NetBSD-6.0/cats/binary/sets/xcomp.tgz) = 4bf6721bd75641fef50dce9cc5781b6991acd0fa +MD5 (NetBSD-6.0/cats/binary/sets/xcomp.tgz) = c78fd7987bf26697dcb6447c6818c8f5 +SHA1 (NetBSD-6.0/cats/binary/sets/xetc.tgz) = 081116c5590415004358c063c13f77a32c0fa5ba +SHA512 (NetBSD-6.0/cats/binary/sets/xetc.tgz) = 129cc55a79bee0d1d821c137fa27ae1fdaa82d71cecbbecd555e7d8ab649dfccbb1c2086575e97ff66bd40a50a34ab5b45233ceb15bc9770044bc776c646d86b +RMD160 (NetBSD-6.0/cats/binary/sets/xetc.tgz) = eb721c7066e0088a6be10b2214fa7227d2b95043 +MD5 (NetBSD-6.0/cats/binary/sets/xetc.tgz) = 7904920faa3acddfb9b635b88789a440 +SHA1 (NetBSD-6.0/cats/binary/sets/xfont.tgz) = f6547d11ac8302fda8b2b992e99f5d8c03ef9f0b +SHA512 (NetBSD-6.0/cats/binary/sets/xfont.tgz) = c38be1439bd2a0b9a10978e1833a5ad243f3d3ed557bb05033aa6c76d1320851663e8819987b4a77c8f4f123820d82cfa950e8e486986686030aa9a40b7577ae +RMD160 (NetBSD-6.0/cats/binary/sets/xfont.tgz) = 401d3e9883c381410c7e45ee3cb1ab72e9fd54a7 +MD5 (NetBSD-6.0/cats/binary/sets/xfont.tgz) = d154b32a82c67ebba30762daad5a37e9 +SHA1 (NetBSD-6.0/cats/binary/sets/xserver.tgz) = 941b1622f43738a9a31860ad6464f2fff35e9f1b +SHA512 (NetBSD-6.0/cats/binary/sets/xserver.tgz) = dbbd41022a86bfd59958a96f821256bec29793952b4adfff10e3974d437e1317b8312662359a27a961d76f4c0ac7e7af9482603d6ab918668174818f9b1c1008 +RMD160 (NetBSD-6.0/cats/binary/sets/xserver.tgz) = 4fb11053b3a0ad7775efdb502bbf8e1198dc0348 +MD5 (NetBSD-6.0/cats/binary/sets/xserver.tgz) = 20c811752f066b472b1f578431f25d42 +SHA1 (NetBSD-6.0/cats/INSTALL.html) = cbe385200e2572a8325f1559ff0b00914b6892f8 +SHA512 (NetBSD-6.0/cats/INSTALL.html) = a62d6cbd6f300d4287f899e76526282ac04a538aedd201754876f8ea906eb3c486e8580b7d373eb6436ffb6c6b0d47273a3999ebfb852b1cecd7d9714931b7af +RMD160 (NetBSD-6.0/cats/INSTALL.html) = 8fd593263624ff1e7a45b7102956094a71f16576 +MD5 (NetBSD-6.0/cats/INSTALL.html) = 50947ae742e64480da9f0f3964789ee0 +SHA1 (NetBSD-6.0/cats/INSTALL.more) = 8343db2afce040778ea31ae38be9700674dc5f02 +SHA512 (NetBSD-6.0/cats/INSTALL.more) = d40356dbe2c728dc51d6cd0efe3857a27ec9b39e2a03a01efe67733debda54b58e768218eba79dd20f97614e4a8c1138362c65acdef1aec922e157bb638f2a18 +RMD160 (NetBSD-6.0/cats/INSTALL.more) = 76588eb4c081058584fc7bd3d350f896177bec31 +MD5 (NetBSD-6.0/cats/INSTALL.more) = a912e620c4899d40ffaf15a00b033920 +SHA1 (NetBSD-6.0/cats/INSTALL.ps) = 06fff86ec204f92418e0050417a548da63a2ddad +SHA512 (NetBSD-6.0/cats/INSTALL.ps) = 31a7ca304e80c80942d5c3b1f055251194981e7e98096fbca7c1d56f6617e5aae082a44702fcbda9cec006823d093973bdf24f1af369c532d72706b5c44243f2 +RMD160 (NetBSD-6.0/cats/INSTALL.ps) = 80c4749fc0e3d9144cae101e3e83709b509eb541 +MD5 (NetBSD-6.0/cats/INSTALL.ps) = aa6a7a310a23fcf771ab49fcec71a77d +SHA1 (NetBSD-6.0/cats/INSTALL.txt) = 59e12295d3e1819f7ff76701baeb4541e637ef88 +SHA512 (NetBSD-6.0/cats/INSTALL.txt) = a710c598d300605c2d2f373f12f8b9b2366dd28f6cf84ccedc3c6ac3efa410e2c0a3e454489824c4a65467b0947231a6f280a4ea2cb3582bdd3d532ed994e63e +RMD160 (NetBSD-6.0/cats/INSTALL.txt) = 5f0042bf269b86bb159915585707077a98a5f06d +MD5 (NetBSD-6.0/cats/INSTALL.txt) = 8cb2eb0a3f5249382607fb963ca82313 +SHA1 (NetBSD-6.0/cesfic/binary/kernel/netbsd-GENERIC.gz) = 5d2bcce895dd7d88e0d5600b6ca55a4b216bd368 +SHA512 (NetBSD-6.0/cesfic/binary/kernel/netbsd-GENERIC.gz) = 85e01da3fe9ebb93fb7ae3f028297972bf4538117430185bf0885b46352f68df08fe025d91569ee0da2e17e8b83a4de99e1f3d56d2c5cb31ede3beb366afa157 +RMD160 (NetBSD-6.0/cesfic/binary/kernel/netbsd-GENERIC.gz) = 7c946881e8b671248896e5e620f8125426911450 +MD5 (NetBSD-6.0/cesfic/binary/kernel/netbsd-GENERIC.gz) = 39a8c5037a6266d0bb6df8fdb5c14c7d +SHA1 (NetBSD-6.0/cesfic/binary/sets/games.tgz) = 16ee93ea4d5fac2fb28fad5c32c8a3d57d011d79 +SHA512 (NetBSD-6.0/cesfic/binary/sets/games.tgz) = a7f49ab72f50273f66c8dcf408b57ec4668debd5537c5bd0ec59aa0f4fa1d599ba0798d1b283315c4208cbcb608925808ce003b1ade79034886edb8208f9f48d +RMD160 (NetBSD-6.0/cesfic/binary/sets/games.tgz) = 1e09d99d7fe2e495763f05919472d27a4ba699df +MD5 (NetBSD-6.0/cesfic/binary/sets/games.tgz) = 8a26f3e864444209088bccf21419a616 +SHA1 (NetBSD-6.0/cesfic/binary/sets/man.tgz) = 899b9d8242e983a5110ab755651c24f709b5af67 +SHA512 (NetBSD-6.0/cesfic/binary/sets/man.tgz) = 410999db110d710f4bb498c3d7ae7adc62170c7c2f470ce189c92f6c436c5ea96149659c631ef0b5605caaa025d97dfe1c07c428d86f51239657bd6b71717b15 +RMD160 (NetBSD-6.0/cesfic/binary/sets/man.tgz) = c1270f68c6d41b351877f71f0396ac34877dfc8d +MD5 (NetBSD-6.0/cesfic/binary/sets/man.tgz) = df4db2bbfa39ef6a4a215d949653d04a +SHA1 (NetBSD-6.0/cesfic/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/cesfic/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/cesfic/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/cesfic/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/cesfic/binary/sets/xserver.tgz) = 1d20fd039546a66b428b854c659ea5e2ee9f8114 +SHA512 (NetBSD-6.0/cesfic/binary/sets/xserver.tgz) = 091d09049d0af5555feec02065234e281677aeb3ecbab5a19413d924a8b58dc7f64401ef68e68bc52d8b6eeb73e091d351c45805374b8bf276b0181415968561 +RMD160 (NetBSD-6.0/cesfic/binary/sets/xserver.tgz) = feef5d52278d23637d7b8ba77639bfd96918e90e +MD5 (NetBSD-6.0/cesfic/binary/sets/xserver.tgz) = b2bd6057c374376388766fc8667eb9a9 +SHA1 (NetBSD-6.0/cesfic/binary/sets/kern-GENERIC.tgz) = 682508a28054a48a7242a494917ac4889bc67992 +SHA512 (NetBSD-6.0/cesfic/binary/sets/kern-GENERIC.tgz) = 0225b3aa055ad8d4c5b3029cea2459cc27e5670cd4aa50529c3490f93692273fabf6fb1d47336ca82e7b9b97c9cd6eaa6da29f1c71076c36664952cd2e8f92cb +RMD160 (NetBSD-6.0/cesfic/binary/sets/kern-GENERIC.tgz) = 39e19612b53e389e4da7ab24ad463d19da13f296 +MD5 (NetBSD-6.0/cesfic/binary/sets/kern-GENERIC.tgz) = ae69c0b436f251484d22512f3207263f +SHA1 (NetBSD-6.0/cesfic/binary/sets/base.tgz) = df22763e9478973636b3651d21f5cc5c5b065515 +SHA512 (NetBSD-6.0/cesfic/binary/sets/base.tgz) = bfdab8e7b9dcbd14d7e6321edbfbf06c45eafc0c85dcace6879ff485d45262706dd29a165c9d89a041618244977763af4c0f0c93d48ac39c96c5a4446122d2b9 +RMD160 (NetBSD-6.0/cesfic/binary/sets/base.tgz) = 1359d35509d93695dd0cfda9adead93875618ddd +MD5 (NetBSD-6.0/cesfic/binary/sets/base.tgz) = 232f3d5ccd51c66577dc50e25c149476 +SHA1 (NetBSD-6.0/cesfic/binary/sets/comp.tgz) = dbd27c5388fd2ccfa90ceaf819f5fb3b86bac78e +SHA512 (NetBSD-6.0/cesfic/binary/sets/comp.tgz) = 0657745dfedf6283919628d26665d30374807c78e049cdf5d9ce3d3dca54275ccaa992b5c21ef5c850decd1def118cb14c1e89a2bbdbe55b905e0f8100e259ef +RMD160 (NetBSD-6.0/cesfic/binary/sets/comp.tgz) = b0bdc0fd2ca77bdadb6d03a465333bd9dca2a016 +MD5 (NetBSD-6.0/cesfic/binary/sets/comp.tgz) = 8ff8a532ccd1d24e93b4ca53a41d1efa +SHA1 (NetBSD-6.0/cesfic/binary/sets/etc.tgz) = 20b9dc0339ed74a93dc82fc1b60f9b3fbf6b4b8d +SHA512 (NetBSD-6.0/cesfic/binary/sets/etc.tgz) = 593ef36e7f37c6153b8068a2f8b433a6bbe821a2bfcad7ea6ce4e30bf5611172aa94e82b7aca57c141d84381c597306779e5023cab4ff28fa415b6b6bac69e3d +RMD160 (NetBSD-6.0/cesfic/binary/sets/etc.tgz) = cd6bcc3d96f38f8e9a00cfedbeb4463a27708d9d +MD5 (NetBSD-6.0/cesfic/binary/sets/etc.tgz) = 343a0c8c930807f71f37e7116bf8f391 +SHA1 (NetBSD-6.0/cesfic/binary/sets/modules.tgz) = d5191e8899d7345c88bae6f65c1fd249b02a0063 +SHA512 (NetBSD-6.0/cesfic/binary/sets/modules.tgz) = 22e74e63cdc763effdcb58c7d549c0811dedee37953a9669dca09010dde364c6ba7440a29ad1e1e634a7c44b69cbca65afe006b9f564bd10bc4f0852cb55dc75 +RMD160 (NetBSD-6.0/cesfic/binary/sets/modules.tgz) = 5ad1d1c039de7da6dd1183ea6f4e9c319931dc86 +MD5 (NetBSD-6.0/cesfic/binary/sets/modules.tgz) = c0dda9a6803a213f3bca675728056dfd +SHA1 (NetBSD-6.0/cesfic/binary/sets/tests.tgz) = fdf867451cd371c25672448a1dbc7c204e8534b7 +SHA512 (NetBSD-6.0/cesfic/binary/sets/tests.tgz) = 9f137af1458c138a40dd2cf293e58deaa93a7145457127ddddabad1c23f380e36950d21cc6051bc5a4b101a632b9610a74cc3fc4bf6129e29e57ee8fd9d2da6b +RMD160 (NetBSD-6.0/cesfic/binary/sets/tests.tgz) = 0c27b80fb02f5ca0dfea6854d0df2818df52b9e1 +MD5 (NetBSD-6.0/cesfic/binary/sets/tests.tgz) = 2cb77946d9b305a0e03a6ac5fed04ff7 +SHA1 (NetBSD-6.0/cesfic/binary/sets/text.tgz) = d9f8aaf67b6ffd9828d447b5a6b208ea5bffcbd3 +SHA512 (NetBSD-6.0/cesfic/binary/sets/text.tgz) = 931dc3aec206ff95df08c36ed09a01caa2b10bdff34affc723e7ea0c6d2cdfc493d02b9875568ec9276c2d35a74cc782ec8c8cee10ad62879831b1d728cd3d62 +RMD160 (NetBSD-6.0/cesfic/binary/sets/text.tgz) = cec72f88379d8c6b30730568eb653de4a07f8c8d +MD5 (NetBSD-6.0/cesfic/binary/sets/text.tgz) = 1daceefaf9afa99dfb01cde29485cfe2 +SHA1 (NetBSD-6.0/cesfic/binary/sets/xbase.tgz) = d052985aaeadbeaad2aab5aab60ef68f5527a9eb +SHA512 (NetBSD-6.0/cesfic/binary/sets/xbase.tgz) = 83089a0b043d1413d865ea766cf1c50da9d1c12165e05bfc72f26b4d4513549119cc716ffebda1fd82b20ff1766c579aa000b7c10b4f29fcca49f0ff9f05177b +RMD160 (NetBSD-6.0/cesfic/binary/sets/xbase.tgz) = 3a8239f2ecb4e13e2352e3b09c3496f51dd12fb4 +MD5 (NetBSD-6.0/cesfic/binary/sets/xbase.tgz) = 61c565148bfbdd631981e7d42845c147 +SHA1 (NetBSD-6.0/cesfic/binary/sets/xcomp.tgz) = f3eda836d68a0b648fec7072373ae0b7267ab7d4 +SHA512 (NetBSD-6.0/cesfic/binary/sets/xcomp.tgz) = c448fa8a9665c6cd19aa05eae8456a06e0301fed427eff4d20f4a337e398c4346b285bea3c46924eada81d2bd1c34bcfa91cfd36d15eeb8ca6e9f7606514f131 +RMD160 (NetBSD-6.0/cesfic/binary/sets/xcomp.tgz) = 68333053bfff6afe3fa5e7555e58039ca42b679e +MD5 (NetBSD-6.0/cesfic/binary/sets/xcomp.tgz) = c318f3138aabcb6453f77a6dfa4778c7 +SHA1 (NetBSD-6.0/cesfic/binary/sets/xetc.tgz) = 5965357819e9e3e64a9cf0963595a5870699cd82 +SHA512 (NetBSD-6.0/cesfic/binary/sets/xetc.tgz) = da1f214b6de2a4a1ef227c608b741a076a7d4ba491131fadd33ebbf0782fd6c0d1ade406b4aa92c973c9f87ee70b2dff20d3a710df08201aac3c1a9ad339fe31 +RMD160 (NetBSD-6.0/cesfic/binary/sets/xetc.tgz) = 7151d3746cae1d748a566356431ca8ba4a5b51f3 +MD5 (NetBSD-6.0/cesfic/binary/sets/xetc.tgz) = 616f7da77033039c3b6972c33223215f +SHA1 (NetBSD-6.0/cesfic/binary/sets/xfont.tgz) = 46a06412b08381288aeb30ddc5b5a30d09530fcf +SHA512 (NetBSD-6.0/cesfic/binary/sets/xfont.tgz) = b5c5c517924de3ae3bc0fd094c0be19501668f4ad25feae8768c5c17065ff90b9b60760afa47ee93909fb92c4c12a818a95f0744e988a04e20be51f0d5dd4d66 +RMD160 (NetBSD-6.0/cesfic/binary/sets/xfont.tgz) = b58231d11d9ea95811dd0a6f548b6bdb18eae61e +MD5 (NetBSD-6.0/cesfic/binary/sets/xfont.tgz) = e52bf6c25b8e5fcef899329b68856e5e +SHA1 (NetBSD-6.0/cobalt/binary/kernel/netbsd-GENERIC.gz) = c9618dcb53044599e6397eac6bfd5dbd6f106cf0 +SHA512 (NetBSD-6.0/cobalt/binary/kernel/netbsd-GENERIC.gz) = f46c57b34ffc0f0140094384a10ea7c3d0140f315fceed6b02a1ec4770d6114eb1e995020fd056e03af71185f0448fde86829f5921b961a903bf0c275ff730e3 +RMD160 (NetBSD-6.0/cobalt/binary/kernel/netbsd-GENERIC.gz) = 4f69bb230b7c20fc591af0ff0e788e0f9a6dfff7 +MD5 (NetBSD-6.0/cobalt/binary/kernel/netbsd-GENERIC.gz) = 4ef49f4e446b38c2dcecf61dbca8fa25 +SHA1 (NetBSD-6.0/cobalt/binary/kernel/netbsd-INSTALL.gz) = 8c6edfcb94e9c0bfe670a78e6599dbba4787ef6b +SHA512 (NetBSD-6.0/cobalt/binary/kernel/netbsd-INSTALL.gz) = aa2dd1067f3fe253b43eb3a1ec0c8119a717c43236f1df4d72a4ac5667de310ac904bbca89588b9438a3aacdee5bb3d569e170dab17487ec5c6d9c148086085f +RMD160 (NetBSD-6.0/cobalt/binary/kernel/netbsd-INSTALL.gz) = 54a79af6fbce4c15b3415137f67a35e0d5e34daa +MD5 (NetBSD-6.0/cobalt/binary/kernel/netbsd-INSTALL.gz) = 112e15f9d41a31dbe6eb6864d62633ef +SHA1 (NetBSD-6.0/cobalt/binary/kernel/netbsd-RAMDISK.gz) = 4075b370e08ffe708669556c584e79073a9280b0 +SHA512 (NetBSD-6.0/cobalt/binary/kernel/netbsd-RAMDISK.gz) = ae5eb10935acf635e7a3abf985b86fbe9a57a071dea8ef7fe08ff5fd887901331d603e61d1bfeba330489534c4accae61e8c63fcc0cbb4a248e8fffa53d59fec +RMD160 (NetBSD-6.0/cobalt/binary/kernel/netbsd-RAMDISK.gz) = 9537810097f1bfe7c0cb7a4154639c8374a17c63 +MD5 (NetBSD-6.0/cobalt/binary/kernel/netbsd-RAMDISK.gz) = 0a477e1b678ab3c2906eef7d9082d2a5 +SHA1 (NetBSD-6.0/cobalt/binary/sets/games.tgz) = 27d9f98fecb3495e51939df9f107e81e527af26f +SHA512 (NetBSD-6.0/cobalt/binary/sets/games.tgz) = 46bb4e10313cfffaaf4f7fa2157474ef940f94bcc9f84b46f829c7615bbf45e4e01edee7b7efb84bc28561e0712c37cfc737f9c2a0d9a73b67c80c8aa0f3a9af +RMD160 (NetBSD-6.0/cobalt/binary/sets/games.tgz) = 947feea90ec2698a65d555cb78a29a001b086589 +MD5 (NetBSD-6.0/cobalt/binary/sets/games.tgz) = 355f00978fed8e8da6a251e591be5387 +SHA1 (NetBSD-6.0/cobalt/binary/sets/man.tgz) = 899b9d8242e983a5110ab755651c24f709b5af67 +SHA512 (NetBSD-6.0/cobalt/binary/sets/man.tgz) = 410999db110d710f4bb498c3d7ae7adc62170c7c2f470ce189c92f6c436c5ea96149659c631ef0b5605caaa025d97dfe1c07c428d86f51239657bd6b71717b15 +RMD160 (NetBSD-6.0/cobalt/binary/sets/man.tgz) = c1270f68c6d41b351877f71f0396ac34877dfc8d +MD5 (NetBSD-6.0/cobalt/binary/sets/man.tgz) = df4db2bbfa39ef6a4a215d949653d04a +SHA1 (NetBSD-6.0/cobalt/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/cobalt/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/cobalt/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/cobalt/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/cobalt/binary/sets/xbase.tgz) = 76468fcada5a9e26652aa9f0f9f3c94829a317e9 +SHA512 (NetBSD-6.0/cobalt/binary/sets/xbase.tgz) = b2adcfc2dedef30b21b885c8fc757d0479541744a280a9997fbeaa9c881009ab4b0019e0001a540a8eb6db5f84db87b365e420bb2d4270af209821bdb080369c +RMD160 (NetBSD-6.0/cobalt/binary/sets/xbase.tgz) = 1e0074d03d9fbb3373e0a427b25cc7097bf6d3c8 +MD5 (NetBSD-6.0/cobalt/binary/sets/xbase.tgz) = a8f29ec2e3768405942f97af3dd08ee7 +SHA1 (NetBSD-6.0/cobalt/binary/sets/xcomp.tgz) = d8ac89f3f6ff20abb0adabc49227afdb74aa2040 +SHA512 (NetBSD-6.0/cobalt/binary/sets/xcomp.tgz) = 4f03213fb061dae9421747209628d06ede6bbb71a7560a9e1a54796b907f1620146a33fdce52974227a21acedcc210b99e15c4fdd36432eba60c1041a92d8cee +RMD160 (NetBSD-6.0/cobalt/binary/sets/xcomp.tgz) = 6be5e72b9b57c9bdf8ed8ea127e2a73830feeecb +MD5 (NetBSD-6.0/cobalt/binary/sets/xcomp.tgz) = 59a7ea141587417be38ab1f6056cc780 +SHA1 (NetBSD-6.0/cobalt/binary/sets/xetc.tgz) = b9f6b1a54ffab37b11f4c6e717b481cd087fb609 +SHA512 (NetBSD-6.0/cobalt/binary/sets/xetc.tgz) = 72f35e65f3a90967e250a2006d500619b3824f7f5c3d7494554f153ec5cda5b28c445f28c34a1e4463f40da5855e8d4257726411796967fe37763d90cf7fe461 +RMD160 (NetBSD-6.0/cobalt/binary/sets/xetc.tgz) = 1169c246f91189fd0c4ae86ac27a92f5c2edda3e +MD5 (NetBSD-6.0/cobalt/binary/sets/xetc.tgz) = 8f3c52cc5af1cafaf7b0d0f884a5b537 +SHA1 (NetBSD-6.0/cobalt/binary/sets/xfont.tgz) = d06848571034f3b7fc975082f1de37b912acb18c +SHA512 (NetBSD-6.0/cobalt/binary/sets/xfont.tgz) = 66a1013c935bee5e7e5d24325a527522306bcded7ced63790f2e58831b3ed91176a1b9510b2159be63504d5167d48d534919927ffc6e225ae2bb2487f90a9ede +RMD160 (NetBSD-6.0/cobalt/binary/sets/xfont.tgz) = c9502843a5d4dd7e996e8d158c519cf7f8575cbd +MD5 (NetBSD-6.0/cobalt/binary/sets/xfont.tgz) = e812899176eac2bf65a6d949ac3f3424 +SHA1 (NetBSD-6.0/cobalt/binary/sets/xserver.tgz) = ff805022f409202f3346c45475c7ec0f8187218e +SHA512 (NetBSD-6.0/cobalt/binary/sets/xserver.tgz) = f2bb3810a5572b519980126a3d934f63b5ab5c2fcf9fb8166c556bd3cc14cfaa151d582086bb1506ac9ac7e21d4e70a5cd5c3faed96212d8a14a0b5bafdcc4c1 +RMD160 (NetBSD-6.0/cobalt/binary/sets/xserver.tgz) = d5ae336337cc77f7f55f542b3457918d6fc0efe8 +MD5 (NetBSD-6.0/cobalt/binary/sets/xserver.tgz) = 92447a1560887d337d22e2deed0670a6 +SHA1 (NetBSD-6.0/cobalt/binary/sets/kern-GENERIC.tgz) = d085ff7c5cd7f260cc1aaca4c2e54c26c948d893 +SHA512 (NetBSD-6.0/cobalt/binary/sets/kern-GENERIC.tgz) = 0c1ad1014af64d059a5ce8261e46534e0eaed8702440b93f5109c19ed9fb0b2dbf37a23cc28f1a688ca45f9e721dd0f4a1ee6771990a835a459cd633ff0f4887 +RMD160 (NetBSD-6.0/cobalt/binary/sets/kern-GENERIC.tgz) = cfecc943b0e501f53558c87be282a948469c57fe +MD5 (NetBSD-6.0/cobalt/binary/sets/kern-GENERIC.tgz) = 630b91f62d422855f30b33590119e9d7 +SHA1 (NetBSD-6.0/cobalt/binary/sets/base.tgz) = 90870f3189063cb2c4a2aa81d1c68d835e48ee25 +SHA512 (NetBSD-6.0/cobalt/binary/sets/base.tgz) = 9a962443ad380ef6d4dce623bb41e6b1aecd452b0adfc6e51d1c17610829f17a1b02cf5be2e539eeafcc7ff47ae79f8f7a367eebd74ea6cb70e0fc57eebbf27b +RMD160 (NetBSD-6.0/cobalt/binary/sets/base.tgz) = 12111c0c67c4f8fbb3c54c2c3480e73caee6f33c +MD5 (NetBSD-6.0/cobalt/binary/sets/base.tgz) = d7aba51f2552fb2e19af9adbd673dff9 +SHA1 (NetBSD-6.0/cobalt/binary/sets/comp.tgz) = f22b026d0b9c1e7725e4db4b9abbda1160a9c80a +SHA512 (NetBSD-6.0/cobalt/binary/sets/comp.tgz) = a0a6f6185d30e28c4db98189134bcb5e2dc9820c748911e36483b84fb598c5b122c10863ccff82a2f2556734004fab2c9ac59cbc1530ec79ec535e4e426d4e5c +RMD160 (NetBSD-6.0/cobalt/binary/sets/comp.tgz) = ed9d28519a8cc55a2806d6c1df0953c535075b1d +MD5 (NetBSD-6.0/cobalt/binary/sets/comp.tgz) = 44112b73f63f4cddda4ac8ab8f5ba1f5 +SHA1 (NetBSD-6.0/cobalt/binary/sets/etc.tgz) = 7109941b0df321286aaf226ee48222fbc7ad692f +SHA512 (NetBSD-6.0/cobalt/binary/sets/etc.tgz) = 1d18f21beb41dd07c5744b127209b5de8f5fd2fbbd109c3c65dbe73126e2a987e1e1d08a68668f597ecce1d0e9875fe349bf89d74d3add850a3c4554808cda07 +RMD160 (NetBSD-6.0/cobalt/binary/sets/etc.tgz) = 1687c63ca2d75377354754bb425c02bd6907c445 +MD5 (NetBSD-6.0/cobalt/binary/sets/etc.tgz) = 3b36b16b387597ceb2233eaa72d3bea6 +SHA1 (NetBSD-6.0/cobalt/binary/sets/kern-INSTALL.tgz) = cfefd1fef2db13b66730678c9df067ab208158ad +SHA512 (NetBSD-6.0/cobalt/binary/sets/kern-INSTALL.tgz) = 2a62524f994a5034d60f679b1d30eafe60dafb35216458055ad9e25f3c7053f4556f1edd233754e0e4eb4a79373fb814c28e832b67d9de69035513b819d5080f +RMD160 (NetBSD-6.0/cobalt/binary/sets/kern-INSTALL.tgz) = 894035c7e551dfee7ae53cd1e7b358876fef240f +MD5 (NetBSD-6.0/cobalt/binary/sets/kern-INSTALL.tgz) = c6f35e3463064c86be5b3229fdf23ce1 +SHA1 (NetBSD-6.0/cobalt/binary/sets/modules.tgz) = eda182e3418c72ab2d0bb33efa014d77be461b73 +SHA512 (NetBSD-6.0/cobalt/binary/sets/modules.tgz) = 52a988323ace3452cdd3c8db6d03e26f15b3d9570314c8e8efd80169676d36209a8dee6736d4a1aed53beb3ad3ecd6fe8ea9d4b3b0a85417a6540cc4f6ca2154 +RMD160 (NetBSD-6.0/cobalt/binary/sets/modules.tgz) = 0610022e6cce6e576d3bbc6f3bca284d36eff821 +MD5 (NetBSD-6.0/cobalt/binary/sets/modules.tgz) = 2850ca4ea69cbac5274f2307a48394f1 +SHA1 (NetBSD-6.0/cobalt/binary/sets/tests.tgz) = ae62656c92b1883296087eec3534d7542356c79e +SHA512 (NetBSD-6.0/cobalt/binary/sets/tests.tgz) = 35a22f1ede3db17eaa2c29645c5675fe5a2c4fd6deefc5d372cbdf1ac61c592fe7acf65486a8c576d3ee8651ddb3afa33e39e644de18d2831d25c89aa74c734b +RMD160 (NetBSD-6.0/cobalt/binary/sets/tests.tgz) = fba7399b23a918470dcd108a422bb4f998a94a42 +MD5 (NetBSD-6.0/cobalt/binary/sets/tests.tgz) = 21dee182d4f02df926ce52688347af72 +SHA1 (NetBSD-6.0/cobalt/binary/sets/text.tgz) = 58049b832c3722ddb05f8eca622f77ff8e4e8a4f +SHA512 (NetBSD-6.0/cobalt/binary/sets/text.tgz) = 4eb3919068d26f193fcca2a30e27152421be198b313fa9700612a0d9d094d67d329b2e72e70b02c4789c1430378269f35f0758042faf60c26a18e293947c7db9 +RMD160 (NetBSD-6.0/cobalt/binary/sets/text.tgz) = a2eaa36b8c306e0cd6a9e17218aad574d4fc3508 +MD5 (NetBSD-6.0/cobalt/binary/sets/text.tgz) = e0f6aa8df8d17719f265922d2aebc787 +SHA1 (NetBSD-6.0/cobalt/installation/boot.gz) = 59e1785a9e2ea35df01f4726b62f6fbbc74c56df +SHA512 (NetBSD-6.0/cobalt/installation/boot.gz) = ad2baef23c54d600d49e7777b924c7d79c8e7e3f74107e9fcd939b16811b31979391ce8f3ebeb4b31810fef2cec13df063d31e4b3a5b5c57b550156b796a4410 +RMD160 (NetBSD-6.0/cobalt/installation/boot.gz) = 9ac9dbfb3932a92e2b4e03664bdb8dbed4fc0e71 +MD5 (NetBSD-6.0/cobalt/installation/boot.gz) = f4b10cb6244d765eb7a9a6a3ef1d09ba +SHA1 (NetBSD-6.0/dreamcast/binary/kernel/netbsd-GENERIC_MD.bin.gz) = 971d8de48c6c6be81f723ada4b7c509dd152b86c +SHA512 (NetBSD-6.0/dreamcast/binary/kernel/netbsd-GENERIC_MD.bin.gz) = ac63feaca53a1abad181877bec95098e06e89343cd783f309ed3d223a80005d49fd5b3420a36c8e2894389373a9a8d4a023f134e1ff847f240864b8f529adfbd +RMD160 (NetBSD-6.0/dreamcast/binary/kernel/netbsd-GENERIC_MD.bin.gz) = 5abfe7b82ce9b81c69818cbb533a9d7e69f01081 +MD5 (NetBSD-6.0/dreamcast/binary/kernel/netbsd-GENERIC_MD.bin.gz) = 6ed9526e1fc60db1cdab3dfedb2a4ffe +SHA1 (NetBSD-6.0/dreamcast/binary/kernel/netbsd-GENERIC.bin.gz) = 7950c0154a603614e8aaa75da019ffe266fe36de +SHA512 (NetBSD-6.0/dreamcast/binary/kernel/netbsd-GENERIC.bin.gz) = 2421894a9dda95a17a30b6a4d87e350f7bd17f467362255eb22c8a56e0ac1e54592136d0b0d218c16a14afb8684bb8eaf11442217af1c217ea4588d6290c761e +RMD160 (NetBSD-6.0/dreamcast/binary/kernel/netbsd-GENERIC.bin.gz) = 326f220c689b47fb30e91d483a009246993da43e +MD5 (NetBSD-6.0/dreamcast/binary/kernel/netbsd-GENERIC.bin.gz) = acaf2f6174037777dc0dfc175da86403 +SHA1 (NetBSD-6.0/dreamcast/binary/kernel/netbsd-GENERIC.gz) = 85e46b6fa4ab45b810f6c3f4b3268cba0f895cb4 +SHA512 (NetBSD-6.0/dreamcast/binary/kernel/netbsd-GENERIC.gz) = d3f2e7306c8b8ea0969bb68e5888ba16436632479a6555a4fffe2479c4cea1dce048c2d18b6653fe1946b9a9bd2d2df1da172d71df45c6eca59a1c91e81f51a9 +RMD160 (NetBSD-6.0/dreamcast/binary/kernel/netbsd-GENERIC.gz) = 31820c3a9b7305792ca4246aaa0d8e5474c2a8ba +MD5 (NetBSD-6.0/dreamcast/binary/kernel/netbsd-GENERIC.gz) = b48de4452de2d94b74d617ba30b529f8 +SHA1 (NetBSD-6.0/dreamcast/binary/kernel/netbsd-GENERIC_MD.symbols.gz) = 83040bbf6395952a68fbfde410db2729c8d814c9 +SHA512 (NetBSD-6.0/dreamcast/binary/kernel/netbsd-GENERIC_MD.symbols.gz) = c48a2bb6dc2bac588b3e9690dbeed3b85361439e40e3410220c0b9fcb70e2e6a2bdffd24ddb428f740895ef34c3e56955f2877509441be0c158e97407656da24 +RMD160 (NetBSD-6.0/dreamcast/binary/kernel/netbsd-GENERIC_MD.symbols.gz) = a6f75d1e098e0bebb9da8f6149114de13416b210 +MD5 (NetBSD-6.0/dreamcast/binary/kernel/netbsd-GENERIC_MD.symbols.gz) = d72d4a1170c9f40c41c951eb2f40dd9c +SHA1 (NetBSD-6.0/dreamcast/binary/kernel/netbsd-GENERIC_MD.gz) = 98765e3c532799a669420e9b6a89b22033059d66 +SHA512 (NetBSD-6.0/dreamcast/binary/kernel/netbsd-GENERIC_MD.gz) = 34a64fc5eb79bec00adf55f9788139730c5f35bb8e05f0b00899776836aa0dc7c372482ed5cb9341fa7354d5f8c76ed6b879ac516210d89e33794efbccf40127 +RMD160 (NetBSD-6.0/dreamcast/binary/kernel/netbsd-GENERIC_MD.gz) = 5a4349f94c8afe0d7ad4c6ca4b02d766ddfc63b3 +MD5 (NetBSD-6.0/dreamcast/binary/kernel/netbsd-GENERIC_MD.gz) = 7c4659ca64c7f31b205e8d1ce4166597 +SHA1 (NetBSD-6.0/dreamcast/binary/sets/games.tgz) = 2040b4af557a62f2ade5fc9fcfe4cab3df88c7e2 +SHA512 (NetBSD-6.0/dreamcast/binary/sets/games.tgz) = 8b5071337dc844042537c24c75660e61c9709cd10cbbeab059a84da6d482260b73365ff3870f85060c130a291b6f02be174d288127ca62ce4d291a6982192317 +RMD160 (NetBSD-6.0/dreamcast/binary/sets/games.tgz) = 28acfa5a131d52df7c157e2edca1dd0f20e774dc +MD5 (NetBSD-6.0/dreamcast/binary/sets/games.tgz) = d82c46dbc0021fd4694e464042936052 +SHA1 (NetBSD-6.0/dreamcast/binary/sets/man.tgz) = 899b9d8242e983a5110ab755651c24f709b5af67 +SHA512 (NetBSD-6.0/dreamcast/binary/sets/man.tgz) = 410999db110d710f4bb498c3d7ae7adc62170c7c2f470ce189c92f6c436c5ea96149659c631ef0b5605caaa025d97dfe1c07c428d86f51239657bd6b71717b15 +RMD160 (NetBSD-6.0/dreamcast/binary/sets/man.tgz) = c1270f68c6d41b351877f71f0396ac34877dfc8d +MD5 (NetBSD-6.0/dreamcast/binary/sets/man.tgz) = df4db2bbfa39ef6a4a215d949653d04a +SHA1 (NetBSD-6.0/dreamcast/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/dreamcast/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/dreamcast/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/dreamcast/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/dreamcast/binary/sets/xcomp.tgz) = 53aa1e2a910e8eed09dc07f8b724804f53fe5e2f +SHA512 (NetBSD-6.0/dreamcast/binary/sets/xcomp.tgz) = 24645da85419528015cdaefd0c835741fa801392e795b363bdfc39558e75e7f384511c0668d12e2440114b7c543c7532aaec438048f08d35c54c9c7a748f20c0 +RMD160 (NetBSD-6.0/dreamcast/binary/sets/xcomp.tgz) = 60a461ffc1f1562274110d65c72a541ee131cd21 +MD5 (NetBSD-6.0/dreamcast/binary/sets/xcomp.tgz) = f1d2650a8d7a4ecd60fda8e1aaf8c09b +SHA1 (NetBSD-6.0/dreamcast/binary/sets/xetc.tgz) = 1636a6fe3e01f6d8a07a19cd204a6807c8caa4c7 +SHA512 (NetBSD-6.0/dreamcast/binary/sets/xetc.tgz) = 9cea4ba4af287dd57e591d4269f2f2582010250316f323746ac56b12cefcf2590b93fbb0197c665f61b1df41dcca62d17fb6ad80d4b1feb8ac8265e91e15074f +RMD160 (NetBSD-6.0/dreamcast/binary/sets/xetc.tgz) = 5f68e3f96f7bb9ae07fccdb1d058e4b1307b4b29 +MD5 (NetBSD-6.0/dreamcast/binary/sets/xetc.tgz) = da84d97230787283e215a4ee1c4053ad +SHA1 (NetBSD-6.0/dreamcast/binary/sets/xfont.tgz) = 97439ccf6840b18b1e9885f5504a401bf1a93650 +SHA512 (NetBSD-6.0/dreamcast/binary/sets/xfont.tgz) = 3d15541f7d7ae2128f44355bf110415adfa4e5182829259d2c6f7a4217feff99e236d13c5bb7bbeb724ff1a09ac1f58f02bdd6eef528bc416ec3118db6fc7d45 +RMD160 (NetBSD-6.0/dreamcast/binary/sets/xfont.tgz) = cdc9fcdb5fd5032803d5bba18db58f3ea6d62c85 +MD5 (NetBSD-6.0/dreamcast/binary/sets/xfont.tgz) = a8466a0477c6c443eafe99e9d1c61131 +SHA1 (NetBSD-6.0/dreamcast/binary/sets/kern-GENERIC.tgz) = 8f11a046a1e6277a5f90f44142735f39375f949c +SHA512 (NetBSD-6.0/dreamcast/binary/sets/kern-GENERIC.tgz) = 12786eb317effcd2f7f108a139a95b99c6026e75370853d3761292d431063859dfff26ab4a2bdf5c8bfcfbda4deaed9025583b30367e00074dc875d759f1cf76 +RMD160 (NetBSD-6.0/dreamcast/binary/sets/kern-GENERIC.tgz) = 464ed36bd11cfa0b181632d2b1c54f34a511fd14 +MD5 (NetBSD-6.0/dreamcast/binary/sets/kern-GENERIC.tgz) = 1cd64692f608f13541288f3ff263fa82 +SHA1 (NetBSD-6.0/dreamcast/binary/sets/base.tgz) = ce23182c9b35fcba35fce0e3f12578a988a8ecc7 +SHA512 (NetBSD-6.0/dreamcast/binary/sets/base.tgz) = 20dc7d634449bb7e57ae55458aa0f2d53c5f03f92df3df5a6429c1f3192871ed2fb8ec64700a045591d308a31baa3212c8a7ee6f3bfcccc05974557bc2e1ebad +RMD160 (NetBSD-6.0/dreamcast/binary/sets/base.tgz) = 7fbdce2370f91ad3aa3abec889333b59755b0f4b +MD5 (NetBSD-6.0/dreamcast/binary/sets/base.tgz) = 3aee642fc36860e63bf85392888ab2a2 +SHA1 (NetBSD-6.0/dreamcast/binary/sets/comp.tgz) = c288c3890b514eb00673399571a6d22d4abf7608 +SHA512 (NetBSD-6.0/dreamcast/binary/sets/comp.tgz) = cfbe2ddaf47453f9b20a74890e3585fd82a23d25489378b41276848019971f1e740e00203418db16e1832777b96d3b16eeeae1a4fcdf9551b93582395c5a3838 +RMD160 (NetBSD-6.0/dreamcast/binary/sets/comp.tgz) = b79a42001602eb84e650fe34a25ac20e5773703e +MD5 (NetBSD-6.0/dreamcast/binary/sets/comp.tgz) = 57451cb40d16c7d6dfb960eb4848754e +SHA1 (NetBSD-6.0/dreamcast/binary/sets/etc.tgz) = df82ad0e59f00bfa96ca079e1dac2b0f772a6b1b +SHA512 (NetBSD-6.0/dreamcast/binary/sets/etc.tgz) = 87d552690ee356eb3a82c763ddf3f44ed57a5d0d8616974570ba21a2901371e6ee6e54d0b25cb5607466f01cbabca86fe096572f395c74aa6dd98be45e4c7ee8 +RMD160 (NetBSD-6.0/dreamcast/binary/sets/etc.tgz) = bbc9f48831c1483ffe9c9aab353995e162a5a385 +MD5 (NetBSD-6.0/dreamcast/binary/sets/etc.tgz) = f0881f75efa980e58cea0c0d60f55656 +SHA1 (NetBSD-6.0/dreamcast/binary/sets/modules.tgz) = 243ab8d8f5d3375fbd17efb668c1abe45d0d1487 +SHA512 (NetBSD-6.0/dreamcast/binary/sets/modules.tgz) = 193c158f2d2f64c3b571c6e10d97bdbca141faf5ee1a970e3c1e194970e2723e74d8372e0110b52d11e210e860102ebf24012a2267a0f98dedeceb0cc60429f8 +RMD160 (NetBSD-6.0/dreamcast/binary/sets/modules.tgz) = 788e45cc0d8a03191c14f3fe0d429ae331d96895 +MD5 (NetBSD-6.0/dreamcast/binary/sets/modules.tgz) = 83acdebfad50fc820d420b4e74c87762 +SHA1 (NetBSD-6.0/dreamcast/binary/sets/tests.tgz) = 263b82b9d13d080e46cd27e4a6e5df9d43e6f74e +SHA512 (NetBSD-6.0/dreamcast/binary/sets/tests.tgz) = ffc4a4348c68f8b06f1387d60e1d5b1bcc1b42ec6d255cd267dea08aef4874591dfc95f69ce416333679cdbc124540cb9b92e58ad9f522e6f34eafa2f6dd9ef2 +RMD160 (NetBSD-6.0/dreamcast/binary/sets/tests.tgz) = 2518cdf17a8f82dcf39525e2928ef52e46e32325 +MD5 (NetBSD-6.0/dreamcast/binary/sets/tests.tgz) = 2f0af9ef7e65f9afb0185e305a206183 +SHA1 (NetBSD-6.0/dreamcast/binary/sets/text.tgz) = 577c45d37aefc65d2787bd989002bd3748440b56 +SHA512 (NetBSD-6.0/dreamcast/binary/sets/text.tgz) = f1a7e6beac2f881e8b9d356491e4b09d7b92b0a0ed33462575db59ce8effae6ca2a1989e4fa9b78fc5d012b118b2f99a2e2fcd7505a0ca80eb61684d5bceb096 +RMD160 (NetBSD-6.0/dreamcast/binary/sets/text.tgz) = 2688ae8578acf1b6b8937abf4d05cb09e7e2ce8d +MD5 (NetBSD-6.0/dreamcast/binary/sets/text.tgz) = 0cc81795b0f4ddd432f3dfa01eb2a530 +SHA1 (NetBSD-6.0/dreamcast/binary/sets/xbase.tgz) = 7305b994f65ffa7d67a9f99d0146e705f81ec723 +SHA512 (NetBSD-6.0/dreamcast/binary/sets/xbase.tgz) = 904f0c21201d51b58c366a984eb20191c620287b77b12b520003d48fb0ce1a3ae10fa871c3514598a74071ce0cc1321ff781b96195a13e81c75d35cdc7958030 +RMD160 (NetBSD-6.0/dreamcast/binary/sets/xbase.tgz) = faa8760bbee9d3b2a21e3b62fddb641faf939ee9 +MD5 (NetBSD-6.0/dreamcast/binary/sets/xbase.tgz) = 655c33ebf6f37bd90b1921b220dff2ac +SHA1 (NetBSD-6.0/dreamcast/binary/sets/xserver.tgz) = df506c92cf396d2d59ee212c03a10f44129f51a3 +SHA512 (NetBSD-6.0/dreamcast/binary/sets/xserver.tgz) = ee8b15abf9e8115ffc50deeb372e9c7dfe9412f8e94d65b3ed78f78fba63e9282b668c8fc2fb2a22437f950adafd1dedf2e9baf395fa945d04eeb50db0d1f5cd +RMD160 (NetBSD-6.0/dreamcast/binary/sets/xserver.tgz) = 73bcaffdf98d0a5c4d5c22c97c5476c1b5901eec +MD5 (NetBSD-6.0/dreamcast/binary/sets/xserver.tgz) = c5e16ae2cf663c0373fbb82f64f4f48b +SHA1 (NetBSD-6.0/emips/binary/kernel/netbsd-INSTALL.symbols.gz) = 7ffd5f42e92a4ae32ca78766815db12dbfd4c4f6 +SHA512 (NetBSD-6.0/emips/binary/kernel/netbsd-INSTALL.symbols.gz) = f7a50a9ee148ac9566dbc3722b14d904c02a3cbf285ea8efb10a24b8a93db514abbf825dbde48a8c494da6b02f48408b9414a6d8a45ed61f334afd2dd148aa71 +RMD160 (NetBSD-6.0/emips/binary/kernel/netbsd-INSTALL.symbols.gz) = e03b53e71c192a3de6d720b0502e0597f2ab0aee +MD5 (NetBSD-6.0/emips/binary/kernel/netbsd-INSTALL.symbols.gz) = 014979ca9f7b5feb3664479cd34dd2d3 +SHA1 (NetBSD-6.0/emips/binary/kernel/netbsd-GENERIC.gz) = 663be1ef5f9177715d8a299d3e610b21a942dc16 +SHA512 (NetBSD-6.0/emips/binary/kernel/netbsd-GENERIC.gz) = 006a5189536650946aeddb6763997bab1cafe82b578777674f75df8346d6bd01467d532de7be3c5ed0664d9b85e4da90a90871f6e15fa5166af29f1e87d9d7ea +RMD160 (NetBSD-6.0/emips/binary/kernel/netbsd-GENERIC.gz) = 15cbdb609c3925081aac2e84ebc104775601fad5 +MD5 (NetBSD-6.0/emips/binary/kernel/netbsd-GENERIC.gz) = 71af44cf65da1b8ecdadbbf037f07ec5 +SHA1 (NetBSD-6.0/emips/binary/kernel/netbsd-INSTALL.gz) = 4f40fd5aa8028bd956dfc51a5e61be77ca742adc +SHA512 (NetBSD-6.0/emips/binary/kernel/netbsd-INSTALL.gz) = 9fb9cfe8aa5d8ea350b24ad80a207d9439141914bd4e3371297b9971969c96ca6899b45f099e1e02ed4c8ffbea75d421b22af7d09b5b91c2f435df176229b4c8 +RMD160 (NetBSD-6.0/emips/binary/kernel/netbsd-INSTALL.gz) = b269d2a87391b9640988493e3493edd114e7e8b2 +MD5 (NetBSD-6.0/emips/binary/kernel/netbsd-INSTALL.gz) = 59724cb6c92366dc47fa0b4ecf2fe22f +SHA1 (NetBSD-6.0/emips/binary/kernel/nfsnetbsd-GENERIC.gz) = 5dc90ad559e682bd427b6165f760bb09ba676e7d +SHA512 (NetBSD-6.0/emips/binary/kernel/nfsnetbsd-GENERIC.gz) = 4992a1e1bd6cc1dc21821a6151aa3561fda5e369ab6057575cd70d63503a98a8d9da257956486f2f58996b0aaabf20266c16033c1f069e3dcc21f582f74006f8 +RMD160 (NetBSD-6.0/emips/binary/kernel/nfsnetbsd-GENERIC.gz) = e7f4efd86d048e9f9857bb3cbf136a3e461b9463 +MD5 (NetBSD-6.0/emips/binary/kernel/nfsnetbsd-GENERIC.gz) = 66abd685dbc87ed5282e1b55a6b7bfbd +SHA1 (NetBSD-6.0/emips/binary/sets/man.tgz) = 899b9d8242e983a5110ab755651c24f709b5af67 +SHA512 (NetBSD-6.0/emips/binary/sets/man.tgz) = 410999db110d710f4bb498c3d7ae7adc62170c7c2f470ce189c92f6c436c5ea96149659c631ef0b5605caaa025d97dfe1c07c428d86f51239657bd6b71717b15 +RMD160 (NetBSD-6.0/emips/binary/sets/man.tgz) = c1270f68c6d41b351877f71f0396ac34877dfc8d +MD5 (NetBSD-6.0/emips/binary/sets/man.tgz) = df4db2bbfa39ef6a4a215d949653d04a +SHA1 (NetBSD-6.0/emips/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/emips/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/emips/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/emips/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/emips/binary/sets/kern-GENERIC.tgz) = ed3903192d38367303cf5210725c33ba123c216d +SHA512 (NetBSD-6.0/emips/binary/sets/kern-GENERIC.tgz) = 62687e8a1af317454e30a65dafd1b54eb444db9a27abf987ba17bfaf4b9796623f279011c2102500563c9a862fa983c5e48a9c94afdedeee15414840dcd328fb +RMD160 (NetBSD-6.0/emips/binary/sets/kern-GENERIC.tgz) = 070bb8b5cab57c375fad13304165f8825e6647d5 +MD5 (NetBSD-6.0/emips/binary/sets/kern-GENERIC.tgz) = 732ac8530d63fe2f3eea6e2def05ab4b +SHA1 (NetBSD-6.0/emips/binary/sets/base.tgz) = d058920475032b263b2020af3230894da8ded663 +SHA512 (NetBSD-6.0/emips/binary/sets/base.tgz) = 606b27579e80fca77e82a385dfda2e03bac6d8563186ccc98d993cd532bc79da93883cf71f850380cafb31107efb424585a4aa5946f54bbc36aae5d9d9495a44 +RMD160 (NetBSD-6.0/emips/binary/sets/base.tgz) = 2663d48750530861b5e9514902b9cc44e8a4162a +MD5 (NetBSD-6.0/emips/binary/sets/base.tgz) = 22ff23e09d0502d77de5fb289ad53427 +SHA1 (NetBSD-6.0/emips/binary/sets/comp.tgz) = 5c25affcdce77ce7a77755c866316a9db89272a1 +SHA512 (NetBSD-6.0/emips/binary/sets/comp.tgz) = d2b09aa5b72624ad3f25fa1438a8feef1e02b8f9ff064dd1d05a621f29a9790b0029baf652ab5c0ae2c3811532208235288c6614f62c378bc6b1b4a5494fd06d +RMD160 (NetBSD-6.0/emips/binary/sets/comp.tgz) = 2fd5cfc13841a1188580c6584f78bf8262752da9 +MD5 (NetBSD-6.0/emips/binary/sets/comp.tgz) = dc12cdcce6751fd44291a95a06cf97aa +SHA1 (NetBSD-6.0/emips/binary/sets/etc.tgz) = 6bf20c929df89dfe6764df1f4ab15b6aeb45d4cb +SHA512 (NetBSD-6.0/emips/binary/sets/etc.tgz) = 4ee6668a884bb4b4c3ccc4370a7ac70ed14f32b7856219fa375f200ad259087400e93fe144bad4650318cbe9af4133e8d8d8f79cd0d91aeb24df117117ac54bd +RMD160 (NetBSD-6.0/emips/binary/sets/etc.tgz) = 9081112a95ee958fce83e79f687b97ef847587b4 +MD5 (NetBSD-6.0/emips/binary/sets/etc.tgz) = 912ab9bd3949946dc2af9522581118fe +SHA1 (NetBSD-6.0/emips/binary/sets/games.tgz) = ec034031c6b1ea012c36910f2e901b032b0aaebe +SHA512 (NetBSD-6.0/emips/binary/sets/games.tgz) = e9bd506e1f6a6c17c0505db90f7da49795dc63905c9962e01a69224a1cf22312d9e4c68d815e9c487f21fd0791bac3a65a5e5f7bce46198694f673522b057d96 +RMD160 (NetBSD-6.0/emips/binary/sets/games.tgz) = 393d511e3432d93932f2b3d2308d6a16b7cce764 +MD5 (NetBSD-6.0/emips/binary/sets/games.tgz) = 71d23c31e025ff3b1eece7b3cb170abe +SHA1 (NetBSD-6.0/emips/binary/sets/modules.tgz) = f9aef1ecd6e2ee16d7ddfdad51da034bbdcd8aa6 +SHA512 (NetBSD-6.0/emips/binary/sets/modules.tgz) = abaa6c62593d85131f691a3125e055970a8c3fdd7d8103db6e501dc2d2379c9dd16f9a819e14ac20959011d8946c40a8dc59ee0b7ead8a8f25c20a6475696bc6 +RMD160 (NetBSD-6.0/emips/binary/sets/modules.tgz) = bca8a2cdb2ced4804cc2e0543981b1db671732e1 +MD5 (NetBSD-6.0/emips/binary/sets/modules.tgz) = c98d2b8fab6184f74545c6fa54897a35 +SHA1 (NetBSD-6.0/emips/binary/sets/tests.tgz) = 05a68659aec8758adb269e6f898607e1fc3f9089 +SHA512 (NetBSD-6.0/emips/binary/sets/tests.tgz) = 1434cd321d5f37e6482645a11ce4f203ea3406fcea550103e1881bc68b1e8760697e5e6207ad01d4dba2d1b71c2ed0488bbb0c01dec2b28a6a74e3529ab81a8a +RMD160 (NetBSD-6.0/emips/binary/sets/tests.tgz) = dc76faefeb42e73abb5727e46bdb46ce7a737be3 +MD5 (NetBSD-6.0/emips/binary/sets/tests.tgz) = 1ef426de07b570c1d9affeb44e452225 +SHA1 (NetBSD-6.0/emips/binary/sets/text.tgz) = 96fc1b82a283a2bf4cdd76168ee3cefa73191be8 +SHA512 (NetBSD-6.0/emips/binary/sets/text.tgz) = 7cfdb8107f4d0bfe28bf41c15b2fe7f9c0aa0d075cdb7fdb0b4566ed512da3123eff94410bf563c6a37aa498d83ed9cc7b9e16d54c8bf33605fc60bf1357c4c4 +RMD160 (NetBSD-6.0/emips/binary/sets/text.tgz) = 1e1ad1dd678eb777938e2320522e275a5751475c +MD5 (NetBSD-6.0/emips/binary/sets/text.tgz) = 11f296781f98a8ae6aac39f40cb45805 +SHA1 (NetBSD-6.0/emips/binary/sets/xbase.tgz) = 535b4c29666ef2de43bb6017102e9181576255ea +SHA512 (NetBSD-6.0/emips/binary/sets/xbase.tgz) = 31656ac187e0adf03eff3f896876510bb7624bb18789094abf22a59008e9d7b8d848cc1703e15b799fa2b4cd9e108f1d29c5625f1ae9f012edf8cf35912e4590 +RMD160 (NetBSD-6.0/emips/binary/sets/xbase.tgz) = c8b8ebfb26aaecc931b8d8a17625eb91f904fcfb +MD5 (NetBSD-6.0/emips/binary/sets/xbase.tgz) = 46641b24d37899b78ef7a83559bfc3b0 +SHA1 (NetBSD-6.0/emips/binary/sets/xcomp.tgz) = 6cddeb4f503fb424f9a06645ef46701288799401 +SHA512 (NetBSD-6.0/emips/binary/sets/xcomp.tgz) = 45f779894389850776fdd4785165f6bf07dfcd46d408199eb352492536b254fa229b9d4e99a716657f210c4772feea966814329f3f2aaa729112c9b8f9d4e50a +RMD160 (NetBSD-6.0/emips/binary/sets/xcomp.tgz) = 9203f95dc810dbbd873aa54234dada2961a6d309 +MD5 (NetBSD-6.0/emips/binary/sets/xcomp.tgz) = cbb4c61d832ebb4aa97c99484e9109b5 +SHA1 (NetBSD-6.0/emips/binary/sets/xetc.tgz) = 7db74837c8e702a831451e4660c1f8670e674003 +SHA512 (NetBSD-6.0/emips/binary/sets/xetc.tgz) = d68c233f0e4dcf5961bfc214fa10188d5fcb954e103ad610b76964c8e832e5758283bb28ef3eba448cde496d610b488f7958fb391371e1230a7b6127c267dcc5 +RMD160 (NetBSD-6.0/emips/binary/sets/xetc.tgz) = 2d5fd67c9ef6ddef6c3f5fdc845ea23f2b0e3b57 +MD5 (NetBSD-6.0/emips/binary/sets/xetc.tgz) = 98767dc7c3a45e641592807be04f1a64 +SHA1 (NetBSD-6.0/emips/binary/sets/xfont.tgz) = 6f8acfd3feb8f6421cfea08d8cfe514ad7bc7acc +SHA512 (NetBSD-6.0/emips/binary/sets/xfont.tgz) = 2b4d59176fdef5055b0c5d8ef7677d6a1ae823d86d5955a2c33be046ba7bd8bfad85ae21e8acb11a50cba250d21bf0f2bb8c43aaa5d7d0767998dfbbfa54d014 +RMD160 (NetBSD-6.0/emips/binary/sets/xfont.tgz) = 34878c9b7c1380c42f57eadea7369b687d0e45bc +MD5 (NetBSD-6.0/emips/binary/sets/xfont.tgz) = 540f04b4c6acb6e1b6364303388f82ed +SHA1 (NetBSD-6.0/emips/binary/sets/xserver.tgz) = a85da9c68ded22e61f2234e696b0bd61739f4a08 +SHA512 (NetBSD-6.0/emips/binary/sets/xserver.tgz) = fd1bf84b2f34befbae2dc34e3fc5af3048c93c185d8cf5e8afe91e324bba7005d14d9cd73db5e09bee783116b9a09b01b650a9097df07a335fc81a2bc569c2b1 +RMD160 (NetBSD-6.0/emips/binary/sets/xserver.tgz) = f066886778a33191aaed1a30ac8494b6deb152c5 +MD5 (NetBSD-6.0/emips/binary/sets/xserver.tgz) = fc4fa9292f46a325f74c4abc922fd215 +SHA1 (NetBSD-6.0/emips/installation/diskimage/diskimage.gz) = 9c4d0f6ee9e3251ef720acdb06e20683c55a3db7 +SHA512 (NetBSD-6.0/emips/installation/diskimage/diskimage.gz) = 5b9c5d72e5e4bfcae27bf51c2ec9fa849b019b475d6677be8c49c31f18eaff6e559d80790ba6d5e606169215e46e04322c4d12ed0386e76635fdebe380cadd28 +RMD160 (NetBSD-6.0/emips/installation/diskimage/diskimage.gz) = e7373c5f20e4728fef9951dfc1beffb70390f651 +MD5 (NetBSD-6.0/emips/installation/diskimage/diskimage.gz) = 4f2e15b3d203006588a75670b4d3e75c +SHA1 (NetBSD-6.0/emips/installation/miniroot/miniroot.fs.gz) = 4075299a2ef6a4368234ed1e378c2931b0df6376 +SHA512 (NetBSD-6.0/emips/installation/miniroot/miniroot.fs.gz) = cee815c8a985125fd2c1a9a4811542371ade25fa7f35b4cc4da1783186146d4620d1910a24b92beb02d1cf836e9cfc2921ff9d8c81ecb4babf585b1ec3601496 +RMD160 (NetBSD-6.0/emips/installation/miniroot/miniroot.fs.gz) = 1701f681ccb15b5232abc07550de79d3380af96c +MD5 (NetBSD-6.0/emips/installation/miniroot/miniroot.fs.gz) = 5cb7df17380c5bd1d56b28d6061332f8 +SHA1 (NetBSD-6.0/emips/installation/netboot/diskimage.tgz) = 04f571f04a2227b98df91f97023e860af233d2c8 +SHA512 (NetBSD-6.0/emips/installation/netboot/diskimage.tgz) = e5c7354014f23996e0e5c331103b9936387b9c6402491041727b69353f6af08b57cf429b51ee0c28e76e3f4506479b0559dac18b05a009a3afca76ad2edbd29d +RMD160 (NetBSD-6.0/emips/installation/netboot/diskimage.tgz) = c57777b29a2c589549a906fd0f425c56366a7075 +MD5 (NetBSD-6.0/emips/installation/netboot/diskimage.tgz) = 9d1bfe38f9ec7d4ed86173bb157abf52 +SHA1 (NetBSD-6.0/emips/INSTALL.html) = bad639d8582318241d268e529e8e024159dc5997 +SHA512 (NetBSD-6.0/emips/INSTALL.html) = 94627da8cf355e0f7b3a597e2e22be0b151a9c4e40301c7c0b67c1877c34abff57476a5c177035c032cfc1d9b8f9d38aa919c27f1f3c15d3edb3403d18e71b44 +RMD160 (NetBSD-6.0/emips/INSTALL.html) = f2b00377e6a6d060e9027d78d2278445ff6b4d75 +MD5 (NetBSD-6.0/emips/INSTALL.html) = 825b11bed2394322021f65e43627a391 +SHA1 (NetBSD-6.0/emips/INSTALL.more) = 9906d8f0c74d8538aa2e7d1361800cbbc2db2d29 +SHA512 (NetBSD-6.0/emips/INSTALL.more) = e8419f85e6beef4bf18f6bc916141ae9bca52eb6f56e2ae7133fc771ca1033cf2172a644e4415be0019868004278605f0e93c42f8f4f60d1e2fecf8c06a51a90 +RMD160 (NetBSD-6.0/emips/INSTALL.more) = 70fa5e023134732afc81b3622480328ae9f5d449 +MD5 (NetBSD-6.0/emips/INSTALL.more) = 0cff06f0f5c3bac3eaf4bf4336494217 +SHA1 (NetBSD-6.0/emips/INSTALL.ps) = 5783005eb38711a9ffb248fb5bdf2987912f26fc +SHA512 (NetBSD-6.0/emips/INSTALL.ps) = a27d36ced381f22565ac6ee290d4ef43de834977ca8be3d96bf758005a6fe0875aa03f703da08b7dfd5fdbd48c19c77ef5263f8571d0f5f983ff7c1d08088873 +RMD160 (NetBSD-6.0/emips/INSTALL.ps) = b8e28009dd02ff9c1f98d5fadadc6455c262238e +MD5 (NetBSD-6.0/emips/INSTALL.ps) = c16b7dcef0674aaf0dd240381961eaa5 +SHA1 (NetBSD-6.0/emips/INSTALL.txt) = 0d166d27be7166a76ad58779f1272a1a1542e952 +SHA512 (NetBSD-6.0/emips/INSTALL.txt) = ba74f2486c3bee1b30fc39edae6ad38b0abcd9610afdad172a49590aa0c1fd8a2256d185a699baf6bea9e40d9fec7d1e56c17d77858d9ebde027419cc044b8dd +RMD160 (NetBSD-6.0/emips/INSTALL.txt) = 729887c61690c966497811da66852780d0d3eec5 +MD5 (NetBSD-6.0/emips/INSTALL.txt) = 8a28948bd5d45a30ca79556be75dbd69 +SHA1 (NetBSD-6.0/evbarm/binary/gzimg/gzimg_TEAMASA_NPWR_sd0_flash_0x00080000.gz) = e8620ef3bbba89642fcce48ed01e16f0783e889e +SHA512 (NetBSD-6.0/evbarm/binary/gzimg/gzimg_TEAMASA_NPWR_sd0_flash_0x00080000.gz) = 055cdfd0872737d68054fa4c2125d131e6ee3f60135be817da7fe111adb2290c4ad8d968b4cbefc67658c3e9f3dfdf99caaec320f572a00a790604c93fa73408 +RMD160 (NetBSD-6.0/evbarm/binary/gzimg/gzimg_TEAMASA_NPWR_sd0_flash_0x00080000.gz) = db49ed4cceac70d18a8a6b335f20923d07c8ad8f +MD5 (NetBSD-6.0/evbarm/binary/gzimg/gzimg_TEAMASA_NPWR_sd0_flash_0x00080000.gz) = 12617c0444b2a570637a45339937c77f +SHA1 (NetBSD-6.0/evbarm/binary/gzimg/gzimg_ADI_BRH_sd0_flash_0x00140000.gz) = 3160f03e833b96020804361b1d98c0cffd8c5345 +SHA512 (NetBSD-6.0/evbarm/binary/gzimg/gzimg_ADI_BRH_sd0_flash_0x00140000.gz) = e5d7ceae7a4b4446002170c84a44dcd65cdbb2458c889582ff3070a20580ff31d2f497b07c320217b55f75e6b343f689b9312d172dd3880bd82808e6cdb995c9 +RMD160 (NetBSD-6.0/evbarm/binary/gzimg/gzimg_ADI_BRH_sd0_flash_0x00140000.gz) = 41f31d747ec5265903490d300bce1e6c34ef32ca +MD5 (NetBSD-6.0/evbarm/binary/gzimg/gzimg_ADI_BRH_sd0_flash_0x00140000.gz) = efec631edb7870b4cc3ab1cec8d98810 +SHA1 (NetBSD-6.0/evbarm/binary/gzimg/gzimg_ADI_BRH_wd0_flash_0x00140000.gz) = e1c927a0718d63609fe15d9dc9c265ab0172ddc5 +SHA512 (NetBSD-6.0/evbarm/binary/gzimg/gzimg_ADI_BRH_wd0_flash_0x00140000.gz) = 5418c2ebffd11c30028d867561e26dc5857167698c88f5d9eb30af3944fdab4950ec2f6953999689c03cf684aaada038d6f7f07494988dba9467a814fcfe1d3f +RMD160 (NetBSD-6.0/evbarm/binary/gzimg/gzimg_ADI_BRH_wd0_flash_0x00140000.gz) = 05680bce8a448c3fec2149d6c89dced13166f34e +MD5 (NetBSD-6.0/evbarm/binary/gzimg/gzimg_ADI_BRH_wd0_flash_0x00140000.gz) = 36d8336012f5603e1b30565061fd8c3a +SHA1 (NetBSD-6.0/evbarm/binary/gzimg/gzimg_CP3100_sd0_flash_0xf0080000.gz) = 9419b71634e5ff228357a37651061a1c4c2c2ebe +SHA512 (NetBSD-6.0/evbarm/binary/gzimg/gzimg_CP3100_sd0_flash_0xf0080000.gz) = b17b66b1b62c16d6a0add67d55f82a6943557abbbcb8001b328770dcd2191b1b55881dca2919d7f76381aceb1ed53ae81ff002317e99d02fbfc2817d9b366661 +RMD160 (NetBSD-6.0/evbarm/binary/gzimg/gzimg_CP3100_sd0_flash_0xf0080000.gz) = dcf913149707315fda181d6dd6967b68fe61fd22 +MD5 (NetBSD-6.0/evbarm/binary/gzimg/gzimg_CP3100_sd0_flash_0xf0080000.gz) = 4f81965829024ad764d293456cd96fbd +SHA1 (NetBSD-6.0/evbarm/binary/gzimg/gzimg_CP3100_wd0_flash_0xf0080000.gz) = 748d01d1b8796881f853c31ce98e0dbf473bcf8e +SHA512 (NetBSD-6.0/evbarm/binary/gzimg/gzimg_CP3100_wd0_flash_0xf0080000.gz) = 898de3034e164cbef89c0f09c76decf48c4291c7c0d077134ba1695cf0c9287d658e61c82cb2d3d46dce986014d2e52d84f0600dab0f99db996623eed7ad93ea +RMD160 (NetBSD-6.0/evbarm/binary/gzimg/gzimg_CP3100_wd0_flash_0xf0080000.gz) = 452633be8258bf3df07d6e9461785a8f3ac09f98 +MD5 (NetBSD-6.0/evbarm/binary/gzimg/gzimg_CP3100_wd0_flash_0xf0080000.gz) = f6644ec6b9e7cbeb624d57e00e764b5e +SHA1 (NetBSD-6.0/evbarm/binary/gzimg/gzimg_GEMINI_flash_0x01600000.gz) = 2dece6cc86980856d901df11995ecb0a5524451b +SHA512 (NetBSD-6.0/evbarm/binary/gzimg/gzimg_GEMINI_flash_0x01600000.gz) = 270b8d528bed206bfee4cfc63ae9a04f69c282d52b2beae8cbc8298872d2ff0e50e00d849c6e435d472845a0f6b8601b94a0fe52e63c61e7b5c534b9d830d252 +RMD160 (NetBSD-6.0/evbarm/binary/gzimg/gzimg_GEMINI_flash_0x01600000.gz) = fbd959fffd37010a92a76026469affec9bbe95da +MD5 (NetBSD-6.0/evbarm/binary/gzimg/gzimg_GEMINI_flash_0x01600000.gz) = adaae55226bd3fc806962ae70e9281dd +SHA1 (NetBSD-6.0/evbarm/binary/gzimg/gzimg_IQ80310_sd0_flash_0x00080000.gz) = 97ec6f4a472d0b73f1d3b8d284f57debab190c78 +SHA512 (NetBSD-6.0/evbarm/binary/gzimg/gzimg_IQ80310_sd0_flash_0x00080000.gz) = c52a596cd2ffb52c1321b2e8006a590186dddde671f4325067e546338eac4d405c7d5fe559ba6d187a1c26eba4c45d233505a434a98ee11b88b315db0a42d63d +RMD160 (NetBSD-6.0/evbarm/binary/gzimg/gzimg_IQ80310_sd0_flash_0x00080000.gz) = 3305a23227d275c25307ab7b999f5e0c0560195b +MD5 (NetBSD-6.0/evbarm/binary/gzimg/gzimg_IQ80310_sd0_flash_0x00080000.gz) = fd76ab094a19b1f66c9d21df4cb69700 +SHA1 (NetBSD-6.0/evbarm/binary/gzimg/gzimg_IQ80310_wd0_flash_0x00080000.gz) = 0ed362fdba88789a5d26d00e0e8285f75587f5c2 +SHA512 (NetBSD-6.0/evbarm/binary/gzimg/gzimg_IQ80310_wd0_flash_0x00080000.gz) = 78110414c2dc51bc378c3a1d44914b4f5dffd6b1d6d0a749576e2d7d5474e7856a2235641fe310fb87b3789bbf495b16459f9c773bdab19161e65af671ae6bec +RMD160 (NetBSD-6.0/evbarm/binary/gzimg/gzimg_IQ80310_wd0_flash_0x00080000.gz) = 4d958d9f772b214efbf9932a00970375a6fa7e57 +MD5 (NetBSD-6.0/evbarm/binary/gzimg/gzimg_IQ80310_wd0_flash_0x00080000.gz) = ec5386e862bee8da4d46a124584e2cee +SHA1 (NetBSD-6.0/evbarm/binary/gzimg/gzimg_IQ80321_sd0_flash_0xf0080000.gz) = 037aa337f876321d75654dfd576dbc0c4c301e0e +SHA512 (NetBSD-6.0/evbarm/binary/gzimg/gzimg_IQ80321_sd0_flash_0xf0080000.gz) = e033668a417f453ca35b2b43633a7eb9160765eb42ba1b86ea61d5fd4cb5136123a69194d58b3bddc51fd7e319bae1d70028e1215a1e8f4e98270bf0b4eabfa2 +RMD160 (NetBSD-6.0/evbarm/binary/gzimg/gzimg_IQ80321_sd0_flash_0xf0080000.gz) = a8e8d6ea67cf26c422d638794675626e7261b3ea +MD5 (NetBSD-6.0/evbarm/binary/gzimg/gzimg_IQ80321_sd0_flash_0xf0080000.gz) = 2b3bb43bdb7fcd4999377eaa3b994c48 +SHA1 (NetBSD-6.0/evbarm/binary/gzimg/gzimg_IQ80321_wd0_flash_0xf0080000.gz) = 6d8870ad00ed9f496738dd5cf7f670b5b43d2f34 +SHA512 (NetBSD-6.0/evbarm/binary/gzimg/gzimg_IQ80321_wd0_flash_0xf0080000.gz) = 414a11de38ff565307fbe599b87b0f59ddf91db1882b5e246774ac23f6af49411ae33de4145a0d8e10755d6e78d85c930ecd0705804a25ad10e3957765e565c1 +RMD160 (NetBSD-6.0/evbarm/binary/gzimg/gzimg_IQ80321_wd0_flash_0xf0080000.gz) = 27959615599b74b946e9e8483c2284aa3f80ffa7 +MD5 (NetBSD-6.0/evbarm/binary/gzimg/gzimg_IQ80321_wd0_flash_0xf0080000.gz) = cc0f0b0621d6d931f6dec494c7bb2305 +SHA1 (NetBSD-6.0/evbarm/binary/gzimg/gzimg_SMDK2800_flash_0x00000000.gz) = 09617a28f2da331a17efe6cbdd4df7367f8ff98a +SHA512 (NetBSD-6.0/evbarm/binary/gzimg/gzimg_SMDK2800_flash_0x00000000.gz) = 9324e9fe0d4756cac25b33f8b6592f2a1a25d12b0f3752447cf660c21a3b2e93eaeb3e41a15d91c2edd827e2f5318a241c58129cff998d8f0a0a7a6a6bbc598f +RMD160 (NetBSD-6.0/evbarm/binary/gzimg/gzimg_SMDK2800_flash_0x00000000.gz) = c2e0b7b74df9090350d1afc52a15465b77eea3b9 +MD5 (NetBSD-6.0/evbarm/binary/gzimg/gzimg_SMDK2800_flash_0x00000000.gz) = ee28fbd00b44705a33d6ca6e6982507f +SHA1 (NetBSD-6.0/evbarm/binary/gzimg/gzimg_TS7200_wd0_flash_0x60660000.gz) = 3036d8f2318c69d791b710a06d2e94c5c563fcac +SHA512 (NetBSD-6.0/evbarm/binary/gzimg/gzimg_TS7200_wd0_flash_0x60660000.gz) = e8f2cab3b75e3f4ecfd2ed85b624c8c643eab3cd32a8d0398148f49923622df598071fbb2fef6b5687c8273762d197992a03b1d8465d96630202b78592199a1f +RMD160 (NetBSD-6.0/evbarm/binary/gzimg/gzimg_TS7200_wd0_flash_0x60660000.gz) = ead79fd1f78230bd30f851b78dd13b670a791863 +MD5 (NetBSD-6.0/evbarm/binary/gzimg/gzimg_TS7200_wd0_flash_0x60660000.gz) = 1e25872ad616b30406dab15aa8c20b22 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-INTEGRATOR.bin.gz) = e673789f88d60407c85c744a64382c102b91e983 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-INTEGRATOR.bin.gz) = 43aa01312bac8975f2f66cfc47e9cbdcbfe37eb37f2076c221e5c118521e987f18c1b14bf2d94b390942820e5f6218cfa1eba67a1818f8723481d434f9fea00c +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-INTEGRATOR.bin.gz) = 7c45cf94c28c04db6df14decfede69e83bc0cf4c +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-INTEGRATOR.bin.gz) = 49da3170f0fe2fb304e1131bf77d4c3d +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-ADI_BRH.bin.gz) = 8f057cc764ab0cc64689c2df8652f9db24e20004 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-ADI_BRH.bin.gz) = 537b67fb3baf1f5363dec0079a7bf64c0ed7d5ec9b2a383362ca04ce3f746011798d12fe10ff6e4a77ccde35aa66e8cb06e689dcd7f19b5233999ffd7a2f817b +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-ADI_BRH.bin.gz) = 3119fe0017084fdb8a97ba14a7f6258450c6b938 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-ADI_BRH.bin.gz) = 755aa54a7e8e2091f3f3e7c37f34f45c +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-ADI_BRH.gz) = f133ab0dedf14635b824f7a0a7d55451933e23be +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-ADI_BRH.gz) = 56d8d397af893debd28cf4283759213f8c3171647fb4df80b570991792d2addf4473d5ac0ac8a4e4dc4a668035ee37d3331cc3b6d5e029876760d4a6e0aab459 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-ADI_BRH.gz) = 59b03c3a53d5b54cef8240612a803d1ea61486f9 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-ADI_BRH.gz) = 9e800486bef03915eec15ca90ea163fe +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-ADI_BRH.srec.gz) = 18f4bd985378baf25a9e28ffeaf95423b4bf85c7 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-ADI_BRH.srec.gz) = 9a535fc733582c7e8b59784c117f6714a96a1be2e9f65be2074731532511458a97b344359992de681bd7d7980c63dcbe98e7cef4bd58cd4cd3a313cefe822814 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-ADI_BRH.srec.gz) = 0e3554f0de32a39d19c1e674084e6b42f7ddfde8 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-ADI_BRH.srec.gz) = 22db840fa81c95919f08d2cb7ef81450 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-CP3100.bin.gz) = 5e3cd42ec6e6af1203ea8921eb1979183164c8b4 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-CP3100.bin.gz) = 21cc95b8e28d50eab2b20e5eda315781ba95c34a4e4f8d1c5907ddd81ed4b236dd100b3bdb957456e3a713211f5de11a0f55cc6516a58dab3d7212b23de95120 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-CP3100.bin.gz) = 5a1f1e22d7a29bf8205c1a3550fd78d2cdbe1d38 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-CP3100.bin.gz) = 61edb94110b4be5c9d8bc9ee660dbd41 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-CP3100.gz) = 19c96d4bf28919a4f30e55838b0859e197d0759f +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-CP3100.gz) = 823dd6b45920bae6c2817091c106af7d7fd4ffc965f64c68da520fcdd70b8bd341765d33f1adf06574baaa79395a501b58aa64b8b83628209f3a08560b90c0d5 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-CP3100.gz) = 30566487cbea824734bd4d9061f5a9df30875b07 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-CP3100.gz) = b35c13395ed69e7931eefff8e42f1198 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-CP3100.srec.gz) = a7d4841b78d684f17658819d150d7d16b135786c +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-CP3100.srec.gz) = e196c13406146baa4b8d923b4406d8e3b2a451a7cfb174a4c652b8a702b0d619d30705bc998acbe8a037fca1c8f2fda53aee9ce8d4a52722cb11c40bf1288f75 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-CP3100.srec.gz) = 78cd23cb694a0062858e5e3bb2959d794176c2db +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-CP3100.srec.gz) = b4e62ffbd5091a667a7fb61c31ff578e +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-GEMINI.bin.gz) = 6f6bf5de9d82b058100eb089aca61b9bd59aaf61 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-GEMINI.bin.gz) = f91cf6eada8a84ce9c0036a4c0b22e550d71bf20fcb67d6b409d252e7db2c707aa104ae68a998cf87e98e8a47e3cda2cfa67f19c6792d3cf4f32bee59f3e2c48 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-GEMINI.bin.gz) = b7ec88f6f6604e897b2450223e791758e1c278d9 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-GEMINI.bin.gz) = fb61d11fbdd49a4d826896bc45bad653 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-GEMINI.gz) = d44a7af68b2dffe73d6a28a742a15a64ad1c7f17 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-GEMINI.gz) = 244d5a9e1b36b7a18f77a1689d444375f733e4abe0a13047300b815633fe76af3bf595544078f89b1de302619e10f6d19245adeabd177fafeba93b7889dd34d8 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-GEMINI.gz) = cad1e137c7d8bdb92221cb76679bee0ecb78f7a7 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-GEMINI.gz) = d5a82888cc0477c064dc3ae9dfb29110 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-GUMSTIX.bin.gz) = af321ff02cea6f05295ed48d63145f2557065034 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-GUMSTIX.bin.gz) = 103b4e272b4ffd89e2705edcde9ecdff2d1b11bb4e4f6c46a2cfed6ea8bae9386bb357dda1fb04ca558f30d201171f2ec2aaae84b39b792715f142ab83772988 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-GUMSTIX.bin.gz) = 69a190021189d71376d88493fbe9bceb5c1bb50a +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-GUMSTIX.bin.gz) = cddd2da663644297ba2737081b26fab8 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-GUMSTIX.gz) = b7ec166d07220620ec458e776df34ce0f954a861 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-GUMSTIX.gz) = 8b38c79a2e2533d85733cc5dd176f808036e3d04f91134fab57110aa2c827f26487cbee563fe85cfb0facd6a463c7069d5d22aafe90c1803a8f0b7df2fe526fe +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-GUMSTIX.gz) = d71b9dc8f5d59f8b126ce83dc06df5f97a009195 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-GUMSTIX.gz) = a8fe08eb1fd48f4870f1f736c4a72cb0 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-HDL_G.bin.gz) = 33e9946d8fc4834f9c74647b322a79425d3d6c52 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-HDL_G.bin.gz) = 354db08b656e913a0803051b861cc77d90c3c7e170362488c9940c3d0dae047e7a9d92fec348f92d951ea4093196b9f0b210d9d0cf04b9d842494c45b6feda5f +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-HDL_G.bin.gz) = 393631ffd8b30a1e3dd5ecccbf950bb1a75759a3 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-HDL_G.bin.gz) = e650bd0cf7ad90361db3a5cd788553e9 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-HDL_G.gz) = eeccc5e10b4cc5b8900e9dca97222f0329c5ee67 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-HDL_G.gz) = 3ef842acc43f885398224dfb7c696d2334aecce84aecf7ea11d9464332e62fb796b45b302a097fd3a1ec4fe48ea92a029a8301f9d97899a51cea19c3524e39cb +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-HDL_G.gz) = b402a5e445815908643d27c5b69b7e055f2487ed +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-HDL_G.gz) = a74d0d8c03f2d840e118654bada47b03 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-SHEEVAPLUG.gz) = 9380dcaafde1fc16b90858e04d0804b159a18b6a +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-SHEEVAPLUG.gz) = 20e027261b82d2188342fc3e10bdf1c2531c9012b4c0a5fea9d480c70bf00f118f0a0487646f541a63422d1acddf4abaabb34ea0a9161bb8f429708fedd18e63 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-SHEEVAPLUG.gz) = 23e93e206ce3d710bdb9f4e57c342aaac073ff70 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-SHEEVAPLUG.gz) = 2101cfda9d3ee129a2768bab982c7d4d +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-RPI.gz) = 1558752bbd6b362decdd3caef1d05b8c80dcf43b +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-RPI.gz) = 15dedb25bd8759aa736fd0ce444c4c782a65ec6cdd64e3fe424e1665d3e937df88b375dae773dda973a66264b90e10d0aa89e03cc217a8afbf4d79a23cce635e +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-RPI.gz) = e64628b2e9cc699bb0a48172cc4422e9e50a624b +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-RPI.gz) = 2224734e36d6bc4a139efdad6cc86978 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-INTEGRATOR.gz) = 2c4862e6fdd14328dee5191b7e007fd7f2e626e3 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-INTEGRATOR.gz) = 259b9964b3d10a4b49a413ad6355c16960a538b02f19bf4c0e07fcfc51699ba9df0a0b6342e6f67b9366302026bade0bf46a53356dfe42342e06f6fcbaf64dcb +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-INTEGRATOR.gz) = afcc94417f4da4b84269420db2b0952565bbee93 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-INTEGRATOR.gz) = 6010c0404590c4264ff824a9a57c0e04 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-INTEGRATOR.srec.gz) = 0226f405675defd77c9dcdda8916e5b372cd206d +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-INTEGRATOR.srec.gz) = 0213a4b6784f018154bc11a148fcd6eec14ab26bc7b714d087c845db361776a6d37ff11aab7b1c1218e7a143e7fb12a85fff77f93d97832fa12d4ac39764691c +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-INTEGRATOR.srec.gz) = c5132bac29060129efd95b4d9beb4eee87e0b6a8 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-INTEGRATOR.srec.gz) = d176d5afd6c40c0cbfd4f64a19e39a25 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-IQ80310.bin.gz) = d105689d85a45fc834acd60c920d1420782e47ed +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-IQ80310.bin.gz) = bbe9fdeebed0c150622bd216013971c27646a4496f4ba64a8dcb0748e91c402a03441a0ee7b78341107f4d92f81771f41299b52d4142c6fd93e345f46a9319d8 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-IQ80310.bin.gz) = ee05e9b64e9039aaee667dfdd71934a2b029b22a +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-IQ80310.bin.gz) = 993d3e5e2595d0da326ec142a45b2750 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-IQ80310.gz) = 7bacc9ecbca2a680a72fa9d71d0f622302fd94ec +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-IQ80310.gz) = f12ed4db4fae72630b905b3edd5f6eaa87f84db7a13d908559f7c1bab054054440dedf6806b8ae6ce873bb09bf2a4cf69d89529f21abbc476ac50274d9a71741 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-IQ80310.gz) = 360190a9de654cf05c1aa9a6edc908079fa2c237 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-IQ80310.gz) = 73b8043c242bb9739d216f3f8da7d3a5 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-IQ80310.srec.gz) = 2c976175ede9683b8a8ec5b8c3711df84001300b +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-IQ80310.srec.gz) = c683332d8fb46e88dd0dc5d9b56a4fa942fe9cc7cb79a005ce59609caa9d357d7dc5126feae3b181f63009980a9bf1700130d086b7b7103a8ac199c2a25090dc +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-IQ80310.srec.gz) = a1cde3a2841db820d89ffaa32232ce83fd5f44f9 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-IQ80310.srec.gz) = 811e47b38fb8e8c1c7f228f0bbab9a74 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-IQ80321.bin.gz) = 862eb1a7ee9de8e3b3525e7d7d26d2cc5ba9bc59 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-IQ80321.bin.gz) = 884b2229b6a78748f61fdba23fe88a623a05c974d71e711821d902fea63e258fea523b9d9c1044ce5afd1d941a2e73d09649a6abc6d38ba0c263bbb4700dcfc1 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-IQ80321.bin.gz) = f3c4d5b5ec632c62410643b9e12960a40b2074ab +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-IQ80321.bin.gz) = 31e7f8b3e40c22ade7cc22d01d95b532 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-IQ80321.gz) = a60ac00d16384a828eef8a837fb21e00b53a8a4a +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-IQ80321.gz) = 54bceeae1a8b27e59a3767284017552f717cefafc71e68b6c74a40429131709ecfd79726737d2dbaefc30e70d09fdab893e4651d125c85f10d9017b1c9e1db7d +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-IQ80321.gz) = f5ce2ac5312c8fecbd072965df9bc2eb0c340d5b +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-IQ80321.gz) = dc8d921c26170e31f92bf29b1ce1a183 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-IQ80321.srec.gz) = 6fc69281083cfff4fa9fe78ab260619b92972167 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-IQ80321.srec.gz) = aaacf4b2b3f5ac015eddf58f6e5757c061b94ad57b8dc850cd5285fa4e111aaacfa2dbc0c9cc3b4e7a866a2fe2b55b900a33fed48e8587b50c6dede0dc66cd9f +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-IQ80321.srec.gz) = d63585bed43debdbb05df1eb44130fc50e2edfb9 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-IQ80321.srec.gz) = db12176962530274584befedc2794d71 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-IXM1200.gz) = cbf69533e9704756eed91dc42ab880300452cbf2 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-IXM1200.gz) = 104cbab6498100ebf4e91b89055568f8e770f33abf331787d061ad000c506caf54ca9cd9afe2d6c16b6874502e10e3b20c0fdb97607f18d2ffb59718b2df62c8 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-IXM1200.gz) = 24af829fe0a4c696a78dc11eeb9a6830c1faded6 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-IXM1200.gz) = e3634e55cff56a10538e3139c4eaf83a +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-MINI2440.bin.gz) = 3921a70d245903a0c95e4944b835f8b05326278d +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-MINI2440.bin.gz) = 49bf1c9de5e10f21603f8eb6a45b7ae29bda1fa9ba8fd4b0c2a07e498af6bfc818be5d59e384ae3afbe6a0aa8000ea494f2a431067d5f32e553d09c4346b488a +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-MINI2440.bin.gz) = 506b209365f4650bf205b3c989504665e6a464da +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-MINI2440.bin.gz) = 4d00574f0fccd038ce96a75e40119f54 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-MINI2440.gz) = ac288980ec3e5615d33d18bbb5b20b863b64d4e5 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-MINI2440.gz) = c96f2aac73d0e62c35d76c6a467f5b3b4ecd8461504a0ebbba456868f5ac1a42b6ff7c80aa2717bdeea242d79b940cd3584184da0fe8a07a79e2ac2f7bdc96bc +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-MINI2440.gz) = 02fd101de84eb4c6aa40bfa7cc477305246a7610 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-MINI2440.gz) = d4f8e1de25f4050d4b357cc9222799a6 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-MINI2440.srec.gz) = 10bb46c7b4e78af1cf9978c76759694a10f5b2b5 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-MINI2440.srec.gz) = 75b010e6766552928518ebda6daca8a979dd9a2168e932621c63271607c48ced148b11ed29cb14a11a1905f4a30a3613a63a41a5743b5857b346501b5516c3b0 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-MINI2440.srec.gz) = c18f791fe071f039783b42800302d62d407245fe +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-MINI2440.srec.gz) = a749256c48d3b8ac02d6ddca5fc669bc +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-MV2120.bin.gz) = 5f240a5493136d85a3b3ce856856a5781873834a +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-MV2120.bin.gz) = 19b95311ee9fe25d64d8eff569a02b68672348a1c7372bb99f9f07421e390ccaa0e1a3c65b6d8a67baae1b34859b5ae2ae0d1471c4c1bce0f249765ee085dd03 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-MV2120.bin.gz) = b0536ea2075ddf15ba68cd3597aca512d25404c5 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-MV2120.bin.gz) = 0174a07da16cafc0426a75dd4c9affbc +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-MV2120.gz) = f59146a75e366ba624eaf77f9582cd7200f56530 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-MV2120.gz) = d68a8a5c29cbcab54673232481a17bb901d64d15de7df630c1657494cb70494436a0763a38ab31b12e3f273c8e8404f8515d29f2f290c99d25372d46763ab6ec +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-MV2120.gz) = 2cf27b32a9bfd684b5f4013c9d25b8837aab0a08 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-MV2120.gz) = f623986c6286c02be5144d832c0fd3c2 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-fxp0-INTEGRATOR.bin.gz) = dc5760fca180affcb51da10f190dffbfd1b56cd1 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-fxp0-INTEGRATOR.bin.gz) = 56d1f1d5cf1faecbd845eb2a4a8fb88ac6d54808c87a6b39c70249231a532c7b7d858d5d89981f5feb726d93bfab384c6e5b8697a020e1c7ab495c13a5580e6f +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-fxp0-INTEGRATOR.bin.gz) = 9be387154227f881c0ed38529c7a7a6916a59433 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-fxp0-INTEGRATOR.bin.gz) = 338ce4a5cb70414c375f3ef8cc9385d6 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-SHEEVAPLUG.bin.gz) = 9d9cab4789700632fb90b593893a81015b51f619 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-SHEEVAPLUG.bin.gz) = b1632b6bf5b3e6ebe3b8f311d8de3218e42e40bfabeabb2ddfd99285b31a0451e4ee4267d0dfbae1618c023b52bbeea5b76aea7162d4bf108f74538b5aa535b3 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-SHEEVAPLUG.bin.gz) = b6861bc0a0266cf68f5d91e6e3fb8c7da61690c5 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-SHEEVAPLUG.bin.gz) = 9da615e9589e8b82d9a7e30c680d87d1 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-SMDK2410.bin.gz) = c7ed735255266257fb135c4abc2187199970ad3c +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-SMDK2410.bin.gz) = fac2299142fe0f8b45f7a433b756d1e48e66940155cf5dd53bfd6bd2827d66fbf43c08306a0cf5d69e25ece03253ce5f806498cc925786d55973f95bc6079c7f +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-SMDK2410.bin.gz) = c3a03ab1bcd188d70b889c6384417025abe0f459 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-SMDK2410.bin.gz) = bc3474cddb53421b463c1172621fd278 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-SMDK2410.gz) = 0b08bd196892dff6fc1997afb9110e3f756f3124 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-SMDK2410.gz) = 77b0d553364442904b9b08a3db76c70a7306b23b1b9f71a495eac9b294165da023d9ded9f8ee86f6e0ef336b514d83461cefc63885f754d4f6e03ea208842326 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-SMDK2410.gz) = c0be26eb32c1d60435e1fea7521fee95660772fb +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-SMDK2410.gz) = 79e74c16602e752a034f0d93be2ca62b +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-SMDK2410.srec.gz) = ecffff46a8c528208595aa47d6739be05f4be815 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-SMDK2410.srec.gz) = 532657ee54b385c79c7ef9768044d4d4012f16f54eb0fba2b743cadd66bc8288b00fac818503faf00db6f28a54f2bf51c7bc7f6ae8d5562e84a60149af119e63 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-SMDK2410.srec.gz) = 749c2ad2c37bc095893a6ae9bf2b614af1effeb6 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-SMDK2410.srec.gz) = bfebb327393531018e6b9f6e66738805 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-SMDK2800.bin.gz) = cbc1ebd6e56937148dae2c2d968add4d8b3df600 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-SMDK2800.bin.gz) = 463210825ff997e4cb1a7dcb36ed0d0f352ce8ab72ce55fdadfdb03f38d18fd524452fc2129942cf78d2911bf7be4875df238a03f8108ce2708944ed8a9682f9 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-SMDK2800.bin.gz) = de526c5e982f7173406cd0b2fffcea1dd4fc9a7e +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-SMDK2800.bin.gz) = 9c8cdb5067ff1bee4fe4705cc1cfebad +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-SMDK2800.gz) = feeb3ef6e66284fa727a9feb4f3d7c45fedd0ca6 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-SMDK2800.gz) = 9ec41f1cbabe0c960134267ec18fe6f1c5d8062489735a85bd3b1b8d9ee2acbbbe5f32c8e8e416ba3bdd55e563dc25c8224500702bbc5038e7bc5f91be5fed05 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-SMDK2800.gz) = d03357b46454c1ffef1b1e3524c8b56a61336a06 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-SMDK2800.gz) = 39dfa81264cd40fa3e0baf2db3f2fb8f +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-SMDK2800.srec.gz) = e7908babcfe4f8e9400a83351028545d87c111d1 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-SMDK2800.srec.gz) = 3e13a586fde15f0fff6be7719975eb9f2fb1c4778de5a19b30b208b050e2b8549de137c5820b0c233af3bb32d4b0dcbcb7d50d4012c6418146c78358f11ad194 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-SMDK2800.srec.gz) = d8a910ca9c3b14abb626d94cce73ffee1d951258 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-SMDK2800.srec.gz) = 43252ffe4ce1a12b526af0b37aa7a2c2 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-TEAMASA_NPWR.bin.gz) = 1eaa16791cd37e16ece1fd2a3f84a9f1b744de4a +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-TEAMASA_NPWR.bin.gz) = c12fe5137c903af5a4291fa06d95408e1a554ff70834036766a971693edb8164dbfecd8783ced92f548a42eb354da31e658e6ea3b347cb41d7551a85ff14b441 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-TEAMASA_NPWR.bin.gz) = a630baa7e17c1dd8e67f5d925fcfa782301efd09 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-TEAMASA_NPWR.bin.gz) = 8bf004134779adbfd47e710810cd541d +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-TEAMASA_NPWR.gz) = 8f750421edb291b7231b9ebb2df970f5da937ba5 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-TEAMASA_NPWR.gz) = fbd4cc574e78cbbdd68754790777507f8b6b6288e05cb5261423f21545ff0825c9be03bc1ec663bf6a5552ac6686cff980ed1f2e4716a4690132058107a6fcf3 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-TEAMASA_NPWR.gz) = dc315d5e0fb0cadb02954e75fb78670244ad1878 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-TEAMASA_NPWR.gz) = a0a2a1a1e5fa5e566b076fd1925f5a0b +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-TEAMASA_NPWR.srec.gz) = 27a486313bf959dbdc89279b8da39ecb7ebf7e6d +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-TEAMASA_NPWR.srec.gz) = 4dca299d4f9a90a2bffe3ffea6b5262e6cd248b9abae0fbd838e6bd83502fd573428952180f2dbd77284907fd7b1ffd1ef0c7524897dce49ab05c8c3aeec3aa3 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-TEAMASA_NPWR.srec.gz) = e06dcfeb9376bb44f0444e71afd03c51754ad533 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-TEAMASA_NPWR.srec.gz) = 0478aad2e41f791604d7d9e33efc16c1 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-TISDP2420.bin.gz) = a9c56c83c032a539bf23ac6250412bdd71a996a8 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-TISDP2420.bin.gz) = d61d6f3e0a937039f13182d03ef1bbce0ff4f04a0b59e60096fbffd34f810d8e254d8e42b456a2be03bd84ce127cbe40e12c7864c85e4bf963ec9761ae322b9c +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-TISDP2420.bin.gz) = fdcb7c9bf1b49107c95e7c0731a6ca97922dfceb +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-TISDP2420.bin.gz) = 23acbd88065f394218ead9a00dbc6daa +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-TISDP2420.gz) = 2d4f5baf51625ecb75fc4d043d248ea326c13102 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-TISDP2420.gz) = 2bb556b33c74bc49b82693a4b66437498f7630709923aa54ae0cfbb0af50f5d28db62d062eb234e6c5b33bfb081490e9cbd687a899fece106756c79abe325a85 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-TISDP2420.gz) = 84c7b73fd2c20914727a86e8aeeecba0e3b54ce9 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-TISDP2420.gz) = c1ef3736981fd98a6f6636a8785066ed +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-TS7200.bin.gz) = 80dea7855e77c34fa5a6df8fb657f23b02777a71 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-TS7200.bin.gz) = 673533b24668f44c09364ddb22f1fe3e058b5aacb2c544b0fe2c70eba9823e8aefcddcd02f6df8fabd74b5283e585b30ae33501e02b7edb7bc05cadcf8deaf07 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-TS7200.bin.gz) = ba834fcc21f7b5210f10388a209172e2a1554944 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-TS7200.bin.gz) = 6228219fac300e28fee657b3d640d2cb +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-TS7200.gz) = 5d321821199ef390140e42f5de3aadbef178ec7d +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-TS7200.gz) = e5c98ca85a4a926860f11a84abbfeadbfdf2ded1f7ba8fe4f852e48188c16878016f66bd79585eef8d8cf1afa28be748ca144cddb742029c27b97051224fd41c +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-TS7200.gz) = ce45d65a2eeb0e8b3af0ce02b09a1dfeeea56d3e +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-TS7200.gz) = 9b77d5ea8b37b0550d4610e53bcce56b +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-TWINTAIL.bin.gz) = cc608ec28ab6439d45fdcaceb2608d00b20f5739 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-TWINTAIL.bin.gz) = 18d2c25112a185bf5b7e23a7c30ebd183a29f16cbc79e11327fb086efd8f04faaa1fdee8ecfda8de6e437eea0ef79f788ee89d4388aa37fbc88331ba3a8cfd4b +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-TWINTAIL.bin.gz) = 85e82f3918141510d0f3b9741fb10e15616d38c8 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-TWINTAIL.bin.gz) = 62e6180d8bc9b2ed8ffd209115083506 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-TWINTAIL.gz) = 784f311793c86ea06397c5e35f93833f1711c92e +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-TWINTAIL.gz) = 3d481b051578603414849bf1e43bc84cca28049991640d3c41af3bf1f223623e46200c872cb29e3f98ad2bfcad5c377c1b489f074ac390f4ac9a04b4260e8c77 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-TWINTAIL.gz) = 17e6e1253799aac23cb810aa24e81c060115d311 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-TWINTAIL.gz) = 823ed2d54f115836527299f9542b1531 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-epe0-TS7200.bin.gz) = 0d27b6fb7baf68c25f5e37005c6864cb82e075e2 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-epe0-TS7200.bin.gz) = 70d04bcb2896f6e27c0278189d57549f9c3a286e43a827a704255487095123fb61b00b155750fd007491e42f5498d4fb207e9ff40d32354d1bb8b4adea67db1b +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-epe0-TS7200.bin.gz) = e2850dff5c5d6a2dcb975ed69d9cdc3dab59304f +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-epe0-TS7200.bin.gz) = 1b5cd32ef196ccff17b3a3bfc3a790f1 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-epe0-TS7200.gz) = 2778315d331ffc62b829685c27668514472f3e19 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-epe0-TS7200.gz) = 1fb7e68c7599c6174abce47d01c5376bd37e966342c5b377e0375e050200737f507c34e76653377a787bd9ea11ce526c0e52fa01009d10ccb4e124b77f59ac33 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-epe0-TS7200.gz) = 08efa696270c86ab0b2ccecec2f65fd0f6ed07e4 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-epe0-TS7200.gz) = 103a3dadd04cf056386a2b7bbd0d666e +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-fxp0-ADI_BRH.bin.gz) = 11f132f4c6e60f09f84e8cc536c38d125336373e +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-fxp0-ADI_BRH.bin.gz) = 0a6442acb206b96f9450a80a1a02f5420fea62d96464695490a5efdd63b11c30ab38e2ba270fbb4125386a5b3bf452ae44427f75fb5dd675202e862301cf28ca +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-fxp0-ADI_BRH.bin.gz) = 14a2ee2c2477084bd47369e3ab5bff9ec5163a2a +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-fxp0-ADI_BRH.bin.gz) = 13646782aa47578a9ad12f7c07907633 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-fxp0-ADI_BRH.gz) = 41474e92c5c2634a3ea25bba4510dffc8d2e399d +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-fxp0-ADI_BRH.gz) = 269cfa9fdab9f28e0931d20e6ff68284ef6e578d11c1c2b23fb272d9e82b12b19fddec101e24032b479c15ce8042efd2265678cf7a3e951e6b2429deb2de2b11 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-fxp0-ADI_BRH.gz) = b080ed55c674ec69554713838ef050eba2a195a9 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-fxp0-ADI_BRH.gz) = 37ec6bc374177e34ac79e774e15cc679 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-fxp0-ADI_BRH.srec.gz) = 98d97a466e67c472d2b778cabb6ff6196b379079 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-fxp0-ADI_BRH.srec.gz) = 8ea14e0483850adef7d6bc614527739e9f3d1880a03522ca6d7c3df1e38222200983ff4fca413b9aa2c2e6d90efd5170aa7b43be8ea68eb9c8cb8f024c9954f4 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-fxp0-ADI_BRH.srec.gz) = b88e4587b48064fc6719bf3e776bc3163efad390 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-fxp0-ADI_BRH.srec.gz) = 5b59dd3b2796db425638472b47970280 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-fxp0-INTEGRATOR.srec.gz) = 77140597384a41679467c0cb3814f4524f5a7fbf +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-fxp0-INTEGRATOR.srec.gz) = 104d1a827d7a622c77139c4a5f6f36a205d708ffa3f3b438ba139981aaca00342288fca6adc82f00603d0210e05e9187fd4fabe3a79b3ab0baa5899a72ce6253 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-fxp0-INTEGRATOR.srec.gz) = 3c1e9ccfe1c9df8c07976c82348191273a09024e +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-fxp0-INTEGRATOR.srec.gz) = 4a503d1c30776dc77a7dc3ba3e160f37 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-fxp0-INTEGRATOR.gz) = f74be1c541128bf2c1bc8992058df64b48d1fb97 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-fxp0-INTEGRATOR.gz) = cf97c8ab92e45baf4fe64c2d5722391cc35569c035143371cdb746c9a3704954a06fc336c50af51f9f0b198a5e05d6e7e3a3e5b5257ed214489fc124525b8104 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-fxp0-INTEGRATOR.gz) = fd503fa3df024d8aa2397a060e986074453d8ed4 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-fxp0-INTEGRATOR.gz) = 240f52b880f6c81b4e67314404fc5a97 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-IQ80321.gz) = 55a7ccaf693a8f72322bd4e898b4ecae4a8e0c80 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-IQ80321.gz) = fd40bcb076b661407034b45baf50731dfcdd9ff9f78b4768b0c300fc6e0187204fba1e9491c8ced8a12e77070a3f599608d7c2c649222a142efd0b799e414499 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-IQ80321.gz) = 6e69674afd923ffa4e320a7c1cdde0224959b3ad +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-IQ80321.gz) = f783d0328ed41dac449058e80fa81dde +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-fxp0-IQ80310.bin.gz) = cd7ca6c6ba8134af29a1cb3c4db19e80753b5cda +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-fxp0-IQ80310.bin.gz) = f1b0bcc810fa29ddd4102477ea422457aca2e037964a284f1eab1b2e31c4c408c5d495eb489c7b4b5c2c578998a9643f68e8577670b9b04e177b5147dc6b17dc +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-fxp0-IQ80310.bin.gz) = 2e7c3d70ad38408b2e24ef3a6e3a5c22c8724706 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-fxp0-IQ80310.bin.gz) = 693dfec6cb311df0ba890e55c610121e +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-fxp0-IQ80310.gz) = a5ed3ef72be67e59c81f1701c630e420c19df6c1 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-fxp0-IQ80310.gz) = b9b4dfb8d4aaabaf3346d5af652fb4d79b15c8ea43eba94bf3ee3b0a9f05bd129a050ede2b4c127f14c3df1149f7a9f965499d09a55640eae83151c42f054dcc +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-fxp0-IQ80310.gz) = 12ea272d03d51081eee0ab7858e05bd77c21a86d +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-fxp0-IQ80310.gz) = 114b5ae7efcf519aa2f969e827ef03a8 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-fxp0-IQ80310.srec.gz) = 01d52551442d858c9e8b9404311a0c3e421083a5 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-fxp0-IQ80310.srec.gz) = f74951ab8e5b2445643c046bee3d34c67310399a84db9b0c2e1c3fb7f460eb1d863f520c6703f51f270d6cd1bdd8ed0569bd32fda709e6f62a4ec9a8088418be +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-fxp0-IQ80310.srec.gz) = 9baca8969db5db172716ad6b6e9154c42c0816ec +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-fxp0-IQ80310.srec.gz) = 60528f9ba917f0412d4c9026c58dba5e +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-mvgbe0-MV2120.bin.gz) = 1d0c2b24a143a451f4ea9e11f4580e45ecab2237 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-mvgbe0-MV2120.bin.gz) = 367845db7dac4bb80eab23acb6d40c193ac2c53239deca54acca2adc5c1161240755bc9dbf9ea4082b48b83eea70f4b01909c46f26f4221df8af74cf64524cd5 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-mvgbe0-MV2120.bin.gz) = 5bb353dba0b6a32a0916359fdaa5b06a260de51c +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-mvgbe0-MV2120.bin.gz) = 56c549b0fe6d221922b59b7ae00c6ca6 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-mvgbe0-MV2120.gz) = 72017ac40eb0de30cee8ffc340e9bb7f33cc40bc +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-mvgbe0-MV2120.gz) = 836362bfbeb34fc0040b9a3492012e1dbea1cf8c1b7bc6afa45c59e784caa1d07be1b829d10e807d1701d71d6350a3d1a5e63ff71d85cb3c37fe8b9b4f65c47f +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-mvgbe0-MV2120.gz) = d74682aaee589c7ca089a49bbaa6029175d13c3c +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-mvgbe0-MV2120.gz) = 6712477894ae747784d281b4ea595131 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-ne0-TWINTAIL.bin.gz) = 0044ec7b51299209fe8a15443aace1984350d1c3 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-ne0-TWINTAIL.bin.gz) = becc7276686635e6b10b03d8374f1a24526066692cdfcc72d556ce07a0a06ac44144ed011451b4542105211d9a9d0b24f408d193a932bf161a52cebcb49a6e06 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-ne0-TWINTAIL.bin.gz) = 35e63f0805242303ded144ee50f429ed6b165797 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-ne0-TWINTAIL.bin.gz) = 56670b2148acf612495ae5a30662bedb +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-ne0-TWINTAIL.gz) = 3e68e8b0d100356489f0a5b027c19139ef9e97ea +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-ne0-TWINTAIL.gz) = 6e87c01ae9a15702a15b2d6eb36a7a4ddaccd3ae0ff9188b3aca9f3c48207443829e2b57cbdbbb01b958cec1f8416e326547380928c928d0fe67a66adff9d2d9 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-ne0-TWINTAIL.gz) = 50496c450bc32fd7da2e16674eff08df7e3ffbc9 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-ne0-TWINTAIL.gz) = 2d40cabe8960a91cb7b995cac28c016c +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-ADI_BRH.bin.gz) = 4fce330a36c78eb1de452bc0df57a84b5df02ddd +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-ADI_BRH.bin.gz) = d021074a1083f3cdf55ac1a1ef9a1e93268b418e36c01bc3a401d52d418f8402c19cba1c06a380c86c0b9f5f552cdf7cafeea19b2f03dfd46aad733ac7095479 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-ADI_BRH.bin.gz) = b573e7bcafe3e1d1fc25aa34177b9c5d845095f9 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-ADI_BRH.bin.gz) = 5035eae6a7bdbf82b39960661bbc1548 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-ADI_BRH.gz) = 3e5e3eaa9d205254d39746b8cc9c4291fc1a8aae +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-ADI_BRH.gz) = c454baa740a1e8e7e16c027ca4da512731a8cee8d265bd7ca7110fecb1019cff0e5b0db423aface71e0228639c4a7465108bf3fe69b9d711bd5f5113c4a0a6b3 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-ADI_BRH.gz) = 1aa0d312767044b044041a1d9431b7d4b4841bef +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-ADI_BRH.gz) = ccc8b7e6d1627a24e5ee493d3d769681 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-ADI_BRH.srec.gz) = 9e3be145e73c346fc467de425aa5ae84c8e86dcb +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-ADI_BRH.srec.gz) = c7f1566fa1665b6f81a36e0c4f7e00f1ccb08af73698d5d938fc26770c65f5485da4c106cde8aa8518fc312208c58182e4a9e6bd92f2cf6c3b7ffd0c822e8fe8 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-ADI_BRH.srec.gz) = 5446c67277640bac0811d35a413b2c9747d2f1f6 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-ADI_BRH.srec.gz) = 9072dfcce2a2736faeff274a61d6b378 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-CP3100.bin.gz) = a8aa9bf7afaf2468e38fd8f9f3e2fbf1957c47e6 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-CP3100.bin.gz) = c40af33b0a32888b18dc3e05cb747269ccdeb38f7fea3457be91688e44ee256754d8b31489b9cb6495af63bdfc6a6ea16a6f800b70f5f567d85130ca50ead974 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-CP3100.bin.gz) = b0b41be5da00dd6a4c84277bfe39975a4cfe31a0 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-CP3100.bin.gz) = b63766732a4710924581351a1778f71f +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-CP3100.gz) = 6a53fe270036359318eb84b30bfd04f089cc6e6e +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-CP3100.gz) = 8c61a2d1a08ae6c889304a8a1335d0b40d092f4f7a1ebc0a14fb721efe1d56fa7c3c3a43c65249754f0bd1baacae5f16a6ff497c6146c6c1fb805aeb14d07f65 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-CP3100.gz) = 1de7507b9869a86de2468c9200d728f6a379148d +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-CP3100.gz) = d878c13f9a7706e55848df3b09563620 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-CP3100.srec.gz) = 4a762c7e63648a321e727cff47e99a01570ed1ee +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-CP3100.srec.gz) = 19e1b9284fe2a46a5952c379400bb1d74117b3b8d2aea91e6820c1356f4e6761add87d462ec0a14a545534d1e17f211e505f539ff681f39eafa10b0893b13038 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-CP3100.srec.gz) = f4b31cb80b5da3de1ab654f7287e544ca9e761cf +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-CP3100.srec.gz) = aa4640c78d3499c1bd1b6ade6b5564df +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-INTEGRATOR.bin.gz) = d297e9f63876e259acadf43d735d26c70648cfea +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-INTEGRATOR.bin.gz) = bba032dbe3a47aa40f45e232a06c38edf352515983e9896b56a28510fc031edb12a3b462ea799bcbe5e3dd2ca7585729c40e8203a02347aaf27f367ebc027cf8 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-INTEGRATOR.bin.gz) = 3c2d8df7cda72b357e291b47454859098d5a71b5 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-INTEGRATOR.bin.gz) = 2cb06ddf778f331df715f39fe0443219 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-INTEGRATOR.gz) = 0ed7595924e6d03491d2bd7d32d42d00f96a3834 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-INTEGRATOR.gz) = 0e33713d7943731f3430b74e4a72cb98ace2878790ad7dc2d185f0e8a825c2a9db9c3194418bf91ebb30c4f87659d1de36706b57349a38d85e584456071d2d84 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-INTEGRATOR.gz) = fef4dbb06bdf1299ffd2719ef5c147f51704ae0d +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-INTEGRATOR.gz) = 142bf1b95c4e72d91063e29379b858a5 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-INTEGRATOR.srec.gz) = 4a12c83305d58e03cd8c49f05cc6b32660939700 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-INTEGRATOR.srec.gz) = c7e132403f37ca9514a8bcd8c8a94de04fb63a2319b1510db5ce9f14d60ff45778228e4c6d9ca5b042bd16ea26396e035a31f948908bbff152a7bf9529b3854a +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-INTEGRATOR.srec.gz) = 306ccfdb478dae1136303199e84f54f1e65a63f9 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-INTEGRATOR.srec.gz) = 4805ccd3adcb1ff438b7c4d900416284 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-IQ80310.bin.gz) = f3f8c21960efb2c67418c29fef978e98b472a813 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-IQ80310.bin.gz) = 7b37f0c129e92372d4f170ab4106c2bcbdce9628c03a22ee1a265ee73263e78e3befbb712ea1f241b2e2b0e0b54bca3a9b3f7628927a18ee28551e867e526bf0 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-IQ80310.bin.gz) = 237204cf97f62dbb37ec28d9a12158f3d7ec01ef +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-IQ80310.bin.gz) = ed5f31fe08e40a01da35e68a8ce24da5 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-IQ80310.gz) = 2aee3ee787581f73d3e667aaa72e5211a316db75 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-IQ80310.gz) = 6a131f56fb801174037294c32a30244a500fa4bcacfccc65b2e1904b63450cd0ef0656dfadb4eaf1db651b8378070b97a93ab2df053641324c345766b4b043ae +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-IQ80310.gz) = f4a9d9ec37f3a9bb98055681735399a914673fb4 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-IQ80310.gz) = 25bbb323800e83e721976fcf4b5d42c1 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-IQ80310.srec.gz) = 766410442e0892a471e2dd4420209f6974ef16ca +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-IQ80310.srec.gz) = ce977a4a9c87431fc57805ee22efe908bb79a344c6a1d2f3c75b974db3b54626908fd25e524a4ed3f55327877c97f78e9496515fd6c4677fd98b3c273ccf1c2e +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-IQ80310.srec.gz) = 093855469bff467f4744c3bf678d55d9eb08b951 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-IQ80310.srec.gz) = fead543e57b7c2f2a458d451b6c59f08 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-IQ80321.bin.gz) = 257ee7c14d678bfbe2511fbd47d72f6c8c461752 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-IQ80321.bin.gz) = db6a78dd47b3298d8f66fedb46e00b6c269e3ea389aa276480c947f606690002c95e7cc2306fe7f243117da3894ca7f7ce9b3bbc12e2cbed4d17b0ece02dddec +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-IQ80321.bin.gz) = 542ae9874a3223e014f50d542c9a677d0a0efdf1 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-IQ80321.bin.gz) = a70cbdb6278eab864d1bf3b288c3392b +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-IQ80321.srec.gz) = 697561a2e82361d2d92775821ea4cd03e163c217 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-IQ80321.srec.gz) = c1959211704f091e865ee26560496424974c0dc3ad3085df21fe51b21c95a56d7f024f833728f9748b02f4ef409a24454ae731d071764921b0fe57df38a3ed3d +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-IQ80321.srec.gz) = 7d95cff40a30f44d91013c8bf2e13a540470e5cd +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-IQ80321.srec.gz) = 7cb2d5067df40372c016211fee729a1c +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-TEAMASA_NPWR.bin.gz) = dc0f06b24ab21f8188a4e3f0321246acf541854c +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-TEAMASA_NPWR.bin.gz) = 13a84014dbb366e32bd715279e46c67a00f09cd40eacdc0fa91cd0e8a7e3e4862110161ca56be8024d3a0cd14f2a17c539111b366e91a27c65c5c47a741dc4e2 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-TEAMASA_NPWR.bin.gz) = 79967e4ee6c3b5038007f8deb9b6ec9172bcd4dd +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-TEAMASA_NPWR.bin.gz) = c5caa593ac363dd9dbf8f44de4c06099 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-TEAMASA_NPWR.gz) = 6f5c0d944bdcf0b3dfa76f60e6b5035dedc94c00 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-TEAMASA_NPWR.gz) = cd56585b5fd7a8d4c15453966942d48c538004a142daf8b0f30d26637e82e0483dba20680a303bd561341b0c35aa4a537f6a24764bd96ca8102fb018d57b22c4 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-TEAMASA_NPWR.gz) = f0c30e5955068a64ce24eb6d96793fd4cabebba5 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-TEAMASA_NPWR.gz) = de797d7956e6fd360b2f4028d05e7608 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-TEAMASA_NPWR.srec.gz) = 0689f7b9a0ff0140a28fdcce4d8cd206d566c680 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-TEAMASA_NPWR.srec.gz) = eafe6cf5e618cf43054145f925f154d99acaffc7eff8d4be2bb801de61c27193debb983412b45c4b14b5dc834633452f89c170a895078ccd31f00a5a0685661e +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-TEAMASA_NPWR.srec.gz) = b07d921cd736ac79d88e8f0e041db636c198faad +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sd0-TEAMASA_NPWR.srec.gz) = 146f7101d810d5b401dc3b320a2f89bc +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sm0-GUMSTIX.bin.gz) = 393c30bf2cdc7bd75e749dd8b2537bd77dc91a65 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sm0-GUMSTIX.bin.gz) = 44d1609a6be448f0df6d7f733a9fa544fdc673da11e0b64b66174a9889b4bd6c069c69a312853954c0c631eb036f37ce56beac486e347e600be01de6c9c3a73d +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sm0-GUMSTIX.bin.gz) = b7b4482aa76347a87722d9eb34662af96fe94e00 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sm0-GUMSTIX.bin.gz) = 6bc478629045ffcd392adc0f5c9d133a +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sm0-GUMSTIX.gz) = 1ae50b9a6c3554474481cfe3c37dc88bc29cc436 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sm0-GUMSTIX.gz) = c1827ec89039136799b21418e0df33992f4ee4c166c130c34865f22cab0601fde056078892a76075714bb3ff09dd1edc54f33464c0dd8854f303398b6357b09d +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sm0-GUMSTIX.gz) = 823391035b738182fdee19bfc807eb2f09573f1d +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-sm0-GUMSTIX.gz) = 46159d039abfeb7e9dc00177ba1f9271 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-smsh0-GUMSTIX.bin.gz) = c7bb680f57a438d65351ba2e665b0c98b979fb80 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-smsh0-GUMSTIX.bin.gz) = c8cc5ec9d35ef1c8bb0db010e358f331335fc69db09f67110a92eea46eb275950f2ea5cb4e9f88ea2ed80561a5e31d88ae6f76e5582c448f3df265dc6141be9a +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-smsh0-GUMSTIX.bin.gz) = cfa0506e9de7a97955bf05bb9d89275ae65bd77e +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-smsh0-GUMSTIX.bin.gz) = ed0673b11f604500c60263dd3dca3991 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-smsh0-GUMSTIX.gz) = 6a22b3a0b0baeb17201a15a1e46b6a1bc22345f5 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-smsh0-GUMSTIX.gz) = 1a44e1fc731b0099fc726ba2362c5967f0073ada7d036656d5f60df865217349b5304bf05c7699662f582ac2519f2db64ee774bfe58c1780824ad04c8ddc8390 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-smsh0-GUMSTIX.gz) = e5872e39e97e9a9e1d72da6d35d5a8013e168b59 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-smsh0-GUMSTIX.gz) = 2d76c6a78af5dbc9a1e5200819e53511 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0-ADI_BRH.bin.gz) = 298b05e33ef85a4b937c2a5e84a48022e388d0f7 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0-ADI_BRH.bin.gz) = 3d709cc48eee7fad9cd986542430e23a4b81c84e549d2f0f9210df57a38a9d36eb3abe1bc2ccf2c66d9ec84575bdc9c1b55981f3686de5ff857b55f86d9ab661 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0-ADI_BRH.bin.gz) = c2d4ab46b1b90b55bc40c74d31f287487f781142 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0-ADI_BRH.bin.gz) = 91e2b298632e8fa0ebebad32ef0df715 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0-ADI_BRH.gz) = a63011e3f96507e9585442178de4c0e41338cf87 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0-ADI_BRH.gz) = 76b99b424e4f8cc4f47b0ba7ed8b4679a5d49ea3a022a84d2cd74be396bc497f481fb3fa16e23deac876d5dcbfc9a29f745bb1672d2844fce15252db989c7677 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0-ADI_BRH.gz) = 8cddff412a5b879ce5b17a5a22b09603ae9f9324 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0-ADI_BRH.gz) = 85c7096f583e4f9f3841d7f663de4999 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0-ADI_BRH.srec.gz) = 83cec666fdaa7fd2d5fb6de32461615839932cc6 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0-ADI_BRH.srec.gz) = ec118ec8fba3c15ba1b6725a1b9778d14c4b4fc6f624d7979c281d6195271df3bbcc6668eaf0bb25b6089243c5d7b05e43ca6247e3d72a548abfff0f31f14f10 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0-ADI_BRH.srec.gz) = 6741604d5336591c02e6a9fce7cd093f7e0703fb +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0-ADI_BRH.srec.gz) = e98cf8ea7ce8704d98880ca519bde38f +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0-CP3100.bin.gz) = faaa399c0796bde9609425f73ebf4b7436516a09 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0-CP3100.bin.gz) = c61821bf159dca3ef32e69aff1f935a9de0228e5e0568afc74dfaa5e91902fdb0b13589e70af2871b3c7afbe2cc3777be64e9bf52798534addd6338ef6fb2095 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0-CP3100.bin.gz) = 081460e1657d3f542615c9b63d2bd8638d4f64bb +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0-CP3100.bin.gz) = f79d3833d46191e99e7617029c981cf8 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0-CP3100.gz) = e56e0fbbbe556a6741af58398b3d7d116f3ce469 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0-CP3100.gz) = ebdbee8f4ffed5e2ffbb7890a8e693299e441aa70aa5a7249f1b468373970bc29d2284d82bf638cbbc258ee8b500ba5b3244b83fedcff1e1465218d9fc76575c +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0-CP3100.gz) = 881461289bc9ee95132cd5997c19c3838aaa6c39 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0-CP3100.gz) = c5d42e48168ba69e065be3f44d2e2e09 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0-CP3100.srec.gz) = 1fb817599a91b10187301c3f2333dc6484451556 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0-CP3100.srec.gz) = 19f6d85d50d1fdd5fbabe1f60b67992acaa80e0afa44ab7d94f31e095592b7852f2c8f42227bd9d90de9698211085a69aa86d4076100711f96e59bd446317164 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0-CP3100.srec.gz) = bd13c2dec6d22ca3e1d245159b0e765ff03301bb +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0-CP3100.srec.gz) = 916df9db9485676f33a5bfd017e4cd2a +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0-IQ80310.bin.gz) = 2c81eb3878a53e36a554b1f4e91c5011ce4ba507 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0-IQ80310.bin.gz) = 2aa85113e7bf69371c8027929857e4c35623f07a16db83bf1cd3824053776e0daf33ab8ddd2e954b938fc33424ea044101c6f9c6bd500a32b030f28ffe40049e +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0-IQ80310.bin.gz) = 1e1187fd6a831f7e9dfc546280681b924c03b36e +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0-IQ80310.bin.gz) = a767b383bfbe980c1da78e744144dbd3 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0-IQ80310.gz) = e60bf72e33a1948bfdf1d84a209b1ab6e4ec6522 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0-IQ80310.gz) = 9459f4a7532ac2d2890c538a3325c217d1ba468db8e8d4c7d2fae8e7a4ba256e0b0453e5757e1e2ecfffa5f1382d843289279d471562911d56215f2f3ee73eac +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0-IQ80310.gz) = 95de4a223120d3c34a7862edb781345652904ffc +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0-IQ80310.gz) = b7113d5899d418131a2d376711e32379 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0-IQ80310.srec.gz) = cc193aac830dabd4793f1fb6722cadc6fed0bdd4 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0-IQ80310.srec.gz) = 05a81920bb52518267ce4046aa79824a763dca9643146646bc6746d16dab1854140d28dabb5f7ba1ce9cfa1cea3a2e9d76df3bdcf227da89ea883011c464a579 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0-IQ80310.srec.gz) = d458f2b8a4afddecde3bad093576b0b6a17b2f3f +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0-IQ80310.srec.gz) = 9d205882f4befbe25707f009910f95b2 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0-IQ80321.bin.gz) = 78884cf87f77551ec0e47bf3d629b41ca5a4420e +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0-IQ80321.bin.gz) = 094252727a03ca3dce207c5c92959ba21a888bddf502d5a9ee9709bfbdf9eba5d60dae5793ca6ab5dacf720d475499710d70b36622b97c1449badc5ba85e82e1 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0-IQ80321.bin.gz) = 4d7b190601413c8c89ed39d8dee44abbd388d8ad +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0-IQ80321.bin.gz) = 6aed071b41867489457065cc3bddb0bb +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0-IQ80321.gz) = 771add734839295eaeb51bb341d43cdeb64733b9 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0-IQ80321.gz) = 1ad26279054ef65ab4c4c37ed2443087a04d530641cd005b7d02dba395bad6770270b6f4e5d9ee522fde9ffcf3e4842e704b4fac2896eff2e73db39cd4c7e96d +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0-IQ80321.gz) = 578a063f106ea04a6e8133cfa3c0eb94b0decac3 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0-IQ80321.gz) = bc6fd4df95278bf2e327a3b85a5528eb +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0-IQ80321.srec.gz) = 1b77033ac9b0bba5b829868fc3a826cc2b8bfc3e +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0-IQ80321.srec.gz) = f14f41fd0600a3502383ffcedc902975372ee3ac03ff8e5ff156e93230eb8572798b00a6049a1cbe6c09d53002a07d6242064068b030a8e588355c0c67508e4c +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0-IQ80321.srec.gz) = 5360066de4b445f57064f767cd41c16d2104da1a +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0-IQ80321.srec.gz) = c4197fe93de106e7b927570baa374dbc +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0-TS7200.bin.gz) = 70a3d642aa8ea8d1a3e9df143a9e453aa1f6284b +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0-TS7200.bin.gz) = 391ac58855b9c24a8dbf8baaab4e9b4efd956eddf343a0bdea8351e1469187798e36ea875d6f4d91b5ba2be0eba5b9b02f33a6eded8fe6d727d3703950d554d8 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0-TS7200.bin.gz) = 7f860a8346d99c80a3cd48694244040d976283ef +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0-TS7200.bin.gz) = 379072e809792e50b4015b9577360574 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0-TS7200.gz) = 0616f7ca1f3ef9c60e4c34aa459b40fb72277025 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0-TS7200.gz) = 8530ac25385210421ab23391925fee75ffd81e369c6b9773034e850519577ec69ba74493a22b08835ff847251ed16bbadc5e86c7956ae88c48e5bd2fff61417c +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0-TS7200.gz) = 18dd6a88210d336fb61e3dcd0826fe50c8d13f94 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0-TS7200.gz) = 10be5c2ffaf39f29b3948473e78ea1a8 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0e-MV2120.bin.gz) = 3ca17c6882a1519488a77a45207f3ed8ea19fa23 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0e-MV2120.bin.gz) = bd41dc8a2e268be47c2900ee5564bbbcd2ad6635f7ab99ff059efb71c27c277cb9da8ebfc34eff5d17839f345867ab9d478d0d027e7980fff4fc3e7494b1ad4b +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0e-MV2120.bin.gz) = daeda9ae3e3cbbf3f5a7a7c6381d13a30070ccaa +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0e-MV2120.bin.gz) = 6eccdeef46d96a5ed0267484262bdee2 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0e-MV2120.gz) = 219f483fe3afb49cdefa8b1865cbbc69730090de +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0e-MV2120.gz) = 937fb99f921b629c1fbecbd60a4de24fe1c55ea70211b03ac15d2b20ae925122a6e3d3b43e34cc8ca6fa9b1d8a1f500ef29ea55f72b1a80a8f52ad43ed6fe1e1 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0e-MV2120.gz) = 437b6861a5f1288ea6553790feb1de02293ed3b4 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0e-MV2120.gz) = 4d05c9e5325526185f0db4a6a11edc92 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0f-MV2120.bin.gz) = a2d678ea1b57438872bb33f8e3f5ab311680ba55 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0f-MV2120.bin.gz) = adc42e2e13bdef6fc24f27cc4cff4363e0287350ba2afd7681e8f3f027865cd7f58e3e5d4fe59131870b34e8e6a8721a935adfb4930957525a24c02cd4c2ceb3 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0f-MV2120.bin.gz) = bc32af49bdcc8ae9226c97ae03f4306efb1b646e +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0f-MV2120.bin.gz) = 344ed7e1145103dd1f747176fa09a993 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0f-MV2120.gz) = 98a9af8c3b74a45940b587383545587a300274cf +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0f-MV2120.gz) = ef6b06092f0a9ada2774b3b172ed405d82f9fb3ea0c3c53c7da7d493f9c4fdd92124970af972342e3134852d9575a80c05f0ab22fcff70b52dfa4007b31c5a10 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0f-MV2120.gz) = 1558754fb8015e4564b65823fa61d74e7ee2758f +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0f-MV2120.gz) = 4c2d594388f5d5ada250a5e9137a2dd1 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0g-MV2120.bin.gz) = 655147b472960f9a2f0addaec681344d62344d52 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0g-MV2120.bin.gz) = 91448fa3831d263781cc4a54b9103ef3fe99f7f71d1b4d5f25ffdc049ad34e9ab84fd38e7703ec55f1875278dc94e808b984b6d6610a0a310b9cb633205a864b +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0g-MV2120.bin.gz) = d985973ac1155c6506fd2dc36208da2c89c1c010 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0g-MV2120.bin.gz) = def424287a7d6e0c9dc9878cb6af8d9b +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0g-MV2120.gz) = ecd70279e4ba36c40e8aa14b9d2705942e48e0de +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0g-MV2120.gz) = 1f4fad54a9a843e66fca15c0ab3de33388b5c94006a051eea03cb3078fce4a671aae802eeb94b410a47b4ea291c7bdac0100359fdd5405fdcc2b0d8db3aad9df +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0g-MV2120.gz) = 16f2789c94f147c86ee94427a2bb0cee353d91bf +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0g-MV2120.gz) = 9df82b31b91bceb714ebd8a7036eec8f +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0h-MV2120.gz) = 7f65f7ce1167b8b0bea66a821a28f8a328f960bc +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0h-MV2120.gz) = 7d98ecd33f11bfcdc1e89d02df391b5c7fb4d66bd66af2713913b9ad8a6de264fb18f64020f009e21f7fe7fadf6cfeadcf72b195be731c5365745d2119a22c08 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0h-MV2120.gz) = d84424851ce6a0cefd0881650870f5c902a50e37 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0h-MV2120.gz) = 2b7ec0cac876ff4758fdb4cfe7e32d7d +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0h-MV2120.bin.gz) = 92236b446b36023cd70765c10fa61fbe3bd2414f +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0h-MV2120.bin.gz) = 2882f6b905d11bd0019d4657586412e93c566abf48d10702af36ccac9f688886fbad3d8ef62c3342bb7ddbfaf72f2cf7510d6635f9388187bd7932c814aea288 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0h-MV2120.bin.gz) = 7bb29d6cd1f68788fdf3a98d198ca7d98e264c7b +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wd0h-MV2120.bin.gz) = a1d749d80636959956efface64861885 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wm0-CP3100.bin.gz) = b3937345ad5103a5331f8f3d9217f6c73b7a2e28 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wm0-CP3100.bin.gz) = 1ddce72f72e631cd8af38d326ff826ac52005cda9974dcf87c33370adf04f90e7a9025177948ef2ddf2f78e259c535bdd5ce2d9da2541f4ca4cc8d57a927afa6 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wm0-CP3100.bin.gz) = adeb55b34d1468ac0fa1ac03ddeb6d86749a4994 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wm0-CP3100.bin.gz) = c10dbd3dd8b711e0e431146585d862c8 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wm0-CP3100.gz) = cf1dad35f06a51619d75518386fb7f0f60330734 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wm0-CP3100.gz) = 085729350310674f285fe2ca0fb41f63701eb1f8f38da50329483d2dd1e4644a84c20815f94cecadf686d925a808eac57a986338aac762e4fe9080b2ad5adf99 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wm0-CP3100.gz) = c51e997b08e72d5e9a1a4953dfca874d4d86d4f6 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wm0-CP3100.gz) = aa4e8b576991e29425d66131a6737800 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wm0-CP3100.srec.gz) = 6823aedd0b5469af8bdc05b9fde2fa1bd5133e48 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wm0-CP3100.srec.gz) = 1b372e4d5cc54171ae399d5d55558e8cc99234c08172c7cd2c83185ec2de4a326aac04a800a050be1d1ef42b60dcc4b20ae25b5fd1f08f707a09926268207031 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wm0-CP3100.srec.gz) = e072eb111fb0bb71c30fc8ad457e1d2711591887 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wm0-CP3100.srec.gz) = db7f9d23f27d533266eda56715e2adfc +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wm0-IQ80321.bin.gz) = fd211bf40ed4f68e9f05bb5f6da85eeeb92e35d3 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wm0-IQ80321.bin.gz) = 1f8dcdc7f7d06a42111745ac2754644cc5796552417f7a0a6d80fb4a7ffa667c6ab577e76f84e2f497d367b244f578b5a1c1d882c558929b12470d02026a3b3b +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wm0-IQ80321.bin.gz) = e853cff382e03161c0354f83f100c67779ecc7bb +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wm0-IQ80321.bin.gz) = 75e9772c889f60ae2baf766aff24f997 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wm0-IQ80321.gz) = 03973311d8dc84c5522524968506a70f3e69e93d +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wm0-IQ80321.gz) = 0582b69eaa266f9874ad02fb21fb7e70fbebe3952d8d2826bc6d58f23cd4d043ff3971775ecd1a12b0a828ff7266677f40c495bf394a2f33c41d372fa1ef7668 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wm0-IQ80321.gz) = 8e8b7d0e5619ca58a50f6ad1f15b2764f9a3570b +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wm0-IQ80321.gz) = ccfc004433b54dc119d556d198e611d6 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wm0-IQ80321.srec.gz) = 72b16c8dea4c9391cb9282e2c1f91e3ba30d9522 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wm0-IQ80321.srec.gz) = 94d123f6a62639d3849b60441d19e49359a922881b8818c11a41cf43ffaccea3e30b5a001e6b96ffea0f6863ca5ed6465d4ae6ea9ec6e91f95c9e498deb44105 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wm0-IQ80321.srec.gz) = 4c94b472797fe5fdfc6bfc8427abe598f7ffbe21 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wm0-IQ80321.srec.gz) = 3c722e71ccd200b5d113f3d5d3b177d0 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wm0-TEAMASA_NPWR.bin.gz) = fc8ab0bc9eb0d8956ade1baa5651d278852ee08a +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wm0-TEAMASA_NPWR.bin.gz) = 00c22223dd564fb484a1a477efca1a4af97bd910a88b722cd3ef05a55f4c56dc90ca0eebb6563ef73106bbe1e3ff1e9c2f51e14ac1ad5277035a1beed8250651 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wm0-TEAMASA_NPWR.bin.gz) = 081ee767155378a6cefb29064e13c46e4de45508 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wm0-TEAMASA_NPWR.bin.gz) = 7c1846c7207b9760e716581a07a5d366 +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wm0-TEAMASA_NPWR.gz) = 72d1968438f4d0b4c063d5b85009669416b39892 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wm0-TEAMASA_NPWR.gz) = cfccacff88e457bf30f0336db8882c63e03fa8ac8eb7d2ae87b7a6bd0eb36b5708eaa512aba0df46ebcd0a89cd7732a0ccadeab0776a54eb4e61ed32bec40df8 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wm0-TEAMASA_NPWR.gz) = 3fdc54921cf7a3e81ae3be6854847d0026720467 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wm0-TEAMASA_NPWR.gz) = 74ef3b97327e4591d8a3d6acb59c6c3e +SHA1 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wm0-TEAMASA_NPWR.srec.gz) = 26020265778b152f20cd35c43dd0a8e8be644f74 +SHA512 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wm0-TEAMASA_NPWR.srec.gz) = 672d1ca404b4dabe7791bbe1506b47e64445c047f92c3eac1810b8deb25e23e6a1e554acc88a307e4f85850df967e521f36c7ffb90da7325f7a3d76aba3494b8 +RMD160 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wm0-TEAMASA_NPWR.srec.gz) = 2e0466a32e150882f148c40d8096b53849a7bfc6 +MD5 (NetBSD-6.0/evbarm/binary/kernel/netbsd-wm0-TEAMASA_NPWR.srec.gz) = 9b35a2416410acc9d4fac08926ffa38c +SHA1 (NetBSD-6.0/evbarm/binary/sets/games.tgz) = e1d2bb091d8202962133475bc83edb55230b9008 +SHA512 (NetBSD-6.0/evbarm/binary/sets/games.tgz) = a147fe6d0419d53d5a428802d0bb6c9fa8a84a76c96d7d6d7c0d399e5af3a69240116463549a83d53387b0214ba0207796d7c10228d92a684fe7ff0ece3aec16 +RMD160 (NetBSD-6.0/evbarm/binary/sets/games.tgz) = 2be515c495548ba5135ff42a75a8ebbfc35ea776 +MD5 (NetBSD-6.0/evbarm/binary/sets/games.tgz) = 9059a6f2cd41cb58827709c9e9a1649b +SHA1 (NetBSD-6.0/evbarm/binary/sets/man.tgz) = 899b9d8242e983a5110ab755651c24f709b5af67 +SHA512 (NetBSD-6.0/evbarm/binary/sets/man.tgz) = 410999db110d710f4bb498c3d7ae7adc62170c7c2f470ce189c92f6c436c5ea96149659c631ef0b5605caaa025d97dfe1c07c428d86f51239657bd6b71717b15 +RMD160 (NetBSD-6.0/evbarm/binary/sets/man.tgz) = c1270f68c6d41b351877f71f0396ac34877dfc8d +MD5 (NetBSD-6.0/evbarm/binary/sets/man.tgz) = df4db2bbfa39ef6a4a215d949653d04a +SHA1 (NetBSD-6.0/evbarm/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/evbarm/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/evbarm/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/evbarm/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/evbarm/binary/sets/xbase.tgz) = 875fd641f969ec00f854ca1334d084947450c740 +SHA512 (NetBSD-6.0/evbarm/binary/sets/xbase.tgz) = 75d0c9e9685b6b7bb706df7427c8b52f59c4fc4d0e725b02ee18024f75a546dc41de5f1a5d8552a8d2c84bdf87856e5857b0f12914801ca7b36b69536d617b4e +RMD160 (NetBSD-6.0/evbarm/binary/sets/xbase.tgz) = 1a4d099d59b2bd882e99f1b2df1c7bf22b890d48 +MD5 (NetBSD-6.0/evbarm/binary/sets/xbase.tgz) = 5eb9c573c5a0c96701f268a3470a58b9 +SHA1 (NetBSD-6.0/evbarm/binary/sets/xcomp.tgz) = 8d7469a85b7433c89690cce74e6b3f4e66cf0647 +SHA512 (NetBSD-6.0/evbarm/binary/sets/xcomp.tgz) = 411304cf66e300a7f162128203099bb4d6eebc4a93ba18ed7caf79f30b31cc7ffcede85c4e1bad02c3f5f8a27d009fb71f3ce5862c1d8aa477f39a25c535fdaa +RMD160 (NetBSD-6.0/evbarm/binary/sets/xcomp.tgz) = 822d26e0ee08b72ca8b991f0709a8c1bf0399208 +MD5 (NetBSD-6.0/evbarm/binary/sets/xcomp.tgz) = 5af361f0334d28119d703064278b3ed3 +SHA1 (NetBSD-6.0/evbarm/binary/sets/xetc.tgz) = 222d14c205f1018cc5a86eb03214d18cda2abb82 +SHA512 (NetBSD-6.0/evbarm/binary/sets/xetc.tgz) = fb82261996aa772fd8a9022eadebf899ee04ee70229ee4fe07758ca14937bdb34752c8218eb4c5b722b6208f719891493bbc141372fcfa503de83e0a61aa7387 +RMD160 (NetBSD-6.0/evbarm/binary/sets/xetc.tgz) = 511ebfe5076f361b7f7ca03a265d16052a16d259 +MD5 (NetBSD-6.0/evbarm/binary/sets/xetc.tgz) = 165cffbb6d2c79663198d80c82afac1e +SHA1 (NetBSD-6.0/evbarm/binary/sets/xfont.tgz) = ce0e141beeffeb5b470478e9887e4127da85de3c +SHA512 (NetBSD-6.0/evbarm/binary/sets/xfont.tgz) = 5d98354ff77103793d56af3192ab5f9afcde62208791976064ac33a149f994e0227dd5dd28ed544eeac5ea504e5212d5fb9e7d05e59e5a48a2fe4062e34e3106 +RMD160 (NetBSD-6.0/evbarm/binary/sets/xfont.tgz) = 4d09f5e82fec875ef0ea328809465e7a98f2ebfc +MD5 (NetBSD-6.0/evbarm/binary/sets/xfont.tgz) = be26b3890261302420b09976a1d38144 +SHA1 (NetBSD-6.0/evbarm/binary/sets/xserver.tgz) = 4ccfef1d49179603286042088bec0218c6b2031d +SHA512 (NetBSD-6.0/evbarm/binary/sets/xserver.tgz) = 809fc0a9065c1b9e7cd17aeb0d41cfd3158efd6c585556af01c4a3c93f0df3646a2ff77c6994449a703a408c0988fc1aa68cf34c7e297a3056d73ded57034c12 +RMD160 (NetBSD-6.0/evbarm/binary/sets/xserver.tgz) = 403604404261764c74f10fab774c4653fd20cc9b +MD5 (NetBSD-6.0/evbarm/binary/sets/xserver.tgz) = 914f909b6878cef16a92765a8cbb52ca +SHA1 (NetBSD-6.0/evbarm/binary/sets/kern-ADI_BRH.tgz) = d9cf46427b7ceed2cbe9e6bb2b62a5d461799474 +SHA512 (NetBSD-6.0/evbarm/binary/sets/kern-ADI_BRH.tgz) = f2beff9ed4d712db8eb3bf1d9e8f60942e3fab2a834b73fed76ac79bd012fccbbb6698e04edd7ce7dba7802852386bdd2996dadc2c8a04a409fae303dace1104 +RMD160 (NetBSD-6.0/evbarm/binary/sets/kern-ADI_BRH.tgz) = 443b7c69a5f5abeaa3dedd3b6213486af56eeaef +MD5 (NetBSD-6.0/evbarm/binary/sets/kern-ADI_BRH.tgz) = 6e3e8b794a16eb8a079342ec0b1af212 +SHA1 (NetBSD-6.0/evbarm/binary/sets/base.tgz) = 74a00851a474a252991743274528e6272f50dd57 +SHA512 (NetBSD-6.0/evbarm/binary/sets/base.tgz) = 154a8230676785921f3d6819d25a2900fe860291ebc2e4891fe94b039871e1515199a4c0e6fe3bb5aba4f9ee802a977e985f87206a1688e4d7e0ad24e1069eee +RMD160 (NetBSD-6.0/evbarm/binary/sets/base.tgz) = c6d3c3b83b8a2a56870929a9d616393e6d19e9fc +MD5 (NetBSD-6.0/evbarm/binary/sets/base.tgz) = 2e26124352843379db4fcc7ab680ec5f +SHA1 (NetBSD-6.0/evbarm/binary/sets/comp.tgz) = 4004f24b5f208575da97b542db46731015cb7573 +SHA512 (NetBSD-6.0/evbarm/binary/sets/comp.tgz) = a0950dab5cbb258ee2f29f2d35173e00a5cfd79ef30b27605782b9f22b8564e05d9633ca6886178c1b1b0cdd6a8112d3a9f663211804e554ac63ac691ff3f9f7 +RMD160 (NetBSD-6.0/evbarm/binary/sets/comp.tgz) = e8a618972f78271ba8a957f4f626b632d1b03ae1 +MD5 (NetBSD-6.0/evbarm/binary/sets/comp.tgz) = ae2425114d29b9fd2136342ce730baf0 +SHA1 (NetBSD-6.0/evbarm/binary/sets/etc.tgz) = e3f3386182b99812eb3fe35daec274b0da1aaa1c +SHA512 (NetBSD-6.0/evbarm/binary/sets/etc.tgz) = 46337fca0954acb3b4e0e6af3b6ecd473002d2f482468ac98c62ee7ff7bd84d90ec9c2bb13d29c5ae608e625f3075471af1da22f8a4254d4e8efc9ab8dcff21d +RMD160 (NetBSD-6.0/evbarm/binary/sets/etc.tgz) = 098b5563540c880d69e0ba9aa793ec9ba6f33a10 +MD5 (NetBSD-6.0/evbarm/binary/sets/etc.tgz) = d3f4709b5264a9a8bd820648330a9653 +SHA1 (NetBSD-6.0/evbarm/binary/sets/kern-GUMSTIX.tgz) = 8a21525ca51f643747145c529add5e1de487f0fc +SHA512 (NetBSD-6.0/evbarm/binary/sets/kern-GUMSTIX.tgz) = f0f9d6e4d8f34b446e511db5a0df6b3d81b20334169caa79790cbbf34a8eaaae0f9da332559b3cb78a00fa05b807b9e3a118474146c69e75d1519c46420003c1 +RMD160 (NetBSD-6.0/evbarm/binary/sets/kern-GUMSTIX.tgz) = 47002447a76cd76c4a2687923682dff473ec25dc +MD5 (NetBSD-6.0/evbarm/binary/sets/kern-GUMSTIX.tgz) = 1ad356834d9467703647793950ccd9a5 +SHA1 (NetBSD-6.0/evbarm/binary/sets/kern-CP3100.tgz) = 4baaacdf8b2ae99e945eabb70c425fd5952eca48 +SHA512 (NetBSD-6.0/evbarm/binary/sets/kern-CP3100.tgz) = 467818af6caa1068437b691fdbc77e11617808fa44e2b3caf3634f7cc8bec1cca7f3a46325825d9427cbfd113eba01a8d3a4d78da832290ff40aa60964c4b42c +RMD160 (NetBSD-6.0/evbarm/binary/sets/kern-CP3100.tgz) = b2a46e69e6b4ce2264eb78a2151274796b224dba +MD5 (NetBSD-6.0/evbarm/binary/sets/kern-CP3100.tgz) = 1528b53a9a8a622972ed1e6891535619 +SHA1 (NetBSD-6.0/evbarm/binary/sets/kern-GEMINI.tgz) = 38ac63a06193c3ad7814b39a11d911da20db6ca4 +SHA512 (NetBSD-6.0/evbarm/binary/sets/kern-GEMINI.tgz) = c05553408f0fde7a1a428faac350de7f969396f9e8caef6e83a269875743472e52435d6bcb1ad5531f9622c1289aebd419cdb02ad83c92d4797e1b4b952e7fdf +RMD160 (NetBSD-6.0/evbarm/binary/sets/kern-GEMINI.tgz) = 5f8d006417864f9609d691652fc03f37f1d12769 +MD5 (NetBSD-6.0/evbarm/binary/sets/kern-GEMINI.tgz) = 0767217ae126cf86a65cb17bdbeb884f +SHA1 (NetBSD-6.0/evbarm/binary/sets/kern-INTEGRATOR.tgz) = a18100b11fa96e4cd1eb1e36831f14c3d17da04c +SHA512 (NetBSD-6.0/evbarm/binary/sets/kern-INTEGRATOR.tgz) = d8bb0260e9e2b687bce84053cb3c88ef6ca3eaf12b79337746e62be94555233c8a1302dc104359b2aa6eb64eac8d633d0640d533688af4c4971a8ea095b96940 +RMD160 (NetBSD-6.0/evbarm/binary/sets/kern-INTEGRATOR.tgz) = b8b57516a6d2c5e62d57dd9437fde58485989d09 +MD5 (NetBSD-6.0/evbarm/binary/sets/kern-INTEGRATOR.tgz) = 7f80ec30a784dddfe53492ecdf78646d +SHA1 (NetBSD-6.0/evbarm/binary/sets/kern-HDL_G.tgz) = 6e95c2e313c04d228a65da51f252791fd1476827 +SHA512 (NetBSD-6.0/evbarm/binary/sets/kern-HDL_G.tgz) = 380861d0bafe812937f004ed00054b6fbcc1dc581fbddf3f745101ec39a57759dbc0a33f0f1e8429a9630febd7ae69e1fc88c75d39c196234260bda58641edd3 +RMD160 (NetBSD-6.0/evbarm/binary/sets/kern-HDL_G.tgz) = 5262674ba10ad272c62440d4f61034dad9be072d +MD5 (NetBSD-6.0/evbarm/binary/sets/kern-HDL_G.tgz) = 1af966fc2df6c623f4147d3cc648d22d +SHA1 (NetBSD-6.0/evbarm/binary/sets/kern-TEAMASA_NPWR.tgz) = 239e37769ab837541fc445e7a74a9bc02c74f0d3 +SHA512 (NetBSD-6.0/evbarm/binary/sets/kern-TEAMASA_NPWR.tgz) = c3d61466da0066d0a61d1fa3052e54f10c19f2f20fe8342c64f0dc6365d95602e47c1e1722d242219e698c824cb4c6dd823b54915eb98f9c6af8a6119920fd6c +RMD160 (NetBSD-6.0/evbarm/binary/sets/kern-TEAMASA_NPWR.tgz) = a4be2875ed76751028c167d6a0c2efecdf3b79d3 +MD5 (NetBSD-6.0/evbarm/binary/sets/kern-TEAMASA_NPWR.tgz) = 72220c0d721aae18cf77bc235bb03cfb +SHA1 (NetBSD-6.0/evbarm/binary/sets/kern-IQ80310.tgz) = dda069ed4e7ad7df46bc23e51a6ef2013af45dc4 +SHA512 (NetBSD-6.0/evbarm/binary/sets/kern-IQ80310.tgz) = 91bd0716398c20a01510a6fe340891d1712da51882e2019bcb7e5852c5b3ac706aa36cc0ebe3f1c1db4b4318624f767118b9ab549a38f253c477b4b25acb84fa +RMD160 (NetBSD-6.0/evbarm/binary/sets/kern-IQ80310.tgz) = bf180d150abaedea9aad9265bb4965197a587490 +MD5 (NetBSD-6.0/evbarm/binary/sets/kern-IQ80310.tgz) = c00c7a69803c130c2f7d34fb3d91610e +SHA1 (NetBSD-6.0/evbarm/binary/sets/kern-IQ80321.tgz) = 2d3162d5072ec3659964ff812b3595ff82830fbb +SHA512 (NetBSD-6.0/evbarm/binary/sets/kern-IQ80321.tgz) = 199bd6e9a8ee5547f4b589c2172400dc1d8204ff2c75ac021004aecc816f5840b04f3e8408e43d64722e829acf654069a161750b733af045648ab5647071a113 +RMD160 (NetBSD-6.0/evbarm/binary/sets/kern-IQ80321.tgz) = 22d77cc3665909c23cbbd57dda56f412c683b75a +MD5 (NetBSD-6.0/evbarm/binary/sets/kern-IQ80321.tgz) = 2bc4f1eb1a0355fdc0dc886c13c895ab +SHA1 (NetBSD-6.0/evbarm/binary/sets/kern-IXM1200.tgz) = eaedad32158dd867e95063f5bb56c66ac8a8f3c3 +SHA512 (NetBSD-6.0/evbarm/binary/sets/kern-IXM1200.tgz) = a8c1730348c3b3aac15b11c2cb598f6a667b9528748e4361baa33ee7a899aadc43366cab3ac0d6a4305e605287952a8ba6db210f4a15fb3158bded3da4071a67 +RMD160 (NetBSD-6.0/evbarm/binary/sets/kern-IXM1200.tgz) = 206d96f4304bb755159fb72884977e53bd608c34 +MD5 (NetBSD-6.0/evbarm/binary/sets/kern-IXM1200.tgz) = 2e6747257e639f5fe31d23d1834ee9c6 +SHA1 (NetBSD-6.0/evbarm/binary/sets/kern-MINI2440.tgz) = bf2d80624e97f1964673908ef28ded8091568b21 +SHA512 (NetBSD-6.0/evbarm/binary/sets/kern-MINI2440.tgz) = 1669f39e3caab537018880d4e93d6010860689f37e60f9d17ceb0a7209442053b1f461b683b6ba201dfd1f0c8641b8650d1561985e8fd47fb80aa3c71d2ee938 +RMD160 (NetBSD-6.0/evbarm/binary/sets/kern-MINI2440.tgz) = be7274304c9c2bb18fe71bbeb9368719ca155cbb +MD5 (NetBSD-6.0/evbarm/binary/sets/kern-MINI2440.tgz) = 1c1547b85d29dae79c76f4d7ee727b31 +SHA1 (NetBSD-6.0/evbarm/binary/sets/kern-MV2120.tgz) = 363e695b0fd04709143647a1f07b22a8029c24b6 +SHA512 (NetBSD-6.0/evbarm/binary/sets/kern-MV2120.tgz) = 99cbcf9b5969385787e852546f3e5685e721c7ff5fb2f898e4d9f29e2bb7640bd08e38cf38eba4cfbfc5d2c1ba3fabcc074328b5ec9bcd13faee233e9a5c10f5 +RMD160 (NetBSD-6.0/evbarm/binary/sets/kern-MV2120.tgz) = 7dcee51999f376d080942e2f46cb936dc32385b9 +MD5 (NetBSD-6.0/evbarm/binary/sets/kern-MV2120.tgz) = 82c6e07c9bb44d8c06d4d4ef7228fc1f +SHA1 (NetBSD-6.0/evbarm/binary/sets/kern-RPI.tgz) = d01b81e07470d09296ca9e2e07eff84ef739865d +SHA512 (NetBSD-6.0/evbarm/binary/sets/kern-RPI.tgz) = df740174545dd2a34f6692b7a15b329c93bf1496b32b70270e339f91cbd6e9c980d92a4da0ea5a8e825eb39cf6b4514ade0d2c78846128ee424fba595e175748 +RMD160 (NetBSD-6.0/evbarm/binary/sets/kern-RPI.tgz) = fb98d2b03e66057f4e002505e26af67d23da171b +MD5 (NetBSD-6.0/evbarm/binary/sets/kern-RPI.tgz) = a07be9e2696fa18bae91363005cd09b0 +SHA1 (NetBSD-6.0/evbarm/binary/sets/kern-SHEEVAPLUG.tgz) = 0f11f8084b40c9f41ef77dc6ae2ec257e819f5c4 +SHA512 (NetBSD-6.0/evbarm/binary/sets/kern-SHEEVAPLUG.tgz) = 8444ff6b4f85c4a8569d51147c83583b37a1dee134c01bb1991666f02d1fd674d80899ac9d11dbe0457a6a1246028a2898444ef0070367edf66dcdde5118d6e8 +RMD160 (NetBSD-6.0/evbarm/binary/sets/kern-SHEEVAPLUG.tgz) = 0f00bd92326287b2db8c825f6e7a93c34e8d7c63 +MD5 (NetBSD-6.0/evbarm/binary/sets/kern-SHEEVAPLUG.tgz) = 3221d316f1518d5bc0680bf7b1179a4f +SHA1 (NetBSD-6.0/evbarm/binary/sets/kern-SMDK2410.tgz) = 93da07d5884e0c20544d001c5f9fb49893f5055f +SHA512 (NetBSD-6.0/evbarm/binary/sets/kern-SMDK2410.tgz) = 69d65444df4a31c129ac2b2f216d6c0c27e84243f3c1870d0e7f133afe6c95e419f1e907b4a4f0ce05162be24ac149616da16d0f840700b39393bf090e1421f1 +RMD160 (NetBSD-6.0/evbarm/binary/sets/kern-SMDK2410.tgz) = 0e515ec91a4186de8cae2243fb079348e91acaab +MD5 (NetBSD-6.0/evbarm/binary/sets/kern-SMDK2410.tgz) = 6a86551a8997ef91ea427022568a658a +SHA1 (NetBSD-6.0/evbarm/binary/sets/kern-SMDK2800.tgz) = 2cdcb47ec0f5173ef5b2dd3ba319dfe10dad37e9 +SHA512 (NetBSD-6.0/evbarm/binary/sets/kern-SMDK2800.tgz) = 106b6c4241c7d4d51f77f2dba13c4977fbf09e8c3b2c4762d9b4de224d04c94a94bd192b89bb3e10a5a52c27141518a0429d09fa39023c9bb59569de7bcc897b +RMD160 (NetBSD-6.0/evbarm/binary/sets/kern-SMDK2800.tgz) = 84e4387b95d8731489c37d13bfd9eb68f323b19b +MD5 (NetBSD-6.0/evbarm/binary/sets/kern-SMDK2800.tgz) = 00ed7a1a639ecc17b6f627bc5e7b2862 +SHA1 (NetBSD-6.0/evbarm/binary/sets/kern-TISDP2420.tgz) = 11e7dfd918fa822c19633b2c0d7139fe3e5b4cbc +SHA512 (NetBSD-6.0/evbarm/binary/sets/kern-TISDP2420.tgz) = f5e0b25240b828e657de6818580bfb5dd47c3d1da978a44f60cbd0fdd86ac824f09922f4ab8ac8af8eb63c32ceb726ce2835498f649828fdae867fca4991a412 +RMD160 (NetBSD-6.0/evbarm/binary/sets/kern-TISDP2420.tgz) = defb0cc263198d9ab3f0fc3e2702d6a2405de15e +MD5 (NetBSD-6.0/evbarm/binary/sets/kern-TISDP2420.tgz) = 00fd1b9a1cc66dc3eff9fe90f85aca6b +SHA1 (NetBSD-6.0/evbarm/binary/sets/kern-TS7200.tgz) = 6e0547db5e16621220bb45150a22b25123022be1 +SHA512 (NetBSD-6.0/evbarm/binary/sets/kern-TS7200.tgz) = e507e5475501cf9b96d1a7f88d5fd8783f089c756a36c6975bdfa0a33ecec441d1c15c06b8387ad5a0cda0a7ce2e18ab731365f8efef4fe8d615da1dd8f8cf52 +RMD160 (NetBSD-6.0/evbarm/binary/sets/kern-TS7200.tgz) = 9b9bc14c01328090ec8b855f30690202a2e3e639 +MD5 (NetBSD-6.0/evbarm/binary/sets/kern-TS7200.tgz) = 1086e9efedf641d90a2fdef271d69944 +SHA1 (NetBSD-6.0/evbarm/binary/sets/kern-TWINTAIL.tgz) = 6587a6dbfe1479c459d670942e9abed58c2077b8 +SHA512 (NetBSD-6.0/evbarm/binary/sets/kern-TWINTAIL.tgz) = 4f2978dada20c19a2b2a35dcee406fdbced5caad7c46b6c733c2c24b2952202d872f666d2ac139baf5b0ff98092a5509594eb8fb70627a25a268fdefa36f1162 +RMD160 (NetBSD-6.0/evbarm/binary/sets/kern-TWINTAIL.tgz) = 49bee3aea5f5b88b79344836c779d428fcd0d19f +MD5 (NetBSD-6.0/evbarm/binary/sets/kern-TWINTAIL.tgz) = c70d7c187e58dd8415522bce16bb12de +SHA1 (NetBSD-6.0/evbarm/binary/sets/modules.tgz) = f9a8894103100366dbd4343aecc6452a35c2fae0 +SHA512 (NetBSD-6.0/evbarm/binary/sets/modules.tgz) = ac2fdf8cc9bff05a5f66749e4dd96a2f0ed4d143acd490e6f8b3826a9b9538918a8fec0045d40f6f418aab80372b23729410997fd81a05f9d9aad27c2dc3589a +RMD160 (NetBSD-6.0/evbarm/binary/sets/modules.tgz) = 35204da96f307f853b28c487b0b78c478cbe99c6 +MD5 (NetBSD-6.0/evbarm/binary/sets/modules.tgz) = b6886a6197725ed21d53bae4a089fc1d +SHA1 (NetBSD-6.0/evbarm/binary/sets/tests.tgz) = 971ffc9e0521617dc678b9e9923371af2e9fca64 +SHA512 (NetBSD-6.0/evbarm/binary/sets/tests.tgz) = 55013634b7d0e607d847ef69ea6a72b7f939830caf8e08dc55c78b04a27897490210377bf1c5b1216778d4ffca44145a0fabddd8ffc449acc93f40877a71daea +RMD160 (NetBSD-6.0/evbarm/binary/sets/tests.tgz) = c9be008f99e4d72d0260139d3ece0db37454d842 +MD5 (NetBSD-6.0/evbarm/binary/sets/tests.tgz) = e1bbc8e25aabbda881eb290efc4b25e2 +SHA1 (NetBSD-6.0/evbarm/binary/sets/text.tgz) = 08a253fdb7a0118ada516bcfd1293100728240c8 +SHA512 (NetBSD-6.0/evbarm/binary/sets/text.tgz) = 41eb29b2f82b18d916d1fa2e858d45fff23f613120c53256c7f7f3dcf7e31ddede9f954a143d9d8c3ec95cd967f46861a1385382634028d61eb0883bebb294b2 +RMD160 (NetBSD-6.0/evbarm/binary/sets/text.tgz) = b2cd2ecb39f44039e90a2465047b5510d0de2eb2 +MD5 (NetBSD-6.0/evbarm/binary/sets/text.tgz) = b5a8566f96d102342467dde0a2ffeeb7 +SHA1 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-ADI_BRH_INSTALL.symbols.gz) = ea2b03a807cb44578f36e3f34d58a0435434f421 +SHA512 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-ADI_BRH_INSTALL.symbols.gz) = f8d97b757b0d0d82f5e4ff14afa6abd1d41ed35e3c97684ade36a0dbb277cfcb55a6f9ef656b1983507247b07f164ecb407d0973d57d1533b2a1e1364ccd51ce +RMD160 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-ADI_BRH_INSTALL.symbols.gz) = 33c2edc444787b5477a459d6426d80ec2ac8c9c1 +MD5 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-ADI_BRH_INSTALL.symbols.gz) = b06f95b94e9fc3ff03d7c02485d9226e +SHA1 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-ADI_BRH_INSTALL.bin.gz) = 72839e1353d343d2ba5e449273aea745a980cb50 +SHA512 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-ADI_BRH_INSTALL.bin.gz) = 9f8019273ef9b3f46a70e6faa97a580e6ae1d0d820974de24033c55a729fff2d2780d5096964673f97e26b3af86835c5087fd0b09a345e15c29403bc1f467c3d +RMD160 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-ADI_BRH_INSTALL.bin.gz) = 81b228fe339897de8d47c2cf5555c39eb891193a +MD5 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-ADI_BRH_INSTALL.bin.gz) = 662f1773c969157b42f70b72bd72c9f8 +SHA1 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-ADI_BRH_INSTALL.gz) = 257f98f33f8429d27486ea526b045f31cc4b9ab0 +SHA512 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-ADI_BRH_INSTALL.gz) = b2b2aff23b6be4c84ef07f1c3ac698f9554a13a54c8fd49ee12b0e175d09da2f116799260083e6a87a8b4e761a4a66ad8d3f02fb6fcec9f3f4b928271cea12a2 +RMD160 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-ADI_BRH_INSTALL.gz) = 0f5a2cdc5951921440a7147912e722a481c1360d +MD5 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-ADI_BRH_INSTALL.gz) = 117ff4be0dd35bb5cfaff3414c27a3f1 +SHA1 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-ADI_BRH_INSTALL.srec.gz) = 1fa80c74c4b2f44a9db4f1d5e0be62a7fd6f68e3 +SHA512 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-ADI_BRH_INSTALL.srec.gz) = 9d291a02fc808baaa9ffe3b259239d64758aa394b6fd782b4220ab47eec1106a33e9972d06ac07fbc1632923b12a9dee9574bfacf5a2dcc096490aedebaa7309 +RMD160 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-ADI_BRH_INSTALL.srec.gz) = cf28c82c673429f391bcfc37493f07489ab8e260 +MD5 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-ADI_BRH_INSTALL.srec.gz) = 6a743321a49a841146309dd71a2b7782 +SHA1 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-CP3100_INSTALL.symbols.gz) = 1d15f8fd20b400aac41fda396b615742593f14c2 +SHA512 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-CP3100_INSTALL.symbols.gz) = 8a2ef21088d568841b740d0c316f513a98ac3f45f1c0d994dc199b4e2529836da832b8409368295b4b326de2f4defdef34f1829e3e4fb7217b39c858ab0eb09b +RMD160 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-CP3100_INSTALL.symbols.gz) = 2202821e57d5506b266456b70f18ff6a1506487e +MD5 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-CP3100_INSTALL.symbols.gz) = 026ab51e016618bcc9f1f1bf363492ce +SHA1 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-CP3100_INSTALL.bin.gz) = feeb79b4d6334a0f6a87ca2c63d195e7039caae7 +SHA512 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-CP3100_INSTALL.bin.gz) = f76735623ac3295690df2eabeefeb39c8cd3e5d85fd09833f9e58b8aa1bbec65f462e8a1edd683a75e5ac2188a50e3ef9f574b00dcbe6f7ffb0c02c4aaaafe26 +RMD160 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-CP3100_INSTALL.bin.gz) = 5344ba62b8815bff63195fb12c5804194c5b74f7 +MD5 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-CP3100_INSTALL.bin.gz) = 1bf8ae796a35caa01e0332fb0c193e2c +SHA1 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-CP3100_INSTALL.gz) = d1d88ea80333147d4b73f6c20d5f0cf9af362acf +SHA512 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-CP3100_INSTALL.gz) = e525b3d43fe6ff0d7ffe83e546b80cdc1892140e3dad8cc409312a544f9ea111869e085fdfb736a1dde3d029d39e84443f06f0175d28a5b21a1a2967c82d904b +RMD160 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-CP3100_INSTALL.gz) = bae57fad021b76fc1a9e9c796b9b6df84b3a8814 +MD5 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-CP3100_INSTALL.gz) = eb56d7e3dbbfffd56cdd5b995690e1d8 +SHA1 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-CP3100_INSTALL.srec.gz) = b0b4f43f1f4f8bcd5ca1a9a0d2877fdce3397998 +SHA512 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-CP3100_INSTALL.srec.gz) = 50c8e9381dfff94d56c7330b217ab079fd3daaa77935dea557d321eca5e5ca59866e59b59b9ac498b0b4a71410dd776c8068f9ee2ee3ed646a39029ba1d6e9da +RMD160 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-CP3100_INSTALL.srec.gz) = 9c88faf5c7de521d9fa0be09a4d9b3b9206a2dcf +MD5 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-CP3100_INSTALL.srec.gz) = 558c67513391c3825047d26f08d48997 +SHA1 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-GEMINI_INSTALL.bin.gz) = 7e8c3f055b239755fecc8aa462e54b8b89a9e8c9 +SHA512 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-GEMINI_INSTALL.bin.gz) = 6977a4d96f1b1cb16ccfe4b15678b40b6627b01385fe6961487817f7ebf84d470277fad37c53ea7bb48e7c19e7b37dd8be3152a6e0274e6f8d6bee69bbb7feab +RMD160 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-GEMINI_INSTALL.bin.gz) = 28fee55b727cc25187df3981d6fbe2bfa64b9e4c +MD5 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-GEMINI_INSTALL.bin.gz) = ecb5118258da0bdb24ec8ab9ac6faa0c +SHA1 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-GEMINI_INSTALL.gz) = 0af690fd4f7fa383ddca7ee5f63bdc698d6ec5a3 +SHA512 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-GEMINI_INSTALL.gz) = 7be43506576a17872997db65441e436b51f1fe3bcc9c42eeea4fd19809f8d3f61d2cb9027ad6cc7e2a26fa3261482b9ff1b7e00878b5bc18ba4e7130919e8dc9 +RMD160 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-GEMINI_INSTALL.gz) = 46c65905cec0fc54bacb408d57af312598bf8502 +MD5 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-GEMINI_INSTALL.gz) = 28ef106d2bffe72fe879c19ef7f25741 +SHA1 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-GEMINI_INSTALL.srec.gz) = f3646a6435283a79f0580692798694d31d8b672b +SHA512 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-GEMINI_INSTALL.srec.gz) = 4b85ad5c44a4076715d43f51aa94e33ddf7f1e6645c7dbbd490ec8d8b305766f3e6a6facdc5c87a20be3865a827e531810e288eeab2184155d83cbc062a0e14a +RMD160 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-GEMINI_INSTALL.srec.gz) = 7f87fafe296706dae3a75441b4f6fe26f52cace7 +MD5 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-GEMINI_INSTALL.srec.gz) = b81ffbbeb626dde373c9c54e4cb15b03 +SHA1 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-INTEGRATOR_INSTALL.symbols.gz) = 0ac81f8038480354e6fafbfba5da86ab333f85e7 +SHA512 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-INTEGRATOR_INSTALL.symbols.gz) = 116b9be7c9e3135d1d1847e084a10e5bb2dc2a95b4810a2e268fee9e6e5b3a5f157b2f34b94a2e03256d959b2bb10d01760347398dc81bda5d6ce64aeac1c2a1 +RMD160 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-INTEGRATOR_INSTALL.symbols.gz) = 4cd6b326352d9398035a2c7eb157c34604da6709 +MD5 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-INTEGRATOR_INSTALL.symbols.gz) = 938ba4475e1668e7fa02cd727e237339 +SHA1 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-GEMINI_INSTALL.symbols.gz) = 9634080097f581271b2e0aa1bc2f87b10c7c57f1 +SHA512 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-GEMINI_INSTALL.symbols.gz) = fb85279a670488e7e8b83c91188bf075363ab8278335c1d3a06411effe829cd8a47cfd269aed5e9a598414fbeb56165eb0ad27550f6f6838d2c9ae9847525e99 +RMD160 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-GEMINI_INSTALL.symbols.gz) = 81c648d753322e87068041c7bdc30dea925ec2ce +MD5 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-GEMINI_INSTALL.symbols.gz) = e4b9a0b3e230fb2cb6a6e2ad3162b1f7 +SHA1 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-GUMSTIX_INSTALL.bin.gz) = 5c60fde2ead5db357827530b6b899e3236fbf814 +SHA512 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-GUMSTIX_INSTALL.bin.gz) = 953fda76c9d47d8af51e578049e98a5f169cf141a057ff1933bccec43ce89b419182f533fd105462af3c09a0a843e8e766f96d2ebcce4cf404166d80ab6b1f08 +RMD160 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-GUMSTIX_INSTALL.bin.gz) = 34e148a900e77f07aa63f0fbbf181bcbc79e2026 +MD5 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-GUMSTIX_INSTALL.bin.gz) = 60aed2122f98e633e78e0f19a3724881 +SHA1 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-GUMSTIX_INSTALL.gz) = d94e8dcfc14fd6928b3d2c784cb38f0f55b009c3 +SHA512 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-GUMSTIX_INSTALL.gz) = 9ef172a0aabcffae7abe5312415da7d407975905484f69ffe73dda2389f0230a39ab2d03e9ca42005db662ca2f6060a4a6ed0db4b5cbf23676a35af38d23a416 +RMD160 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-GUMSTIX_INSTALL.gz) = bd13d39ee7366ba6ab2a1ee1b6094322a5b894fa +MD5 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-GUMSTIX_INSTALL.gz) = 9c16afcb3ce11d9923247d310c23875b +SHA1 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-GUMSTIX_INSTALL.srec.gz) = 380390e6eba24b258a8eed603561f05e2a1cdfd6 +SHA512 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-GUMSTIX_INSTALL.srec.gz) = 519683b9ee12d3dcce26182bd8a46c27d9f6285debe96df2b88d46d0eff372deb2342a1823216da2dd0c28f90732858e7e8a4d9d6305d5e0b82b5345dce92112 +RMD160 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-GUMSTIX_INSTALL.srec.gz) = ad5c85bb6d641596e2b0ae7dbdb6f235b758546f +MD5 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-GUMSTIX_INSTALL.srec.gz) = e2612b861cab60aa64008ab686f570bd +SHA1 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-GUMSTIX_INSTALL.symbols.gz) = 91f9c530da00c48d4b22b7fd98916ba4528f77a8 +SHA512 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-GUMSTIX_INSTALL.symbols.gz) = cefcbae785c5fb72ef5548c16a8ae083a5be19fd27f386c1eaa723c7cd296dbf4c4e774150bf3017a5ae52eecff0aef125f7ebce87f73fd930a019759e0ce7a8 +RMD160 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-GUMSTIX_INSTALL.symbols.gz) = e91be60bcee907ee6259c16e54ce1e3e79f7937b +MD5 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-GUMSTIX_INSTALL.symbols.gz) = 088c9eeabf75406c634a15511972829e +SHA1 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-INTEGRATOR_INSTALL.bin.gz) = 3fb32f0f8c981cf7d0012870d9c5019f06b844b9 +SHA512 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-INTEGRATOR_INSTALL.bin.gz) = 7b7ecc024c36ffe8d57ffb7f53f25e9a3aaa203605ef955c3d94b47627bdf63cb0ac49a8ab230f5f7d5c07c4a56aca94787e861b381af4c84acf48c8b6040b4e +RMD160 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-INTEGRATOR_INSTALL.bin.gz) = f0faa1b8b1d48e6c736959211a1581221e92de24 +MD5 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-INTEGRATOR_INSTALL.bin.gz) = 66e3c14d2f927cd248e0b07882892fdf +SHA1 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-INTEGRATOR_INSTALL.gz) = 90ef61bc7a306fae7f41e20a6c615e37b7d51bb1 +SHA512 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-INTEGRATOR_INSTALL.gz) = 98bcba4e6a5ea6260f42e44b78010bf5b02475a12c198c5898a6e4342bdbfb0207a5b7ee17ebb7cda0859057abe0e5442a41e7fed2c9b78b566e67c7897c21c1 +RMD160 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-INTEGRATOR_INSTALL.gz) = a0fb23b82b04fcd0817a38d5b1b2da620bf23ccf +MD5 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-INTEGRATOR_INSTALL.gz) = 546a0231797a48e08fcba615fbb5dc5c +SHA1 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-INTEGRATOR_INSTALL.srec.gz) = d234b22bf784c64b812dcf9afeba9f106c969e08 +SHA512 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-INTEGRATOR_INSTALL.srec.gz) = f7f78ffeb87a42943c8271cc0bb7d9a3805569fe0cc75f62359ea827cd44ae48f425bdecae341f1a947a10f35df32ce12155105f333b97c765d48db2b1f4c0f7 +RMD160 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-INTEGRATOR_INSTALL.srec.gz) = 218875a0a61876726f5790366ba2748acaf63996 +MD5 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-INTEGRATOR_INSTALL.srec.gz) = 63e3b095ce7b3512ab0fcdc562cff952 +SHA1 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-IQ80310_INSTALL.bin.gz) = 9b24a0420c1b2b406fd2b6d8fc7f25a3dca984ca +SHA512 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-IQ80310_INSTALL.bin.gz) = 5a46d91f646c354c5bf39ae4c15cf45b2ea205328f859a3006bfef815a40b71109b748e6efe91b85ce692663db36c2b6f08e6a43b4ee843c5d1dbb2eb095a7ac +RMD160 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-IQ80310_INSTALL.bin.gz) = 4a6cb6eb7612c34d1b3c68ab7cb56fe32e45b7f4 +MD5 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-IQ80310_INSTALL.bin.gz) = 86823cc4ac5a09992501014bf88c877b +SHA1 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-IQ80310_INSTALL.gz) = a4c5e90d5a9fc6c4b127fd2ba479b27228b64f98 +SHA512 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-IQ80310_INSTALL.gz) = 98f9d8a9bb4c6b29be7002dc4aba375b89a7e98d23fe77634c26efcf4bfec3bec46917718f4c245a9ad8a480db0205224bf0946962ad5b748e04f2b170645344 +RMD160 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-IQ80310_INSTALL.gz) = c9756d9b19051c3f34a748eeca4fc283784f205c +MD5 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-IQ80310_INSTALL.gz) = edc01ffccbf9a6db1d1b40878927b492 +SHA1 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-IQ80310_INSTALL.srec.gz) = 1d2d7369ea182d3cbe36b6cf0929bd26e48e7799 +SHA512 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-IQ80310_INSTALL.srec.gz) = 2164f0f36fbdf41d2fb37ca8a19beffcfdbcfee8a5629350e28a94a105e9b9707fa44b99cf122c102e073084d09905a75a69a8da2f263882e89e9192d66c232b +RMD160 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-IQ80310_INSTALL.srec.gz) = 91147de829c8e594800eb713e55330fb2160c062 +MD5 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-IQ80310_INSTALL.srec.gz) = 1ac108b4534ab6529420b5e6eb4596ee +SHA1 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-IQ80310_INSTALL.symbols.gz) = a594571814d5fd54f060a324f961c8728207414c +SHA512 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-IQ80310_INSTALL.symbols.gz) = 6a55dbba559e4675123270036ef2b05d877463c0101628e50d6f84d12035784a76e010e469840b46cf56291e5d27fa5569457cf83fe7d5a5f128ef6777d4b0fa +RMD160 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-IQ80310_INSTALL.symbols.gz) = 54553929ec55ca2d3e1a34163f79019ce8d21f68 +MD5 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-IQ80310_INSTALL.symbols.gz) = 796f55a92c0f4a29a920251d51a90d9d +SHA1 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-IQ80321_INSTALL.bin.gz) = 8667913b1247f23e940f945fc1d3c6d7b42e3bc1 +SHA512 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-IQ80321_INSTALL.bin.gz) = 30df01772cc961320c0600225caad50145a9f84b9fa5689ed61c59b136c4489e4f6ce3f1075e53c46335f955ed2dd94e662ba2674c56a0171f33e3ace70af2c8 +RMD160 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-IQ80321_INSTALL.bin.gz) = b6c98b6c38bfb10e36bf119c49749cd5c6be20b0 +MD5 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-IQ80321_INSTALL.bin.gz) = 9a3b14a1e64592301beaa6c7581e5f3f +SHA1 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-IQ80321_INSTALL.gz) = e619f80715bb394b1fe67cc05f45cf0e076fc3d5 +SHA512 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-IQ80321_INSTALL.gz) = b131081790eb4e2a82ac2cbd9726b8239f8ec91e25567606411bbcb4c9cb0676f8f15d1daca89623e29d6045fb4e6b6edc40ec7bff4d0646cd06313c8a827672 +RMD160 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-IQ80321_INSTALL.gz) = f791654aa8cf1ee8d9d71aef03ac0f904345465f +MD5 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-IQ80321_INSTALL.gz) = 42b4d81e7d76bf98705e97927f1a6fed +SHA1 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-IQ80321_INSTALL.srec.gz) = 418c6e4fdae62a9dffc0cc52300b3308d4c39726 +SHA512 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-IQ80321_INSTALL.srec.gz) = c6025b5ca7555b4870026cf2a9b23a000bf3f3bdac4a20347593f431062ccfa8b43c29dd1caf17f95787ef685066509e409164c302fcbb40cc18307fec372442 +RMD160 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-IQ80321_INSTALL.srec.gz) = fcaa8176ac524a456a5e75dfcffadbeafc133187 +MD5 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-IQ80321_INSTALL.srec.gz) = 0674c1b44f421bd847dddac9e87e1221 +SHA1 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-IQ80321_INSTALL.symbols.gz) = 579e6ecfc351e91ba0bcf36918bd3fb781b7c1e7 +SHA512 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-IQ80321_INSTALL.symbols.gz) = 34074f57b8eeca79deb3f2a070ea824be2fddae7e8b5a2d8bedab2b4dd4796f2eb1baab06cdf95b53da4b43cbd8e8fa873dc0986325282dea9902ffe9fe521da +RMD160 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-IQ80321_INSTALL.symbols.gz) = 139e713201e03fa17e31803834d898d1ef636bb6 +MD5 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-IQ80321_INSTALL.symbols.gz) = d08f0319e5ccb9d142f20f81a1a4d0f9 +SHA1 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-MINI2440_INSTALL.bin.gz) = eb490e7ec36f92c871934f2cd7c1fcb2339ad2a7 +SHA512 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-MINI2440_INSTALL.bin.gz) = 7be26fc8e01142f873d0e2ca89a414bb4d2dd332dabfec1f7cd126ba2eaf0d803abde4f62c627b583fe2a57b93bd1669fc669666185ce1d5cdbeb47b88690ca6 +RMD160 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-MINI2440_INSTALL.bin.gz) = a93d35c0251e92ac7562cc6138419fefb6fca84b +MD5 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-MINI2440_INSTALL.bin.gz) = dc54e455b762156bdfd6a0fb2d14fe2f +SHA1 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-MINI2440_INSTALL.gz) = 2567dce09ac1764f78ec074e4f5644a87ac83c8c +SHA512 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-MINI2440_INSTALL.gz) = 6beb220906314c4ac93a058a4994104ec2dccefcca4e8c2a0be6d3399536b4765e49294b275dacfe20e39c7cccd81b88c9521b2b273835001cc6b131237b20d2 +RMD160 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-MINI2440_INSTALL.gz) = bc87bf5b540e6847689016b2301ad48aa637a3eb +MD5 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-MINI2440_INSTALL.gz) = c96abcd45f88d52e5826c9419e895e49 +SHA1 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-MINI2440_INSTALL.srec.gz) = 82575c4f3f6344ff9fcd848f30364fd1b65eed82 +SHA512 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-MINI2440_INSTALL.srec.gz) = f1c6e41724db95eefe005e2a4f3defa81b7d8319521ad2897fb976cc8fd31af9f9399bb0df03e8b910d72baf25384112efad9699a111c6a0ebc2e8d79dc63f72 +RMD160 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-MINI2440_INSTALL.srec.gz) = 82c356d5a3916d82b941cfca334f55586b30805b +MD5 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-MINI2440_INSTALL.srec.gz) = 16ff2a11bc97e2bddfa4ecda023be897 +SHA1 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-MINI2440_INSTALL.symbols.gz) = a8cf19b83ab6b0aa48e6486a2ef5717c14025933 +SHA512 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-MINI2440_INSTALL.symbols.gz) = 3c9919130d4470ff778d77119b4f17132002de6229a1d0f4f2024e1bbe8e68de7cfe93a4da18835c111dad1de50bbc4e5e0e50a89e71757acc2da888afcf944a +RMD160 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-MINI2440_INSTALL.symbols.gz) = 53339f2e886137c722353c7e4641fb79fb4160c9 +MD5 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-MINI2440_INSTALL.symbols.gz) = 2125d332a50f2382dc9ea2fa1c76fff6 +SHA1 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-TEAMASA_NPWR_INSTALL.bin.gz) = 7f7533adb7f744376eda30bed953e0c24925a7ac +SHA512 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-TEAMASA_NPWR_INSTALL.bin.gz) = 6df01180c26dea9f40e427414375f872d65be05f1541d887fedf8d98f22e3f98354ca15aa058c1cba0d0e4d30974b37787855c1a9ee36f7b702ad42c31ef69ab +RMD160 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-TEAMASA_NPWR_INSTALL.bin.gz) = 1c6192b2841123a6a7b34f46530a49cf731fe8b0 +MD5 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-TEAMASA_NPWR_INSTALL.bin.gz) = 7080e515fcdbe3d4d976da0bd0db1356 +SHA1 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-TEAMASA_NPWR_INSTALL.gz) = 009c609c69eb87be8129cb8cca61732493771053 +SHA512 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-TEAMASA_NPWR_INSTALL.gz) = 1aef3bb8e1f66280e2478e207618ef125b02fee796f1d31bc9c8ab5e28f132bd5aa5c6e78cf1dd2e63a72cfe814264db394c74a2c1f04ae139dbd3d592bca8ce +RMD160 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-TEAMASA_NPWR_INSTALL.gz) = 6b7f00ce3de221960905acde44c93679d12318b0 +MD5 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-TEAMASA_NPWR_INSTALL.gz) = cb78419cf4b8862517c4cdb83f09edcb +SHA1 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-TEAMASA_NPWR_INSTALL.srec.gz) = 5405155f29eab526e4b489e156a3a6a84b694c04 +SHA512 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-TEAMASA_NPWR_INSTALL.srec.gz) = e4ddb650bed5716c2a6070a88104ead0119e3e41a6ad61d0a1ab944966fd5e29d3c17b83061940c81788583d833b3b90e2b3fca30a2291bb7e99be7acfc52eb4 +RMD160 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-TEAMASA_NPWR_INSTALL.srec.gz) = d28c777e9f79b74d39d9cebeb55582bf6554bdf4 +MD5 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-TEAMASA_NPWR_INSTALL.srec.gz) = e33527c137440f91dc481372e55b5153 +SHA1 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-TEAMASA_NPWR_INSTALL.symbols.gz) = 0adc4d2b9af7fed43f2cb2a6d461b0b67dca64ff +SHA512 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-TEAMASA_NPWR_INSTALL.symbols.gz) = fac69e001c5383808c41901f250e53267cee4df0738cf2fda17675057f397d33fd2be817b4235ba4ff47c3ad4c667388fe94e935372702729e38a39d95932bf1 +RMD160 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-TEAMASA_NPWR_INSTALL.symbols.gz) = 08cb50f087ee2c1edcb6bb8b0a10fd9436ee5291 +MD5 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-TEAMASA_NPWR_INSTALL.symbols.gz) = 303fa88bab1f84ce1e5e7392b63d335f +SHA1 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-TS7200_INSTALL.bin.gz) = 6d96ba7627a743040710559958052fe5ad516e07 +SHA512 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-TS7200_INSTALL.bin.gz) = c8980e5a5fcbf6d16a94b273537d0b7e684d46621d46cb52b1c2672e67c864bc4651a09fed96356e441d209f57c5eba10696d9d82a3aba7bca24781ef6e6d570 +RMD160 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-TS7200_INSTALL.bin.gz) = 8faf196aecee5eab9fe5a256daf1bdeee5f485e0 +MD5 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-TS7200_INSTALL.bin.gz) = fa021fd649cc68d99ed50414c562937e +SHA1 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-TS7200_INSTALL.gz) = 7084ab7948465cd7fb832a191991166d460bcbe9 +SHA512 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-TS7200_INSTALL.gz) = a6e2dd918a3965573e3417e24984ff5d4c546a9bade8d7b68a930e695a76243aa4acb89eaede1ad8ea07280a836fbdc3200b7cade29486e1a1783734ad3164aa +RMD160 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-TS7200_INSTALL.gz) = eb9e46f17f5a0d0d296fcf3983fc7cac086d139d +MD5 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-TS7200_INSTALL.gz) = ad30409880e74a4c9aa9be2f0cd67ba4 +SHA1 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-TS7200_INSTALL.srec.gz) = 5dce945d53df7aa098712e966a08d8c4a11d5615 +SHA512 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-TS7200_INSTALL.srec.gz) = 13270d86a94b74829fdd691cd97b8afbebf397fd68d9e8ecc8dcce611b3eca79666e5da303d75ad0af56f762b65d3d487ef1317685538b6962ff5b482e57c954 +RMD160 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-TS7200_INSTALL.srec.gz) = dbb6b76ac38227dc2b5e0dcf35dbbc187a0f9cec +MD5 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-TS7200_INSTALL.srec.gz) = 573eddbddcc0e213758ee25fd7f3d6e0 +SHA1 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-TS7200_INSTALL.symbols.gz) = 7a5bcaaa2847b816c0568f28647ee07a18650c38 +SHA512 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-TS7200_INSTALL.symbols.gz) = e7fa9c30cef40ab421ed36421f9c92bac2fb21c88077d4dd176a55b3b82cb94ff1e912b35d6504e5d37ca737378da3eae0f64e7721a023e7af596a037f0970a0 +RMD160 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-TS7200_INSTALL.symbols.gz) = dbe42d8b278149bae03d553e4d8a2676544b53ba +MD5 (NetBSD-6.0/evbarm/installation/instkernel/netbsd-TS7200_INSTALL.symbols.gz) = 28d969c46d89d77b04fdc532621a9c5b +SHA1 (NetBSD-6.0/evbarm/installation/bootmini2440) = 322711938832b81edf3a30de085fe84c118fffdd +SHA512 (NetBSD-6.0/evbarm/installation/bootmini2440) = f985790660b66ab4843a2e938e67bb7b1856e6acfee877e00bcadaf945cae7f85dd5f5ea2557f331d142c2f79ff129ac505a9f8ac276650ed49ae86b202cdd1f +RMD160 (NetBSD-6.0/evbarm/installation/bootmini2440) = 6549e1c02eec982d3bfbd42317bc0c49bd7a3fcc +MD5 (NetBSD-6.0/evbarm/installation/bootmini2440) = ab71c605b7165325bc2efffbf8366e01 +SHA1 (NetBSD-6.0/evbarm/INSTALL.html) = 364e208c39e0aa0c1a873702629363049749555b +SHA512 (NetBSD-6.0/evbarm/INSTALL.html) = 0d23a02d74624eceee1b8908f49ca677ab4c260725798614faf67cfcf396aa0862aaf5296ab68315b3a1b110a998cd9fc08f36630aa3202ffb18db915e6bc5cf +RMD160 (NetBSD-6.0/evbarm/INSTALL.html) = 5e46ad234a6311ea55f157da0978fd0ca4543ee1 +MD5 (NetBSD-6.0/evbarm/INSTALL.html) = 4ddc104e853a1b0a9ff34bdeffdb849a +SHA1 (NetBSD-6.0/evbarm/INSTALL.more) = 49005be72eacdfd5e58240ea40c272362f1794ca +SHA512 (NetBSD-6.0/evbarm/INSTALL.more) = 29b0240cd5e8b957fd6f0cb26858f856f2ca1e5bc664d7617138519d38788f442bd0e2045f506eb49b6fb07200e3251694679c7e9079e152e022e4c36d69339c +RMD160 (NetBSD-6.0/evbarm/INSTALL.more) = b2227c9abf8c42edad582429b388b46292b2b642 +MD5 (NetBSD-6.0/evbarm/INSTALL.more) = 8f7edc27634f260c5216ce2ac1c7ab20 +SHA1 (NetBSD-6.0/evbarm/INSTALL.ps) = be244573aa70f6ea8bd6afef50d3129e95ecb232 +SHA512 (NetBSD-6.0/evbarm/INSTALL.ps) = b4dcdf490b1e2fdfb72a21fbd00922eef14da81665f56e69d5fce4458222a3108c27fc793a1507e9f6f3b3555c236899f06863282b3a0dcf061ddd81451e0f82 +RMD160 (NetBSD-6.0/evbarm/INSTALL.ps) = 38340ef793c940f555c637fb63ed603e2813b6b0 +MD5 (NetBSD-6.0/evbarm/INSTALL.ps) = 0702cfb1c18290c2f6b3990ec2b9b838 +SHA1 (NetBSD-6.0/evbarm/INSTALL.txt) = 84d0cf406199e9e160201946ef76c5544f859094 +SHA512 (NetBSD-6.0/evbarm/INSTALL.txt) = 779245d5eac9f6aad487d0ef8c09ad8ed1ccd1ab6b315d5436d681422a1ca23376304d9f5f36e0010d38a26947c2d67b214f7fe06207b52ec4ca1d1abf996280 +RMD160 (NetBSD-6.0/evbarm/INSTALL.txt) = f21886bd1f37f1557a890ce294fc842a4a9322ba +MD5 (NetBSD-6.0/evbarm/INSTALL.txt) = 4e8f849ebf04f5af7feb401bd8b828ac +SHA1 (NetBSD-6.0/evbmips-mips64eb/binary/kernel/netbsd-MALTA32.gz) = 837f5c347644ad20116892b91a170bd9a177cf25 +SHA512 (NetBSD-6.0/evbmips-mips64eb/binary/kernel/netbsd-MALTA32.gz) = 83ef6ec1fea23841a6a03d5f91d0c00f8dae56d78276b04dc56f3be1121950c8b21cdc3b4f580929f85e0b7dca9f5635cbc248cd9bdf018bd019837953165796 +RMD160 (NetBSD-6.0/evbmips-mips64eb/binary/kernel/netbsd-MALTA32.gz) = da9f38ccb4f1a09ce9567d148115538eedddfd64 +MD5 (NetBSD-6.0/evbmips-mips64eb/binary/kernel/netbsd-MALTA32.gz) = 94e33f6853b4a1d9253b01310a9d31e8 +SHA1 (NetBSD-6.0/evbmips-mips64eb/binary/kernel/netbsd-MALTA64.gz) = 1194bf50c6a2a1cccfd7017ec100e18840cab60a +SHA512 (NetBSD-6.0/evbmips-mips64eb/binary/kernel/netbsd-MALTA64.gz) = 05939d55299eb8c98f89c0cced1f090fc47568c81be3c4aaf32325ce4a087b44b1c6945bb8b9a12384ae588e9dfb1ad0ca1c701e2f0603a672bf3ea1d2bad1d0 +RMD160 (NetBSD-6.0/evbmips-mips64eb/binary/kernel/netbsd-MALTA64.gz) = ceecace87ff5c72a8bf0551d03e7f24297c8210e +MD5 (NetBSD-6.0/evbmips-mips64eb/binary/kernel/netbsd-MALTA64.gz) = f70db6b8696d6db6538471a0389aba6a +SHA1 (NetBSD-6.0/evbmips-mips64eb/binary/kernel/netbsd-XLSATX32.gz) = 50baddbb54cecc95e5aacae73100b35b1a50808a +SHA512 (NetBSD-6.0/evbmips-mips64eb/binary/kernel/netbsd-XLSATX32.gz) = 937b7632d22c4e22bdacdad4bb473b1c4537cccb35f97d1bb08b80d64c6228a410f59310ba336d19e62e0bf38f3ccb9c5e1c27aed8d769ef66657de06070b273 +RMD160 (NetBSD-6.0/evbmips-mips64eb/binary/kernel/netbsd-XLSATX32.gz) = 97d67324ca36d259e51a80f89b3ff8c32aeb0936 +MD5 (NetBSD-6.0/evbmips-mips64eb/binary/kernel/netbsd-XLSATX32.gz) = 2c17d4f86050689342b031332bae427b +SHA1 (NetBSD-6.0/evbmips-mips64eb/binary/kernel/netbsd-XLSATX64.gz) = 1e1c1a9cd9c7bedace03b3c25a736014d7053adf +SHA512 (NetBSD-6.0/evbmips-mips64eb/binary/kernel/netbsd-XLSATX64.gz) = dd0689962b451e442a48a35c35f426d4428aad93a22e6e2d33dd0033125eeb8e763ed31ee13410a6f7b7d337a46c351a736605adf49e301e09df14096fffbf41 +RMD160 (NetBSD-6.0/evbmips-mips64eb/binary/kernel/netbsd-XLSATX64.gz) = c94021afffc7e21001cd3f045063b725fcbbdb96 +MD5 (NetBSD-6.0/evbmips-mips64eb/binary/kernel/netbsd-XLSATX64.gz) = 7ed50990347095eced85286bac3894ad +SHA1 (NetBSD-6.0/evbmips-mips64eb/binary/sets/man.tgz) = 899b9d8242e983a5110ab755651c24f709b5af67 +SHA512 (NetBSD-6.0/evbmips-mips64eb/binary/sets/man.tgz) = 410999db110d710f4bb498c3d7ae7adc62170c7c2f470ce189c92f6c436c5ea96149659c631ef0b5605caaa025d97dfe1c07c428d86f51239657bd6b71717b15 +RMD160 (NetBSD-6.0/evbmips-mips64eb/binary/sets/man.tgz) = c1270f68c6d41b351877f71f0396ac34877dfc8d +MD5 (NetBSD-6.0/evbmips-mips64eb/binary/sets/man.tgz) = df4db2bbfa39ef6a4a215d949653d04a +SHA1 (NetBSD-6.0/evbmips-mips64eb/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/evbmips-mips64eb/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/evbmips-mips64eb/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/evbmips-mips64eb/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/evbmips-mips64eb/binary/sets/kern-MALTA32.tgz) = 8aef48b2afd3a5c2daaf9298b1377e5fb48a4775 +SHA512 (NetBSD-6.0/evbmips-mips64eb/binary/sets/kern-MALTA32.tgz) = 769777c570e41cef669cadd1caca734ca55f71382656b3d229bf32811e22fcac10c3258032e79ad190d9e34b4a4168269b0a44352209f9321d3b3d18e1d920ef +RMD160 (NetBSD-6.0/evbmips-mips64eb/binary/sets/kern-MALTA32.tgz) = 27fd132ecb4aef492c8194a598641b0d57df788f +MD5 (NetBSD-6.0/evbmips-mips64eb/binary/sets/kern-MALTA32.tgz) = 547ed14fd7607348ac12d50d6e142625 +SHA1 (NetBSD-6.0/evbmips-mips64eb/binary/sets/base.tgz) = 321d0a48e96415413f6c76fe94cfae0b763c0ab4 +SHA512 (NetBSD-6.0/evbmips-mips64eb/binary/sets/base.tgz) = e3306d01022a478928ebf33894603aa4788983b58b73beb1cdd1592cc5d545bb3eefcc07ef381f7be24099bf5100914d65f5575c9ccc43279332972d5e84c01c +RMD160 (NetBSD-6.0/evbmips-mips64eb/binary/sets/base.tgz) = 822520b0721dbc6ff7402acf65a7078df4ee495b +MD5 (NetBSD-6.0/evbmips-mips64eb/binary/sets/base.tgz) = 838db1b3837f00c46b9b7f8e2ceddee5 +SHA1 (NetBSD-6.0/evbmips-mips64eb/binary/sets/comp.tgz) = 9e1125bb9734db8e861c085c3f4baeefed5bc5ca +SHA512 (NetBSD-6.0/evbmips-mips64eb/binary/sets/comp.tgz) = 405ffdb54d1ad4f0cb56b07ade8ef1cf26235526e143f62622870e9733d9f860405519b355129bfad7ebe659c56358c73dcc941bf0554a89ef210a70e69c2855 +RMD160 (NetBSD-6.0/evbmips-mips64eb/binary/sets/comp.tgz) = 13b1ab9f477f0d22afd1dc11d7a0ce04ed87e247 +MD5 (NetBSD-6.0/evbmips-mips64eb/binary/sets/comp.tgz) = 880a15da9d452aba11a9c3e4b8c32c44 +SHA1 (NetBSD-6.0/evbmips-mips64eb/binary/sets/etc.tgz) = 793af95b8423250427980e55e1b40e7d2d946dd7 +SHA512 (NetBSD-6.0/evbmips-mips64eb/binary/sets/etc.tgz) = 9c9dafc30b85ced01a296fa4464bed9c8bbed77b359307a637e236646880d93aa3b17c857423f26c286732686b00855131a359295fbb22c4f4d4271aaf21fd23 +RMD160 (NetBSD-6.0/evbmips-mips64eb/binary/sets/etc.tgz) = dc21febaa97b3f196ddf788541e93081919ac05d +MD5 (NetBSD-6.0/evbmips-mips64eb/binary/sets/etc.tgz) = affff84911016dc75d8dcc556ed1cd90 +SHA1 (NetBSD-6.0/evbmips-mips64eb/binary/sets/games.tgz) = 6a9922b70c13cccb7e2c3b2d2b4f63f4d6ba8b83 +SHA512 (NetBSD-6.0/evbmips-mips64eb/binary/sets/games.tgz) = e17192d20cebcb6583f76e3badf382c2734bdccb596b5a7c7104c28bd6d96419a59a642c4eac1e246d821d8cdf211e8b00aeb7043a439edfa6cf9e5554441007 +RMD160 (NetBSD-6.0/evbmips-mips64eb/binary/sets/games.tgz) = f93c4992616fc210ae24c58b64f8607ca6f3d1af +MD5 (NetBSD-6.0/evbmips-mips64eb/binary/sets/games.tgz) = 2186988f1072dc9be8a8e1ea77bc1906 +SHA1 (NetBSD-6.0/evbmips-mips64eb/binary/sets/kern-MALTA64.tgz) = 6cff22a0f2e961617cd4eaf3bb571a7b7f4845a0 +SHA512 (NetBSD-6.0/evbmips-mips64eb/binary/sets/kern-MALTA64.tgz) = 05b431e02e4e858f79103bc1950c4da7fc87d476d46479a8f0c2a9850b96391d8a55cedc0fa3b47da4857d7f91a9acacc08369e2121a7d47af3bda5712ad333f +RMD160 (NetBSD-6.0/evbmips-mips64eb/binary/sets/kern-MALTA64.tgz) = e1048547f5851837f476010b3c5866f527542465 +MD5 (NetBSD-6.0/evbmips-mips64eb/binary/sets/kern-MALTA64.tgz) = 3ccf1d8db71de9c182c81d99689aab8d +SHA1 (NetBSD-6.0/evbmips-mips64eb/binary/sets/kern-XLSATX32.tgz) = 4400d1601558ff59a7d90028bd91e00c4b67e230 +SHA512 (NetBSD-6.0/evbmips-mips64eb/binary/sets/kern-XLSATX32.tgz) = a16e8b5d34e07c97fdda6b09e41a67d48fcf56b4276e9e52c2a2d8ce1eac5d21abb542afb67991f7b2bf87261c8134f8e522d59375ccd251f4e853d3ed877b71 +RMD160 (NetBSD-6.0/evbmips-mips64eb/binary/sets/kern-XLSATX32.tgz) = a7ea06c9ce95d00548c7dc9a3403f873d3f42749 +MD5 (NetBSD-6.0/evbmips-mips64eb/binary/sets/kern-XLSATX32.tgz) = a6c542f79813324f5ddaf80a9a12a531 +SHA1 (NetBSD-6.0/evbmips-mips64eb/binary/sets/kern-XLSATX64.tgz) = 47cc48be2b1edf22d48fb3d45c2ebcf1e6b84655 +SHA512 (NetBSD-6.0/evbmips-mips64eb/binary/sets/kern-XLSATX64.tgz) = ce9378b66f327c84e004d075e0033e195c1e649acc7f668d154b5608fa71070cfed74b1eedea404cead8c92a9f9f332fb5f2407a14d80175d4f2e7f3115962d7 +RMD160 (NetBSD-6.0/evbmips-mips64eb/binary/sets/kern-XLSATX64.tgz) = 64602c29c9cad9767bdc771464f766d4c4bc7a14 +MD5 (NetBSD-6.0/evbmips-mips64eb/binary/sets/kern-XLSATX64.tgz) = f55ccc413a2546e5db4c66b38095dfb2 +SHA1 (NetBSD-6.0/evbmips-mips64eb/binary/sets/modules.tgz) = 150d99ebadd4c626bf48d9dd772584df18d0f161 +SHA512 (NetBSD-6.0/evbmips-mips64eb/binary/sets/modules.tgz) = eb3e15f4dd50d6eb59ffec96245ca440abdc2427f7cd14f6405ce979f9ee13b5d40ed30d0fc544cd92e5c8dd49b2cd033cafa44f32baef8c434734665c7b35d2 +RMD160 (NetBSD-6.0/evbmips-mips64eb/binary/sets/modules.tgz) = 74a564f4270f8b8df9c0f207512ccbf02cd4436e +MD5 (NetBSD-6.0/evbmips-mips64eb/binary/sets/modules.tgz) = 6f2c6d66540b3994a5400f1b3a7c0e06 +SHA1 (NetBSD-6.0/evbmips-mips64eb/binary/sets/tests.tgz) = 607a8a23fb7447a1bd6363feb446cdfc7110ac7f +SHA512 (NetBSD-6.0/evbmips-mips64eb/binary/sets/tests.tgz) = babcea43b781105dea81af3797bce6f77bbf2766a28104c45aa7f43952d0a0a7e3c981927d4b2745ed46b290ff4db7d43b5a2620b82d7185a55e06156604432f +RMD160 (NetBSD-6.0/evbmips-mips64eb/binary/sets/tests.tgz) = 90dc0855b2b85584cc08f07d55645bd98f04b40b +MD5 (NetBSD-6.0/evbmips-mips64eb/binary/sets/tests.tgz) = c0dc4879f5bf2e13462fe11f1afb9755 +SHA1 (NetBSD-6.0/evbmips-mips64eb/binary/sets/text.tgz) = a38aef75824fe9c86579b8a320ec645e1079224d +SHA512 (NetBSD-6.0/evbmips-mips64eb/binary/sets/text.tgz) = 39f42cbd084867ba177e3f3c7eda0ae19040eac2ee4dca991caa172211ba499081f720f16511b967fe6e4529f78e446cf9cf8ab89b595bca41aff3e7017b2028 +RMD160 (NetBSD-6.0/evbmips-mips64eb/binary/sets/text.tgz) = af58fb15683143196193ee0ad443a9fc94b6f8b7 +MD5 (NetBSD-6.0/evbmips-mips64eb/binary/sets/text.tgz) = 8716d1b4d2cb02c015e20e87650021ed +SHA1 (NetBSD-6.0/evbmips-mips64eb/binary/sets/xbase.tgz) = f22a560c757bc506a118ce9803f68e148fbcf5f8 +SHA512 (NetBSD-6.0/evbmips-mips64eb/binary/sets/xbase.tgz) = 5ee7c1db10aaf6a67fe6e9026057266340e901a2a4042d126862bb3ebc1b26dc824a3d47febaf2c38738b10e563feb903c1020ef98dd34a34ed6ab1811e1dd0a +RMD160 (NetBSD-6.0/evbmips-mips64eb/binary/sets/xbase.tgz) = 4dd1d30eed29fad5ad00d08f8655850ba2966beb +MD5 (NetBSD-6.0/evbmips-mips64eb/binary/sets/xbase.tgz) = 83fe206984459147b084ce31f5712ac5 +SHA1 (NetBSD-6.0/evbmips-mips64eb/binary/sets/xcomp.tgz) = 6a62de4e61ca7fb51120a2d949f0c6a76728c795 +SHA512 (NetBSD-6.0/evbmips-mips64eb/binary/sets/xcomp.tgz) = 1a4d6159f2afb79ea54d7b50515d33585ac70a41da0dce13790d9acc1bc83636eedf83284aa76c4b9be2d51e25000fcb000842d4491edc1f0032e6e68f591359 +RMD160 (NetBSD-6.0/evbmips-mips64eb/binary/sets/xcomp.tgz) = b5d253b8ed963d2aa4542c177199f8bf56a7413f +MD5 (NetBSD-6.0/evbmips-mips64eb/binary/sets/xcomp.tgz) = 9ab19bfd18fe8afea9ec8b987eb3f745 +SHA1 (NetBSD-6.0/evbmips-mips64eb/binary/sets/xetc.tgz) = b3ca1c7e85d0832091fc391717c914889f745a13 +SHA512 (NetBSD-6.0/evbmips-mips64eb/binary/sets/xetc.tgz) = e386fa04d66afe2b4817c6e77d6ae351e7a10265099395285e15ff5fb8c41d169de511b3bdc71d9b8fd144a0153262b068b6b837b846310e255bfea1a06ac5e6 +RMD160 (NetBSD-6.0/evbmips-mips64eb/binary/sets/xetc.tgz) = d7cd1c13d547ec0fe4ad59ee92be9499cbeb53ed +MD5 (NetBSD-6.0/evbmips-mips64eb/binary/sets/xetc.tgz) = 8165fb3d8f4f335f32f391d6f6ba414c +SHA1 (NetBSD-6.0/evbmips-mips64eb/binary/sets/xfont.tgz) = c3b40e7a439d60c27022fc1cea5e58fff68f2da3 +SHA512 (NetBSD-6.0/evbmips-mips64eb/binary/sets/xfont.tgz) = 5a7e564dc9cc41d3704722a461ffe7ada8011510e3db08c2a209afc462a69986261ec02d41e792f1e1a305300f4d23216cb07c231c461df5edb2fb54916d2438 +RMD160 (NetBSD-6.0/evbmips-mips64eb/binary/sets/xfont.tgz) = 03066eeaa22fac20cb69be43939f870a313519d2 +MD5 (NetBSD-6.0/evbmips-mips64eb/binary/sets/xfont.tgz) = 46e16e5288c250f4f2394bf709df039b +SHA1 (NetBSD-6.0/evbmips-mips64eb/binary/sets/xserver.tgz) = 13d61af721933a9484ea722fcf5a151900b07d55 +SHA512 (NetBSD-6.0/evbmips-mips64eb/binary/sets/xserver.tgz) = 1372c13478ca7da2c5ba2b3d56f2f09f2bd764f2c345a9e4b8c2fa81fd101d557d53b16637b7644676431cc57b481d22d7f702c1a24d7c6456c04b75422f9485 +RMD160 (NetBSD-6.0/evbmips-mips64eb/binary/sets/xserver.tgz) = 3cc8603545553cf13c0e41525d4f71df2f04a243 +MD5 (NetBSD-6.0/evbmips-mips64eb/binary/sets/xserver.tgz) = 599284f9e42a94928802db5b36d6c8db +SHA1 (NetBSD-6.0/evbmips-mips64eb/installation/netbsd-INSTALL_MALTA32.srec.gz) = f94948277528ab8356fbcb1f447ea3f88da0dbff +SHA512 (NetBSD-6.0/evbmips-mips64eb/installation/netbsd-INSTALL_MALTA32.srec.gz) = 37025250657daad79c15d79ade2f1e815b551bb9541d852e0e0b208b6964b2e7bcff4eab477ff9dc8c62b23a061681c6076684f41d50ffac2b9ca1c9b85eb657 +RMD160 (NetBSD-6.0/evbmips-mips64eb/installation/netbsd-INSTALL_MALTA32.srec.gz) = e0f5ead94d76d0131e9b6351a1b32066c0e37004 +MD5 (NetBSD-6.0/evbmips-mips64eb/installation/netbsd-INSTALL_MALTA32.srec.gz) = f07bb28b2742e51e8a130a1633813342 +SHA1 (NetBSD-6.0/evbmips-mips64eb/installation/netbsd-INSTALL_MALTA32.gz) = ce135463449caf04fe5915edf2689e53f7d34450 +SHA512 (NetBSD-6.0/evbmips-mips64eb/installation/netbsd-INSTALL_MALTA32.gz) = e30a6963cdee29fc634232bad314c1093df462a1fc2751908ff1f6118165b1f4cbc7fa3fb780c7483b26dbed2339f562d75618ed355388ca4a7ea8da182f5718 +RMD160 (NetBSD-6.0/evbmips-mips64eb/installation/netbsd-INSTALL_MALTA32.gz) = 726d74693693f22e261de851efc11f489af83d5e +MD5 (NetBSD-6.0/evbmips-mips64eb/installation/netbsd-INSTALL_MALTA32.gz) = cf0519b0dc9ab365ee268ee0cf667cd3 +SHA1 (NetBSD-6.0/evbmips-mips64eb/installation/netbsd-INSTALL_MALTA32.symbols.gz) = 7d61c5ea450b2348bbf829f17801d1444142030a +SHA512 (NetBSD-6.0/evbmips-mips64eb/installation/netbsd-INSTALL_MALTA32.symbols.gz) = be8fadc2f971b5ceae719fe76f121a1d394826c0509d0052eb681ec3398e8944a8866c45ed213bc1a07ccc0306ede8ec3c28c1415a26bfc92721fe8a90ec8c86 +RMD160 (NetBSD-6.0/evbmips-mips64eb/installation/netbsd-INSTALL_MALTA32.symbols.gz) = 8be481d57e200549bddd24d27e640fc192758aa8 +MD5 (NetBSD-6.0/evbmips-mips64eb/installation/netbsd-INSTALL_MALTA32.symbols.gz) = 23dc546c19890b5bfe2981a4be93cf61 +SHA1 (NetBSD-6.0/evbmips-mips64eb/installation/netbsd-INSTALL_MALTA64.gz) = 774d5ac21ea9f3b0d356a7de041c89afedd85cb4 +SHA512 (NetBSD-6.0/evbmips-mips64eb/installation/netbsd-INSTALL_MALTA64.gz) = 228797b395c498e531f359c59d8a79f336138923e95881c1506c9b1a772865b6a7df96be8a05e62a8f3a3b791e208173e35bc6ac1ad29d8c62b388620d3bb828 +RMD160 (NetBSD-6.0/evbmips-mips64eb/installation/netbsd-INSTALL_MALTA64.gz) = d84a8c78f5f81c897066771fabb70dd447d423ab +MD5 (NetBSD-6.0/evbmips-mips64eb/installation/netbsd-INSTALL_MALTA64.gz) = 9392b5ff6a21a0f043f4ba6e9ff14a00 +SHA1 (NetBSD-6.0/evbmips-mips64eb/installation/netbsd-INSTALL_MALTA64.srec.gz) = 028bf1fb8a8e7f1733eecb45b7016b387660558c +SHA512 (NetBSD-6.0/evbmips-mips64eb/installation/netbsd-INSTALL_MALTA64.srec.gz) = c7d3178f2dc591e1d39e8e04aaae780cdd38c190d850d0b71a0c69eca7a8dc29b8adb300e106a236e9fbd7ea9e85dc070bc5ae6baf6bc742aff4dbafca91c00e +RMD160 (NetBSD-6.0/evbmips-mips64eb/installation/netbsd-INSTALL_MALTA64.srec.gz) = b4f76a19a3119f6b35830db195d0db3b40b962d7 +MD5 (NetBSD-6.0/evbmips-mips64eb/installation/netbsd-INSTALL_MALTA64.srec.gz) = 6f1c87fa36192f6cce9fe900576de781 +SHA1 (NetBSD-6.0/evbmips-mips64eb/installation/netbsd-INSTALL_MALTA64.symbols.gz) = 05ebd0d64d73f452fbc31f9a7945fc1503bfa23d +SHA512 (NetBSD-6.0/evbmips-mips64eb/installation/netbsd-INSTALL_MALTA64.symbols.gz) = 839eafde2ed98b6be776ad75e591c23a295aae726a2d384fa1c2f9e52333f1d5ba14c21473ad5d7c51098608d04b055cc163e743485556ac30c75a5a913f0422 +RMD160 (NetBSD-6.0/evbmips-mips64eb/installation/netbsd-INSTALL_MALTA64.symbols.gz) = 6f1dbafcaf7ca5df8c47a61b5f6d8805a209d7eb +MD5 (NetBSD-6.0/evbmips-mips64eb/installation/netbsd-INSTALL_MALTA64.symbols.gz) = cebaa3e1af8c79ccb42a92f25140c653 +SHA1 (NetBSD-6.0/evbmips-mips64eb/installation/netbsd-INSTALL_XLSATX32.gz) = 039e0a1c46bd768a34bd4522d2523018429e6987 +SHA512 (NetBSD-6.0/evbmips-mips64eb/installation/netbsd-INSTALL_XLSATX32.gz) = 4914b5675a4b3858c3feee1eed653a75f0708b84c12d80a82715502fc9e2761eef8d23735ccdff6c596a93fa3e01ee69dcdc39cd44b5e3876722134ee90ef31b +RMD160 (NetBSD-6.0/evbmips-mips64eb/installation/netbsd-INSTALL_XLSATX32.gz) = c0cb5df60249fca57ac322b2cb8fcc6f90645698 +MD5 (NetBSD-6.0/evbmips-mips64eb/installation/netbsd-INSTALL_XLSATX32.gz) = ee03b9d28419f05275ee663b8b9d0ac9 +SHA1 (NetBSD-6.0/evbmips-mips64eb/installation/netbsd-INSTALL_XLSATX32.srec.gz) = e831083d34e0200ed793aee4a890a80f518e1ab1 +SHA512 (NetBSD-6.0/evbmips-mips64eb/installation/netbsd-INSTALL_XLSATX32.srec.gz) = 7cd35c5f5ed1ee14dbabfa9c7d89a6ed592e37b66676c1a523422d24830a28507afea99d6408dbe436d59233703257684a9cc765370c98dc23de78f3931b50c3 +RMD160 (NetBSD-6.0/evbmips-mips64eb/installation/netbsd-INSTALL_XLSATX32.srec.gz) = e6de2239f84cf7cacf8ae6b1bb62326483a1c62e +MD5 (NetBSD-6.0/evbmips-mips64eb/installation/netbsd-INSTALL_XLSATX32.srec.gz) = d7de63125741840ff89a6dff9fda38c8 +SHA1 (NetBSD-6.0/evbmips-mips64eb/installation/netbsd-INSTALL_XLSATX32.symbols.gz) = 5aa1511398191686462abbd5e20ab6e6b56fb325 +SHA512 (NetBSD-6.0/evbmips-mips64eb/installation/netbsd-INSTALL_XLSATX32.symbols.gz) = bd4c5f4b969c6c5bbb5d424c21430a3c1cbdc1f6d40a60842402ffe2d812393e0556ef6b7fade839a117a0ec601359127fd2957d35bf7468217c9adcaca53e70 +RMD160 (NetBSD-6.0/evbmips-mips64eb/installation/netbsd-INSTALL_XLSATX32.symbols.gz) = 6a2fd527f96c49423f58f6f8363e0582e2b894e9 +MD5 (NetBSD-6.0/evbmips-mips64eb/installation/netbsd-INSTALL_XLSATX32.symbols.gz) = d0654f9677e051fc34fed0d81a27e528 +SHA1 (NetBSD-6.0/evbmips-mips64eb/installation/netbsd-INSTALL_XLSATX64.gz) = 39ea7d6f681981f11fbdd9e63473e4dd69cc2f9c +SHA512 (NetBSD-6.0/evbmips-mips64eb/installation/netbsd-INSTALL_XLSATX64.gz) = 41378a129484896d4598dcfd29b1f65cc462c5746d4793e973b7912ad10cf3f1e487701f4d3267ba7615bb6fbe9390a356f1d89146e8f90d7bc8aa57ae575dec +RMD160 (NetBSD-6.0/evbmips-mips64eb/installation/netbsd-INSTALL_XLSATX64.gz) = cd77d4e08b77ede06fdcacf53cac8360b115b11d +MD5 (NetBSD-6.0/evbmips-mips64eb/installation/netbsd-INSTALL_XLSATX64.gz) = d736cdad40ba2ae3beba484dd5a5ce05 +SHA1 (NetBSD-6.0/evbmips-mips64eb/installation/netbsd-INSTALL_XLSATX64.srec.gz) = a2fd46154978cde95b379f110407c52ae0c688e1 +SHA512 (NetBSD-6.0/evbmips-mips64eb/installation/netbsd-INSTALL_XLSATX64.srec.gz) = c778ee1c88dc9aed20d7113233f43660258d1f7616e611d8e8df413b9db1e73039fe422a9ddc8c02039baea5bf5434f660fed57148f13ee641e339f9277f2c51 +RMD160 (NetBSD-6.0/evbmips-mips64eb/installation/netbsd-INSTALL_XLSATX64.srec.gz) = e98d08b85f6aae19176ad570f061f4ac14c42629 +MD5 (NetBSD-6.0/evbmips-mips64eb/installation/netbsd-INSTALL_XLSATX64.srec.gz) = c2de85181edf54b18fbe495d65faf32a +SHA1 (NetBSD-6.0/evbmips-mips64eb/installation/netbsd-INSTALL_XLSATX64.symbols.gz) = 2808091cbd1d32e9f38e7c38e7f2a0aa8c66e617 +SHA512 (NetBSD-6.0/evbmips-mips64eb/installation/netbsd-INSTALL_XLSATX64.symbols.gz) = 7c4157a809dec6f292fafd1fa21744932e8b0add59d2f3ea62c4536d31e14c6b8a24633354cb4918dd38fc88695d373d356dda7e93dfb77f83c6a6fcf6e70b54 +RMD160 (NetBSD-6.0/evbmips-mips64eb/installation/netbsd-INSTALL_XLSATX64.symbols.gz) = a31fb2125afada861428f3b416218cef7a641caf +MD5 (NetBSD-6.0/evbmips-mips64eb/installation/netbsd-INSTALL_XLSATX64.symbols.gz) = d727b2cd38e49bed46bba3a1d33f9b97 +SHA1 (NetBSD-6.0/evbmips-mips64el/binary/kernel/netbsd-GDIUM64.gz) = 938493a6f165b0a66e87d0ced332116b3e5fa1e7 +SHA512 (NetBSD-6.0/evbmips-mips64el/binary/kernel/netbsd-GDIUM64.gz) = 05906bce297394f48bddff8ea2a92f527ca5a673c1ddad6ee776eaeeb5298c562e01b533288add57bf39239c9cb02e6e8f3569c4430b658bf99b0bac61245aaf +RMD160 (NetBSD-6.0/evbmips-mips64el/binary/kernel/netbsd-GDIUM64.gz) = a2d803c0597759fcaebb669d3f4ccb7d008d2e9b +MD5 (NetBSD-6.0/evbmips-mips64el/binary/kernel/netbsd-GDIUM64.gz) = e1f26f59ce4ff562a5c8e6f8bd511a0b +SHA1 (NetBSD-6.0/evbmips-mips64el/binary/kernel/netbsd-LOONGSON.gz) = b717b1950f7e2ee2745b74e32c9f6cfc7d7ca15a +SHA512 (NetBSD-6.0/evbmips-mips64el/binary/kernel/netbsd-LOONGSON.gz) = 47916c7dc402df96876307fe31e21de43b5dcd6a57425d2454ba44593c03b0852b6dc1c5822880590a14a91717e7478314e6ac0a099004596f4d256ba3427e4b +RMD160 (NetBSD-6.0/evbmips-mips64el/binary/kernel/netbsd-LOONGSON.gz) = a1c0e2c2ea412fa4a49fce8cc1a366d9d373a5d0 +MD5 (NetBSD-6.0/evbmips-mips64el/binary/kernel/netbsd-LOONGSON.gz) = 7da6b1ffa558b1b211fe3702c5837e54 +SHA1 (NetBSD-6.0/evbmips-mips64el/binary/kernel/netbsd-MALTA32.gz) = 7c79ae79c6672c73ac03b88dab24103a01a86658 +SHA512 (NetBSD-6.0/evbmips-mips64el/binary/kernel/netbsd-MALTA32.gz) = de76f96e25bb798dfc28c0e186676833392c47a47e9eaa9c0883f9ac43f89946addd61ebfd3c91a9556eee4bb218f483053513190242abe472ddc79131224081 +RMD160 (NetBSD-6.0/evbmips-mips64el/binary/kernel/netbsd-MALTA32.gz) = 325db86c0e99e01418f70575d75c3285ad586bad +MD5 (NetBSD-6.0/evbmips-mips64el/binary/kernel/netbsd-MALTA32.gz) = 67b5fcff9d18ad156d0c028ab16ba081 +SHA1 (NetBSD-6.0/evbmips-mips64el/binary/kernel/netbsd-MALTA64.gz) = 8c7904ebdd030a94458f13ac7c11df832929cc86 +SHA512 (NetBSD-6.0/evbmips-mips64el/binary/kernel/netbsd-MALTA64.gz) = a51547232434584769c0a8ea108bff1425e5e96f1989224b3420863ebeded4a3cb272b6873e3fe860aef3658982bcde844d86fcb46d79ce647b6969e6758c978 +RMD160 (NetBSD-6.0/evbmips-mips64el/binary/kernel/netbsd-MALTA64.gz) = 656bc08ab196ab9e4638804a5ca840327a8a31a4 +MD5 (NetBSD-6.0/evbmips-mips64el/binary/kernel/netbsd-MALTA64.gz) = 8cad946d5e2a395f26d8f18eba137ada +SHA1 (NetBSD-6.0/evbmips-mips64el/binary/kernel/netbsd-P5064-64.gz) = a228a6982bb8c5cf468860e09fd9b17b4307f356 +SHA512 (NetBSD-6.0/evbmips-mips64el/binary/kernel/netbsd-P5064-64.gz) = db4187479c550a71c23f9bde6cc8dc50d2eb758293b293c7444a786ab30becbae9e150c12ef3fd55a42df1b88efdb937a7fffc48457c20c5441b082e0c0e2745 +RMD160 (NetBSD-6.0/evbmips-mips64el/binary/kernel/netbsd-P5064-64.gz) = 8d9bc3f9d1ea60e3322fac87a3c9ccd43a54055d +MD5 (NetBSD-6.0/evbmips-mips64el/binary/kernel/netbsd-P5064-64.gz) = c318ae2623b38a290cce71191c6c6afd +SHA1 (NetBSD-6.0/evbmips-mips64el/binary/kernel/netbsd-XLSATX32.gz) = 2ef72f56c819a2bc0fd4d48e463161ebef9551f2 +SHA512 (NetBSD-6.0/evbmips-mips64el/binary/kernel/netbsd-XLSATX32.gz) = 4b80ebf478d77d91205ab2d89d2459317c4b61bbae18646c2c201fb4ba1ee2978f5be3a87ad33c83d9b139d3ffa077a4bcb3e315c16fb68f116b802dd2217637 +RMD160 (NetBSD-6.0/evbmips-mips64el/binary/kernel/netbsd-XLSATX32.gz) = b5a20d970f5ad8c177c6244b1e527ea04c705cce +MD5 (NetBSD-6.0/evbmips-mips64el/binary/kernel/netbsd-XLSATX32.gz) = 34ceee3acf4435335a43c594dceff98e +SHA1 (NetBSD-6.0/evbmips-mips64el/binary/kernel/netbsd-XLSATX64.gz) = 5bf585188ba90ab0231e99247967eacfff520cc8 +SHA512 (NetBSD-6.0/evbmips-mips64el/binary/kernel/netbsd-XLSATX64.gz) = 20e39f09067084fccb2587a05a3820e50816fb3f097e8e89cb07091c937fe97aa27593948fa3466f9a5d6835a8bd1bfe31268a2414c6c8694fb9fac156e68f98 +RMD160 (NetBSD-6.0/evbmips-mips64el/binary/kernel/netbsd-XLSATX64.gz) = 96ebcf3117c2a1f60b50ba1de3852898083393d4 +MD5 (NetBSD-6.0/evbmips-mips64el/binary/kernel/netbsd-XLSATX64.gz) = 335908a4efd612fbc51487db37af3eb0 +SHA1 (NetBSD-6.0/evbmips-mips64el/binary/sets/man.tgz) = 899b9d8242e983a5110ab755651c24f709b5af67 +SHA512 (NetBSD-6.0/evbmips-mips64el/binary/sets/man.tgz) = 410999db110d710f4bb498c3d7ae7adc62170c7c2f470ce189c92f6c436c5ea96149659c631ef0b5605caaa025d97dfe1c07c428d86f51239657bd6b71717b15 +RMD160 (NetBSD-6.0/evbmips-mips64el/binary/sets/man.tgz) = c1270f68c6d41b351877f71f0396ac34877dfc8d +MD5 (NetBSD-6.0/evbmips-mips64el/binary/sets/man.tgz) = df4db2bbfa39ef6a4a215d949653d04a +SHA1 (NetBSD-6.0/evbmips-mips64el/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/evbmips-mips64el/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/evbmips-mips64el/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/evbmips-mips64el/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/evbmips-mips64el/binary/sets/kern-GDIUM64.tgz) = a09a36dad31ab7a766bcddea3fb08807d93819bd +SHA512 (NetBSD-6.0/evbmips-mips64el/binary/sets/kern-GDIUM64.tgz) = e3876e7f4164e117ada834e6769fd3357d144fe36779a197573a8ea735821150fbc6c4b6c2b9ea917b14b23a795e4db7e069cb8e121ac3fe9ae5e0296400d065 +RMD160 (NetBSD-6.0/evbmips-mips64el/binary/sets/kern-GDIUM64.tgz) = 945ea08a5fdad4d8ac8504212712b40aa01d1443 +MD5 (NetBSD-6.0/evbmips-mips64el/binary/sets/kern-GDIUM64.tgz) = 2fcaffaee00d469cb7f2756fdcfd2fa6 +SHA1 (NetBSD-6.0/evbmips-mips64el/binary/sets/base.tgz) = e7550ddcf5edc7c3c27f53b7e6b4636f744108c7 +SHA512 (NetBSD-6.0/evbmips-mips64el/binary/sets/base.tgz) = 0096eb300e8a71093cbe3e84830ff048af73e85cbbad1986390b8838c50ab6bd63cdc201062514aa63529c2043e1a2b2428cb2b50fa2bcb9dfd4ed11e42febdc +RMD160 (NetBSD-6.0/evbmips-mips64el/binary/sets/base.tgz) = a5509e8f5a4e5aadcf057710489fa4105dc4dcbc +MD5 (NetBSD-6.0/evbmips-mips64el/binary/sets/base.tgz) = 76f45332e5fae1c999dba2da97f92834 +SHA1 (NetBSD-6.0/evbmips-mips64el/binary/sets/comp.tgz) = 2475e5bc61cb7084e06f111d6e24e3ef4527ab0e +SHA512 (NetBSD-6.0/evbmips-mips64el/binary/sets/comp.tgz) = 5ca83f2b42cd3145d3fa5c88e72dec3509f52f63bd0e5ac26f752a18065473ea298bc0e88cb0b954a06d3d7eba5a9afdee3087feb06079e9c76cd5a0ae3a6759 +RMD160 (NetBSD-6.0/evbmips-mips64el/binary/sets/comp.tgz) = 8bf71a3552e3e9388c85d5426530e58d2ff15f9f +MD5 (NetBSD-6.0/evbmips-mips64el/binary/sets/comp.tgz) = e8dcb0d4b7b5acbf8f4603be69f4e9b1 +SHA1 (NetBSD-6.0/evbmips-mips64el/binary/sets/etc.tgz) = 106b0102ae77486072a61db71016443e4a63af9e +SHA512 (NetBSD-6.0/evbmips-mips64el/binary/sets/etc.tgz) = 386948f2aa4dd140bf17c9aa0a8bd0b41096603497dbb9792454fa3772724312a3a2ddd3e69a7b1a710e6339f799b5174b16f8f91ef123ebde548eb47aee4e90 +RMD160 (NetBSD-6.0/evbmips-mips64el/binary/sets/etc.tgz) = c704f1a292af8fbfe37a9a61654f8e8873b6cf49 +MD5 (NetBSD-6.0/evbmips-mips64el/binary/sets/etc.tgz) = ea16b2ab565706b8038b459e0519936e +SHA1 (NetBSD-6.0/evbmips-mips64el/binary/sets/games.tgz) = fbb547d701d95fa7c9fedb8ce1616fa73dc0a962 +SHA512 (NetBSD-6.0/evbmips-mips64el/binary/sets/games.tgz) = 9b0c4338c3227f974305624f0ba8756836f156f3d3f9bbb1ec3188ca9ec2de344d5ff3f8b9969180e2c871cc0b09b12b9e6311e33ca548d59f4596a04224f14e +RMD160 (NetBSD-6.0/evbmips-mips64el/binary/sets/games.tgz) = ae8ec9dca5729ee4203ff86e10ebb16379ccf5f5 +MD5 (NetBSD-6.0/evbmips-mips64el/binary/sets/games.tgz) = 18b0244267ae2ea671632562ebf493c2 +SHA1 (NetBSD-6.0/evbmips-mips64el/binary/sets/kern-LOONGSON.tgz) = 8da37bef5b86301e6e5741969aaab713752c2866 +SHA512 (NetBSD-6.0/evbmips-mips64el/binary/sets/kern-LOONGSON.tgz) = be868f49e960bdee048cc1a717d17563c081afdf2a258007312f306f14470159943877ef29d0c3c783b32682074c299aeb2b48a7623bdc4af2adaf82ee9b52e1 +RMD160 (NetBSD-6.0/evbmips-mips64el/binary/sets/kern-LOONGSON.tgz) = 10f65602b7dab9305df83c26e670221efe1b452c +MD5 (NetBSD-6.0/evbmips-mips64el/binary/sets/kern-LOONGSON.tgz) = caffb25555770c6474b23e6cd028e82e +SHA1 (NetBSD-6.0/evbmips-mips64el/binary/sets/kern-MALTA32.tgz) = 7e5d386cee62920ecd932af45ff4a854234edc8a +SHA512 (NetBSD-6.0/evbmips-mips64el/binary/sets/kern-MALTA32.tgz) = f5e9bb4886260c3eb0b18e29999047b1f39692be5cd5cbeb58638604efae408f167cbccb81d2fc6c601f20515955b48035113cc2cb2e6d30088cd9750fa64465 +RMD160 (NetBSD-6.0/evbmips-mips64el/binary/sets/kern-MALTA32.tgz) = e0a36f2148ed78c4eda1c26e5ef0045ff6b97e22 +MD5 (NetBSD-6.0/evbmips-mips64el/binary/sets/kern-MALTA32.tgz) = 3ccd62f53f80b0eabb9baa2a29a691ac +SHA1 (NetBSD-6.0/evbmips-mips64el/binary/sets/kern-MALTA64.tgz) = 225382c44befe15c46b05f2f052718bd80dd9a7d +SHA512 (NetBSD-6.0/evbmips-mips64el/binary/sets/kern-MALTA64.tgz) = 1c1a13c0b73098d14468cf12d7744f79696773698adf94e622afd95e436560fc4934d3b02390187647a9d97effbed9162542149fbe06628cf38aff197faaafd6 +RMD160 (NetBSD-6.0/evbmips-mips64el/binary/sets/kern-MALTA64.tgz) = e5ae37af03461f04dc6550141e4c2301dce51ff2 +MD5 (NetBSD-6.0/evbmips-mips64el/binary/sets/kern-MALTA64.tgz) = 672129c4f8f0315c9b374ac5651f82cc +SHA1 (NetBSD-6.0/evbmips-mips64el/binary/sets/kern-P5064-64.tgz) = a41b86f2235180b688882c8eb2959edcb48c81ca +SHA512 (NetBSD-6.0/evbmips-mips64el/binary/sets/kern-P5064-64.tgz) = 9db6c584144a249006a671894e010fa0674e62e6abc60d43441462d1f1478bf4b1f9c6d9b46f14a1e9ffc3f7641bc206f5ed95c90b405e57f3f40e54d74aec92 +RMD160 (NetBSD-6.0/evbmips-mips64el/binary/sets/kern-P5064-64.tgz) = a7f59b498f286aeffe614b4ae43461d8a859f758 +MD5 (NetBSD-6.0/evbmips-mips64el/binary/sets/kern-P5064-64.tgz) = 5dc76b6c8b5b49b757dd4a5dfa370420 +SHA1 (NetBSD-6.0/evbmips-mips64el/binary/sets/kern-XLSATX32.tgz) = 9cdf4993097b04929dbad4b76c5bbf0cd6796c7d +SHA512 (NetBSD-6.0/evbmips-mips64el/binary/sets/kern-XLSATX32.tgz) = 171bcfbb92a1c1ca96dc14707604998eb4c5760179e9781da9b0ad18ad9695ea44d49c5cdd9ac9250a7a60e08b336daefa9a6efc2f172c9a70d10417e4643b0d +RMD160 (NetBSD-6.0/evbmips-mips64el/binary/sets/kern-XLSATX32.tgz) = a1a517153943866b07fb5850644d1079721fd131 +MD5 (NetBSD-6.0/evbmips-mips64el/binary/sets/kern-XLSATX32.tgz) = f68253bb53367876e463884c2a8eaabf +SHA1 (NetBSD-6.0/evbmips-mips64el/binary/sets/kern-XLSATX64.tgz) = 73dcbbb4ffbd263a8ab68a5144b16cda35e14272 +SHA512 (NetBSD-6.0/evbmips-mips64el/binary/sets/kern-XLSATX64.tgz) = bee28f3a052cad0a8624729675f28d42847b7545234f98e141c180e851a3f2052236606c512f1a7515c7ba115417eb8e8a9ceba2224a1c5915ea44f25cd99abb +RMD160 (NetBSD-6.0/evbmips-mips64el/binary/sets/kern-XLSATX64.tgz) = ba17bd15f5e3b131ed77687817b58f8a1730232c +MD5 (NetBSD-6.0/evbmips-mips64el/binary/sets/kern-XLSATX64.tgz) = 0a2ea3efdd4858019a64cf67994cbc36 +SHA1 (NetBSD-6.0/evbmips-mips64el/binary/sets/modules.tgz) = 4ce7dd5ecba275042042fc283bf93453fc57b2fa +SHA512 (NetBSD-6.0/evbmips-mips64el/binary/sets/modules.tgz) = b90e1c87a5ad7981bf51e9fd33b2614d6d092c10c6d67a242ebd814276dd116ac660d9801ad02a5b9b09ce58e3c2aca802322c97ea73c9e270f88d1162e7ae24 +RMD160 (NetBSD-6.0/evbmips-mips64el/binary/sets/modules.tgz) = 73d91a2e36f2ec78fc3aa1f2c2af0d2a2d9174a8 +MD5 (NetBSD-6.0/evbmips-mips64el/binary/sets/modules.tgz) = ead882dfd50f9421b51a5fc5deb0151e +SHA1 (NetBSD-6.0/evbmips-mips64el/binary/sets/tests.tgz) = 441100d5b3275b38c206eeb86a9153084f37e613 +SHA512 (NetBSD-6.0/evbmips-mips64el/binary/sets/tests.tgz) = e3f33662a577ad2ec975b432424b5d2c2b3b2b742d5e2ce37043cb1820ba225b185638c5c88a34fe05af9fa0083db918074cbb8f091354c35e8f2fd121f93dea +RMD160 (NetBSD-6.0/evbmips-mips64el/binary/sets/tests.tgz) = 64e119a7b1ed5eec0151ebe0ac8c6d2f362e8dc0 +MD5 (NetBSD-6.0/evbmips-mips64el/binary/sets/tests.tgz) = 0d6eedfa2f9aae4c8f0055ca1a358c66 +SHA1 (NetBSD-6.0/evbmips-mips64el/binary/sets/text.tgz) = b7f32924a9d2c54824fb19b1bb3158b2996a16d1 +SHA512 (NetBSD-6.0/evbmips-mips64el/binary/sets/text.tgz) = 00b6a2831c439c9a5bb07023fecbd7ac99285b2f08a2eb2ba00ace828eaa4cb5fdbd12c339170b9235713d9936683837214389ebfeb52c9bc4be07bcc0df0e15 +RMD160 (NetBSD-6.0/evbmips-mips64el/binary/sets/text.tgz) = 6f72bbbef2e15bc63b99ae7419a6a68f3a82b7e5 +MD5 (NetBSD-6.0/evbmips-mips64el/binary/sets/text.tgz) = ec982ff4007c1082127af777e978bc85 +SHA1 (NetBSD-6.0/evbmips-mips64el/binary/sets/xbase.tgz) = 2e87de8a350d32c3529222c0195e8b89a03f1192 +SHA512 (NetBSD-6.0/evbmips-mips64el/binary/sets/xbase.tgz) = 65ba278254dcef89f1cc464487921995413a5400cf0a3388eb987416486f96f510c91569b6c3145d687e05eedc93be79bf54374c67fb33ffc57eb2b89902d096 +RMD160 (NetBSD-6.0/evbmips-mips64el/binary/sets/xbase.tgz) = 7acd24fa398777d99977da6d6080c89ab8a75ef3 +MD5 (NetBSD-6.0/evbmips-mips64el/binary/sets/xbase.tgz) = 5535460ce0de58bbbd1aa49741edc463 +SHA1 (NetBSD-6.0/evbmips-mips64el/binary/sets/xcomp.tgz) = 70a07fcea399d1032660b185c2d9ac6486da8fbc +SHA512 (NetBSD-6.0/evbmips-mips64el/binary/sets/xcomp.tgz) = a803322c59fef449066d1d2e42beec42587e40f6134f5c62d475440a01fbf93a91aa9bfae96b89eb6394e2f20d925fb85dc23754bf8600feb40cc98a9beb844e +RMD160 (NetBSD-6.0/evbmips-mips64el/binary/sets/xcomp.tgz) = 12a13cd5fa3a63ddc24e4f4bfc6d35ce99dad31d +MD5 (NetBSD-6.0/evbmips-mips64el/binary/sets/xcomp.tgz) = 0b455b3722b1429e0a134317b8dbdea2 +SHA1 (NetBSD-6.0/evbmips-mips64el/binary/sets/xetc.tgz) = a95c9eb9995be3639417ed3098f7ef36baa0d729 +SHA512 (NetBSD-6.0/evbmips-mips64el/binary/sets/xetc.tgz) = be4544652b01b9161ba2f27461ed723378712d0b34058ba5a16de3cc366a5b551f0e8e7b740404eebbee7ae656e7745281b7d329068bb1aedf8f757ed06e9f98 +RMD160 (NetBSD-6.0/evbmips-mips64el/binary/sets/xetc.tgz) = b7e1bac15f5d4dda393d5e07e2b26d3c3877a01d +MD5 (NetBSD-6.0/evbmips-mips64el/binary/sets/xetc.tgz) = ee2771391cc229fb9bea94f455e841e4 +SHA1 (NetBSD-6.0/evbmips-mips64el/binary/sets/xfont.tgz) = b985c741b487ae0e65ca36e318c558c147d1eca5 +SHA512 (NetBSD-6.0/evbmips-mips64el/binary/sets/xfont.tgz) = 3da2aa9b1cb7906f515d0c02d67a8aa994a0022189dab11428a28040f57f5ae3cfb758cc7676837aca3479bfcc1e1551afe592417b59ad79b80a6392d6f34929 +RMD160 (NetBSD-6.0/evbmips-mips64el/binary/sets/xfont.tgz) = bccdaaa5821219a03bd67a57320311b265a19e94 +MD5 (NetBSD-6.0/evbmips-mips64el/binary/sets/xfont.tgz) = 60eaa14a01f682577ab5b1774fefd7b8 +SHA1 (NetBSD-6.0/evbmips-mips64el/binary/sets/xserver.tgz) = 30134e060bc2ad1df81dfb637ec9d7e35bbc4932 +SHA512 (NetBSD-6.0/evbmips-mips64el/binary/sets/xserver.tgz) = 94e7986f96ec8b41653db1b4c05d0237c614678b43f1a52ab3b40c5627ffea2c7e91ae3e154391b964dc36edbd60aaed767427bd50eae5306beb0fead97c0346 +RMD160 (NetBSD-6.0/evbmips-mips64el/binary/sets/xserver.tgz) = 2423334e389526cac76e76fa0fa38fd671e0d3c2 +MD5 (NetBSD-6.0/evbmips-mips64el/binary/sets/xserver.tgz) = 508453785f0150d7115610f4ab1f0ae9 +SHA1 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_LOONGSON.srec.gz) = 3d7cbad15200cb0e18ed529e8d65768503bd0a96 +SHA512 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_LOONGSON.srec.gz) = c549dc552ae2b10bd3d8b6b716d6a107e5ef6988a49b2ae1292b40608d217cafa8bbb77974c3e8fe9291820bd534b0713c1136a09c173c282384f2805cabad1c +RMD160 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_LOONGSON.srec.gz) = eb53ea3f18593ad0a8d23ab92b8d78e590709cae +MD5 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_LOONGSON.srec.gz) = 6c0fbfaa9cafb5799820bf14e057a5fe +SHA1 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_LOONGSON.gz) = 5f370ee3290556f0df9346c1c279b4cd239815bd +SHA512 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_LOONGSON.gz) = 8a7770a9dca3bd6bb59525c7f5340c9347d7c315e6f54c719d5f46312e0ff25d1fd6ba0e31d881ee680d904534a71f7258c49c16e706a46cb6ff0ada537630fc +RMD160 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_LOONGSON.gz) = ed1b7878ae50846b27db943ff3f82d0be2e4bd05 +MD5 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_LOONGSON.gz) = d935eea2ed1da5225fd8af96482ecc08 +SHA1 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_LOONGSON.symbols.gz) = 0f65b3f9550c07786d711dfa98c426f3601e0f01 +SHA512 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_LOONGSON.symbols.gz) = b37c854b5a20cd45da6e1fb4132a0fc8bf1234ff08294168249a3a38e8463a9c52fc9863af80787c10ae62e1bb17be087cab605478f5fb29dd615f8168ea9180 +RMD160 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_LOONGSON.symbols.gz) = 1365f99730e4ab317d1d35e73f2eb5592680ece6 +MD5 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_LOONGSON.symbols.gz) = af18fc0829c787d47e6cdc7e6146413f +SHA1 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_MALTA32.gz) = 24b04245cb3bb8808c2643f6efa74677e18425c9 +SHA512 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_MALTA32.gz) = 4d76662f4aaa9fbdb3bc3e807eb716804f4ac070e8b0e6def5e9c4c816ed456894bad40a3b51ff8f68a21b05bee08de02e7fb1ee1ece8e625884dbb2bccd9109 +RMD160 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_MALTA32.gz) = cdff1dcb0aecc09f926915055769081acab42201 +MD5 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_MALTA32.gz) = 06cca864f41f90c5f0bd6d95a57ecc5c +SHA1 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_MALTA32.srec.gz) = 5a432e451fb73617b8377b4f479a6eaf611bac29 +SHA512 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_MALTA32.srec.gz) = 3f92a16819d8452f7d105e19d803985832f89e1d6c09b067d6ffe4522c7e924707d9411535ccf838cdec3b7fd1fa17cd7cfbb6e2d3bd369690dcd9094f5e10f3 +RMD160 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_MALTA32.srec.gz) = 71a1e5b455df4458e1bb4ec9d45b4043bebc5788 +MD5 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_MALTA32.srec.gz) = 98534235eaeb7626a485458779a0e6a8 +SHA1 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_MALTA32.symbols.gz) = 2f3ed468ae1a3a4082bfd5412bc11ee8d8cb90f9 +SHA512 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_MALTA32.symbols.gz) = fc3b4ac13b3c951037e30132d9178dd79635cb78adea2b97046ef6d8a8486bf9b12e43d26897f32f7db967fddd048c177acbb5585b573bc2b9c80374b59c133d +RMD160 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_MALTA32.symbols.gz) = 5e863f2e95a8623056dc32ea5ba0265876f102df +MD5 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_MALTA32.symbols.gz) = e84090937754b1d91357b759679a2ae4 +SHA1 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_MALTA64.gz) = 3e9f23c9e3f15de38a7e0908f0253d1f23e49a43 +SHA512 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_MALTA64.gz) = 57cf422b28f5442c105e23fae81119e993b543e3eb2c344ab5334e8edb1018c54f3b39245d1bc4091b8de4e28fe78e357dfef31bfa51de174342ba881ef9cf45 +RMD160 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_MALTA64.gz) = 9950fb85a0100463810fee9d0ab79d4297e94401 +MD5 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_MALTA64.gz) = 571361834195d0048cfb4c2bb13faf10 +SHA1 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_MALTA64.srec.gz) = 03a6a6428275c9f01f514031f5c288739a081850 +SHA512 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_MALTA64.srec.gz) = 4165164e3830c5dd897107c64cd6dcbb27edc31e32bf6cf7305fe74024c467a81e703ed1be94071c62cf467eab89ecd66b3b72876fc1d8fece4792dbb8384255 +RMD160 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_MALTA64.srec.gz) = 68586dd9c3e823a26a5439907f088772a5939b88 +MD5 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_MALTA64.srec.gz) = 37ec696958709fadbfe7e08fcac3bb57 +SHA1 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_MALTA64.symbols.gz) = bdc6c366da273e056df2ea2bd9d92813b61f5b36 +SHA512 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_MALTA64.symbols.gz) = 574c80f478e5f87eae6602a8e8b6d52df19061199f2e78d05bc6e662daca5f9b6aef26dd4b543d24e557b78aa2d5f0a5e80aa9cdfca5fbcdfc8a4da7a84b95d0 +RMD160 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_MALTA64.symbols.gz) = 4f8ba01f1ba53c8b8230a974d7c8aa45a9667915 +MD5 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_MALTA64.symbols.gz) = 5e726ecc87a4406b10e5c11cbf745a7e +SHA1 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_XLSATX32.gz) = a21c899aa2389958474b94a057e7356da840589f +SHA512 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_XLSATX32.gz) = d092b4d17356ed34a9a7a79838b76a487c35d99b26671f1ddfadb85db810bda74b3db64f7734e30114429cd8fad87f13c04ca462c6d3bb56dc1f78855d7b9def +RMD160 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_XLSATX32.gz) = ae46da84fdb8a17e60c91ef88049989eed666a96 +MD5 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_XLSATX32.gz) = 1ec7762cd142ac3eacfad76ebd7f018d +SHA1 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_XLSATX32.srec.gz) = b76ec124d80dbda9a425bd14737ff88105d4c053 +SHA512 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_XLSATX32.srec.gz) = eb446974d31976ddac9313a0a45ffc084dea1bfff75d18e6544f16cab3333dcaf6e62cff59b0cf88070985c1ab7a4c0285cdd0b54eb75d73f538d45a80be9256 +RMD160 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_XLSATX32.srec.gz) = 1eae8b53f9ad020c3a39d67502e74888059125f1 +MD5 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_XLSATX32.srec.gz) = 3c2a22221dab7153f7eb41daec3a4de3 +SHA1 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_XLSATX32.symbols.gz) = 0be09076adaccfe13864e71c9f1ed8085a515401 +SHA512 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_XLSATX32.symbols.gz) = 7bd72d9d584872ca346e2ee6eeebc8e8fd06a7e655acf621ad1b849b440ff66a33bf71650738a074732845c2bde24acb08e1b457e08abde3234d2972da370773 +RMD160 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_XLSATX32.symbols.gz) = cfc81eef00d46e0c1deea04c9364f64e87d637db +MD5 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_XLSATX32.symbols.gz) = 11e04b25355c8c60ba97c142c21ba8f3 +SHA1 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_XLSATX64.gz) = a68f5f892312208526869378614a6c38f0ce7ac1 +SHA512 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_XLSATX64.gz) = 7b298f7fe80f77e2283c407af4736c643e3b0d0710d43bbe809dda43660344caa948ebb07727ec80cf19065eb1a30ef24c68d0249d2cbc9598833c14f36a04fb +RMD160 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_XLSATX64.gz) = 431a3a8bf7ea9aa86b7c82075a2c6272ea9f4938 +MD5 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_XLSATX64.gz) = d1cfbf1aea636ec7f9b36760eea32d08 +SHA1 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_XLSATX64.srec.gz) = e766bb842b698937ab7252c0bf6f325f1ec2c7b6 +SHA512 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_XLSATX64.srec.gz) = 832e277c2366f3379f104fe68aa927b3c7358c40df62f393419ae9f2fe30a989a532f4d4cac8dd821ea07c5707246329990e64ded734cad1c4e755a59cb59402 +RMD160 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_XLSATX64.srec.gz) = 44af060baa21f3c09fa3e283cde72a7171f6e6f2 +MD5 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_XLSATX64.srec.gz) = 058b4dc450b1e2e5fc14136e4ccf3743 +SHA1 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_XLSATX64.symbols.gz) = 5130e72edc460e5bc620f9101c6b260db4417ef3 +SHA512 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_XLSATX64.symbols.gz) = 53360173909b40e40ac018fa0f5211a74970d3429c85c182f59a6ee4ce782f54d707f2d6205d9bb5f4fd5b100b074babec12bbaf178f74b867cfba5964aa2ec2 +RMD160 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_XLSATX64.symbols.gz) = db94d2cc9bfc2eb2fd44e87d47be4b273aa7533e +MD5 (NetBSD-6.0/evbmips-mips64el/installation/netbsd-INSTALL_XLSATX64.symbols.gz) = 37e4e9464364847ad2327d6352019047 +SHA1 (NetBSD-6.0/evbmips-mipseb/binary/kernel/netbsd-aumac0-ALCHEMY.gz) = c8b43df25bfc2e9171d6ddaa73b436f63a9c7085 +SHA512 (NetBSD-6.0/evbmips-mipseb/binary/kernel/netbsd-aumac0-ALCHEMY.gz) = 73d80744cb6154342f5c3d36f8849c2a9686c1318fea913b840eb97e3177f1b225f4cb9178a9e15b4cadae35579c2258b38d180d1aedfb0e9ffa00543b1cd8e6 +RMD160 (NetBSD-6.0/evbmips-mipseb/binary/kernel/netbsd-aumac0-ALCHEMY.gz) = c8e8dd4c41e4e88fd7bc0c34420df32a00a941b6 +MD5 (NetBSD-6.0/evbmips-mipseb/binary/kernel/netbsd-aumac0-ALCHEMY.gz) = 53e030127285e17b67640e9fd98af1a6 +SHA1 (NetBSD-6.0/evbmips-mipseb/binary/kernel/netbsd-ALCHEMY.gz) = 9f738766737db8cb0f2404c4952bb75cbf407669 +SHA512 (NetBSD-6.0/evbmips-mipseb/binary/kernel/netbsd-ALCHEMY.gz) = 1298e944b4d8495905e6649476cb8e1bf49719abf2d2fb3ae55f5e1416a2af3234310047926fc261264bb12b8c40d09159a42cd978297cd6ee4197249a34561e +RMD160 (NetBSD-6.0/evbmips-mipseb/binary/kernel/netbsd-ALCHEMY.gz) = 53f5c1646d7811b99d2a6bade48712647802264e +MD5 (NetBSD-6.0/evbmips-mipseb/binary/kernel/netbsd-ALCHEMY.gz) = 7315ee909933e50ada51ab5652ad0d2f +SHA1 (NetBSD-6.0/evbmips-mipseb/binary/kernel/netbsd-DB120.gz) = ff83b1a41048bcef21a723c356d5e762d1ae697f +SHA512 (NetBSD-6.0/evbmips-mipseb/binary/kernel/netbsd-DB120.gz) = 400430bfab26962e450f73640ca169fdf4f748ff34c63dac1edaab893f58a3494a81ecefa807bd80cdf846213d004dcedeeb0b57e785436488c26a66c06ed685 +RMD160 (NetBSD-6.0/evbmips-mipseb/binary/kernel/netbsd-DB120.gz) = aa36f1124c77777325cf30badccc02f2353e9065 +MD5 (NetBSD-6.0/evbmips-mipseb/binary/kernel/netbsd-DB120.gz) = 8e6dfcd4eaa37591d2648cfbead5b650 +SHA1 (NetBSD-6.0/evbmips-mipseb/binary/kernel/netbsd-DBAU1500.gz) = 5e4747aafb2621b40c0adb250613225090d8f219 +SHA512 (NetBSD-6.0/evbmips-mipseb/binary/kernel/netbsd-DBAU1500.gz) = a24d3164c5f9eac497b338e99fd04881e9fb3ea1e25844c4d9927383f306b9d0fe16e26f61e33ca7fcc47be9e6b1a04b2cc6b397f51187e49c5683714ee4880f +RMD160 (NetBSD-6.0/evbmips-mipseb/binary/kernel/netbsd-DBAU1500.gz) = c90b133fd12b1327cbf8cd0229df26d3b71774dd +MD5 (NetBSD-6.0/evbmips-mipseb/binary/kernel/netbsd-DBAU1500.gz) = b691ce9b6e0e31b0945fb7ff041e336d +SHA1 (NetBSD-6.0/evbmips-mipseb/binary/kernel/netbsd-DBAU1550.gz) = 62ac90542124d3b65582b7c5667e545fbd7b1145 +SHA512 (NetBSD-6.0/evbmips-mipseb/binary/kernel/netbsd-DBAU1550.gz) = 29622cc0d471a80ab095fda13f2d06ac32d4757d2a2ce4c4c7a54b490b6445ee86c702007de54ac9fe81515566d7eca3805f2d1c4d842a49d8c752df4d09099c +RMD160 (NetBSD-6.0/evbmips-mipseb/binary/kernel/netbsd-DBAU1550.gz) = b624724146136eaf312d9be3cead0eb8f55445bc +MD5 (NetBSD-6.0/evbmips-mipseb/binary/kernel/netbsd-DBAU1550.gz) = 0d30e656a06c9c5ab86c9097e08b2ca8 +SHA1 (NetBSD-6.0/evbmips-mipseb/binary/kernel/netbsd-MALTA.gz) = 83ac7456a68f04283e651f472160025d9af2b256 +SHA512 (NetBSD-6.0/evbmips-mipseb/binary/kernel/netbsd-MALTA.gz) = 1c36d9ef350ae385688a4300af725d1b2ccc94ca3f6eded04d54ca2dcfceb40d5ef8db88610428051598e7a1504340ab86bfda25d96bfc3b454aa74f0f35ece7 +RMD160 (NetBSD-6.0/evbmips-mipseb/binary/kernel/netbsd-MALTA.gz) = 59acc8c3c660bf2256966b58cce5df78cc6a4da3 +MD5 (NetBSD-6.0/evbmips-mipseb/binary/kernel/netbsd-MALTA.gz) = a64c723ecc8ff566fc859d155bf288a5 +SHA1 (NetBSD-6.0/evbmips-mipseb/binary/kernel/netbsd-RB433UAH.gz) = 8af25f51ed2e87eaa234c4bf43a0c8adefa3c267 +SHA512 (NetBSD-6.0/evbmips-mipseb/binary/kernel/netbsd-RB433UAH.gz) = ecfff13379b5e6a657670f69aec3ce471a593505e0f6284f80c0b4f3c4c903bc9bb7d9cf0c9385e0b0f5288cc141bf5c21e56250ae17107f53ca38152fc59a13 +RMD160 (NetBSD-6.0/evbmips-mipseb/binary/kernel/netbsd-RB433UAH.gz) = 38d8fcad12171bb0209eaef94e137483d6d3f5e5 +MD5 (NetBSD-6.0/evbmips-mipseb/binary/kernel/netbsd-RB433UAH.gz) = da92ce6119755ebd89fe27c24f452aea +SHA1 (NetBSD-6.0/evbmips-mipseb/binary/sets/games.tgz) = f56d3e5181634f6a3d7908dcb002ebcb1c5aaff0 +SHA512 (NetBSD-6.0/evbmips-mipseb/binary/sets/games.tgz) = 0cff50ea13e34fe338edf70da6a28af061580feb4cb0773828adefa631ebd471a96568a3b30ea0f13f3bb116856a1b6aad8a5a52443346f52e4907f4caabc5f1 +RMD160 (NetBSD-6.0/evbmips-mipseb/binary/sets/games.tgz) = 1538910578dbb8eee2931200fac0ccda44758e5f +MD5 (NetBSD-6.0/evbmips-mipseb/binary/sets/games.tgz) = 2bd5bd0ce72df5cf92767b8c3f7cc208 +SHA1 (NetBSD-6.0/evbmips-mipseb/binary/sets/man.tgz) = 899b9d8242e983a5110ab755651c24f709b5af67 +SHA512 (NetBSD-6.0/evbmips-mipseb/binary/sets/man.tgz) = 410999db110d710f4bb498c3d7ae7adc62170c7c2f470ce189c92f6c436c5ea96149659c631ef0b5605caaa025d97dfe1c07c428d86f51239657bd6b71717b15 +RMD160 (NetBSD-6.0/evbmips-mipseb/binary/sets/man.tgz) = c1270f68c6d41b351877f71f0396ac34877dfc8d +MD5 (NetBSD-6.0/evbmips-mipseb/binary/sets/man.tgz) = df4db2bbfa39ef6a4a215d949653d04a +SHA1 (NetBSD-6.0/evbmips-mipseb/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/evbmips-mipseb/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/evbmips-mipseb/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/evbmips-mipseb/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/evbmips-mipseb/binary/sets/xcomp.tgz) = c8f5ff5ea9f9bbe231f92d8b7f3bfcbd2897069f +SHA512 (NetBSD-6.0/evbmips-mipseb/binary/sets/xcomp.tgz) = c7590075195019078b68ec5f87e36479ae2e7b7749c523df4ef21c9d881c343cda9f5c2bba897dd313329a76fe5c18e920d92827878d98ce08a7dc776352cd02 +RMD160 (NetBSD-6.0/evbmips-mipseb/binary/sets/xcomp.tgz) = bc60e267cb6e11b4a7305f8b7074084e179e0ff5 +MD5 (NetBSD-6.0/evbmips-mipseb/binary/sets/xcomp.tgz) = 8e58ee51667def3bd015f79769c0d932 +SHA1 (NetBSD-6.0/evbmips-mipseb/binary/sets/xfont.tgz) = c551bd13179b9508c2e3a7e19cec323e8ba21844 +SHA512 (NetBSD-6.0/evbmips-mipseb/binary/sets/xfont.tgz) = 764527f2f3f4686759fcae3fd093f4e00f34e1249994126221a6f9afe73d4cf8ddfbe8b8311798da2ed38c52466a44bb26ea08ad5aab1c08eebcc9019b4223f7 +RMD160 (NetBSD-6.0/evbmips-mipseb/binary/sets/xfont.tgz) = b3a365bedf8b4a20f3920d0e33b9a42fce288953 +MD5 (NetBSD-6.0/evbmips-mipseb/binary/sets/xfont.tgz) = adac8939da213a0195cc1d351f979199 +SHA1 (NetBSD-6.0/evbmips-mipseb/binary/sets/kern-ALCHEMY.tgz) = 0adc8f742c596217127185e8f9e4db43896d9299 +SHA512 (NetBSD-6.0/evbmips-mipseb/binary/sets/kern-ALCHEMY.tgz) = 35865aa4e39ecbf9c8f4e48ac85b804b571b1488de729cbbc5663deec75bdbf90a229ce99473975ea46715d502442497a596fa35ed89e5d3602c3b1221db6676 +RMD160 (NetBSD-6.0/evbmips-mipseb/binary/sets/kern-ALCHEMY.tgz) = 8a4fea3817d615408966528475869669efc69701 +MD5 (NetBSD-6.0/evbmips-mipseb/binary/sets/kern-ALCHEMY.tgz) = 94e9d6a99aa8ad762dfd71d5c2c5a410 +SHA1 (NetBSD-6.0/evbmips-mipseb/binary/sets/base.tgz) = 152709728189dfceee8db96c9b793229d80514ca +SHA512 (NetBSD-6.0/evbmips-mipseb/binary/sets/base.tgz) = fab7d3d262ebc5bff7c6edd891b967dc10f4c274b33da21a874ef874ccd1f1917afef30cccc27efce5869296e9bcec95584fd6109a48abd94b958b231a5e2fbe +RMD160 (NetBSD-6.0/evbmips-mipseb/binary/sets/base.tgz) = e52f8333537d524fd1580d0b07c9c63414fe680b +MD5 (NetBSD-6.0/evbmips-mipseb/binary/sets/base.tgz) = b2dae13bf91a2929948ee84429598111 +SHA1 (NetBSD-6.0/evbmips-mipseb/binary/sets/comp.tgz) = b04647e2ea51827ceff965350bff9290cb4e1da7 +SHA512 (NetBSD-6.0/evbmips-mipseb/binary/sets/comp.tgz) = 15b6bda11ff6d85a0e1696a2fbd174d1b060e606f52e7447d6c25a48de41f03e99e8601f098c6604608e3a056096c8b17ea6865802db353a018860a3c563d387 +RMD160 (NetBSD-6.0/evbmips-mipseb/binary/sets/comp.tgz) = 0ca46bc47c48ba36c8e56b9131abd9d61d5c7ae6 +MD5 (NetBSD-6.0/evbmips-mipseb/binary/sets/comp.tgz) = 5917382e90e63ec66e687546760a8532 +SHA1 (NetBSD-6.0/evbmips-mipseb/binary/sets/etc.tgz) = e55b4d17ca25e42c4a0652a40106d64eda9f8096 +SHA512 (NetBSD-6.0/evbmips-mipseb/binary/sets/etc.tgz) = e6286e75f5ec6591a53162c332be61b976e4e0386d429aa675cce295ed8fdb90d62287b244eecd0e0341235a637bbd593f50164dc8f589ac4f969991d2a3f0f9 +RMD160 (NetBSD-6.0/evbmips-mipseb/binary/sets/etc.tgz) = b45e18e794d732b11dc8eb3ef733c2dfdbd0155a +MD5 (NetBSD-6.0/evbmips-mipseb/binary/sets/etc.tgz) = 2a4d24ad39ee26ad3bf2a6c9d86381a2 +SHA1 (NetBSD-6.0/evbmips-mipseb/binary/sets/kern-DBAU1500.tgz) = d6c5b3f1074c70e13e1388d68a1932cc11b6a3ff +SHA512 (NetBSD-6.0/evbmips-mipseb/binary/sets/kern-DBAU1500.tgz) = 6ed5b668ff52a75aeadbf11b1096822b97f01af47d8b6b171343feab7e10258cc02b04e151f37995bc85cf6a7c562c4404181c8484a3aa3d593ba9a2c934cd04 +RMD160 (NetBSD-6.0/evbmips-mipseb/binary/sets/kern-DBAU1500.tgz) = 3f5750e9b576ed3e05624052d5f69103eb32c61d +MD5 (NetBSD-6.0/evbmips-mipseb/binary/sets/kern-DBAU1500.tgz) = a4513305f6d3e69cc52c47047d89de2a +SHA1 (NetBSD-6.0/evbmips-mipseb/binary/sets/kern-DB120.tgz) = 2f08fca9d13f265f4d560740a55bebf8b115dc37 +SHA512 (NetBSD-6.0/evbmips-mipseb/binary/sets/kern-DB120.tgz) = a4a2c6e1711da7562520ee189131e499aa65ec114f713cccd7ccb94f55d9e845a253607ec2219284df1422ba5492a0f24004b8088601dc807aaa2a925e14bcab +RMD160 (NetBSD-6.0/evbmips-mipseb/binary/sets/kern-DB120.tgz) = 018c1be32ee04724b86fa2ea173adbe460f63e50 +MD5 (NetBSD-6.0/evbmips-mipseb/binary/sets/kern-DB120.tgz) = d89deab24227d2179a680db2c9477357 +SHA1 (NetBSD-6.0/evbmips-mipseb/binary/sets/kern-DBAU1550.tgz) = efd95e1f98f8ebc28f7621e5696b7ac148091aa4 +SHA512 (NetBSD-6.0/evbmips-mipseb/binary/sets/kern-DBAU1550.tgz) = c67276ab70bdfef9c8a9b9ace43ae950a686aa630f0bd11fb06c533cc463faf41ad1bb89d5a6f2cd6d4d04914ada697da20ec19924720aeeb4d5d1282393cad6 +RMD160 (NetBSD-6.0/evbmips-mipseb/binary/sets/kern-DBAU1550.tgz) = d91cfd72640e117cf952ea3978af6ad106fbed88 +MD5 (NetBSD-6.0/evbmips-mipseb/binary/sets/kern-DBAU1550.tgz) = 1e914a5acbbc55fdab0a70d059171d99 +SHA1 (NetBSD-6.0/evbmips-mipseb/binary/sets/kern-MALTA.tgz) = a5da116a64f3b9e840cd568391f7f755a1ca3f14 +SHA512 (NetBSD-6.0/evbmips-mipseb/binary/sets/kern-MALTA.tgz) = aef284a501e6b2cd16293a5689c5c798dc6bfdc0879fe2cf212b43a4f9d33e9f7dc863f7020c6eda08c8958e713412e5b531e0af799c4695d327c4b66206030e +RMD160 (NetBSD-6.0/evbmips-mipseb/binary/sets/kern-MALTA.tgz) = ed3afb30019e8ac95a9a7348c9099827de561edc +MD5 (NetBSD-6.0/evbmips-mipseb/binary/sets/kern-MALTA.tgz) = c85bd4c68c3458f9581c45a240f5e1ab +SHA1 (NetBSD-6.0/evbmips-mipseb/binary/sets/kern-RB433UAH.tgz) = 64f38dca64142a0a8426e216cb8edd0884551603 +SHA512 (NetBSD-6.0/evbmips-mipseb/binary/sets/kern-RB433UAH.tgz) = b0904e89e80ee6b16f9a97a36974ac5e8a4a7ca8dda9e5f4b27de218fd824d9515ad446574337139aab25fb290c6a93a177f4ddbae7b7a92c8daf5586c87f727 +RMD160 (NetBSD-6.0/evbmips-mipseb/binary/sets/kern-RB433UAH.tgz) = b5e20de5b71f3f0880f714b49e0c39a54d19736e +MD5 (NetBSD-6.0/evbmips-mipseb/binary/sets/kern-RB433UAH.tgz) = 687ac6220a984373b976c5e73cf23240 +SHA1 (NetBSD-6.0/evbmips-mipseb/binary/sets/modules.tgz) = f46c0e5db2b77d898161bf6e3ebac55b05413047 +SHA512 (NetBSD-6.0/evbmips-mipseb/binary/sets/modules.tgz) = 04dfd0379e10923c47b740c5ceed84f69beecf5a72f581885e5c4dddcf9d241499578e6b7a435a119ef8be74909878620fdb700e6638ae119da59c635883aae7 +RMD160 (NetBSD-6.0/evbmips-mipseb/binary/sets/modules.tgz) = 1b674a6cc66d8c1362d66acc69f99f1e0fd70bd9 +MD5 (NetBSD-6.0/evbmips-mipseb/binary/sets/modules.tgz) = a3500877590cea3b09db38130581d10d +SHA1 (NetBSD-6.0/evbmips-mipseb/binary/sets/tests.tgz) = c0a06d6671f0141559bfc80c076fe6f0b2d87003 +SHA512 (NetBSD-6.0/evbmips-mipseb/binary/sets/tests.tgz) = 114f7f7e299614296fe2b272a172b9c1d77da42dfe09064c6d9fe9a6450322a38a3c1fc403348aa536d2039884899200591b59d653a3a7d89d22ea22b1750b29 +RMD160 (NetBSD-6.0/evbmips-mipseb/binary/sets/tests.tgz) = 4833a7fb848401385159dd129da45d96a9a7b180 +MD5 (NetBSD-6.0/evbmips-mipseb/binary/sets/tests.tgz) = fb54298f8aa3423bcf7bc43b3fea488e +SHA1 (NetBSD-6.0/evbmips-mipseb/binary/sets/text.tgz) = 91921b0be07535e75e97288e49ee2bc0b3c9949b +SHA512 (NetBSD-6.0/evbmips-mipseb/binary/sets/text.tgz) = 336ae450c79b99cf2f2c64a9b378125904c2b7f2d2b6de8eb0f8cd5a2b735cc7a55fe69b599daed3e3e8ef9c51bc6044d994e6dcda85adba659204b92724b814 +RMD160 (NetBSD-6.0/evbmips-mipseb/binary/sets/text.tgz) = 3e1e8f989f25749485c0ce9471dedc141cb73726 +MD5 (NetBSD-6.0/evbmips-mipseb/binary/sets/text.tgz) = ff542bf96a0884faa5df5e30d2ac2ff5 +SHA1 (NetBSD-6.0/evbmips-mipseb/binary/sets/xbase.tgz) = 6c4272f0ef26a4f32eb393bb479f62b2b7142bc5 +SHA512 (NetBSD-6.0/evbmips-mipseb/binary/sets/xbase.tgz) = 568a69f2077f011b98792eb1f71a8b7bf11251f42ca8a082559fd3d836a6afcb7eb05e77331b1cd8b996731c4fddd4ddc8abc6b82cc3c4d9460827e52dde424b +RMD160 (NetBSD-6.0/evbmips-mipseb/binary/sets/xbase.tgz) = 4bcb45e19d2da3ccb065977c5cbdf640144afb8f +MD5 (NetBSD-6.0/evbmips-mipseb/binary/sets/xbase.tgz) = f7cc64d9cdf50d1c85923eb835bc6dcd +SHA1 (NetBSD-6.0/evbmips-mipseb/binary/sets/xetc.tgz) = 19444f8d1799d782bc72d2684588b1479ee5976b +SHA512 (NetBSD-6.0/evbmips-mipseb/binary/sets/xetc.tgz) = 0075efc99fa5c63bfce8806d5bc083e3e68bb6e9dc885b382353dff0bf55b85a27608318deeeb504833cc5abcedd5bacb45b943bc3beba42e202d08ed368962d +RMD160 (NetBSD-6.0/evbmips-mipseb/binary/sets/xetc.tgz) = 32b296247a2f343a49473e7d54987c6d87229a38 +MD5 (NetBSD-6.0/evbmips-mipseb/binary/sets/xetc.tgz) = 7d63fd2d8fdbb123792d61e4fa3ece2f +SHA1 (NetBSD-6.0/evbmips-mipseb/binary/sets/xserver.tgz) = 2f38506d78bb7be30d5cd8719f3c137dc28b7f92 +SHA512 (NetBSD-6.0/evbmips-mipseb/binary/sets/xserver.tgz) = 3364dfa7db892eb0c1c92ff50c1e321687300a2cb572da25e55ff501d958201fc3f2d916681778de0879ea20cb31ccf30766038863e0b97e4ca52365b5dcbf51 +RMD160 (NetBSD-6.0/evbmips-mipseb/binary/sets/xserver.tgz) = 9a26ea480f7ff2ce07a648e0004dcabcadb8432e +MD5 (NetBSD-6.0/evbmips-mipseb/binary/sets/xserver.tgz) = 00b808e0f27ff7924b22f2c74b1f7121 +SHA1 (NetBSD-6.0/evbmips-mipseb/installation/netbsd-INSTALL_MALTA.srec.gz) = a05b722b902910be1bda3a582d3ebc850048ced1 +SHA512 (NetBSD-6.0/evbmips-mipseb/installation/netbsd-INSTALL_MALTA.srec.gz) = fcde1c3163e2973f213350595dd38d202524e4f125f14ff48b68f9d569f10788c8796123e051ae72e64b786452f60ac7079ae59390333b63252a8991ee1a1786 +RMD160 (NetBSD-6.0/evbmips-mipseb/installation/netbsd-INSTALL_MALTA.srec.gz) = 2d4a3c604fec21934e0bf2c4e987c8978aa8bce3 +MD5 (NetBSD-6.0/evbmips-mipseb/installation/netbsd-INSTALL_MALTA.srec.gz) = ecd58d8ad5bf459ed7022e72580b9942 +SHA1 (NetBSD-6.0/evbmips-mipseb/installation/netbsd-INSTALL_MALTA.gz) = fde4c37b9543ae150854af55c5c34243e1316c05 +SHA512 (NetBSD-6.0/evbmips-mipseb/installation/netbsd-INSTALL_MALTA.gz) = b72c9f6516e3ff03e64c6598e153893d6beb5c64997488571bf3aa4547f2f251b78721fb4a23892470c8b352b0ba3a6c95f2e0c8e450918533ed1b9cbebf90ef +RMD160 (NetBSD-6.0/evbmips-mipseb/installation/netbsd-INSTALL_MALTA.gz) = c37277dcb3eff20bf03c9319d4a6766d1f869225 +MD5 (NetBSD-6.0/evbmips-mipseb/installation/netbsd-INSTALL_MALTA.gz) = d6f55d866675b4e51178d7c7daeb7b6c +SHA1 (NetBSD-6.0/evbmips-mipseb/installation/netbsd-INSTALL_MALTA.symbols.gz) = baff18cdf467ce42a54eb77e9774c524c9ba347d +SHA512 (NetBSD-6.0/evbmips-mipseb/installation/netbsd-INSTALL_MALTA.symbols.gz) = 530df115006eef8bf3f3ea78c1bc1b8a37e90dc460fc8c3cfbeb70422bcb0a9ef52fd116b5b9ae3a9eec83fe60cd3a32fa0933ac0589e2c68c831978e7e988b7 +RMD160 (NetBSD-6.0/evbmips-mipseb/installation/netbsd-INSTALL_MALTA.symbols.gz) = e4ed20740fecd9b75d635d99567d3b67f5ae5cf6 +MD5 (NetBSD-6.0/evbmips-mipseb/installation/netbsd-INSTALL_MALTA.symbols.gz) = 6c54f00839d4980e95252520ce7a3814 +SHA1 (NetBSD-6.0/evbmips-mipsel/binary/kernel/netbsd-aumac0-ALCHEMY.gz) = 134fb77bafabb2f5cdc53713cedd145c6695b5c2 +SHA512 (NetBSD-6.0/evbmips-mipsel/binary/kernel/netbsd-aumac0-ALCHEMY.gz) = f21c2b6185b6ddfcca9f1873239ca3855165898d537f4ceb6fec7818ae157ac95b143f559c77be261d4fa3c427e0579d5ecdcdd6047944d0faa94681b8375c16 +RMD160 (NetBSD-6.0/evbmips-mipsel/binary/kernel/netbsd-aumac0-ALCHEMY.gz) = 003133387cb76ab3a8afcb59683cd6d117e4dd0a +MD5 (NetBSD-6.0/evbmips-mipsel/binary/kernel/netbsd-aumac0-ALCHEMY.gz) = c99637f4bab91983011482c5cd8f84e7 +SHA1 (NetBSD-6.0/evbmips-mipsel/binary/kernel/netbsd-ALCHEMY.gz) = 87f20bbd047d0c7b793c4ad98ecb01128565e2c6 +SHA512 (NetBSD-6.0/evbmips-mipsel/binary/kernel/netbsd-ALCHEMY.gz) = 25a0f40f69c8fa908265a4e757cb64c074f47442b3f9e4d6051e7024042d2685b4e01bf3b0081d603bd633523b8f28c3570b93f5886a4021986b03131175854c +RMD160 (NetBSD-6.0/evbmips-mipsel/binary/kernel/netbsd-ALCHEMY.gz) = 4f0ded0dec635ab37d6e43e5198a3eebb9d5432f +MD5 (NetBSD-6.0/evbmips-mipsel/binary/kernel/netbsd-ALCHEMY.gz) = 886795f8573d66ada3b5bf8f8443cbc4 +SHA1 (NetBSD-6.0/evbmips-mipsel/binary/kernel/netbsd-CPMBR1400.gz) = f90b68d7d1fb37b69896657f4060f0dc1c196951 +SHA512 (NetBSD-6.0/evbmips-mipsel/binary/kernel/netbsd-CPMBR1400.gz) = a639799a0431ab22cc468f7168358416ff6095a6015cfd783406b24a6e62f1dc38a978c2c4875cef999654c3f0fa2f8cdadaed5d0283fa05bc56db9ff89d4c68 +RMD160 (NetBSD-6.0/evbmips-mipsel/binary/kernel/netbsd-CPMBR1400.gz) = 5265e5e99e360048b07d997d3bf0f73b806f905c +MD5 (NetBSD-6.0/evbmips-mipsel/binary/kernel/netbsd-CPMBR1400.gz) = 5447c227f2147295b74c3cd9a62efa60 +SHA1 (NetBSD-6.0/evbmips-mipsel/binary/kernel/netbsd-DBAU1500.gz) = c298c37feb22bee4f641ede6c29b82f55a15fb43 +SHA512 (NetBSD-6.0/evbmips-mipsel/binary/kernel/netbsd-DBAU1500.gz) = 9ac3727e8f9777042fe7aab1613e910da72d07fd5b8277349f2b538f620f6ac34cfe5972fa72a91275cf99ce0e98e062bd559b169eab6cf9700d0065262d2d98 +RMD160 (NetBSD-6.0/evbmips-mipsel/binary/kernel/netbsd-DBAU1500.gz) = 45fbbb985b1bd77331e018f10df8d95d17c12af1 +MD5 (NetBSD-6.0/evbmips-mipsel/binary/kernel/netbsd-DBAU1500.gz) = 3391b8ea4799c856e260069f7a4a0761 +SHA1 (NetBSD-6.0/evbmips-mipsel/binary/kernel/netbsd-DBAU1550.gz) = 2a32d5bda59467bf957d1dba8f4c716c553436bc +SHA512 (NetBSD-6.0/evbmips-mipsel/binary/kernel/netbsd-DBAU1550.gz) = f5b499dd62317cda4483cc70f65e56d7a8a6be0095dfa1a3836158b6615066237ecc13b3ca66a11545a47a938ec2f2c54c27c8613d16f931ba0b3a8bdbabd2dd +RMD160 (NetBSD-6.0/evbmips-mipsel/binary/kernel/netbsd-DBAU1550.gz) = 52319f5ea1ba91f0e3d762df4580873ae8015f3f +MD5 (NetBSD-6.0/evbmips-mipsel/binary/kernel/netbsd-DBAU1550.gz) = e55c5185cd7d35ddf3a8aaca93be4598 +SHA1 (NetBSD-6.0/evbmips-mipsel/binary/kernel/netbsd-GDIUM.gz) = cd1ba889150b543a42b1abc72bed2da50a4705ee +SHA512 (NetBSD-6.0/evbmips-mipsel/binary/kernel/netbsd-GDIUM.gz) = ba267fc4d44531b95167b3321c4b6f2885902a8a19332c647ea325ba2ab37e7d48a1753d2ebe3991dde1ea286455b1062e56242b0d7804b9db51bd906fc6fa46 +RMD160 (NetBSD-6.0/evbmips-mipsel/binary/kernel/netbsd-GDIUM.gz) = c4fc7d36e9e1b9d22f04c85db96894267551ce4a +MD5 (NetBSD-6.0/evbmips-mipsel/binary/kernel/netbsd-GDIUM.gz) = 53fbc4ff1eabc437ff5546fa12df92df +SHA1 (NetBSD-6.0/evbmips-mipsel/binary/kernel/netbsd-MALTA.gz) = 18cb97fb9b5fa551a4230460d66174bec28a7017 +SHA512 (NetBSD-6.0/evbmips-mipsel/binary/kernel/netbsd-MALTA.gz) = 5887e65233675d5584c5f8b9d14ab70b0368ad9c9d6e085470f63f3a37a82d5adfab7306866fa55303cb73668ab8b836082609da77eb5ebb5fb7b05fcf36ad03 +RMD160 (NetBSD-6.0/evbmips-mipsel/binary/kernel/netbsd-MALTA.gz) = 326fb5286d584548044d264ce8650cf9b13e3901 +MD5 (NetBSD-6.0/evbmips-mipsel/binary/kernel/netbsd-MALTA.gz) = 06f4d46d9d802dac0954390934246fa3 +SHA1 (NetBSD-6.0/evbmips-mipsel/binary/kernel/netbsd-MTX-1.gz) = 95b45facdc9fa0b69709e7e5505e3849eb3c318d +SHA512 (NetBSD-6.0/evbmips-mipsel/binary/kernel/netbsd-MTX-1.gz) = abf3ee530bf7a515fb2f4d93ff50d5ead425232171eaf33ecd9fdc56fb0ee37e976aa918fb3a153b0c8d8b7b51cf288bca1acf7a9a61402d149818e83ff70296 +RMD160 (NetBSD-6.0/evbmips-mipsel/binary/kernel/netbsd-MTX-1.gz) = eeb4eac3e382e41631e8f3f8806e2c3f10355a4e +MD5 (NetBSD-6.0/evbmips-mipsel/binary/kernel/netbsd-MTX-1.gz) = 36da2e3383b17e5bf06844c414dc239a +SHA1 (NetBSD-6.0/evbmips-mipsel/binary/kernel/netbsd-OMSAL400.gz) = 44841ceb6f1af159ff6056ef89884da1f3c7cb3a +SHA512 (NetBSD-6.0/evbmips-mipsel/binary/kernel/netbsd-OMSAL400.gz) = 7ed282421374238ff02c9ca3e413165be0d0b16e1011cdab9d4af9f9b3b868b05d5832a8f24ea396222035ebf46ea3b02b2eb49cf378f93f26d807192a5b6458 +RMD160 (NetBSD-6.0/evbmips-mipsel/binary/kernel/netbsd-OMSAL400.gz) = 7b039a86fd581c56153a113366efd278414f9921 +MD5 (NetBSD-6.0/evbmips-mipsel/binary/kernel/netbsd-OMSAL400.gz) = a8bcd078458637f91753faae2c99c8ac +SHA1 (NetBSD-6.0/evbmips-mipsel/binary/kernel/netbsd-P4032.gz) = e14fd9558a2cf7405398aec0f3df97f846ccbbdd +SHA512 (NetBSD-6.0/evbmips-mipsel/binary/kernel/netbsd-P4032.gz) = 4640b39a386e0223ff255ddb9796820a249e34e25eb2f550cae3ca36d2a3af7eeb2f0133d084323b964b8aa3db93db462db2bd3debdd78388e71eedcce37a48d +RMD160 (NetBSD-6.0/evbmips-mipsel/binary/kernel/netbsd-P4032.gz) = 845c8595b29846b3ad87272048e0d5ea18413c2a +MD5 (NetBSD-6.0/evbmips-mipsel/binary/kernel/netbsd-P4032.gz) = c2e071d630599cb393bc13e4db60a187 +SHA1 (NetBSD-6.0/evbmips-mipsel/binary/kernel/netbsd-P5064.gz) = 11fecb91f2c90740271dcc51a7fe5f78cfd35281 +SHA512 (NetBSD-6.0/evbmips-mipsel/binary/kernel/netbsd-P5064.gz) = 076c38f8684254a744cb14d592b5f0404d5a7944cbd486b2b6da4c4a1057057029f5f1949f007ad5255d97466ca5ea1b5af047566823526b7e7804280b0206f9 +RMD160 (NetBSD-6.0/evbmips-mipsel/binary/kernel/netbsd-P5064.gz) = c2e78b4d2da205e8af4b8bffe97e71b78649917c +MD5 (NetBSD-6.0/evbmips-mipsel/binary/kernel/netbsd-P5064.gz) = ae9f3bd2236f924b501fc6d0ae0b42c0 +SHA1 (NetBSD-6.0/evbmips-mipsel/binary/kernel/netbsd-P6032.gz) = cd8af99e05c16d79b574f176d0229bc363c3f094 +SHA512 (NetBSD-6.0/evbmips-mipsel/binary/kernel/netbsd-P6032.gz) = f1375dd13b2950afed3a0b3c9217a0630da47ce52fe467140217a2b29706e68354018d2e5c4b0ab7b16a9af119a66b6430cdca1298275dfd1d9b22eb65cd9ea3 +RMD160 (NetBSD-6.0/evbmips-mipsel/binary/kernel/netbsd-P6032.gz) = 0af7124d320813134c90c509027396730e0bb758 +MD5 (NetBSD-6.0/evbmips-mipsel/binary/kernel/netbsd-P6032.gz) = 277e59364f2ed7160337ec3d20060a9b +SHA1 (NetBSD-6.0/evbmips-mipsel/binary/kernel/netbsd-reth0-CPMBR1400.gz) = 55565c142f55fac5076d21a61b0a5ac8cad002ee +SHA512 (NetBSD-6.0/evbmips-mipsel/binary/kernel/netbsd-reth0-CPMBR1400.gz) = 8db0765cc0d2affa6cf5490d766f577f202c89d6694fb8e57f81c076257242ad47439fa9e3d46c738d2e1dc1bc306f951fff54211f48c4bcf3c27ce672db67bd +RMD160 (NetBSD-6.0/evbmips-mipsel/binary/kernel/netbsd-reth0-CPMBR1400.gz) = 015a00aebbe3f9ff27bbc38e50863794829c34a5 +MD5 (NetBSD-6.0/evbmips-mipsel/binary/kernel/netbsd-reth0-CPMBR1400.gz) = 994571e2665c04bfc5ed50709b09d74e +SHA1 (NetBSD-6.0/evbmips-mipsel/binary/kernel/netbsd-sd0a-CPMBR1400.gz) = 7c23499487a89cd84aa8b4a429b097e8ace4c0bb +SHA512 (NetBSD-6.0/evbmips-mipsel/binary/kernel/netbsd-sd0a-CPMBR1400.gz) = 1a517e528904e379b39f740f0335c93de12e1b9398fa0564ebfd702fa064b75dab85bcbbd44f2f5baca767dcc61cd79bc7415648ed346e2e4d15ff3c2c278bb8 +RMD160 (NetBSD-6.0/evbmips-mipsel/binary/kernel/netbsd-sd0a-CPMBR1400.gz) = 95ca7bbed50714a1aa9694362565c4219305a9a8 +MD5 (NetBSD-6.0/evbmips-mipsel/binary/kernel/netbsd-sd0a-CPMBR1400.gz) = df9de39483767ed081aeb4bfe5d87f23 +SHA1 (NetBSD-6.0/evbmips-mipsel/binary/sets/games.tgz) = 27d9f98fecb3495e51939df9f107e81e527af26f +SHA512 (NetBSD-6.0/evbmips-mipsel/binary/sets/games.tgz) = 46bb4e10313cfffaaf4f7fa2157474ef940f94bcc9f84b46f829c7615bbf45e4e01edee7b7efb84bc28561e0712c37cfc737f9c2a0d9a73b67c80c8aa0f3a9af +RMD160 (NetBSD-6.0/evbmips-mipsel/binary/sets/games.tgz) = 947feea90ec2698a65d555cb78a29a001b086589 +MD5 (NetBSD-6.0/evbmips-mipsel/binary/sets/games.tgz) = 355f00978fed8e8da6a251e591be5387 +SHA1 (NetBSD-6.0/evbmips-mipsel/binary/sets/man.tgz) = 899b9d8242e983a5110ab755651c24f709b5af67 +SHA512 (NetBSD-6.0/evbmips-mipsel/binary/sets/man.tgz) = 410999db110d710f4bb498c3d7ae7adc62170c7c2f470ce189c92f6c436c5ea96149659c631ef0b5605caaa025d97dfe1c07c428d86f51239657bd6b71717b15 +RMD160 (NetBSD-6.0/evbmips-mipsel/binary/sets/man.tgz) = c1270f68c6d41b351877f71f0396ac34877dfc8d +MD5 (NetBSD-6.0/evbmips-mipsel/binary/sets/man.tgz) = df4db2bbfa39ef6a4a215d949653d04a +SHA1 (NetBSD-6.0/evbmips-mipsel/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/evbmips-mipsel/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/evbmips-mipsel/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/evbmips-mipsel/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/evbmips-mipsel/binary/sets/xcomp.tgz) = d8ac89f3f6ff20abb0adabc49227afdb74aa2040 +SHA512 (NetBSD-6.0/evbmips-mipsel/binary/sets/xcomp.tgz) = 4f03213fb061dae9421747209628d06ede6bbb71a7560a9e1a54796b907f1620146a33fdce52974227a21acedcc210b99e15c4fdd36432eba60c1041a92d8cee +RMD160 (NetBSD-6.0/evbmips-mipsel/binary/sets/xcomp.tgz) = 6be5e72b9b57c9bdf8ed8ea127e2a73830feeecb +MD5 (NetBSD-6.0/evbmips-mipsel/binary/sets/xcomp.tgz) = 59a7ea141587417be38ab1f6056cc780 +SHA1 (NetBSD-6.0/evbmips-mipsel/binary/sets/xetc.tgz) = b9f6b1a54ffab37b11f4c6e717b481cd087fb609 +SHA512 (NetBSD-6.0/evbmips-mipsel/binary/sets/xetc.tgz) = 72f35e65f3a90967e250a2006d500619b3824f7f5c3d7494554f153ec5cda5b28c445f28c34a1e4463f40da5855e8d4257726411796967fe37763d90cf7fe461 +RMD160 (NetBSD-6.0/evbmips-mipsel/binary/sets/xetc.tgz) = 1169c246f91189fd0c4ae86ac27a92f5c2edda3e +MD5 (NetBSD-6.0/evbmips-mipsel/binary/sets/xetc.tgz) = 8f3c52cc5af1cafaf7b0d0f884a5b537 +SHA1 (NetBSD-6.0/evbmips-mipsel/binary/sets/xfont.tgz) = d06848571034f3b7fc975082f1de37b912acb18c +SHA512 (NetBSD-6.0/evbmips-mipsel/binary/sets/xfont.tgz) = 66a1013c935bee5e7e5d24325a527522306bcded7ced63790f2e58831b3ed91176a1b9510b2159be63504d5167d48d534919927ffc6e225ae2bb2487f90a9ede +RMD160 (NetBSD-6.0/evbmips-mipsel/binary/sets/xfont.tgz) = c9502843a5d4dd7e996e8d158c519cf7f8575cbd +MD5 (NetBSD-6.0/evbmips-mipsel/binary/sets/xfont.tgz) = e812899176eac2bf65a6d949ac3f3424 +SHA1 (NetBSD-6.0/evbmips-mipsel/binary/sets/kern-ALCHEMY.tgz) = 5835e5112e44bae1346420ffc0f3e09a2e4f6117 +SHA512 (NetBSD-6.0/evbmips-mipsel/binary/sets/kern-ALCHEMY.tgz) = c3b2ad6f9678403cb3a6e0b8dbd05b6717aceac5472eac0c2bad86dbeb30b509f7a8b865daa499279bd524a10b075da08f6fa9736994cdc4633b0f67b0ac22b6 +RMD160 (NetBSD-6.0/evbmips-mipsel/binary/sets/kern-ALCHEMY.tgz) = 3b7c2006143846db5c3eab27c2f881dc22ef5e05 +MD5 (NetBSD-6.0/evbmips-mipsel/binary/sets/kern-ALCHEMY.tgz) = da923fa9431ec9e4349f58d50bea5adc +SHA1 (NetBSD-6.0/evbmips-mipsel/binary/sets/base.tgz) = f0e2ba7bc4f19f19c71a28de51c4359ac56a6a44 +SHA512 (NetBSD-6.0/evbmips-mipsel/binary/sets/base.tgz) = fbf1b00664f9a8530afad453e1af05ff39741d87187d25e3e5242c06fa013e6f6027d40944ef82fbc12c0ced24e90824a135bdff8ecfd69b04f2ffd03aa8d065 +RMD160 (NetBSD-6.0/evbmips-mipsel/binary/sets/base.tgz) = 581b658d659de51923f79c189fb4dc75201aff64 +MD5 (NetBSD-6.0/evbmips-mipsel/binary/sets/base.tgz) = 185928a3ba27f23a06356b0b0df0ff4a +SHA1 (NetBSD-6.0/evbmips-mipsel/binary/sets/comp.tgz) = 66f0609c617456757b6563e94e2feaa2f788d2df +SHA512 (NetBSD-6.0/evbmips-mipsel/binary/sets/comp.tgz) = 83bc3d7127bbf0bb9d86f015d4cded042e1c0cdb75efdab00fd7941a7d96e8b54893b54a36b489d221dcbc17348473ba73287708f031b2ef37e0288074201400 +RMD160 (NetBSD-6.0/evbmips-mipsel/binary/sets/comp.tgz) = d8d32c55c767525effee5ea75186373d6c253873 +MD5 (NetBSD-6.0/evbmips-mipsel/binary/sets/comp.tgz) = e56af26f877a19649c558c9d3ced6e6c +SHA1 (NetBSD-6.0/evbmips-mipsel/binary/sets/etc.tgz) = df85d74c9f2767c9be3de45d693f13547ff9e3da +SHA512 (NetBSD-6.0/evbmips-mipsel/binary/sets/etc.tgz) = e06ac6ef086e5951de773f02fe83c16ca1804611dda15b1dfcc0a44e81c3e6e6acf06b94480b0f643ef63e1a90c8eea81b2af4302e82801c033705418201e66a +RMD160 (NetBSD-6.0/evbmips-mipsel/binary/sets/etc.tgz) = 16cb173c32cd73373937f89eab796e5bc987ec96 +MD5 (NetBSD-6.0/evbmips-mipsel/binary/sets/etc.tgz) = 81f8caccfb4f464cf105f293393f6c78 +SHA1 (NetBSD-6.0/evbmips-mipsel/binary/sets/kern-CPMBR1400.tgz) = 1da339adf6e178fd648cf87cc4d2b5e1ad0bcc2a +SHA512 (NetBSD-6.0/evbmips-mipsel/binary/sets/kern-CPMBR1400.tgz) = eb2c935de15c5622d5752c949b86965ec587b5c36c5f51ae2b801a9e20482772d1d728563aa70b299ec0316bc71f7754a0c4fb2e9795c01effcafa9123bf2029 +RMD160 (NetBSD-6.0/evbmips-mipsel/binary/sets/kern-CPMBR1400.tgz) = 3dd811b1a249023ffa47e31969f4086b9e156a15 +MD5 (NetBSD-6.0/evbmips-mipsel/binary/sets/kern-CPMBR1400.tgz) = bd1349e129ae6367bf0e3532935c2317 +SHA1 (NetBSD-6.0/evbmips-mipsel/binary/sets/kern-DBAU1500.tgz) = 3f3199d94860f1a97269132ec110acb983133723 +SHA512 (NetBSD-6.0/evbmips-mipsel/binary/sets/kern-DBAU1500.tgz) = 1a1ed387d0902cad78598dba5c0a088e231594d16b4f49ac73c082f5c05f972b1a8e5ab5f28b97b23d696297cc9f334f1c8bff2daeb8a386aebf1930e3587007 +RMD160 (NetBSD-6.0/evbmips-mipsel/binary/sets/kern-DBAU1500.tgz) = d7f81fc610d0f09a26d14a082c9a143283d8594f +MD5 (NetBSD-6.0/evbmips-mipsel/binary/sets/kern-DBAU1500.tgz) = 54e6afe80b72e44b94d994d2465d63f1 +SHA1 (NetBSD-6.0/evbmips-mipsel/binary/sets/kern-DBAU1550.tgz) = 22c9cf65d89b9042f2b47316b99368dc0cad4d45 +SHA512 (NetBSD-6.0/evbmips-mipsel/binary/sets/kern-DBAU1550.tgz) = 3d2e737026c76a192d4461234be70622682563a14584ba8da5272be018a711dd108fc71f93d8251f8851246f8998c768f4a2f6e81b7985482dccf1fc166b5138 +RMD160 (NetBSD-6.0/evbmips-mipsel/binary/sets/kern-DBAU1550.tgz) = bde90234bc61e0105d5b7d1b23c23cae81461f84 +MD5 (NetBSD-6.0/evbmips-mipsel/binary/sets/kern-DBAU1550.tgz) = 2905ebd9467c3a2ca17f776044ac9b80 +SHA1 (NetBSD-6.0/evbmips-mipsel/binary/sets/kern-GDIUM.tgz) = d7085296fbaf3357d9b3bdfc107c0632b7855d24 +SHA512 (NetBSD-6.0/evbmips-mipsel/binary/sets/kern-GDIUM.tgz) = 8841e72b1c725be15c37489f42254fc84feecfc2bc90050a4360ffc248ec14dce16dfe41ed8950f198c6a13fe78f287ed53d5545a9c0de775161de52994c1c21 +RMD160 (NetBSD-6.0/evbmips-mipsel/binary/sets/kern-GDIUM.tgz) = 49552df226923fde73b20818fcc3b88859095252 +MD5 (NetBSD-6.0/evbmips-mipsel/binary/sets/kern-GDIUM.tgz) = e24f2b056cbf42955f24fc45075f2836 +SHA1 (NetBSD-6.0/evbmips-mipsel/binary/sets/kern-MALTA.tgz) = bbd9390fc5aee7d91c0fe0651503360f32fa6498 +SHA512 (NetBSD-6.0/evbmips-mipsel/binary/sets/kern-MALTA.tgz) = c09a032170d82e55a1c32fc468e6656509c99e9ee2a661255ed92d663c0605e1836afa2a098b40cbb9f6ca16854973733f6aacafafd129ca752c3ef569434f76 +RMD160 (NetBSD-6.0/evbmips-mipsel/binary/sets/kern-MALTA.tgz) = ff39a003e6a67114cbf0cac19c38f958cd07cc14 +MD5 (NetBSD-6.0/evbmips-mipsel/binary/sets/kern-MALTA.tgz) = f9b7bf0cc95c4da411d9342dd2ebe8b8 +SHA1 (NetBSD-6.0/evbmips-mipsel/binary/sets/kern-MTX-1.tgz) = 5d4fb7abbffb58499873b02451e2d87e3818cd3f +SHA512 (NetBSD-6.0/evbmips-mipsel/binary/sets/kern-MTX-1.tgz) = 2801b511740ce3310fb21ed8d1d1bba46ec2565721bbea394e1e1683c05984a88b2346b6949e90dcc737929e2919fb752661582984b27ea4c726ca6c70fdcff7 +RMD160 (NetBSD-6.0/evbmips-mipsel/binary/sets/kern-MTX-1.tgz) = 5b55476b98c8b0610bb7b03b15a457640b03df95 +MD5 (NetBSD-6.0/evbmips-mipsel/binary/sets/kern-MTX-1.tgz) = f185c47ceea774af477cdc675e5da827 +SHA1 (NetBSD-6.0/evbmips-mipsel/binary/sets/kern-OMSAL400.tgz) = 854aac9898f3c0552fb0b4491d45dae21dc084b3 +SHA512 (NetBSD-6.0/evbmips-mipsel/binary/sets/kern-OMSAL400.tgz) = eb6aa82deeb2fa15ea59198d3ba10275eb73b85a902af353442138df9b66307ac2a595a61824301e56bdcf3fddea03414fd7c312564d039fb8d75fd9159cde58 +RMD160 (NetBSD-6.0/evbmips-mipsel/binary/sets/kern-OMSAL400.tgz) = 0fc4d0bf3a667e4fae2f60a504a4032751a5bb84 +MD5 (NetBSD-6.0/evbmips-mipsel/binary/sets/kern-OMSAL400.tgz) = 53a48a5e4731a1160347ad6c655ccf5b +SHA1 (NetBSD-6.0/evbmips-mipsel/binary/sets/kern-P4032.tgz) = 9e8cb0ee684033f08ba0b4bda5a4eb16eac71fb6 +SHA512 (NetBSD-6.0/evbmips-mipsel/binary/sets/kern-P4032.tgz) = 100f84c1ca2763695d90d8b65822c0ce4156c5c51236be33e395dcb7e68c806f979f7afc50c3c76457c82f225df32c44b7cf42c9c8a183469ead0b512a5880f2 +RMD160 (NetBSD-6.0/evbmips-mipsel/binary/sets/kern-P4032.tgz) = bdda2cb2f34b84c0d46a8dfb7ef72bb6f3562018 +MD5 (NetBSD-6.0/evbmips-mipsel/binary/sets/kern-P4032.tgz) = 36f64c61f21f88c7d6067d2e9b1476ab +SHA1 (NetBSD-6.0/evbmips-mipsel/binary/sets/kern-P5064.tgz) = 8d6f635c7b19fe4b4ae3f81b8e55782ff929a275 +SHA512 (NetBSD-6.0/evbmips-mipsel/binary/sets/kern-P5064.tgz) = 4382b4df12950d3ee601efd85e13a0b3aa4e41ec9ab7f1bb5024d1b198ee8c588592c2b50099354f1164aedb585ffd7e9dd123516f32f1f30c32cf78e77fc70f +RMD160 (NetBSD-6.0/evbmips-mipsel/binary/sets/kern-P5064.tgz) = b0bccd6abe423b957c452d1d42f40796f42533d4 +MD5 (NetBSD-6.0/evbmips-mipsel/binary/sets/kern-P5064.tgz) = b9659cc8f1fba16994a78e42ba17d9ed +SHA1 (NetBSD-6.0/evbmips-mipsel/binary/sets/kern-P6032.tgz) = 86427980342dd947c57c838152ae64d15cff5142 +SHA512 (NetBSD-6.0/evbmips-mipsel/binary/sets/kern-P6032.tgz) = c86734213f246621075f8b35f51997d4abfc722502a4b8a3006d8224b1808871fb9103e539ab7ebf730dbb94377c3f75cd1596a3f7d3fda2505cca879c4608b8 +RMD160 (NetBSD-6.0/evbmips-mipsel/binary/sets/kern-P6032.tgz) = 75aa0da6324608e7055e923ba1004f5427c88770 +MD5 (NetBSD-6.0/evbmips-mipsel/binary/sets/kern-P6032.tgz) = abcfe72de3e084c79528616c061d70ad +SHA1 (NetBSD-6.0/evbmips-mipsel/binary/sets/modules.tgz) = 66831501dc768e732c9b93cd102bd84f078ea1a6 +SHA512 (NetBSD-6.0/evbmips-mipsel/binary/sets/modules.tgz) = 6b50ee54d67e9f57f125ac1eb0f1cf849f566a2ca4055032f708d8bda121b8ba96274c5fca21deec4753a3bbd64e18ffa66fc0548b363f95b5c0d0d4f2690dcd +RMD160 (NetBSD-6.0/evbmips-mipsel/binary/sets/modules.tgz) = 1db5ef74be63618d39d44716face7ca5cbafb86f +MD5 (NetBSD-6.0/evbmips-mipsel/binary/sets/modules.tgz) = 47d708c50d3fbb3f170883f337a84a3c +SHA1 (NetBSD-6.0/evbmips-mipsel/binary/sets/tests.tgz) = b87c52edef5dae8c13e4982f742d107c6bde617a +SHA512 (NetBSD-6.0/evbmips-mipsel/binary/sets/tests.tgz) = a227c03925059ca58390063e75c934e9bebda7f2944478302ffca4f53a48bf991314c4bf837c4e833aa700424e154cc62526f76c53f23ac7281457606e975c20 +RMD160 (NetBSD-6.0/evbmips-mipsel/binary/sets/tests.tgz) = ea25f7257b61f3530435a9dc66123831d59e6c43 +MD5 (NetBSD-6.0/evbmips-mipsel/binary/sets/tests.tgz) = 42da5bef4121a88ef7ba8e89bbd065d6 +SHA1 (NetBSD-6.0/evbmips-mipsel/binary/sets/text.tgz) = 38e7f089801576d8a7370546c8f6dfee8938c54d +SHA512 (NetBSD-6.0/evbmips-mipsel/binary/sets/text.tgz) = 4694ab32a63c7a00b2da8921e278d14ac83dd114beec338716a98cfbdbe7c06ed07abe0d6a10b317b50a9deeff4f4049c487458bfa9cef043b92905e9f4828e7 +RMD160 (NetBSD-6.0/evbmips-mipsel/binary/sets/text.tgz) = 6b4ed0dc8220b79963b2cbabfcbe1ae449cb4509 +MD5 (NetBSD-6.0/evbmips-mipsel/binary/sets/text.tgz) = bfbab9eee77986403da3513d836616bf +SHA1 (NetBSD-6.0/evbmips-mipsel/binary/sets/xbase.tgz) = 71f5a25bb86649bdbeab0146bb32c76329afa9c6 +SHA512 (NetBSD-6.0/evbmips-mipsel/binary/sets/xbase.tgz) = 70afd5fdc176eda270259b113d7f28cc92fe2037d7bc84cc69a2bb32ea05b23bf26c10f834fa9d59be9900a2ef780b55e5e181d6b1a88ff51ccf35488d28fa22 +RMD160 (NetBSD-6.0/evbmips-mipsel/binary/sets/xbase.tgz) = 95a5dcc67edbe81dccf5f90e0125e84a6f267cfe +MD5 (NetBSD-6.0/evbmips-mipsel/binary/sets/xbase.tgz) = b0a603b80fceb0f5f0c02786d87542cc +SHA1 (NetBSD-6.0/evbmips-mipsel/binary/sets/xserver.tgz) = 9be61698fe883646972e3441d1ea02e16fa351d2 +SHA512 (NetBSD-6.0/evbmips-mipsel/binary/sets/xserver.tgz) = 17d9d25171859208b00a7e64dc74eeaf4a2533cb86d7be138227aa731a09654c007bc4245817177dc2308d693c1792ad247bc0692de79e3b0dd8e5d2257c7246 +RMD160 (NetBSD-6.0/evbmips-mipsel/binary/sets/xserver.tgz) = 168f6c36213258b1f7f3019bc47434a58cf68a54 +MD5 (NetBSD-6.0/evbmips-mipsel/binary/sets/xserver.tgz) = fdf224dd21749c1a2eb06f6ebde96338 +SHA1 (NetBSD-6.0/evbmips-mipsel/installation/netbsd-INSTALL_MALTA.srec.gz) = 1148ef0c3e4745f529e78b33e048e77a2357b107 +SHA512 (NetBSD-6.0/evbmips-mipsel/installation/netbsd-INSTALL_MALTA.srec.gz) = 127eac81b94185bea670ef1766abe38506310147c058be948614bb472cd97444402c65eef69375c39d6bad518b617a2fcfae314095c94c9263b322e061ffda0b +RMD160 (NetBSD-6.0/evbmips-mipsel/installation/netbsd-INSTALL_MALTA.srec.gz) = 88a878858ddcfbdcc82d30efe6db396e12324245 +MD5 (NetBSD-6.0/evbmips-mipsel/installation/netbsd-INSTALL_MALTA.srec.gz) = e0fd06b18d51bbed126e558fa66a0124 +SHA1 (NetBSD-6.0/evbmips-mipsel/installation/netbsd-INSTALL_MALTA.gz) = 388abbcf174f34d8615308f4d9387534d0dd4973 +SHA512 (NetBSD-6.0/evbmips-mipsel/installation/netbsd-INSTALL_MALTA.gz) = 6aa9bcccacbb410b5f0fc8fc905e78bde3af777913ea3c2035cc6f9a6e4a436fefb7a3afa987403d16a6f1e7151cec117391ba0d146679e7c0c4c9ab1f9727dd +RMD160 (NetBSD-6.0/evbmips-mipsel/installation/netbsd-INSTALL_MALTA.gz) = de9ce82a62f7f24c1c78b0bde362f0e4e1d66293 +MD5 (NetBSD-6.0/evbmips-mipsel/installation/netbsd-INSTALL_MALTA.gz) = b90209535b8a3e40f5d020a99bba9813 +SHA1 (NetBSD-6.0/evbmips-mipsel/installation/netbsd-INSTALL_OMSAL400.symbols.gz) = b1199797080df5d8669b35bcde9172d628bee188 +SHA512 (NetBSD-6.0/evbmips-mipsel/installation/netbsd-INSTALL_OMSAL400.symbols.gz) = 3b4d915b17ba81bfe9b4f9768841c8a140359ea07121d88b2016f0712f42de965f5cf37dca483ba718d47743da6c300b38499ab5c93ff1978d10622e203f84db +RMD160 (NetBSD-6.0/evbmips-mipsel/installation/netbsd-INSTALL_OMSAL400.symbols.gz) = cdb363ed9995287373ce565c3a6a0a4c0441e9cd +MD5 (NetBSD-6.0/evbmips-mipsel/installation/netbsd-INSTALL_OMSAL400.symbols.gz) = 16a4265a582c47946a7bb8ad40f93856 +SHA1 (NetBSD-6.0/evbmips-mipsel/installation/netbsd-INSTALL_MALTA.symbols.gz) = 067b86e211cec25f5b7b826139195679a7b13ad8 +SHA512 (NetBSD-6.0/evbmips-mipsel/installation/netbsd-INSTALL_MALTA.symbols.gz) = 7d4006e0da241ee8b44572a510dcdc33d14cd543d46022faa855b1a554832309d0ca756702a0c7eb551d0d2b77643bf1905153c59cfabd9879e8057d4d9ba89d +RMD160 (NetBSD-6.0/evbmips-mipsel/installation/netbsd-INSTALL_MALTA.symbols.gz) = 432610d592a1e11d09d2c6de9bcfa6eb8021e2cf +MD5 (NetBSD-6.0/evbmips-mipsel/installation/netbsd-INSTALL_MALTA.symbols.gz) = 4c03720d979460cbb6b5311c54214642 +SHA1 (NetBSD-6.0/evbmips-mipsel/installation/netbsd-INSTALL_OMSAL400.gz) = bf85a74b3aba2ec80e8aa7b595e34ed729b9beba +SHA512 (NetBSD-6.0/evbmips-mipsel/installation/netbsd-INSTALL_OMSAL400.gz) = efe3a15153df52551b5542dcceb8c41c9ac74a56cb9e5e4fb2d531d0d933d6ea3f8555831e8e9b707d724ae15cc27b79c790232fa9c5ad142f71b6a15ec61e1d +RMD160 (NetBSD-6.0/evbmips-mipsel/installation/netbsd-INSTALL_OMSAL400.gz) = 4299849406f323f0f65a40f74734a1cd34206bb8 +MD5 (NetBSD-6.0/evbmips-mipsel/installation/netbsd-INSTALL_OMSAL400.gz) = 54ed1ba8d8009ba512e9019f905c0368 +SHA1 (NetBSD-6.0/evbmips-mipsel/installation/netbsd-INSTALL_OMSAL400.srec.gz) = 2f72f6fe9f6a716994fc2dd68ae51c6401c7389e +SHA512 (NetBSD-6.0/evbmips-mipsel/installation/netbsd-INSTALL_OMSAL400.srec.gz) = 4d8d6a4eebdda98b6a8074ea33ee54f729bff3e8e1f8c5c47699819a3cd29d329853bf0083024f9ba3a8893a2255651fe00232408433de8654308d27ba72560d +RMD160 (NetBSD-6.0/evbmips-mipsel/installation/netbsd-INSTALL_OMSAL400.srec.gz) = b05f15e41052f8ab490d7cc00367eb5ce2430bde +MD5 (NetBSD-6.0/evbmips-mipsel/installation/netbsd-INSTALL_OMSAL400.srec.gz) = 1b2e3da6a2b2dfea79a9669561f04413 +SHA1 (NetBSD-6.0/evbppc/binary/kernel/netbsd-EV64260.img.gz) = 963fb1dfd634ec77183e0e19e63add5d6f515a46 +SHA512 (NetBSD-6.0/evbppc/binary/kernel/netbsd-EV64260.img.gz) = 670195305b6eba8bc6cd2b5a05bcae746dffd3a9bcac873d61bc659893de97f35dca7707d073d9fd2e55058f99f83102364bcaa64d0fa9954aba2bd42eaf297a +RMD160 (NetBSD-6.0/evbppc/binary/kernel/netbsd-EV64260.img.gz) = 4ff261bfda6f964c67273e2c6cad05577ff39cc8 +MD5 (NetBSD-6.0/evbppc/binary/kernel/netbsd-EV64260.img.gz) = b3cbc16d9f2d3870fb9c137fa21b7625 +SHA1 (NetBSD-6.0/evbppc/binary/kernel/netbsd-EV64260.gz) = f74b0a7d7afc324d7b463780fc6cbcee71030e28 +SHA512 (NetBSD-6.0/evbppc/binary/kernel/netbsd-EV64260.gz) = 894aa697fd0f0968e534db42528be520c74adec169dcbd2d3603cc262d33e23092253494b072f7239f1542b6237128d8c5069616e28e51422dc69d0bca117d1b +RMD160 (NetBSD-6.0/evbppc/binary/kernel/netbsd-EV64260.gz) = 7d00ed85fbb611948f16e513072f2a307fa46d83 +MD5 (NetBSD-6.0/evbppc/binary/kernel/netbsd-EV64260.gz) = fce468eda12d673785cf7b16c7f4355c +SHA1 (NetBSD-6.0/evbppc/binary/kernel/netbsd-EXPLORA451.img.gz) = 0dcdbfd5853cd5ee3649e1bcdfe16e3133128dce +SHA512 (NetBSD-6.0/evbppc/binary/kernel/netbsd-EXPLORA451.img.gz) = 0654c6b68a52bdee61715fb8b2b1af775f4c7b4a034d11ad7d4cf9f31cae4b8fb327a78dbabfaefcf6d68352ef8be2b4e71d053c97c0c59a24250358fbf47589 +RMD160 (NetBSD-6.0/evbppc/binary/kernel/netbsd-EXPLORA451.img.gz) = e307e29dbdc57b0843e54caf02092c38dcb11cae +MD5 (NetBSD-6.0/evbppc/binary/kernel/netbsd-EXPLORA451.img.gz) = 444e406bfe16f2653bf60273db88dc3a +SHA1 (NetBSD-6.0/evbppc/binary/kernel/netbsd-EXPLORA451.gz) = 54c5de8e61a39b7114fab8a4a28036ae9d44090e +SHA512 (NetBSD-6.0/evbppc/binary/kernel/netbsd-EXPLORA451.gz) = 092f45dab2ddc2cfb79b1c1d649f3a86f169a380c01b7016737bff28b4404a47871546c33e89fe43a6db0255556a2a1cfb2bf8cfd725a852af2c19dea35462bb +RMD160 (NetBSD-6.0/evbppc/binary/kernel/netbsd-EXPLORA451.gz) = 30903e7cf5db4e4f57334f71240da21f6e0fbad2 +MD5 (NetBSD-6.0/evbppc/binary/kernel/netbsd-EXPLORA451.gz) = 229f310637a0c65b47a078f2a6f0df82 +SHA1 (NetBSD-6.0/evbppc/binary/kernel/netbsd-INSTALL_OPENBLOCKS266.img.gz) = 5046cdf7029475b3c2d6f8fb0eb9ac766d55d568 +SHA512 (NetBSD-6.0/evbppc/binary/kernel/netbsd-INSTALL_OPENBLOCKS266.img.gz) = db6f4a419ea019f46205cbb75f76bb8a35bc9d6cee83f9da3b776abb3f83334a60fcad2ef6de4041c0ed3b0689cc259789ca2517dca0e101fd46ede807846d20 +RMD160 (NetBSD-6.0/evbppc/binary/kernel/netbsd-INSTALL_OPENBLOCKS266.img.gz) = 42f2c254a99df74b42ae21c1a89d42ca1d8dc105 +MD5 (NetBSD-6.0/evbppc/binary/kernel/netbsd-INSTALL_OPENBLOCKS266.img.gz) = c7b61fa28cd76c1c694fad7becf124c5 +SHA1 (NetBSD-6.0/evbppc/binary/kernel/netbsd-INSTALL_OPENBLOCKS266.gz) = caf9b0a77c6adfa8d6cf1effad83b107ea9c5976 +SHA512 (NetBSD-6.0/evbppc/binary/kernel/netbsd-INSTALL_OPENBLOCKS266.gz) = 14db94aae558e9e3311e667343468625f309cb71dafc7610f029e6b6e27267ad6169ce21320d6fc512bef2cba49c3f1919d396fbaccbeebe49e8e53dcab865b0 +RMD160 (NetBSD-6.0/evbppc/binary/kernel/netbsd-INSTALL_OPENBLOCKS266.gz) = 3a12875aed7924a33df8290b73576ecfbc8dd752 +MD5 (NetBSD-6.0/evbppc/binary/kernel/netbsd-INSTALL_OPENBLOCKS266.gz) = 20580d5bd36fc097ce824bf9915fae05 +SHA1 (NetBSD-6.0/evbppc/binary/kernel/netbsd-MPC8536DS.gz) = 54b88ef9d752b74a27f85affe9d162bcb43009b2 +SHA512 (NetBSD-6.0/evbppc/binary/kernel/netbsd-MPC8536DS.gz) = 42903a0d5f74e45d00cb48a4cca92c164e26097791048f2cc1c2b7a1d8b243cebe9f64a3daba9542c12b077017e59c1d0d6c8a8c11ea120855f0f40cc7ff8fb0 +RMD160 (NetBSD-6.0/evbppc/binary/kernel/netbsd-MPC8536DS.gz) = fd7ac6dae359227cb757ae1eadf39b1fe08e43d3 +MD5 (NetBSD-6.0/evbppc/binary/kernel/netbsd-MPC8536DS.gz) = 505ede4a04c4726a1121a17a531a74d4 +SHA1 (NetBSD-6.0/evbppc/binary/kernel/netbsd-INSTALL_OPENBLOCKS266.symbols.gz) = 9c6ab2ce83f2ca09cc8789a9431638f7fccdd64a +SHA512 (NetBSD-6.0/evbppc/binary/kernel/netbsd-INSTALL_OPENBLOCKS266.symbols.gz) = 8ffdfde54ed60c89f642b91c6e434fb4ed4de6ed91009df3bd70556e73f6eb5cc28b7bb3090823cd8671e052c5d52bb15eaf8409e779cbbbf4ee6776580b67e7 +RMD160 (NetBSD-6.0/evbppc/binary/kernel/netbsd-INSTALL_OPENBLOCKS266.symbols.gz) = d52adf8dfa375abc8e4d0cfd7a414afc7b44aef9 +MD5 (NetBSD-6.0/evbppc/binary/kernel/netbsd-INSTALL_OPENBLOCKS266.symbols.gz) = 6bf07ac6f2c54f9b46171b57492b6c4d +SHA1 (NetBSD-6.0/evbppc/binary/kernel/netbsd-INSTALL_WALNUT.gz) = c4999c62d6e7c7c8351dba57c34ed0213d2d374e +SHA512 (NetBSD-6.0/evbppc/binary/kernel/netbsd-INSTALL_WALNUT.gz) = 2acf7209a186bb3c52c54e49660c76629fdc8e80e73e1b77beb23e6b56c7acd1d985c958f152c8692303c41d3a4bdcb753ba00c232a772919ce106b1c439d697 +RMD160 (NetBSD-6.0/evbppc/binary/kernel/netbsd-INSTALL_WALNUT.gz) = 9a5d70bdff7b5208eb2f7f6bc2df3b72ce770588 +MD5 (NetBSD-6.0/evbppc/binary/kernel/netbsd-INSTALL_WALNUT.gz) = 777ada452ccd51471ab700f4a6f9e652 +SHA1 (NetBSD-6.0/evbppc/binary/kernel/netbsd-INSTALL_WALNUT.img.gz) = 2a5de49c3e1b5a2f4455ea780f85d185b26845fb +SHA512 (NetBSD-6.0/evbppc/binary/kernel/netbsd-INSTALL_WALNUT.img.gz) = f1f740403f47dc84dd3935611f4e1f71d860c202baeb8b53c23c4c4c6543f9b903cfd559465f7a5c3e1e59a8604f0194af556ebbc7000592cd532c7895b25287 +RMD160 (NetBSD-6.0/evbppc/binary/kernel/netbsd-INSTALL_WALNUT.img.gz) = e974201a8d50e1c9a77bc34a4df289e94a58e966 +MD5 (NetBSD-6.0/evbppc/binary/kernel/netbsd-INSTALL_WALNUT.img.gz) = f710c52befd5c32ae49e90b7f74f8e77 +SHA1 (NetBSD-6.0/evbppc/binary/kernel/netbsd-INSTALL_WALNUT.symbols.gz) = 89c1b110f3a260ae41093f65323a11028f37826b +SHA512 (NetBSD-6.0/evbppc/binary/kernel/netbsd-INSTALL_WALNUT.symbols.gz) = 30c988a3a2b647a1c93a95ab3bc7fcf0428f89dcce44152f81c2a58af49f5e6c95817650f5affca8a83ea0318d913a0ba20c28dfb6b7cb3027dce2c5561ece52 +RMD160 (NetBSD-6.0/evbppc/binary/kernel/netbsd-INSTALL_WALNUT.symbols.gz) = 4838d9d57fdcd79da40dbf3fdbbf09e77118ff2d +MD5 (NetBSD-6.0/evbppc/binary/kernel/netbsd-INSTALL_WALNUT.symbols.gz) = 5b9c0173413ff799fe5140db7ab9c13b +SHA1 (NetBSD-6.0/evbppc/binary/kernel/netbsd-MPC8548CDS.gz) = fa0461c820b70c326f5f2867ff081cc88d357aa4 +SHA512 (NetBSD-6.0/evbppc/binary/kernel/netbsd-MPC8548CDS.gz) = 436d573a0b468d6794a9fc16955bca56a7b726c3e0e306f05e6965bcbd109ebf71fff060b8afcda9782043bd5389e961f1bb191d9b9dd209b385e64e448eb63f +RMD160 (NetBSD-6.0/evbppc/binary/kernel/netbsd-MPC8548CDS.gz) = 01ccef4bca33dfd5dbc63d901d9b006a930858ed +MD5 (NetBSD-6.0/evbppc/binary/kernel/netbsd-MPC8548CDS.gz) = 9c552da04cd50465e8451c12ce98ac4c +SHA1 (NetBSD-6.0/evbppc/binary/kernel/netbsd-OPENBLOCKS200.gz) = d8431c30e8c1e34eb2b721d51f10e2429b542cf9 +SHA512 (NetBSD-6.0/evbppc/binary/kernel/netbsd-OPENBLOCKS200.gz) = 1d111341a7439e63ec210bc09c168cd613b114222241cba494f19e6bf582a0085a8894e1a6a8842b7b1c6f8ee5f2c8b39238b9dd714727a053637cbb59a1f77e +RMD160 (NetBSD-6.0/evbppc/binary/kernel/netbsd-OPENBLOCKS200.gz) = 47a3f7ebc1980ce1817112520f13396d6efa2d44 +MD5 (NetBSD-6.0/evbppc/binary/kernel/netbsd-OPENBLOCKS200.gz) = 4875531aefe44295429c200a8dbbf3d6 +SHA1 (NetBSD-6.0/evbppc/binary/kernel/netbsd-OPENBLOCKS200.img.gz) = e7e23c8fbe61ca6ef52822a4fb9336be7168abba +SHA512 (NetBSD-6.0/evbppc/binary/kernel/netbsd-OPENBLOCKS200.img.gz) = 6c78a517557651386736d048efb9953b4df3350b411291fae3029074ad0dd961f128ebcac4e6f14dd56e53d43465994972ca29572fbcdcd8793f713df74a3e5c +RMD160 (NetBSD-6.0/evbppc/binary/kernel/netbsd-OPENBLOCKS200.img.gz) = 04ea401821e981bff21fd61d8503608fde540bb8 +MD5 (NetBSD-6.0/evbppc/binary/kernel/netbsd-OPENBLOCKS200.img.gz) = 3e5f6b82afebe7b1ab5de3fca0bd75f0 +SHA1 (NetBSD-6.0/evbppc/binary/kernel/netbsd-OPENBLOCKS266.gz) = 22aed20110feacb4634479f3080db81e3a511e30 +SHA512 (NetBSD-6.0/evbppc/binary/kernel/netbsd-OPENBLOCKS266.gz) = e0934031d3b963fe5edbb5944b92a57c8f4ba4b496d8c5ab6aed555012a53f73bfcaba7eebcc1669bd6a308603360804242b7c37e92c022872c524c159c92f54 +RMD160 (NetBSD-6.0/evbppc/binary/kernel/netbsd-OPENBLOCKS266.gz) = ad1b890f8ef6418a1ed2858dadafc7e99729b6bd +MD5 (NetBSD-6.0/evbppc/binary/kernel/netbsd-OPENBLOCKS266.gz) = e935df1037b38d1a903359f63aca6df4 +SHA1 (NetBSD-6.0/evbppc/binary/kernel/netbsd-OPENBLOCKS266.img.gz) = a3b023c3bf29f930fc5ff0e0c074e54e23141963 +SHA512 (NetBSD-6.0/evbppc/binary/kernel/netbsd-OPENBLOCKS266.img.gz) = 3d1c0b86676c2bdd861f7e8e4e20d6a34d1a04079d908b6d2ef5404b1d00ec1f394a8b13fe5d4b4906c996d1912777e0f52ec367ad6e1c9db64cbd22931347c0 +RMD160 (NetBSD-6.0/evbppc/binary/kernel/netbsd-OPENBLOCKS266.img.gz) = abdf86f9c182d23740543843d59e4dfcb05e59cb +MD5 (NetBSD-6.0/evbppc/binary/kernel/netbsd-OPENBLOCKS266.img.gz) = 84ce6f797d900ad639313c55e64178b2 +SHA1 (NetBSD-6.0/evbppc/binary/kernel/netbsd-P2020DS.gz) = 8cc216c33fcb3f59904067c3e9294f0369d6f1e9 +SHA512 (NetBSD-6.0/evbppc/binary/kernel/netbsd-P2020DS.gz) = 6bb4dd7dba52e6a6f4dcb76aa5218ab893deb64d57a87048ed5dbf882c13e92646ca89a037ebcba5211407363a9365d2bc9296397322dac95374e3f03bd88e51 +RMD160 (NetBSD-6.0/evbppc/binary/kernel/netbsd-P2020DS.gz) = d8f03ff91019223b562ee52da049a4f71facf379 +MD5 (NetBSD-6.0/evbppc/binary/kernel/netbsd-P2020DS.gz) = 958385f31a4f6b1a234652faa95c6c95 +SHA1 (NetBSD-6.0/evbppc/binary/kernel/netbsd-P2020RDB.gz) = 9140563a57548b77f93eee35e2615f4a377612d3 +SHA512 (NetBSD-6.0/evbppc/binary/kernel/netbsd-P2020RDB.gz) = 1fbddd9a55f6669c1f2f48dd96b7147cae93a2d5642b262a81669fa4a2670d465cd09347a6f9b7751baa338935114bc2ba2e67622e2f524d9793628274f92625 +RMD160 (NetBSD-6.0/evbppc/binary/kernel/netbsd-P2020RDB.gz) = 3ad3d010c5c0f34a69d7b49c7c1d639f7c5c3618 +MD5 (NetBSD-6.0/evbppc/binary/kernel/netbsd-P2020RDB.gz) = 094787fd9d22021a1b63422895976203 +SHA1 (NetBSD-6.0/evbppc/binary/kernel/netbsd-PMPPC.gz) = 8f72cbe7df21613d6b796b579ced2911efbe66e3 +SHA512 (NetBSD-6.0/evbppc/binary/kernel/netbsd-PMPPC.gz) = f4f11445454376ec9f83f9e3072421a8ccb7bee9b1aaf01aee70a6c044e0de1156a5fbe28b1243e8efb334adeb70621e8eab875c44f590fd0276114a26d8db15 +RMD160 (NetBSD-6.0/evbppc/binary/kernel/netbsd-PMPPC.gz) = ff1f745891b1c4a02836982de15575afe78c16eb +MD5 (NetBSD-6.0/evbppc/binary/kernel/netbsd-PMPPC.gz) = 87d0847ec4707e24c58146eb0475d1aa +SHA1 (NetBSD-6.0/evbppc/binary/kernel/netbsd-RB800.gz) = 139b9c2b87b112ab2d6498e726360504d0adedd1 +SHA512 (NetBSD-6.0/evbppc/binary/kernel/netbsd-RB800.gz) = 8ffc6ac565bf37ee69f8736d7c86738dd69ab7873b77ec062a12a442851559e4c94c903f76e649a21984efd4b98ccaa97333177be635807e6dec8a17bd421880 +RMD160 (NetBSD-6.0/evbppc/binary/kernel/netbsd-RB800.gz) = b6724d690aef60f63c4b1339eb6ce514e0886151 +MD5 (NetBSD-6.0/evbppc/binary/kernel/netbsd-RB800.gz) = 2df5233415f6f20f2af441b4b54379b5 +SHA1 (NetBSD-6.0/evbppc/binary/kernel/netbsd-WALNUT.gz) = d5e489629cc8d1b2903e541b944a123cfc0937bb +SHA512 (NetBSD-6.0/evbppc/binary/kernel/netbsd-WALNUT.gz) = 77d3eda4223f4cf9120a7e84e8c61917749462734c5adc70d95e3108a1b151e0ab7518092d37ddceead9e9047297ef47f4712de7eb0dc05f4190ab60e775d313 +RMD160 (NetBSD-6.0/evbppc/binary/kernel/netbsd-WALNUT.gz) = 15568ccc03d6a06ebdaf407b6d2b4ac07985a0f1 +MD5 (NetBSD-6.0/evbppc/binary/kernel/netbsd-WALNUT.gz) = 11d3fcb67c3ec63c5c43ab5bfe06c0b1 +SHA1 (NetBSD-6.0/evbppc/binary/kernel/netbsd-WALNUT.img.gz) = f001160c675e3d0f73978743c88bf61561a7b10a +SHA512 (NetBSD-6.0/evbppc/binary/kernel/netbsd-WALNUT.img.gz) = a85072ff3b1a1d8b9e35b40b1bb49f5065bad003f603add8330de38a71c19028ed54e377534e4e901281ad5eb65dcf73e8657a39bffac9645e6fee6bce7ac391 +RMD160 (NetBSD-6.0/evbppc/binary/kernel/netbsd-WALNUT.img.gz) = 31480f15986b52f445cefa8aa4e056b6fcb74f1b +MD5 (NetBSD-6.0/evbppc/binary/kernel/netbsd-WALNUT.img.gz) = a0719a86fd17f9ddfa5131e58f77622d +SHA1 (NetBSD-6.0/evbppc/binary/kernel/netbsd-esata-P2020DS.gz) = 50b925468b1ace37856fbfbd4fe5363ed187b4e6 +SHA512 (NetBSD-6.0/evbppc/binary/kernel/netbsd-esata-P2020DS.gz) = f8cde43dbaf1744d7dec3437beb43be1b73178fb95038771a52315b5b54f4ae369c9261c35b710be563b0bc9be07e4801100e012c8313c564f3bf66845082c31 +RMD160 (NetBSD-6.0/evbppc/binary/kernel/netbsd-esata-P2020DS.gz) = cff81475ea7ebe293bbefc4088d5dcb76906108d +MD5 (NetBSD-6.0/evbppc/binary/kernel/netbsd-esata-P2020DS.gz) = d79a18ae8aa921fbd0df460cd5e550a3 +SHA1 (NetBSD-6.0/evbppc/binary/kernel/netbsd-sd0a-P2020DS.gz) = 1c75ca32cb0267f982916a5fb2740483e5aa9f7b +SHA512 (NetBSD-6.0/evbppc/binary/kernel/netbsd-sd0a-P2020DS.gz) = 99d1b928ee2674f7dd22a10ea6c3cb7b24f5bdd4961a5315ad310e2189cf4508bde00d9b752cf3eb6843c3a461f748deeda4f395206a4973be55165f6f17c9ff +RMD160 (NetBSD-6.0/evbppc/binary/kernel/netbsd-sd0a-P2020DS.gz) = 24d2b7dab4018de8de5feb65f23cda0e8b4c1502 +MD5 (NetBSD-6.0/evbppc/binary/kernel/netbsd-sd0a-P2020DS.gz) = 6fc3a2ba5e17d4ecef5cb52b482761ff +SHA1 (NetBSD-6.0/evbppc/binary/kernel/netbsd-sd0a-P2020RDB.gz) = 342dcb5cc506d3272737f3b2c0fd16b7221ef429 +SHA512 (NetBSD-6.0/evbppc/binary/kernel/netbsd-sd0a-P2020RDB.gz) = c74ccc79f91ac3780093676aa88cb544da9cd17abaee1c1d2692acef50c5f13c4ff1e6ea4c334c43242f20460ca6f08406c1514f4b84cb7206900192699b2e09 +RMD160 (NetBSD-6.0/evbppc/binary/kernel/netbsd-sd0a-P2020RDB.gz) = db206fd4eaec146d07e71794320de0e680bed506 +MD5 (NetBSD-6.0/evbppc/binary/kernel/netbsd-sd0a-P2020RDB.gz) = 6a7ec6e8e8a7a2f75e60073154234efa +SHA1 (NetBSD-6.0/evbppc/binary/kernel/nfsnetbsd-MPC8536DS.gz) = 3c9abf574a3c5dd2c38ef5af3433ce2123a30192 +SHA512 (NetBSD-6.0/evbppc/binary/kernel/nfsnetbsd-MPC8536DS.gz) = e58dd95eadafef8b242ce0894ec809b1d73063f7142cb0d6ce42dd03f5a71032ef3d31ef09e19f9cd6594b5bf65806473f560e17f0d505f5491c3651d6f9e930 +RMD160 (NetBSD-6.0/evbppc/binary/kernel/nfsnetbsd-MPC8536DS.gz) = a419d3af2732cc85c1fe0ca06322e0996a7946cb +MD5 (NetBSD-6.0/evbppc/binary/kernel/nfsnetbsd-MPC8536DS.gz) = c900656ec6ae14a67385ea265639a500 +SHA1 (NetBSD-6.0/evbppc/binary/kernel/nfsnetbsd-MPC8548CDS.gz) = 14a02ead1d8e5963e96ddd3a5b3b2625202d0011 +SHA512 (NetBSD-6.0/evbppc/binary/kernel/nfsnetbsd-MPC8548CDS.gz) = c51940733928beb1f9beb280ecc642dd867317be5d0ca36ed9e0e01b1c8b2a1d788658bdb822e4b7be358fca34fce4620a9e2afb10a265007824efb965dfeaf6 +RMD160 (NetBSD-6.0/evbppc/binary/kernel/nfsnetbsd-MPC8548CDS.gz) = fbf09f5e31f3b61a3cb4f1cde889a2c91635cfd3 +MD5 (NetBSD-6.0/evbppc/binary/kernel/nfsnetbsd-MPC8548CDS.gz) = a4094ff843bdcfcd143957a0fd15a01e +SHA1 (NetBSD-6.0/evbppc/binary/kernel/nfsnetbsd-P2020DS.gz) = d5125242574b57126e0a9ed0b2c9e18ba47ba7dd +SHA512 (NetBSD-6.0/evbppc/binary/kernel/nfsnetbsd-P2020DS.gz) = af9b230b2940352e71cba43854b29418e2d1c6a51cfbac7cfcc801a4c1ecbc0605d055fe673fae7f244a421058073f921f1cbc8ce55b3131017138396f2071ac +RMD160 (NetBSD-6.0/evbppc/binary/kernel/nfsnetbsd-P2020DS.gz) = 7e25cb6632e7d744f60572c578fe34ea1acecae8 +MD5 (NetBSD-6.0/evbppc/binary/kernel/nfsnetbsd-P2020DS.gz) = 3659db43dbb405a80a675b7f2840c7df +SHA1 (NetBSD-6.0/evbppc/binary/kernel/nfsnetbsd-P2020RDB.gz) = 9a55d38b7e6f8c5b274ab45f20794feab61a6264 +SHA512 (NetBSD-6.0/evbppc/binary/kernel/nfsnetbsd-P2020RDB.gz) = 15ee2dfc4c476a54f0483facb66aec9b2b743775df471353ca1e443522119af238bebf7a986413d6cfac237aec8242180499b23fa85b85017d20179561025ab8 +RMD160 (NetBSD-6.0/evbppc/binary/kernel/nfsnetbsd-P2020RDB.gz) = dceb778c7ea33542379775b8481122d7e55f9e98 +MD5 (NetBSD-6.0/evbppc/binary/kernel/nfsnetbsd-P2020RDB.gz) = 39f5865216f1e2e37984109a0cf2c708 +SHA1 (NetBSD-6.0/evbppc/binary/kernel/nfsnetbsd-RB800.gz) = ea5d21d649ce2a6c3502b58446cbe747433dcf12 +SHA512 (NetBSD-6.0/evbppc/binary/kernel/nfsnetbsd-RB800.gz) = 8748659a4a7e79a6b4b00dcb90ed2cf8213c138d4df7f93e6e53bee63f0c8f6c9a837f9522c9dba0580226eaa756473640226d1f4edb688a5b04807cb588730c +RMD160 (NetBSD-6.0/evbppc/binary/kernel/nfsnetbsd-RB800.gz) = 9fe62c16553ca3e5955d12ca7e59cd0336bba55d +MD5 (NetBSD-6.0/evbppc/binary/kernel/nfsnetbsd-RB800.gz) = b4a5d575b02cf078c5c31542e5b4954f +SHA1 (NetBSD-6.0/evbppc/binary/sets/man.tgz) = 899b9d8242e983a5110ab755651c24f709b5af67 +SHA512 (NetBSD-6.0/evbppc/binary/sets/man.tgz) = 410999db110d710f4bb498c3d7ae7adc62170c7c2f470ce189c92f6c436c5ea96149659c631ef0b5605caaa025d97dfe1c07c428d86f51239657bd6b71717b15 +RMD160 (NetBSD-6.0/evbppc/binary/sets/man.tgz) = c1270f68c6d41b351877f71f0396ac34877dfc8d +MD5 (NetBSD-6.0/evbppc/binary/sets/man.tgz) = df4db2bbfa39ef6a4a215d949653d04a +SHA1 (NetBSD-6.0/evbppc/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/evbppc/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/evbppc/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/evbppc/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/evbppc/binary/sets/xbase.tgz) = b7c8146146ebc15191c1bf53f51f8f980fe8c816 +SHA512 (NetBSD-6.0/evbppc/binary/sets/xbase.tgz) = 091f5d00414a9ad478811bfb0e953f2a204869bc5e310790886a59c11953974cf7068cd9a96c8823856ab2687ffa2ac31e97494f47338bfe31d80217382c59f1 +RMD160 (NetBSD-6.0/evbppc/binary/sets/xbase.tgz) = 4bd1bfdc7c1e1619de63fb83276c21039b945357 +MD5 (NetBSD-6.0/evbppc/binary/sets/xbase.tgz) = e621806afa0fcc9cdcef0f9b3c7dfcbd +SHA1 (NetBSD-6.0/evbppc/binary/sets/xcomp.tgz) = 960dd33b61e19dec92096a54791aca1cdf56ce54 +SHA512 (NetBSD-6.0/evbppc/binary/sets/xcomp.tgz) = 111dd50041e4008aeadb898c3d08f9995c5c13a41ccc20993b4ad51c81d7f6ee3b4dab16158ac7436d085b80e4a643b236a9c97edd3e915125a1466154538420 +RMD160 (NetBSD-6.0/evbppc/binary/sets/xcomp.tgz) = 0cf8b9a8d1489a32ba0b5a277d90e429c40650fb +MD5 (NetBSD-6.0/evbppc/binary/sets/xcomp.tgz) = 4ba4077ca2c0edf71813165fcf5321fb +SHA1 (NetBSD-6.0/evbppc/binary/sets/xfont.tgz) = 4711fcbade0238d60b7b89cf0d7873b03d7ed1f7 +SHA512 (NetBSD-6.0/evbppc/binary/sets/xfont.tgz) = c29130f55f536f602253a7f92f073ebf6ba02baea09f8011530bbf7e03ae96594334f0c60b29a8bceaffc3eb8b152db47548e38a3c8a14abc5fe35bc5d1d7d93 +RMD160 (NetBSD-6.0/evbppc/binary/sets/xfont.tgz) = 3b01af0f8e34367988d559fe0fbb0acbbafb0b2b +MD5 (NetBSD-6.0/evbppc/binary/sets/xfont.tgz) = 6ba15ed12217b726d9129db8e942a048 +SHA1 (NetBSD-6.0/evbppc/binary/sets/xserver.tgz) = 05aac7e617e0cac05a88062fef29bb459da7a1d1 +SHA512 (NetBSD-6.0/evbppc/binary/sets/xserver.tgz) = 19fb5af5d6afd78839a22e5c0694a492047b5200c569cbf58c676ff32ec250b21edcfe2ed00b65092fdac374d1ab9eaaed6113c69bc03009cf458aedc6014913 +RMD160 (NetBSD-6.0/evbppc/binary/sets/xserver.tgz) = 774d2a1072b8d122790ad189a6d2ada2ad99e7cf +MD5 (NetBSD-6.0/evbppc/binary/sets/xserver.tgz) = 3daf1477cadf3593e9ba45e3703fe8a5 +SHA1 (NetBSD-6.0/evbppc/binary/sets/kern-EV64260.tgz) = f49583bb3bdb33b9eb3b0b4136668772da20f45b +SHA512 (NetBSD-6.0/evbppc/binary/sets/kern-EV64260.tgz) = ba5c1437d9a233dc818880e72de7746dced45081a2fe998ca922c51eaf404bce9f42f7f763a611485bb518e50c1e4da5a6906d0b28d01b9cd3c9f1be4d8c2761 +RMD160 (NetBSD-6.0/evbppc/binary/sets/kern-EV64260.tgz) = f477b6948cae222002fa140de299929d9d9807c5 +MD5 (NetBSD-6.0/evbppc/binary/sets/kern-EV64260.tgz) = 168a599ee54d18f0eab734e5717b2984 +SHA1 (NetBSD-6.0/evbppc/binary/sets/base.tgz) = 660713e719fb1be5824c7b5f573730b9d1408922 +SHA512 (NetBSD-6.0/evbppc/binary/sets/base.tgz) = 366e7065fad6b8e8a7e593fa5790eaaba11a8ad49006730fc01fba2f1d7908a6ac1ebfc88a4cf7731b1d31b3e21dd5d0aa5c5433cd4f01ce95254735da15c772 +RMD160 (NetBSD-6.0/evbppc/binary/sets/base.tgz) = a460662933495846dc34b422fbf2f2f3b7141068 +MD5 (NetBSD-6.0/evbppc/binary/sets/base.tgz) = f527c4156acc659412d01a00756d57f3 +SHA1 (NetBSD-6.0/evbppc/binary/sets/comp.tgz) = c9caa7ece23746ea1423f1cb05924d7aafb69081 +SHA512 (NetBSD-6.0/evbppc/binary/sets/comp.tgz) = d60f9bbefcaa3331646da3e9bd2738cf11e357807ce64619cd48db62cd3c72469f39113b04883771c610c63f74e574941add1d83ee2cce2a7b13e85e844b9eaf +RMD160 (NetBSD-6.0/evbppc/binary/sets/comp.tgz) = 2db97b320a8befeb352b84a44e32b3844648b85a +MD5 (NetBSD-6.0/evbppc/binary/sets/comp.tgz) = ab787a55ed8b6765619f75f613914955 +SHA1 (NetBSD-6.0/evbppc/binary/sets/etc.tgz) = 01f15943e5ac9e3d4885c4391f332b3367a96483 +SHA512 (NetBSD-6.0/evbppc/binary/sets/etc.tgz) = 3d69692f01bf9b9dd36e719af4f2e99d7c9aac0b92925e2751b0ff8ff7651e37f948d18765fda1d1841fe8d97a7869674d584423594ad1ca48da8b4c35e0a3ec +RMD160 (NetBSD-6.0/evbppc/binary/sets/etc.tgz) = 6422793912a3843dafb20baa3c9ecdc10305262a +MD5 (NetBSD-6.0/evbppc/binary/sets/etc.tgz) = 789c56228f05a0cf67d1917ae04862f5 +SHA1 (NetBSD-6.0/evbppc/binary/sets/games.tgz) = e7bde1f51127db8c3a7d15ec931c915806661f0b +SHA512 (NetBSD-6.0/evbppc/binary/sets/games.tgz) = f39fcc09a9b81a604a29c968dc74264a42c46ccc122c9ac01030e6ca01c28967fb7e20d8fa182f2ba07ade376a14a802c2abd06154c754f907a9879b7e7ab52e +RMD160 (NetBSD-6.0/evbppc/binary/sets/games.tgz) = a09ee1c7811eaa0ed3aa1ca0f85e1279b096fc46 +MD5 (NetBSD-6.0/evbppc/binary/sets/games.tgz) = 81e8837aedbfcea8d6957f192e54545f +SHA1 (NetBSD-6.0/evbppc/binary/sets/kern-OPENBLOCKS200.tgz) = 561ca3ad31c44deca4b197207d2a2e6a92ed4bd4 +SHA512 (NetBSD-6.0/evbppc/binary/sets/kern-OPENBLOCKS200.tgz) = b47b23e9b6c3efdc389ce3b47218eea8da190734075985e7ad009a10addcba48e565efabbc3b11c32e220d6059fe5114ae77351bc72549e8b8f37be98dcba27b +RMD160 (NetBSD-6.0/evbppc/binary/sets/kern-OPENBLOCKS200.tgz) = b2058d6a4e4fe11ebb19f429347a6ed69a1b014a +MD5 (NetBSD-6.0/evbppc/binary/sets/kern-OPENBLOCKS200.tgz) = b2ea5966c8110677fd107fd4029242f1 +SHA1 (NetBSD-6.0/evbppc/binary/sets/kern-EXPLORA451.tgz) = 7a6fe1de68c0fffedc5918ffabeb87ee71ad3da1 +SHA512 (NetBSD-6.0/evbppc/binary/sets/kern-EXPLORA451.tgz) = 2e30f89fc77fd9bcd9310c4d12379245a18aed68b661c037593870c86ea806edb62f32a433f46e4f4c205c2eddfd86c353c3ca970a887a324b4d9eaf952b537d +RMD160 (NetBSD-6.0/evbppc/binary/sets/kern-EXPLORA451.tgz) = d68c12c132889e9cb48e003811e9c2de7fe41aa3 +MD5 (NetBSD-6.0/evbppc/binary/sets/kern-EXPLORA451.tgz) = b5ba93f49378f17fa86d91832a97d63b +SHA1 (NetBSD-6.0/evbppc/binary/sets/kern-MPC8536DS.tgz) = cb9e2b4befa9231d5c6bcf52460189d6ad18fe85 +SHA512 (NetBSD-6.0/evbppc/binary/sets/kern-MPC8536DS.tgz) = 937bdfd98369d438c25a0839e50cac22602b3766db5f359d31825445c156fbe94de24956584b0668bf5c1b09565733c5dc4e9dec8fb5c034f5764edbf8241bff +RMD160 (NetBSD-6.0/evbppc/binary/sets/kern-MPC8536DS.tgz) = 63389f49fc87afc7227318374fa8fbb130c1f076 +MD5 (NetBSD-6.0/evbppc/binary/sets/kern-MPC8536DS.tgz) = b4ccb088690ba31893f554c22874c25c +SHA1 (NetBSD-6.0/evbppc/binary/sets/kern-MPC8548CDS.tgz) = f17cacf88747cab418fed98c8f2d4341d883c45c +SHA512 (NetBSD-6.0/evbppc/binary/sets/kern-MPC8548CDS.tgz) = 13adbfaa5c03713aba913d4bb08f6c8f654b3af210164d111d4c5825bd49ebc7ea8b0b4e5dabecfe685cc9ea9bbdbd0c41cbbe3e3a4bf9d497186c0cc15ed3b7 +RMD160 (NetBSD-6.0/evbppc/binary/sets/kern-MPC8548CDS.tgz) = 5e2198d8b2c62f629a2e41ff422f50f0d90b2ca2 +MD5 (NetBSD-6.0/evbppc/binary/sets/kern-MPC8548CDS.tgz) = efdf3c8e143e54c672ba669c5b2211c7 +SHA1 (NetBSD-6.0/evbppc/binary/sets/kern-OPENBLOCKS266.tgz) = 3dff6cb4cc77e770b17e56dc132fbb3ecafa65f1 +SHA512 (NetBSD-6.0/evbppc/binary/sets/kern-OPENBLOCKS266.tgz) = 6309b5240c155074f7f0ad04684043e26886283d81369faa2c5d5ae202a82c5fad980c1101cb5f03fbf50e61b78fa87cf5ce633ab354b90ae0f267c4fc03dd92 +RMD160 (NetBSD-6.0/evbppc/binary/sets/kern-OPENBLOCKS266.tgz) = 22a0af77fbc2dc62e11aabc36b92701e12a23624 +MD5 (NetBSD-6.0/evbppc/binary/sets/kern-OPENBLOCKS266.tgz) = 776cb54622eca1a207cef956b8fe9a2f +SHA1 (NetBSD-6.0/evbppc/binary/sets/kern-P2020DS.tgz) = 6ce50d8dc26e08d660edc8daf9b4c35e2a03b005 +SHA512 (NetBSD-6.0/evbppc/binary/sets/kern-P2020DS.tgz) = b04c1630a1bcf4ac4855e4242c5cd12b82c846b371b6257abb99ba4b28026c546ae914d68ed31ecfc02d952aef81bd8fa50879c698735d453bb0a8ed72131fd0 +RMD160 (NetBSD-6.0/evbppc/binary/sets/kern-P2020DS.tgz) = 16938708031722094448b4a613dce8e2acbf8c63 +MD5 (NetBSD-6.0/evbppc/binary/sets/kern-P2020DS.tgz) = 94ba27899a9ee3756ec7084e362ca968 +SHA1 (NetBSD-6.0/evbppc/binary/sets/kern-P2020RDB.tgz) = b0bbfe5b10d1596af93eec4960120ebb23d00411 +SHA512 (NetBSD-6.0/evbppc/binary/sets/kern-P2020RDB.tgz) = 536a382b932643d9e4a65dca9f4601edce766799da3e291484e9460291ce4168b5cfc59a39bb1169e69065bb65d1ff8f56caa98651d643bad9f33ef35b219d0f +RMD160 (NetBSD-6.0/evbppc/binary/sets/kern-P2020RDB.tgz) = ea8619e5c65fa02151fb23136e03ee8889f68ab4 +MD5 (NetBSD-6.0/evbppc/binary/sets/kern-P2020RDB.tgz) = b14ef5c3eff1d4c89afb1e9d883aa3d4 +SHA1 (NetBSD-6.0/evbppc/binary/sets/kern-PMPPC.tgz) = 56e8d8a4c533163eaf18a2b9cb988e0a61be8174 +SHA512 (NetBSD-6.0/evbppc/binary/sets/kern-PMPPC.tgz) = 87f5c77334788e59662c95dd073e3fa8a680f840ccab27e839fb405cc942941d5c2459cfa4d93a02179ab27fc6e75f8d3c957c3c95e5e271a404f64ec08a0b19 +RMD160 (NetBSD-6.0/evbppc/binary/sets/kern-PMPPC.tgz) = 7160a35f527dc620a2e67e17a22e8cbdffd8fdfe +MD5 (NetBSD-6.0/evbppc/binary/sets/kern-PMPPC.tgz) = d0459860eae7ad936e2b318a2cbfd7ac +SHA1 (NetBSD-6.0/evbppc/binary/sets/kern-RB800.tgz) = 79b942c2076a9219525ec9da7b25da3a21488675 +SHA512 (NetBSD-6.0/evbppc/binary/sets/kern-RB800.tgz) = 0c9462c4519ed0fc1b378a7abb23c3a89768d6fe128c726e2847c6daf576757492438d4cab244e32f1bd7601f1a3e808d79f874b3480e22abff4a45b9cc5a8fb +RMD160 (NetBSD-6.0/evbppc/binary/sets/kern-RB800.tgz) = 6c7309b72d5a61879c3151d2065cb70361ad5c70 +MD5 (NetBSD-6.0/evbppc/binary/sets/kern-RB800.tgz) = 9951a8e7708ca609ec9abfb3b313f03b +SHA1 (NetBSD-6.0/evbppc/binary/sets/kern-WALNUT.tgz) = 0a60e6f9a6fbaa8477b05baae64d4b405c9c252d +SHA512 (NetBSD-6.0/evbppc/binary/sets/kern-WALNUT.tgz) = cf5e16c71fbe6366c41503578254a5be9bacf01cab691f3667c6b3b5ec3413cfd30f3dd00152a7c0dea73effa0f46fde1070df5aa29db02c021bc60a83d2ebc9 +RMD160 (NetBSD-6.0/evbppc/binary/sets/kern-WALNUT.tgz) = 54ade37dbefe29a6de73720d7900ce68b7dff1f3 +MD5 (NetBSD-6.0/evbppc/binary/sets/kern-WALNUT.tgz) = 4f92053a06ab8e494ae5068657a449ee +SHA1 (NetBSD-6.0/evbppc/binary/sets/modules.tgz) = 3297a716bfbfdb870519304912c1f0ba834ef318 +SHA512 (NetBSD-6.0/evbppc/binary/sets/modules.tgz) = 586c1502a8fcb99323ba75ca343fbb8204fb80a00de8b09aa6722bc4d7bb142dd35bf023f11ef981f5ede707dec673dc1040578677216cb0aab2e1d9d871263d +RMD160 (NetBSD-6.0/evbppc/binary/sets/modules.tgz) = bb87c0bfbb41190443d888876e2f6329f8c5a0c6 +MD5 (NetBSD-6.0/evbppc/binary/sets/modules.tgz) = be483e96c1f3eb3a155b17fe7097d398 +SHA1 (NetBSD-6.0/evbppc/binary/sets/tests.tgz) = a9c5bab23ec89b45bc96550385064ca681c1aaf7 +SHA512 (NetBSD-6.0/evbppc/binary/sets/tests.tgz) = a629539a7f807f4cf5651329769924fbd42102b4e9f96b4aaef254d1237e0ff4b6a55a9a1968bd6aaecf5f4e4db667fe59b8e2afa8232b80af4372fc436eed18 +RMD160 (NetBSD-6.0/evbppc/binary/sets/tests.tgz) = 8f786bbb44342927ecaee51314d2492b228ca507 +MD5 (NetBSD-6.0/evbppc/binary/sets/tests.tgz) = 6d2a4b03364dadacd276c5e908c6053d +SHA1 (NetBSD-6.0/evbppc/binary/sets/text.tgz) = 9b944538cc5e87133cecd712523216a783ba97d7 +SHA512 (NetBSD-6.0/evbppc/binary/sets/text.tgz) = 7d87e8bfe246ce56e93257beac1808fd00160911acc22b5abcfc4de9125182d982e69709ff8e7f5dabd2454024cbf2969d836cfec0bc8b314f09143654648e99 +RMD160 (NetBSD-6.0/evbppc/binary/sets/text.tgz) = cf2dc7ca65a246453309df0e94e804c5a04b0719 +MD5 (NetBSD-6.0/evbppc/binary/sets/text.tgz) = e8220cff6b33bd3cb4e91d50573b43ff +SHA1 (NetBSD-6.0/evbppc/binary/sets/xetc.tgz) = b6aafacecaf76d99a4c3c428e33a23633419f52d +SHA512 (NetBSD-6.0/evbppc/binary/sets/xetc.tgz) = 9257fc58e039f2afc1ae7f46a7ed2ecdd1a13e67a76960490e89efb8fb12b44100a465270469058071249e0864346ff4dca825786552a4a8ddc804cc7a90dd33 +RMD160 (NetBSD-6.0/evbppc/binary/sets/xetc.tgz) = 6c17517837ddebee9482883db92d1542a89835b4 +MD5 (NetBSD-6.0/evbppc/binary/sets/xetc.tgz) = 77d81348f7721a447c8548aac150659b +SHA1 (NetBSD-6.0/evbppc/INSTALL.html) = d106438243f94987f5d126102e6324f6c1ad274c +SHA512 (NetBSD-6.0/evbppc/INSTALL.html) = d83cf719d3601674fe54b1fff57a8916d342ca9924dd38eaf3f6be43a3d109b85213d4217a5ede1f54734644d1e062437a63f428063cc3bf66166c6131860cc8 +RMD160 (NetBSD-6.0/evbppc/INSTALL.html) = 991e52340a15583f9b28560cacf1d10a5e8a6617 +MD5 (NetBSD-6.0/evbppc/INSTALL.html) = ab505dcacfa6b669a830b026c43d929d +SHA1 (NetBSD-6.0/evbppc/INSTALL.more) = 375545e5f7e921c1635e3538cfa3f615f58ba82a +SHA512 (NetBSD-6.0/evbppc/INSTALL.more) = d2c28cbf4417afcfcb33f363f3c234403f60c3899cee910767c9dcb7c8f39ef2f1dcc84779e67c5ad386a162ba886c37dfc64d4c7e8a70a3b0fcba1286a5a059 +RMD160 (NetBSD-6.0/evbppc/INSTALL.more) = af295999442791298fff266b84d6ab1a92c3cbe1 +MD5 (NetBSD-6.0/evbppc/INSTALL.more) = b21374e21e9e0599b62595c1aca77cce +SHA1 (NetBSD-6.0/evbppc/INSTALL.ps) = ec4c228a542dd84139f5eb00ff550be759020a10 +SHA512 (NetBSD-6.0/evbppc/INSTALL.ps) = f784251812449ee49a2a2f69b54e20aaad818e0c07c220553da4d1c34676f843c7f60472c750a3dbe952725aad68e5abdf5dc19bb4d3b90cb742d8fcacf1334a +RMD160 (NetBSD-6.0/evbppc/INSTALL.ps) = 525b9a28bed1478b2c2ff4a94da78aaae125bcc7 +MD5 (NetBSD-6.0/evbppc/INSTALL.ps) = cfa9f4c9a173353430edc81cfe8a37af +SHA1 (NetBSD-6.0/evbppc/INSTALL.txt) = fc26b26f28fb8eeeb5bb990fc72d9c3d57067350 +SHA512 (NetBSD-6.0/evbppc/INSTALL.txt) = 1bd1da4343b0ab19075682a1ea38e33c7a0e11aa2253bae18a19dfb82c99c2b21b7e74e28f0952cbe6c3499a00bf412e998309b52c0c6fffafc868fd5a370e43 +RMD160 (NetBSD-6.0/evbppc/INSTALL.txt) = 9d44c454ba9249c02ac948603f1305342bedf9a5 +MD5 (NetBSD-6.0/evbppc/INSTALL.txt) = 44b21d90e58f137302ac1c96f78914ef +SHA1 (NetBSD-6.0/evbsh3-sh3eb/binary/kernel/netbsd-COMPUTEX7750.gz) = 99907a8b29592f20a683481b351d6c3b629ae74d +SHA512 (NetBSD-6.0/evbsh3-sh3eb/binary/kernel/netbsd-COMPUTEX7750.gz) = d25c300a0bef7432042f22856f899b60993f739522f62d7c1450da81c6774d01769d54f83b1039ed7b97af8ea4cabd954f8017b77b35d0d1a09c47baa09f0cae +RMD160 (NetBSD-6.0/evbsh3-sh3eb/binary/kernel/netbsd-COMPUTEX7750.gz) = cca19d946d47159fc455f36067dbd3cfee7f0f5f +MD5 (NetBSD-6.0/evbsh3-sh3eb/binary/kernel/netbsd-COMPUTEX7750.gz) = 2556834458fa65b30784812d6defbce0 +SHA1 (NetBSD-6.0/evbsh3-sh3eb/binary/kernel/netbsd-COMPUTEXEVB.gz) = b4fcb725319fdf75cb8fbfe3cc385f0546536032 +SHA512 (NetBSD-6.0/evbsh3-sh3eb/binary/kernel/netbsd-COMPUTEXEVB.gz) = 3ae3fa47d5e760564ba5309b5bcbd4ca32ec52bf80ede5764811779acf73c206643cdfa9b0020b300ee70d75af820aa28ba798663ea962b16af935df79c9e4df +RMD160 (NetBSD-6.0/evbsh3-sh3eb/binary/kernel/netbsd-COMPUTEXEVB.gz) = 697977f6961f8dc0b2204532edc875fc23dd309b +MD5 (NetBSD-6.0/evbsh3-sh3eb/binary/kernel/netbsd-COMPUTEXEVB.gz) = a163b83287053245cd74d74a2c66a13b +SHA1 (NetBSD-6.0/evbsh3-sh3eb/binary/kernel/netbsd-CQREEKSH3.gz) = 3bc3953e940f68f2edadd93f79c8ef7c841c4000 +SHA512 (NetBSD-6.0/evbsh3-sh3eb/binary/kernel/netbsd-CQREEKSH3.gz) = 532a1d96716c85a6b77ebcbeb19560f2e402cbf68a50feafa6452117b477285ca05a0c86dd073bf9c237b6156fa59b42c05fa5c4029739b4fdb277a0c5238e09 +RMD160 (NetBSD-6.0/evbsh3-sh3eb/binary/kernel/netbsd-CQREEKSH3.gz) = dad35f588cb96a63d46bad58b6f4e565402ecc3e +MD5 (NetBSD-6.0/evbsh3-sh3eb/binary/kernel/netbsd-CQREEKSH3.gz) = dfdbab13faaee507abaa31e6b1819e30 +SHA1 (NetBSD-6.0/evbsh3-sh3eb/binary/kernel/netbsd-KZSH401.gz) = 6bc4eb9bc72f6ab2412a0f4db523f849955d12e6 +SHA512 (NetBSD-6.0/evbsh3-sh3eb/binary/kernel/netbsd-KZSH401.gz) = 80208e8df1f7c9fdc60ba1558c6f7182d65d6f96f7d57afc3d41887908dfee3598db6e82e827d2a9f14106ec262c4428fcf1a2046dc847c7993cabd9e6e668e6 +RMD160 (NetBSD-6.0/evbsh3-sh3eb/binary/kernel/netbsd-KZSH401.gz) = e16349b9d4c834165922b78175d291af77caa0d9 +MD5 (NetBSD-6.0/evbsh3-sh3eb/binary/kernel/netbsd-KZSH401.gz) = f95e0f3c93cff1ad0ea5667fdaba435b +SHA1 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/games.tgz) = 37e15b0950aaaf1af36427ae5dd5866c1879b6b3 +SHA512 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/games.tgz) = e674abb1b1966acbc581a8f8b3e37841f48656e66f3302077cbb2de443487912b99521336ec5dc096fa3c7769b2d7623e1d1720a079407ec1861d32159a72ebc +RMD160 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/games.tgz) = 36070071e8315d2352be1b3e563ce7ef7625d184 +MD5 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/games.tgz) = 0016145b46957b95dd158b4441dfb010 +SHA1 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/man.tgz) = 899b9d8242e983a5110ab755651c24f709b5af67 +SHA512 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/man.tgz) = 410999db110d710f4bb498c3d7ae7adc62170c7c2f470ce189c92f6c436c5ea96149659c631ef0b5605caaa025d97dfe1c07c428d86f51239657bd6b71717b15 +RMD160 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/man.tgz) = c1270f68c6d41b351877f71f0396ac34877dfc8d +MD5 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/man.tgz) = df4db2bbfa39ef6a4a215d949653d04a +SHA1 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/xbase.tgz) = 564bce6dd7c37b5e941e41d50f363c133fdf8f97 +SHA512 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/xbase.tgz) = 23b3306254c789331542e63974f9d7cdc54d99ba2cd67cf6a1c97f09afa4f6cf6aa8798e37b7c38f4a55afd1572154f291fa1bf2e2a1fc87165fd6bd7f89fb80 +RMD160 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/xbase.tgz) = 476fbd8301bec0795a01552728ada44204d2dbe6 +MD5 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/xbase.tgz) = 9fbbbdb3acfa4ccd9f0b309ea0ed0700 +SHA1 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/xcomp.tgz) = 526a278a13833073e6231e879abdec85400ca888 +SHA512 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/xcomp.tgz) = d2081a7536e3d7fa27a363afd8f6eb5fc3de4606f11b4857be2f1df59934da9d3d16e0df3a6edf4cdf52c8f579e0e4c06f07de0959b5213c21be1a8fdc2ee134 +RMD160 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/xcomp.tgz) = 4a767ff08e9bcf98f886849cabebd1300397256f +MD5 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/xcomp.tgz) = a23a2d8be9298497b4b6d39fda330bf4 +SHA1 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/xetc.tgz) = 93a5cfbbfdc641f91ab363d4b65d1158d71c0cfc +SHA512 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/xetc.tgz) = 85a67734801e81e129a37b73ae62211459fb16d4e52a945ef21a4bb908dd7d1d775233956086dd3d59af45bcea24fbd6f54a2a9175756d242b57e07d10767548 +RMD160 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/xetc.tgz) = 6fb055d0e1b6264bf1ec396236d903218832377a +MD5 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/xetc.tgz) = af954b56e624948145b91aa451d77392 +SHA1 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/xfont.tgz) = 6139c05273b6feeecdfcd11cbe0da91256d12a11 +SHA512 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/xfont.tgz) = bb849454ede88d39ca60d6c513c833c2b29ea548adedb9f76870839174a3daa838d38a6ad701c78bfc164e690c5ebda9c9d00d4c23ad816df9f1962313afdbf2 +RMD160 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/xfont.tgz) = ea8f123f9f78b429b77ff15c924803da1da2068d +MD5 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/xfont.tgz) = a87cb6769c37ae20dbf0dd70cef93d11 +SHA1 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/xserver.tgz) = 6cd4fdb0ff00ef5d89b47e68e538c86e395b2054 +SHA512 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/xserver.tgz) = e3b575cab95e297a05a26a03eeff0cf843d665ebdfd103846ad544bef1d04f93aa20ceab09b1dfaae8f59d89ebb1cbef400b7521bdb41f7542f23156540aa4c0 +RMD160 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/xserver.tgz) = 7e52b98276b4d097f7babe918e6768ae9d7945db +MD5 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/xserver.tgz) = a505ab4ce0801aabe21fe6038b63809f +SHA1 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/kern-CQREEKSH3.tgz) = 126932a5bc72bd20874c71d76047894c6a7fedb4 +SHA512 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/kern-CQREEKSH3.tgz) = 89727c156d25912c17f801e7cab55d487eff7abc0a9168f490f77313d38eed5a37bde3c0ffbad4db49cc70c335b1147df1408ded59c4b5aeec9a0557a47e7b8f +RMD160 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/kern-CQREEKSH3.tgz) = 427056f8e924c6346b86a52b73dc8f0e9a98e44b +MD5 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/kern-CQREEKSH3.tgz) = 07b32973dbbb2d0a7bf8f397349c032e +SHA1 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/base.tgz) = 3dc230ebfc3669475edb5f69a61191cf0310b438 +SHA512 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/base.tgz) = e60bf3c63a76db118e7646ddc582150558df14cfde8cb8a6fa74f06bdfcb1f920e6015091ef4763be13072da77e2243b69a8e2739cc8945ec388b8f7fdb2fe50 +RMD160 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/base.tgz) = 5b347ce9da19b214d2069c8dc029cd0448af298d +MD5 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/base.tgz) = 79849fe1cbe830a98d8bc0a7db8f4e62 +SHA1 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/comp.tgz) = 882b629fd6de1ec706834199fb45736bb599bbd9 +SHA512 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/comp.tgz) = 700640c27a7453cb2ca1b5c29a2e0558a9cce8f21e4c44e17659bff25c4727aa578f85d3bdbf6da6173c80cac33955ec1731288160b1870fbf92a5df0ed258c1 +RMD160 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/comp.tgz) = 0c3da5c9c5ad1e9d8835040b230e89192f8cc98f +MD5 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/comp.tgz) = ae57e406883549f546048ff2480c5707 +SHA1 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/etc.tgz) = 5ef345b014742f576164cd85dc6744b87a4da775 +SHA512 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/etc.tgz) = 998a737bb0964b9bb61798310ae4f979c9e8518f90c482817bcaff1251036e51bdefb39a6b9595f2e313c0df79d44b387c960878582d7721c551882f2a3aba14 +RMD160 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/etc.tgz) = 64d587adda384831dccfee1548c9c09ed5c36f44 +MD5 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/etc.tgz) = 495f4d62d00649132f218565bddeb50b +SHA1 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/kern-COMPUTEX7750.tgz) = 364b983f7368d62a6f35a63945026cd8c19c3bf6 +SHA512 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/kern-COMPUTEX7750.tgz) = 8341464294654062caf3c3cfdc1ece9bff1cb6642b9873cebc4520e4ff9a0ed27e5e0106a488ee323d41d77b0bed99d7ad450c35d9d2f805ab18b3e3a941ea71 +RMD160 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/kern-COMPUTEX7750.tgz) = c84e2532d3efe0b47b0db0c7471f9f78b0fd6dde +MD5 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/kern-COMPUTEX7750.tgz) = bf341bdb90b335be676be766b8949217 +SHA1 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/kern-COMPUTEXEVB.tgz) = fd664ded3626416bfbabf99bc73dac4a2bac909e +SHA512 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/kern-COMPUTEXEVB.tgz) = 3adcebf6f3acda9c84666cc1ce39a75302776e0f640cc02024d1ae2a7fb4ef7df14bfbb32e808f4a30fb482fdf181670c87327c0d5ded1145ee0f6bda268e369 +RMD160 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/kern-COMPUTEXEVB.tgz) = f21c49e3f0a4a5fe70070da938296750a222e0f4 +MD5 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/kern-COMPUTEXEVB.tgz) = 39ababb0c8156e51b2c9b3854286a72f +SHA1 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/kern-KZSH401.tgz) = 58b48cb56251a87dfc59abd0ae25e8cb0e0ec7bb +SHA512 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/kern-KZSH401.tgz) = 4c3c9efd94bf1b9080d7355143d40f2796841448a92bf25c6f8b49772dec595915c8d7aa091afffab8df6f2eec40685c5a008ea65abe3ab32f2da6a7000de523 +RMD160 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/kern-KZSH401.tgz) = 5931d576a61a240dacf5dfdaaeab6ac8a435b17e +MD5 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/kern-KZSH401.tgz) = d4dfbdffb2514e61fbfb4d7d39962091 +SHA1 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/modules.tgz) = e5078cfd24cfc29249d14a6a6f84de8d27bf1153 +SHA512 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/modules.tgz) = bc00fa4158aa2606925bd8f71698e543a5628739dcaa953ae99c0218fb8d3d1b70c78134cc5554353c612ec7be6fb4efe2f57b28a91a54c87266a9f7450eb38d +RMD160 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/modules.tgz) = d35c1aa762a049440ce3095ae19f14cece89102f +MD5 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/modules.tgz) = 09a7af7e7ec408df3bd4541aa159ee66 +SHA1 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/tests.tgz) = bc89ec5fa64ca7df4c9b4a748cdf2ea437bbbf11 +SHA512 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/tests.tgz) = 011d3773e6363fccfb41d424a51d455d5508cdfb8da226a3a08670c0f5f96a613f0fa5b9818b634d750ab728a8e1546b3c8823b37c91317eb1d0b1cbd85cb0e6 +RMD160 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/tests.tgz) = b5534365eea74dcca99a5d5568c41b3ce79109c2 +MD5 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/tests.tgz) = 324430decd8312ba548bff34d8197b5a +SHA1 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/text.tgz) = 8cbc530ce508c246c6bfca4abc898f139da4cb39 +SHA512 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/text.tgz) = 6cb69d7b7019a82cc1db4326cff681916eee736081c55e08d8a7ff163db75deb91ce2b6feed78fd5775224d3aa24d74d0ca594535447826c03f6613792c9871b +RMD160 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/text.tgz) = 85f073b017e79c9f8069912fe27ac96b7ad84cc8 +MD5 (NetBSD-6.0/evbsh3-sh3eb/binary/sets/text.tgz) = 72ac1c599c8f41bbe40cad9c17afb550 +SHA1 (NetBSD-6.0/evbsh3-sh3el/binary/kernel/netbsd-AP_MS104_SH4.bin.gz) = 156a43383fb461877ca595a24fe433c41bb53505 +SHA512 (NetBSD-6.0/evbsh3-sh3el/binary/kernel/netbsd-AP_MS104_SH4.bin.gz) = 74da9a5e48ac2fcc998176c4a8ae90f6d82e4269b071af2922210d23075c5c8b9b41ee63e9a4a7eddf5edb98a7b1ff32d07ea78a3b1ca95f533bc69a108ecb4b +RMD160 (NetBSD-6.0/evbsh3-sh3el/binary/kernel/netbsd-AP_MS104_SH4.bin.gz) = bb94e484f2bfba2253bc36a6724491e54d94739c +MD5 (NetBSD-6.0/evbsh3-sh3el/binary/kernel/netbsd-AP_MS104_SH4.bin.gz) = 02ffe820f66f7d380b2a35522ea3d438 +SHA1 (NetBSD-6.0/evbsh3-sh3el/binary/kernel/netbsd-AP_MS104_SH4.gz) = 0056d5cf3c88e73792a091ea2aea6ccdfa8ae908 +SHA512 (NetBSD-6.0/evbsh3-sh3el/binary/kernel/netbsd-AP_MS104_SH4.gz) = 678c13171474bc55453f9a69467b8d85365e6a61e371e212e6e03a75193170bbd033575a46450b11c31724e56eeae77991a225aca564f1e1ca27e625f0dca191 +RMD160 (NetBSD-6.0/evbsh3-sh3el/binary/kernel/netbsd-AP_MS104_SH4.gz) = 5303158d3acafe0290bbbbff80db24fb2ca0ec28 +MD5 (NetBSD-6.0/evbsh3-sh3el/binary/kernel/netbsd-AP_MS104_SH4.gz) = 30c622231e6b9daac8ed290bdeebd164 +SHA1 (NetBSD-6.0/evbsh3-sh3el/binary/kernel/netbsd-T_SH7706LAN.bin.gz) = 16ae6982b9df3f6eb4a035477fd951edb3d300af +SHA512 (NetBSD-6.0/evbsh3-sh3el/binary/kernel/netbsd-T_SH7706LAN.bin.gz) = c1ca446d125f788e8a155d7069247c3d63daf8ac9c99da2ad9f3b7d56e11b4491444f0ff0fdb2f4ff3722834d9e811f38621d4aa22d2f15434beb2d7033a0355 +RMD160 (NetBSD-6.0/evbsh3-sh3el/binary/kernel/netbsd-T_SH7706LAN.bin.gz) = 032c5396f55b50ad489e595c91c08b680d045154 +MD5 (NetBSD-6.0/evbsh3-sh3el/binary/kernel/netbsd-T_SH7706LAN.bin.gz) = 47885af19837e332b23aea912dd25c3c +SHA1 (NetBSD-6.0/evbsh3-sh3el/binary/kernel/netbsd-T_SH7706LAN.gz) = fbe844ab7e33356c35da0a05e841a4e01e4adfa0 +SHA512 (NetBSD-6.0/evbsh3-sh3el/binary/kernel/netbsd-T_SH7706LAN.gz) = abd3144c85d886bf6ed4be0315fe8a6f027d7c31be94d4252fc005c243abe8ac92de6fbb6a5459c0ead867de119ec83caaf6a078c6a6544dfc8c0a98661ed11a +RMD160 (NetBSD-6.0/evbsh3-sh3el/binary/kernel/netbsd-T_SH7706LAN.gz) = a2e21620fb48f5eac2314187bbafd65cfd80cbcc +MD5 (NetBSD-6.0/evbsh3-sh3el/binary/kernel/netbsd-T_SH7706LAN.gz) = c3681279fd8bb4637c6552ba2be82ea6 +SHA1 (NetBSD-6.0/evbsh3-sh3el/binary/kernel/netbsd-T_SH7706LSR.bin.gz) = 3abb9efd6ce8a3dc1fe36eda3e3544d40b8fadaa +SHA512 (NetBSD-6.0/evbsh3-sh3el/binary/kernel/netbsd-T_SH7706LSR.bin.gz) = 881ed27f7a5b433a6189fa71445db10f9525396c230b1c28a6bdaca291ac658ea15b479cb0bea31a9f1e97ce3d348ec10fbb590c46543a3beb0284b3b12cacfb +RMD160 (NetBSD-6.0/evbsh3-sh3el/binary/kernel/netbsd-T_SH7706LSR.bin.gz) = fae500b91381408aa48f2cbbd2f10ff4f7f10744 +MD5 (NetBSD-6.0/evbsh3-sh3el/binary/kernel/netbsd-T_SH7706LSR.bin.gz) = 5b3c31bbb5f5ef0a547728d1d38fe0ad +SHA1 (NetBSD-6.0/evbsh3-sh3el/binary/kernel/netbsd-T_SH7706LSR.gz) = e108054983abed92e290fb262e94a13afa9d9863 +SHA512 (NetBSD-6.0/evbsh3-sh3el/binary/kernel/netbsd-T_SH7706LSR.gz) = d7c0232734a6cca9d6e077da1b287dc2dbea5c195efd838de60a90121f3625b56978327fd28630d04249faf4f780a54a9154fdab5bf52226a1e7744d417d9d91 +RMD160 (NetBSD-6.0/evbsh3-sh3el/binary/kernel/netbsd-T_SH7706LSR.gz) = c1f2c381a07c03b405656f033475ca9faede3ba2 +MD5 (NetBSD-6.0/evbsh3-sh3el/binary/kernel/netbsd-T_SH7706LSR.gz) = 8c1c70f2f1a89d30184699d3a72d690f +SHA1 (NetBSD-6.0/evbsh3-sh3el/binary/sets/games.tgz) = 2040b4af557a62f2ade5fc9fcfe4cab3df88c7e2 +SHA512 (NetBSD-6.0/evbsh3-sh3el/binary/sets/games.tgz) = 8b5071337dc844042537c24c75660e61c9709cd10cbbeab059a84da6d482260b73365ff3870f85060c130a291b6f02be174d288127ca62ce4d291a6982192317 +RMD160 (NetBSD-6.0/evbsh3-sh3el/binary/sets/games.tgz) = 28acfa5a131d52df7c157e2edca1dd0f20e774dc +MD5 (NetBSD-6.0/evbsh3-sh3el/binary/sets/games.tgz) = d82c46dbc0021fd4694e464042936052 +SHA1 (NetBSD-6.0/evbsh3-sh3el/binary/sets/man.tgz) = 899b9d8242e983a5110ab755651c24f709b5af67 +SHA512 (NetBSD-6.0/evbsh3-sh3el/binary/sets/man.tgz) = 410999db110d710f4bb498c3d7ae7adc62170c7c2f470ce189c92f6c436c5ea96149659c631ef0b5605caaa025d97dfe1c07c428d86f51239657bd6b71717b15 +RMD160 (NetBSD-6.0/evbsh3-sh3el/binary/sets/man.tgz) = c1270f68c6d41b351877f71f0396ac34877dfc8d +MD5 (NetBSD-6.0/evbsh3-sh3el/binary/sets/man.tgz) = df4db2bbfa39ef6a4a215d949653d04a +SHA1 (NetBSD-6.0/evbsh3-sh3el/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/evbsh3-sh3el/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/evbsh3-sh3el/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/evbsh3-sh3el/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/evbsh3-sh3el/binary/sets/xcomp.tgz) = 53aa1e2a910e8eed09dc07f8b724804f53fe5e2f +SHA512 (NetBSD-6.0/evbsh3-sh3el/binary/sets/xcomp.tgz) = 24645da85419528015cdaefd0c835741fa801392e795b363bdfc39558e75e7f384511c0668d12e2440114b7c543c7532aaec438048f08d35c54c9c7a748f20c0 +RMD160 (NetBSD-6.0/evbsh3-sh3el/binary/sets/xcomp.tgz) = 60a461ffc1f1562274110d65c72a541ee131cd21 +MD5 (NetBSD-6.0/evbsh3-sh3el/binary/sets/xcomp.tgz) = f1d2650a8d7a4ecd60fda8e1aaf8c09b +SHA1 (NetBSD-6.0/evbsh3-sh3el/binary/sets/xetc.tgz) = 1636a6fe3e01f6d8a07a19cd204a6807c8caa4c7 +SHA512 (NetBSD-6.0/evbsh3-sh3el/binary/sets/xetc.tgz) = 9cea4ba4af287dd57e591d4269f2f2582010250316f323746ac56b12cefcf2590b93fbb0197c665f61b1df41dcca62d17fb6ad80d4b1feb8ac8265e91e15074f +RMD160 (NetBSD-6.0/evbsh3-sh3el/binary/sets/xetc.tgz) = 5f68e3f96f7bb9ae07fccdb1d058e4b1307b4b29 +MD5 (NetBSD-6.0/evbsh3-sh3el/binary/sets/xetc.tgz) = da84d97230787283e215a4ee1c4053ad +SHA1 (NetBSD-6.0/evbsh3-sh3el/binary/sets/xfont.tgz) = 97439ccf6840b18b1e9885f5504a401bf1a93650 +SHA512 (NetBSD-6.0/evbsh3-sh3el/binary/sets/xfont.tgz) = 3d15541f7d7ae2128f44355bf110415adfa4e5182829259d2c6f7a4217feff99e236d13c5bb7bbeb724ff1a09ac1f58f02bdd6eef528bc416ec3118db6fc7d45 +RMD160 (NetBSD-6.0/evbsh3-sh3el/binary/sets/xfont.tgz) = cdc9fcdb5fd5032803d5bba18db58f3ea6d62c85 +MD5 (NetBSD-6.0/evbsh3-sh3el/binary/sets/xfont.tgz) = a8466a0477c6c443eafe99e9d1c61131 +SHA1 (NetBSD-6.0/evbsh3-sh3el/binary/sets/base.tgz) = 125d939841f4c0d2d66af02a7cafcb788e62f49e +SHA512 (NetBSD-6.0/evbsh3-sh3el/binary/sets/base.tgz) = 768d8f497c4f735be3799406807852393df11f432b5cc9b1ec69ebe56953f1592a48794629c6cf556eb7bbfed2fd8c0c308b91ca9349256d28ce475a75c44ffb +RMD160 (NetBSD-6.0/evbsh3-sh3el/binary/sets/base.tgz) = 94a40312cf09aa8867a6dedb8cdb8b3fbdc00f76 +MD5 (NetBSD-6.0/evbsh3-sh3el/binary/sets/base.tgz) = 2f9a062d6116d6c89893fc2d0568521c +SHA1 (NetBSD-6.0/evbsh3-sh3el/binary/sets/comp.tgz) = b1c32d11d282303c29854fa152b78be77361dfcb +SHA512 (NetBSD-6.0/evbsh3-sh3el/binary/sets/comp.tgz) = 715ed5bd87827f3a84d78b28e855c28ea91944b02c1020551d1fa171239547c7b131f11149fae355ae75aae3059c1cbdbaefaa8a22e6daecf26dd045193bd424 +RMD160 (NetBSD-6.0/evbsh3-sh3el/binary/sets/comp.tgz) = 25c1503f1c807c8edb6521d85a26c45130b066e1 +MD5 (NetBSD-6.0/evbsh3-sh3el/binary/sets/comp.tgz) = 5b355abbc1cd023a56a5d91b06b00883 +SHA1 (NetBSD-6.0/evbsh3-sh3el/binary/sets/etc.tgz) = 9e2708dd9d1dfabdb39ed6979adb744ab09c72af +SHA512 (NetBSD-6.0/evbsh3-sh3el/binary/sets/etc.tgz) = c13a2812104b2f36cf94129d638cdffdd62bb86928eb1478306e205745ea5dc56038e40051da26a94cf56a25a6acd46c86cec2e4e04680715089dc8591d84e0c +RMD160 (NetBSD-6.0/evbsh3-sh3el/binary/sets/etc.tgz) = 741003e38321059470fcb7bd727ee4c05add965c +MD5 (NetBSD-6.0/evbsh3-sh3el/binary/sets/etc.tgz) = 474217b3b8eb1c86fba55ed465eb0bff +SHA1 (NetBSD-6.0/evbsh3-sh3el/binary/sets/modules.tgz) = a6704d748c69ac31bfc6277d625ba6ecce318deb +SHA512 (NetBSD-6.0/evbsh3-sh3el/binary/sets/modules.tgz) = ccccacf090cf2a8dcef8df2c43b99f188d6a8898d30546d2f69341819e9feac6f2fd92e0f14086c45e9afcd462a6e4320ef3fc13bde002f3c697094d2d98144e +RMD160 (NetBSD-6.0/evbsh3-sh3el/binary/sets/modules.tgz) = 68a529c0d25d89b79bc283b265fb5fd355328d2f +MD5 (NetBSD-6.0/evbsh3-sh3el/binary/sets/modules.tgz) = d7d56e99bb5ba43313e55abf65901ef0 +SHA1 (NetBSD-6.0/evbsh3-sh3el/binary/sets/tests.tgz) = 68b5f95807399dc8a592abdd911d015938152e1f +SHA512 (NetBSD-6.0/evbsh3-sh3el/binary/sets/tests.tgz) = 2798d89e86057ced5d3e12c7771db2e94a96bd6c09fb49ec5803a56d0c484ea0614a1ea6a8a8647ec4427ee34fc191968e9a4025ca1257d072adcd536bc7c3f2 +RMD160 (NetBSD-6.0/evbsh3-sh3el/binary/sets/tests.tgz) = 6a3f335d038da0dcb81227f0b909399ddecdb0c3 +MD5 (NetBSD-6.0/evbsh3-sh3el/binary/sets/tests.tgz) = 7de6b24e3df249a77cdc4c002259ef30 +SHA1 (NetBSD-6.0/evbsh3-sh3el/binary/sets/kern-AP_MS104_SH4.tgz) = 74f70ee0502eab199c5d1a5855698772627c4ac7 +SHA512 (NetBSD-6.0/evbsh3-sh3el/binary/sets/kern-AP_MS104_SH4.tgz) = 76656c9b809e842a7db95daa3a5210f845dbc1a6cc2c05dfcd2d31b4404178ab6c3f9dce8705c4c1f1841ee6d75121fec557ffe25660fa24b492e4ee3f4dde4d +RMD160 (NetBSD-6.0/evbsh3-sh3el/binary/sets/kern-AP_MS104_SH4.tgz) = d4e2fc853980b624a04b6a4f895a65ea99c3fa6f +MD5 (NetBSD-6.0/evbsh3-sh3el/binary/sets/kern-AP_MS104_SH4.tgz) = cbf232a6d90bbb23a2ff524dc95d0765 +SHA1 (NetBSD-6.0/evbsh3-sh3el/binary/sets/kern-T_SH7706LAN.tgz) = bd3d26a06d12126b4bcfd594ec43b5b1b2b141ad +SHA512 (NetBSD-6.0/evbsh3-sh3el/binary/sets/kern-T_SH7706LAN.tgz) = 7eaeccc298861c058298a99c1f77c4bdc201a4dd11704fa3033177412893e3934f4f6018ba26604c0da00d1544f610af3e606d40b647d25f4d758ebd3803e3f0 +RMD160 (NetBSD-6.0/evbsh3-sh3el/binary/sets/kern-T_SH7706LAN.tgz) = 802229436fd22dd4213b8ee964c06d0e264032cc +MD5 (NetBSD-6.0/evbsh3-sh3el/binary/sets/kern-T_SH7706LAN.tgz) = d0f7d8401f8a43421267722847806897 +SHA1 (NetBSD-6.0/evbsh3-sh3el/binary/sets/kern-T_SH7706LSR.tgz) = 07c0d72f0d893ce0812faf6c6a5c98d7b3b58035 +SHA512 (NetBSD-6.0/evbsh3-sh3el/binary/sets/kern-T_SH7706LSR.tgz) = 8c724d951a2492d879318720c6e768b86094ffbb935c6107ec0bc42fd225e45ec2ac301bd6bad4e2d8df1b59fdf10f0c68df542369ef57c2e2b4ab537b39efe4 +RMD160 (NetBSD-6.0/evbsh3-sh3el/binary/sets/kern-T_SH7706LSR.tgz) = ce3c2734ca7c81d61f7794add983ac3d40d6c0f1 +MD5 (NetBSD-6.0/evbsh3-sh3el/binary/sets/kern-T_SH7706LSR.tgz) = 9efdd97f65905080d86975228272f5ad +SHA1 (NetBSD-6.0/evbsh3-sh3el/binary/sets/text.tgz) = ec93765a5c45be2526dd74721c706cf2349cbcad +SHA512 (NetBSD-6.0/evbsh3-sh3el/binary/sets/text.tgz) = ca1d8ae749a5cae5b06f568bd4d6cfb9b0af76848cac05b3d6bd6e1bbecbf84a76213064de51cd4ffff3062b5ee039fb7a99b8336474b39110d298dde616a51f +RMD160 (NetBSD-6.0/evbsh3-sh3el/binary/sets/text.tgz) = 55c63f02b460a593dcca374f26d03b9595b6a20a +MD5 (NetBSD-6.0/evbsh3-sh3el/binary/sets/text.tgz) = a7d639318aac350f9f955f97035a8fd4 +SHA1 (NetBSD-6.0/evbsh3-sh3el/binary/sets/xbase.tgz) = 4cb422608de78100a7b3bb2113f334951a6d8602 +SHA512 (NetBSD-6.0/evbsh3-sh3el/binary/sets/xbase.tgz) = acbe1e8859d013a1756d97db9bb194d7ead04db13102f45437f1e3054308471ca2c2498cc0c60c4ac8f6431e58ccf7ad4bae62a9d8e2b9857689af4c0f637de2 +RMD160 (NetBSD-6.0/evbsh3-sh3el/binary/sets/xbase.tgz) = 94f03b6f83e22818d2c98c726a4065680049385a +MD5 (NetBSD-6.0/evbsh3-sh3el/binary/sets/xbase.tgz) = 7e4b59a51385b2d05aa15b0d98179e7c +SHA1 (NetBSD-6.0/evbsh3-sh3el/binary/sets/xserver.tgz) = 1423504dda963a794f5710462bd0e3b0ad2a23ba +SHA512 (NetBSD-6.0/evbsh3-sh3el/binary/sets/xserver.tgz) = 36e50002ccd00c6e945a3e9f49f3f210a3bdd5c493aad4932cb81d30ffcc22ab1d11403bfa04859153148bec4a1c57d6f8d2206dc8ee37dfb2ccb23914144c8c +RMD160 (NetBSD-6.0/evbsh3-sh3el/binary/sets/xserver.tgz) = 23d438695d917fcf7ece054eeea841fe02bf268c +MD5 (NetBSD-6.0/evbsh3-sh3el/binary/sets/xserver.tgz) = b526fe22ecba0abf60efad839e21f4d7 +SHA1 (NetBSD-6.0/evbsh3-sh3el/installation/instkernel/netbsd-AP_MS104_SH4_INSTALL.symbols.gz) = 1a3978b4d00f62cb2ff6277dcdbf79fa3f9bf2eb +SHA512 (NetBSD-6.0/evbsh3-sh3el/installation/instkernel/netbsd-AP_MS104_SH4_INSTALL.symbols.gz) = b504aaa9957cb2b08b5656c1c38e35697d38b3fb8f7fe2dcd2942bc0dcbf7d7fd6cfa1ebd79f536a8cb8e86eb1b69a3676afb3c01f9cdd50c2a61a8fa7f6fcb6 +RMD160 (NetBSD-6.0/evbsh3-sh3el/installation/instkernel/netbsd-AP_MS104_SH4_INSTALL.symbols.gz) = 48c1c3a15270f558fe3b30cbf745a790e51acff6 +MD5 (NetBSD-6.0/evbsh3-sh3el/installation/instkernel/netbsd-AP_MS104_SH4_INSTALL.symbols.gz) = e2e15163e4bae081865da32d01514e6f +SHA1 (NetBSD-6.0/evbsh3-sh3el/installation/instkernel/netbsd-AP_MS104_SH4_INSTALL.bin.gz) = 873515f4532952c89f5a9f6d91a3f7fa7f948490 +SHA512 (NetBSD-6.0/evbsh3-sh3el/installation/instkernel/netbsd-AP_MS104_SH4_INSTALL.bin.gz) = c19c7a649d4723f255d79005c6da3caa022857e7a7dfee1afdcaf7db9138d777eebec9a2715032e461ec10129403bbdbb25a5bde1eb84efc2a1e7dc044921149 +RMD160 (NetBSD-6.0/evbsh3-sh3el/installation/instkernel/netbsd-AP_MS104_SH4_INSTALL.bin.gz) = 18f832108e5af4f1db1314b3d619950f22660c32 +MD5 (NetBSD-6.0/evbsh3-sh3el/installation/instkernel/netbsd-AP_MS104_SH4_INSTALL.bin.gz) = 5c15217d997a48ae98f97ef5bc1d9f37 +SHA1 (NetBSD-6.0/evbsh3-sh3el/installation/instkernel/netbsd-AP_MS104_SH4_INSTALL.gz) = 86b21fd531bdc7e87b16064ae739b5dcb3c92e81 +SHA512 (NetBSD-6.0/evbsh3-sh3el/installation/instkernel/netbsd-AP_MS104_SH4_INSTALL.gz) = 4e2413b98a091922a7b468169345e4c5090b87264b7232105b0684c2511c78d44a0b0b72f9a8c4ed37bdfb1f24826f87347f883074225fcdd715cadbbf6e8b2b +RMD160 (NetBSD-6.0/evbsh3-sh3el/installation/instkernel/netbsd-AP_MS104_SH4_INSTALL.gz) = 882aff308401e9ef5a895233e0759a69840da2f7 +MD5 (NetBSD-6.0/evbsh3-sh3el/installation/instkernel/netbsd-AP_MS104_SH4_INSTALL.gz) = fa60323505d7a47e47b73dc44e394e47 +SHA1 (NetBSD-6.0/evbsh3-sh3el/installation/instkernel/netbsd-T_SH7706LAN_INSTALL.symbols.gz) = 349e56359f7f6dec8f0ae526b3a789516a9e4f88 +SHA512 (NetBSD-6.0/evbsh3-sh3el/installation/instkernel/netbsd-T_SH7706LAN_INSTALL.symbols.gz) = c1c075a4ac229add650e83aa77c6d7efe562793645fe7ca868234f53bd79a112f2198905255f0f03e8bdf7a2e44904146907aaf67da9e41652faa7014686ba08 +RMD160 (NetBSD-6.0/evbsh3-sh3el/installation/instkernel/netbsd-T_SH7706LAN_INSTALL.symbols.gz) = 6c87f32161c4c2d529cb6a8026cc481dd1d42139 +MD5 (NetBSD-6.0/evbsh3-sh3el/installation/instkernel/netbsd-T_SH7706LAN_INSTALL.symbols.gz) = b64153e036a04f448159999e4f96b863 +SHA1 (NetBSD-6.0/evbsh3-sh3el/installation/instkernel/netbsd-T_SH7706LAN_INSTALL.bin.gz) = 23b1af2b9b450007d33c9c68946d6650f8121077 +SHA512 (NetBSD-6.0/evbsh3-sh3el/installation/instkernel/netbsd-T_SH7706LAN_INSTALL.bin.gz) = 51a3cb3daaba5d099524325af6a4f32ed164bff6118e88c1e4a5f33ff8a69df456833e5a041396179660af053bd0d1c6a43b5f72ad524be4e61ae9e833222c99 +RMD160 (NetBSD-6.0/evbsh3-sh3el/installation/instkernel/netbsd-T_SH7706LAN_INSTALL.bin.gz) = e5bcd565add34239cf0c2083fad873dd12f4e13d +MD5 (NetBSD-6.0/evbsh3-sh3el/installation/instkernel/netbsd-T_SH7706LAN_INSTALL.bin.gz) = 54fde28b5da7660812ff14933dabc902 +SHA1 (NetBSD-6.0/evbsh3-sh3el/installation/instkernel/netbsd-T_SH7706LAN_INSTALL.gz) = 26f7c3703bac98f6350f5a2423f5d9df4a46bbb3 +SHA512 (NetBSD-6.0/evbsh3-sh3el/installation/instkernel/netbsd-T_SH7706LAN_INSTALL.gz) = a0a4afa1c58fe9ae74fc03a3780ce16d10f6f00ed6db84e713e2fa51d3b6fb697e281f412eed74d30206edf624ed3bb585b7706252cee2ea37b85de9ed7fe2e4 +RMD160 (NetBSD-6.0/evbsh3-sh3el/installation/instkernel/netbsd-T_SH7706LAN_INSTALL.gz) = 6e9be1eba2d6db27781fbcc035d794758b4dd444 +MD5 (NetBSD-6.0/evbsh3-sh3el/installation/instkernel/netbsd-T_SH7706LAN_INSTALL.gz) = d2d661e75be21be7987c548ee785236a +SHA1 (NetBSD-6.0/evbsh3-sh3el/installation/instkernel/netbsd-T_SH7706LSR_INSTALL.bin.gz) = 9f3fabe29ffe68e56430d35f894893491a16c169 +SHA512 (NetBSD-6.0/evbsh3-sh3el/installation/instkernel/netbsd-T_SH7706LSR_INSTALL.bin.gz) = 8ca978143e29fed1916beccb35493521ad70772cc7d4093dd2d2d0bee973e06275abd8167a072db9d79f28d2cba1394d7fd940baaf8d55c84622db60ecce735b +RMD160 (NetBSD-6.0/evbsh3-sh3el/installation/instkernel/netbsd-T_SH7706LSR_INSTALL.bin.gz) = 3ecea6d66ed1fc3adb83b5e68d7b5d03ee2ab8ca +MD5 (NetBSD-6.0/evbsh3-sh3el/installation/instkernel/netbsd-T_SH7706LSR_INSTALL.bin.gz) = 853aef3ffec3749a8e387c0b8cf9c183 +SHA1 (NetBSD-6.0/evbsh3-sh3el/installation/instkernel/netbsd-T_SH7706LSR_INSTALL.gz) = 5ea3158a1ddb01af1b0ad97d2788d1e70341faa6 +SHA512 (NetBSD-6.0/evbsh3-sh3el/installation/instkernel/netbsd-T_SH7706LSR_INSTALL.gz) = 9d2e7c9da144cc79317b2e40f737b09f5320b90c920d7927db332ed3638c68b5cfbdda3f8dbefcb74330e98bcd9163d9003666b842ef74aada7b2b609de25b1a +RMD160 (NetBSD-6.0/evbsh3-sh3el/installation/instkernel/netbsd-T_SH7706LSR_INSTALL.gz) = 1f2d464e7b2c50a3c33b0a7d2076ff44627e476d +MD5 (NetBSD-6.0/evbsh3-sh3el/installation/instkernel/netbsd-T_SH7706LSR_INSTALL.gz) = 79f028dbbb91d2c182523ef5d1a26b1e +SHA1 (NetBSD-6.0/evbsh3-sh3el/installation/instkernel/netbsd-T_SH7706LSR_INSTALL.symbols.gz) = e1393c12d538858fc67c3dbb850099d363802af8 +SHA512 (NetBSD-6.0/evbsh3-sh3el/installation/instkernel/netbsd-T_SH7706LSR_INSTALL.symbols.gz) = 1a2d80f70a65e38f036a652bcad7774bbc11df1ef51d96868c988dadd25e07c96c2c19d29095b8cebadc6460b2ed5fd141254313d8e3c3f968098cfc136a1b95 +RMD160 (NetBSD-6.0/evbsh3-sh3el/installation/instkernel/netbsd-T_SH7706LSR_INSTALL.symbols.gz) = 50d94667fa3c0d7f63e9a6e202967ca006f2f00d +MD5 (NetBSD-6.0/evbsh3-sh3el/installation/instkernel/netbsd-T_SH7706LSR_INSTALL.symbols.gz) = bd8daee983f82ce040f96f6f929f273d +SHA1 (NetBSD-6.0/ews4800mips/binary/kernel/netbsd-RAMDISK.symbols.gz) = 25a30d5745b993e2102a3786fe1a6f39f470ce45 +SHA512 (NetBSD-6.0/ews4800mips/binary/kernel/netbsd-RAMDISK.symbols.gz) = 2c6541b1f613443ffd5f7b331a19ec7e8426783232e3fa9241e621ed96ced5e030fcde14e27c1127e336d74f60e21908f2ff4240285df516a5315c37d5e39943 +RMD160 (NetBSD-6.0/ews4800mips/binary/kernel/netbsd-RAMDISK.symbols.gz) = 5736b4fd760d469af93d177f831ea83e63fcee43 +MD5 (NetBSD-6.0/ews4800mips/binary/kernel/netbsd-RAMDISK.symbols.gz) = f9ae07f7f20a790a2bba49ed48e9f50b +SHA1 (NetBSD-6.0/ews4800mips/binary/kernel/netbsd-GENERIC.gz) = 4c6d1486cc99844354d97e2b1b2ebd6fe061ecc6 +SHA512 (NetBSD-6.0/ews4800mips/binary/kernel/netbsd-GENERIC.gz) = 6f5e544688a50385b3c519e4929508d663e646457c832cd715d0e05ef5f1ef38a40206c90e95356e17cdef5eede141f10371abab306b534087afca9b65536061 +RMD160 (NetBSD-6.0/ews4800mips/binary/kernel/netbsd-GENERIC.gz) = 81246f09144ee348e548fa9b7cee0d410ec98f38 +MD5 (NetBSD-6.0/ews4800mips/binary/kernel/netbsd-GENERIC.gz) = c861b19c9c0ac6c97350564aebddbe77 +SHA1 (NetBSD-6.0/ews4800mips/binary/kernel/netbsd-RAMDISK.gz) = 95a9a9ba6a613ba5be0afdd1457f7243f01d7efd +SHA512 (NetBSD-6.0/ews4800mips/binary/kernel/netbsd-RAMDISK.gz) = 8a36cc3704bc474e9ca4542c8cedcf59dfb93b71a2a5ad44d4c605f059cc515742921eb6de4b64382735a09ae9a72c1fc14e08107480a5090f4319d196a304c3 +RMD160 (NetBSD-6.0/ews4800mips/binary/kernel/netbsd-RAMDISK.gz) = 5577d47f6a4429aef2e64789a3ea604718275d7c +MD5 (NetBSD-6.0/ews4800mips/binary/kernel/netbsd-RAMDISK.gz) = cc1a04eff2275ed68971e5799b9d8af9 +SHA1 (NetBSD-6.0/ews4800mips/binary/sets/man.tgz) = 899b9d8242e983a5110ab755651c24f709b5af67 +SHA512 (NetBSD-6.0/ews4800mips/binary/sets/man.tgz) = 410999db110d710f4bb498c3d7ae7adc62170c7c2f470ce189c92f6c436c5ea96149659c631ef0b5605caaa025d97dfe1c07c428d86f51239657bd6b71717b15 +RMD160 (NetBSD-6.0/ews4800mips/binary/sets/man.tgz) = c1270f68c6d41b351877f71f0396ac34877dfc8d +MD5 (NetBSD-6.0/ews4800mips/binary/sets/man.tgz) = df4db2bbfa39ef6a4a215d949653d04a +SHA1 (NetBSD-6.0/ews4800mips/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/ews4800mips/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/ews4800mips/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/ews4800mips/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/ews4800mips/binary/sets/kern-GENERIC.tgz) = 81a3b610f413d0a6be35c6de2b7047dc4dd1cbf3 +SHA512 (NetBSD-6.0/ews4800mips/binary/sets/kern-GENERIC.tgz) = c9716b08912af531dc5304baac333f34ddc0899bca52dc53185bc48d22217613c03533bed4d70faa01423f0a253d2d03ecc6e1c1704430b28eedaec74110cbab +RMD160 (NetBSD-6.0/ews4800mips/binary/sets/kern-GENERIC.tgz) = 5cd01bbebf5245014d265995f6f96e699dd4bad8 +MD5 (NetBSD-6.0/ews4800mips/binary/sets/kern-GENERIC.tgz) = 5a01f783440f099de1bd80cc3abeb52b +SHA1 (NetBSD-6.0/ews4800mips/binary/sets/base.tgz) = 7b4b71623002896a52c0a7c9efe856a0c95de7b1 +SHA512 (NetBSD-6.0/ews4800mips/binary/sets/base.tgz) = 97361d892e6c9618569c1022f7b2c2e3485cdf3f1db8b3da1fadd8051a9241dd8baae01c89ffc4b2209651df13be64e8121fa34e1e9373b877add6a4c497e72e +RMD160 (NetBSD-6.0/ews4800mips/binary/sets/base.tgz) = 93372c7049c0a931f1f408d764c3a25600944d7f +MD5 (NetBSD-6.0/ews4800mips/binary/sets/base.tgz) = 0ba9f6bb4c14ce56fb8b4c24d28c5b54 +SHA1 (NetBSD-6.0/ews4800mips/binary/sets/comp.tgz) = fb67d7d7410b3489167d90ac9eab8739d5981b69 +SHA512 (NetBSD-6.0/ews4800mips/binary/sets/comp.tgz) = 123e4214744b4b319f93de9443465a1185a755ad34053ef82ed74b5b859ab2ba08655528b98110f7b90973c2f6fe6cc4567d83117e215078819d5558e4795829 +RMD160 (NetBSD-6.0/ews4800mips/binary/sets/comp.tgz) = 2949a78034cb32eaf732d7127b21990ef697247e +MD5 (NetBSD-6.0/ews4800mips/binary/sets/comp.tgz) = 1eaf1d6e18c59de98043f4e477aef4d2 +SHA1 (NetBSD-6.0/ews4800mips/binary/sets/etc.tgz) = 9112e98e3b0e6214758b386e4d49dddff2c53fa8 +SHA512 (NetBSD-6.0/ews4800mips/binary/sets/etc.tgz) = f6e54b49bd6585c117474ca5a04c9efecebb63f9c074b5e81fc73bb8c4508d21695f8b6689aa518b0a156c1d0fc3653c5d7487e7f373c5eec679bd7d5b80bbc0 +RMD160 (NetBSD-6.0/ews4800mips/binary/sets/etc.tgz) = d797fc90bbdef32b5b9d024d4363acec2abbf787 +MD5 (NetBSD-6.0/ews4800mips/binary/sets/etc.tgz) = eb8800ef4e55b63b58066f1f85001efc +SHA1 (NetBSD-6.0/ews4800mips/binary/sets/games.tgz) = e4e2e655f93f3594f4db543839016077023fd1ab +SHA512 (NetBSD-6.0/ews4800mips/binary/sets/games.tgz) = 377f737cae00cc7d9ccc2eae825e68d08a9f6d09474f39294406699ff7d9ca5a0a4347004759b6da9e3a4fb46f3e7ea14c90183bd0ee983cd3625bafb1712e23 +RMD160 (NetBSD-6.0/ews4800mips/binary/sets/games.tgz) = 96e4da250eec674b1f3a795026593364798b6a7f +MD5 (NetBSD-6.0/ews4800mips/binary/sets/games.tgz) = cefe2cbb2de8304de93b3fdb34c664ec +SHA1 (NetBSD-6.0/ews4800mips/binary/sets/modules.tgz) = 5179ba1557042dd0edf4b0dcb43feeb51a51fd9c +SHA512 (NetBSD-6.0/ews4800mips/binary/sets/modules.tgz) = c1f026f1e1ef0dfb74347a9f846971ec05d9c9cd27d9480b4dca4105d7f87c39678c8c76557a8bec407b985087c2371f47856cb81912ccf0e8e219d8f2b1ba4f +RMD160 (NetBSD-6.0/ews4800mips/binary/sets/modules.tgz) = 8cacd504f4fce3b4547758a812d28fc41f1c29a4 +MD5 (NetBSD-6.0/ews4800mips/binary/sets/modules.tgz) = 17f5259f27b6b9e35e05d38e32a47bc7 +SHA1 (NetBSD-6.0/ews4800mips/binary/sets/tests.tgz) = 05f79c3300425fa9c41fb0f6d4b67bbd22143c43 +SHA512 (NetBSD-6.0/ews4800mips/binary/sets/tests.tgz) = 5202c4bf6086643686bf4fef3927bedb17262acba8c62bfad92db632d6b545a9ffba8eafbb237f8076beba9da3f496f2da068031745bbad9c042d84b954d7bc2 +RMD160 (NetBSD-6.0/ews4800mips/binary/sets/tests.tgz) = 7dceaf484da2d9856cbea453914309af8f75faff +MD5 (NetBSD-6.0/ews4800mips/binary/sets/tests.tgz) = 379a301eaec46b70599b92ff3d69e568 +SHA1 (NetBSD-6.0/ews4800mips/binary/sets/text.tgz) = 591abf75de4e52fa3c188ff87fe5fbf28f541766 +SHA512 (NetBSD-6.0/ews4800mips/binary/sets/text.tgz) = 0fa9434b5447025c84b3fccbf175b25fe975e88fe711126a9b0625fa070bcfc05c6c962dc59a57ecec38e97e85455911bdc59c411cb6ea9ba2232256191fea4b +RMD160 (NetBSD-6.0/ews4800mips/binary/sets/text.tgz) = 8ccae27fd5067d3e60148abc0751ed5cfb1fb10a +MD5 (NetBSD-6.0/ews4800mips/binary/sets/text.tgz) = 93c20890d37a4c4b7aacb3cdd534070c +SHA1 (NetBSD-6.0/ews4800mips/binary/sets/xbase.tgz) = 5516e5fd661a6aa8886689fbeab06f0d6ef315bc +SHA512 (NetBSD-6.0/ews4800mips/binary/sets/xbase.tgz) = 16f7b97341977b5b7d1629598d8cc250b0fd361f01b2b65afff93dcc97fcd81e3df2b20b42ef37902b64a20fa5a96c48407eac6f0faa8f6467bddfdfa6dcc975 +RMD160 (NetBSD-6.0/ews4800mips/binary/sets/xbase.tgz) = 55c47dd7eed35b436fb033ce22281a13d3c016fb +MD5 (NetBSD-6.0/ews4800mips/binary/sets/xbase.tgz) = 949eb603afb4e09b5c53facf3ffcba03 +SHA1 (NetBSD-6.0/ews4800mips/binary/sets/xcomp.tgz) = c20568ce72c1ab65b9b2b7d6063d4b330c67e0dd +SHA512 (NetBSD-6.0/ews4800mips/binary/sets/xcomp.tgz) = 5ce8a9f1749abed8c536fabd262ca65297d851a26dd108bf917171ae38dc82dda3ecc4315b5d532e8a393778ed566394c3b7a0cd4d8140f4e9ad275371360504 +RMD160 (NetBSD-6.0/ews4800mips/binary/sets/xcomp.tgz) = 138ba52cf36085ea08c8f9022fce482e2b119b1e +MD5 (NetBSD-6.0/ews4800mips/binary/sets/xcomp.tgz) = 9267462e8d885667f784d3e444574bab +SHA1 (NetBSD-6.0/ews4800mips/binary/sets/xetc.tgz) = 0b6040849347e71dc6694909b064c46858ef7267 +SHA512 (NetBSD-6.0/ews4800mips/binary/sets/xetc.tgz) = 94cf5fe5f971595d5e17d182aa5fd5cae717fb030336783ec18b34bc054da2b183c184e948b75dda13b1b31468bdadf228682c586e2c1687f4acca2c3545da04 +RMD160 (NetBSD-6.0/ews4800mips/binary/sets/xetc.tgz) = f90d3564bda34f368372300e7e0f1dbc716f0761 +MD5 (NetBSD-6.0/ews4800mips/binary/sets/xetc.tgz) = 08fbdb1532ed26f606faba4a71052f15 +SHA1 (NetBSD-6.0/ews4800mips/binary/sets/xfont.tgz) = 1c83cc716a88a16e480948fb712c55617dac4840 +SHA512 (NetBSD-6.0/ews4800mips/binary/sets/xfont.tgz) = b1913d99dc60c680f2fc82aa8d2ff0970cc7c5a712ca412445334cc2b6136993b6fc58c27aecf12d24455bd8ed5e434e4b6e7067b87f8df73960c5b090f4e624 +RMD160 (NetBSD-6.0/ews4800mips/binary/sets/xfont.tgz) = a079720a15cdc7659a8efc5a3ef574814993f517 +MD5 (NetBSD-6.0/ews4800mips/binary/sets/xfont.tgz) = 1ceec721c52139d9b94d42631fb45b5b +SHA1 (NetBSD-6.0/ews4800mips/binary/sets/xserver.tgz) = 5acda874d4e98472f3bde4d22ee5c76f8e63753d +SHA512 (NetBSD-6.0/ews4800mips/binary/sets/xserver.tgz) = 044bc28fb73dff4c2c50482adc2b69ec1b0b880b40ca25ea528be078b8f1d84e9e797b5238ea5ce0103aed54f5b32d0ff96ab67661156e28e9969aebe33a548b +RMD160 (NetBSD-6.0/ews4800mips/binary/sets/xserver.tgz) = df7ea47ab25dbe8529abb8f5dc1d49cd996d6cdc +MD5 (NetBSD-6.0/ews4800mips/binary/sets/xserver.tgz) = 20191a4f5c5a6cca80c760bfd8836183 +SHA1 (NetBSD-6.0/ews4800mips/installation/boot/boot-RAMDISK.gz) = c0d874d928968bc07c4378652d9df32f5ea0367b +SHA512 (NetBSD-6.0/ews4800mips/installation/boot/boot-RAMDISK.gz) = 2cfedab16bbb540c131f2518ed74ee2692d96d8a11d008a11279d4c4b95cdf52fb76baf81823e49d3037f1f5230c1194a473f9e0fd37b36025a14988f6e49de3 +RMD160 (NetBSD-6.0/ews4800mips/installation/boot/boot-RAMDISK.gz) = ee3f845cb765fca243be9bb84f17162c7a865304 +MD5 (NetBSD-6.0/ews4800mips/installation/boot/boot-RAMDISK.gz) = 42ccd2d2f905ccadd7497ccd4ff91996 +SHA1 (NetBSD-6.0/ews4800mips/installation/boot/boot) = df1c0cdcdea86e38dface2a89e2fe26dc7df108f +SHA512 (NetBSD-6.0/ews4800mips/installation/boot/boot) = 6007e2ed816488fc00fca543ab2541f5db95f7a6ad44d4dbde05f4a397fcbf667a41290f7fab5249d6a2f80870a6c04a6bf061d8a25c91b496cbb02d5699b29e +RMD160 (NetBSD-6.0/ews4800mips/installation/boot/boot) = d321a217c04aafeb530f5d3eb29954eda9fb5838 +MD5 (NetBSD-6.0/ews4800mips/installation/boot/boot) = f39fbdcdde61cea48a1e10e426480550 +SHA1 (NetBSD-6.0/ews4800mips/installation/boot/boot.coff) = e0b297b3888ffdfd4077e67124efa2444194cdc7 +SHA512 (NetBSD-6.0/ews4800mips/installation/boot/boot.coff) = 2c465d178b1c8b4688249410c55b6224b06436dc0b42f09028bd1ce7352c2542749a9e3b685b92f670d3401d6b3b207dfbbf549e19ba38bfe3522f09e08f9429 +RMD160 (NetBSD-6.0/ews4800mips/installation/boot/boot.coff) = 7e7161d03b7f04a55c35dfd8c34a2a5debed56c7 +MD5 (NetBSD-6.0/ews4800mips/installation/boot/boot.coff) = 6bc92c0ddea36ee0816580d8cce6167d +SHA1 (NetBSD-6.0/ews4800mips/installation/floppy/boot1.fs) = e706f91cc1733ab264473d3f1a887285ca79f013 +SHA512 (NetBSD-6.0/ews4800mips/installation/floppy/boot1.fs) = b946e58e4d1318d5be27e7bfc943b464309c02c63b936f3d11f57a519988d8847b172f30e2d61dad13bd672325dd2dc9ad502ddc5ed0dd49ca5583c1c51c1fed +RMD160 (NetBSD-6.0/ews4800mips/installation/floppy/boot1.fs) = 16d59bb5fd830cf9551e4184bc338b7395bef5f7 +MD5 (NetBSD-6.0/ews4800mips/installation/floppy/boot1.fs) = 1a09cfb0f06ab364b4a5b55754474310 +SHA1 (NetBSD-6.0/ews4800mips/installation/floppy/boot2.fs) = 73d13ad2676d8db24c4c53e59be5cd53a70e7dee +SHA512 (NetBSD-6.0/ews4800mips/installation/floppy/boot2.fs) = 4841e1aeb787ece67e3d172c2a614655746beab89f2b09a7566d36979b57d5793d0a308122182e1ca4e052257501f460d0e3d692ef701a1c869041b95e452c14 +RMD160 (NetBSD-6.0/ews4800mips/installation/floppy/boot2.fs) = 3fac30b411e6650a18a85afdca71695e7ecf2d4b +MD5 (NetBSD-6.0/ews4800mips/installation/floppy/boot2.fs) = 4f501c25c15a582ed08e3e211c040506 +SHA1 (NetBSD-6.0/ews4800mips/installation/floppy/boot3.fs) = 32e2072f8bcef77633e24ec29215c45d2a448c5e +SHA512 (NetBSD-6.0/ews4800mips/installation/floppy/boot3.fs) = 31f812f795fcecef8d5acf1511e0ccf8a498a51a199cef9384e4f197ecb28409fe9dfa7ccc66ea88fdcdfb7c11bbf2a908f3afda7aba16d4adbce172c48a291c +RMD160 (NetBSD-6.0/ews4800mips/installation/floppy/boot3.fs) = baa412f7b18b72d89a2f7468b5d10bf76aa1a437 +MD5 (NetBSD-6.0/ews4800mips/installation/floppy/boot3.fs) = e0a8da5b5ed80730a3c4ff8ec316f22b +SHA1 (NetBSD-6.0/ews4800mips/INSTALL.html) = a2b19549f5348d2f1d52980adce6b6dd1c5fa58c +SHA512 (NetBSD-6.0/ews4800mips/INSTALL.html) = f70a62de3ff88606a2193b8bf01036b6770079bc8e5c7912c82e223d81671f8e2bc6dddbcd1022fce4352bccee3a1c19c90a2b1fa72bd12bf7edcf4dd42fb101 +RMD160 (NetBSD-6.0/ews4800mips/INSTALL.html) = 500263b32d3fd4f6459496b7e9d250d0d048c79c +MD5 (NetBSD-6.0/ews4800mips/INSTALL.html) = a341d2e552eea54e2887ab795e752d24 +SHA1 (NetBSD-6.0/ews4800mips/INSTALL.more) = 112fc313673a7ec94f1c6a7ab3ba79d232e0b866 +SHA512 (NetBSD-6.0/ews4800mips/INSTALL.more) = 61df394591fc7b7554c82ced0edec2bd62e7a7e98e0203cc908c6fa48f961062a42148b856f2046f9a3d5262de7d7cc392c15e346b0bea8ec5ef2717760dc30f +RMD160 (NetBSD-6.0/ews4800mips/INSTALL.more) = e92e60dd50dfc2ed354ed18f01cd412f62257367 +MD5 (NetBSD-6.0/ews4800mips/INSTALL.more) = f6ff574342525c12f5e039e524ab23cf +SHA1 (NetBSD-6.0/ews4800mips/INSTALL.ps) = a5e622805b2d9d7f96b2aae0b819b7607335d8fc +SHA512 (NetBSD-6.0/ews4800mips/INSTALL.ps) = c8cfeb73d5c4f033877795597dc9edd1dab7902a9753b09127bd9e1875d55ead42746d06b3b31b6ddecc19d876495201736b9ef6c242c357d0bca6d74aac9dc3 +RMD160 (NetBSD-6.0/ews4800mips/INSTALL.ps) = 07d50c1fde4cd58f0db754495c39509f69e1dbbe +MD5 (NetBSD-6.0/ews4800mips/INSTALL.ps) = 831c1f71243c24726c508a45dfa97dbc +SHA1 (NetBSD-6.0/ews4800mips/INSTALL.txt) = 6528e1b0d61bf2daab21a1ad8b36dfaf56ef8289 +SHA512 (NetBSD-6.0/ews4800mips/INSTALL.txt) = f2f1d34cc0d64c9764604de75197554e49095f305042d0d729da16a0a8edfa4792ce647d3321072af4c1980367270b7097275b32bcacf841409ba4eaa6e97edd +RMD160 (NetBSD-6.0/ews4800mips/INSTALL.txt) = 5311f44e35a9074f47aec723c579e2c04e9928ea +MD5 (NetBSD-6.0/ews4800mips/INSTALL.txt) = 1e6dfee2b6a42e87aa56dbf9f345174c +SHA1 (NetBSD-6.0/hp300/binary/kernel/netbsd-RAMDISK.symbols.gz) = 3e4f61e16b7b76ffbda7ab2b2826ed6e47f55cac +SHA512 (NetBSD-6.0/hp300/binary/kernel/netbsd-RAMDISK.symbols.gz) = 7c0389792e3d8722cd6187619978b413194ec8aebc17fab04ea75f37207c1c74bcf6f44a70beb5ca6712382b745d37d6e1ea3c87e1e93cf03c5891b583f5b513 +RMD160 (NetBSD-6.0/hp300/binary/kernel/netbsd-RAMDISK.symbols.gz) = 94f4e2e55d48069e13e05c43ee7688999a9d8488 +MD5 (NetBSD-6.0/hp300/binary/kernel/netbsd-RAMDISK.symbols.gz) = a1f4d88bc66a8924f563b00b4c194823 +SHA1 (NetBSD-6.0/hp300/binary/kernel/netbsd-GENERIC.gz) = 70a5a051fb4b94008c3598cf7432e40048ac15b5 +SHA512 (NetBSD-6.0/hp300/binary/kernel/netbsd-GENERIC.gz) = 342651536f367f4adcae4435afd623af0818e56362ba8f8c9376b49a0f2c57af2ca568edd32954744792904aa1fdf98392d398d75b5c8cc4f30ac456fdedb62d +RMD160 (NetBSD-6.0/hp300/binary/kernel/netbsd-GENERIC.gz) = ce09eea6cbeaf12e2fcd4aabcdb2047e48c686ac +MD5 (NetBSD-6.0/hp300/binary/kernel/netbsd-GENERIC.gz) = d1b8cd8ebde9c0bf97177f7cc8615bbf +SHA1 (NetBSD-6.0/hp300/binary/kernel/netbsd-RAMDISK.gz) = 653c4beb8dc20a0c8d66e9cee85225fc221b5e8e +SHA512 (NetBSD-6.0/hp300/binary/kernel/netbsd-RAMDISK.gz) = 62259ecdcaf08723230e0fcd0c9738fa3b4e42954e114146a7bfc11ab775adf2c36a7924fc9532ffeb5b50da52c9789162b56fd991511922a074f109edf22212 +RMD160 (NetBSD-6.0/hp300/binary/kernel/netbsd-RAMDISK.gz) = 634dcaef5fd936621863005e583978fff3f4638c +MD5 (NetBSD-6.0/hp300/binary/kernel/netbsd-RAMDISK.gz) = b4cfe5ee1d9fcffa55595ceceb2cf7dd +SHA1 (NetBSD-6.0/hp300/binary/sets/games.tgz) = 16ee93ea4d5fac2fb28fad5c32c8a3d57d011d79 +SHA512 (NetBSD-6.0/hp300/binary/sets/games.tgz) = a7f49ab72f50273f66c8dcf408b57ec4668debd5537c5bd0ec59aa0f4fa1d599ba0798d1b283315c4208cbcb608925808ce003b1ade79034886edb8208f9f48d +RMD160 (NetBSD-6.0/hp300/binary/sets/games.tgz) = 1e09d99d7fe2e495763f05919472d27a4ba699df +MD5 (NetBSD-6.0/hp300/binary/sets/games.tgz) = 8a26f3e864444209088bccf21419a616 +SHA1 (NetBSD-6.0/hp300/binary/sets/man.tgz) = 899b9d8242e983a5110ab755651c24f709b5af67 +SHA512 (NetBSD-6.0/hp300/binary/sets/man.tgz) = 410999db110d710f4bb498c3d7ae7adc62170c7c2f470ce189c92f6c436c5ea96149659c631ef0b5605caaa025d97dfe1c07c428d86f51239657bd6b71717b15 +RMD160 (NetBSD-6.0/hp300/binary/sets/man.tgz) = c1270f68c6d41b351877f71f0396ac34877dfc8d +MD5 (NetBSD-6.0/hp300/binary/sets/man.tgz) = df4db2bbfa39ef6a4a215d949653d04a +SHA1 (NetBSD-6.0/hp300/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/hp300/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/hp300/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/hp300/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/hp300/binary/sets/xbase.tgz) = ffc6dc889560371042dd12a5486a9a2c499b86a9 +SHA512 (NetBSD-6.0/hp300/binary/sets/xbase.tgz) = 9aa2ba4d703a13020acf8543d1efcde76b6f0f4b411be20f804709b3802e537be1e651eba469830c4fd4777a379ea9936200a3a3eb4b1a702c04bb81aafcc723 +RMD160 (NetBSD-6.0/hp300/binary/sets/xbase.tgz) = 3ecf53e7414ef859a47fe5afc108cf3bfa82fb1d +MD5 (NetBSD-6.0/hp300/binary/sets/xbase.tgz) = a6af002ce158cf72eb5c6a7cde2c0989 +SHA1 (NetBSD-6.0/hp300/binary/sets/kern-GENERIC.tgz) = 7ab2f7be438f52926aee3c94e07951b7eb288775 +SHA512 (NetBSD-6.0/hp300/binary/sets/kern-GENERIC.tgz) = a4fdc0d2604b8f00790d8a3766bca90391cde8f0f564b7409738f151355f2bc1bc512a25629ee45ba7321a8791f983dda206124a7280ab082f7b255d50b57df2 +RMD160 (NetBSD-6.0/hp300/binary/sets/kern-GENERIC.tgz) = 85283b11855a8e69be87b21678328f4a675ca02e +MD5 (NetBSD-6.0/hp300/binary/sets/kern-GENERIC.tgz) = 64374db1afce82099588ba9afc920440 +SHA1 (NetBSD-6.0/hp300/binary/sets/base.tgz) = 06b4b615865b0d72c01ca5676c7755af13eaec39 +SHA512 (NetBSD-6.0/hp300/binary/sets/base.tgz) = 326b28bb808cfc55a3f25766ba747483c7b1ec585b56ef8deaabbb62e3a6adbee3af61eeadf34ea1b6ff41a379e267bfea7516ee2bd80684e3228913c11f771f +RMD160 (NetBSD-6.0/hp300/binary/sets/base.tgz) = e1bffbda1eb605d10b7eb6e607971d53ba6bf26a +MD5 (NetBSD-6.0/hp300/binary/sets/base.tgz) = 23ecb1b54aa4c4f5d8a3217a1ef01ca0 +SHA1 (NetBSD-6.0/hp300/binary/sets/comp.tgz) = 3031c0b6b9903720a6b1fe865c366faf35e35af9 +SHA512 (NetBSD-6.0/hp300/binary/sets/comp.tgz) = 37ec2ee919d9d087dd0690cfce76d6be60abc618c3939ab32941ee6c0990c9d5de75f0035f56d2c501d0c5f6e016098bacd502eeaf0849c091dff2ec1ec52cb4 +RMD160 (NetBSD-6.0/hp300/binary/sets/comp.tgz) = 2b934c679fb8e8c0f79a2dcec65e9ffb1ee3477f +MD5 (NetBSD-6.0/hp300/binary/sets/comp.tgz) = 5db470910b6991bd50d1003122e50bec +SHA1 (NetBSD-6.0/hp300/binary/sets/etc.tgz) = 6f8edda4999c8a4343fc2bc279241b9550ea490c +SHA512 (NetBSD-6.0/hp300/binary/sets/etc.tgz) = 562d88456cedf5e071d8fa1d93a8dce22f687ffdac77354129d67db4f701cae1af8108a27d9bbd3fae6035f29cea3438d08954e4e784e0a4a103bbc97362179d +RMD160 (NetBSD-6.0/hp300/binary/sets/etc.tgz) = 924ef5e6623a78f068d2be3eb41d7acd6dc767d4 +MD5 (NetBSD-6.0/hp300/binary/sets/etc.tgz) = 21fd073754ac797a337928786b03c811 +SHA1 (NetBSD-6.0/hp300/binary/sets/modules.tgz) = 83594fc109e081cdb189cc607f9f0e2bdbd17149 +SHA512 (NetBSD-6.0/hp300/binary/sets/modules.tgz) = 0741d29e6d7a9ab7bdcd0f7d24cfdce277787bb4e4677035222b34a66570a245279b257b1adb1a0e174af3009ba8f54db7801238b754365efee73af0c1aedef7 +RMD160 (NetBSD-6.0/hp300/binary/sets/modules.tgz) = bdf66666ad75847756c3fc123fdcc44ce959e1af +MD5 (NetBSD-6.0/hp300/binary/sets/modules.tgz) = 28892a09bb10b455457f5f581f57f2f0 +SHA1 (NetBSD-6.0/hp300/binary/sets/tests.tgz) = a5ef542440872976bdd13a62aefa0d14d61c26c0 +SHA512 (NetBSD-6.0/hp300/binary/sets/tests.tgz) = c3f7eec4bdf7dee4746ce7c6f234fb0fd98b97cf4d8eaf6b3ac2f90c3e9ca5cb8cdf35427310135ff7e90f81f584ac3e42c5e7ccfdf2de03c07bca5b5768e078 +RMD160 (NetBSD-6.0/hp300/binary/sets/tests.tgz) = 1088670cc9cf63a9232b07ead39467b939007ec5 +MD5 (NetBSD-6.0/hp300/binary/sets/tests.tgz) = afa98cf6d10be6bd60a4122ad26f69b6 +SHA1 (NetBSD-6.0/hp300/binary/sets/text.tgz) = 34cbcecdf88d3b20397c210adaef51a7aeebdbf1 +SHA512 (NetBSD-6.0/hp300/binary/sets/text.tgz) = 9718fde476237be7d04c9e3bc0fef0ac97fe275d6c98cc58f42e4266a7501b8a95e0edf8b46e1a33b4aef67222731978be2fe427d52993a0fc8ea30185411c5c +RMD160 (NetBSD-6.0/hp300/binary/sets/text.tgz) = c96e584c3615a0f4e9eb12a8542b0fa8e60e1f1f +MD5 (NetBSD-6.0/hp300/binary/sets/text.tgz) = 3dc6892231a62bff94ab46648015667f +SHA1 (NetBSD-6.0/hp300/binary/sets/xcomp.tgz) = 55de1ba9512bb95b3678c1569840e740e6f5b556 +SHA512 (NetBSD-6.0/hp300/binary/sets/xcomp.tgz) = 83011012f7ce5cd11e58e12f068cfbb5ee4987d40aeae1026503899cdb9d5cf4d4edd6497b2ef0a3e75894d6bcf962fc3492572b51a505fae38ce9d12e4dc36b +RMD160 (NetBSD-6.0/hp300/binary/sets/xcomp.tgz) = d696a85c3da7325eb570111f63f9d3517d47572f +MD5 (NetBSD-6.0/hp300/binary/sets/xcomp.tgz) = 5729b37859a9265fbbfe184d66daaa9b +SHA1 (NetBSD-6.0/hp300/binary/sets/xetc.tgz) = 64f0dab5e32092b4ea7dc9352efd06fd648f5f4b +SHA512 (NetBSD-6.0/hp300/binary/sets/xetc.tgz) = 6fdac8545bf826d9a263cef4354914842986159aae07cd49ffbdda2cefeff6906f3f369141e0f54a213f4530b34160ac420c91c0fa9638354f244c1a625c8ffe +RMD160 (NetBSD-6.0/hp300/binary/sets/xetc.tgz) = b1167b7794746ee9e9828f6b5d3a34efee1e0fe4 +MD5 (NetBSD-6.0/hp300/binary/sets/xetc.tgz) = fd2d95f88081017c690d585af9cb52fa +SHA1 (NetBSD-6.0/hp300/binary/sets/xfont.tgz) = 7ff182435282d7ae2377257437bf5f2ead69bf6a +SHA512 (NetBSD-6.0/hp300/binary/sets/xfont.tgz) = aec8b80b466469fd5ab3d851f46cdeccb90b708401d15bd97301001640888b1d6cb50d4b5df95e95516e74e2b644e9b940be085ecd174a7b165ec6557b15fd40 +RMD160 (NetBSD-6.0/hp300/binary/sets/xfont.tgz) = 1de0aef2c305fd7dd1ed69d5c14ada0f1b709bc7 +MD5 (NetBSD-6.0/hp300/binary/sets/xfont.tgz) = cc29580d8a56cca694e732c04ec99480 +SHA1 (NetBSD-6.0/hp300/binary/sets/xserver.tgz) = 2c9dda0fd8c1e7212d505f36e5c89ad2468efe52 +SHA512 (NetBSD-6.0/hp300/binary/sets/xserver.tgz) = 412e82089215b7a52c4fd12ad4df99d3c2a0ed39207e41b102163ae7a627fd765f6b3b93cf0d197d2122d50a2196f17ff1bcfbdcc99c44f03e4b4cc80ee95455 +RMD160 (NetBSD-6.0/hp300/binary/sets/xserver.tgz) = 133cec24a054a44d8137770ae19faeae2d454a43 +MD5 (NetBSD-6.0/hp300/binary/sets/xserver.tgz) = 5f4ca5d0340f3616df2a4514e9bee2e3 +SHA1 (NetBSD-6.0/hp300/installation/miniroot/miniroot.fs.gz) = 2bffdc8e8f2ad0c26c428349eb4e04adcaaaf0da +SHA512 (NetBSD-6.0/hp300/installation/miniroot/miniroot.fs.gz) = 6a9135af4681c6b56877b2beff8a5e3e5bd2ae07283f1c78ad2b52d7c56db82779daf57c8c1939aba1dbab03be129372a2d1255f7c23692f548d684bcab2825f +RMD160 (NetBSD-6.0/hp300/installation/miniroot/miniroot.fs.gz) = f81c0d294b7e481ea7f881e4ee89dfe9090e30bd +MD5 (NetBSD-6.0/hp300/installation/miniroot/miniroot.fs.gz) = 6e487378f7e4b0cff281e3d2270e0a80 +SHA1 (NetBSD-6.0/hp300/installation/misc/HP-IB.geometry) = 1f0f75de1ee7d8e3181a5d6aa66773677755a884 +SHA512 (NetBSD-6.0/hp300/installation/misc/HP-IB.geometry) = 92d43dab00d4075e373ef3bb391cbfc404778b79b12da342eecc67a3c1a6cd1bcdf6da79ce48dc7262fe8b7d58f62317d4c2175ae67e3b7c69bdab6708509e50 +RMD160 (NetBSD-6.0/hp300/installation/misc/HP-IB.geometry) = c98d08dbec0a38097b07350201358ce795207abb +MD5 (NetBSD-6.0/hp300/installation/misc/HP-IB.geometry) = 5d37ef7fbd5c7cf0fc9be6ca42e13766 +SHA1 (NetBSD-6.0/hp300/installation/misc/SYS_INST) = a49379b1d8420e60551f6255fef597495bfa6ed1 +SHA512 (NetBSD-6.0/hp300/installation/misc/SYS_INST) = 6c56496dbd3c76c120c9b4acec61a2e91bce64c9c640cc7d2d1aeb7865f57aff311b71526e82eae87b92d5938ce56264d427dfa02b434ce1859ff179e64cfb6f +RMD160 (NetBSD-6.0/hp300/installation/misc/SYS_INST) = 827a7056af385da9b3d3adaea74d39e819dc0041 +MD5 (NetBSD-6.0/hp300/installation/misc/SYS_INST) = f396854e44d13f00a55e32217d907781 +SHA1 (NetBSD-6.0/hp300/installation/misc/SYS_UBOOT) = 2939db5d57267e58c09ce33be7a91e4842cd8152 +SHA512 (NetBSD-6.0/hp300/installation/misc/SYS_UBOOT) = d609c8e747839742255b0826d0024adb2c9fd6b454e4ab6af71f371c2e437fea20f74eaeec52446d1eeff113edb7a4335a435bd9493d4356f2c6fdabfff6a99b +RMD160 (NetBSD-6.0/hp300/installation/misc/SYS_UBOOT) = 94935b4c88578641336c28fca15951e613869a4d +MD5 (NetBSD-6.0/hp300/installation/misc/SYS_UBOOT) = ca853b39c14fb1cf61fb9a8291e86c0f +SHA1 (NetBSD-6.0/hp300/INSTALL.html) = 8e1c3fbcbc18743ea7a5e551efdb53f84615c5f6 +SHA512 (NetBSD-6.0/hp300/INSTALL.html) = 03450311591c740dd9a59f7d59c82d347f216141a7d297b2aceec341ba73afaa39fe7a97c7d929e93e48db1a38d3e8e82fd5df6036ca1387a9fdcb67e5f1860e +RMD160 (NetBSD-6.0/hp300/INSTALL.html) = 74b4c33c7bdf6739b4fab6d95811c4a6e705f441 +MD5 (NetBSD-6.0/hp300/INSTALL.html) = b432699922bc91b44886f23df7cf19f3 +SHA1 (NetBSD-6.0/hp300/INSTALL.more) = 1cf75d206beed7a64d40e96fbe895f74a70d1f16 +SHA512 (NetBSD-6.0/hp300/INSTALL.more) = d4ba1700ff39cce32ce327e810d4e87d40d942209a323beee44697e44e541acb0fe44e66d16277a0cda05cbebd0051e6c7573269868b1e7574e6645c678449ff +RMD160 (NetBSD-6.0/hp300/INSTALL.more) = 89b542e3ef218607f3e65413c3965b7f2333187f +MD5 (NetBSD-6.0/hp300/INSTALL.more) = 624bd59da093361cdaaab5c1de5cecba +SHA1 (NetBSD-6.0/hp300/INSTALL.ps) = 382b1bee832f5d64618348011bbafa088821422f +SHA512 (NetBSD-6.0/hp300/INSTALL.ps) = d986b290afd180501692aca87592c0c71f4a79a2ab774b4b5f28a2fec714547732964125e11ac047afdabbe5f2aec9c44c40d4abbe064716368d012c88a696e6 +RMD160 (NetBSD-6.0/hp300/INSTALL.ps) = 484e2cd1d11eccb452fe023cf442225f60381c75 +MD5 (NetBSD-6.0/hp300/INSTALL.ps) = 532f28fb7f53079a80b851a5ada9cdf5 +SHA1 (NetBSD-6.0/hp300/INSTALL.txt) = 5f6a19f1fcbe957565baf1fae076513a127af37c +SHA512 (NetBSD-6.0/hp300/INSTALL.txt) = 39744f1a32fa5869dac98bdf458d4c43b55857ea7881f3f66e437c496840707fe2a587be8c38bf1d61593c7d3603d231df56f8110be97a65f6a551d4aa75c1f0 +RMD160 (NetBSD-6.0/hp300/INSTALL.txt) = 026e4872a0fc52ba4d08907a6907cc72a814c577 +MD5 (NetBSD-6.0/hp300/INSTALL.txt) = 025fee7db55908a9ba7a358d3598a074 +SHA1 (NetBSD-6.0/hp700/binary/kernel/netbsd-RAMDISK.symbols.gz) = 3b574a0a7fa12dccfe7ec7a74f3c6d44b3de73d8 +SHA512 (NetBSD-6.0/hp700/binary/kernel/netbsd-RAMDISK.symbols.gz) = 3de19c62127f98cc12b223d296bf8c69c262c7cc79e4eb4975eb313c96882f4df8d8bc0ff64a7c57b7e7d30896b49935c5475203a369a8f2e134622dcc29d3cd +RMD160 (NetBSD-6.0/hp700/binary/kernel/netbsd-RAMDISK.symbols.gz) = 9c58c704e1a31f946467144840d8eeb207137fbb +MD5 (NetBSD-6.0/hp700/binary/kernel/netbsd-RAMDISK.symbols.gz) = de4a876f7ef0c5aa9c566e4f976723c5 +SHA1 (NetBSD-6.0/hp700/binary/kernel/netbsd-GENERIC.gz) = b9b1dddb8855998b36022d03cc9c49ce5e6ed212 +SHA512 (NetBSD-6.0/hp700/binary/kernel/netbsd-GENERIC.gz) = 39bcd475712ece695379203c3ec20e2bada75f8b6b6c6f8f80a8826c65ff112a6e2cc8e8c18a5547fa4fa2e2bb7704d6f5b303b2c600f05cadd9dff1da997904 +RMD160 (NetBSD-6.0/hp700/binary/kernel/netbsd-GENERIC.gz) = 0b67d5990ab7491b64a591e99053470eadcb13a6 +MD5 (NetBSD-6.0/hp700/binary/kernel/netbsd-GENERIC.gz) = 2090d459fd5d513c070c401d72b3ca74 +SHA1 (NetBSD-6.0/hp700/binary/kernel/netbsd-RAMDISK.gz) = 38bb542016466c8e1a7c8535520729cc5b9726b8 +SHA512 (NetBSD-6.0/hp700/binary/kernel/netbsd-RAMDISK.gz) = 49d747023260ee1b61b59e0a14ff413c97b1daaf5cc20ae916b42d83b99f7438465afed77185c7ef0154ac762edfa93acc8733574fed66e68b58db11c34ce72f +RMD160 (NetBSD-6.0/hp700/binary/kernel/netbsd-RAMDISK.gz) = 268e5e4322fb04246e0a1f8df5788e8530cb88c7 +MD5 (NetBSD-6.0/hp700/binary/kernel/netbsd-RAMDISK.gz) = 4175ca432943eb0d4cae87e5eafd3316 +SHA1 (NetBSD-6.0/hp700/binary/sets/man.tgz) = 899b9d8242e983a5110ab755651c24f709b5af67 +SHA512 (NetBSD-6.0/hp700/binary/sets/man.tgz) = 410999db110d710f4bb498c3d7ae7adc62170c7c2f470ce189c92f6c436c5ea96149659c631ef0b5605caaa025d97dfe1c07c428d86f51239657bd6b71717b15 +RMD160 (NetBSD-6.0/hp700/binary/sets/man.tgz) = c1270f68c6d41b351877f71f0396ac34877dfc8d +MD5 (NetBSD-6.0/hp700/binary/sets/man.tgz) = df4db2bbfa39ef6a4a215d949653d04a +SHA1 (NetBSD-6.0/hp700/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/hp700/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/hp700/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/hp700/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/hp700/binary/sets/kern-GENERIC.tgz) = a7b11dacf977418c4a57b400530c123c99447a66 +SHA512 (NetBSD-6.0/hp700/binary/sets/kern-GENERIC.tgz) = 071f2e512f843bd91f68e757682e5414600220833b8269be06956d29e61f0383a5f187bdf9a9414a8d64edc6ed9808c8df468fabca174f9079954991c6582300 +RMD160 (NetBSD-6.0/hp700/binary/sets/kern-GENERIC.tgz) = be81b5bc0509f3c9a10888b8f7fac2982871320a +MD5 (NetBSD-6.0/hp700/binary/sets/kern-GENERIC.tgz) = 313aa8cbee11f72da2bb608cb35f7a29 +SHA1 (NetBSD-6.0/hp700/binary/sets/base.tgz) = 4cc8adc7171679140335cc44ecc8f4f338f47ba5 +SHA512 (NetBSD-6.0/hp700/binary/sets/base.tgz) = 48e68c7d28cbc15733f8677d7d139897350c389f7032e78e06d6cbb8b9debc09bde2aa52e7226ef58660da81c238e960e5794689a3f3e19f5eca40f532117542 +RMD160 (NetBSD-6.0/hp700/binary/sets/base.tgz) = 3582b7f0c2852854cccad70a2e8f372a7acf0369 +MD5 (NetBSD-6.0/hp700/binary/sets/base.tgz) = f8166ed58eec05489e3857d9e09469ad +SHA1 (NetBSD-6.0/hp700/binary/sets/comp.tgz) = d9f4674db21772a521c5eb24e5fbe4ae2656c5d6 +SHA512 (NetBSD-6.0/hp700/binary/sets/comp.tgz) = caa488b17380cc2cc8f35ed9703bcac5c778fd597f8f607b26328c58b6b64dec7a784b22335a5c144f31fddf6d03a67d0f2c473ed7498e4f1ada17570f2893aa +RMD160 (NetBSD-6.0/hp700/binary/sets/comp.tgz) = b625cf9eaa395a2844cea44b1904ce9358c862b8 +MD5 (NetBSD-6.0/hp700/binary/sets/comp.tgz) = 07a825a8852f558425856a06e5677bfd +SHA1 (NetBSD-6.0/hp700/binary/sets/etc.tgz) = 0576313db33f67f3208c996a1819d19b5f0bd2e3 +SHA512 (NetBSD-6.0/hp700/binary/sets/etc.tgz) = 4d1eb5b04fd24f34112c49829b68ea0b7c841fc8b465e363ed4e79d58cd448ddcc6a493bae49cc9a4a4e9bb92314ddc032c5ed060f48b6de60e5045e981809af +RMD160 (NetBSD-6.0/hp700/binary/sets/etc.tgz) = eedfb6a8724ef33f4bc3ef4e08c1ec6f868d548b +MD5 (NetBSD-6.0/hp700/binary/sets/etc.tgz) = 8c95ad14875e9a87428ac7f6cf3a944e +SHA1 (NetBSD-6.0/hp700/binary/sets/games.tgz) = 1be2d6b3d863032e376b31b2b4489a65acd09d94 +SHA512 (NetBSD-6.0/hp700/binary/sets/games.tgz) = 322569b0060cc67b16d15a79b8c813e548ea4908ec18fdb91472a4ac5b03bc8abcbba2e5bfed3ed400cbc84ecc82a5edf087f54c06bc682c276a15b516f4dacd +RMD160 (NetBSD-6.0/hp700/binary/sets/games.tgz) = b4d4f8cbddbca828beadbd87ef4f20f1b23d7421 +MD5 (NetBSD-6.0/hp700/binary/sets/games.tgz) = 235dc6818c1a24a788301264c292ca2a +SHA1 (NetBSD-6.0/hp700/binary/sets/modules.tgz) = 1b4ecd74bda33a325888994e03e67327a959a381 +SHA512 (NetBSD-6.0/hp700/binary/sets/modules.tgz) = 7f77163eb7973139a1e6a2c4aaf3147b94e5f1f977ee642c08b1ad912861d810d953c71ac9db5c5b74c9f9b691a48faeccb4192b099f6ba3cc7fb41093f55533 +RMD160 (NetBSD-6.0/hp700/binary/sets/modules.tgz) = e6f669845fcac20f9921602a26bfed3d83c0b453 +MD5 (NetBSD-6.0/hp700/binary/sets/modules.tgz) = d5fdd2b3f62edab0ea9e9652c2274b01 +SHA1 (NetBSD-6.0/hp700/binary/sets/tests.tgz) = 4a3701895f22ba6d97662a345fa9c14bda977335 +SHA512 (NetBSD-6.0/hp700/binary/sets/tests.tgz) = 9ec93c9ec1b2732690f2a3d07cce15569b5ff57a2cabe9489ad28e7b52ccbc0382795267abb6d30a7db9b38f3b7b6a0c6016ea175b1d91f24b50922e3098cc4a +RMD160 (NetBSD-6.0/hp700/binary/sets/tests.tgz) = f62f1798af8d3df9d9653487c543be4411fb2037 +MD5 (NetBSD-6.0/hp700/binary/sets/tests.tgz) = 764d8df608cc1e9c23923eb7292f1962 +SHA1 (NetBSD-6.0/hp700/binary/sets/text.tgz) = 12fe20e8ab174d0f6bcd8ec6be600ed0e0cca782 +SHA512 (NetBSD-6.0/hp700/binary/sets/text.tgz) = b56b29228d79ba548c3ad908f9c81cf7e427bc72e607820438c6154e256f5bb4bd102aab7c31e86b241ecc42f824420aa7969e6ac418250c344eeffd1280abdc +RMD160 (NetBSD-6.0/hp700/binary/sets/text.tgz) = 1e16f9ea1efaee41bc10b045105a1d0dc4f0d17c +MD5 (NetBSD-6.0/hp700/binary/sets/text.tgz) = 09610caef8a531f7c490920d43a7c3d0 +SHA1 (NetBSD-6.0/hp700/binary/sets/xbase.tgz) = 0c5e93ea81c0f09063e5c30f42c9d652aa9b68cc +SHA512 (NetBSD-6.0/hp700/binary/sets/xbase.tgz) = 03f48b4ef5dc3f869866f00214d7d5482f03d2d838ceb05e0003484d8835f05b484d998debf24d801721dbb155aa5632a9a1e6d3a830d6faddc552c4500ac3e7 +RMD160 (NetBSD-6.0/hp700/binary/sets/xbase.tgz) = 8661bbe49a27e86810bee528b84947926e0a2e65 +MD5 (NetBSD-6.0/hp700/binary/sets/xbase.tgz) = 21b4506d3d4f407c33d8c152ca8ef304 +SHA1 (NetBSD-6.0/hp700/binary/sets/xcomp.tgz) = a70481db9baba9f60cf23c52e72dac446888df2d +SHA512 (NetBSD-6.0/hp700/binary/sets/xcomp.tgz) = 07c5ba6aa0ce0da2c5c2a3987c7c20226e4ee3158578a7ff70609bbfafc83becdd6a6185fd2c0b4a441f7d92c2cf5be3c767252c11f8fae07068f3ddeb48382e +RMD160 (NetBSD-6.0/hp700/binary/sets/xcomp.tgz) = 2d0179f816fb0a90c931f0733cbfad6dfe3f4d17 +MD5 (NetBSD-6.0/hp700/binary/sets/xcomp.tgz) = 84ddb46d08c60fab91553d60f848e21d +SHA1 (NetBSD-6.0/hp700/binary/sets/xetc.tgz) = 0ba461866c920a4fb82c50eede51ec242527a428 +SHA512 (NetBSD-6.0/hp700/binary/sets/xetc.tgz) = 1e84618c1e253df70f3801c93b1276ab63df818b231afb21a6c34089fd53cc95c9314a8ff14270d622a231c7fb963473e152f013e1cc2f338e7f231eabf524af +RMD160 (NetBSD-6.0/hp700/binary/sets/xetc.tgz) = a98382606c9775e89131fc737d791b9c4c8334d6 +MD5 (NetBSD-6.0/hp700/binary/sets/xetc.tgz) = 626d88e448091f14845bf3a565d330ec +SHA1 (NetBSD-6.0/hp700/binary/sets/xfont.tgz) = b70a4c27223f81cf49a62a85c3addc59b52f4b48 +SHA512 (NetBSD-6.0/hp700/binary/sets/xfont.tgz) = 82d94e80e98de78d71d5bae5af20b2755cadbaca48d548b2575fba4a52b2f35e09b71efb4fc8f0f1eadb5282e449807745feeb1d121275e9457eebe93722deb1 +RMD160 (NetBSD-6.0/hp700/binary/sets/xfont.tgz) = ec9a08a3c3e1563d8c4bd9a86d0e7fa38dcfa944 +MD5 (NetBSD-6.0/hp700/binary/sets/xfont.tgz) = 0bd2c8bc1760f957a2dec6126148ccb3 +SHA1 (NetBSD-6.0/hp700/binary/sets/xserver.tgz) = 892de89d8c46c05b44affea346312132bdc9d7b8 +SHA512 (NetBSD-6.0/hp700/binary/sets/xserver.tgz) = 18f1705c9e448b34e240f0f215fd618f62af2c1efa59fc9456a28df4fd477a6da26af82f7a99c359edd312abfedfc7b3058f651472a17d339f672db872ade390 +RMD160 (NetBSD-6.0/hp700/binary/sets/xserver.tgz) = dadd7b1915e43f92a618b65f739d91fc47cb17f4 +MD5 (NetBSD-6.0/hp700/binary/sets/xserver.tgz) = d0ce54a0227edeea0ed0572c32f7382e +SHA1 (NetBSD-6.0/hp700/installation/netinstall.lif) = e4f530ba8005c2a02ab8cc5f6f2f9bc266ed7d27 +SHA512 (NetBSD-6.0/hp700/installation/netinstall.lif) = 9cb62f32608d400472276a255cc25c872406cd9a2113a787dd9735759a3d05a1de97c2b53daeeb35b4ab07e3e016aaea0bcc2da165c3c07633ac716900383354 +RMD160 (NetBSD-6.0/hp700/installation/netinstall.lif) = 00807d44c30717d4b524a94e209ae8881d9894b8 +MD5 (NetBSD-6.0/hp700/installation/netinstall.lif) = 070bcd9b95c8c1f02cb3e233bbfd997d +SHA1 (NetBSD-6.0/hp700/installation/SYSNBSD) = 0458f52af240895100db4e2c15e685a9a8af00da +SHA512 (NetBSD-6.0/hp700/installation/SYSNBSD) = 6acc8321830dbb38cbbbe88bba88c6f0bbdfcfe60380f11fbe92724b0defcb8dbf3ea9207e7522fb90b95a0a401114a751cdef01ddcd5d354cb7ec058c83f98a +RMD160 (NetBSD-6.0/hp700/installation/SYSNBSD) = 2c9d5b050abe290f785eaf9fd1fb746ec0c2d310 +MD5 (NetBSD-6.0/hp700/installation/SYSNBSD) = d6cb9aa32688c2b571b6b62f7141d23d +SHA1 (NetBSD-6.0/hp700/INSTALL.html) = caa84e344b51c67646142496becf7b3580bdd769 +SHA512 (NetBSD-6.0/hp700/INSTALL.html) = 87e4eaa6077a464832397ddf9eb59ca95949c655d9897fb630899274176ded45b22f4da21ebbfad688515b7cb63a7aca9e5fa8b003d4c81208c0c514ddaa9d3f +RMD160 (NetBSD-6.0/hp700/INSTALL.html) = e46593839ae31aa17259f36ae4f71ee9cf56d317 +MD5 (NetBSD-6.0/hp700/INSTALL.html) = 5b63b1d8b0e76a1626ced50e760b6a24 +SHA1 (NetBSD-6.0/hp700/INSTALL.more) = bec1e3da9f724159b4a5b52e7bde3948e92573a4 +SHA512 (NetBSD-6.0/hp700/INSTALL.more) = 14a618c17e946dfc8c537f48b3f8c225ccf0484acdd1311555c7273a720a867f57b0f72786bf1c5ce874c0a8dc122d6452e476f6b3b5cfd2fdcf3e7b90c20b0a +RMD160 (NetBSD-6.0/hp700/INSTALL.more) = 3cf2ba4b0c27b4e83b2275ffe8b0736c536b40b0 +MD5 (NetBSD-6.0/hp700/INSTALL.more) = 211474596cbc940278e9edfbf8ab7d23 +SHA1 (NetBSD-6.0/hp700/INSTALL.ps) = 31767f9d14e0018f59f4bf89233f3a546d53234b +SHA512 (NetBSD-6.0/hp700/INSTALL.ps) = 7f1ef8344a35e0aacf8246212f9ef07fe7727048de0a7b24030fdf7698e736152623e6d5d02c32bffbceb3c0337aeac719c523711f838118f0d31316d46c6fb1 +RMD160 (NetBSD-6.0/hp700/INSTALL.ps) = bca575e3df8abf0c7f8ff70e614fe52a9c39f645 +MD5 (NetBSD-6.0/hp700/INSTALL.ps) = 644eaeb94d45f3183b9cae5f0b39d974 +SHA1 (NetBSD-6.0/hp700/INSTALL.txt) = 546cea2f82e5c548de6f6978f569d3dcf65476ce +SHA512 (NetBSD-6.0/hp700/INSTALL.txt) = 4d0d5e6363680e11da17d445fe7156b709e11d28f3226d1374e3612e68ba9c445bd2ec01e4422b523ea2d4197fc8a8b465da0c75401b9560ced43f217931b558 +RMD160 (NetBSD-6.0/hp700/INSTALL.txt) = b7536cf8d4f664d03d213978619724a94a16b1d5 +MD5 (NetBSD-6.0/hp700/INSTALL.txt) = 241f27fd87ec0932db94a067465d30b0 +SHA1 (NetBSD-6.0/hpcarm/binary/kernel/netbsd-JORNADA720.gz) = 7a39f220d6af810e25b4799685aab25a226b9b91 +SHA512 (NetBSD-6.0/hpcarm/binary/kernel/netbsd-JORNADA720.gz) = 4b2d4125cf737229264e73bd830c4def0ee33dba71cc5f68abf3e8e936dc89fb02f48a0d821754d2427fe1f72595dd266cd9cfc369c778f50f48573fb2c0bbe1 +RMD160 (NetBSD-6.0/hpcarm/binary/kernel/netbsd-JORNADA720.gz) = 129136e4544bb8fcee75e1addd1fee16c522e416 +MD5 (NetBSD-6.0/hpcarm/binary/kernel/netbsd-JORNADA720.gz) = 6ed126d914383f7ca0c3269960e885db +SHA1 (NetBSD-6.0/hpcarm/binary/kernel/netbsd-IPAQ.gz) = 7750f05c52fc8460f3ad8b271ae2d9e723c24ebe +SHA512 (NetBSD-6.0/hpcarm/binary/kernel/netbsd-IPAQ.gz) = 485f621f65f80fa02b8fbc08a876aa135d3e4c541ccc6d13ebb3bf119b0628dc5a540ba168a6e908b84422450829dd5a98915a145d629e893930ed40d9e3dfde +RMD160 (NetBSD-6.0/hpcarm/binary/kernel/netbsd-IPAQ.gz) = ee2d243a0fd633e6dac497b28b420b4a8157879f +MD5 (NetBSD-6.0/hpcarm/binary/kernel/netbsd-IPAQ.gz) = 563942f00d685c8618fb5bfa2a6a893b +SHA1 (NetBSD-6.0/hpcarm/binary/kernel/netbsd-WZERO3.gz) = e6f2cede1c69a3f41582f1a8f2a5187948512248 +SHA512 (NetBSD-6.0/hpcarm/binary/kernel/netbsd-WZERO3.gz) = 8cc9f93b55a9a64341b266f7d3b8c6d1051f84a36f8aa398b24404d8aa57a16e883b1e7215b7cd235764b4507e04259525333f28369aa95efa39713e17bef07b +RMD160 (NetBSD-6.0/hpcarm/binary/kernel/netbsd-WZERO3.gz) = 536bc6153a0c83339c95e38b87a87bc98e738cb5 +MD5 (NetBSD-6.0/hpcarm/binary/kernel/netbsd-WZERO3.gz) = c4092d8e84f02fa75ea88436d404f1b1 +SHA1 (NetBSD-6.0/hpcarm/binary/sets/games.tgz) = e1d2bb091d8202962133475bc83edb55230b9008 +SHA512 (NetBSD-6.0/hpcarm/binary/sets/games.tgz) = a147fe6d0419d53d5a428802d0bb6c9fa8a84a76c96d7d6d7c0d399e5af3a69240116463549a83d53387b0214ba0207796d7c10228d92a684fe7ff0ece3aec16 +RMD160 (NetBSD-6.0/hpcarm/binary/sets/games.tgz) = 2be515c495548ba5135ff42a75a8ebbfc35ea776 +MD5 (NetBSD-6.0/hpcarm/binary/sets/games.tgz) = 9059a6f2cd41cb58827709c9e9a1649b +SHA1 (NetBSD-6.0/hpcarm/binary/sets/man.tgz) = 899b9d8242e983a5110ab755651c24f709b5af67 +SHA512 (NetBSD-6.0/hpcarm/binary/sets/man.tgz) = 410999db110d710f4bb498c3d7ae7adc62170c7c2f470ce189c92f6c436c5ea96149659c631ef0b5605caaa025d97dfe1c07c428d86f51239657bd6b71717b15 +RMD160 (NetBSD-6.0/hpcarm/binary/sets/man.tgz) = c1270f68c6d41b351877f71f0396ac34877dfc8d +MD5 (NetBSD-6.0/hpcarm/binary/sets/man.tgz) = df4db2bbfa39ef6a4a215d949653d04a +SHA1 (NetBSD-6.0/hpcarm/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/hpcarm/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/hpcarm/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/hpcarm/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/hpcarm/binary/sets/kern-IPAQ.tgz) = c2bc2e5d8606cbd122fc825031025e2946f06e40 +SHA512 (NetBSD-6.0/hpcarm/binary/sets/kern-IPAQ.tgz) = 52e8c28012dca6e4cc1bab2cce4443a6600a9cd42b3e1e027e715792e794f34baab32300da9ad58fbc23ecb2a22e7787a1d181577317a0dc6fd457ba66f11fc6 +RMD160 (NetBSD-6.0/hpcarm/binary/sets/kern-IPAQ.tgz) = 7be149eb7b493fd76dfe0dfc533315458fb0bfea +MD5 (NetBSD-6.0/hpcarm/binary/sets/kern-IPAQ.tgz) = 0d6a168f2d92d06962b581d06f807d46 +SHA1 (NetBSD-6.0/hpcarm/binary/sets/base.tgz) = 080c8331106fce332cc5092a8332c2ad603e2596 +SHA512 (NetBSD-6.0/hpcarm/binary/sets/base.tgz) = e22024be4e644ae872d6cf538a1210f8ec2aefeadfb47f6497e3892de2b617109a082650e1c1b16006cb84312c1550d3e98610ca63a36a083a073c55a08a3ab2 +RMD160 (NetBSD-6.0/hpcarm/binary/sets/base.tgz) = dc0f2bef3b562a81901faf28d738e34168c3b812 +MD5 (NetBSD-6.0/hpcarm/binary/sets/base.tgz) = 0e05338048fb790920168e820e0f5771 +SHA1 (NetBSD-6.0/hpcarm/binary/sets/comp.tgz) = 8ae72e40483c13b3ea15aebb3efbcb5cedcf921e +SHA512 (NetBSD-6.0/hpcarm/binary/sets/comp.tgz) = 3ee22dfba60196fe19897537c3139dff0b50d1aa6f6c27a024dcdbdc810a9dccd2c32480f73c0ffb0e4dcc4261e03ca6c565a875e291c963011467bc119f292c +RMD160 (NetBSD-6.0/hpcarm/binary/sets/comp.tgz) = 8bbf9baef503fd64c7676821abad991027f42ccf +MD5 (NetBSD-6.0/hpcarm/binary/sets/comp.tgz) = 84a5d47bbb69b46673a2b2a53ffe3854 +SHA1 (NetBSD-6.0/hpcarm/binary/sets/etc.tgz) = cbd3aeb7eee9da4d67693adee922e65835ad8908 +SHA512 (NetBSD-6.0/hpcarm/binary/sets/etc.tgz) = 96f02aae1ff4fe6096261449dabe1c749ddf179e809b936393bd3b1aea3d708b878ea9c6fcededf0820216bc3f5a4862da04cd9ad5cd4991094bfc309421dc4f +RMD160 (NetBSD-6.0/hpcarm/binary/sets/etc.tgz) = b3f5dbf2f1a092a0fed4f7ff661635387bdfb7cc +MD5 (NetBSD-6.0/hpcarm/binary/sets/etc.tgz) = 940a5d84fd6546eb8ef1fc0fc2af9f12 +SHA1 (NetBSD-6.0/hpcarm/binary/sets/kern-JORNADA720.tgz) = fbe60c24963e700dbcded7ed9d6a006fce937c4d +SHA512 (NetBSD-6.0/hpcarm/binary/sets/kern-JORNADA720.tgz) = 0ff4a883f983d768355dab3a124bb1ccc3418d7a61bd8dbfc571089b934153eda2b9bcedf4d655e61c680c60b50772a40322804f86accb96acbd11dbd0159aab +RMD160 (NetBSD-6.0/hpcarm/binary/sets/kern-JORNADA720.tgz) = 010eea6fd1f9645480ed8d96e67a7a87766e6097 +MD5 (NetBSD-6.0/hpcarm/binary/sets/kern-JORNADA720.tgz) = 8a1eb406cc9cb944a0dc11ade6d139d9 +SHA1 (NetBSD-6.0/hpcarm/binary/sets/kern-WZERO3.tgz) = 5a30317da0f7f2c6f1998a8c53350da39a390bff +SHA512 (NetBSD-6.0/hpcarm/binary/sets/kern-WZERO3.tgz) = 6908dea8428f52a08f481105b602fd2b93318207b5142ccec5104a897a9ad5b10ec25db1a5849074c179e064c7c418cebccbc529609873b031dde5ef1659ec6e +RMD160 (NetBSD-6.0/hpcarm/binary/sets/kern-WZERO3.tgz) = db2ec740804a2c22b4d9d5f05f7b20748206fcca +MD5 (NetBSD-6.0/hpcarm/binary/sets/kern-WZERO3.tgz) = b745687a92452be38b0d2cdb625175e8 +SHA1 (NetBSD-6.0/hpcarm/binary/sets/modules.tgz) = cd6c4ccc2c87d573cdb5a92a8806292c5063bd28 +SHA512 (NetBSD-6.0/hpcarm/binary/sets/modules.tgz) = 66efd8e33cb118fcb7e6094a55dce87db0b38f03398688e19eaa29a88a61075ca4456cfbcf262e4ad372d1a85d31f1a230e79a09a60d9d0315ee2691f836f408 +RMD160 (NetBSD-6.0/hpcarm/binary/sets/modules.tgz) = 1a4f4a21d35c183594080c4c2c6aeb63d0f07ec0 +MD5 (NetBSD-6.0/hpcarm/binary/sets/modules.tgz) = 0d07dc5c45004e2442e6da94a40e2082 +SHA1 (NetBSD-6.0/hpcarm/binary/sets/tests.tgz) = d77efdefa2b3df022767062ce3e5b37ee33aca9f +SHA512 (NetBSD-6.0/hpcarm/binary/sets/tests.tgz) = b2827bef6684fe45b1ca7dc690a30787a0033b46013281c0d12dc182939a32287579ea0ed6dfdda5ac357cb69a1bfccffcce2cbc991a3b47f0cf714df45f511c +RMD160 (NetBSD-6.0/hpcarm/binary/sets/tests.tgz) = c51c78a413d9b8d240db9965edd6732158319bec +MD5 (NetBSD-6.0/hpcarm/binary/sets/tests.tgz) = a157cb333c867f1efce0c0009db0c596 +SHA1 (NetBSD-6.0/hpcarm/binary/sets/text.tgz) = 5e276b4e097bd1ab37a48ba8ac4591d784311152 +SHA512 (NetBSD-6.0/hpcarm/binary/sets/text.tgz) = f7d62b4ac928028f37cc0ad711a12e4f5d4a2b77d2e108ce8716194052e6796bf5fb54ce77fa148aa257165f3d71f2e30d562d3dc809052020b85daaa5ba9fcb +RMD160 (NetBSD-6.0/hpcarm/binary/sets/text.tgz) = 806a5e59b90062c827a23ca33be22cda14a2e0c6 +MD5 (NetBSD-6.0/hpcarm/binary/sets/text.tgz) = e4ed04614c1a767e663fc73d647f5b7a +SHA1 (NetBSD-6.0/hpcarm/binary/sets/xbase.tgz) = 56daf552141d6161e0b08d5918e351f9cf5f783b +SHA512 (NetBSD-6.0/hpcarm/binary/sets/xbase.tgz) = ccc570735b9636dad693a87964efa1c6d5b14a15e8e9ea28b0ebbcf97db04a671a771d6163a62f78d9979357f7fb0d5543591ac584781cfb47778228a268d723 +RMD160 (NetBSD-6.0/hpcarm/binary/sets/xbase.tgz) = 134800ce03d324aa4090e1ce235cc5a6e5ba9f2b +MD5 (NetBSD-6.0/hpcarm/binary/sets/xbase.tgz) = e3afaa495833b5492470b03d432bc773 +SHA1 (NetBSD-6.0/hpcarm/binary/sets/xcomp.tgz) = 380508f5e8d94d66e301a6f8fddbddddaf2eb15d +SHA512 (NetBSD-6.0/hpcarm/binary/sets/xcomp.tgz) = 4860c2274b0d4d3b1188d915c90b7e183672527e6734023c78694df3f507d2e920e5af9374353f7581c8f0e22462e8af30aff7e989146de61c0c7b9de7cff93c +RMD160 (NetBSD-6.0/hpcarm/binary/sets/xcomp.tgz) = 2f0f86a40b6887699ea5949b994007a9bb6ad876 +MD5 (NetBSD-6.0/hpcarm/binary/sets/xcomp.tgz) = 8f917121a2bbc2df46c6ab3db5f7c276 +SHA1 (NetBSD-6.0/hpcarm/binary/sets/xetc.tgz) = 4109069bd859ebc949dede730589472e53e9e73a +SHA512 (NetBSD-6.0/hpcarm/binary/sets/xetc.tgz) = 260ee8565cb3b0fc496ff20856cc718585d36d380a85a5793c0e6502e57b683e132a3904ddb5990ce670ad9069eb999c2a41e427d5bb4ce96dd7f526427dfecf +RMD160 (NetBSD-6.0/hpcarm/binary/sets/xetc.tgz) = 24731afa16c748e4129111adbc446931859ac8b5 +MD5 (NetBSD-6.0/hpcarm/binary/sets/xetc.tgz) = c5aa4d6e7bda3c04ff21c49fa7a88349 +SHA1 (NetBSD-6.0/hpcarm/binary/sets/xfont.tgz) = 93475dc493faa6b2df35bede901aa170b6f9e9af +SHA512 (NetBSD-6.0/hpcarm/binary/sets/xfont.tgz) = 182e2f9f19c09b4a10c5591d2d9a85a151263ed9773ecc581fd4ab155f5342b364b2fd15c3ce7e82ba9b760ef567f0ccaa8fd51fa4ad3e70dbc63a429ec544b4 +RMD160 (NetBSD-6.0/hpcarm/binary/sets/xfont.tgz) = ea5190cce3fb48693746b233b2173595263d0b64 +MD5 (NetBSD-6.0/hpcarm/binary/sets/xfont.tgz) = e866b30099f57e267e8be054446c259b +SHA1 (NetBSD-6.0/hpcarm/binary/sets/xserver.tgz) = 33ea7cf47464441ccaa2779544df524406479446 +SHA512 (NetBSD-6.0/hpcarm/binary/sets/xserver.tgz) = 718cb878630d6a3d8e2a4c8c0ca427e36f6772017810df557ff9bb0a688445af10f4087662e91631ec07a0a83e3007fa016c485950b3753c50bfdd3cc219ccd1 +RMD160 (NetBSD-6.0/hpcarm/binary/sets/xserver.tgz) = 09ce10d8e2254deac07ece3f8625d6c3bf2c4513 +MD5 (NetBSD-6.0/hpcarm/binary/sets/xserver.tgz) = a36d535d398b0d6e6e66da91d03ddb6a +SHA1 (NetBSD-6.0/hpcarm/installation/miniroot/miniroot.fs.gz) = add38fbef1c9a42872427fc3ae856cc490dba491 +SHA512 (NetBSD-6.0/hpcarm/installation/miniroot/miniroot.fs.gz) = 1ac653efe632dd53dc6bf8f1abda479a4bdecf57b4aadce9b289381a8608601e7444404bac4b4187ea5eb87a8e56affafb06b30c5f27264797b8811b4b4a61ce +RMD160 (NetBSD-6.0/hpcarm/installation/miniroot/miniroot.fs.gz) = d36e893b023bc07b2ae23e65891cd8edd74ae60c +MD5 (NetBSD-6.0/hpcarm/installation/miniroot/miniroot.fs.gz) = d790021f968d07d34a34acb3fdc18a3c +SHA1 (NetBSD-6.0/hpcarm/installation/netbsd-IPAQ.gz) = 640e6d70fa752f3f1e6b415d79bfa26eb524d49f +SHA512 (NetBSD-6.0/hpcarm/installation/netbsd-IPAQ.gz) = 0266c16c91cd0edf3fad56c8806d8736edcb70138486a8596afd2ad58a89846ed319973d4383c6dc240e894a23658effd390012c6bb55d768a3980c5cb9bfa34 +RMD160 (NetBSD-6.0/hpcarm/installation/netbsd-IPAQ.gz) = 8b57f335f3ce186509ff88c07bc85c27716b542d +MD5 (NetBSD-6.0/hpcarm/installation/netbsd-IPAQ.gz) = 4963aae14a8da8a218ec0f43110e4329 +SHA1 (NetBSD-6.0/hpcarm/installation/hpcboot.exe) = f62f1b2bbf14dd5ee1159d987365122bbfa061d4 +SHA512 (NetBSD-6.0/hpcarm/installation/hpcboot.exe) = b1ad5471eec903659a2fe6ff79e631ea40d940e447126a6d8d6b46166dadd7cbbbea4285927968134d2ff493fe66a698d97374febf991ee9ecd4d295f06c92b8 +RMD160 (NetBSD-6.0/hpcarm/installation/hpcboot.exe) = fefa32b139995cd0b71c59d09cfb225fce08dbc8 +MD5 (NetBSD-6.0/hpcarm/installation/hpcboot.exe) = e8da90c935c719d600bed4f07046950f +SHA1 (NetBSD-6.0/hpcarm/installation/netbsd-JORNADA720.symbols.gz) = 04eac0a968c96a038388c18816b735fd0fda5c2e +SHA512 (NetBSD-6.0/hpcarm/installation/netbsd-JORNADA720.symbols.gz) = 61357b623b75c75df8f2c5318c82f3300183de81003900fb10a1caa566cd9cbc90563277a5d0738b0a7ed52934cfb40d08b4c7af428b06bca90dd907b89673ad +RMD160 (NetBSD-6.0/hpcarm/installation/netbsd-JORNADA720.symbols.gz) = 43b52d529a62cbfeacdae60b54d9e0fece7a1ab0 +MD5 (NetBSD-6.0/hpcarm/installation/netbsd-JORNADA720.symbols.gz) = acfc91c707d81e9c84b3fb7f6626f9e5 +SHA1 (NetBSD-6.0/hpcarm/installation/netbsd-IPAQ.symbols.gz) = 48c1a0db5c6a2e7d69b1bcf77763e88adadf6373 +SHA512 (NetBSD-6.0/hpcarm/installation/netbsd-IPAQ.symbols.gz) = de5ef76b391472a2c18637f36f58a904d693085bfd9108676a1c0476712ab94b72ac41628a65a9c0bfcd5f33c9e141540906f63cfa5614ab8ea2f3f6867b9b1d +RMD160 (NetBSD-6.0/hpcarm/installation/netbsd-IPAQ.symbols.gz) = 383e05d6255afda312b4b81fdaffe4e4a9c83dbf +MD5 (NetBSD-6.0/hpcarm/installation/netbsd-IPAQ.symbols.gz) = 4b4a3474459c93e727e4f20559139464 +SHA1 (NetBSD-6.0/hpcarm/installation/netbsd-JORNADA720.gz) = 70818132f816688fa6d74e13544e9e6f07faaddb +SHA512 (NetBSD-6.0/hpcarm/installation/netbsd-JORNADA720.gz) = 0b9b7718b30b88b81fb66cdc32ddee57ac7fd6c90c1ecb6a422f84513df70d594b48badb8b71f00b3ef8d90f544c01439bef4942a51eace3d1fc5dbca1461ced +RMD160 (NetBSD-6.0/hpcarm/installation/netbsd-JORNADA720.gz) = bd193cf9815e6f8a60ca9df77eb1537913c2daa0 +MD5 (NetBSD-6.0/hpcarm/installation/netbsd-JORNADA720.gz) = 39c8584c95a8c2197165b102a1548a5c +SHA1 (NetBSD-6.0/hpcarm/installation/netbsd-WZERO3.symbols.gz) = 2afaf89d89ef9c6538960f64b36802beb3e74472 +SHA512 (NetBSD-6.0/hpcarm/installation/netbsd-WZERO3.symbols.gz) = 53c9ddac6c56fa5e1c77323483b129b0b1ebe88b558f0e50346d17d54477db1187831c6c8e0e2a231b9473dfcf8d285672f69cbca8197e6fa889f8285836b38f +RMD160 (NetBSD-6.0/hpcarm/installation/netbsd-WZERO3.symbols.gz) = 9dfb61526eb859fd999c8c05b257d436a6d209f3 +MD5 (NetBSD-6.0/hpcarm/installation/netbsd-WZERO3.symbols.gz) = c8aa20ace8e4938a05386d8c02f1cb6c +SHA1 (NetBSD-6.0/hpcarm/installation/netbsd-WZERO3.gz) = ded59dfdb078cd978a9a74670d43899ef5186b39 +SHA512 (NetBSD-6.0/hpcarm/installation/netbsd-WZERO3.gz) = f93d2e0c80f5b9f8d2f1d851515b2b50f8f518caf7e0b8b71dfdb002a2f97c1da80f7a7d7263228a0d5400267d0be91ee649b558eb4fea8dac4fe07f23b24138 +RMD160 (NetBSD-6.0/hpcarm/installation/netbsd-WZERO3.gz) = 99920bf26d5c1697ed030c151c630b125e3b6cf1 +MD5 (NetBSD-6.0/hpcarm/installation/netbsd-WZERO3.gz) = c958ba2807a0e03d47f98fa66fcbccef +SHA1 (NetBSD-6.0/hpcarm/INSTALL.html) = 90f13483a6a7cefd8261806546700202df5e89ee +SHA512 (NetBSD-6.0/hpcarm/INSTALL.html) = f7b3a19235b72a4a19c27380e6e22f89e4ce58864a8ef3b492b05aff47cd017a0157adf96bf1d04ef4d6c9b1f4f24980afad91f2644e74fccac06274a35bc75b +RMD160 (NetBSD-6.0/hpcarm/INSTALL.html) = 6228411bb6d6018e59a1fd74f2887aefed5ae8fe +MD5 (NetBSD-6.0/hpcarm/INSTALL.html) = 3d21d24e5a8b5a1ed45afd2f0e7c25e0 +SHA1 (NetBSD-6.0/hpcarm/INSTALL.more) = bab711c6d2c3ef110b778fa3bb18a690e3350071 +SHA512 (NetBSD-6.0/hpcarm/INSTALL.more) = 85c117ec4b92633391497f62723320999e714a68f0a9b008508fd1b884f77729235859c2ed0ff9539af6615eb452cd87a9bf9f10456ae53fc057b5a3d665dbb5 +RMD160 (NetBSD-6.0/hpcarm/INSTALL.more) = 5283c45bcd291d03e3d2f579eaccdc78708a2dc6 +MD5 (NetBSD-6.0/hpcarm/INSTALL.more) = fd547cbcd59d803d4f5ef38f619fca0c +SHA1 (NetBSD-6.0/hpcarm/INSTALL.ps) = 6ce0b3584e4b45bbed722cb8bddb66e3deedc88a +SHA512 (NetBSD-6.0/hpcarm/INSTALL.ps) = 3d766bafb31be6edb83b4ada23bd1eec923f7297f6b4cf51adc247a160749c5488a99282ce7e4380b4c27025581901c6f5d7d774c799fdb23f8410c43c8e4b0b +RMD160 (NetBSD-6.0/hpcarm/INSTALL.ps) = e8c042d83705b3b63bcb793d856307b95ed31521 +MD5 (NetBSD-6.0/hpcarm/INSTALL.ps) = 1a50f108a265984cdd0f0206c83daa35 +SHA1 (NetBSD-6.0/hpcarm/INSTALL.txt) = 06a8b26e2de81570eaaa71593a67b1e4c517590a +SHA512 (NetBSD-6.0/hpcarm/INSTALL.txt) = 4fa7355a943c7e48925ab6db1c281ee9cc7e674095c7eea355d270d15afbb73d45891ce07a4b6104b1fcb0dfaceb3af48db6cb134070077fa4f1bcab453e83eb +RMD160 (NetBSD-6.0/hpcarm/INSTALL.txt) = 3bb0f03d782104ec4792423f3d640e8e7adc29b8 +MD5 (NetBSD-6.0/hpcarm/INSTALL.txt) = 68c0576d6d8b54ebfbb0728b7a73438b +SHA1 (NetBSD-6.0/hpcmips/binary/kernel/netbsd-GENERIC.gz) = b038fa721af9faeddea84add1762439db98cf908 +SHA512 (NetBSD-6.0/hpcmips/binary/kernel/netbsd-GENERIC.gz) = 6d550d0b1797734c7340d8632930c78be193f397591767e2eed674423ad469dda333206a8f539adfba9d0d81ee70cda7c01de58cfcc4e3ca0440cd6615ba8167 +RMD160 (NetBSD-6.0/hpcmips/binary/kernel/netbsd-GENERIC.gz) = a4627fac6aad12dd9a2f04c3aa90fc8c61699d4f +MD5 (NetBSD-6.0/hpcmips/binary/kernel/netbsd-GENERIC.gz) = 6b0e8c6ff949fbea7ff99cbbed4df778 +SHA1 (NetBSD-6.0/hpcmips/binary/kernel/netbsd-TX3912.gz) = be377f94448f7026050fbd885d0eeb2ed6a1e84f +SHA512 (NetBSD-6.0/hpcmips/binary/kernel/netbsd-TX3912.gz) = 3855f4e59d507281b41d8363e8d39ea229bd41fd1cc6090704727dcd97bb75f3c265f68a0cfe84a10292e55c7d58a266f4d27705a1fb9218d34e1727210692f0 +RMD160 (NetBSD-6.0/hpcmips/binary/kernel/netbsd-TX3912.gz) = 686c703228a5ace7ddb3dcbb232bdb4ece47b6f1 +MD5 (NetBSD-6.0/hpcmips/binary/kernel/netbsd-TX3912.gz) = e462f4f6a2cbc6d8eb20e49cbcfed56f +SHA1 (NetBSD-6.0/hpcmips/binary/sets/games.tgz) = 27d9f98fecb3495e51939df9f107e81e527af26f +SHA512 (NetBSD-6.0/hpcmips/binary/sets/games.tgz) = 46bb4e10313cfffaaf4f7fa2157474ef940f94bcc9f84b46f829c7615bbf45e4e01edee7b7efb84bc28561e0712c37cfc737f9c2a0d9a73b67c80c8aa0f3a9af +RMD160 (NetBSD-6.0/hpcmips/binary/sets/games.tgz) = 947feea90ec2698a65d555cb78a29a001b086589 +MD5 (NetBSD-6.0/hpcmips/binary/sets/games.tgz) = 355f00978fed8e8da6a251e591be5387 +SHA1 (NetBSD-6.0/hpcmips/binary/sets/man.tgz) = 899b9d8242e983a5110ab755651c24f709b5af67 +SHA512 (NetBSD-6.0/hpcmips/binary/sets/man.tgz) = 410999db110d710f4bb498c3d7ae7adc62170c7c2f470ce189c92f6c436c5ea96149659c631ef0b5605caaa025d97dfe1c07c428d86f51239657bd6b71717b15 +RMD160 (NetBSD-6.0/hpcmips/binary/sets/man.tgz) = c1270f68c6d41b351877f71f0396ac34877dfc8d +MD5 (NetBSD-6.0/hpcmips/binary/sets/man.tgz) = df4db2bbfa39ef6a4a215d949653d04a +SHA1 (NetBSD-6.0/hpcmips/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/hpcmips/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/hpcmips/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/hpcmips/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/hpcmips/binary/sets/xcomp.tgz) = d8ac89f3f6ff20abb0adabc49227afdb74aa2040 +SHA512 (NetBSD-6.0/hpcmips/binary/sets/xcomp.tgz) = 4f03213fb061dae9421747209628d06ede6bbb71a7560a9e1a54796b907f1620146a33fdce52974227a21acedcc210b99e15c4fdd36432eba60c1041a92d8cee +RMD160 (NetBSD-6.0/hpcmips/binary/sets/xcomp.tgz) = 6be5e72b9b57c9bdf8ed8ea127e2a73830feeecb +MD5 (NetBSD-6.0/hpcmips/binary/sets/xcomp.tgz) = 59a7ea141587417be38ab1f6056cc780 +SHA1 (NetBSD-6.0/hpcmips/binary/sets/xetc.tgz) = b9f6b1a54ffab37b11f4c6e717b481cd087fb609 +SHA512 (NetBSD-6.0/hpcmips/binary/sets/xetc.tgz) = 72f35e65f3a90967e250a2006d500619b3824f7f5c3d7494554f153ec5cda5b28c445f28c34a1e4463f40da5855e8d4257726411796967fe37763d90cf7fe461 +RMD160 (NetBSD-6.0/hpcmips/binary/sets/xetc.tgz) = 1169c246f91189fd0c4ae86ac27a92f5c2edda3e +MD5 (NetBSD-6.0/hpcmips/binary/sets/xetc.tgz) = 8f3c52cc5af1cafaf7b0d0f884a5b537 +SHA1 (NetBSD-6.0/hpcmips/binary/sets/xfont.tgz) = d06848571034f3b7fc975082f1de37b912acb18c +SHA512 (NetBSD-6.0/hpcmips/binary/sets/xfont.tgz) = 66a1013c935bee5e7e5d24325a527522306bcded7ced63790f2e58831b3ed91176a1b9510b2159be63504d5167d48d534919927ffc6e225ae2bb2487f90a9ede +RMD160 (NetBSD-6.0/hpcmips/binary/sets/xfont.tgz) = c9502843a5d4dd7e996e8d158c519cf7f8575cbd +MD5 (NetBSD-6.0/hpcmips/binary/sets/xfont.tgz) = e812899176eac2bf65a6d949ac3f3424 +SHA1 (NetBSD-6.0/hpcmips/binary/sets/kern-GENERIC.tgz) = 5a49a4163b7d841104dd4082113ba253ca95f946 +SHA512 (NetBSD-6.0/hpcmips/binary/sets/kern-GENERIC.tgz) = 3856b27c3d200e162fb88b7e094e38d843a91f67dadb56b31bd66c18daddd2c0aed58dbea87d43a3d530d3ece68bac562c20d623b613bdd4855fb86bc4794463 +RMD160 (NetBSD-6.0/hpcmips/binary/sets/kern-GENERIC.tgz) = cbd699ebfe796b39eee403ac3831765f5871e789 +MD5 (NetBSD-6.0/hpcmips/binary/sets/kern-GENERIC.tgz) = 22031cc2c2f3a4a6002fe20cff53264c +SHA1 (NetBSD-6.0/hpcmips/binary/sets/base.tgz) = ff9051176546bd2cacea52fee85fcef472e0fc39 +SHA512 (NetBSD-6.0/hpcmips/binary/sets/base.tgz) = 2a770bede2e0f7af3a0d8c2a1f3871bd72c1f67dbe5aed9f6d1cf12b78c8676c819dfd99d3c7cbfc1794c993e8cf059f9e72b764f8d25a5f1ad3406c42169d6d +RMD160 (NetBSD-6.0/hpcmips/binary/sets/base.tgz) = c0d7aa660957624cda33c738d6026870f14fb823 +MD5 (NetBSD-6.0/hpcmips/binary/sets/base.tgz) = b79936c5e1c4ff6a86270da2931b1c54 +SHA1 (NetBSD-6.0/hpcmips/binary/sets/comp.tgz) = 32515af667967de5ad8dbca2ad993c62c9794b80 +SHA512 (NetBSD-6.0/hpcmips/binary/sets/comp.tgz) = 5604e8af6fe737b81128a976cd53cc5f5b287f04de2b21fdbc8bfffa1b521ceae4f7244ad8b98580ca77af7c43b75623e2e9ab8772bd23e8e3c7d297b6c54bfa +RMD160 (NetBSD-6.0/hpcmips/binary/sets/comp.tgz) = b9a5cf74d2c16f7870081a27a3862459c101b690 +MD5 (NetBSD-6.0/hpcmips/binary/sets/comp.tgz) = 4265c60c89150dc4c7de32c0c3f4aeac +SHA1 (NetBSD-6.0/hpcmips/binary/sets/etc.tgz) = 68b265bdfcdf09e792bcdfe69656516b44d37b66 +SHA512 (NetBSD-6.0/hpcmips/binary/sets/etc.tgz) = af2d02e2aa9a03df02dd8f0a8840e7d185e18b57e8086f0eeb5b7a1349e02433bd7ef1c83f77d5962f90350b71fb4610932e29d723f1cf4488c930048ab43dd1 +RMD160 (NetBSD-6.0/hpcmips/binary/sets/etc.tgz) = 3a5d433571b7a9c44fa0ffca6efd6df514101b15 +MD5 (NetBSD-6.0/hpcmips/binary/sets/etc.tgz) = 295c108b6f0e7a9dd8f7cc142e87dbd9 +SHA1 (NetBSD-6.0/hpcmips/binary/sets/kern-TX3912.tgz) = e1ff4c2bdcfe12d8c26b87801f28970661e5e109 +SHA512 (NetBSD-6.0/hpcmips/binary/sets/kern-TX3912.tgz) = 42d069cd3e055b33ffd04b0e99f3db75a45c80cf8cfffb0a4cc08fd3fafb9e9e8c8c6205cf827689a91080c75250c9e753c5c4f1657427287bd567244e29891a +RMD160 (NetBSD-6.0/hpcmips/binary/sets/kern-TX3912.tgz) = d5d7c8d6ab8d3cec287bd0ede9c658f5e196471d +MD5 (NetBSD-6.0/hpcmips/binary/sets/kern-TX3912.tgz) = d9aa987b53c079063b97e947c2b561ed +SHA1 (NetBSD-6.0/hpcmips/binary/sets/modules.tgz) = fd655bd27b90d1cd9ebb2f64a2b744e5f57178bc +SHA512 (NetBSD-6.0/hpcmips/binary/sets/modules.tgz) = c7b1ba107094c528d6edc3c3fa68962882af4fa207bb6b323e6230ebd09f0d7555abc34a4f76bc7f6c7fbf393258089a3a11d9ed7284edd0a9deb44bd8b6b1a7 +RMD160 (NetBSD-6.0/hpcmips/binary/sets/modules.tgz) = 13356c7a4e3f09123b31fbd42bcef53ebb10ed61 +MD5 (NetBSD-6.0/hpcmips/binary/sets/modules.tgz) = b820dfc2e2d9420fa72bd887eb9ab505 +SHA1 (NetBSD-6.0/hpcmips/binary/sets/tests.tgz) = 12c5aab5f1f4ab6124d3cb5e8598359b5f893652 +SHA512 (NetBSD-6.0/hpcmips/binary/sets/tests.tgz) = e7656a5f8bb8104576f8218fcbc48c5fdf4d4cfdf407c6805421f1101471c95ac6e1f83444c13ffd1cd82d3b51d4da0d8fc726795b0765363b700d5054cfd553 +RMD160 (NetBSD-6.0/hpcmips/binary/sets/tests.tgz) = 8abc82efc30f6bde5b48bd7778a3774fcd993ae4 +MD5 (NetBSD-6.0/hpcmips/binary/sets/tests.tgz) = d1cd20123adb795808586fef4825bc29 +SHA1 (NetBSD-6.0/hpcmips/binary/sets/text.tgz) = 66f261af8763d48f3c6e62511b0660801b89115a +SHA512 (NetBSD-6.0/hpcmips/binary/sets/text.tgz) = f7428c73f23bfaec5ddad225487c3e569479c537231c2c7ce46869c6debe07a0bf2f139cecd1622230337871a706d6da3891759bd75166d1ae700e85c014dcca +RMD160 (NetBSD-6.0/hpcmips/binary/sets/text.tgz) = 8735b6f7b4e4f04f0db4736cce5cced1b12a4cfb +MD5 (NetBSD-6.0/hpcmips/binary/sets/text.tgz) = 69d9e8e32932f359964186ee95b11c42 +SHA1 (NetBSD-6.0/hpcmips/binary/sets/xbase.tgz) = 0299ef346075a8066e40486b3de09de5148940a3 +SHA512 (NetBSD-6.0/hpcmips/binary/sets/xbase.tgz) = 077e6b5023eeb6ccbbdd3ebe6b4f677d8a2ac2e76ff235951fe3cfba327f87149e9dd46abedf0963ef465fa829589a802cd0b1ad76a49b983f1766a881c648c4 +RMD160 (NetBSD-6.0/hpcmips/binary/sets/xbase.tgz) = 3c7a528dfb109df9525b7f41dd3c1a0ef7ce8bda +MD5 (NetBSD-6.0/hpcmips/binary/sets/xbase.tgz) = 24312b9cd85e739ec15b4b53ad6955f6 +SHA1 (NetBSD-6.0/hpcmips/binary/sets/xserver.tgz) = 9faebdfa18d6846a47ee49174a2b510265cf26c0 +SHA512 (NetBSD-6.0/hpcmips/binary/sets/xserver.tgz) = 367f12b49e0ab6793075bed49a4830d8d4ca08eca3d93489c90e55201a4e5d7c1454aaea447684309552c5ca3a695abb800fe9da35ec129f1fc11f80f3d904bd +RMD160 (NetBSD-6.0/hpcmips/binary/sets/xserver.tgz) = ece37a2b4b5096401d6add543d13dc136cabe85d +MD5 (NetBSD-6.0/hpcmips/binary/sets/xserver.tgz) = 3c0b67d9f4dc00af6b197724b41b572e +SHA1 (NetBSD-6.0/hpcmips/installation/miniroot/miniroot.fs.gz) = 1e1ce1cba7ab9b704105a3d52f7c5b17773e9ba5 +SHA512 (NetBSD-6.0/hpcmips/installation/miniroot/miniroot.fs.gz) = f1746402d265c51ed693fd30961d3dd7da011a30ad47ccdc709a2a9a5dd665dd884f91de6d56ecab947d8c958bb572a4a19b8c446ec6644fd2f3b3096b14e615 +RMD160 (NetBSD-6.0/hpcmips/installation/miniroot/miniroot.fs.gz) = 15102213a728cb35bcac2a49f93b496b8f9aa838 +MD5 (NetBSD-6.0/hpcmips/installation/miniroot/miniroot.fs.gz) = d910bba08c66b4454242edd78b73cebc +SHA1 (NetBSD-6.0/hpcmips/installation/netbsd-TX3912.gz) = b1cb178b2c1edd93e4d03ab3205c07c701c1a7ce +SHA512 (NetBSD-6.0/hpcmips/installation/netbsd-TX3912.gz) = b982379b9ed3f09895be90c2dcaff7c041e249102bbf72f6ff41bd9100e28990095563db8de6c6dbd40accf3b11f9e0848c2b1bff5dcf0ab9688e65d5229d39a +RMD160 (NetBSD-6.0/hpcmips/installation/netbsd-TX3912.gz) = 6923c07471d3beb90bdb466c1cb76f03ac65ad00 +MD5 (NetBSD-6.0/hpcmips/installation/netbsd-TX3912.gz) = 8860562df651f9ca3adf61dd62718dba +SHA1 (NetBSD-6.0/hpcmips/installation/hpcboot.exe) = 70e5234558257f49964fcb28a19f544670791c47 +SHA512 (NetBSD-6.0/hpcmips/installation/hpcboot.exe) = bcde10547db4de0623863c93a733706edc1096e2535ff6a7574e86ccab25144c0c653d80ccfb1989eaf685e0b0710eab41f34cc2c45a7bbdc10bb9f845326102 +RMD160 (NetBSD-6.0/hpcmips/installation/hpcboot.exe) = ec4e5dfcbb787ba57de55209e12cbbf891c29f7d +MD5 (NetBSD-6.0/hpcmips/installation/hpcboot.exe) = 9c4073db4cb8cc5a534f709731e271bf +SHA1 (NetBSD-6.0/hpcmips/installation/netbsd-TX3912.symbols.gz) = 6aea661d601c817cef6d1283efe84a23e98bfef8 +SHA512 (NetBSD-6.0/hpcmips/installation/netbsd-TX3912.symbols.gz) = 0ae88640bdd00cfd0f1d908bab889b72f71173a376d26159e5bd9221e4241a867f4050bb9c349bf4225ecc4b82ae558002b3303e7c03e98dff7f72f57b08a9fc +RMD160 (NetBSD-6.0/hpcmips/installation/netbsd-TX3912.symbols.gz) = 1ddaff9ebe6775a9b1f98e3d592c9e38f944a5f3 +MD5 (NetBSD-6.0/hpcmips/installation/netbsd-TX3912.symbols.gz) = ccf4219237474d2c8e2fa02fe33f2e9b +SHA1 (NetBSD-6.0/hpcmips/installation/netbsd.gz) = 75ecc93d0f321a819aca2fafbf58a92651c2ef8e +SHA512 (NetBSD-6.0/hpcmips/installation/netbsd.gz) = 94ef6d49c91ac5ffba39ada8854d3a7be535bdcc7a5121a4941255a30a8c9d68acaebcb1e99ad804360910a45562e3c17b307819ed4f97c1f9a4900c765ac06c +RMD160 (NetBSD-6.0/hpcmips/installation/netbsd.gz) = 10470fb18a31416543c016667bcbcaab1b454297 +MD5 (NetBSD-6.0/hpcmips/installation/netbsd.gz) = 1acf8ad6849c07fb17c0646acf7e76c2 +SHA1 (NetBSD-6.0/hpcmips/installation/netbsd.symbols.gz) = 8a2bfae03f350dc2c9d83709c8255b8ee4eb9e15 +SHA512 (NetBSD-6.0/hpcmips/installation/netbsd.symbols.gz) = c4917814e14d1163139be52927a5a59d422304289239eae15e91495a9964a16e005865f231b3647964bdfed2658d955ef983fccda7775616df92487e10f36b53 +RMD160 (NetBSD-6.0/hpcmips/installation/netbsd.symbols.gz) = b353f7752d20b78218082d129e4ed5b6702ee2a2 +MD5 (NetBSD-6.0/hpcmips/installation/netbsd.symbols.gz) = 453e0c8ae44500b483151a83e1689a2f +SHA1 (NetBSD-6.0/hpcmips/installation/pbsdboot.exe) = 3b0a8ac9c0d4c6e7fef95970e81f1ae42462f405 +SHA512 (NetBSD-6.0/hpcmips/installation/pbsdboot.exe) = 28b6b8b3ac983d5fa9ae9dd28127981367720c3754a88fd0b08e404093c657df3df93bceae63835fdaf021fd608002464411818ef3e9becf100e0e7ffd94fcbc +RMD160 (NetBSD-6.0/hpcmips/installation/pbsdboot.exe) = d713fda3478b92d9dc71347122a1fd7bac6cab9b +MD5 (NetBSD-6.0/hpcmips/installation/pbsdboot.exe) = 5c184fc062316a94d8408adf0884bee2 +SHA1 (NetBSD-6.0/hpcmips/installation/pbsdboot1.exe) = e937c9bf2759e58c32523ff19c45feeb5e90fe77 +SHA512 (NetBSD-6.0/hpcmips/installation/pbsdboot1.exe) = 65e044958194d15fd58b222dba5470343068ffbe968d43819b11744c711bf75083d1e61df0e433ac846629d8d0ccd14ccd0388b58424a123d4018f9731b6415d +RMD160 (NetBSD-6.0/hpcmips/installation/pbsdboot1.exe) = 9e072b9c080bcfa4213b36fe9d85ac684de46f06 +MD5 (NetBSD-6.0/hpcmips/installation/pbsdboot1.exe) = 4d6c719c61a98aae297369c41e3991a8 +SHA1 (NetBSD-6.0/hpcmips/INSTALL.html) = 34d4a448b23da2e50007d37ba33938d78baf8b03 +SHA512 (NetBSD-6.0/hpcmips/INSTALL.html) = 508dd90bf6b4543b31108ec82b96a8ef765ffd29d2fcfbb463e380bd8cff6909fcad9673a8c7307b8a524347c20c117a94220dc743813028785520f1739b8d89 +RMD160 (NetBSD-6.0/hpcmips/INSTALL.html) = 3e111666257f4bcbc22fba2a542559733ab56f28 +MD5 (NetBSD-6.0/hpcmips/INSTALL.html) = cea8b96d283b5ddec4b1be43b327a986 +SHA1 (NetBSD-6.0/hpcmips/INSTALL.more) = d4dc5bdab669d3e4a97c6e07e3a4e6634a171103 +SHA512 (NetBSD-6.0/hpcmips/INSTALL.more) = 90924423731cdaeca599d151e56ef996a4a217432ffe1791b3bf7ad2ea3e025ae031d9e237377d1cd7fbab33a6e8e666909a77bb4867be3aac99340e4292d140 +RMD160 (NetBSD-6.0/hpcmips/INSTALL.more) = d8517223e07059e28737972d4cc4ebee900a308f +MD5 (NetBSD-6.0/hpcmips/INSTALL.more) = 6b918c9fc18e093fdae5e4c61fe2fe3e +SHA1 (NetBSD-6.0/hpcmips/INSTALL.ps) = eb7befb368fa0e792db5c250f1cf7cfa9d21d529 +SHA512 (NetBSD-6.0/hpcmips/INSTALL.ps) = 42f376e89f871f1a1f223d12816ffa887891818897a591d7b6ac0495c088559eac383449569dda24bfae563991e775c89b55dbec27aac2449ce5363c02581ec9 +RMD160 (NetBSD-6.0/hpcmips/INSTALL.ps) = 718659993cfe1a81d63fcb9b7717e551c7213944 +MD5 (NetBSD-6.0/hpcmips/INSTALL.ps) = 660ff8cf43dcbeacb63a10a2ac4442cd +SHA1 (NetBSD-6.0/hpcmips/INSTALL.txt) = 93686fc2958437cddbb8e0ab34efa7a153b16939 +SHA512 (NetBSD-6.0/hpcmips/INSTALL.txt) = f71addf8728978547ec7d560a4590e392cfb55bd2d06b9987def48a08373fa27fdc7d2d1bfd241d6c9d8b22297b180b434043ffbbe86281b56edb9d4b714a567 +RMD160 (NetBSD-6.0/hpcmips/INSTALL.txt) = 0da553b2c528d6766776dfae2005bd6ff531e905 +MD5 (NetBSD-6.0/hpcmips/INSTALL.txt) = 3c60451e18599c7e2d8bc6a79c6fc8e9 +SHA1 (NetBSD-6.0/hpcsh/binary/kernel/netbsd-GENERIC.gz) = 0a43926fc91b70cb80d51c78394a2fa54fd98ae1 +SHA512 (NetBSD-6.0/hpcsh/binary/kernel/netbsd-GENERIC.gz) = 42ba58126c60285a642156c27dfa9d89009b41739a832898f876abe6387edac7c36f08e71028c326ef617a29020e525d779def3e583381645b5a1fc6ba6413b3 +RMD160 (NetBSD-6.0/hpcsh/binary/kernel/netbsd-GENERIC.gz) = 0d01f666a4b6fd2df148381e442ee85aa8afc635 +MD5 (NetBSD-6.0/hpcsh/binary/kernel/netbsd-GENERIC.gz) = de0c019c15358bd1673689f590e64529 +SHA1 (NetBSD-6.0/hpcsh/binary/kernel/netbsd-HPW650PA.gz) = c0359ab834228b4b0af9fd92ec0870cfa424fcab +SHA512 (NetBSD-6.0/hpcsh/binary/kernel/netbsd-HPW650PA.gz) = 6e2d1f10d4eda5725c7293c179162091fb9f04630f14bf37506e49700178b1baee5594ccf70fa3ede42ef702bb512016d9edef3a23cd0777fd40f961a43ba021 +RMD160 (NetBSD-6.0/hpcsh/binary/kernel/netbsd-HPW650PA.gz) = f6b944beeaf6fda516165b2196b429db28741e96 +MD5 (NetBSD-6.0/hpcsh/binary/kernel/netbsd-HPW650PA.gz) = 7dc95c93d4b9b5a94e566c9f5565bd74 +SHA1 (NetBSD-6.0/hpcsh/binary/sets/games.tgz) = 2040b4af557a62f2ade5fc9fcfe4cab3df88c7e2 +SHA512 (NetBSD-6.0/hpcsh/binary/sets/games.tgz) = 8b5071337dc844042537c24c75660e61c9709cd10cbbeab059a84da6d482260b73365ff3870f85060c130a291b6f02be174d288127ca62ce4d291a6982192317 +RMD160 (NetBSD-6.0/hpcsh/binary/sets/games.tgz) = 28acfa5a131d52df7c157e2edca1dd0f20e774dc +MD5 (NetBSD-6.0/hpcsh/binary/sets/games.tgz) = d82c46dbc0021fd4694e464042936052 +SHA1 (NetBSD-6.0/hpcsh/binary/sets/man.tgz) = 899b9d8242e983a5110ab755651c24f709b5af67 +SHA512 (NetBSD-6.0/hpcsh/binary/sets/man.tgz) = 410999db110d710f4bb498c3d7ae7adc62170c7c2f470ce189c92f6c436c5ea96149659c631ef0b5605caaa025d97dfe1c07c428d86f51239657bd6b71717b15 +RMD160 (NetBSD-6.0/hpcsh/binary/sets/man.tgz) = c1270f68c6d41b351877f71f0396ac34877dfc8d +MD5 (NetBSD-6.0/hpcsh/binary/sets/man.tgz) = df4db2bbfa39ef6a4a215d949653d04a +SHA1 (NetBSD-6.0/hpcsh/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/hpcsh/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/hpcsh/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/hpcsh/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/hpcsh/binary/sets/xcomp.tgz) = 53aa1e2a910e8eed09dc07f8b724804f53fe5e2f +SHA512 (NetBSD-6.0/hpcsh/binary/sets/xcomp.tgz) = 24645da85419528015cdaefd0c835741fa801392e795b363bdfc39558e75e7f384511c0668d12e2440114b7c543c7532aaec438048f08d35c54c9c7a748f20c0 +RMD160 (NetBSD-6.0/hpcsh/binary/sets/xcomp.tgz) = 60a461ffc1f1562274110d65c72a541ee131cd21 +MD5 (NetBSD-6.0/hpcsh/binary/sets/xcomp.tgz) = f1d2650a8d7a4ecd60fda8e1aaf8c09b +SHA1 (NetBSD-6.0/hpcsh/binary/sets/xetc.tgz) = 1636a6fe3e01f6d8a07a19cd204a6807c8caa4c7 +SHA512 (NetBSD-6.0/hpcsh/binary/sets/xetc.tgz) = 9cea4ba4af287dd57e591d4269f2f2582010250316f323746ac56b12cefcf2590b93fbb0197c665f61b1df41dcca62d17fb6ad80d4b1feb8ac8265e91e15074f +RMD160 (NetBSD-6.0/hpcsh/binary/sets/xetc.tgz) = 5f68e3f96f7bb9ae07fccdb1d058e4b1307b4b29 +MD5 (NetBSD-6.0/hpcsh/binary/sets/xetc.tgz) = da84d97230787283e215a4ee1c4053ad +SHA1 (NetBSD-6.0/hpcsh/binary/sets/xfont.tgz) = 97439ccf6840b18b1e9885f5504a401bf1a93650 +SHA512 (NetBSD-6.0/hpcsh/binary/sets/xfont.tgz) = 3d15541f7d7ae2128f44355bf110415adfa4e5182829259d2c6f7a4217feff99e236d13c5bb7bbeb724ff1a09ac1f58f02bdd6eef528bc416ec3118db6fc7d45 +RMD160 (NetBSD-6.0/hpcsh/binary/sets/xfont.tgz) = cdc9fcdb5fd5032803d5bba18db58f3ea6d62c85 +MD5 (NetBSD-6.0/hpcsh/binary/sets/xfont.tgz) = a8466a0477c6c443eafe99e9d1c61131 +SHA1 (NetBSD-6.0/hpcsh/binary/sets/kern-GENERIC.tgz) = 567f596fd760416c4805a60ccdc39634394b368a +SHA512 (NetBSD-6.0/hpcsh/binary/sets/kern-GENERIC.tgz) = 517a450a02d80e4ae14463b5abcbb4e887d404ac5fd97a2d70092d9d53b6117af874171db26e1b43712b81f6f5f7c23d34ef4d6ee60a911c1288f07ed86675ba +RMD160 (NetBSD-6.0/hpcsh/binary/sets/kern-GENERIC.tgz) = 9f9a50ba10b38fd0a92e4671a61dc968ed206c49 +MD5 (NetBSD-6.0/hpcsh/binary/sets/kern-GENERIC.tgz) = 43c86c80541870470199c27117d78bdd +SHA1 (NetBSD-6.0/hpcsh/binary/sets/base.tgz) = 09469ee791c205b746f290108fb4e0fd2d2e157c +SHA512 (NetBSD-6.0/hpcsh/binary/sets/base.tgz) = b4f946a01df921d1b6b83db51e4da06934be1c23d5bd8602d357c4716524a944abd24f9053c130121a05a0a73b06124b1fb8d2e433b461e7122a6f7994b70d4f +RMD160 (NetBSD-6.0/hpcsh/binary/sets/base.tgz) = 9ba69deac2b406c07e38117048bc439865eb8061 +MD5 (NetBSD-6.0/hpcsh/binary/sets/base.tgz) = 7a62d7baa2d993d1de3d579d7076fdb2 +SHA1 (NetBSD-6.0/hpcsh/binary/sets/comp.tgz) = 2487c8289908b3f46b47dfe16a78d041d159e4a9 +SHA512 (NetBSD-6.0/hpcsh/binary/sets/comp.tgz) = 9e89c2f701cd69fc74aeb6ab03304f4bb51d73b6ff6c75b93906d2b05e42639e1da36dbce39a37519070a991bf5efe9ae93b29b6ae20da42fe2b01e951a51cf1 +RMD160 (NetBSD-6.0/hpcsh/binary/sets/comp.tgz) = 3843c49d31f966f8d41b2b07407d5952eb788d18 +MD5 (NetBSD-6.0/hpcsh/binary/sets/comp.tgz) = 313b69abf3e1a78923f1a7c5c6f171b4 +SHA1 (NetBSD-6.0/hpcsh/binary/sets/etc.tgz) = 0ede2593731365cb6501ca69865e1fdcfa72717c +SHA512 (NetBSD-6.0/hpcsh/binary/sets/etc.tgz) = 612da4fc764826c7f374c846d7712c4142d1cd041eb13944c578054fec342a2cb435c8815f9c477afc70a5655e35e9fb9eb1d01ee6c57218c944c6e11f18ffd7 +RMD160 (NetBSD-6.0/hpcsh/binary/sets/etc.tgz) = e226671156547333000c60e32b9b24376cc63885 +MD5 (NetBSD-6.0/hpcsh/binary/sets/etc.tgz) = 420c5afbc0c1dd6c1d7a085979bab643 +SHA1 (NetBSD-6.0/hpcsh/binary/sets/kern-HPW650PA.tgz) = 5534a47bdec7e7e6ce7d5474d3b159ffebe72cd1 +SHA512 (NetBSD-6.0/hpcsh/binary/sets/kern-HPW650PA.tgz) = a7d789cafbe113131a7a93700ec06da4256ab5f93513d2ce96e0ed715a7dd99e866a89a907336a761ff53e53c20ca325b4a569198b75ca806e810395638a0ebd +RMD160 (NetBSD-6.0/hpcsh/binary/sets/kern-HPW650PA.tgz) = 2dcb3e3e54ce471cd2185469e4f788aeef5c6539 +MD5 (NetBSD-6.0/hpcsh/binary/sets/kern-HPW650PA.tgz) = e146321b865991498743de2b41a3c034 +SHA1 (NetBSD-6.0/hpcsh/binary/sets/modules.tgz) = 36ccb3afb83508f713aa2aabd8c66990a7bee974 +SHA512 (NetBSD-6.0/hpcsh/binary/sets/modules.tgz) = a9cc7bdcc7e3cb7aab35d329095b0b67cb46b13850f9897433539ce2836b96d38ba69ec95515ae8988a80864f865546dbb619352261f8e413ac21580c78a7be4 +RMD160 (NetBSD-6.0/hpcsh/binary/sets/modules.tgz) = 29b45abec58e7be9e801cf6a2be74bcc56df595e +MD5 (NetBSD-6.0/hpcsh/binary/sets/modules.tgz) = 82ca10605dffe603d39ad994e305b53e +SHA1 (NetBSD-6.0/hpcsh/binary/sets/tests.tgz) = d7eb3b59410ff4f341e9dd65c9995e160684fada +SHA512 (NetBSD-6.0/hpcsh/binary/sets/tests.tgz) = 443ff8b932876a515b75ac9b4eb1e225d2d09bd7dfc531f6e19f812e659de4644d0aac96ca74e73aa877bffbaddf13d308905f28cfe23d48a6cef1decf9b820b +RMD160 (NetBSD-6.0/hpcsh/binary/sets/tests.tgz) = 7030e2b09ddbe4bd952524d58f0916b2079a4bb1 +MD5 (NetBSD-6.0/hpcsh/binary/sets/tests.tgz) = 9a95f9e73414b2c3ad7acbb2241178fe +SHA1 (NetBSD-6.0/hpcsh/binary/sets/text.tgz) = 028f0e33f75acdbab625786cec067f630aa63e4a +SHA512 (NetBSD-6.0/hpcsh/binary/sets/text.tgz) = 434ec2e2627f4068e75db33cf4ad353ae1c7437c21d4aa0e861f06fb5eb1d85bae5ca15f7c1091017f76adb8b517a6e7860c5a406d157cf4485c1e6acfedfdda +RMD160 (NetBSD-6.0/hpcsh/binary/sets/text.tgz) = 37213e71f1fe2e1d8222d4b64ea6cbbbd2e40a4f +MD5 (NetBSD-6.0/hpcsh/binary/sets/text.tgz) = da797fc1c503a808baea4b873b4575eb +SHA1 (NetBSD-6.0/hpcsh/binary/sets/xbase.tgz) = 3c17cc530069599ced85ef999be6012422973217 +SHA512 (NetBSD-6.0/hpcsh/binary/sets/xbase.tgz) = 3dd6421f3248867b6015fcc420b29dcdbe82506c75b7bdd9698dc55b1a93e54d078cc93a68015ccf4bae00dcc96695702acde53f0a47f521116081f44255e205 +RMD160 (NetBSD-6.0/hpcsh/binary/sets/xbase.tgz) = f3a5a0df1ced2758ac1016c970034a8a7e9f16c2 +MD5 (NetBSD-6.0/hpcsh/binary/sets/xbase.tgz) = fef3052b786c27898ebfcab88012729d +SHA1 (NetBSD-6.0/hpcsh/binary/sets/xserver.tgz) = e518391c0fa08ecefd59c19049aa8b6e05427683 +SHA512 (NetBSD-6.0/hpcsh/binary/sets/xserver.tgz) = 85fe307f64bf7b5eb0300293426a377ddde46de15d7cdc7365eea65651d5b952cee395107dc6d73c55b19d43b19c47bac3bdc253d251c5f98858cd2d0aee8cad +RMD160 (NetBSD-6.0/hpcsh/binary/sets/xserver.tgz) = 04274aa41e6f003c492c4d27e8a7182694a98386 +MD5 (NetBSD-6.0/hpcsh/binary/sets/xserver.tgz) = 3fb668ea3e2d13574cd78b5a59cc40df +SHA1 (NetBSD-6.0/hpcsh/installation/miniroot/miniroot.fs.gz) = d65c961e5411c64f1110f55036f20c59b3a4ef75 +SHA512 (NetBSD-6.0/hpcsh/installation/miniroot/miniroot.fs.gz) = 95a54cd59939533feb467c23085569f35f2ac246a205825acb84ad8c144ae0c6cda888844270f74d452c5bbf4bd7056e9ae62e56f22c598f21a2cb92dcd8499b +RMD160 (NetBSD-6.0/hpcsh/installation/miniroot/miniroot.fs.gz) = 10cd9e01b234129588477829523bed1ea19164f2 +MD5 (NetBSD-6.0/hpcsh/installation/miniroot/miniroot.fs.gz) = f5098b166d3da210356a284e484315e5 +SHA1 (NetBSD-6.0/hpcsh/installation/netbsd.symbols.gz) = 1a92b94312e5e4cdf5c088342d52040948fefc6c +SHA512 (NetBSD-6.0/hpcsh/installation/netbsd.symbols.gz) = c0ca68315dee6c402bcd7a0180808d4a1c9fab799466d76a8fb460ae110c22fee7ceae5dbac451cb7a0d7ddb59d3af49f3965de88201778c7b14513f2ba1e61a +RMD160 (NetBSD-6.0/hpcsh/installation/netbsd.symbols.gz) = d9c41a7a101b96727c040c0fdd992ba57999fc89 +MD5 (NetBSD-6.0/hpcsh/installation/netbsd.symbols.gz) = 67c48072e6d7c01c9c35c60071d1e371 +SHA1 (NetBSD-6.0/hpcsh/installation/hpcboot-sh3.exe) = 567ca586f3c3604143e61ee4b644faed466cf60c +SHA512 (NetBSD-6.0/hpcsh/installation/hpcboot-sh3.exe) = bbbda6cb7c671816e07ac1ba9a05f57632f501019f9e7e2b3a373aa2b55bd56d600f7a6353fe433201284b0ff43908bc988f12568d95b251e8b89d5d5656b244 +RMD160 (NetBSD-6.0/hpcsh/installation/hpcboot-sh3.exe) = cac5d9056182928594f5c15b2c5d8a6bb54e6654 +MD5 (NetBSD-6.0/hpcsh/installation/hpcboot-sh3.exe) = af41643f4b488f837514418c34d06eee +SHA1 (NetBSD-6.0/hpcsh/installation/hpcboot-sh4.exe) = 3b04443ede94fb5345be01440dfac5c600e46683 +SHA512 (NetBSD-6.0/hpcsh/installation/hpcboot-sh4.exe) = 60ae23af771f81a472d5ea84b5df140f9b2c2678753ca1878d51157366c9d04253a41b19a6bb5ef08ce755ec82b9fa67f82209fa6a0e49eb507e4ba8118dbc3e +RMD160 (NetBSD-6.0/hpcsh/installation/hpcboot-sh4.exe) = 69a4509e0e173a94a2720f1469a00dd424e19ee4 +MD5 (NetBSD-6.0/hpcsh/installation/hpcboot-sh4.exe) = d259e7fcc3c329c95448f96b7fda6920 +SHA1 (NetBSD-6.0/hpcsh/installation/netbsd.gz) = 77bc4656ee9ce29522e56beeedf26cdec6df77ef +SHA512 (NetBSD-6.0/hpcsh/installation/netbsd.gz) = 98ba42e9f3d8be016785ef5a807d009f6f8cf46a7c9c4abd8ad860fca5db37bbae22bdfe54bcd8b5963b1d0aa8610fca21402817ceac6b6e59a2c8cf7e986f21 +RMD160 (NetBSD-6.0/hpcsh/installation/netbsd.gz) = 705cf57dfbf1a1ee4e3629d1d82a60b8aa8cd6b6 +MD5 (NetBSD-6.0/hpcsh/installation/netbsd.gz) = 75c72e83a03c4d9f316f28e81c428c2b +SHA1 (NetBSD-6.0/hpcsh/INSTALL.html) = 8ab73c33b0ecde2e0b0beea372a7996e866553ef +SHA512 (NetBSD-6.0/hpcsh/INSTALL.html) = 7d7f628cd37890c8db79d76dcc9d87984b6ded522ccb2cb5670aa4a40114b1b323cb78b1b7274bb4bd27daefa25c3ee1dd0c6611736222ee546d0dd895cd6e52 +RMD160 (NetBSD-6.0/hpcsh/INSTALL.html) = 1e3edb91c943f9e1aa17315a592f5c68e7d66487 +MD5 (NetBSD-6.0/hpcsh/INSTALL.html) = 7b6883d6de2349156019286bbf61d14f +SHA1 (NetBSD-6.0/hpcsh/INSTALL.more) = 29137bc092201f10bb2f2725d72299b5e5475b5b +SHA512 (NetBSD-6.0/hpcsh/INSTALL.more) = 6a8737896c43bed9befbd131f8b13fc6070008f13bf9a9e798cc5bcb2210271f92c8b4138b20e716b5f48aeb478bc7ca9be66347d8636fdecd7bebb013b35ebc +RMD160 (NetBSD-6.0/hpcsh/INSTALL.more) = b50c579d04464e3781f5bf7dcb4b69327d79a9a9 +MD5 (NetBSD-6.0/hpcsh/INSTALL.more) = 4f08e258b707193fea1797d2915df90f +SHA1 (NetBSD-6.0/hpcsh/INSTALL.ps) = bc5b3e51e6a6f8a09ccac7db7f1ac85366921911 +SHA512 (NetBSD-6.0/hpcsh/INSTALL.ps) = 3945a024ba07da3ff29847c33f4061c8395113eaadf053b603b1391c3b994ee23c271442d90b8e9cfe104aee458348422068b5e704f8c89f2cd248e248414f36 +RMD160 (NetBSD-6.0/hpcsh/INSTALL.ps) = fadfccdee249158cab774c1bae128f6889f9bbd1 +MD5 (NetBSD-6.0/hpcsh/INSTALL.ps) = 01cdb6201ba834eb25dd70d0cd7dd827 +SHA1 (NetBSD-6.0/hpcsh/INSTALL.txt) = b291d1be7635867dda1fe5ffb3f24d41b43107ff +SHA512 (NetBSD-6.0/hpcsh/INSTALL.txt) = 7a5ecbef64ad55680dcaa3e58319a5019096e1fef9ff24de2a8401c29b4006520dc724ff740c14f8bf56cc4fca1bf26a5525040c63d0de3559cfdc7f34710e2c +RMD160 (NetBSD-6.0/hpcsh/INSTALL.txt) = a2e4347c690cb982b5097800f74a3729dc6c2628 +MD5 (NetBSD-6.0/hpcsh/INSTALL.txt) = 39020135702f1291d2691258a598ef52 +SHA1 (NetBSD-6.0/i386/binary/kernel/netbsd-GENERIC.symbols.gz) = 747df3225196d826d632a750770850510c725c3d +SHA512 (NetBSD-6.0/i386/binary/kernel/netbsd-GENERIC.symbols.gz) = bf7546bf878dc86c2579e4660adfe0dfc2e7aa06416526ba2ce70425fee806f92bd7e61d2211aa8f302e167f77dd5e61674a1144274be7a3b9a14c13f2a758f0 +RMD160 (NetBSD-6.0/i386/binary/kernel/netbsd-GENERIC.symbols.gz) = e2aef01c044902e8685f72d3f0bba4b0ed6857ce +MD5 (NetBSD-6.0/i386/binary/kernel/netbsd-GENERIC.symbols.gz) = 71aca09f9e5bd22fd42144fbadabcda5 +SHA1 (NetBSD-6.0/i386/binary/kernel/netbsd-GENERIC.gz) = d680282ec53e51ed2f2df312764748ef2dbce31f +SHA512 (NetBSD-6.0/i386/binary/kernel/netbsd-GENERIC.gz) = b9c3bf1bd9a442e5a7e7f515561771436b4c43e44cf454db37c94070de292aa6c00ab0a95957f80f71ffaa517a60dc1651bcb4452853f35fd541cbca2df87139 +RMD160 (NetBSD-6.0/i386/binary/kernel/netbsd-GENERIC.gz) = 60783b17fa32bdef611c8c8c793248f2494f8b4f +MD5 (NetBSD-6.0/i386/binary/kernel/netbsd-GENERIC.gz) = 780873f1a06cad1f8e2644f2827e6b8b +SHA1 (NetBSD-6.0/i386/binary/kernel/netbsd-INSTALL.symbols.gz) = 986e2b589d49d58105c82c1a3bf8d4292f5ec1c0 +SHA512 (NetBSD-6.0/i386/binary/kernel/netbsd-INSTALL.symbols.gz) = 0919e2e21da9aace7144d82119ecf8097548ad7179b5f8b495b72b6ad75544c72d462526d7625a2b42fbf9c68a436b2d233ca7e06367f5ddf5be3386d67659ac +RMD160 (NetBSD-6.0/i386/binary/kernel/netbsd-INSTALL.symbols.gz) = 4abf1e4dd5c1df9578a256eb7fc9bfc6de174f60 +MD5 (NetBSD-6.0/i386/binary/kernel/netbsd-INSTALL.symbols.gz) = acd73bddb752df740099d651da32881d +SHA1 (NetBSD-6.0/i386/binary/kernel/netbsd-INSTALL.gz) = 88fdedc8bea8f6e139947e6e4a8922324a2073a2 +SHA512 (NetBSD-6.0/i386/binary/kernel/netbsd-INSTALL.gz) = 0f13507f05a4dc76faa937fbb9dc8c5107b55e2a7dbcd97a6fd2dede7c2dff1f16ff0b908433b826125a2e1f5c4b9d14b9a809e920b92acd88968588b8129f1a +RMD160 (NetBSD-6.0/i386/binary/kernel/netbsd-INSTALL.gz) = 0b7be220f16b74210af24ce8bbb42402909ad847 +MD5 (NetBSD-6.0/i386/binary/kernel/netbsd-INSTALL.gz) = 85d626d678c978ad387238dfc76e20a9 +SHA1 (NetBSD-6.0/i386/binary/kernel/netbsd-INSTALL_XEN3PAE_DOMU.gz) = 82987dd8d3d035c3741ec54e567c797aa527b85e +SHA512 (NetBSD-6.0/i386/binary/kernel/netbsd-INSTALL_XEN3PAE_DOMU.gz) = 43c9d6c594b997834e1bfadf63a20fe0735947419a1e86e9e06bc97a7953738219eba2072f9a7b1fa6b23870287be413650145234d2c58166138bb00bd0136a2 +RMD160 (NetBSD-6.0/i386/binary/kernel/netbsd-INSTALL_XEN3PAE_DOMU.gz) = c0c2edf5e75878f0a07a2d7f971d020a16bd33dc +MD5 (NetBSD-6.0/i386/binary/kernel/netbsd-INSTALL_XEN3PAE_DOMU.gz) = a6a8ef4a7c0da213a9821e7f2d0e18c8 +SHA1 (NetBSD-6.0/i386/binary/kernel/netbsd-INSTALL_XEN3_DOMU.gz) = 67b61d551fd822e4578b9a8d54bc4a08a39f8b34 +SHA512 (NetBSD-6.0/i386/binary/kernel/netbsd-INSTALL_XEN3_DOMU.gz) = bfdb3e7ab7a5456434117156bd187d1f111eeedbc7a2d568266fecfeab33bf847fcc4b72e6edffe8015841b87aa04645c1c0442ce521c8965cd7007326b38e78 +RMD160 (NetBSD-6.0/i386/binary/kernel/netbsd-INSTALL_XEN3_DOMU.gz) = c5378820ecdb9baf20fabded1f5caa4a1d6a3021 +MD5 (NetBSD-6.0/i386/binary/kernel/netbsd-INSTALL_XEN3_DOMU.gz) = a09e8070066fb225a26b0904422e1704 +SHA1 (NetBSD-6.0/i386/binary/kernel/netbsd-MONOLITHIC.gz) = 205b7f5a5c457a2db4c997c75c02d1f55a0692e7 +SHA512 (NetBSD-6.0/i386/binary/kernel/netbsd-MONOLITHIC.gz) = 68953183a437b13d94af72acbc231553e6aa57f4e3acbe432e710ad452317b974509a9ae83ea0f350d24164de4d1ae6a3d8d4a221e31c61734b67df026b93b03 +RMD160 (NetBSD-6.0/i386/binary/kernel/netbsd-MONOLITHIC.gz) = 11fd88405a800b36b7b030991e632d17992f5e15 +MD5 (NetBSD-6.0/i386/binary/kernel/netbsd-MONOLITHIC.gz) = f746f0b2fcebfb329cdd45181f2acb74 +SHA1 (NetBSD-6.0/i386/binary/kernel/netbsd-XEN3PAE_DOM0.gz) = 6c7943423d026377f0d9308e8aac75d52f08907c +SHA512 (NetBSD-6.0/i386/binary/kernel/netbsd-XEN3PAE_DOM0.gz) = a2fea33cd4aaebb2c2e69d8790ea40b0c2f00e8be3a823ca93274e534a751fe04efdc9d5ed7fc15897c42c9cc7d987ee645f50897cf6ef55383c448885a324f5 +RMD160 (NetBSD-6.0/i386/binary/kernel/netbsd-XEN3PAE_DOM0.gz) = 948c072d5d1424578e2ff5bc3bc7bca39364f8e0 +MD5 (NetBSD-6.0/i386/binary/kernel/netbsd-XEN3PAE_DOM0.gz) = 1d4aafba1a470802f7f2c7e10e98ca52 +SHA1 (NetBSD-6.0/i386/binary/kernel/netbsd-XEN3PAE_DOMU.gz) = 2ae71d2f1c2b512d124e2d92d431ab5b2c1f05a7 +SHA512 (NetBSD-6.0/i386/binary/kernel/netbsd-XEN3PAE_DOMU.gz) = 9b553c5b145d2b29b9032416bc01f5c43bbad80f2c6feb1e96c881e4d1dd77c02740413cefbbd4fb6cd247cb75fd24959d5a60d3210020548236e3a14a82a65a +RMD160 (NetBSD-6.0/i386/binary/kernel/netbsd-XEN3PAE_DOMU.gz) = 2b884a96bb6cdc3059448104c7ddafc31be7c188 +MD5 (NetBSD-6.0/i386/binary/kernel/netbsd-XEN3PAE_DOMU.gz) = dba74b4cb61cf1606556492f6f1b213c +SHA1 (NetBSD-6.0/i386/binary/kernel/netbsd-XEN3_DOM0.gz) = 7b21a86bc29b1573539105b83e6f847124afee15 +SHA512 (NetBSD-6.0/i386/binary/kernel/netbsd-XEN3_DOM0.gz) = 9f0a07816ba899e5d003750e1320c6f83c66bee70b71b1356980e64019a4eeff2ee105eea33dc31822c614609782e3143c6575afa7cd9dbfdf05c119ab2cb92c +RMD160 (NetBSD-6.0/i386/binary/kernel/netbsd-XEN3_DOM0.gz) = e976db5aa9e2e5e1109f804913e5a8f075708f85 +MD5 (NetBSD-6.0/i386/binary/kernel/netbsd-XEN3_DOM0.gz) = b8ec7670143458921b7dd71f05251257 +SHA1 (NetBSD-6.0/i386/binary/kernel/netbsd-XEN3_DOMU.gz) = f528d474640a5bda692eb50859c208f2277ca61f +SHA512 (NetBSD-6.0/i386/binary/kernel/netbsd-XEN3_DOMU.gz) = 24f2b7317b51e12e15084d1aad1177a63d37be3ecc3777de4f7b2b93076e4c980a4667c7013db8bdb500e033e745adb665c45aa842d4422494d67beb3f2f4442 +RMD160 (NetBSD-6.0/i386/binary/kernel/netbsd-XEN3_DOMU.gz) = 373525999967fd37d620cea1b0b38692ea102d64 +MD5 (NetBSD-6.0/i386/binary/kernel/netbsd-XEN3_DOMU.gz) = f76afc8d70580acebe22d4daba31df3b +SHA1 (NetBSD-6.0/i386/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/i386/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/i386/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/i386/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/i386/binary/sets/kern-GENERIC.tgz) = dfbdb16d93f42cafac4314e173c3698abb2b2249 +SHA512 (NetBSD-6.0/i386/binary/sets/kern-GENERIC.tgz) = 572284b4e2daab363f9f89f6bb9b80428f6d048fbb70120541b7cff881ed7fd8145b2a5dcafb63160a4292d286e57a3191154267167cedb7641f1ee3098072fc +RMD160 (NetBSD-6.0/i386/binary/sets/kern-GENERIC.tgz) = e663f76167f352828f007b3271408d0c4d1f6735 +MD5 (NetBSD-6.0/i386/binary/sets/kern-GENERIC.tgz) = 43a3993a20de2d5c58aa9a1aa90dc667 +SHA1 (NetBSD-6.0/i386/binary/sets/base.tgz) = 5847817e7b75483373fe51fb6b465404cb74e1ad +SHA512 (NetBSD-6.0/i386/binary/sets/base.tgz) = 927acc412e1372e2205d4c90fe017b2812bbd6036823b6a18bfcc33513279bdf9f02731b874ad73f614da46194bdacd525a8bf9e301c5842f3f6475fa27507be +RMD160 (NetBSD-6.0/i386/binary/sets/base.tgz) = b36be3ba67b7b2209c5baf2fe314ddc2a7254054 +MD5 (NetBSD-6.0/i386/binary/sets/base.tgz) = c643ea74ea234056b1f741a561790c1f +SHA1 (NetBSD-6.0/i386/binary/sets/comp.tgz) = 0f22e69dce5b6678e1ab117b875c7b28f2a1224a +SHA512 (NetBSD-6.0/i386/binary/sets/comp.tgz) = 99a73445be3ac1354a3ec94c7b4d231d3fe72bc2bc7cc020c9dd4c74d5fa06f1a7e681f48a2dbf3e90f0d8e611d51e6524883a1a4edf1494607259bc1c49a99b +RMD160 (NetBSD-6.0/i386/binary/sets/comp.tgz) = 1bae0e183624d0dc957e24eb52041e2b3e42492c +MD5 (NetBSD-6.0/i386/binary/sets/comp.tgz) = 5cff8ef6491c3b9270310558ca8360db +SHA1 (NetBSD-6.0/i386/binary/sets/etc.tgz) = 00df7a05fddcdbbf9e0ee430c634fd1e1da2a2db +SHA512 (NetBSD-6.0/i386/binary/sets/etc.tgz) = 0100afa02f2c0f09bcbe513b282b7e23124b94d5d77816f88c7b927e0625bedde3020b0c34e03f26da5d53941cdb0aac1398d2e15c9b4bc6cbb4e46e4bf8786a +RMD160 (NetBSD-6.0/i386/binary/sets/etc.tgz) = 978efa1d91dea561eaa148f4da679a88e1730c7e +MD5 (NetBSD-6.0/i386/binary/sets/etc.tgz) = 3f174862437df05c82293f93a42a52f3 +SHA1 (NetBSD-6.0/i386/binary/sets/games.tgz) = eb79bb969242401a2573c8cb861e399f374ffdce +SHA512 (NetBSD-6.0/i386/binary/sets/games.tgz) = 537eaab987a71933b63673477c276cf3b558f4dd46331ea224f5c0f2b0ac387fb591a7880b1055225746b9c46fcb4ff0f8b72382a629abc6af6315ee038c0d0d +RMD160 (NetBSD-6.0/i386/binary/sets/games.tgz) = cfbc8842fcc975fdff71c6fc472396d533d8aa5c +MD5 (NetBSD-6.0/i386/binary/sets/games.tgz) = df096416d676f1a44710711d7c895329 +SHA1 (NetBSD-6.0/i386/binary/sets/kern-XEN3PAE_DOM0.tgz) = 714c9b6c0a41973c06ea62a97babb7000ea1245e +SHA512 (NetBSD-6.0/i386/binary/sets/kern-XEN3PAE_DOM0.tgz) = 97529a4c90a36ad65bec57dca59bc80f724981c4358d32195e3b4e614761fae96a79cab552fe0388e7c8e57da581a2b07a84a44d12d32f23e6ce45c771493ccc +RMD160 (NetBSD-6.0/i386/binary/sets/kern-XEN3PAE_DOM0.tgz) = 0171b60434e21cf6d29d38300c05988d19ad1783 +MD5 (NetBSD-6.0/i386/binary/sets/kern-XEN3PAE_DOM0.tgz) = 6baad66e20421f3fb0af25e4b95f8a6d +SHA1 (NetBSD-6.0/i386/binary/sets/kern-MONOLITHIC.tgz) = 52d1f2b561194201e67abf1ba2c1726d72e97984 +SHA512 (NetBSD-6.0/i386/binary/sets/kern-MONOLITHIC.tgz) = 19aa162f30e144882f2924be4b864821e109991ca16027c4016d54baf812945c8231f423d141091f08ecf8dc9310a74fcbae43b6ea18578afd1bef3346772cf6 +RMD160 (NetBSD-6.0/i386/binary/sets/kern-MONOLITHIC.tgz) = ca3d3b0cb59e5d5ba2089b6cf250c62c079b6855 +MD5 (NetBSD-6.0/i386/binary/sets/kern-MONOLITHIC.tgz) = 56528935806a8a2ec9f48c6dbfd9c175 +SHA1 (NetBSD-6.0/i386/binary/sets/modules.tgz) = a6d22e796d8b1f344b43bcf38fbb79e53ffdce13 +SHA512 (NetBSD-6.0/i386/binary/sets/modules.tgz) = 9bbf31b0e1c1192e9ff0ff38f0978c4c2972a82638e63f5f023bd7263ff9386d36cfd666e55e62a6bf3bf3e8c47571252b3508e485ec86830caaa89c66c19fe7 +RMD160 (NetBSD-6.0/i386/binary/sets/modules.tgz) = e3dcc86e04adaa6f347d51801422854b35fcedfb +MD5 (NetBSD-6.0/i386/binary/sets/modules.tgz) = 71908d43cbba617e2ff14e3fffa3dae0 +SHA1 (NetBSD-6.0/i386/binary/sets/man.tgz) = f526dfe015359f1181af9cf3dc6061960289451f +SHA512 (NetBSD-6.0/i386/binary/sets/man.tgz) = 75dc7781f8531f09bee6f1696561d036b12f08a66a44c4e56b11986e6d91df213ca8b4c6e59da9a2168038c94322c6cfdcdeb52125f5fb03c5b84cdb9522bd7a +RMD160 (NetBSD-6.0/i386/binary/sets/man.tgz) = 1f8551b79ca0342aaf8df0c6f2a77e7337cb7672 +MD5 (NetBSD-6.0/i386/binary/sets/man.tgz) = 6114b3fadf0a5e3bf8fde0e7bf0101fc +SHA1 (NetBSD-6.0/i386/binary/sets/kern-XEN3PAE_DOMU.tgz) = 4e24d5f9641c69962f0e9124a3a0082074db7117 +SHA512 (NetBSD-6.0/i386/binary/sets/kern-XEN3PAE_DOMU.tgz) = cbbd3c74d74bcd20c8fe2dfa5052b6886a5d25bf8c7aa595638655af790072bd3067e8555201849c2f3d0ec67465f41721c4a8aa14fb060231683de850fd6e99 +RMD160 (NetBSD-6.0/i386/binary/sets/kern-XEN3PAE_DOMU.tgz) = 56610e7d2c9e2844ce0516255bbf76b330d23f80 +MD5 (NetBSD-6.0/i386/binary/sets/kern-XEN3PAE_DOMU.tgz) = e79dd5d5ca1fc640045efccb106e6a01 +SHA1 (NetBSD-6.0/i386/binary/sets/kern-XEN3_DOM0.tgz) = 9c8c6c75aec356a4b6591bd5ce5fcf0e76536c41 +SHA512 (NetBSD-6.0/i386/binary/sets/kern-XEN3_DOM0.tgz) = 2acd400b61f87b32e41daf0cb89b512d887f222310cab9be25f2b030480b720042c86abb68ae81ba73875a2c70dfc01184e1e771ad671e98383ce9c8357b4e8e +RMD160 (NetBSD-6.0/i386/binary/sets/kern-XEN3_DOM0.tgz) = ac64d2c3ff6ff7352d43f4f275cfc07a509e40de +MD5 (NetBSD-6.0/i386/binary/sets/kern-XEN3_DOM0.tgz) = 5541acebbb837f4882be868d86bc2b22 +SHA1 (NetBSD-6.0/i386/binary/sets/kern-XEN3_DOMU.tgz) = 01432bab26f65297c0739bc3eb4740bd984d67ab +SHA512 (NetBSD-6.0/i386/binary/sets/kern-XEN3_DOMU.tgz) = bd7221f127923ebbd3099589b5bfd332cadbdcf2ad29870b9eee66b8241d1ad50c4d9481647d41d9ceba1e7071735538acd19d458d78e666d2b8ae1b097f993b +RMD160 (NetBSD-6.0/i386/binary/sets/kern-XEN3_DOMU.tgz) = f9c5fd62ac6b11f4cb1ab8eb648f4ee51209ff17 +MD5 (NetBSD-6.0/i386/binary/sets/kern-XEN3_DOMU.tgz) = fead463ca4403cdf358b55114421e53e +SHA1 (NetBSD-6.0/i386/binary/sets/tests.tgz) = 65e60f978857f50c36bf4066ad82acee0ef06af4 +SHA512 (NetBSD-6.0/i386/binary/sets/tests.tgz) = 714220aecacd2640160768ae00089cb25b5d3b5cf29f715e32257889159699566fe8d9b3bbcfa7bb6e2864ee1945dbfc61b48a66e20463025774616d91cc5392 +RMD160 (NetBSD-6.0/i386/binary/sets/tests.tgz) = 83c54132cfa9e7b0b5352466070bba098576ff86 +MD5 (NetBSD-6.0/i386/binary/sets/tests.tgz) = 1cf15f457ca67156d7dad0f7723ed259 +SHA1 (NetBSD-6.0/i386/binary/sets/text.tgz) = 0e426ee26f13d2523798fa8c09e934725087dc5e +SHA512 (NetBSD-6.0/i386/binary/sets/text.tgz) = 2809f127e3baa3e6ebdb181c31620b68d01e90208bd191db99aa9657c91db9a97b061cdfdc2d7a39fbedf2288067f2ed885d6515fdcf8e5b5a68dc754e9b3e30 +RMD160 (NetBSD-6.0/i386/binary/sets/text.tgz) = b30ff1dd8f2cfe414939980d4be3b61f39c04353 +MD5 (NetBSD-6.0/i386/binary/sets/text.tgz) = 2667947b26dffe05f3de7d1e2c8906d7 +SHA1 (NetBSD-6.0/i386/binary/sets/xbase.tgz) = 934f64b717d722045717691a55fb9d295f83b4e3 +SHA512 (NetBSD-6.0/i386/binary/sets/xbase.tgz) = 385cf3a944f4a6ef7271220f0367f12d123d9a2b84ebd3ca46181279f7cf5d544a946df3e10ea52f1e07638c5bc5d0b766fd63bed4e08b468f6ea5b0a75e17de +RMD160 (NetBSD-6.0/i386/binary/sets/xbase.tgz) = 04203a7b8bb5cd1a41aeeb2b92697677cfe58e98 +MD5 (NetBSD-6.0/i386/binary/sets/xbase.tgz) = ec9f6a167fd05c459f1fdf8cc889785d +SHA1 (NetBSD-6.0/i386/binary/sets/xcomp.tgz) = 7bc2f4e10afaa599959832c62f024d9f2f45bc10 +SHA512 (NetBSD-6.0/i386/binary/sets/xcomp.tgz) = 148bfb83357133e5377aeee82fdae29e0b90913ba59b1f51264108ca70010d55bd4adc4ce0ba7611a83b5f3f13307f196f724f3cb3a170d7f2caef801b79cc38 +RMD160 (NetBSD-6.0/i386/binary/sets/xcomp.tgz) = be8c61b5890936fc93dfb88c02c5f17f79f3cc73 +MD5 (NetBSD-6.0/i386/binary/sets/xcomp.tgz) = 9c25f1bf64f97c778e3c87b6e0e72871 +SHA1 (NetBSD-6.0/i386/binary/sets/xetc.tgz) = ea4db636b3919906a00e7b161b2c5f62fe7b4fa6 +SHA512 (NetBSD-6.0/i386/binary/sets/xetc.tgz) = a59442b3ab58c33774197f9bb28a96836b4c519c750270bd880d166250523f8119a68a9de6b6861f76cdf713da9682772e754075c965c56aa260b52ed837943e +RMD160 (NetBSD-6.0/i386/binary/sets/xetc.tgz) = 28e3ce094b557af508e1ec82ef46ebb01eb68509 +MD5 (NetBSD-6.0/i386/binary/sets/xetc.tgz) = 2a521f73ba4bd630070b01f24c8647d6 +SHA1 (NetBSD-6.0/i386/binary/sets/xfont.tgz) = a7a41c82046568a695ba0afeb81d11bf92e67950 +SHA512 (NetBSD-6.0/i386/binary/sets/xfont.tgz) = f46f4c6b4c61bbcbde85333cc714654902263c92e70035545caba3f3e2d5029cb074c8e427c85ea83b8478b19f32b93c4735a7adf64cc75609a4acd1118d0416 +RMD160 (NetBSD-6.0/i386/binary/sets/xfont.tgz) = 8863108bc2cc456cd1298b5317f519c5c6b3147a +MD5 (NetBSD-6.0/i386/binary/sets/xfont.tgz) = 36e968072dae462efddd6014f9f44272 +SHA1 (NetBSD-6.0/i386/binary/sets/xserver.tgz) = 27fd7ca36d5a3ca94b66eb5fd81ceeaed1648fe0 +SHA512 (NetBSD-6.0/i386/binary/sets/xserver.tgz) = 6a0d364672e4513dbf4c76c1cada80f84e774efa85c3e1fe4865ab26333765fab1db8ce3b590682a3e2c63895165e0d694c3e6717789b2f0ec87defa608930dd +RMD160 (NetBSD-6.0/i386/binary/sets/xserver.tgz) = 7521930788a2410a2842767b9c2886af83fccad7 +MD5 (NetBSD-6.0/i386/binary/sets/xserver.tgz) = ce3565a1b5e8af09e54ef8488edb14df +SHA1 (NetBSD-6.0/i386/installation/cdrom/boot-com.iso) = bcfbd8c6288248e55d78704802dfdbbd1d20519a +SHA512 (NetBSD-6.0/i386/installation/cdrom/boot-com.iso) = 9531877436cf8853db4dbd96672cb13a0784a1eef2a90ab43aeaae421f70bb6bdab7d5c10095f186b733d04ee1184087ff7b5d26ec7ef77d0783ee0f5c0d21f3 +RMD160 (NetBSD-6.0/i386/installation/cdrom/boot-com.iso) = 46205ca4d924c43e85b01b7750274f31fa2ad170 +MD5 (NetBSD-6.0/i386/installation/cdrom/boot-com.iso) = da3da9b120520e631bc5c17dfb70bd27 +SHA1 (NetBSD-6.0/i386/installation/cdrom/boot.iso) = 146e96103568f2ab3e98c1a0c7b98f89a93ac474 +SHA512 (NetBSD-6.0/i386/installation/cdrom/boot.iso) = 5073e008276c0fe9a4c3231bea37b2534e40d20b17d32a5bb30e9811a0578feae08a810a808201f44f74ab7258a58c5c1dfa1cc59ad0d4d41eff02f6772dade5 +RMD160 (NetBSD-6.0/i386/installation/cdrom/boot.iso) = 54ff36aedaa5266fb788b1b3f74dee0799c432f7 +MD5 (NetBSD-6.0/i386/installation/cdrom/boot.iso) = 6d1fae4935084e853fa152e09b472be5 +SHA1 (NetBSD-6.0/i386/installation/floppy/boot-com1.fs) = d4891595c9155d7598f1718cce43ed2fde9d4aa8 +SHA512 (NetBSD-6.0/i386/installation/floppy/boot-com1.fs) = 89d2af1f41e20deba16c1abfdc4709f353021710ae33ff40f9f4f20dd4c875db855f2bddf9af444f49dfb2d1d1caf0a2f3eab7bced113c45708da590092c9b04 +RMD160 (NetBSD-6.0/i386/installation/floppy/boot-com1.fs) = f2d8d259d8abaed540079cb0301fd111462bc0ba +MD5 (NetBSD-6.0/i386/installation/floppy/boot-com1.fs) = 320d7fcd247eee78495d4bc56205ba9f +SHA1 (NetBSD-6.0/i386/installation/floppy/boot-com2.fs) = 25012df4758eca3d307004fe1b448bfd1002b6ba +SHA512 (NetBSD-6.0/i386/installation/floppy/boot-com2.fs) = 3ad3778e665bbb8a0ea8e39d9c6a9144a79fc158aeef0af4bac90ee98561beb460b2f3993c929f27a1f26170be53d153faa0ec523e402bb1143d9cec5a54ac91 +RMD160 (NetBSD-6.0/i386/installation/floppy/boot-com2.fs) = e76b6f6a667e4548f8efdce8fded360a9ab7ce00 +MD5 (NetBSD-6.0/i386/installation/floppy/boot-com2.fs) = 1c731748f3af6300b39311051870dd5d +SHA1 (NetBSD-6.0/i386/installation/floppy/boot-com3.fs) = 00f812e968818ac87e2f0217b9aa2f67cf1826b2 +SHA512 (NetBSD-6.0/i386/installation/floppy/boot-com3.fs) = ac293ed38646e83851e74e70451893b301fe935fd4ee91fbe2f66d4a49583763ce3a5a123f05e38d0806e6b51c6db01dce467908f7ac49447b872e1a06364e74 +RMD160 (NetBSD-6.0/i386/installation/floppy/boot-com3.fs) = cd261aa83970e5699763ec792aebbc4bcedae712 +MD5 (NetBSD-6.0/i386/installation/floppy/boot-com3.fs) = a9073f83732b763206b32fd46c166fab +SHA1 (NetBSD-6.0/i386/installation/floppy/boot-com4.fs) = 6d9f052a4ba66b7a8d818418c7548a96b358189c +SHA512 (NetBSD-6.0/i386/installation/floppy/boot-com4.fs) = 86909e41525fe7744c3e10f523b7bd2651a80a000906e7040bae8fadeed8f2ee00e6d39998aab110a4aedbe9af95aa15eff7a8fd5781b6d979545c7751c54aea +RMD160 (NetBSD-6.0/i386/installation/floppy/boot-com4.fs) = 64980af391f001e6b67d6b603fd67e3d424a48a4 +MD5 (NetBSD-6.0/i386/installation/floppy/boot-com4.fs) = 9868c40fe2e4e26b0db5eb1a24d4b84b +SHA1 (NetBSD-6.0/i386/installation/floppy/boot-com5.fs) = e138754c8978462f24c07a3e61be0085592ab1be +SHA512 (NetBSD-6.0/i386/installation/floppy/boot-com5.fs) = 785ae7b940e77d108d20f4c8f9625db138334144e740ccf15949e4434572115fdcafecce25c3ea9c0e0d260e7d4c526a860bacda09ab8b2823d5d48a3a220b1a +RMD160 (NetBSD-6.0/i386/installation/floppy/boot-com5.fs) = 9eae2380cd42784b68dba1da19eb8e7a2f37940e +MD5 (NetBSD-6.0/i386/installation/floppy/boot-com5.fs) = 6f1b2546ecddd49db5fae090706ced45 +SHA1 (NetBSD-6.0/i386/installation/floppy/boot1.fs) = 955c193dc080b69fe111652972bb1a4a5fb88b70 +SHA512 (NetBSD-6.0/i386/installation/floppy/boot1.fs) = bea5bb410069dc463f5d670ca33a8040c6bc741ee30e90c93492ce5110334f0e87cc519571f35f2962bc18de0352c3f50002ceb8346f4aed84069b60c61740a8 +RMD160 (NetBSD-6.0/i386/installation/floppy/boot1.fs) = 3828a790e9743011d6b2f257f79deecee3686c4b +MD5 (NetBSD-6.0/i386/installation/floppy/boot1.fs) = 83997622af685d71b47e687ee0226d5c +SHA1 (NetBSD-6.0/i386/installation/floppy/boot2.fs) = 25012df4758eca3d307004fe1b448bfd1002b6ba +SHA512 (NetBSD-6.0/i386/installation/floppy/boot2.fs) = 3ad3778e665bbb8a0ea8e39d9c6a9144a79fc158aeef0af4bac90ee98561beb460b2f3993c929f27a1f26170be53d153faa0ec523e402bb1143d9cec5a54ac91 +RMD160 (NetBSD-6.0/i386/installation/floppy/boot2.fs) = e76b6f6a667e4548f8efdce8fded360a9ab7ce00 +MD5 (NetBSD-6.0/i386/installation/floppy/boot2.fs) = 1c731748f3af6300b39311051870dd5d +SHA1 (NetBSD-6.0/i386/installation/floppy/boot3.fs) = 00f812e968818ac87e2f0217b9aa2f67cf1826b2 +SHA512 (NetBSD-6.0/i386/installation/floppy/boot3.fs) = ac293ed38646e83851e74e70451893b301fe935fd4ee91fbe2f66d4a49583763ce3a5a123f05e38d0806e6b51c6db01dce467908f7ac49447b872e1a06364e74 +RMD160 (NetBSD-6.0/i386/installation/floppy/boot3.fs) = cd261aa83970e5699763ec792aebbc4bcedae712 +MD5 (NetBSD-6.0/i386/installation/floppy/boot3.fs) = a9073f83732b763206b32fd46c166fab +SHA1 (NetBSD-6.0/i386/installation/floppy/boot4.fs) = 6d9f052a4ba66b7a8d818418c7548a96b358189c +SHA512 (NetBSD-6.0/i386/installation/floppy/boot4.fs) = 86909e41525fe7744c3e10f523b7bd2651a80a000906e7040bae8fadeed8f2ee00e6d39998aab110a4aedbe9af95aa15eff7a8fd5781b6d979545c7751c54aea +RMD160 (NetBSD-6.0/i386/installation/floppy/boot4.fs) = 64980af391f001e6b67d6b603fd67e3d424a48a4 +MD5 (NetBSD-6.0/i386/installation/floppy/boot4.fs) = 9868c40fe2e4e26b0db5eb1a24d4b84b +SHA1 (NetBSD-6.0/i386/installation/floppy/boot5.fs) = e138754c8978462f24c07a3e61be0085592ab1be +SHA512 (NetBSD-6.0/i386/installation/floppy/boot5.fs) = 785ae7b940e77d108d20f4c8f9625db138334144e740ccf15949e4434572115fdcafecce25c3ea9c0e0d260e7d4c526a860bacda09ab8b2823d5d48a3a220b1a +RMD160 (NetBSD-6.0/i386/installation/floppy/boot5.fs) = 9eae2380cd42784b68dba1da19eb8e7a2f37940e +MD5 (NetBSD-6.0/i386/installation/floppy/boot5.fs) = 6f1b2546ecddd49db5fae090706ced45 +SHA1 (NetBSD-6.0/i386/installation/miniroot/miniroot.kmod) = 3949ed3ca0384f45c40b59eef585566e947fc150 +SHA512 (NetBSD-6.0/i386/installation/miniroot/miniroot.kmod) = e91e8d4aa8ef1f81945c495df4b43f8bcc669fa1f0183c5d0092d526889d985432d6f318418a42910596f1f44cc0d235d32a0b5e3aa1572198182ff1d90188c1 +RMD160 (NetBSD-6.0/i386/installation/miniroot/miniroot.kmod) = 2d67e98155d79210ae2349fb13937724f79cef47 +MD5 (NetBSD-6.0/i386/installation/miniroot/miniroot.kmod) = 2fbac91d26cec04141c2c79a18aa839e +SHA1 (NetBSD-6.0/i386/installation/misc/pfdisktc.zip) = e3dedc5211120fdb8259075541a6bf4fdb5a0c5b +SHA512 (NetBSD-6.0/i386/installation/misc/pfdisktc.zip) = 2f4daa1b52b4f40be868ee04faf9b55f17df64ca03ed0b6577f2f1680692226b68d84c0a9f59fd0b08085219555c25e52e447053a6e03589957718b954aadeaf +RMD160 (NetBSD-6.0/i386/installation/misc/pfdisktc.zip) = 29ed32ef8b4390bd1545f9337f16994a154c20e6 +MD5 (NetBSD-6.0/i386/installation/misc/pfdisktc.zip) = 33c938480de81999f82a3ba3fca0b233 +SHA1 (NetBSD-6.0/i386/installation/misc/dosboot.com) = 0c89f2a01913cbd69002b821273fe196ff835f89 +SHA512 (NetBSD-6.0/i386/installation/misc/dosboot.com) = 661bb1a057d23a8dbd8f33216e590439e83b8cbc1ee7988980de68890148c8d86b9e58254be366afdc92b8238cf1d304ce972b518e4656ed9a378fa5eb7e03e6 +RMD160 (NetBSD-6.0/i386/installation/misc/dosboot.com) = 11182a8c2c18dc561e9b07f84895e21f81d42aeb +MD5 (NetBSD-6.0/i386/installation/misc/dosboot.com) = 8d32a69f5a7c200404b5e6747eb38397 +SHA1 (NetBSD-6.0/i386/installation/misc/pfdisk.doc) = 9886ea575769f46c49251fe1b096c860457e996b +SHA512 (NetBSD-6.0/i386/installation/misc/pfdisk.doc) = a34e971ec8a0d1eb5107ddfa2a5a6c7eb028ec58235983658ccee2e3b42bd2e40e2ff4504a2b6aa16668a918e17f0d1866ca4ef904df114f30674dd9f8e32c17 +RMD160 (NetBSD-6.0/i386/installation/misc/pfdisk.doc) = 9e6ddcbeab7d6894f3173efbc9b1067d40d79409 +MD5 (NetBSD-6.0/i386/installation/misc/pfdisk.doc) = 7c9091037c42ecd0d1fb67275af0650a +SHA1 (NetBSD-6.0/i386/installation/misc/pfdisk.exe) = e780cbcd893d446cc9d07950e9b9462d9a02e439 +SHA512 (NetBSD-6.0/i386/installation/misc/pfdisk.exe) = 798a00ddfd76ffcae1dd427ebcd9eac6ef4fc54bb0eeeba36ecca3903b9de785ff6113e3ee0960ca695d9a8196dbdd3f7434530e50dd0208d5b872e989038c3b +RMD160 (NetBSD-6.0/i386/installation/misc/pfdisk.exe) = 4569b5259fb5d13606e521a4d85a0748afa92670 +MD5 (NetBSD-6.0/i386/installation/misc/pfdisk.exe) = 6e470b18a39a3b7bf7c8fe7c34241da7 +SHA1 (NetBSD-6.0/i386/installation/misc/pxeboot_ia32.bin) = a1c0c4f7137ad0c4131aec154c3cdc7fd62c4ad6 +SHA512 (NetBSD-6.0/i386/installation/misc/pxeboot_ia32.bin) = 4ef5af523ac4d164885c4ce7ea8286303ce1a60d6225730d98b14f6b96c56c1227bf8bbd4d4ee77ff30645e5f0375aea1f879fc1f61de1263bc5f68e470abe28 +RMD160 (NetBSD-6.0/i386/installation/misc/pxeboot_ia32.bin) = 732aa68a238219b0fa20ac73fed5cdd59ba4b775 +MD5 (NetBSD-6.0/i386/installation/misc/pxeboot_ia32.bin) = d56818a2c96b381e6b907ef7ee5c146d +SHA1 (NetBSD-6.0/i386/installation/misc/rawr32.exe) = b43acce43bab52a4d7a5cca69b5c448700c3084c +SHA512 (NetBSD-6.0/i386/installation/misc/rawr32.exe) = c8e466f2a57083a0cd577720f31ec6d84096680e89c824b633f168ccde962be28cc3ec8019cf136a12437b3df92b872a3600266857c4e5c43f12c6989ce3490c +RMD160 (NetBSD-6.0/i386/installation/misc/rawr32.exe) = b0cafd5f6dab34b71cbd5885821188bb8479bdc8 +MD5 (NetBSD-6.0/i386/installation/misc/rawr32.exe) = a38e68ebd955604d1b4e137c8eb63dbc +SHA1 (NetBSD-6.0/i386/installation/misc/rawrite.c) = 45e127dcd24e3a5666d1d4fff54349ca9bf5c077 +SHA512 (NetBSD-6.0/i386/installation/misc/rawrite.c) = 05315a055d1b95bb409c986e3a4faa0ffaf407a239ca32638b8df05757af480cd409abf141cc9b695bf2f61ececbb0de07737a9a927e8c9d9e9f78c39a54c9a1 +RMD160 (NetBSD-6.0/i386/installation/misc/rawrite.c) = 424511ff8fe6118c147cda137803fbc3bdea34a0 +MD5 (NetBSD-6.0/i386/installation/misc/rawrite.c) = 606e8042f2343028bbe2fbb7db391c53 +SHA1 (NetBSD-6.0/i386/installation/misc/rawrite.doc) = a5d3f4916c427ec4ec93d3b1e044f8141ed83dd8 +SHA512 (NetBSD-6.0/i386/installation/misc/rawrite.doc) = ccc3a2b7daadd7527e048de382bdf37580fc8069f5ad2e9f5f8feec5e50374ad2c8a8cbd293f38fffddb08a84573f13ed1152695f64a9c4b745c6e6dae793401 +RMD160 (NetBSD-6.0/i386/installation/misc/rawrite.doc) = 892d37aa0401f9d42effec57944c007e7a6d530d +MD5 (NetBSD-6.0/i386/installation/misc/rawrite.doc) = 0006cfba390f738eb0d4f6c2fcafb7c6 +SHA1 (NetBSD-6.0/i386/installation/misc/rawrite.exe) = 81152a9688b5fdce26ba09c1685ffa842e31c83d +SHA512 (NetBSD-6.0/i386/installation/misc/rawrite.exe) = 76ca20eca1b087c8d583b23c52734ef6db49f15d5bbbc4da0eef301b2b46fad5b86c063e4d868bf3db41c625e022c4604759e1a1bc50c9caff2665eaecf11920 +RMD160 (NetBSD-6.0/i386/installation/misc/rawrite.exe) = 2b5707df5c5a7a84b8e80fafb03442fd29ca3eac +MD5 (NetBSD-6.0/i386/installation/misc/rawrite.exe) = 7dac6ea496014d32dbce6c50feb254ca +SHA1 (NetBSD-6.0/i386/INSTALL.html) = 6b92ae0724869e0b33123151562db113ff87310d +SHA512 (NetBSD-6.0/i386/INSTALL.html) = a3541d32c0c954af91d5af22c7b1d134096a4d87f61baa9e76d192aed5461f5a44bca260dfabc3cf1979b9736958ea2d4467a5f98023bf816ea9915c6ad81786 +RMD160 (NetBSD-6.0/i386/INSTALL.html) = beba55314f919265ffba84528a2ed7b2ebc2ef7d +MD5 (NetBSD-6.0/i386/INSTALL.html) = 5597002f70f1f3e1905becc1a21b5046 +SHA1 (NetBSD-6.0/i386/INSTALL.more) = fd226e8ade97b7071048c7f3a71d68b8f2fbc440 +SHA512 (NetBSD-6.0/i386/INSTALL.more) = df5bfc36c307a943d5def074292619b8b9452b7d8ad612feb6e3aed63534c5698701fa0008e007f6b08a742141643b2d9d82d3386a1194421c556a499e12b1b6 +RMD160 (NetBSD-6.0/i386/INSTALL.more) = 811bda03f587e977180da84b2ee3a1715e059a68 +MD5 (NetBSD-6.0/i386/INSTALL.more) = a080d66a0f33055ae14ac59dd13b6c11 +SHA1 (NetBSD-6.0/i386/INSTALL.ps) = 81b57f86901189d2f513553abf30858d95ce11d0 +SHA512 (NetBSD-6.0/i386/INSTALL.ps) = b2fcab6677f9949755c9aa702719c0572c7a7198c926e8d50103e513f2c44ec92b11147488eea8a1f0e5f04c3e024480cde2c47e538137b99f80df27f9deab91 +RMD160 (NetBSD-6.0/i386/INSTALL.ps) = f7e87587ad8249b5f71b89988802cbff68e645cf +MD5 (NetBSD-6.0/i386/INSTALL.ps) = 134248944ca4bca697eeb3aaa49c1dc6 +SHA1 (NetBSD-6.0/i386/INSTALL.txt) = a1072904f9c7baa1f3b9136a12e7b8fe7821f757 +SHA512 (NetBSD-6.0/i386/INSTALL.txt) = 4229cbe31deb065a67fd10b737e4acb0784f9a8b31546e4c9d8b41fd002e81a9d48acf08a455dfa488669358d19cc1daa5c329cd3ccad5bfa1471432656fc70f +RMD160 (NetBSD-6.0/i386/INSTALL.txt) = 2dee238856637d6990f33f3aac177f34478c6ff1 +MD5 (NetBSD-6.0/i386/INSTALL.txt) = 92702556c5a08e156b8eae602d975fdf +SHA1 (NetBSD-6.0/ibmnws/binary/kernel/netbsd-GENERIC.symbols.gz) = c4b53dcc495fbb67f30084776444088c6fa69af6 +SHA512 (NetBSD-6.0/ibmnws/binary/kernel/netbsd-GENERIC.symbols.gz) = 08dc9f41dbc5f88e4e4d718880f8ac072ee9386daf727cd717b7276c88443dbe194781b062cd29409a964737cb8b27f0b158dfefbcb1b4226f9bc40deedd1f19 +RMD160 (NetBSD-6.0/ibmnws/binary/kernel/netbsd-GENERIC.symbols.gz) = 5d66efd39a08359a525748ecd06b42705c53028f +MD5 (NetBSD-6.0/ibmnws/binary/kernel/netbsd-GENERIC.symbols.gz) = e819b2d7af2bddcf3d4cf935724695f0 +SHA1 (NetBSD-6.0/ibmnws/binary/kernel/netbsd-GENERIC.gz) = 0494a909caf1ca5dec73b1f5aada6ef099653a7d +SHA512 (NetBSD-6.0/ibmnws/binary/kernel/netbsd-GENERIC.gz) = 5ca8f4fec7a5b89369934e081f7316c4e482ef7090ed8904f0985e941e20bf42fae8396d7da4151b78234568b0a735667b56f7b480fa37d1bba36b594d3d71f6 +RMD160 (NetBSD-6.0/ibmnws/binary/kernel/netbsd-GENERIC.gz) = 2ff1c7a5c604f56f85ff3ade294e3cb55c053ac3 +MD5 (NetBSD-6.0/ibmnws/binary/kernel/netbsd-GENERIC.gz) = d4f4dfb62bac44f16e9bd16c7df8a501 +SHA1 (NetBSD-6.0/ibmnws/binary/sets/games.tgz) = fbf69640b362df2446d7414ac3a13db100c289eb +SHA512 (NetBSD-6.0/ibmnws/binary/sets/games.tgz) = d86b41d79aea4204ccf45306937a5ec45629e37873a5956c0280fd1d54cf4a808542d097f9d978fd3277791554ce8a6fb4d0ccd46e30210549d5cce1145bb499 +RMD160 (NetBSD-6.0/ibmnws/binary/sets/games.tgz) = fd2aed1eb51f4db522fb5163e8fde4c040b55d30 +MD5 (NetBSD-6.0/ibmnws/binary/sets/games.tgz) = 997ae5fb42196a787df89873be321e47 +SHA1 (NetBSD-6.0/ibmnws/binary/sets/man.tgz) = 899b9d8242e983a5110ab755651c24f709b5af67 +SHA512 (NetBSD-6.0/ibmnws/binary/sets/man.tgz) = 410999db110d710f4bb498c3d7ae7adc62170c7c2f470ce189c92f6c436c5ea96149659c631ef0b5605caaa025d97dfe1c07c428d86f51239657bd6b71717b15 +RMD160 (NetBSD-6.0/ibmnws/binary/sets/man.tgz) = c1270f68c6d41b351877f71f0396ac34877dfc8d +MD5 (NetBSD-6.0/ibmnws/binary/sets/man.tgz) = df4db2bbfa39ef6a4a215d949653d04a +SHA1 (NetBSD-6.0/ibmnws/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/ibmnws/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/ibmnws/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/ibmnws/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/ibmnws/binary/sets/xbase.tgz) = b7c8146146ebc15191c1bf53f51f8f980fe8c816 +SHA512 (NetBSD-6.0/ibmnws/binary/sets/xbase.tgz) = 091f5d00414a9ad478811bfb0e953f2a204869bc5e310790886a59c11953974cf7068cd9a96c8823856ab2687ffa2ac31e97494f47338bfe31d80217382c59f1 +RMD160 (NetBSD-6.0/ibmnws/binary/sets/xbase.tgz) = 4bd1bfdc7c1e1619de63fb83276c21039b945357 +MD5 (NetBSD-6.0/ibmnws/binary/sets/xbase.tgz) = e621806afa0fcc9cdcef0f9b3c7dfcbd +SHA1 (NetBSD-6.0/ibmnws/binary/sets/xcomp.tgz) = 960dd33b61e19dec92096a54791aca1cdf56ce54 +SHA512 (NetBSD-6.0/ibmnws/binary/sets/xcomp.tgz) = 111dd50041e4008aeadb898c3d08f9995c5c13a41ccc20993b4ad51c81d7f6ee3b4dab16158ac7436d085b80e4a643b236a9c97edd3e915125a1466154538420 +RMD160 (NetBSD-6.0/ibmnws/binary/sets/xcomp.tgz) = 0cf8b9a8d1489a32ba0b5a277d90e429c40650fb +MD5 (NetBSD-6.0/ibmnws/binary/sets/xcomp.tgz) = 4ba4077ca2c0edf71813165fcf5321fb +SHA1 (NetBSD-6.0/ibmnws/binary/sets/xfont.tgz) = 4711fcbade0238d60b7b89cf0d7873b03d7ed1f7 +SHA512 (NetBSD-6.0/ibmnws/binary/sets/xfont.tgz) = c29130f55f536f602253a7f92f073ebf6ba02baea09f8011530bbf7e03ae96594334f0c60b29a8bceaffc3eb8b152db47548e38a3c8a14abc5fe35bc5d1d7d93 +RMD160 (NetBSD-6.0/ibmnws/binary/sets/xfont.tgz) = 3b01af0f8e34367988d559fe0fbb0acbbafb0b2b +MD5 (NetBSD-6.0/ibmnws/binary/sets/xfont.tgz) = 6ba15ed12217b726d9129db8e942a048 +SHA1 (NetBSD-6.0/ibmnws/binary/sets/xserver.tgz) = 05aac7e617e0cac05a88062fef29bb459da7a1d1 +SHA512 (NetBSD-6.0/ibmnws/binary/sets/xserver.tgz) = 19fb5af5d6afd78839a22e5c0694a492047b5200c569cbf58c676ff32ec250b21edcfe2ed00b65092fdac374d1ab9eaaed6113c69bc03009cf458aedc6014913 +RMD160 (NetBSD-6.0/ibmnws/binary/sets/xserver.tgz) = 774d2a1072b8d122790ad189a6d2ada2ad99e7cf +MD5 (NetBSD-6.0/ibmnws/binary/sets/xserver.tgz) = 3daf1477cadf3593e9ba45e3703fe8a5 +SHA1 (NetBSD-6.0/ibmnws/binary/sets/kern-GENERIC.tgz) = c9804814e9b76392c467295e0700798f7305d9ea +SHA512 (NetBSD-6.0/ibmnws/binary/sets/kern-GENERIC.tgz) = dbe66f41c0023cf48726763c0accca7d17146888cef03f6bcd8356f48bca2a5685e60224e3369fcf4ebc524843a9e3a2df558199a4b2b1a43cc7b22931c52c5b +RMD160 (NetBSD-6.0/ibmnws/binary/sets/kern-GENERIC.tgz) = e054c430a723e57798b9f13d852d6be6895a6b18 +MD5 (NetBSD-6.0/ibmnws/binary/sets/kern-GENERIC.tgz) = 9bb6d0f70b522f8bdfe0da0855fe12b2 +SHA1 (NetBSD-6.0/ibmnws/binary/sets/base.tgz) = 150b9b1ed403c611d17b3bf258f7bf064f3f76c6 +SHA512 (NetBSD-6.0/ibmnws/binary/sets/base.tgz) = 7c9eb4dbb9e770395ea516b27dc37c86a34d10437bfbc59bd6b55ebd9a3565e470ee7553a238e69012c7eb19f1fafe3bb94d750c642c179190566d0b97ba79f7 +RMD160 (NetBSD-6.0/ibmnws/binary/sets/base.tgz) = 6f959eb6b88fa607c19c9ab5e0b82d172960676e +MD5 (NetBSD-6.0/ibmnws/binary/sets/base.tgz) = 1d2ccb914175ffb1a6e90e787914e08d +SHA1 (NetBSD-6.0/ibmnws/binary/sets/comp.tgz) = 449a6e0ccfaa3b9105912d05d4204242bab79635 +SHA512 (NetBSD-6.0/ibmnws/binary/sets/comp.tgz) = 5ceb6d751f429f466ae15f98244e82f32461f7f0bf546c982a1e35bcfc4c6c845a121ecf07b387189fa4173d672e0291a0d396010f5c6ab9130f3264ef26f36d +RMD160 (NetBSD-6.0/ibmnws/binary/sets/comp.tgz) = 6d544592799a77914a724215f8514f0d22bae2b2 +MD5 (NetBSD-6.0/ibmnws/binary/sets/comp.tgz) = 84f35afba48084d9eed192a484616382 +SHA1 (NetBSD-6.0/ibmnws/binary/sets/etc.tgz) = 4ec9d5606ead158c85791c298c829a030aaa6acd +SHA512 (NetBSD-6.0/ibmnws/binary/sets/etc.tgz) = 2786ad3a1aca388352f2c4fa1da7da624d9762c4d8c7deec54441bd3ce95c79cb2ccd6fd15619a224987f9726c66d5a88b825e57b69b68aac7033ce80c96af3e +RMD160 (NetBSD-6.0/ibmnws/binary/sets/etc.tgz) = 25c6401fec22c9ec3f2bc6c3d33127b9222def9b +MD5 (NetBSD-6.0/ibmnws/binary/sets/etc.tgz) = 9f83cc04c872ec0e355e2528387cdcac +SHA1 (NetBSD-6.0/ibmnws/binary/sets/modules.tgz) = fef0894685186ef94fc691e71a8a366fe7bb66e0 +SHA512 (NetBSD-6.0/ibmnws/binary/sets/modules.tgz) = 0051ecab124fbe7a4a8005ae4fddc9b4be520e6be5c34cd1811f6c280e35f10d79914756f5106a840177b7cc33f39db337c3f461f00669c1838a6ac0c2204ee5 +RMD160 (NetBSD-6.0/ibmnws/binary/sets/modules.tgz) = fce29d3683f7e0eec8e0b45c94bba924bad6b5d7 +MD5 (NetBSD-6.0/ibmnws/binary/sets/modules.tgz) = a47b110fc0e721d6849bb6fa4d3a7ab3 +SHA1 (NetBSD-6.0/ibmnws/binary/sets/tests.tgz) = 3eb8ca45b13b0c43f1d9e10322b8b8469859ffac +SHA512 (NetBSD-6.0/ibmnws/binary/sets/tests.tgz) = d9d2bc61ad2f5ba8ca9bd4b53c348b01fc4f7dc7417d14fe7c6c3f68b2a0ff32221bda546b9ca26a0b998ee72a393e3231de17c94bd1e72a0bc6365dba42ea5f +RMD160 (NetBSD-6.0/ibmnws/binary/sets/tests.tgz) = 8348b43e8543ad7ab8ba46978930fd7bef910c6d +MD5 (NetBSD-6.0/ibmnws/binary/sets/tests.tgz) = 5cb30f9ed33e774f3c1bc14cea070f34 +SHA1 (NetBSD-6.0/ibmnws/binary/sets/text.tgz) = 38ca726175c32d5ef01309254f51584001f2888b +SHA512 (NetBSD-6.0/ibmnws/binary/sets/text.tgz) = 78102b1494c3e0d92ee40eaed00cdf6a4cd9e6d5dcfe2f523442fdce7f46d9de2e63c9ee5e0ba90fbae71509518ed2d212a0eab357f0a235ad8b4339b8f74bc6 +RMD160 (NetBSD-6.0/ibmnws/binary/sets/text.tgz) = 9532b62eed56ed6308d0b564552a77239ddcc406 +MD5 (NetBSD-6.0/ibmnws/binary/sets/text.tgz) = 25b993723182c6c3fc4c4c7d5544a7c0 +SHA1 (NetBSD-6.0/ibmnws/binary/sets/xetc.tgz) = 6068a07bd5602c1e57dcce29ce0a58ab8d6fc63f +SHA512 (NetBSD-6.0/ibmnws/binary/sets/xetc.tgz) = 2bc55ed596339c00a303d972145c4621db7f5781f7f4bf7bd8cd6ca634cd397f8b603c83b2f607f9a65c73cc237b16db0fa3ac30f28ed898d555224355741f4f +RMD160 (NetBSD-6.0/ibmnws/binary/sets/xetc.tgz) = f5b7f09b378d534eb6436d76a135192dae3cae0a +MD5 (NetBSD-6.0/ibmnws/binary/sets/xetc.tgz) = 1c3134612470159dcad9c60e9e0664d9 +SHA1 (NetBSD-6.0/images/NetBSD-6.0-amd64-install.img.gz) = 0fb40298c03dc94850911ccf296f74b4daee6ab1 +SHA512 (NetBSD-6.0/images/NetBSD-6.0-amd64-install.img.gz) = e0cf82777d65c1f8fa2776a154f297f8cadcca5c8ea8064adf0ac87b51f5999af8208fe284e95478d87f45d68ece4c63e82611d624514b96a9e236bfbe2aa56d +RMD160 (NetBSD-6.0/images/NetBSD-6.0-amd64-install.img.gz) = 0f38bf9ac003bdc7b7a73a1321af35f77e498de4 +MD5 (NetBSD-6.0/images/NetBSD-6.0-amd64-install.img.gz) = 05aa2e9948e5f613ac8942f04f5703b3 +SHA1 (NetBSD-6.0/images/NetBSD-6.0-acorn26.iso) = 3d532f8e1c0d8c70ac0204a0e30352946d5b4cf8 +SHA512 (NetBSD-6.0/images/NetBSD-6.0-acorn26.iso) = faac85c94da6ff71b98f6ee934aee21d972c52b4ecf1a1bd39609b31ac80956fed51442fa34e423c432fe6a2957768df5db91585c0edd385cbd4e13f067eedfe +RMD160 (NetBSD-6.0/images/NetBSD-6.0-acorn26.iso) = db40e23e1cd76af703d18f9e9fadfb7bad0bdbc0 +MD5 (NetBSD-6.0/images/NetBSD-6.0-acorn26.iso) = c3adc16971c37d3319e62fe83dbc6fe9 +SHA1 (NetBSD-6.0/images/NetBSD-6.0-acorn32.iso) = 1b8406a3ddc779f865e4edca16d6e5cbb0b33728 +SHA512 (NetBSD-6.0/images/NetBSD-6.0-acorn32.iso) = 8c15a060921d1339eb814456955753badacc1db25f84f471ae66106f78f3ebc22f017ec1ff9af71cf1c59ad9a669943210967105e2669ba9093596e6b2009020 +RMD160 (NetBSD-6.0/images/NetBSD-6.0-acorn32.iso) = 58b72463d91d486398514eac65f3cebb2bbcb0db +MD5 (NetBSD-6.0/images/NetBSD-6.0-acorn32.iso) = eef67583eee51a578d4f6ce69864fd25 +SHA1 (NetBSD-6.0/images/NetBSD-6.0-alpha.iso) = ff793eb5257ba6f7c3ca97049cab973dafc70785 +SHA512 (NetBSD-6.0/images/NetBSD-6.0-alpha.iso) = e2fcfb789c6c0bf801cb02b1a4f9d133902a9d78be3458b19e12b8050c0686cfae37d2ad4a5661ffc3cddb089e7079d0bfe5b0c7fddbc0ad7c43abc250f21db4 +RMD160 (NetBSD-6.0/images/NetBSD-6.0-alpha.iso) = 50a4b3f98483a0ff94e2c6c4d93615069d2c4953 +MD5 (NetBSD-6.0/images/NetBSD-6.0-alpha.iso) = eacfcb881765bac2c8fc45e1650091a1 +SHA1 (NetBSD-6.0/images/NetBSD-6.0-dreamcast.iso) = dd89f98a8bcd0d8bdc9861682227cd1e48031db3 +SHA512 (NetBSD-6.0/images/NetBSD-6.0-dreamcast.iso) = f18e432d93110b9cafe06c1a5bb13a27b028a5a773bc9ddfc59685737b2939f4ebf30de6e8e7fc5d6bca2f16b576af48cd2aa62ebd791b28d499b008cb5f11db +RMD160 (NetBSD-6.0/images/NetBSD-6.0-dreamcast.iso) = 763baa9e578be882dd458c8879f42745cf6ff2f2 +MD5 (NetBSD-6.0/images/NetBSD-6.0-dreamcast.iso) = 19d1400e0b92a906c4f01cae132e5d22 +SHA1 (NetBSD-6.0/images/NetBSD-6.0-amd64.iso) = 78d8ca5aa25eef0bdab5c794550e7c43637169a5 +SHA512 (NetBSD-6.0/images/NetBSD-6.0-amd64.iso) = f4900e8effcb1f5b5767873976dbb231a07346f48df20f56a8441942a91ecca0b6ea1309e01ea6a67b0513e61ebe3b8501b436063676558f119735f6d35592b6 +RMD160 (NetBSD-6.0/images/NetBSD-6.0-amd64.iso) = 76a6c030ca86c7d5abdfe91568a543d3bad04ffa +MD5 (NetBSD-6.0/images/NetBSD-6.0-amd64.iso) = 9155899df5ebc1a69c7f13ef004677a0 +SHA1 (NetBSD-6.0/images/NetBSD-6.0-amiga.iso) = 7a81516c832299ddcfa8b364422e82a63b3869df +SHA512 (NetBSD-6.0/images/NetBSD-6.0-amiga.iso) = 6695416ad0dbe2bf03bb75df8b40b04cec9179d2f60aec0b1a5e8f56ad12995911158251cb78c67d62d60324e8708c85c02b84ba0fcffd3fcf73a69aaa497b0b +RMD160 (NetBSD-6.0/images/NetBSD-6.0-amiga.iso) = 72c96741b1fad68368043e16d21ff533490b8275 +MD5 (NetBSD-6.0/images/NetBSD-6.0-amiga.iso) = 6b214d3da92f2d84210ac00c4eb9650b +SHA1 (NetBSD-6.0/images/NetBSD-6.0-arc.iso) = 09dd2c85bf2772333ec299e45dec5c016dc22d7e +SHA512 (NetBSD-6.0/images/NetBSD-6.0-arc.iso) = 6eaab9510f8ea92a175115377924dfb7806be38c78d12920a86e6284bc59bf0711adbb5b46809eb48fa8c299d8c9683b777ad16fe78c3e4760adc6ff605941e6 +RMD160 (NetBSD-6.0/images/NetBSD-6.0-arc.iso) = d4f2d0301da83d93a18cce50be4a878cb5955202 +MD5 (NetBSD-6.0/images/NetBSD-6.0-arc.iso) = a4c2332dc064e7d8cbccb921af5c2022 +SHA1 (NetBSD-6.0/images/NetBSD-6.0-atari.iso) = 9976598eb68ec6bb90329161c3ffad985e2b3c35 +SHA512 (NetBSD-6.0/images/NetBSD-6.0-atari.iso) = ac4951dcf3f148925c19db7bc7027db69549ac90e57db25994c7de5959943476eff7eeb0c490ca7b3df4b6f7bc0604fb5515c337e776a384d5b6a8169e92bf47 +RMD160 (NetBSD-6.0/images/NetBSD-6.0-atari.iso) = 35d389ebb1ea02751e819cd76750a1116d472b1f +MD5 (NetBSD-6.0/images/NetBSD-6.0-atari.iso) = 44c8de8283cccb8a576242adcad878fc +SHA1 (NetBSD-6.0/images/NetBSD-6.0-cats.iso) = a1f0554b7193949055ee9cb35eae529893bfc8a8 +SHA512 (NetBSD-6.0/images/NetBSD-6.0-cats.iso) = 7a38bfe0e1ff3948579dbcceed822634e3352e690911052dcf25f9b8746f457f1acb80830b6ca22637c559948eb8fb1eab8c9434225f13c000204879b9edc16c +RMD160 (NetBSD-6.0/images/NetBSD-6.0-cats.iso) = 2116103ecfe4c450432b7c1bad8787aaa6149a51 +MD5 (NetBSD-6.0/images/NetBSD-6.0-cats.iso) = ebcfe064bb40fc87487654d7f8ccc15a +SHA1 (NetBSD-6.0/images/NetBSD-6.0-cobalt.iso) = d5e6a8be8cfcef7362542c2ecbfe7e0173845061 +SHA512 (NetBSD-6.0/images/NetBSD-6.0-cobalt.iso) = 28181b68559432a4c566bcc9f71a5ed2b00a5d7118073d114ce4085f39d2139ce50e6b843beb46a59ab4e55aab4ead1e2fb952610f633fb77ae87edb5d2c3d76 +RMD160 (NetBSD-6.0/images/NetBSD-6.0-cobalt.iso) = ddcff88c659b8f0190e66ed2df4014395bf819e7 +MD5 (NetBSD-6.0/images/NetBSD-6.0-cobalt.iso) = 5975ccac715d36432aa101e6c1c745e4 +SHA1 (NetBSD-6.0/images/NetBSD-6.0-emips.iso) = 0c9a09ee73ef6d90af39aca9513b539a79e7c505 +SHA512 (NetBSD-6.0/images/NetBSD-6.0-emips.iso) = a0ec2048ab0c44ac69722b79b56308781e9f298fc3366bd628d4cfeebd8891e08091e8d86a576be50ccb12b1ae48263f86c8f0bf42d743d040a2407fb21039de +RMD160 (NetBSD-6.0/images/NetBSD-6.0-emips.iso) = 2d0e11edc64ceb8af1fc7239a9390868e1febfae +MD5 (NetBSD-6.0/images/NetBSD-6.0-emips.iso) = d5dbd826114f5e530d171761462718c6 +SHA1 (NetBSD-6.0/images/NetBSD-6.0-evbarm.iso) = 95e132f2d72a36eadf98b59d6883cac167d22887 +SHA512 (NetBSD-6.0/images/NetBSD-6.0-evbarm.iso) = 5c3a43f9609687ac5e5f5d5f21cdc798dd75f0d89bfe3a4d46ee151f60e13a90e2059d9906efcc5831f5e7ef0c267c3615737da03cb781eeff39dcff518b4114 +RMD160 (NetBSD-6.0/images/NetBSD-6.0-evbarm.iso) = 99c9115a98e45e96730163fde4fc90f37ef11e26 +MD5 (NetBSD-6.0/images/NetBSD-6.0-evbarm.iso) = 1bb998b53e8a82a28fdefecd4c2d559b +SHA1 (NetBSD-6.0/images/NetBSD-6.0-evbmips-mips64eb.iso) = 0ffea2aa4fb1fc1d58b87259e56080caa9fd6996 +SHA512 (NetBSD-6.0/images/NetBSD-6.0-evbmips-mips64eb.iso) = 2d3a7807156a465c9b2d8ee5d23951f5415984c2bc0cd8a7e06102399ac4b89d247380542efe1148d5bf71bb945c4de005fc64df7ecf2cdc9ce63481a2f10d07 +RMD160 (NetBSD-6.0/images/NetBSD-6.0-evbmips-mips64eb.iso) = 1de400a05e285d41af9eb1fcb4164932ecee0888 +MD5 (NetBSD-6.0/images/NetBSD-6.0-evbmips-mips64eb.iso) = 62143f6b35eee23d62a01b9cd05e17bf +SHA1 (NetBSD-6.0/images/NetBSD-6.0-evbmips-mips64el.iso) = 5b0f9688d925754bd79d28226f29dc0057c634b0 +SHA512 (NetBSD-6.0/images/NetBSD-6.0-evbmips-mips64el.iso) = d4dda568787efe15faa1c00b604c9c262c579ae86f4abd07dcdb796112fa9ca41122efc9c3beedf2281ab1859e11e2ede536d3a7d679a31590021acca4b32324 +RMD160 (NetBSD-6.0/images/NetBSD-6.0-evbmips-mips64el.iso) = 9cb45c46d6ce9d9cabcee0f660fc1a646f849190 +MD5 (NetBSD-6.0/images/NetBSD-6.0-evbmips-mips64el.iso) = 320f53af1cf67bf37bf6d962a49aa688 +SHA1 (NetBSD-6.0/images/NetBSD-6.0-evbmips-mipseb.iso) = c9894866972a80c2ff9032d21339e3ca59c8d0dd +SHA512 (NetBSD-6.0/images/NetBSD-6.0-evbmips-mipseb.iso) = 04a89998d1cd8e70b045479265ce82b3733aa630d536c349e12b4d12e3aae123bd29cc0a7a6930fe07dc121a89e0327d14c2b78987542f064b67287268300830 +RMD160 (NetBSD-6.0/images/NetBSD-6.0-evbmips-mipseb.iso) = 13cc4119e07eb9a8a26666cbf6ae983001cbf39c +MD5 (NetBSD-6.0/images/NetBSD-6.0-evbmips-mipseb.iso) = a5af80295a5bce15ae2cb3c585891d7e +SHA1 (NetBSD-6.0/images/NetBSD-6.0-evbmips-mipsel.iso) = 09155023a46f527048b17f00f554d64b73fb1d40 +SHA512 (NetBSD-6.0/images/NetBSD-6.0-evbmips-mipsel.iso) = 21108a854d7f8ee48d18f8d1fc74886350d1d95ca2eef044f5314570619f108f471c768f93b99b917b887fca4a1d5bfb9f858929c88672faf505ccc6493eef61 +RMD160 (NetBSD-6.0/images/NetBSD-6.0-evbmips-mipsel.iso) = c6c4eddd0acb7b311e6bc40a9ef7acea4c8792d9 +MD5 (NetBSD-6.0/images/NetBSD-6.0-evbmips-mipsel.iso) = 37b00a36438893f30b98de7327628d48 +SHA1 (NetBSD-6.0/images/NetBSD-6.0-evbppc.iso) = bba761cfabb03d27837a21a61e681c0a39b82b50 +SHA512 (NetBSD-6.0/images/NetBSD-6.0-evbppc.iso) = 615d5ba030e1d19c56aaf9152640e652c6aa3ab3609d357b859df61a874125c551ae912f01179f861bae6fa0b09cbb899e9ad689dd62ec7edcd1caec3157d5ca +RMD160 (NetBSD-6.0/images/NetBSD-6.0-evbppc.iso) = 4cba6606c2fc9febb684665512c89ff8106790bd +MD5 (NetBSD-6.0/images/NetBSD-6.0-evbppc.iso) = 45b10af76ae7128c4619864237e703fc +SHA1 (NetBSD-6.0/images/NetBSD-6.0-evbsh3-sh3eb.iso) = 51da3d8f99c84a9e12bab81442a0249624550532 +SHA512 (NetBSD-6.0/images/NetBSD-6.0-evbsh3-sh3eb.iso) = c804c8f1457178bffa1e5b7989a5818381f4911a8fe18a2c75ef9c02b866a9f53be17926faaa4a9460852e482d7a304a13424b8fd6b8013cae15696ebcc24bea +RMD160 (NetBSD-6.0/images/NetBSD-6.0-evbsh3-sh3eb.iso) = 05f04f2d8e64a4508034424bbd9f6adf795675a5 +MD5 (NetBSD-6.0/images/NetBSD-6.0-evbsh3-sh3eb.iso) = c9358e63b62edc277bb8e630627fa49d +SHA1 (NetBSD-6.0/images/NetBSD-6.0-evbsh3-sh3el.iso) = 89dd396a870a8d08bb1ab2a09f9e8b24bb55bb53 +SHA512 (NetBSD-6.0/images/NetBSD-6.0-evbsh3-sh3el.iso) = d9d2018111fc190ab0602e87572e210572bebf2185df101265f29d4ac8bfed8ca671038131eefe125ffacef63924e1274c34fa248b88d01764d138144e768b2b +RMD160 (NetBSD-6.0/images/NetBSD-6.0-evbsh3-sh3el.iso) = ccc5e6f669147c71f9272cae12d63bb270407748 +MD5 (NetBSD-6.0/images/NetBSD-6.0-evbsh3-sh3el.iso) = d33272ecf641d0c4ced897c2fb4d0ae1 +SHA1 (NetBSD-6.0/images/NetBSD-6.0-ews4800mips.iso) = 029c1d1910dd234ad3b33f8a53557a56779dde86 +SHA512 (NetBSD-6.0/images/NetBSD-6.0-ews4800mips.iso) = 09e0dec1e67c44a29cea4eae8c2e7840906c8cc6881331b720905c71dfd0f8050210568d2e5ad6a325a827a08e1e440d84980cb4b515d76501616c7e3f104cf2 +RMD160 (NetBSD-6.0/images/NetBSD-6.0-ews4800mips.iso) = bd7da2f0e68a488d351eab9cda26f11ca2ddaa35 +MD5 (NetBSD-6.0/images/NetBSD-6.0-ews4800mips.iso) = 1286a5646c2f93fc128c8fabb2244bd1 +SHA1 (NetBSD-6.0/images/NetBSD-6.0-hp300.iso) = 3b62c2c6037a1009b5d417e6f09dfdda2781f12a +SHA512 (NetBSD-6.0/images/NetBSD-6.0-hp300.iso) = 2a3d668fde1b5098933d0fbd9fe9100092043a81389f6f7b457a3425dfca5cca52382a29434309baae791c908855b1aed99d32f290723172c62f439f68e4fe5d +RMD160 (NetBSD-6.0/images/NetBSD-6.0-hp300.iso) = 8314b4f992aff06157d9dae5951cce3d6083e6cf +MD5 (NetBSD-6.0/images/NetBSD-6.0-hp300.iso) = 144eb416cc2563df1330cecf26c19f2c +SHA1 (NetBSD-6.0/images/NetBSD-6.0-hp700.iso) = d2840fa102cff8b3d5825304818c98ba2ffdcbe5 +SHA512 (NetBSD-6.0/images/NetBSD-6.0-hp700.iso) = 322461efc0e1648c8e4e16c93421831d14937b5ca93f2a6f25405882c2de40482315ee9e4c914a2e9206cc25eade89687a2a248bc60ea1145626272067fdecba +RMD160 (NetBSD-6.0/images/NetBSD-6.0-hp700.iso) = 11dad584942591d9c719eab0248dba8f71ba8ec8 +MD5 (NetBSD-6.0/images/NetBSD-6.0-hp700.iso) = 93522e82b2562f1f889f74153deccf30 +SHA1 (NetBSD-6.0/images/NetBSD-6.0-hpcarm.iso) = 5afcc737502c47e2a4efcf6a897ecbdee400d3aa +SHA512 (NetBSD-6.0/images/NetBSD-6.0-hpcarm.iso) = 32bd828c5ef1b50b6a9cdac2a419ef80522625bedd2bbb9f60b8076b7f9bef969af19fe28da9b56b6f552e008700b9fa586e1159706aa6eb4c998b2dcf89384f +RMD160 (NetBSD-6.0/images/NetBSD-6.0-hpcarm.iso) = 9a609fb57d4c4a2f8fd9aecee475eddaf7e26da7 +MD5 (NetBSD-6.0/images/NetBSD-6.0-hpcarm.iso) = 7b8bbdc89300d63043e233de6d56584b +SHA1 (NetBSD-6.0/images/NetBSD-6.0-hpcmips.iso) = 203b9953e02574d71e49277b847dfd4b253199cb +SHA512 (NetBSD-6.0/images/NetBSD-6.0-hpcmips.iso) = 72a2e1eb4f9398c3779a64226c8e442e9628edcc0601b9e0c835af9e2ac31d77217b731c831d8d9bbb2c9322ef28b61194281beb0074e39aaa747610fa065ca1 +RMD160 (NetBSD-6.0/images/NetBSD-6.0-hpcmips.iso) = b384e1bd9b5e0644e1d98f68270a82b47e1e0103 +MD5 (NetBSD-6.0/images/NetBSD-6.0-hpcmips.iso) = fc5caa7af29622771e2451debd59f75a +SHA1 (NetBSD-6.0/images/NetBSD-6.0-hpcsh.iso) = 1b3ad4689058b56f012dcdf2ec78d046c7469d0c +SHA512 (NetBSD-6.0/images/NetBSD-6.0-hpcsh.iso) = f2d4686d5560a5ebadbd0f235033bb18db4b291ac9080635e67a8b42328108f0944c69e81ff9daaf28820f0ee98d32c0faba0ba3d397053670f4b2312ba7fdf2 +RMD160 (NetBSD-6.0/images/NetBSD-6.0-hpcsh.iso) = a39e04b9cdcfb2d21fe9ee262756b05f122893b7 +MD5 (NetBSD-6.0/images/NetBSD-6.0-hpcsh.iso) = ca44003562262d681f9eb5e6e3c1f25f +SHA1 (NetBSD-6.0/images/NetBSD-6.0-i386-install.img.gz) = 43e6d3f9d0ae352b8eaec597e3ab48590a8dd62c +SHA512 (NetBSD-6.0/images/NetBSD-6.0-i386-install.img.gz) = 2911ec984eb0b74ffc89dea948d2f0ec6570cf0a13790be8ce31bfe7d90cbcf132d9b7fa27bc3202d16426cf15c192c3543db7d108455f375aebd291e5162827 +RMD160 (NetBSD-6.0/images/NetBSD-6.0-i386-install.img.gz) = 7da2b6c329c7e19a96d7473bed4fed2847a9e7dd +MD5 (NetBSD-6.0/images/NetBSD-6.0-i386-install.img.gz) = 9db5437e777175f3d9fee3370070cca1 +SHA1 (NetBSD-6.0/images/NetBSD-6.0-i386.iso) = ccc8c4d50aaa0e43724df3b3c3afa0e130164053 +SHA512 (NetBSD-6.0/images/NetBSD-6.0-i386.iso) = e71e4dc1ab41720e04f34ae8f5daccd5441f58efe983683574578b4f6c3019b53060e25e4e4880792f3012e47acfeb7eb0f571d01910435db6a4ac541ede8fef +RMD160 (NetBSD-6.0/images/NetBSD-6.0-i386.iso) = 4aefd7279ff09f228506f66ac5e91195c081e31c +MD5 (NetBSD-6.0/images/NetBSD-6.0-i386.iso) = 9b7aca4464fdd5dbeea6d6d85c5ba64f +SHA1 (NetBSD-6.0/images/NetBSD-6.0-ibmnws.iso) = 766ffac66f62d90b017d02b9f571b27ee002eb30 +SHA512 (NetBSD-6.0/images/NetBSD-6.0-ibmnws.iso) = ba2e04ac3173b765d98a72796f643f2c7fe2fbc9eae9f7a85402e65d731c3a089df5a685ad98603e6e44c72956507bd77939d855f4820bcf0aaa1e705be68ec4 +RMD160 (NetBSD-6.0/images/NetBSD-6.0-ibmnws.iso) = f6c480b79e05eb34818b5f018750c4dbfceb7b38 +MD5 (NetBSD-6.0/images/NetBSD-6.0-ibmnws.iso) = 8cbc5b4e8fd0cd9d6cbf6d77f1285f3f +SHA1 (NetBSD-6.0/images/NetBSD-6.0-luna68k.iso) = fb688537b94273c74c52027a5bd0e9f0f1d96381 +SHA512 (NetBSD-6.0/images/NetBSD-6.0-luna68k.iso) = 62911e352841866cdadd4f9ebf909cfe496a03ac4f4452f83ed7a96890448a527a0afc3ab199bcc13a12760bbf287b5b367b96ac340d148d522e759db20a7c5c +RMD160 (NetBSD-6.0/images/NetBSD-6.0-luna68k.iso) = ad5c1f6747d72a83816e13c37eb97cc4b6b0bbfb +MD5 (NetBSD-6.0/images/NetBSD-6.0-luna68k.iso) = 5373e0ffd08922c1e8e5a1f66908d2b7 +SHA1 (NetBSD-6.0/images/NetBSD-6.0-mac68k.iso) = 2216006dda929d7b66bb2c92549378362f772b52 +SHA512 (NetBSD-6.0/images/NetBSD-6.0-mac68k.iso) = 26d539ab284db402e00b48bddcdd726e7869bd28f717771d45cb6e5934fb069ec98f789a2baab8b7fd76aa35db5f9992f58094b9e3e936c83901e277a4bbe6b8 +RMD160 (NetBSD-6.0/images/NetBSD-6.0-mac68k.iso) = b8cf8d1c1ccbb739ce29c01896a4aa55ad66469c +MD5 (NetBSD-6.0/images/NetBSD-6.0-mac68k.iso) = 4e06fdc52d82cc401d3b02c4d0232733 +SHA1 (NetBSD-6.0/images/NetBSD-6.0-macppc.iso) = a8697c11dbd8b3811f1fcc8562a9d11a35f4431b +SHA512 (NetBSD-6.0/images/NetBSD-6.0-macppc.iso) = ba31ab8d00ac0038dc6509661eb39b41d7cafc268b17e9ff75809aac3fc4978fe338b2ee4c2ff59991ae93c11c32cfe019e7309fc507562f9c276172e63492e4 +RMD160 (NetBSD-6.0/images/NetBSD-6.0-macppc.iso) = 36f6b8b12eba9cb39f412ce2cba71ab88a4445fe +MD5 (NetBSD-6.0/images/NetBSD-6.0-macppc.iso) = ca246495fb1465b57eb93c826063a20d +SHA1 (NetBSD-6.0/images/NetBSD-6.0-mipsco.iso) = 5f3a351f960e81c829d7bb8f6924b0b912006c05 +SHA512 (NetBSD-6.0/images/NetBSD-6.0-mipsco.iso) = e04111c293c6a3a6df5433aaa8d7883c7f88bf03c868ddccb05ae7c243d9a880e54329d4d995cc5bfc6539fdb7120207463f54c3a4a5c0a317bd12173e0fac18 +RMD160 (NetBSD-6.0/images/NetBSD-6.0-mipsco.iso) = 85552cf47b7eab35619385444e0d76ce8c6ed887 +MD5 (NetBSD-6.0/images/NetBSD-6.0-mipsco.iso) = 7e684c533513710039e0fa96ba70b51c +SHA1 (NetBSD-6.0/images/NetBSD-6.0-mvme68k.iso) = 48ed08c58863636dcf49ad5728812def96cf82eb +SHA512 (NetBSD-6.0/images/NetBSD-6.0-mvme68k.iso) = ded376941ef8437fcf37f7ca801f4e9996b4adcd97d9ccc7a16d30c8045880d4e7a894ab5cd44000bb3895950c007669207bfd58bdbde3a11b2a123e5b747c47 +RMD160 (NetBSD-6.0/images/NetBSD-6.0-mvme68k.iso) = cfb7ee4fc9422ebf6dc0c7d73b59dc2b161d58ef +MD5 (NetBSD-6.0/images/NetBSD-6.0-mvme68k.iso) = 9ee62757053b2cb7f7a1d6ab82db929d +SHA1 (NetBSD-6.0/images/NetBSD-6.0-mvmeppc.iso) = 5b74dd3e1d76f697d089ad1a769ef8aba17330ba +SHA512 (NetBSD-6.0/images/NetBSD-6.0-mvmeppc.iso) = a007559063e269c4f27597f27c3bf6dda97f34a33d7e750c2a6fb36bacc0a64b12a0011b0570ae71b5977735de5f1d58de553e5a89ea4f61b6c09fc34e3989ea +RMD160 (NetBSD-6.0/images/NetBSD-6.0-mvmeppc.iso) = 9d26c663310b2555b8dc544e9b286a7ab80e8bd3 +MD5 (NetBSD-6.0/images/NetBSD-6.0-mvmeppc.iso) = 3c8ab738e662b3b7f1b481a4712c4525 +SHA1 (NetBSD-6.0/images/NetBSD-6.0-news68k.iso) = b40de418e4f4140f31895100674dc69e1b3c2f80 +SHA512 (NetBSD-6.0/images/NetBSD-6.0-news68k.iso) = bfca4085850abfe577482870397af0c964574cb7b426903c5634a747026e1db835fe6db0dde4d8a320438b1f136dc7aa2dd0bd1e05d664c92ddd307b3ad718e9 +RMD160 (NetBSD-6.0/images/NetBSD-6.0-news68k.iso) = 00df7a8b50bb5b4f45b56107db94a559b1571458 +MD5 (NetBSD-6.0/images/NetBSD-6.0-news68k.iso) = a9a9524f9d696a5104d2b9f157f8a416 +SHA1 (NetBSD-6.0/images/NetBSD-6.0-newsmips.iso) = 91c6ba0265d2ab04f60358dbf8fcb388c81e674f +SHA512 (NetBSD-6.0/images/NetBSD-6.0-newsmips.iso) = 182904027a2e24e0869e0c177915c2d99be87ea8994298f7106940bfde95feacb1ab07e17f0535adaea35d63eb6ec014378bb2777b0a3dc4e15f362038050460 +RMD160 (NetBSD-6.0/images/NetBSD-6.0-newsmips.iso) = 93bedba32f25a7d6f658e396de5b7eb98ec7654a +MD5 (NetBSD-6.0/images/NetBSD-6.0-newsmips.iso) = c6a0377dfb49f663d7bf657589a68c48 +SHA1 (NetBSD-6.0/images/NetBSD-6.0-ofppc.iso) = 1b0927effa1f68779ec787536f67447574f50674 +SHA512 (NetBSD-6.0/images/NetBSD-6.0-ofppc.iso) = 7cfa755bab97c165f5ed60063d4fde79d90fa4a786cf13d32617f324759719175b909806aac34df32b39a5a443348f020787bce43f4d7600ba9bc65ec00e111a +RMD160 (NetBSD-6.0/images/NetBSD-6.0-ofppc.iso) = aab50e82812ffe6b4216d9c9a44787d9f0f667b8 +MD5 (NetBSD-6.0/images/NetBSD-6.0-ofppc.iso) = 97772de08fb8020d661192e622e3cf21 +SHA1 (NetBSD-6.0/images/NetBSD-6.0-pmax.iso) = 5293cfe1a34eced76bd825d7eeef7ee55af98299 +SHA512 (NetBSD-6.0/images/NetBSD-6.0-pmax.iso) = 681eb46ded55a111f6ac2f5baa9ebe4f3f6c252ecd20270377b466305402a97f6be47db192e5a05920a17ecbf03c03bb169161bcb75b4813af5a2e10b1becd53 +RMD160 (NetBSD-6.0/images/NetBSD-6.0-pmax.iso) = b61b7ee3525e26f990f4276d689d23469b4639a1 +MD5 (NetBSD-6.0/images/NetBSD-6.0-pmax.iso) = 4211afdc8ed6225b395f65a089347ebb +SHA1 (NetBSD-6.0/images/NetBSD-6.0-prep.iso) = e1702b470594f9b5955bba78d9179eec12176e9d +SHA512 (NetBSD-6.0/images/NetBSD-6.0-prep.iso) = 552a43f2a255b844a0a39db0e352dcf04b7df73cbe6eb4851a2bbfd1f5bcdf12d4742ef9f596052fd678ff4adae4c92a1eda71acccaa53c8bf310cf5900dbaa2 +RMD160 (NetBSD-6.0/images/NetBSD-6.0-prep.iso) = 382ff5006df921cb66fc8ab2bf78544c1dc501ae +MD5 (NetBSD-6.0/images/NetBSD-6.0-prep.iso) = 2cacc13c35c1e406dfe0aec549f97eee +SHA1 (NetBSD-6.0/images/NetBSD-6.0-sandpoint.iso) = 6d866b095f838011b6132d443b602d4b97a644e0 +SHA512 (NetBSD-6.0/images/NetBSD-6.0-sandpoint.iso) = 6e6a0eaa9de07b142c43a749bc6257a410f9c7f801c450cfec17fa30c0f7b0f5a925d1c73705a4d2d567451fe5c88304c6e85c4f1ba1c0127b07f9bd0ed452c5 +RMD160 (NetBSD-6.0/images/NetBSD-6.0-sandpoint.iso) = a2d052a86ed3bc1a751de334b737cdd1e1661f8b +MD5 (NetBSD-6.0/images/NetBSD-6.0-sandpoint.iso) = 8a137ad061aba60a2bcffa8b9c9fa370 +SHA1 (NetBSD-6.0/images/NetBSD-6.0-sgimips.iso) = eee6aecc9d478d101b20756b5438e858d43f2700 +SHA512 (NetBSD-6.0/images/NetBSD-6.0-sgimips.iso) = 3979fa422cd562e6dcfa83eefc072d66380ce1ec10f5534c394c08bebcc977d58d5c27f0f41efe1555570be9eb93e33143df0c1fb1cec47b29f3f8961853132e +RMD160 (NetBSD-6.0/images/NetBSD-6.0-sgimips.iso) = b20388701c9428de38cf7cd5afa7464bb0d5a07c +MD5 (NetBSD-6.0/images/NetBSD-6.0-sgimips.iso) = 73c4e4f6723ef82859be32abb34b9367 +SHA1 (NetBSD-6.0/images/NetBSD-6.0-shark.iso) = d331eaa8be85d8a112c277ac018d9d0cc88d8b39 +SHA512 (NetBSD-6.0/images/NetBSD-6.0-shark.iso) = 91aacdd54e4ae41cbf71d4a91533bf66ef9dacaf7d71ffa81f0fabec5e98f3f5685f62b75ceac6db51a3da160a4c3e92fe3a5469165fa92c23d76d4e9aebe9a2 +RMD160 (NetBSD-6.0/images/NetBSD-6.0-shark.iso) = 88a248ed7456f4c08fa9581026c555df29c05daf +MD5 (NetBSD-6.0/images/NetBSD-6.0-shark.iso) = ea424a950e7168c79a2b80152504fe61 +SHA1 (NetBSD-6.0/images/NetBSD-6.0-source.iso) = 09749966ddaadad296254adec70d4f4c01f20fdf +SHA512 (NetBSD-6.0/images/NetBSD-6.0-source.iso) = d45abaf7551b96232228024a7f08d19943a8912a2383c456a66aff8bde1dc4ec60a3dc084ea4801c6c4691d714e257672f87436d7070a939fbf0fb5b2119854e +RMD160 (NetBSD-6.0/images/NetBSD-6.0-source.iso) = 002f87e50d6113c7a2820a4888b8484c1848bfa7 +MD5 (NetBSD-6.0/images/NetBSD-6.0-source.iso) = 4d63a05600813e5588720da5328967ac +SHA1 (NetBSD-6.0/images/NetBSD-6.0-sparc.iso) = c60cdabd739d287e3424f8a6e2b671b7b41a944a +SHA512 (NetBSD-6.0/images/NetBSD-6.0-sparc.iso) = 1dd5305519efa2c90341088e26b66b38426ce5e42a066277605abaa0e85322a9af2031ada8faf1e303e7f10f8b29e8765673de14a5a04c4e5f2f6001b7c52241 +RMD160 (NetBSD-6.0/images/NetBSD-6.0-sparc.iso) = ba9dc6b22a648f9b0af3c44eed518401b20e50ab +MD5 (NetBSD-6.0/images/NetBSD-6.0-sparc.iso) = ec7578864447eb816413264ad512b017 +SHA1 (NetBSD-6.0/images/NetBSD-6.0-sparc64.iso) = a6a5475eeb3e88d520a5bbed7d62f0067c5fe65d +SHA512 (NetBSD-6.0/images/NetBSD-6.0-sparc64.iso) = 50f36f089ee8c27190512d16ec50661db4136c257c947439d670893fe610a9b07d577a7ab8b9f4d9cd6766e9daa8b619aa3a0f6f95e3abe43a4955dbf9d2d401 +RMD160 (NetBSD-6.0/images/NetBSD-6.0-sparc64.iso) = b8dd4236c01dbe061cc0e0e20e71b805aee8b998 +MD5 (NetBSD-6.0/images/NetBSD-6.0-sparc64.iso) = dd2dd0625585e969262fd0c99751c64e +SHA1 (NetBSD-6.0/images/NetBSD-6.0-sun2.iso) = 1c0755c7c8a094769b4c1b50566fa05e4848e113 +SHA512 (NetBSD-6.0/images/NetBSD-6.0-sun2.iso) = d37ddcca3ac60bba6e8547c8bdd2029d5ee39517eff1b90534dd02eacb5e5e36b3be9a06b86386d451ee89c2408c151fb55f0427d3ba682b4076dc3f5c8925a8 +RMD160 (NetBSD-6.0/images/NetBSD-6.0-sun2.iso) = 4a20723c243cd7dd43c8eb4272971072d21a2efc +MD5 (NetBSD-6.0/images/NetBSD-6.0-sun2.iso) = c2f9f999646eef2bcf2c9bdb6d2e860d +SHA1 (NetBSD-6.0/images/NetBSD-6.0-sun3.iso) = db35e360979a3c38984afb91309387fa9a415bf0 +SHA512 (NetBSD-6.0/images/NetBSD-6.0-sun3.iso) = c4a8fde6c486ee8b23a485d6b2947a1620a2f7582df13a255dc8f6fd2860dd93b0e1c2dc3b56387adad49b935999c70cdb293f25f87c2f227af35e158fe6a7b5 +RMD160 (NetBSD-6.0/images/NetBSD-6.0-sun3.iso) = 0ff6f3798f945c797b2ccae534cbece05e3a4d34 +MD5 (NetBSD-6.0/images/NetBSD-6.0-sun3.iso) = 042f8191d0aa3b4ee986408c1bcce04a +SHA1 (NetBSD-6.0/images/NetBSD-6.0-vax.iso) = 8f43de5ed15d0178faa9b79763c7564d479711c8 +SHA512 (NetBSD-6.0/images/NetBSD-6.0-vax.iso) = afa099641b4684f021c3a94f3a8624c3aad92a8083555ad3bf78028fcb530d08b9b778d96635bbe098c88e6e08be2733d01c4dfca8933d4120e7571dbc715a88 +RMD160 (NetBSD-6.0/images/NetBSD-6.0-vax.iso) = 09800ce94b2007f7c51850e9db87270e0123e9f7 +MD5 (NetBSD-6.0/images/NetBSD-6.0-vax.iso) = 0830c9dc45aa84e08cf97580708cc60e +SHA1 (NetBSD-6.0/images/NetBSD-6.0-x68k.iso) = 022558b77ecb7c5b6a35aa0e79c6aaab56031d16 +SHA512 (NetBSD-6.0/images/NetBSD-6.0-x68k.iso) = 0cf2986fa2477df206a46bc19f566c6cbe8712ad14fbf40d9d4c20aa104a65eaeb93d73c86ac101125d0c5b5619f53a7296d032f56c15930baf496853b604902 +RMD160 (NetBSD-6.0/images/NetBSD-6.0-x68k.iso) = 5becbb0b0c10a69dfaf131910da0c72a208beeb3 +MD5 (NetBSD-6.0/images/NetBSD-6.0-x68k.iso) = 6f7c0d6afb962d18f61cfafc78f38b12 +SHA1 (NetBSD-6.0/images/NetBSD-6.0-zaurus.iso) = 5c78cce50c6f26c64456228695ff51b12b8cd44f +SHA512 (NetBSD-6.0/images/NetBSD-6.0-zaurus.iso) = 8a0849c505a0db1ed89fb066f6814f32e9998017cfd684ac38b9027d94ba4a2ebec496ba1ee194e0f98d176820077ea50c5a45cb85b6f24a1d1a2b14e9a0dd1a +RMD160 (NetBSD-6.0/images/NetBSD-6.0-zaurus.iso) = f505c50d0049b053abd5fce076e0e67dcd13c2aa +MD5 (NetBSD-6.0/images/NetBSD-6.0-zaurus.iso) = 5e3a023090f8b8df40a7372dc1749b81 +SHA1 (NetBSD-6.0/iyonix/binary/kernel/netbsd-GENERIC.gz) = 235873272a098d18934590d26ab5c636859262ad +SHA512 (NetBSD-6.0/iyonix/binary/kernel/netbsd-GENERIC.gz) = 0a4f296210a18785815dc51d191c97aa069403e2e0460038f6dc59a65a97f39d9345abf0e793a12dc562068a7eb0d825881030969ea43a48775704958700ee86 +RMD160 (NetBSD-6.0/iyonix/binary/kernel/netbsd-GENERIC.gz) = 1c5a2e39c1876ee7b46a9ee9751da1d418c2a607 +MD5 (NetBSD-6.0/iyonix/binary/kernel/netbsd-GENERIC.gz) = 5f2302d30d7dcfa644d62c656eeb33e3 +SHA1 (NetBSD-6.0/iyonix/binary/sets/games.tgz) = e1d2bb091d8202962133475bc83edb55230b9008 +SHA512 (NetBSD-6.0/iyonix/binary/sets/games.tgz) = a147fe6d0419d53d5a428802d0bb6c9fa8a84a76c96d7d6d7c0d399e5af3a69240116463549a83d53387b0214ba0207796d7c10228d92a684fe7ff0ece3aec16 +RMD160 (NetBSD-6.0/iyonix/binary/sets/games.tgz) = 2be515c495548ba5135ff42a75a8ebbfc35ea776 +MD5 (NetBSD-6.0/iyonix/binary/sets/games.tgz) = 9059a6f2cd41cb58827709c9e9a1649b +SHA1 (NetBSD-6.0/iyonix/binary/sets/man.tgz) = 899b9d8242e983a5110ab755651c24f709b5af67 +SHA512 (NetBSD-6.0/iyonix/binary/sets/man.tgz) = 410999db110d710f4bb498c3d7ae7adc62170c7c2f470ce189c92f6c436c5ea96149659c631ef0b5605caaa025d97dfe1c07c428d86f51239657bd6b71717b15 +RMD160 (NetBSD-6.0/iyonix/binary/sets/man.tgz) = c1270f68c6d41b351877f71f0396ac34877dfc8d +MD5 (NetBSD-6.0/iyonix/binary/sets/man.tgz) = df4db2bbfa39ef6a4a215d949653d04a +SHA1 (NetBSD-6.0/iyonix/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/iyonix/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/iyonix/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/iyonix/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/iyonix/binary/sets/xbase.tgz) = 875fd641f969ec00f854ca1334d084947450c740 +SHA512 (NetBSD-6.0/iyonix/binary/sets/xbase.tgz) = 75d0c9e9685b6b7bb706df7427c8b52f59c4fc4d0e725b02ee18024f75a546dc41de5f1a5d8552a8d2c84bdf87856e5857b0f12914801ca7b36b69536d617b4e +RMD160 (NetBSD-6.0/iyonix/binary/sets/xbase.tgz) = 1a4d099d59b2bd882e99f1b2df1c7bf22b890d48 +MD5 (NetBSD-6.0/iyonix/binary/sets/xbase.tgz) = 5eb9c573c5a0c96701f268a3470a58b9 +SHA1 (NetBSD-6.0/iyonix/binary/sets/xcomp.tgz) = 8d7469a85b7433c89690cce74e6b3f4e66cf0647 +SHA512 (NetBSD-6.0/iyonix/binary/sets/xcomp.tgz) = 411304cf66e300a7f162128203099bb4d6eebc4a93ba18ed7caf79f30b31cc7ffcede85c4e1bad02c3f5f8a27d009fb71f3ce5862c1d8aa477f39a25c535fdaa +RMD160 (NetBSD-6.0/iyonix/binary/sets/xcomp.tgz) = 822d26e0ee08b72ca8b991f0709a8c1bf0399208 +MD5 (NetBSD-6.0/iyonix/binary/sets/xcomp.tgz) = 5af361f0334d28119d703064278b3ed3 +SHA1 (NetBSD-6.0/iyonix/binary/sets/xetc.tgz) = 222d14c205f1018cc5a86eb03214d18cda2abb82 +SHA512 (NetBSD-6.0/iyonix/binary/sets/xetc.tgz) = fb82261996aa772fd8a9022eadebf899ee04ee70229ee4fe07758ca14937bdb34752c8218eb4c5b722b6208f719891493bbc141372fcfa503de83e0a61aa7387 +RMD160 (NetBSD-6.0/iyonix/binary/sets/xetc.tgz) = 511ebfe5076f361b7f7ca03a265d16052a16d259 +MD5 (NetBSD-6.0/iyonix/binary/sets/xetc.tgz) = 165cffbb6d2c79663198d80c82afac1e +SHA1 (NetBSD-6.0/iyonix/binary/sets/xfont.tgz) = ce0e141beeffeb5b470478e9887e4127da85de3c +SHA512 (NetBSD-6.0/iyonix/binary/sets/xfont.tgz) = 5d98354ff77103793d56af3192ab5f9afcde62208791976064ac33a149f994e0227dd5dd28ed544eeac5ea504e5212d5fb9e7d05e59e5a48a2fe4062e34e3106 +RMD160 (NetBSD-6.0/iyonix/binary/sets/xfont.tgz) = 4d09f5e82fec875ef0ea328809465e7a98f2ebfc +MD5 (NetBSD-6.0/iyonix/binary/sets/xfont.tgz) = be26b3890261302420b09976a1d38144 +SHA1 (NetBSD-6.0/iyonix/binary/sets/xserver.tgz) = 4ccfef1d49179603286042088bec0218c6b2031d +SHA512 (NetBSD-6.0/iyonix/binary/sets/xserver.tgz) = 809fc0a9065c1b9e7cd17aeb0d41cfd3158efd6c585556af01c4a3c93f0df3646a2ff77c6994449a703a408c0988fc1aa68cf34c7e297a3056d73ded57034c12 +RMD160 (NetBSD-6.0/iyonix/binary/sets/xserver.tgz) = 403604404261764c74f10fab774c4653fd20cc9b +MD5 (NetBSD-6.0/iyonix/binary/sets/xserver.tgz) = 914f909b6878cef16a92765a8cbb52ca +SHA1 (NetBSD-6.0/iyonix/binary/sets/kern-GENERIC.tgz) = 13354b2863a67ec38b91a8b8cab2ae5081cf68cf +SHA512 (NetBSD-6.0/iyonix/binary/sets/kern-GENERIC.tgz) = 02ad11423d70de2c4b1e937bfdb6348af4025c026513f4f05768f2344997a4414896f10b72af056410dcc62d8760449c2dd47ff2bd37d0e4011d45a1fe0e98b1 +RMD160 (NetBSD-6.0/iyonix/binary/sets/kern-GENERIC.tgz) = 4a98f89230f9faaf839d5b607097d7612aa6741e +MD5 (NetBSD-6.0/iyonix/binary/sets/kern-GENERIC.tgz) = ecfbf309ba59a5ed39e46ed54b8173e4 +SHA1 (NetBSD-6.0/iyonix/binary/sets/base.tgz) = 697554f5182bff135cb94ba8c99b29d719aeefc1 +SHA512 (NetBSD-6.0/iyonix/binary/sets/base.tgz) = 52b73ea3de1d96f706a48b02e7cc6234576d5bad72828ef34e61929c460ea839f6051e3a650880307a86757f35265c2a33780bbe4640d301f70a4ebae06c7e8b +RMD160 (NetBSD-6.0/iyonix/binary/sets/base.tgz) = 7e7a5a24095a326e8998ba95c291c5380a89600f +MD5 (NetBSD-6.0/iyonix/binary/sets/base.tgz) = 74682becd88ad5b73b5434940f1e8436 +SHA1 (NetBSD-6.0/iyonix/binary/sets/comp.tgz) = ab05d7d706899d1a555b6ec101f6d13d7f13ad97 +SHA512 (NetBSD-6.0/iyonix/binary/sets/comp.tgz) = 246d589d8d3c37375496ddd3e15da6a5bb101bc1405c13ba2751818555eaad37c403e27437326bac2ff3c20763c95a49df0bfdb324faf3110c7ec01d7676b78e +RMD160 (NetBSD-6.0/iyonix/binary/sets/comp.tgz) = a5835f803a5c74d6484e7171085460b803705e22 +MD5 (NetBSD-6.0/iyonix/binary/sets/comp.tgz) = 53c3ef4ec81bc6b1f89e15081ad4bb48 +SHA1 (NetBSD-6.0/iyonix/binary/sets/etc.tgz) = 7294ce630333a9bea7392c5083118cc68bcb5732 +SHA512 (NetBSD-6.0/iyonix/binary/sets/etc.tgz) = f1699017e37109605eecfb44174327a974f1a7a741e16f67f387170ddd1b2c661c58bd9b6dc0795153e828ef52d16cc45b37743cb86be98623da38736938061b +RMD160 (NetBSD-6.0/iyonix/binary/sets/etc.tgz) = 1a9cdec0a39de8c3d0b2ec63b7c674bd597e67e0 +MD5 (NetBSD-6.0/iyonix/binary/sets/etc.tgz) = d655e4ef20778005efe66b02cdd5f471 +SHA1 (NetBSD-6.0/iyonix/binary/sets/modules.tgz) = 2689f2acb9a977df7801394cd49f6f84d93fab8a +SHA512 (NetBSD-6.0/iyonix/binary/sets/modules.tgz) = 853553a5ae0acde4b24a80372c1fa71777ede655a76c60f1d2bc835df50fc2ff03270a5edca72c492fe07a3208a8680a10277b83fab4e7a3f064ded4c91cd151 +RMD160 (NetBSD-6.0/iyonix/binary/sets/modules.tgz) = 4d2d0ba3492b751accda0a03daef7cba859f223f +MD5 (NetBSD-6.0/iyonix/binary/sets/modules.tgz) = 129dd8d6331eacc63934568b1467edc9 +SHA1 (NetBSD-6.0/iyonix/binary/sets/tests.tgz) = b54fb7a814d7bebe4a40a00c17253d0bc6ca4544 +SHA512 (NetBSD-6.0/iyonix/binary/sets/tests.tgz) = c99e6c4b80fc2d6a0f236f324f844a562db128876a5b89ced62097a732b273fb6d9af8fde55f3e949768882cb31fab2918cd731f1259b67a1b2548030417c2de +RMD160 (NetBSD-6.0/iyonix/binary/sets/tests.tgz) = 61ee29ddcfd0268fb7ef37829aeb75e3152b76d8 +MD5 (NetBSD-6.0/iyonix/binary/sets/tests.tgz) = ce8b49fc2bfd31965b5b989de17d5cd1 +SHA1 (NetBSD-6.0/iyonix/binary/sets/text.tgz) = 6f119b3eb99d94a4aa41b5bde28856b3daa83d84 +SHA512 (NetBSD-6.0/iyonix/binary/sets/text.tgz) = 03a29fcc5ba8ce7d6ab590d61bc0a3f4dbb9bbce89d4e8cefc00cf398fa92e2363f3e3fa5da4cc17d3bd9195434c5a951550c6091b1168614a6a0b2831f3f881 +RMD160 (NetBSD-6.0/iyonix/binary/sets/text.tgz) = 2a1331121dc41105accbf9b491bcd4aaa3589907 +MD5 (NetBSD-6.0/iyonix/binary/sets/text.tgz) = 9bd5612ff2228f1bfee64c0f6a872fe4 +SHA1 (NetBSD-6.0/landisk/binary/kernel/netbsd-INSTALL.symbols.gz) = d9440af1a917beaff6598eec266db86853625b08 +SHA512 (NetBSD-6.0/landisk/binary/kernel/netbsd-INSTALL.symbols.gz) = 982b13dc871a9e562e191ff6d156f202cef18174b66e18adac8e77037fd4edbd29848dfbfec15f94744375b7967bdbd0c5bac0414eac22b78c5ea1fae91f0ed6 +RMD160 (NetBSD-6.0/landisk/binary/kernel/netbsd-INSTALL.symbols.gz) = 6320116f0640f069a52a4c52196ba45a306b594f +MD5 (NetBSD-6.0/landisk/binary/kernel/netbsd-INSTALL.symbols.gz) = b6d766477c4b69e1e3003d68a28d742a +SHA1 (NetBSD-6.0/landisk/binary/kernel/netbsd-GENERIC.gz) = 2f1a4b4a1b4b88ab919ce3addcf2310da10c1c12 +SHA512 (NetBSD-6.0/landisk/binary/kernel/netbsd-GENERIC.gz) = 21fe1b84d9c5c85f3c9d963ce9497d6b8250a3c5789dcf387612089aea424a728503c9adc5e047d8887959be84a8cbbdf397b7f2685fbef2d0fab448238279fb +RMD160 (NetBSD-6.0/landisk/binary/kernel/netbsd-GENERIC.gz) = e35fb6d1b917230c4b622ea52276a47e2a711d33 +MD5 (NetBSD-6.0/landisk/binary/kernel/netbsd-GENERIC.gz) = b6c0c1333ca3b1a45d3a828f7d18d918 +SHA1 (NetBSD-6.0/landisk/binary/kernel/netbsd-INSTALL.gz) = 3348d95ce13a6217331a1992064194aec1775db4 +SHA512 (NetBSD-6.0/landisk/binary/kernel/netbsd-INSTALL.gz) = bfa4fa3ab82db17aef5f5b4b818cb8fb5d9101d6709752bd88231042ce3c2c731a452a1360fdcd77d8eb3c0cd7368de7aa359b65b7d35d4f78d8182670de4a72 +RMD160 (NetBSD-6.0/landisk/binary/kernel/netbsd-INSTALL.gz) = 95d2efee62025110beb81c829712563b4495633b +MD5 (NetBSD-6.0/landisk/binary/kernel/netbsd-INSTALL.gz) = 143697e4aa570e39175812011fca30f1 +SHA1 (NetBSD-6.0/landisk/binary/sets/man.tgz) = 899b9d8242e983a5110ab755651c24f709b5af67 +SHA512 (NetBSD-6.0/landisk/binary/sets/man.tgz) = 410999db110d710f4bb498c3d7ae7adc62170c7c2f470ce189c92f6c436c5ea96149659c631ef0b5605caaa025d97dfe1c07c428d86f51239657bd6b71717b15 +RMD160 (NetBSD-6.0/landisk/binary/sets/man.tgz) = c1270f68c6d41b351877f71f0396ac34877dfc8d +MD5 (NetBSD-6.0/landisk/binary/sets/man.tgz) = df4db2bbfa39ef6a4a215d949653d04a +SHA1 (NetBSD-6.0/landisk/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/landisk/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/landisk/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/landisk/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/landisk/binary/sets/kern-GENERIC.tgz) = 4ed0c44b9ce3362aa10429a75e3dcd4a01963055 +SHA512 (NetBSD-6.0/landisk/binary/sets/kern-GENERIC.tgz) = 1764a9d7ef8a4fc9cc321cecd486f767096a6bc34eb83b3bf3fd24c0383a3df139200560a7846d23bebdc4e02feffe7252a26689b2971964b9240a26abf4acd7 +RMD160 (NetBSD-6.0/landisk/binary/sets/kern-GENERIC.tgz) = 75e8fa6b9c66cec999c28d9242379df0142d0bdc +MD5 (NetBSD-6.0/landisk/binary/sets/kern-GENERIC.tgz) = 7226e2efa45822998b444dfbce3affe8 +SHA1 (NetBSD-6.0/landisk/binary/sets/base.tgz) = 7cef6d1878fea6a5448eb32456056155477dbb47 +SHA512 (NetBSD-6.0/landisk/binary/sets/base.tgz) = fd16dca9619d1e1a3770486594935e091bc7219b24db8bf91ec0cc8b064f2a201d13dca61b50885e1a2428512bbf510ea7f69a9b8174ac82f511f66c6a8cb70b +RMD160 (NetBSD-6.0/landisk/binary/sets/base.tgz) = 97e06530ed9a98f0d48746c33db25e2ee0460360 +MD5 (NetBSD-6.0/landisk/binary/sets/base.tgz) = d0e0468ef015bcada5e688057a53efc2 +SHA1 (NetBSD-6.0/landisk/binary/sets/comp.tgz) = fb19c5e935ea83f6c5679796cc9527fa3e435508 +SHA512 (NetBSD-6.0/landisk/binary/sets/comp.tgz) = 0636a207ee4126ef209fee7b5fdbee6eea677cd8b640798aeab5138803fbe8754de69aeff925e3298783409009e6cf8658f9983a213425d397e90f76a93e3f7e +RMD160 (NetBSD-6.0/landisk/binary/sets/comp.tgz) = 0f4190b6173c8618f7609ba726e73cb041ac75e6 +MD5 (NetBSD-6.0/landisk/binary/sets/comp.tgz) = 7317e108ba56869a21b9d7137605eaf5 +SHA1 (NetBSD-6.0/landisk/binary/sets/etc.tgz) = 25f6f82b594c5d383d45e6c7ee3e0720afe0cb32 +SHA512 (NetBSD-6.0/landisk/binary/sets/etc.tgz) = f2f77e86753a1193cc4c37372a303a88e6c51fd0d3d2e6ffa1927a697aab915c9fd5f1f7ac81137e9182388a6a60912b0b2d6d6975abe0029cf9206367b7454d +RMD160 (NetBSD-6.0/landisk/binary/sets/etc.tgz) = a5db723013194035deb0e61dc04f6985fcc4a51f +MD5 (NetBSD-6.0/landisk/binary/sets/etc.tgz) = 92d41bd9cd00823be1afb0d3846e10e2 +SHA1 (NetBSD-6.0/landisk/binary/sets/games.tgz) = 65ef265cc562c21af9cea790c1eb0f7d1ee4ac50 +SHA512 (NetBSD-6.0/landisk/binary/sets/games.tgz) = f55cb863e6bd20e52f04d643199317ffeb673d8ad7a1b1506ccb6d798d6b511766d8188b1a567ab148ad38ab8dfb4516eb624044827880a0c1f289631e9d7f88 +RMD160 (NetBSD-6.0/landisk/binary/sets/games.tgz) = 9a0cfcc234841f9b3086c8e6479686a9e486fe27 +MD5 (NetBSD-6.0/landisk/binary/sets/games.tgz) = 9f57cb59ad62f29327c1f1daf6d8e130 +SHA1 (NetBSD-6.0/landisk/binary/sets/modules.tgz) = 0755c390f758947aaa8fa5942c3600a9c1da0155 +SHA512 (NetBSD-6.0/landisk/binary/sets/modules.tgz) = d20bbd1969460b825f413f06e28280bfc549d74e82287ec6f8b7eb70db2dc8680fcb5f1b42e96e48feda3c377eda9ef4890bcb03aeb2401dc45cc79353826a5a +RMD160 (NetBSD-6.0/landisk/binary/sets/modules.tgz) = b43dea943dd41ece88282f1a858926afba42f061 +MD5 (NetBSD-6.0/landisk/binary/sets/modules.tgz) = 77fe2185916c4e1df174079291a33e61 +SHA1 (NetBSD-6.0/landisk/binary/sets/tests.tgz) = d5cafffe5049a81843f684c81ff1909669e6e8a4 +SHA512 (NetBSD-6.0/landisk/binary/sets/tests.tgz) = b01eccf78b1fac7ca92a10e6440a80ccccbcbc90dcafc44692d149a0b719c9058de6e1a28207f06fa7db29403552df527c200a27ffda708cf49ae2f2c7033886 +RMD160 (NetBSD-6.0/landisk/binary/sets/tests.tgz) = 0a2d702412e9add961586f2cd87eb2895889cdef +MD5 (NetBSD-6.0/landisk/binary/sets/tests.tgz) = 7fa1f86aabba0e9ff906164c5046418f +SHA1 (NetBSD-6.0/landisk/binary/sets/text.tgz) = 753e3063d3a42b43208bfb9ee44cadfbf777b02b +SHA512 (NetBSD-6.0/landisk/binary/sets/text.tgz) = 63c337c80b7fb440d813803b06c0b34d1a484c1e5a18f1bcf6fe90f3880bde3269c8ed7fb0485405bd9ba618069fbe680163be2b4c53c6d81ff8e263777fd51c +RMD160 (NetBSD-6.0/landisk/binary/sets/text.tgz) = 83afeda6e537627561023c5570ca05aaa2d3027c +MD5 (NetBSD-6.0/landisk/binary/sets/text.tgz) = fae31d47dbe89c926a95c602012bcd36 +SHA1 (NetBSD-6.0/landisk/binary/sets/xbase.tgz) = 240739fa38b2f6bf5ff63504fc02b5e006d404fa +SHA512 (NetBSD-6.0/landisk/binary/sets/xbase.tgz) = 93ace6b1ec640cb33e586a2e3b4b53c46b34efa1c3cb40ac7bde2531a6b253a42fa92564ba203f7f5b725b9673017766ba5a7636ac32e6722a3787559be916be +RMD160 (NetBSD-6.0/landisk/binary/sets/xbase.tgz) = e76eddb131991fd9641a77469b782e1672370644 +MD5 (NetBSD-6.0/landisk/binary/sets/xbase.tgz) = f0502dec4137d4ba757447285b98f09e +SHA1 (NetBSD-6.0/landisk/binary/sets/xcomp.tgz) = 06e8daf72bf753e226e3d5df7b47ef8344470c27 +SHA512 (NetBSD-6.0/landisk/binary/sets/xcomp.tgz) = 101b0c365ad2209e8b4520f586a9cd60595b0dfa414c061cf24cfbf18a9455ab6a786f968d3a5eb5f06db57cd9cde4262d5031aaf6d5cdde152ac92c91a31c09 +RMD160 (NetBSD-6.0/landisk/binary/sets/xcomp.tgz) = 3bfd31356e625cbb25f035db41d44d3a4523fb25 +MD5 (NetBSD-6.0/landisk/binary/sets/xcomp.tgz) = 2d4a2c3e4a93d2b1e56e7641bfa730d9 +SHA1 (NetBSD-6.0/landisk/binary/sets/xetc.tgz) = 06a24e45e73bf98cb87b951fe3bfe4a81a1d0793 +SHA512 (NetBSD-6.0/landisk/binary/sets/xetc.tgz) = 72d35ff20eec9cb6674031e31c382ff63fea51f6cb10290a540cb83de5639145faff66119fe7f176ba97bb389b9edf4aae3838f008df9f1b111699fb8555f4ee +RMD160 (NetBSD-6.0/landisk/binary/sets/xetc.tgz) = e63035911479f2a87f20fe5f030ef31b3bee1878 +MD5 (NetBSD-6.0/landisk/binary/sets/xetc.tgz) = 309875d5ca3be7fb66f2ec0ab6e2e18b +SHA1 (NetBSD-6.0/landisk/binary/sets/xfont.tgz) = 06922d4fa8af9ec61283885a5040552442f1a0dd +SHA512 (NetBSD-6.0/landisk/binary/sets/xfont.tgz) = 48790c97453934379e37f2826498b64480554cad16ee807d44e83eed4c53b324659df0cc8aa954ec6f5f5a16ae03209a0c03dcf45db3bd807011d6d16d66654a +RMD160 (NetBSD-6.0/landisk/binary/sets/xfont.tgz) = 5f1a4142f95c2fbf064d94e11afb0660d17c384f +MD5 (NetBSD-6.0/landisk/binary/sets/xfont.tgz) = 0a8a39b6c5e1ae9be657196b82c16717 +SHA1 (NetBSD-6.0/landisk/binary/sets/xserver.tgz) = fc311910c92490d19bb81ff540f65370a01cfa9d +SHA512 (NetBSD-6.0/landisk/binary/sets/xserver.tgz) = 8f8f392ab9696e20149e94dc85061be26982179e63fbfaac269dcb13509d4e9ec44c8188b6f333cad0b2139703c78e1f0919b71394ac6ac2526ce7935ec2329d +RMD160 (NetBSD-6.0/landisk/binary/sets/xserver.tgz) = 86ec983a4047e7a0c146cfab94df6331f0363e89 +MD5 (NetBSD-6.0/landisk/binary/sets/xserver.tgz) = 2befe5df4dce2ccb1770ac2019da8ec6 +SHA1 (NetBSD-6.0/landisk/installation/misc/boot.fs) = b8bbc9b7108311040a9a3e1bad714efccbdeab21 +SHA512 (NetBSD-6.0/landisk/installation/misc/boot.fs) = 8fbf69cfcb9e7e104c244a8cc2c11d0bc2e2f006eb8a5b8e97267604519fb0e415a9da6bc81a0e75fd30e2ce8fb40a4026a97cbd413de71c05caa1e5f16871fa +RMD160 (NetBSD-6.0/landisk/installation/misc/boot.fs) = 333044e352899852a8fbb7308a6009c1b5a69bcb +MD5 (NetBSD-6.0/landisk/installation/misc/boot.fs) = 47ea13afac308dfe956f2d5c16a3a285 +SHA1 (NetBSD-6.0/landisk/installation/netboot) = ca38444ab6911f5b12f0797a6198f082030ba9b3 +SHA512 (NetBSD-6.0/landisk/installation/netboot) = 064115997cd9a49abeb68a811406fad102a2ad325dd1e3ddac075f19e86d04d660bc4f6640483f825310e51d7cfdd90de4997c52dabc883e64f7d984444ef276 +RMD160 (NetBSD-6.0/landisk/installation/netboot) = dad8b6e8b216ef75971c7805baf4b4f86ecfad60 +MD5 (NetBSD-6.0/landisk/installation/netboot) = d29e773e58700dde6b5384464b517785 +SHA1 (NetBSD-6.0/landisk/INSTALL.html) = 5222270ac1c6fa408d5ef0bb7e901d99e916be72 +SHA512 (NetBSD-6.0/landisk/INSTALL.html) = 4011e42ffc09b225893c360690d01099ef76445c496e10c2434e50f8c97755d15038206bd2bc9bb4ee773c24e7b5bb64bf969a1e4ac4e07f4ec84c0beb21bf8d +RMD160 (NetBSD-6.0/landisk/INSTALL.html) = 48a1b2c374b38629c87e1c04e661e36182caab0a +MD5 (NetBSD-6.0/landisk/INSTALL.html) = dfa8413fc180b897d13c0964362e7b3f +SHA1 (NetBSD-6.0/landisk/INSTALL.more) = add61a5d904d34e380a4fcd69cb7fffd24143a42 +SHA512 (NetBSD-6.0/landisk/INSTALL.more) = 4165166b8cc79bd589c80490352c0741edc2087e7560658ea0da993347301f94b3685babd2c40e8927fdd8ca9a58350232dad0cc1ec0c247890a283f1ca191b2 +RMD160 (NetBSD-6.0/landisk/INSTALL.more) = 7416e0e529dcbd99dca03cb901e7038cc60731a5 +MD5 (NetBSD-6.0/landisk/INSTALL.more) = 871f600baa29f1db802884fc26783526 +SHA1 (NetBSD-6.0/landisk/INSTALL.ps) = 734d5c64f3e69a68dd0b987492851f7f915692a9 +SHA512 (NetBSD-6.0/landisk/INSTALL.ps) = a34a07c314fe9a7e4f9dfc296f9e05116675f722ad0aaab757d76c31246a9182398bca5906c3882ff1b14fda9480bb674f12daa90274df9968f2c374d7a2d356 +RMD160 (NetBSD-6.0/landisk/INSTALL.ps) = 88c78a031426844ab1afca9dec3ba7289e994dd3 +MD5 (NetBSD-6.0/landisk/INSTALL.ps) = 446d71c39365e90bf6491895a781a4e7 +SHA1 (NetBSD-6.0/landisk/INSTALL.txt) = f4d9af9565019dda406298ac72875959cdcb1b72 +SHA512 (NetBSD-6.0/landisk/INSTALL.txt) = fe20c04bf5c15d95d5bcf8cafc9efd9ffb07e37ed6234c7abe8a2ff01fae1cb7aca2c4eb28a7d032212a31cae34331d0ce9fad7a3f7a01bb0a9b66e40352f5ec +RMD160 (NetBSD-6.0/landisk/INSTALL.txt) = 3739b2ac5572c87aa6e8a86c6b33023db1c5e6f1 +MD5 (NetBSD-6.0/landisk/INSTALL.txt) = 7e1c46e08b5773bcd5ecc0717834c25a +SHA1 (NetBSD-6.0/luna68k/binary/kernel/netbsd-INSTALL.symbols.gz) = 6d24a14ed0376a5672de20c9c3b64137fcfe3b90 +SHA512 (NetBSD-6.0/luna68k/binary/kernel/netbsd-INSTALL.symbols.gz) = 5b4957606a4a575aa8c0fea6dbb10df17ef4ac7afa8624c456cc625a0e0e2d1d86c2ca9a4fcf770949933af22cda99479bfab55d383878d0acd8f0c0a260820f +RMD160 (NetBSD-6.0/luna68k/binary/kernel/netbsd-INSTALL.symbols.gz) = bd90a974d6697d2921362ed308fef5df89a6a7f5 +MD5 (NetBSD-6.0/luna68k/binary/kernel/netbsd-INSTALL.symbols.gz) = b5fa03bb653ae6c758c1374109969d01 +SHA1 (NetBSD-6.0/luna68k/binary/kernel/netbsd-GENERIC.aout.gz) = 1a6b46426c3e93110e9138dc56dbf4e15391c7c4 +SHA512 (NetBSD-6.0/luna68k/binary/kernel/netbsd-GENERIC.aout.gz) = fe4cf575cd9e08ccf01adec28e38311c7fda42dfd2de5d17f98be37fbac8023b9fa4225c58b5d46728af2f3885825f34068acb82f600447ed60ec54ccc5753ad +RMD160 (NetBSD-6.0/luna68k/binary/kernel/netbsd-GENERIC.aout.gz) = d1e8da51257a921f3d3c0ecec9f5a06712018302 +MD5 (NetBSD-6.0/luna68k/binary/kernel/netbsd-GENERIC.aout.gz) = 1d29443ff1170766ece9a482e2468f73 +SHA1 (NetBSD-6.0/luna68k/binary/kernel/netbsd-GENERIC.gz) = d36634bfc138c395323135e9c60824b7f987b588 +SHA512 (NetBSD-6.0/luna68k/binary/kernel/netbsd-GENERIC.gz) = b7cdfcd815eea67d65ea003a2e56fd0a83ddfa1695749a5316566f9e59ef69dd9d78e80c54e99c9aa2db57d8e0ee9a3af43580ed40b45086b357362428e4faf1 +RMD160 (NetBSD-6.0/luna68k/binary/kernel/netbsd-GENERIC.gz) = 2d36be27f36008788fee498a9c18dbe7a3d66c08 +MD5 (NetBSD-6.0/luna68k/binary/kernel/netbsd-GENERIC.gz) = ca10cc06f8e60b045230888b523f71ad +SHA1 (NetBSD-6.0/luna68k/binary/kernel/netbsd-INSTALL.aout.gz) = e081ce3c03ff74c60f2a0ba80540e5b398aac926 +SHA512 (NetBSD-6.0/luna68k/binary/kernel/netbsd-INSTALL.aout.gz) = a02d1a6974fe702be5e51419440ebdf00bd333b0c4b88cf1289a992bfc21be4f731edb386bdb5e559b5f1fac064e392b97a800431538bd21e76ebb2f6f1c24a6 +RMD160 (NetBSD-6.0/luna68k/binary/kernel/netbsd-INSTALL.aout.gz) = 0db65548da46e8d651e8b2b9d4ee3b1f95086f61 +MD5 (NetBSD-6.0/luna68k/binary/kernel/netbsd-INSTALL.aout.gz) = 22e3b4a434ae0bf2e200bd4f6f223ff9 +SHA1 (NetBSD-6.0/luna68k/binary/kernel/netbsd-INSTALL.gz) = 43172b3e8115db8f41cff2170f4b5d47dd1da8e5 +SHA512 (NetBSD-6.0/luna68k/binary/kernel/netbsd-INSTALL.gz) = e7e217acc802aff14a3ea852a1dd0f62088dea15ecadc3cc9b335259ecabf352028dfa5929ff139f31f5b299311a5e42e944c0979be0299501caed3592e1d86e +RMD160 (NetBSD-6.0/luna68k/binary/kernel/netbsd-INSTALL.gz) = c53f3f5d7e4150eb768b377877d8a8d71f22d156 +MD5 (NetBSD-6.0/luna68k/binary/kernel/netbsd-INSTALL.gz) = 5d3869dcf1301987a12ffa512b626d19 +SHA1 (NetBSD-6.0/luna68k/binary/sets/games.tgz) = 16ee93ea4d5fac2fb28fad5c32c8a3d57d011d79 +SHA512 (NetBSD-6.0/luna68k/binary/sets/games.tgz) = a7f49ab72f50273f66c8dcf408b57ec4668debd5537c5bd0ec59aa0f4fa1d599ba0798d1b283315c4208cbcb608925808ce003b1ade79034886edb8208f9f48d +RMD160 (NetBSD-6.0/luna68k/binary/sets/games.tgz) = 1e09d99d7fe2e495763f05919472d27a4ba699df +MD5 (NetBSD-6.0/luna68k/binary/sets/games.tgz) = 8a26f3e864444209088bccf21419a616 +SHA1 (NetBSD-6.0/luna68k/binary/sets/man.tgz) = 899b9d8242e983a5110ab755651c24f709b5af67 +SHA512 (NetBSD-6.0/luna68k/binary/sets/man.tgz) = 410999db110d710f4bb498c3d7ae7adc62170c7c2f470ce189c92f6c436c5ea96149659c631ef0b5605caaa025d97dfe1c07c428d86f51239657bd6b71717b15 +RMD160 (NetBSD-6.0/luna68k/binary/sets/man.tgz) = c1270f68c6d41b351877f71f0396ac34877dfc8d +MD5 (NetBSD-6.0/luna68k/binary/sets/man.tgz) = df4db2bbfa39ef6a4a215d949653d04a +SHA1 (NetBSD-6.0/luna68k/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/luna68k/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/luna68k/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/luna68k/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/luna68k/binary/sets/xbase.tgz) = ffc6dc889560371042dd12a5486a9a2c499b86a9 +SHA512 (NetBSD-6.0/luna68k/binary/sets/xbase.tgz) = 9aa2ba4d703a13020acf8543d1efcde76b6f0f4b411be20f804709b3802e537be1e651eba469830c4fd4777a379ea9936200a3a3eb4b1a702c04bb81aafcc723 +RMD160 (NetBSD-6.0/luna68k/binary/sets/xbase.tgz) = 3ecf53e7414ef859a47fe5afc108cf3bfa82fb1d +MD5 (NetBSD-6.0/luna68k/binary/sets/xbase.tgz) = a6af002ce158cf72eb5c6a7cde2c0989 +SHA1 (NetBSD-6.0/luna68k/binary/sets/kern-GENERIC.tgz) = dca3d0e2fc1d884287bd283e81bc797ceeb13195 +SHA512 (NetBSD-6.0/luna68k/binary/sets/kern-GENERIC.tgz) = 58388c5d51f6f09f0884904ba8b18ae63374f807312177898080267382141c631e6aa0698a55b427e5673b34fa995cb3d8cd7e77dc1036c9812fe8356f976dc7 +RMD160 (NetBSD-6.0/luna68k/binary/sets/kern-GENERIC.tgz) = d9c5321bc472e64656a250e3e3bd6d72119435ce +MD5 (NetBSD-6.0/luna68k/binary/sets/kern-GENERIC.tgz) = 374856b19bd6eb0c072c4b25933f5f8d +SHA1 (NetBSD-6.0/luna68k/binary/sets/base.tgz) = bc10452b7a7a1a24dec1813d74ff78d1d82ae750 +SHA512 (NetBSD-6.0/luna68k/binary/sets/base.tgz) = 5525e21ff9566b0c7ce169e2a087094e41cd3e60d4f67d8ae026c4169cc5b606cb88f600e4410570053dd9ea8202b0da0fd7293fc8c6531c722bb4109accc605 +RMD160 (NetBSD-6.0/luna68k/binary/sets/base.tgz) = d763e9b40ced7122fa0ccb461386a7b7ff1dce1a +MD5 (NetBSD-6.0/luna68k/binary/sets/base.tgz) = 665d860c4af2fd73227eda7bbfbf124f +SHA1 (NetBSD-6.0/luna68k/binary/sets/comp.tgz) = c69dde9c6ef3a0ed4457ced09c7016465b0e82df +SHA512 (NetBSD-6.0/luna68k/binary/sets/comp.tgz) = bbb46b665a23fb728945c51cc19ae85da4e33da19d91ce15ed24d7832258c0cb53f75351c869aa46704cf09245403b9b28fb55624e0b8e28c2e509b653d459ba +RMD160 (NetBSD-6.0/luna68k/binary/sets/comp.tgz) = c622dbd3522567457fd890414386ebbebf6204e9 +MD5 (NetBSD-6.0/luna68k/binary/sets/comp.tgz) = c0c2030d7bd68b455be0b4094a1e949a +SHA1 (NetBSD-6.0/luna68k/binary/sets/etc.tgz) = 7d1db50a753d92b90ee1eaf6b4a4f02cab03d981 +SHA512 (NetBSD-6.0/luna68k/binary/sets/etc.tgz) = 86c1904b4007d3a1f4a91f30140a3c6d53af8b90c38c01fee75b679484096079d357e7a71c027464a5d48d4789d9c4a04f3f2545df907953c739a22877ae130e +RMD160 (NetBSD-6.0/luna68k/binary/sets/etc.tgz) = 52873f9a82119f52ef847e3e27e00ab4e10c68cf +MD5 (NetBSD-6.0/luna68k/binary/sets/etc.tgz) = cef84e15f32a2bf92f3657f981235991 +SHA1 (NetBSD-6.0/luna68k/binary/sets/modules.tgz) = 9428e74da3601eab14416d01bc4880dcfe21a6f7 +SHA512 (NetBSD-6.0/luna68k/binary/sets/modules.tgz) = ec64bcf7ebed5af30e85708133fcac6f0946aa0ba7175906b1f9ed06c300c23028ba0ba1957c1e4fe6d4c7a99877e7ed104b1439cec728db79fe9f3cad3eccb1 +RMD160 (NetBSD-6.0/luna68k/binary/sets/modules.tgz) = 8060c8587dfadee593f84db43c0e63acfc259e06 +MD5 (NetBSD-6.0/luna68k/binary/sets/modules.tgz) = 1477ab794d1c6494bb5a9628820c4c08 +SHA1 (NetBSD-6.0/luna68k/binary/sets/tests.tgz) = 8380e48719aca55a72f3f91629e52a774eb7e4d7 +SHA512 (NetBSD-6.0/luna68k/binary/sets/tests.tgz) = eced534537094e8ee83154a5319f89f4cf8e46bf8715ff6329a01f8824e231bdf726ea6f6cd4ad940d0a0a45b5b99c27eb5083e69ae915f56b2beaa7d8b63d89 +RMD160 (NetBSD-6.0/luna68k/binary/sets/tests.tgz) = 05c755294af5ff529c495865595c8bfe7f5d91fb +MD5 (NetBSD-6.0/luna68k/binary/sets/tests.tgz) = 4e8df8ec4228f385e7eb7d097904a8fc +SHA1 (NetBSD-6.0/luna68k/binary/sets/text.tgz) = 19f8fb95eef7c6162c661a5262f5f41fd92f6078 +SHA512 (NetBSD-6.0/luna68k/binary/sets/text.tgz) = f2a4f42b05526d21fffc8d4783885b155bdcd8183b194058e9554bb34eb47a6b0ba2d6a9779c12f17844a6bb2fc07530a7a1d7dcacbec44b437fbc08796b65bf +RMD160 (NetBSD-6.0/luna68k/binary/sets/text.tgz) = f01ee7d5dd88c612e8c8b3aae25ca93e1c70df0b +MD5 (NetBSD-6.0/luna68k/binary/sets/text.tgz) = c55b5fb2f398aaebe749d7d2a6fc8570 +SHA1 (NetBSD-6.0/luna68k/binary/sets/xcomp.tgz) = 01bdf2494bf84313fb000f36606161f17cbc0114 +SHA512 (NetBSD-6.0/luna68k/binary/sets/xcomp.tgz) = d4fb1fb22011bf3b178593e1a2be51626563c6ccb35f3c2db922374d9dc1dc1fdd7830df24f1f699a89c46d5a7044c221372015134682aba5a2010d5f44ef77f +RMD160 (NetBSD-6.0/luna68k/binary/sets/xcomp.tgz) = 03191d2a871d99076fe73355da23bfaf537294bf +MD5 (NetBSD-6.0/luna68k/binary/sets/xcomp.tgz) = c30eac2a665f533444de26dafbbdd77f +SHA1 (NetBSD-6.0/luna68k/binary/sets/xetc.tgz) = 3d78331b298a38fb6bd231bff59cccdedceaf71a +SHA512 (NetBSD-6.0/luna68k/binary/sets/xetc.tgz) = ecaaaaa343d9abb3d24d147826956ad64fe96338d38511b5226d3cf2cc564eb8cc39aa833c7e0875fc4378aa6b8c2f3a7ad17c8906f8c68e5adc16c3cec5b715 +RMD160 (NetBSD-6.0/luna68k/binary/sets/xetc.tgz) = 7734dfa9521226f76e23b91d237109bf30855cbf +MD5 (NetBSD-6.0/luna68k/binary/sets/xetc.tgz) = 0e5ef946483a93d487b70b526477efb0 +SHA1 (NetBSD-6.0/luna68k/binary/sets/xfont.tgz) = dca18181278f672451b3902ebdbf3d79ccfdedb4 +SHA512 (NetBSD-6.0/luna68k/binary/sets/xfont.tgz) = 3979a9cc4b1731c8b31f44cabbe74920cb03d7e7d551743eee78442e0ba67a6faa854cdc674cd0338422aa09119ae653f2fdbd2c78dc6811c49661e812ce7fc1 +RMD160 (NetBSD-6.0/luna68k/binary/sets/xfont.tgz) = 9b946721f534b2fd651e742f9061ef5d648efd3a +MD5 (NetBSD-6.0/luna68k/binary/sets/xfont.tgz) = a3b4aad9b96343e5565a441b3376f454 +SHA1 (NetBSD-6.0/luna68k/binary/sets/xserver.tgz) = 859f7b47396c427f5d6c3570f6f68227131b2b34 +SHA512 (NetBSD-6.0/luna68k/binary/sets/xserver.tgz) = e1eee654564f67397c0324d8f89e62b0fcb40857b423ad2fb47c04d3bca7fa833a04adef639baf3c48bc27400f4d8a548d55efc7e29dfac74a82794e5182ce2a +RMD160 (NetBSD-6.0/luna68k/binary/sets/xserver.tgz) = 1f75e4523b978323e96a0c986edbd700ae351846 +MD5 (NetBSD-6.0/luna68k/binary/sets/xserver.tgz) = e50f795889ea9f0cfc49fcc6d8991ec4 +SHA1 (NetBSD-6.0/mac68k/binary/kernel/netbsd-GENERICSBC.gz) = 33453c6105617ec6e41c81d71be7b04b68f26e24 +SHA512 (NetBSD-6.0/mac68k/binary/kernel/netbsd-GENERICSBC.gz) = 9ea5036462094ff9ff7696cc13f9b76166f4c6058ee8e79547898866c27e96b5e31e4e27228fc7bddc69b0f11ca242113778b2ab8c6c458d16fd08e7b5148557 +RMD160 (NetBSD-6.0/mac68k/binary/kernel/netbsd-GENERICSBC.gz) = aa85610097d3144646f7bdcbdfd1cd55fd248280 +MD5 (NetBSD-6.0/mac68k/binary/kernel/netbsd-GENERICSBC.gz) = 4b4ce73206f5d0203aedf08b4e9e73e4 +SHA1 (NetBSD-6.0/mac68k/binary/kernel/netbsd-GENERIC.gz) = 644b65114d6ffc9bef291f18e3935ca539ed29e5 +SHA512 (NetBSD-6.0/mac68k/binary/kernel/netbsd-GENERIC.gz) = 8e590640af3dfd78202b83a4bc6afec869ee37b467a10b3221c08e54c3a66bddc1726cca88d09fa98598f77d8bbc6dd36c136c685bab7e75198a9b6fa89e11da +RMD160 (NetBSD-6.0/mac68k/binary/kernel/netbsd-GENERIC.gz) = 2bccecd72133b03055457567ea8eca57acc56ac6 +MD5 (NetBSD-6.0/mac68k/binary/kernel/netbsd-GENERIC.gz) = ece356c2c95629fc502bb2e9382f9b4c +SHA1 (NetBSD-6.0/mac68k/binary/sets/games.tgz) = 16ee93ea4d5fac2fb28fad5c32c8a3d57d011d79 +SHA512 (NetBSD-6.0/mac68k/binary/sets/games.tgz) = a7f49ab72f50273f66c8dcf408b57ec4668debd5537c5bd0ec59aa0f4fa1d599ba0798d1b283315c4208cbcb608925808ce003b1ade79034886edb8208f9f48d +RMD160 (NetBSD-6.0/mac68k/binary/sets/games.tgz) = 1e09d99d7fe2e495763f05919472d27a4ba699df +MD5 (NetBSD-6.0/mac68k/binary/sets/games.tgz) = 8a26f3e864444209088bccf21419a616 +SHA1 (NetBSD-6.0/mac68k/binary/sets/man.tgz) = 899b9d8242e983a5110ab755651c24f709b5af67 +SHA512 (NetBSD-6.0/mac68k/binary/sets/man.tgz) = 410999db110d710f4bb498c3d7ae7adc62170c7c2f470ce189c92f6c436c5ea96149659c631ef0b5605caaa025d97dfe1c07c428d86f51239657bd6b71717b15 +RMD160 (NetBSD-6.0/mac68k/binary/sets/man.tgz) = c1270f68c6d41b351877f71f0396ac34877dfc8d +MD5 (NetBSD-6.0/mac68k/binary/sets/man.tgz) = df4db2bbfa39ef6a4a215d949653d04a +SHA1 (NetBSD-6.0/mac68k/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/mac68k/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/mac68k/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/mac68k/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/mac68k/binary/sets/xcomp.tgz) = e13548b8974f5d55e98caf17b2b4bbbcf2430370 +SHA512 (NetBSD-6.0/mac68k/binary/sets/xcomp.tgz) = e4b13c798df04ffef88e72100e2db5af400e5ae255cd7a1ca2907736b8138a59045b6f3bd8531b5753d0b87eadb1b5f801043a929bb25d1611e4be693c1da954 +RMD160 (NetBSD-6.0/mac68k/binary/sets/xcomp.tgz) = 3b1f4e26ddd57e69afd9709553c1bf70d6e29ea0 +MD5 (NetBSD-6.0/mac68k/binary/sets/xcomp.tgz) = 894bb9aa05b164d9923682165d708335 +SHA1 (NetBSD-6.0/mac68k/binary/sets/xetc.tgz) = d2ca34bd668e108cbbfd4b45720823663339f8bd +SHA512 (NetBSD-6.0/mac68k/binary/sets/xetc.tgz) = 431ca465f300e7eb5d4dbd44c43e412a296fb4d3129217e752f86a720e8a8bdf736c9add05a45518a4f3e6cffa32381ef61e9186d360b68a5f8c64d87e385fb5 +RMD160 (NetBSD-6.0/mac68k/binary/sets/xetc.tgz) = 4c5d664679856b02b694534cd6afdf20597e6d53 +MD5 (NetBSD-6.0/mac68k/binary/sets/xetc.tgz) = 72bd67556ac14ea0ce147374af0ba624 +SHA1 (NetBSD-6.0/mac68k/binary/sets/xfont.tgz) = 24ca4cb77a59246b1b05e0a91fed21c63259d12b +SHA512 (NetBSD-6.0/mac68k/binary/sets/xfont.tgz) = 8dc297fb6205a995767e68e77cc21169234dfb66a86bbcd2e1828fd32efeda0a25c9f2a9b1a39b97fe8d7b24f8cd5cf6160859af6be2259876f39ee4e76c405b +RMD160 (NetBSD-6.0/mac68k/binary/sets/xfont.tgz) = d2f134959940e6667aca185f01e388c05dc6bc85 +MD5 (NetBSD-6.0/mac68k/binary/sets/xfont.tgz) = 3c96c1f0a13cd7d277ca35622ac9c058 +SHA1 (NetBSD-6.0/mac68k/binary/sets/kern-GENERIC.tgz) = f8cc845ee4bb3a6eaba937a9aa9ef56ee7df39a1 +SHA512 (NetBSD-6.0/mac68k/binary/sets/kern-GENERIC.tgz) = 173879f5b2cee758aaec0d6baa6adfe208aa0817ce70edb8a4d821189de5e6a64dd5a4f0cd1da4b166579427f416383bc068d7e49677999e075cbe3ed40c99d8 +RMD160 (NetBSD-6.0/mac68k/binary/sets/kern-GENERIC.tgz) = 2e10430ed05682c3d2e2c9496d847535a68988a8 +MD5 (NetBSD-6.0/mac68k/binary/sets/kern-GENERIC.tgz) = 4c60130363f2cf09731d6dd9b98fbcb3 +SHA1 (NetBSD-6.0/mac68k/binary/sets/base.tgz) = 702a0468018c02cc7ce229811a3905477da4f722 +SHA512 (NetBSD-6.0/mac68k/binary/sets/base.tgz) = 871ff91422cfc76ef2e1fdf7a2052cbceaba0b7afacbf5856f2b440e834f1f4cc3759322f99bf85c4effff2a657f03a68978479d495985cf3ecf1cc3d0db4d88 +RMD160 (NetBSD-6.0/mac68k/binary/sets/base.tgz) = 184263ea29fe40e2def660f30c049a1f7c80d42d +MD5 (NetBSD-6.0/mac68k/binary/sets/base.tgz) = ee8a6af6800f2a8ad6b9d6bb099bdf1d +SHA1 (NetBSD-6.0/mac68k/binary/sets/comp.tgz) = c355ad494accbc2a9cc99011c6a7f1030027b4cd +SHA512 (NetBSD-6.0/mac68k/binary/sets/comp.tgz) = 084828af876a61b296f6d34258462165cd23bdcb43ff5ac7f30d2b1ca43be31716c98de636e708ff193d8f97671eff2535d09710a66e4aa67151f326e423052c +RMD160 (NetBSD-6.0/mac68k/binary/sets/comp.tgz) = 3119965a0c66603ebb2b62b7ca53838f2a468e0b +MD5 (NetBSD-6.0/mac68k/binary/sets/comp.tgz) = 777aac0001fb61b70b6f5da36c73e8ea +SHA1 (NetBSD-6.0/mac68k/binary/sets/etc.tgz) = a279de07a8d912b05e056c846bc616c084edeab9 +SHA512 (NetBSD-6.0/mac68k/binary/sets/etc.tgz) = 833a3c74e048bf2cc9f148b14a81eeb526071a1226fbafc3b501409922f4bb67b69d68cdd59cc8b83fe8fccb0afd1135e64b16683e8f42230530efab0e3ed115 +RMD160 (NetBSD-6.0/mac68k/binary/sets/etc.tgz) = 11fed26b10f5d68485667c9b0eb0673b4fb17390 +MD5 (NetBSD-6.0/mac68k/binary/sets/etc.tgz) = c6e0534c4470b66908a3f6e194723ffe +SHA1 (NetBSD-6.0/mac68k/binary/sets/kern-GENERICSBC.tgz) = 851fd53f568f2c855c934f975d322954de4c6b07 +SHA512 (NetBSD-6.0/mac68k/binary/sets/kern-GENERICSBC.tgz) = 869f6b8f6eb4408a4f2950e8b9e10d020d14c0b829dd951d9746a9a778dbf142d53cb263cd797ec862b34a1aa367dfdbef5a633bd1181e442cce9fc0da2c8de7 +RMD160 (NetBSD-6.0/mac68k/binary/sets/kern-GENERICSBC.tgz) = ff894994dc6fe3773893eae064bbd95aca6077ab +MD5 (NetBSD-6.0/mac68k/binary/sets/kern-GENERICSBC.tgz) = 0f2df7a929df022d55d5a73fe75e47a4 +SHA1 (NetBSD-6.0/mac68k/binary/sets/modules.tgz) = aefbcaa2fb397cb690e38e3be240caabf9282947 +SHA512 (NetBSD-6.0/mac68k/binary/sets/modules.tgz) = 83c696fccc6143c9c03e4efdf8ec65363dad51bbc48b434dc21a9949424f12db413de66abfa328b6d45f4097c59ee0324797ccc4ee7e462451170ce9ed7a81f9 +RMD160 (NetBSD-6.0/mac68k/binary/sets/modules.tgz) = 44606993e2ae655bdafaf93a92cee5a85efb9e2a +MD5 (NetBSD-6.0/mac68k/binary/sets/modules.tgz) = 03bdab5790fdf19db36149fc33857b4f +SHA1 (NetBSD-6.0/mac68k/binary/sets/tests.tgz) = 56b5e85ef88683b81048d2e6136aa949e690d92a +SHA512 (NetBSD-6.0/mac68k/binary/sets/tests.tgz) = d4290b5069cb2290aac992145bcd69ff6e34b98ae2661e5cc16dd5b70362c1036c079dad7c96288f473c600e9cd1870c079268ffd08acb418ecc21708e3399ae +RMD160 (NetBSD-6.0/mac68k/binary/sets/tests.tgz) = 7d46086a6a53cd19439f6967849dd294bb27b631 +MD5 (NetBSD-6.0/mac68k/binary/sets/tests.tgz) = 746ea69e63fb5af15f526f2f950ea449 +SHA1 (NetBSD-6.0/mac68k/binary/sets/text.tgz) = db35814cfb2c8ecce27765b3257b885d2e6debde +SHA512 (NetBSD-6.0/mac68k/binary/sets/text.tgz) = 4110c6d47405005eafdb9fb205505f2cc40c6a2ace5b611312f4ef15ae5207a9ef5c4a42ca3b53164ec6f00a80efa5aa6d669a79a9e89da6f73fadd2dc5e437d +RMD160 (NetBSD-6.0/mac68k/binary/sets/text.tgz) = 38345e956e8a7be25706d4809bfa83ac626a3e96 +MD5 (NetBSD-6.0/mac68k/binary/sets/text.tgz) = 90b4f37e590530f361f5ba22882f6184 +SHA1 (NetBSD-6.0/mac68k/binary/sets/xbase.tgz) = a9988db70cf4a221f20fa81d7f2525575eff6161 +SHA512 (NetBSD-6.0/mac68k/binary/sets/xbase.tgz) = 996a52c0e2a69be7ffbad4fca9e79e03cd72533d3c5059660b2bc5ebb3e982e010f53a870583d9eba702f143365508f5a8ab307d9806fda3df1f48021a3dcf4e +RMD160 (NetBSD-6.0/mac68k/binary/sets/xbase.tgz) = 10e9d44638eab39da8b579a32ebf1ae283901401 +MD5 (NetBSD-6.0/mac68k/binary/sets/xbase.tgz) = 649bdf23aca348bbb0d7d3741154cbcd +SHA1 (NetBSD-6.0/mac68k/binary/sets/xserver.tgz) = 2139abe77fda0708a14f6cf7cb3787ede3369f35 +SHA512 (NetBSD-6.0/mac68k/binary/sets/xserver.tgz) = db558b4f6be34da37cc971183c3a67d8d51ea26f3852b9ae53844ca5bc3fc0be405b6c30b6409d1e0d653178f4f6dc46645f37526ddd7d74be735a38beeaab09 +RMD160 (NetBSD-6.0/mac68k/binary/sets/xserver.tgz) = 32d160c3aab16c5a3ed819c9c020c8189e735c9f +MD5 (NetBSD-6.0/mac68k/binary/sets/xserver.tgz) = c17de992b6f02ad51a720faaf0ac04d5 +SHA1 (NetBSD-6.0/mac68k/installation/instkernel/netbsd-INSTALL.symbols.gz) = 7ab45cb4b64d15f930d7b275acf62d70015c7d9c +SHA512 (NetBSD-6.0/mac68k/installation/instkernel/netbsd-INSTALL.symbols.gz) = 107b76145d7484485984483a8b793bbd3fd56f0eccafc619f9b5cb119bdbd0f87ca5918257554a9623c535416368eb4dac4df8fcdfdd12ac279459b775827e56 +RMD160 (NetBSD-6.0/mac68k/installation/instkernel/netbsd-INSTALL.symbols.gz) = 2f2e4239577f923664edb12730c51e15106079a2 +MD5 (NetBSD-6.0/mac68k/installation/instkernel/netbsd-INSTALL.symbols.gz) = d53fc2a484e0add618fcdd9b236ffdd3 +SHA1 (NetBSD-6.0/mac68k/installation/instkernel/netbsd-INSTALL.gz) = 6f94e9d416e73a7019fd05338369616e459db5a3 +SHA512 (NetBSD-6.0/mac68k/installation/instkernel/netbsd-INSTALL.gz) = 8fc1096815fdcc6e987e0c69b991553ff094e226127a10bcd9510ffa0dcc746fb7416896e54ea32f18e80c5782937b8af34d20c55d8758c750ff7810ec69c203 +RMD160 (NetBSD-6.0/mac68k/installation/instkernel/netbsd-INSTALL.gz) = 6ddc97fcb3cf13544c3190956c37f34897cf35f7 +MD5 (NetBSD-6.0/mac68k/installation/instkernel/netbsd-INSTALL.gz) = 3d4a8d946ed122290abac6375a9ef863 +SHA1 (NetBSD-6.0/mac68k/installation/instkernel/netbsd-INSTALLSBC.symbols.gz) = 2672525b1b4997e3793edea3ee8b30c23cffb102 +SHA512 (NetBSD-6.0/mac68k/installation/instkernel/netbsd-INSTALLSBC.symbols.gz) = 003877e10fb0dad0b7190bbf559f190f3de2c0e1068caa5601a0a938706225e2cb7b141f8e4e767da7ed1ff15350f42792ee9a7de5e1d7149dfc233d6dbb4da9 +RMD160 (NetBSD-6.0/mac68k/installation/instkernel/netbsd-INSTALLSBC.symbols.gz) = 8f7b7ddfd1b96f5ca34f4a074cf27adf7701ceca +MD5 (NetBSD-6.0/mac68k/installation/instkernel/netbsd-INSTALLSBC.symbols.gz) = 2aba4f14a7812f2d935c5ddd84634529 +SHA1 (NetBSD-6.0/mac68k/installation/instkernel/netbsd-INSTALLSBC.gz) = c91cbdc339088c1c32868779c918f746d4b5f4f7 +SHA512 (NetBSD-6.0/mac68k/installation/instkernel/netbsd-INSTALLSBC.gz) = 11eff94f2d5aaef7decbf6447a91f692c605a5d36acbea876e6a2501dddc681a60a89d3084ed1413c80ba3d8b23c90abfc567dc99254a9d810353992757d6284 +RMD160 (NetBSD-6.0/mac68k/installation/instkernel/netbsd-INSTALLSBC.gz) = f26b7b6f484d727ff6aa460985f23af89f72c8f7 +MD5 (NetBSD-6.0/mac68k/installation/instkernel/netbsd-INSTALLSBC.gz) = 2dffa66829a868235a11ab636e793d52 +SHA1 (NetBSD-6.0/mac68k/installation/miniroot/miniroot.fs.gz) = dc091b6ed92bd1269a8f76c427d606345a8f49fa +SHA512 (NetBSD-6.0/mac68k/installation/miniroot/miniroot.fs.gz) = ba5b9a96d964da2b2c0c5640a4669840352057ea799013ceae75d3d9a7782d6a4096cbc591b287b663edd27a3db54ff5a5b62a81099c2f97d21c3919b0bc7b59 +RMD160 (NetBSD-6.0/mac68k/installation/miniroot/miniroot.fs.gz) = dc09fba5a4fe6ead5f59da6026018a63065ee414 +MD5 (NetBSD-6.0/mac68k/installation/miniroot/miniroot.fs.gz) = ab49b728c7a2ef8c273a3ad07b5e3e6b +SHA1 (NetBSD-6.0/mac68k/installation/misc/src/Installer_1.1g.src.sea.hqx) = 5ae75a6179968ac955f38b60f57e3811a1e4a3de +SHA512 (NetBSD-6.0/mac68k/installation/misc/src/Installer_1.1g.src.sea.hqx) = 0017e59c1c000d154df2f9e868a85df1897b8a7918471dd6d468a4527b092ae2d069bbd686487b0b05ed4d61abfffaa7eb6584f5ee03b320469386e2b64c89cf +RMD160 (NetBSD-6.0/mac68k/installation/misc/src/Installer_1.1g.src.sea.hqx) = d29a9600c614d00c7af518b2f75f1d1ebebf4b6d +MD5 (NetBSD-6.0/mac68k/installation/misc/src/Installer_1.1g.src.sea.hqx) = 5d00aedc5729c2e2ffcea77e666a4adc +SHA1 (NetBSD-6.0/mac68k/installation/misc/src/Booter2.0.0-src.sea) = 5a4598fcbd39bfed29d58f9d712ed8d3408ae5c1 +SHA512 (NetBSD-6.0/mac68k/installation/misc/src/Booter2.0.0-src.sea) = 4828cb2efb9b40753be27ecd1cbe235e3842b9b2b024070eb6135f10716dfae1ab7cd6d45db862c64eb5b2267b40c6660af53986d3b5fcfab03600a75c0b08f3 +RMD160 (NetBSD-6.0/mac68k/installation/misc/src/Booter2.0.0-src.sea) = 9f284e11ef74ef0202d4a46ffcdafce282f3104f +MD5 (NetBSD-6.0/mac68k/installation/misc/src/Booter2.0.0-src.sea) = d9185a15e8dbcefdc26e8dceea7eaa51 +SHA1 (NetBSD-6.0/mac68k/installation/misc/src/Installer_1.1h.src.sea.hqx) = 3a4d1868a5f6c6e010dd6e3d0ff7ddb63a034c9e +SHA512 (NetBSD-6.0/mac68k/installation/misc/src/Installer_1.1h.src.sea.hqx) = cafa4aadc01ce3c515945359d67df14aefb9cf36cafab93d113cc5079e0cdc06360310173febca13cf7bc8fe66eb9161f6afed97a0810ddf025bca38d327e444 +RMD160 (NetBSD-6.0/mac68k/installation/misc/src/Installer_1.1h.src.sea.hqx) = 90b7070035d00fe09ac95962c4d47e1ba2f565e2 +MD5 (NetBSD-6.0/mac68k/installation/misc/src/Installer_1.1h.src.sea.hqx) = 9f792b26b1a5691f13193a7e08cf6d18 +SHA1 (NetBSD-6.0/mac68k/installation/misc/src/Mkfs_1.47src.sea.hqx) = 76823266114b2ff531d35c646eef705677085907 +SHA512 (NetBSD-6.0/mac68k/installation/misc/src/Mkfs_1.47src.sea.hqx) = ceb5f5665acc0a9c8f273bf659e17a55dec3ffde647deb90cfa9001e43a82d5e1b4e8001175559b2f1d6327f2a80f86bfbf2798f27bbe6bbe52547a92de11d57 +RMD160 (NetBSD-6.0/mac68k/installation/misc/src/Mkfs_1.47src.sea.hqx) = af8327f6e2d66bbd8a04498d27ab3f5668556cce +MD5 (NetBSD-6.0/mac68k/installation/misc/src/Mkfs_1.47src.sea.hqx) = 61facd7fdeb336f108d78feb8327555b +SHA1 (NetBSD-6.0/mac68k/installation/misc/BSD_Mac68k_Booter.bin.uue) = 432b619e0eb127a5fd70fd3dc8f2988a93211a34 +SHA512 (NetBSD-6.0/mac68k/installation/misc/BSD_Mac68k_Booter.bin.uue) = ab3650cca71dc57f38f480bfa74f6bdffe2d0ccbf76072658503cd168b91f90a7fe5ba0ef4f51aa497a11684ee05d73376e059957c75773d92f894877042c0ab +RMD160 (NetBSD-6.0/mac68k/installation/misc/BSD_Mac68k_Booter.bin.uue) = 61bdb1fc795bfe9242816682fc98cfdee036e0ef +MD5 (NetBSD-6.0/mac68k/installation/misc/BSD_Mac68k_Booter.bin.uue) = aed2003c59f8e824dc30c44366439426 +SHA1 (NetBSD-6.0/mac68k/installation/misc/BSD_Mac68k_Booter.bin) = 8e940cccdfe4e645ddd01738477f7f58342788e0 +SHA512 (NetBSD-6.0/mac68k/installation/misc/BSD_Mac68k_Booter.bin) = 0d3e0d39aa811921b012a6fd07dbf97b63f61dd14800c61d2941f3c624db88cd0805478df900120cd20c3fcf6af11c5989c52400e5b4eefabd4bf5c62f9f2023 +RMD160 (NetBSD-6.0/mac68k/installation/misc/BSD_Mac68k_Booter.bin) = 49146172c77c05a522bdf118e879f0bd933bc99c +MD5 (NetBSD-6.0/mac68k/installation/misc/BSD_Mac68k_Booter.bin) = 757b6ca3559185feafc36927ce9ab578 +SHA1 (NetBSD-6.0/mac68k/installation/misc/res-edit-and-others.hqx) = fe505f1ff77f1574ddec17dd4de93f0370fe236b +SHA512 (NetBSD-6.0/mac68k/installation/misc/res-edit-and-others.hqx) = cf382e50ea9a8fd8c30c8bddfadf44b64b94216656dc623039a37c88bc642080b54002b9aca1cad25c251c719cda9fb3ad89bbf3ed645672c0040baf459e0ae9 +RMD160 (NetBSD-6.0/mac68k/installation/misc/res-edit-and-others.hqx) = 19be7f536eee28b7e30cffc4ef3e8a2f8c7fe88f +MD5 (NetBSD-6.0/mac68k/installation/misc/res-edit-and-others.hqx) = 707c4953e155315abe519d5d48c54318 +SHA1 (NetBSD-6.0/mac68k/installation/misc/Booter-HTML-manual-12.tar) = 94e2f09daeb119ece95abfe24b103f85f9c5d558 +SHA512 (NetBSD-6.0/mac68k/installation/misc/Booter-HTML-manual-12.tar) = 3d9a743e71ee985134ab679608ffc31b197a638e302450c888f90d02fefae72b647622024b3ebb4263e57b6e58ce457890d6a0774c62a8e4a9f90d235d04c15a +RMD160 (NetBSD-6.0/mac68k/installation/misc/Booter-HTML-manual-12.tar) = ee32b1b55b0495b9b4723ff3cbc42123f5b360a2 +MD5 (NetBSD-6.0/mac68k/installation/misc/Booter-HTML-manual-12.tar) = 24120554ffbac39c8edd8e939706b7c5 +SHA1 (NetBSD-6.0/mac68k/installation/misc/Booter2.0.0.sea) = d5178c25cc71514816986842e39c716e6cd5ab4c +SHA512 (NetBSD-6.0/mac68k/installation/misc/Booter2.0.0.sea) = fafbf6f153e9b9bf657aac3c74d569b44ff21c1e306f0cbc4a2fcab5fbe439bd46746ff0469113bc715b69990507994ae94934d8caf82321684326f4e8b4d146 +RMD160 (NetBSD-6.0/mac68k/installation/misc/Booter2.0.0.sea) = 97798bf61397243efee8480c7f2f19e63fda7d00 +MD5 (NetBSD-6.0/mac68k/installation/misc/Booter2.0.0.sea) = 05b46210443c60ee28bcbe81f1ebc004 +SHA1 (NetBSD-6.0/mac68k/installation/misc/BooterManual.stxt.bin) = 2859ea6089df13333b6b521d8bc858079083251c +SHA512 (NetBSD-6.0/mac68k/installation/misc/BooterManual.stxt.bin) = 1891f4c07bfb51de08fea8e3a5cd572e99897d20f6df748ae72af8da5e8191ca07d5f0dc836b39be12236286926677896e4a456a8f64b31517d09285bebed460 +RMD160 (NetBSD-6.0/mac68k/installation/misc/BooterManual.stxt.bin) = 37fe1a762925b8bb8ae71177bea992aad27ee03f +MD5 (NetBSD-6.0/mac68k/installation/misc/BooterManual.stxt.bin) = fcc43fd81d5691559a5aa8ae15be8899 +SHA1 (NetBSD-6.0/mac68k/installation/misc/BooterManual.stxt.bin.uue) = beb0225c706b12fc8a241025c483133c1d5e6b86 +SHA512 (NetBSD-6.0/mac68k/installation/misc/BooterManual.stxt.bin.uue) = 7e98b555d7cf30da5948b115595f06a725c55cc0ef3e7a705423c600cafceca2e04966c65573805e6e553cf9f7a2faa05803ff2d6cd9deb714f4e98924e2a5d7 +RMD160 (NetBSD-6.0/mac68k/installation/misc/BooterManual.stxt.bin.uue) = ed9a5860dafd3484d380f1f3a91cec366b59be9d +MD5 (NetBSD-6.0/mac68k/installation/misc/BooterManual.stxt.bin.uue) = cacb436bfbfc9a4b0995c789fee8342f +SHA1 (NetBSD-6.0/mac68k/installation/misc/Installer.sea.hqx) = c6a6c25ae1fcdfe4a0ba90616c3779068280b759 +SHA512 (NetBSD-6.0/mac68k/installation/misc/Installer.sea.hqx) = 5ff75859fd5eb2fdcf75215ec6c045518ef111d0e8caecbe951dbf6f9f1129cac6948ab991949cbb3ee68d05ee8f398b07206acc9af53a5db1c4c6c7148a3a2a +RMD160 (NetBSD-6.0/mac68k/installation/misc/Installer.sea.hqx) = 36b141ff6722fd5e76fe293d1247587ae0efdd8a +MD5 (NetBSD-6.0/mac68k/installation/misc/Installer.sea.hqx) = 01bc744d539b4f2f8e4fb2761d4c77e7 +SHA1 (NetBSD-6.0/mac68k/installation/misc/Installer_1.1g.sea.bin) = 8ef8265fa77478a6741bc65ceb6f64e790c7aac2 +SHA512 (NetBSD-6.0/mac68k/installation/misc/Installer_1.1g.sea.bin) = 45324e1231e7d53816640b8867eb117294373e90463297f05e6d187b1fe719b82bc1782b24dff8ad6a71e0383eddd0f47bd15d604f6cf3bb2bf3499df887eb48 +RMD160 (NetBSD-6.0/mac68k/installation/misc/Installer_1.1g.sea.bin) = 506451703e3f00ac0a26b450d33463fd2c1e4582 +MD5 (NetBSD-6.0/mac68k/installation/misc/Installer_1.1g.sea.bin) = ea338e4327628024d670ae9eb64323db +SHA1 (NetBSD-6.0/mac68k/installation/misc/Installer_1.1g.sea.hqx) = 8e28517a94b1b0b57a504938077aa740de7e3b80 +SHA512 (NetBSD-6.0/mac68k/installation/misc/Installer_1.1g.sea.hqx) = 6e07c3682a0bbb4f7d23c235f83f3d22d4a8813cade67ab9f76092c68f41767c00eccde01600283df36e4d222bddd2b7fec355db468d07d7db8dbf51adc9f5bb +RMD160 (NetBSD-6.0/mac68k/installation/misc/Installer_1.1g.sea.hqx) = 4159e0226c6f58b480bd0cdc42f9d2d411521034 +MD5 (NetBSD-6.0/mac68k/installation/misc/Installer_1.1g.sea.hqx) = 2c214a1b2429702942436e92e2a408c3 +SHA1 (NetBSD-6.0/mac68k/installation/misc/Installer_1.1h.sea.bin) = 0bda2b9e6a95f1b10414823f048087ad6455e6ed +SHA512 (NetBSD-6.0/mac68k/installation/misc/Installer_1.1h.sea.bin) = bb9ad3f95609c3f23d31a876055f2cae692d8abb853431d0945ee7e66e292fe7069dda82f5ee615ac5fe5893e0699323632de8d4c1c668d987a8172597d78386 +RMD160 (NetBSD-6.0/mac68k/installation/misc/Installer_1.1h.sea.bin) = bc7f88652ae4d51954c967dde99dc6c11494a7c8 +MD5 (NetBSD-6.0/mac68k/installation/misc/Installer_1.1h.sea.bin) = 763ff66b2234fd52ffe4ad08de5f090f +SHA1 (NetBSD-6.0/mac68k/installation/misc/Installer_1.1h.sea.hqx) = c6a6c25ae1fcdfe4a0ba90616c3779068280b759 +SHA512 (NetBSD-6.0/mac68k/installation/misc/Installer_1.1h.sea.hqx) = 5ff75859fd5eb2fdcf75215ec6c045518ef111d0e8caecbe951dbf6f9f1129cac6948ab991949cbb3ee68d05ee8f398b07206acc9af53a5db1c4c6c7148a3a2a +RMD160 (NetBSD-6.0/mac68k/installation/misc/Installer_1.1h.sea.hqx) = 36b141ff6722fd5e76fe293d1247587ae0efdd8a +MD5 (NetBSD-6.0/mac68k/installation/misc/Installer_1.1h.sea.hqx) = 01bc744d539b4f2f8e4fb2761d4c77e7 +SHA1 (NetBSD-6.0/mac68k/installation/misc/Mkfs_1.47.sea.bin) = 9783f80336af95dfbf854278f58b577891a6442e +SHA512 (NetBSD-6.0/mac68k/installation/misc/Mkfs_1.47.sea.bin) = fb3d537f73cd7a5c05b4deeacfebe4805de1172071b97af545ef0c360c8093dd34007cdb498dad1b8fba4930e939c35429b314c575ab1e6d57fc208d72bee767 +RMD160 (NetBSD-6.0/mac68k/installation/misc/Mkfs_1.47.sea.bin) = eb92d84b516d3c84a2c54fa501a1f585434639cb +MD5 (NetBSD-6.0/mac68k/installation/misc/Mkfs_1.47.sea.bin) = 0b6f626c1d8f578e01818cfc2a2e79b5 +SHA1 (NetBSD-6.0/mac68k/installation/misc/Mkfs.sea.hqx) = e2286a389c29eebadaad19c9c3f3c9095b8bcb3d +SHA512 (NetBSD-6.0/mac68k/installation/misc/Mkfs.sea.hqx) = 5021b88d12bdc6545c681a3df24750375d63cac19b9e0f6a7148cb8592de6d0cc22f254b9755a96e1780541acbbdf54f0f6f9b62ff7cdab8dc94db0d247b2b87 +RMD160 (NetBSD-6.0/mac68k/installation/misc/Mkfs.sea.hqx) = 14c18aceaab0593ca0f41bcce95499db3fc4f8f7 +MD5 (NetBSD-6.0/mac68k/installation/misc/Mkfs.sea.hqx) = a20825a32ee72f356880169993c3ac73 +SHA1 (NetBSD-6.0/mac68k/installation/misc/README) = 6f10f67afd988de6fa0a66f78ec46da15cc994f3 +SHA512 (NetBSD-6.0/mac68k/installation/misc/README) = e8f6d9c3217e7ad084ebc6758a07f14a664db9a34feb2b4dfb19fce8692ca1703f2b119eabcb13cb38f629a9588dea3279bfcf0cda65260acd585514d129701d +RMD160 (NetBSD-6.0/mac68k/installation/misc/README) = 9d125cfe0be05fb26b9b5f52690b9280e282af44 +MD5 (NetBSD-6.0/mac68k/installation/misc/README) = 6081e0a4521b8f229bd3c09e094d4bc0 +SHA1 (NetBSD-6.0/mac68k/installation/misc/Mkfs_1.47.sea.hqx) = e2286a389c29eebadaad19c9c3f3c9095b8bcb3d +SHA512 (NetBSD-6.0/mac68k/installation/misc/Mkfs_1.47.sea.hqx) = 5021b88d12bdc6545c681a3df24750375d63cac19b9e0f6a7148cb8592de6d0cc22f254b9755a96e1780541acbbdf54f0f6f9b62ff7cdab8dc94db0d247b2b87 +RMD160 (NetBSD-6.0/mac68k/installation/misc/Mkfs_1.47.sea.hqx) = 14c18aceaab0593ca0f41bcce95499db3fc4f8f7 +MD5 (NetBSD-6.0/mac68k/installation/misc/Mkfs_1.47.sea.hqx) = a20825a32ee72f356880169993c3ac73 +SHA1 (NetBSD-6.0/mac68k/installation/misc/NetBSD_ROM.sit.hqx) = 009c5f376751cda897cdd5707932a42ed8c4c75f +SHA512 (NetBSD-6.0/mac68k/installation/misc/NetBSD_ROM.sit.hqx) = a04d6873fe2e0d3b543a05d1c12893f2715479e5bbfeeb9657babd146610197e4eec045a428d51bce4a9f8fb90f23f81b31b35f672692de953d6df8379a7531c +RMD160 (NetBSD-6.0/mac68k/installation/misc/NetBSD_ROM.sit.hqx) = 6dcd7e0f25e19d77d38b18c22af77ef0c80769e6 +MD5 (NetBSD-6.0/mac68k/installation/misc/NetBSD_ROM.sit.hqx) = 6d9984dacf90adcd3f5f4a906b72b436 +SHA1 (NetBSD-6.0/mac68k/installation/misc/README.Booter) = cb2fb0233a1f5444c5c1b9648a6c167a4ce09437 +SHA512 (NetBSD-6.0/mac68k/installation/misc/README.Booter) = b233f9b5f8e6b615ecbb117d1853c64a82b1ac78958a7d394133e6e5f777ca6075b1e65d74ce52d1bc9cc97257584cbc4c70a11b0865ef095e6376d2c4e46bf4 +RMD160 (NetBSD-6.0/mac68k/installation/misc/README.Booter) = 2bd403db763c410b968f85cb8da32d10a7520b59 +MD5 (NetBSD-6.0/mac68k/installation/misc/README.Booter) = ae0f90a35340fc51be774ebd33674a41 +SHA1 (NetBSD-6.0/mac68k/installation/misc/README.Installer) = e8e4011a516b40ea99e9f1b16708fc91878f88fb +SHA512 (NetBSD-6.0/mac68k/installation/misc/README.Installer) = 791e8a5415bdfd0ac0412e964d0ed1dac9dbebfbe9d546fbd92d3aa3d9b82eececba55628ac6cbbd7dd843f62183d718e2a1ad98c10311fb76c24dd40c77af06 +RMD160 (NetBSD-6.0/mac68k/installation/misc/README.Installer) = fc1b834d11c4df6677ee4a40b1e3ba2015d5ad00 +MD5 (NetBSD-6.0/mac68k/installation/misc/README.Installer) = bd6be3091a274d7c68da789ad1db0eda +SHA1 (NetBSD-6.0/mac68k/installation/misc/extensions.map) = 4a5fa646db0c73433f3538e17e7d18b38679284f +SHA512 (NetBSD-6.0/mac68k/installation/misc/extensions.map) = 32db0ebf9c0e80e4856c963ef21d3626060e20ba33cd61301e4114b77a636cf248e705700444b42a4631d1c56ef09294981158e1f0b0527b795501b9cea1b8f6 +RMD160 (NetBSD-6.0/mac68k/installation/misc/extensions.map) = f6811f3b103ab5c902a204dce2578e8cba6e8e9a +MD5 (NetBSD-6.0/mac68k/installation/misc/extensions.map) = 5007a814ca2442a9693969cb997b4905 +SHA1 (NetBSD-6.0/mac68k/installation/misc/mode32-7.5.bin) = 6eb3cb3b988e6295f7222016d241f53c61cf347e +SHA512 (NetBSD-6.0/mac68k/installation/misc/mode32-7.5.bin) = 16f05d2792e03d3a9c9ccd9d435ca5556224bd73619d89b9d2f6ac3b282f6587b76745bbbc9383c20f11c2125b60dff138845dac4a269e459a5b76ee1d5e865c +RMD160 (NetBSD-6.0/mac68k/installation/misc/mode32-7.5.bin) = be8fc56378e697fc1f6fe9da5e8e69c787dbc434 +MD5 (NetBSD-6.0/mac68k/installation/misc/mode32-7.5.bin) = 33ff34f5db2f0ba88c83ce85b1e51664 +SHA1 (NetBSD-6.0/mac68k/installation/misc/mode32-7.5.hqx) = f588fece9bb911749d1038da2ec31e5ea50b2b21 +SHA512 (NetBSD-6.0/mac68k/installation/misc/mode32-7.5.hqx) = 1d4a1b489419171022e120d7292f479ea0d47833b2868bccc47ea1d97c442ff1e18044f43783fbd920145a6e6aad094be796dc8db00d5d997235c8f9d8ecb7ab +RMD160 (NetBSD-6.0/mac68k/installation/misc/mode32-7.5.hqx) = 6e0bd805b5595d6d8ee3a24a63290978bd8da8cc +MD5 (NetBSD-6.0/mac68k/installation/misc/mode32-7.5.hqx) = cf14fb32d042ba270b527ec8b11f6d3e +SHA1 (NetBSD-6.0/mac68k/installation/misc/pdisk.sea.hqx) = ac3641da27c3615456310ff795b2d684eb2661ef +SHA512 (NetBSD-6.0/mac68k/installation/misc/pdisk.sea.hqx) = a5404597c2479adf6ad9a910771f8d9cff57dbc4066d73346bfde3f1380a59641855820658ff3a6c8c0fd97b242dcfd4c30e7ecde50047bbbc7a7d45e9d77e4e +RMD160 (NetBSD-6.0/mac68k/installation/misc/pdisk.sea.hqx) = a5368be868266f37bdf3459067659ef0c4186dc6 +MD5 (NetBSD-6.0/mac68k/installation/misc/pdisk.sea.hqx) = 71be22598a33042751caa6dc6c0af834 +SHA1 (NetBSD-6.0/mac68k/INSTALL.html) = 85efa4b8402dccb52805752ff82e87eb1259e5cd +SHA512 (NetBSD-6.0/mac68k/INSTALL.html) = dd8012db2cb801b02b808eadd473f529b58977b9d2088c878aeb7deafc214adb2e281aa3b2094e0988f23e1ede88a1528492634211f86fe73d4b6085a1a917fe +RMD160 (NetBSD-6.0/mac68k/INSTALL.html) = 01614436a73df3cae2149a607abb6c59671dcb63 +MD5 (NetBSD-6.0/mac68k/INSTALL.html) = deaafd9baf0d73ad2fe1e731ca8d4391 +SHA1 (NetBSD-6.0/mac68k/INSTALL.more) = 02b0da5241dfb0e94347c45aa2b59230a4c4beaa +SHA512 (NetBSD-6.0/mac68k/INSTALL.more) = e167052f3a76308dda76a45e7fe93622a3e40fb7905d2bfc3e6438007d5bee8cafa06f9bddf4fabd9801d82bc3de56fbec1892a4977d2b818ece0ee570bc7729 +RMD160 (NetBSD-6.0/mac68k/INSTALL.more) = 1602b574a726ead87163bea4a121dc4d5573c321 +MD5 (NetBSD-6.0/mac68k/INSTALL.more) = ab7ed66c5f64540dc7b9d036048fcfb1 +SHA1 (NetBSD-6.0/mac68k/INSTALL.ps) = 999ea4a94acf0cf256157ba3b447d866b0347bfa +SHA512 (NetBSD-6.0/mac68k/INSTALL.ps) = dfaf48953a73ed32b722bc95d34a58866ea8ccbf0d9d79e1fd9769634920426826a1e5cc86b94cc2eaf39eb3365bd5977ae0ee4284af484f64bb3e92847567ce +RMD160 (NetBSD-6.0/mac68k/INSTALL.ps) = 73548f30c2c139ae5e62e98dbc54a4a80d1398c5 +MD5 (NetBSD-6.0/mac68k/INSTALL.ps) = 43662b6328dcc148ea4b6121de934e7b +SHA1 (NetBSD-6.0/mac68k/INSTALL.txt) = d198c59c8fb2bcb408013794ef3d8cadcb4ad448 +SHA512 (NetBSD-6.0/mac68k/INSTALL.txt) = efb0679da4c0f9b6b8f15f92579ecabb67a4e7451e156430f9a748368bf8815d563d83050c24784c80985d06d0c257d66f91a03c792ad9b65da17e408d2e732b +RMD160 (NetBSD-6.0/mac68k/INSTALL.txt) = 3ea97712841cab74a13994769fbe4ff66705b6c0 +MD5 (NetBSD-6.0/mac68k/INSTALL.txt) = ed4f38a04160feaf88388c0970e6ed6e +SHA1 (NetBSD-6.0/macppc/binary/kernel/netbsd-GENERIC_MD.symbols.gz) = ce9bd080acdc497dd570c416befca032a1e8d823 +SHA512 (NetBSD-6.0/macppc/binary/kernel/netbsd-GENERIC_MD.symbols.gz) = 39b5933f7f43c990c2478041d398e9764dce24bfbae9baba2f603fe574448370d9d5cef5e398613fa047648cc0120dc7e878f527bc12751c6a37fe8966cb9d2b +RMD160 (NetBSD-6.0/macppc/binary/kernel/netbsd-GENERIC_MD.symbols.gz) = d23e372373d18f19b55bc87635bc45f3f730a91d +MD5 (NetBSD-6.0/macppc/binary/kernel/netbsd-GENERIC_MD.symbols.gz) = c0e545e698824468f2b0acefaf788bea +SHA1 (NetBSD-6.0/macppc/binary/kernel/netbsd-GENERIC.MP.gz) = 0a065a75b49d53c192d1a79e9d216a2d9382d570 +SHA512 (NetBSD-6.0/macppc/binary/kernel/netbsd-GENERIC.MP.gz) = dc2a00bcdf70c08d7089b775b3328f1b828c5a5962ec077d95c8ea279586c6b65c48bcde34b9432c4f7a0a7cb4dc6e8f4887ae254038919de8b4f2d2a3d2e3c3 +RMD160 (NetBSD-6.0/macppc/binary/kernel/netbsd-GENERIC.MP.gz) = 39e88535fff406327f536ecd319c2b5785898fbf +MD5 (NetBSD-6.0/macppc/binary/kernel/netbsd-GENERIC.MP.gz) = 3410df9cc4df7b28a292ed3d150808ea +SHA1 (NetBSD-6.0/macppc/binary/kernel/netbsd-GENERIC.gz) = 597f394bd55facd236e90f6aa213a5eef4711f7c +SHA512 (NetBSD-6.0/macppc/binary/kernel/netbsd-GENERIC.gz) = f7cbec6767fd9ce1aa61065ebc360d4aa1d2fcb26c4457f38c409fb5465753b726c8fb37ab0448863efd69c21a8216dea27e8067cd1fa1f74299677985195181 +RMD160 (NetBSD-6.0/macppc/binary/kernel/netbsd-GENERIC.gz) = 21e5329fc0c500af9e333fabef527385021bde0a +MD5 (NetBSD-6.0/macppc/binary/kernel/netbsd-GENERIC.gz) = 7da219cc304f59d1662eaf7f4dc1833f +SHA1 (NetBSD-6.0/macppc/binary/kernel/netbsd-GENERIC_MD.gz) = e594f013594f13f586f6789005e49f13b9f3467f +SHA512 (NetBSD-6.0/macppc/binary/kernel/netbsd-GENERIC_MD.gz) = bc68d5a6cf29cdc0c9ee8b9ca7610703025621f64a9b427f04b87cf53bf9e14e765785283a0a66aed1a15dd0abbe81e8fc2029c3310b715ef75cacc7eec93283 +RMD160 (NetBSD-6.0/macppc/binary/kernel/netbsd-GENERIC_MD.gz) = 7ce6740e080b6f9b5dc8d99c70c779b0486ad916 +MD5 (NetBSD-6.0/macppc/binary/kernel/netbsd-GENERIC_MD.gz) = 3f6f6c37b2c6f7b04c9595245c7224c4 +SHA1 (NetBSD-6.0/macppc/binary/kernel/netbsd-INSTALL.symbols.gz) = de3656de1e94d49bb43e6f0b21fc21ee15f2170a +SHA512 (NetBSD-6.0/macppc/binary/kernel/netbsd-INSTALL.symbols.gz) = c90cb34afa99a7ceb8ba3742a0a4b7bd59da93ecb4aca1ff1a540d18d540947446467627e3df717bb880f1b0a567336316bc8a2d59026a7a8f6935eca93984ff +RMD160 (NetBSD-6.0/macppc/binary/kernel/netbsd-INSTALL.symbols.gz) = b617db2dfd9b44f855f06b777f4c69680115ed27 +MD5 (NetBSD-6.0/macppc/binary/kernel/netbsd-INSTALL.symbols.gz) = c90b9ecfb302f54de790366b2e17b625 +SHA1 (NetBSD-6.0/macppc/binary/kernel/netbsd-INSTALL.gz) = 661d08043304e74da8232e5d14d1f4f748762510 +SHA512 (NetBSD-6.0/macppc/binary/kernel/netbsd-INSTALL.gz) = e4dec9781eea446f078df552033c52e4b8df30231ecbc14131ece1f7312c8a0f98d47b06d9b66988c5c4c2ff45e8dd57e7f2715e165c431b391127f0e5c03565 +RMD160 (NetBSD-6.0/macppc/binary/kernel/netbsd-INSTALL.gz) = 99e3fd9681bd7f400de2e2206163d501b6d23d41 +MD5 (NetBSD-6.0/macppc/binary/kernel/netbsd-INSTALL.gz) = 1f1b3e39dcde937788a32ef3a4f65c1b +SHA1 (NetBSD-6.0/macppc/binary/sets/games.tgz) = fbf69640b362df2446d7414ac3a13db100c289eb +SHA512 (NetBSD-6.0/macppc/binary/sets/games.tgz) = d86b41d79aea4204ccf45306937a5ec45629e37873a5956c0280fd1d54cf4a808542d097f9d978fd3277791554ce8a6fb4d0ccd46e30210549d5cce1145bb499 +RMD160 (NetBSD-6.0/macppc/binary/sets/games.tgz) = fd2aed1eb51f4db522fb5163e8fde4c040b55d30 +MD5 (NetBSD-6.0/macppc/binary/sets/games.tgz) = 997ae5fb42196a787df89873be321e47 +SHA1 (NetBSD-6.0/macppc/binary/sets/man.tgz) = 899b9d8242e983a5110ab755651c24f709b5af67 +SHA512 (NetBSD-6.0/macppc/binary/sets/man.tgz) = 410999db110d710f4bb498c3d7ae7adc62170c7c2f470ce189c92f6c436c5ea96149659c631ef0b5605caaa025d97dfe1c07c428d86f51239657bd6b71717b15 +RMD160 (NetBSD-6.0/macppc/binary/sets/man.tgz) = c1270f68c6d41b351877f71f0396ac34877dfc8d +MD5 (NetBSD-6.0/macppc/binary/sets/man.tgz) = df4db2bbfa39ef6a4a215d949653d04a +SHA1 (NetBSD-6.0/macppc/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/macppc/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/macppc/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/macppc/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/macppc/binary/sets/kern-GENERIC.MP.tgz) = e11a4e1da81be3a4650be198c5f9fe7204991540 +SHA512 (NetBSD-6.0/macppc/binary/sets/kern-GENERIC.MP.tgz) = 924fc04dff6c7458196d0a19ec38a9a1114ef3cf5cd557aa68563c3d1d2dee67d9daf3ec72fec95c9bad8862ceb663c1f96cad61965e65c042c2723ffacfe43e +RMD160 (NetBSD-6.0/macppc/binary/sets/kern-GENERIC.MP.tgz) = 585796f103490e30928aca2c4977a41acb990c84 +MD5 (NetBSD-6.0/macppc/binary/sets/kern-GENERIC.MP.tgz) = 5b9f58a612ad00b10d4812ce9e325204 +SHA1 (NetBSD-6.0/macppc/binary/sets/base.tgz) = a31efb13ffcb70f4f429ad018d0ca6f9bc9e1db5 +SHA512 (NetBSD-6.0/macppc/binary/sets/base.tgz) = 9746428cdb65b283fa668f63cd33cc2c0bff75e85f4357f460da4d7c0c874bbc0369170d813fa70a1f0933fc2240da6536fa1c2c2be59c6722ab3849d92a3dc0 +RMD160 (NetBSD-6.0/macppc/binary/sets/base.tgz) = c83a80159c7128c8d311c62c15776776dae0fd97 +MD5 (NetBSD-6.0/macppc/binary/sets/base.tgz) = 13ea19ca37828efa708cc77efe1a18f4 +SHA1 (NetBSD-6.0/macppc/binary/sets/comp.tgz) = 2608b27059b55a9d53c2e4fb0f6f3417aafa8293 +SHA512 (NetBSD-6.0/macppc/binary/sets/comp.tgz) = 2f6ec81a049c6c4688fc362a341d11c100ce057760eb5832fceb039ce810abde76d035a3f8e9a23fbb0f4ec3709a8729eba0e92c0f56aed9aed0779588b44bc0 +RMD160 (NetBSD-6.0/macppc/binary/sets/comp.tgz) = 566f37564d448641e6bdcbd70e87c7b9406ee78e +MD5 (NetBSD-6.0/macppc/binary/sets/comp.tgz) = 0ab55dfc92d16a84368d2f1118b6385d +SHA1 (NetBSD-6.0/macppc/binary/sets/etc.tgz) = 42a97230bebad52fff9236fe06f3ac0aab27f929 +SHA512 (NetBSD-6.0/macppc/binary/sets/etc.tgz) = b574a57a33d58eebac3a048823fa845d4a403e0503b21340c9cfb05ae9a743a213aa7222530c9e20d30fd90003b56366815ebcb28d085c2d9c998a73972ce602 +RMD160 (NetBSD-6.0/macppc/binary/sets/etc.tgz) = dfbd6641e45fed5e9fa425be5c8878462ff8c6fe +MD5 (NetBSD-6.0/macppc/binary/sets/etc.tgz) = aa3881b4329b45b318e6d6f0d97ac24a +SHA1 (NetBSD-6.0/macppc/binary/sets/kern-GENERIC.tgz) = 77f4b674c6ef5bf00c6d6173d2498ff7ebbc64f9 +SHA512 (NetBSD-6.0/macppc/binary/sets/kern-GENERIC.tgz) = f16e4dcf74059eafc235bbe7d7b59de1071b56ade3f77308bbb646fdd19e90362635125bff5f81ca92e51502c668106067ca6b377a8aec2bff708e589380977a +RMD160 (NetBSD-6.0/macppc/binary/sets/kern-GENERIC.tgz) = 0906acf7e10f69ea769a5a58d0ffe2d1e060ba98 +MD5 (NetBSD-6.0/macppc/binary/sets/kern-GENERIC.tgz) = 50cf40ab93c7505da5fe7c9bd488abd2 +SHA1 (NetBSD-6.0/macppc/binary/sets/modules.tgz) = b2c51fb3ca33a8f70c00f9e7d49cd4b91fb79673 +SHA512 (NetBSD-6.0/macppc/binary/sets/modules.tgz) = 2cfd8f4f53c0561b8ab8aafac2c38363750be6484c21c8d670b7afb89390875893a9b549b2e28d08cdeeb81217f7e0e0fe437e09059871d4b063ffa0057bae97 +RMD160 (NetBSD-6.0/macppc/binary/sets/modules.tgz) = 9fb4d8eb95a719022a522b3e9a970cda1a416f15 +MD5 (NetBSD-6.0/macppc/binary/sets/modules.tgz) = 54914b3291b652b921239631c740dcea +SHA1 (NetBSD-6.0/macppc/binary/sets/tests.tgz) = f87666428063cf6b980c1d284aab5894e2c3d2b3 +SHA512 (NetBSD-6.0/macppc/binary/sets/tests.tgz) = 94474f3ed0feff6b8c10299c4e190154bf4c6d579dd3edced5de901aec60c9413a921b282bc7ae0c2dd3ec49de8162204660a7fe80393102aa7ebd3318f4124e +RMD160 (NetBSD-6.0/macppc/binary/sets/tests.tgz) = 7467da9599fb2cb270854e337b696568de24b205 +MD5 (NetBSD-6.0/macppc/binary/sets/tests.tgz) = 165d0d19f6c40d8249ddd46214a68e25 +SHA1 (NetBSD-6.0/macppc/binary/sets/text.tgz) = b3e0e6f977a3598fb6f8a377cf91a67aa21ff74f +SHA512 (NetBSD-6.0/macppc/binary/sets/text.tgz) = 361c67a072fbfe6055fcf8436f3a84b10d92a0cc987c818a32a9f536466b285d47ef2ba39c8f04319ac0a93e7b2353eed589e6b72c3bd32f38c12aae82ff26ed +RMD160 (NetBSD-6.0/macppc/binary/sets/text.tgz) = 3d0c5c4e3a84335431a0d6cc9b78315495e137d0 +MD5 (NetBSD-6.0/macppc/binary/sets/text.tgz) = d968d8f10bd69add51020decb7cd01bf +SHA1 (NetBSD-6.0/macppc/binary/sets/xbase.tgz) = 63043b541de378d777f43d0a333d2112a98a4e8a +SHA512 (NetBSD-6.0/macppc/binary/sets/xbase.tgz) = 189d8b05121b356d4fa587c46cd4bb50df1ff89a197c983dafed9ce93293ad16e82f77d14ae3ea2c8e9f01f8a5eab4d9841274d9caa7143f4d977d921d3e1a84 +RMD160 (NetBSD-6.0/macppc/binary/sets/xbase.tgz) = 3cccd55a4407632e7d7444a6919901aca686c9cb +MD5 (NetBSD-6.0/macppc/binary/sets/xbase.tgz) = 1e9175f276efb45934e2e976787ec61b +SHA1 (NetBSD-6.0/macppc/binary/sets/xcomp.tgz) = 9322a94973bf4e59542a1c3fe2d307f1dee362ff +SHA512 (NetBSD-6.0/macppc/binary/sets/xcomp.tgz) = ca37cdedb39625b92d2068c8736c2d1bdadd132edbffb4bf6ea3a4b1a21ffcd5bfdd78e5aaad874be32cff4d1b98059e142c5a2192dc1f38ffb7a64e8e180a17 +RMD160 (NetBSD-6.0/macppc/binary/sets/xcomp.tgz) = 48ef59c053d4a964872a70f1350252f98423794b +MD5 (NetBSD-6.0/macppc/binary/sets/xcomp.tgz) = fc0aa962b13c0e092657bfc3d6368284 +SHA1 (NetBSD-6.0/macppc/binary/sets/xetc.tgz) = 5ace04f9545e5ac27432bddcde0d42dd592540c1 +SHA512 (NetBSD-6.0/macppc/binary/sets/xetc.tgz) = ccdaeb27301167072fc0c98b78633c2d52b1eb4a5bf3ed5c606a646a420c7bd73e197b73d1a928c4aa17013fca5bbbd98f06fc4baa4ca97ada3a3e89490fdc06 +RMD160 (NetBSD-6.0/macppc/binary/sets/xetc.tgz) = 048fd168d184f88b2164c654594e68665dec62c4 +MD5 (NetBSD-6.0/macppc/binary/sets/xetc.tgz) = 1735140072351ccaa55f8b25cd002fd6 +SHA1 (NetBSD-6.0/macppc/binary/sets/xfont.tgz) = 2cea3fa057b220c72ba147f9821d33b18d8346d2 +SHA512 (NetBSD-6.0/macppc/binary/sets/xfont.tgz) = d76f6d6613f96475c85427792ad339576815f1423ae7e84018944d31cb66aa6ec14f2a8886f0912963745293326812a7efb8b1d2f08a6ee27da8fbf53c3223d7 +RMD160 (NetBSD-6.0/macppc/binary/sets/xfont.tgz) = 42190ebf50a1db179d8d7b1bdd1aa3e86082ac77 +MD5 (NetBSD-6.0/macppc/binary/sets/xfont.tgz) = 752888a1280d52af5e6b3c79287738e4 +SHA1 (NetBSD-6.0/macppc/binary/sets/xserver.tgz) = 4c9ca17aec65f27a569ee9e6ed4af95ad3b9cd21 +SHA512 (NetBSD-6.0/macppc/binary/sets/xserver.tgz) = 208d60880438a476ecacab3a4ab5872007c2728cafe16022cee9c0d781ce4dd8ef95d302ac9212a1a66b825869dc35c8df096d9f7c97a97054cf963ba58418fa +RMD160 (NetBSD-6.0/macppc/binary/sets/xserver.tgz) = f0bd1020d51ed7036593840c49bfaee57e09e58c +MD5 (NetBSD-6.0/macppc/binary/sets/xserver.tgz) = c241cf0caa30e6ae203fef4c95d2d74d +SHA1 (NetBSD-6.0/macppc/installation/floppy/boot1.fs) = 053808f21cbc6acc50469ffa2a6c48471bfbf8fe +SHA512 (NetBSD-6.0/macppc/installation/floppy/boot1.fs) = 82f844d8ee09d09a5cb06ad8cf8131826ad9e8c38a289e95757d6b9664b0aff4e30743ba750dd7ea780d556b4aa619388fbbef8727c52b302e314b08a6853306 +RMD160 (NetBSD-6.0/macppc/installation/floppy/boot1.fs) = 291a7e7bd8b98758f2dce412054abbb69c6cf4cb +MD5 (NetBSD-6.0/macppc/installation/floppy/boot1.fs) = 369cf1bf5a69c9220d3ab6213c0a10d1 +SHA1 (NetBSD-6.0/macppc/installation/floppy/boot2.fs) = 46098cec194fe5de4ffc1b66508397916cabd968 +SHA512 (NetBSD-6.0/macppc/installation/floppy/boot2.fs) = 25ed41f6712ae333101fb168cdafbdb4c4dc677e4a0c701665d02758202af2238a2a53828e833b0917ac0547ea34a1a1c95f8b9018084ff9053bbba985814b91 +RMD160 (NetBSD-6.0/macppc/installation/floppy/boot2.fs) = 9e743d123b1f43953743e347218ad29f022822be +MD5 (NetBSD-6.0/macppc/installation/floppy/boot2.fs) = 05843ccdeb93f326ddad69e810303fe5 +SHA1 (NetBSD-6.0/macppc/installation/ofwboot.elf) = a013bc2f2d4d39cf9e56b0d625b6c48d08bb455d +SHA512 (NetBSD-6.0/macppc/installation/ofwboot.elf) = d28569738cfad70b6d5aef80b32e9d44f38dc5038f38143bf93f78eba708ff05e9a7955c03a682833ace2cd20daf4adb1a3c36956768e5f2b08fb59a44573854 +RMD160 (NetBSD-6.0/macppc/installation/ofwboot.elf) = 9a9f54b00b80d91a934e83cb17a68b15a9fe8c00 +MD5 (NetBSD-6.0/macppc/installation/ofwboot.elf) = 2d4598a059853f8f7e99541afcf6e31e +SHA1 (NetBSD-6.0/macppc/installation/ofwboot.xcf) = a15eef375d155080b6809e2db46d0475baebd872 +SHA512 (NetBSD-6.0/macppc/installation/ofwboot.xcf) = 4756b6eeb05754185c16ff02e9d98642ae75c3545b385a67870e58b8211feda3ce265eaf020ca5252e9c47fab64922d9af8eead98b2cff798c58af9840fbd345 +RMD160 (NetBSD-6.0/macppc/installation/ofwboot.xcf) = 1654bc8a15f5d3c2bb248033cbfbc37ca23980a7 +MD5 (NetBSD-6.0/macppc/installation/ofwboot.xcf) = 84cc2385de486f3e72868ab7c75c8683 +SHA1 (NetBSD-6.0/macppc/INSTALL.html) = 9752ce3a0ae1964208f027404c5aa3b526efe08c +SHA512 (NetBSD-6.0/macppc/INSTALL.html) = 71dbe4d992bcea022b1aac0dbdc3cf596a7538bf3fd2de390925094bfaa5cb1f71e332a2eb419cdfa1528cb7951c92491b3b3d7b88cd9e4c40f81af0a8ea34b2 +RMD160 (NetBSD-6.0/macppc/INSTALL.html) = b5e2c12fbcf7fcf56e6e9354b178188c88e772b2 +MD5 (NetBSD-6.0/macppc/INSTALL.html) = 31c92f0b3c87409d1d74b17912f05333 +SHA1 (NetBSD-6.0/macppc/INSTALL.more) = 7b4f4aa288bbbacca5a7f69f7fb1dde30b6a67e4 +SHA512 (NetBSD-6.0/macppc/INSTALL.more) = 7ab24e82eb0b779f11e16b10982fb82d6831058b0a51b57c2abbb0c91f09daa92a7a724c18f775d551b6bc4b8bff36eb91b6a823d2f9810a478180c50f9c676e +RMD160 (NetBSD-6.0/macppc/INSTALL.more) = 7bc31a39cfc1017821c29032432a8765af7b240c +MD5 (NetBSD-6.0/macppc/INSTALL.more) = 0a198a6d31ac02b702c103117400eafb +SHA1 (NetBSD-6.0/macppc/INSTALL.ps) = 9a14912c8a58fc4e6d004dc2426c189b991d5e6a +SHA512 (NetBSD-6.0/macppc/INSTALL.ps) = 94ffb000d582ea09c0f3d4e0b6e757f0bbbe50e6793d33e3e3ec29a0da26a0130f23c778e19e681892ceab4f440dc01d37b206272d24aa96c9ef3a9a6c49ed0e +RMD160 (NetBSD-6.0/macppc/INSTALL.ps) = edde76230d345a53de93bb00af333be03971d0dc +MD5 (NetBSD-6.0/macppc/INSTALL.ps) = f275f19c885be2a1ca922cff1561b5c8 +SHA1 (NetBSD-6.0/macppc/INSTALL.txt) = e7e55b4231206d5fc087d6ad0c4b8ef52a73e385 +SHA512 (NetBSD-6.0/macppc/INSTALL.txt) = 51f4462c903b0948ca5634bf27a9988924cfc3a8249310f1c5f2fc3c8372e9ab916cf106fa7bd9153ccc44454a1fc298024214575f43bf938a7e8a8a18163038 +RMD160 (NetBSD-6.0/macppc/INSTALL.txt) = 8213d05b6c035c0932159f098633921ab6d79247 +MD5 (NetBSD-6.0/macppc/INSTALL.txt) = 319bfbce37725d2bbafa032c7891529a +SHA1 (NetBSD-6.0/mipsco/binary/kernel/netbsd-INSTALL.ecoff.gz) = c7357a28d27e6ba6fd9a1ca72b7f0d0d95c23089 +SHA512 (NetBSD-6.0/mipsco/binary/kernel/netbsd-INSTALL.ecoff.gz) = 3a0fbe1a79b886094cbb8a3613d3193d2731dbace050847c6d70ee8961b4d0e0dbf2f5d666e5f6c43e5ee2871ef9c59823b5fcadbf2dba16144f8c13e778c821 +RMD160 (NetBSD-6.0/mipsco/binary/kernel/netbsd-INSTALL.ecoff.gz) = 12b0c1cda3875379f2cd582b5eac8316d9fec2f4 +MD5 (NetBSD-6.0/mipsco/binary/kernel/netbsd-INSTALL.ecoff.gz) = c24f3d6e9a289d321c0ee250817cd348 +SHA1 (NetBSD-6.0/mipsco/binary/kernel/netbsd-GENERIC.gz) = 188a82d7aab86e27f7defbd0318c12deb06a5200 +SHA512 (NetBSD-6.0/mipsco/binary/kernel/netbsd-GENERIC.gz) = e6c278b3bc3e93137e2a0ccd894420671dc3d8f880b08aa673e51b758d88667fd416b317b90e1eaa72087a8b97322ce629f538f7daf2bc7746f0209d00e3d2f4 +RMD160 (NetBSD-6.0/mipsco/binary/kernel/netbsd-GENERIC.gz) = 19b32d196282fccad2907b3972d0bd8673b0b63b +MD5 (NetBSD-6.0/mipsco/binary/kernel/netbsd-GENERIC.gz) = d91b37f1b364bf92609c4cd56e738873 +SHA1 (NetBSD-6.0/mipsco/binary/kernel/netbsd-INSTALL.symbols.gz) = cfae9b61b6577966f0bf0f99e4592ce788f2e047 +SHA512 (NetBSD-6.0/mipsco/binary/kernel/netbsd-INSTALL.symbols.gz) = e100ef50b40411ee3886ec6b0a77ac45459c4a50b1f5b6fee1961aecbef6ee4fcc5a4a1a215eeaefcf5a47407a3d907848e09fa0299be61acb7a93da813da77f +RMD160 (NetBSD-6.0/mipsco/binary/kernel/netbsd-INSTALL.symbols.gz) = 1e65145861489b78275308a994aca38a4e60e3d6 +MD5 (NetBSD-6.0/mipsco/binary/kernel/netbsd-INSTALL.symbols.gz) = 5a441172f0a1659f405e7db91dcbdbc9 +SHA1 (NetBSD-6.0/mipsco/binary/kernel/netbsd-INSTALL.gz) = 517897ab45650448a730ae2d9df177e3858c7ecf +SHA512 (NetBSD-6.0/mipsco/binary/kernel/netbsd-INSTALL.gz) = c8f2a2b0e243000b5c6a134b1c822e40cd454230039ed39a147320e049a8c4b8f540ba32613a1a189455d2f14f56b2291549b3cc40a16c65baf451e5e6005874 +RMD160 (NetBSD-6.0/mipsco/binary/kernel/netbsd-INSTALL.gz) = 7a428cf2e424233910e6941975b984f54639d581 +MD5 (NetBSD-6.0/mipsco/binary/kernel/netbsd-INSTALL.gz) = 989821fb043e7208eb7464b9cc3d6faf +SHA1 (NetBSD-6.0/mipsco/binary/sets/games.tgz) = f56d3e5181634f6a3d7908dcb002ebcb1c5aaff0 +SHA512 (NetBSD-6.0/mipsco/binary/sets/games.tgz) = 0cff50ea13e34fe338edf70da6a28af061580feb4cb0773828adefa631ebd471a96568a3b30ea0f13f3bb116856a1b6aad8a5a52443346f52e4907f4caabc5f1 +RMD160 (NetBSD-6.0/mipsco/binary/sets/games.tgz) = 1538910578dbb8eee2931200fac0ccda44758e5f +MD5 (NetBSD-6.0/mipsco/binary/sets/games.tgz) = 2bd5bd0ce72df5cf92767b8c3f7cc208 +SHA1 (NetBSD-6.0/mipsco/binary/sets/man.tgz) = 899b9d8242e983a5110ab755651c24f709b5af67 +SHA512 (NetBSD-6.0/mipsco/binary/sets/man.tgz) = 410999db110d710f4bb498c3d7ae7adc62170c7c2f470ce189c92f6c436c5ea96149659c631ef0b5605caaa025d97dfe1c07c428d86f51239657bd6b71717b15 +RMD160 (NetBSD-6.0/mipsco/binary/sets/man.tgz) = c1270f68c6d41b351877f71f0396ac34877dfc8d +MD5 (NetBSD-6.0/mipsco/binary/sets/man.tgz) = df4db2bbfa39ef6a4a215d949653d04a +SHA1 (NetBSD-6.0/mipsco/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/mipsco/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/mipsco/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/mipsco/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/mipsco/binary/sets/xbase.tgz) = d81c7fe75a90f1b2111a066e78f1f2b3e8edcd8c +SHA512 (NetBSD-6.0/mipsco/binary/sets/xbase.tgz) = c241391fcde4a685a0a2af6f843844ac2e918024c447a2b5ea2cf5300f69acc42fdadf53d3b0348f10723b786bcc0f420e68fe36228375bf3cb5140de41eb40f +RMD160 (NetBSD-6.0/mipsco/binary/sets/xbase.tgz) = 2fbf60b64c0b7ac2be72ebf998d9d7390fc40705 +MD5 (NetBSD-6.0/mipsco/binary/sets/xbase.tgz) = cd23ca0f6b359c4d695d4494a147d40f +SHA1 (NetBSD-6.0/mipsco/binary/sets/xcomp.tgz) = c8f5ff5ea9f9bbe231f92d8b7f3bfcbd2897069f +SHA512 (NetBSD-6.0/mipsco/binary/sets/xcomp.tgz) = c7590075195019078b68ec5f87e36479ae2e7b7749c523df4ef21c9d881c343cda9f5c2bba897dd313329a76fe5c18e920d92827878d98ce08a7dc776352cd02 +RMD160 (NetBSD-6.0/mipsco/binary/sets/xcomp.tgz) = bc60e267cb6e11b4a7305f8b7074084e179e0ff5 +MD5 (NetBSD-6.0/mipsco/binary/sets/xcomp.tgz) = 8e58ee51667def3bd015f79769c0d932 +SHA1 (NetBSD-6.0/mipsco/binary/sets/xfont.tgz) = c551bd13179b9508c2e3a7e19cec323e8ba21844 +SHA512 (NetBSD-6.0/mipsco/binary/sets/xfont.tgz) = 764527f2f3f4686759fcae3fd093f4e00f34e1249994126221a6f9afe73d4cf8ddfbe8b8311798da2ed38c52466a44bb26ea08ad5aab1c08eebcc9019b4223f7 +RMD160 (NetBSD-6.0/mipsco/binary/sets/xfont.tgz) = b3a365bedf8b4a20f3920d0e33b9a42fce288953 +MD5 (NetBSD-6.0/mipsco/binary/sets/xfont.tgz) = adac8939da213a0195cc1d351f979199 +SHA1 (NetBSD-6.0/mipsco/binary/sets/xserver.tgz) = 686f6e6d722c9676351ab058736f7077b4ebd2f6 +SHA512 (NetBSD-6.0/mipsco/binary/sets/xserver.tgz) = 5c818f22edbeac7325228af99d6da6e44b5eb659c7c9fcc6b332071e97a0a490081eda7f9e0f22d6a3f3a589ae34179b434751a6191db5c664683d7510aecedc +RMD160 (NetBSD-6.0/mipsco/binary/sets/xserver.tgz) = 0e9f066095b505c7f062bf877147189a7a2f0649 +MD5 (NetBSD-6.0/mipsco/binary/sets/xserver.tgz) = cdd2e5127838437df40af161e0c8398f +SHA1 (NetBSD-6.0/mipsco/binary/sets/kern-GENERIC.tgz) = 814522219e9ef7544ff09e8a1aeec2544e62e456 +SHA512 (NetBSD-6.0/mipsco/binary/sets/kern-GENERIC.tgz) = 2e81957dd87b68e9f3b69b89d1eaf2f1cea45ea237558bc50e953d1d4987e86bd1fd7701f00971b252df35c8dfa8c006b1777c5941ee4385894680346aa3f286 +RMD160 (NetBSD-6.0/mipsco/binary/sets/kern-GENERIC.tgz) = 00a21ba72b46c7d743c2255d02a5fe462ac90774 +MD5 (NetBSD-6.0/mipsco/binary/sets/kern-GENERIC.tgz) = 85c821c524ccbfede1d34c6436de595e +SHA1 (NetBSD-6.0/mipsco/binary/sets/base.tgz) = 1a989a4f1f5bd6aa082d2af9c9e339530994e710 +SHA512 (NetBSD-6.0/mipsco/binary/sets/base.tgz) = 0b0029d19eba066306c386aa7569a5af8ce9e2d4e12f73539cceabb3bf3eb9696f006b0fefda001cef488fe4db40a3b519928fa139fd025c8e95669a2b7fddec +RMD160 (NetBSD-6.0/mipsco/binary/sets/base.tgz) = 30de7c1cda91944523275d184e5629beb3be54f8 +MD5 (NetBSD-6.0/mipsco/binary/sets/base.tgz) = dbf30b2affc7c471b1488c36fab8c383 +SHA1 (NetBSD-6.0/mipsco/binary/sets/comp.tgz) = eae1cdcf3ca993f6903f7c0315b3bded0cb19954 +SHA512 (NetBSD-6.0/mipsco/binary/sets/comp.tgz) = a777f285e5b72c5cd21eae29dc374956a80b738acd11f13d536513cb30a31273043c8c73554e4d227df99d4ef7d20f15bcc8fafc1af1c16718dbe6276c28f5b9 +RMD160 (NetBSD-6.0/mipsco/binary/sets/comp.tgz) = c4dcbd1a3ddec8bf1dddd2ec18d6d9de13dddcb8 +MD5 (NetBSD-6.0/mipsco/binary/sets/comp.tgz) = 2df422a2c23ad3357f41a02d305ca753 +SHA1 (NetBSD-6.0/mipsco/binary/sets/etc.tgz) = 4035cdd82aad7dd4b19ce7b4f18f93de45b4a35a +SHA512 (NetBSD-6.0/mipsco/binary/sets/etc.tgz) = 8df26b3954bda34cd79ee7036056c166654d36d642c7abddd10caafb0f6692bd745a1f336047de01dcefc32060712559b82ea4381dbb1c3d90eb962a798e9ed0 +RMD160 (NetBSD-6.0/mipsco/binary/sets/etc.tgz) = cb67e9de5fb8560ab973dd6dd877f856582c0538 +MD5 (NetBSD-6.0/mipsco/binary/sets/etc.tgz) = 7cc0cebd7f9c62e5e2cd7fe61e041a2a +SHA1 (NetBSD-6.0/mipsco/binary/sets/modules.tgz) = 17b0db51acea9fb430bf4f9ee65a3d10b7e01747 +SHA512 (NetBSD-6.0/mipsco/binary/sets/modules.tgz) = 4b60e6a7405c8cdda48f8c85723b4245f3af0f31c333090bc3833f203606d91cdf067a02a9a179956642b368d4f78d1da53cb48bb783a0abf24ac5a1c56681cd +RMD160 (NetBSD-6.0/mipsco/binary/sets/modules.tgz) = 34019b1b1080db5d84607337765c6fb19c103651 +MD5 (NetBSD-6.0/mipsco/binary/sets/modules.tgz) = f53620978a24bc909f9555125ddc6416 +SHA1 (NetBSD-6.0/mipsco/binary/sets/tests.tgz) = 528b2898dfd85f9c51f382d31f357ff470fccbed +SHA512 (NetBSD-6.0/mipsco/binary/sets/tests.tgz) = fb52dddb334a13e19dfd657aa165a2be4c9ed546e739d337141735927c74ed444c63a2ccfc7676ddc7301ade3bd9b713ac238a3cc37b8716705222856f26edde +RMD160 (NetBSD-6.0/mipsco/binary/sets/tests.tgz) = 4bf30f676d0c7cdb6838ea7807c505de82372884 +MD5 (NetBSD-6.0/mipsco/binary/sets/tests.tgz) = a150e930291903d9751319a92ad116be +SHA1 (NetBSD-6.0/mipsco/binary/sets/text.tgz) = 01174401e42d87684ed569f3001994142451fe29 +SHA512 (NetBSD-6.0/mipsco/binary/sets/text.tgz) = 8f2c57883df809889d5371730ff738429f147eb659895ef3bd25c23a1c78ed3baacee1e09d82630daa92b9dc5810167924537cdcb1234536acbc02269acbfd2f +RMD160 (NetBSD-6.0/mipsco/binary/sets/text.tgz) = 690f4481c50ab0bcd2a2773e762f250b60a7d088 +MD5 (NetBSD-6.0/mipsco/binary/sets/text.tgz) = 0bb0dfa52358016da848c0783a4e9ccd +SHA1 (NetBSD-6.0/mipsco/binary/sets/xetc.tgz) = 1824720386f5e1fca6135a77aad15444221ffd3f +SHA512 (NetBSD-6.0/mipsco/binary/sets/xetc.tgz) = 1f752393b0913fa39f222eb8cff44c9c4b8045008459e2c2122748114a5c69c684153aed737aabceb9fde1cb4852527d6f4375be177b6f8e270aaef9a3360ab7 +RMD160 (NetBSD-6.0/mipsco/binary/sets/xetc.tgz) = 346eb417698387537bd483d12d70796c968c970a +MD5 (NetBSD-6.0/mipsco/binary/sets/xetc.tgz) = d9822dfdedccbf5fbd3bf6ab9b178186 +SHA1 (NetBSD-6.0/mipsco/installation/diskimage/diskimage.gz) = 7f3836f8a683b1bc03880af9a5440ce0c43d45be +SHA512 (NetBSD-6.0/mipsco/installation/diskimage/diskimage.gz) = 1c513851002df0e3d6d11e33b5b62df96547e75c300c22737be8f553613404d94dbddf036cb2a00707b8d23b00a14ab3b37fd2251fa0f04b05ab35fd13c241a8 +RMD160 (NetBSD-6.0/mipsco/installation/diskimage/diskimage.gz) = 8b22ef52868c3da50f224a8663683a990816d87e +MD5 (NetBSD-6.0/mipsco/installation/diskimage/diskimage.gz) = 0264b27319b43fd4e9c8c74e0478dac4 +SHA1 (NetBSD-6.0/mipsco/installation/netboot/diskimage.tgz) = 62ce9d94cbc2d187ef03f9c4c22f0d865c482500 +SHA512 (NetBSD-6.0/mipsco/installation/netboot/diskimage.tgz) = 4b53601368b9a70e6391efab32547a038c5b05b39ac73c1677f8b1317ca0d0458d1178218aa5457d8e0d8545a1f2a20e65e200c3e8d8b04e395d11886e30c22c +RMD160 (NetBSD-6.0/mipsco/installation/netboot/diskimage.tgz) = 8da2d5476ab14c8f44c732fc07202a234d5b4abc +MD5 (NetBSD-6.0/mipsco/installation/netboot/diskimage.tgz) = b83ebc427977f9b30679b06765d6babe +SHA1 (NetBSD-6.0/mmeye/binary/kernel/netbsd-GENERIC.gz) = 93157fd963d5e5967b626593297490082c21b426 +SHA512 (NetBSD-6.0/mmeye/binary/kernel/netbsd-GENERIC.gz) = 300868a582f1eaa960d0d211374ca563a7a5f8347239b178a368ad3c527ee8ef76ca54628fbacc01521903cda04309b666953e1136d1f1fa8ddd28a046d1182c +RMD160 (NetBSD-6.0/mmeye/binary/kernel/netbsd-GENERIC.gz) = 7da72149fd4cbd471bf3abf076a4f33c8dc0a3a5 +MD5 (NetBSD-6.0/mmeye/binary/kernel/netbsd-GENERIC.gz) = 053862a7ced67c229e688793b99d2fa1 +SHA1 (NetBSD-6.0/mmeye/binary/sets/games.tgz) = 37e15b0950aaaf1af36427ae5dd5866c1879b6b3 +SHA512 (NetBSD-6.0/mmeye/binary/sets/games.tgz) = e674abb1b1966acbc581a8f8b3e37841f48656e66f3302077cbb2de443487912b99521336ec5dc096fa3c7769b2d7623e1d1720a079407ec1861d32159a72ebc +RMD160 (NetBSD-6.0/mmeye/binary/sets/games.tgz) = 36070071e8315d2352be1b3e563ce7ef7625d184 +MD5 (NetBSD-6.0/mmeye/binary/sets/games.tgz) = 0016145b46957b95dd158b4441dfb010 +SHA1 (NetBSD-6.0/mmeye/binary/sets/man.tgz) = 899b9d8242e983a5110ab755651c24f709b5af67 +SHA512 (NetBSD-6.0/mmeye/binary/sets/man.tgz) = 410999db110d710f4bb498c3d7ae7adc62170c7c2f470ce189c92f6c436c5ea96149659c631ef0b5605caaa025d97dfe1c07c428d86f51239657bd6b71717b15 +RMD160 (NetBSD-6.0/mmeye/binary/sets/man.tgz) = c1270f68c6d41b351877f71f0396ac34877dfc8d +MD5 (NetBSD-6.0/mmeye/binary/sets/man.tgz) = df4db2bbfa39ef6a4a215d949653d04a +SHA1 (NetBSD-6.0/mmeye/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/mmeye/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/mmeye/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/mmeye/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/mmeye/binary/sets/xbase.tgz) = 564bce6dd7c37b5e941e41d50f363c133fdf8f97 +SHA512 (NetBSD-6.0/mmeye/binary/sets/xbase.tgz) = 23b3306254c789331542e63974f9d7cdc54d99ba2cd67cf6a1c97f09afa4f6cf6aa8798e37b7c38f4a55afd1572154f291fa1bf2e2a1fc87165fd6bd7f89fb80 +RMD160 (NetBSD-6.0/mmeye/binary/sets/xbase.tgz) = 476fbd8301bec0795a01552728ada44204d2dbe6 +MD5 (NetBSD-6.0/mmeye/binary/sets/xbase.tgz) = 9fbbbdb3acfa4ccd9f0b309ea0ed0700 +SHA1 (NetBSD-6.0/mmeye/binary/sets/xcomp.tgz) = 526a278a13833073e6231e879abdec85400ca888 +SHA512 (NetBSD-6.0/mmeye/binary/sets/xcomp.tgz) = d2081a7536e3d7fa27a363afd8f6eb5fc3de4606f11b4857be2f1df59934da9d3d16e0df3a6edf4cdf52c8f579e0e4c06f07de0959b5213c21be1a8fdc2ee134 +RMD160 (NetBSD-6.0/mmeye/binary/sets/xcomp.tgz) = 4a767ff08e9bcf98f886849cabebd1300397256f +MD5 (NetBSD-6.0/mmeye/binary/sets/xcomp.tgz) = a23a2d8be9298497b4b6d39fda330bf4 +SHA1 (NetBSD-6.0/mmeye/binary/sets/xetc.tgz) = 93a5cfbbfdc641f91ab363d4b65d1158d71c0cfc +SHA512 (NetBSD-6.0/mmeye/binary/sets/xetc.tgz) = 85a67734801e81e129a37b73ae62211459fb16d4e52a945ef21a4bb908dd7d1d775233956086dd3d59af45bcea24fbd6f54a2a9175756d242b57e07d10767548 +RMD160 (NetBSD-6.0/mmeye/binary/sets/xetc.tgz) = 6fb055d0e1b6264bf1ec396236d903218832377a +MD5 (NetBSD-6.0/mmeye/binary/sets/xetc.tgz) = af954b56e624948145b91aa451d77392 +SHA1 (NetBSD-6.0/mmeye/binary/sets/xfont.tgz) = 6139c05273b6feeecdfcd11cbe0da91256d12a11 +SHA512 (NetBSD-6.0/mmeye/binary/sets/xfont.tgz) = bb849454ede88d39ca60d6c513c833c2b29ea548adedb9f76870839174a3daa838d38a6ad701c78bfc164e690c5ebda9c9d00d4c23ad816df9f1962313afdbf2 +RMD160 (NetBSD-6.0/mmeye/binary/sets/xfont.tgz) = ea8f123f9f78b429b77ff15c924803da1da2068d +MD5 (NetBSD-6.0/mmeye/binary/sets/xfont.tgz) = a87cb6769c37ae20dbf0dd70cef93d11 +SHA1 (NetBSD-6.0/mmeye/binary/sets/xserver.tgz) = 6cd4fdb0ff00ef5d89b47e68e538c86e395b2054 +SHA512 (NetBSD-6.0/mmeye/binary/sets/xserver.tgz) = e3b575cab95e297a05a26a03eeff0cf843d665ebdfd103846ad544bef1d04f93aa20ceab09b1dfaae8f59d89ebb1cbef400b7521bdb41f7542f23156540aa4c0 +RMD160 (NetBSD-6.0/mmeye/binary/sets/xserver.tgz) = 7e52b98276b4d097f7babe918e6768ae9d7945db +MD5 (NetBSD-6.0/mmeye/binary/sets/xserver.tgz) = a505ab4ce0801aabe21fe6038b63809f +SHA1 (NetBSD-6.0/mmeye/binary/sets/kern-GENERIC.tgz) = e14c11631e2e88e3b57b7d20fc3c645faf18fe37 +SHA512 (NetBSD-6.0/mmeye/binary/sets/kern-GENERIC.tgz) = 29dfa7b68e616b6192620316e85972381e7c104070f2570a4222b22c738eddeebd3d8a49518f64adada548f3cbc31a2c501db6f186d7c2fb4178cd9187d7e289 +RMD160 (NetBSD-6.0/mmeye/binary/sets/kern-GENERIC.tgz) = b4289ab1966d34a7fc19d6736c374e98c969f2f0 +MD5 (NetBSD-6.0/mmeye/binary/sets/kern-GENERIC.tgz) = 6469d2d171a8a4bb99ec9a396d43c4b1 +SHA1 (NetBSD-6.0/mmeye/binary/sets/base.tgz) = f26be3019cb31f22bea52c431ec65026536117d8 +SHA512 (NetBSD-6.0/mmeye/binary/sets/base.tgz) = d595fa01b6176f11dd722a4c0416e83975fabb7669cfb018b364681a82c1fab6d456e35aee5c1e8f62d721708976da1ddea203ba31c782265d95dadc046080b8 +RMD160 (NetBSD-6.0/mmeye/binary/sets/base.tgz) = d08e45a281fa538ba47d5e01b7ca7d2c34d05847 +MD5 (NetBSD-6.0/mmeye/binary/sets/base.tgz) = 3a7f10d4e415aeeab19f10c6cd9683e6 +SHA1 (NetBSD-6.0/mmeye/binary/sets/comp.tgz) = 0e37635ed1c12873ba9443f765fa8ecd7441aa43 +SHA512 (NetBSD-6.0/mmeye/binary/sets/comp.tgz) = 2528bf14ced0b15c49452d705cb60cf9e33187fc759920e4e400fc7a2cbb140efb4e46a135a3c06b7c8b4ae9a2b06094e4f14b32372d3b744d0d898818ac0e4a +RMD160 (NetBSD-6.0/mmeye/binary/sets/comp.tgz) = 51bee8a0d676f8f51918b76a816ddd417cc38a6b +MD5 (NetBSD-6.0/mmeye/binary/sets/comp.tgz) = cb209fc3bf35ff197cec755c15879f27 +SHA1 (NetBSD-6.0/mmeye/binary/sets/etc.tgz) = 574390c9066c5a2867c217726a60c5b0fcd954c6 +SHA512 (NetBSD-6.0/mmeye/binary/sets/etc.tgz) = 29f0fdf264263ddca8a04e2a645999127bac3025daf2ee560647f4d15fbaec3d929c725256244fa561ee69d8eddf4c9439d81629894dcccba13d063ec1a0d70f +RMD160 (NetBSD-6.0/mmeye/binary/sets/etc.tgz) = 5e68a1f6a88a56e63788525987bcbef81314cfd0 +MD5 (NetBSD-6.0/mmeye/binary/sets/etc.tgz) = bb1639782d6f4027a7b872732e0f819c +SHA1 (NetBSD-6.0/mmeye/binary/sets/modules.tgz) = d687589906a811d0ecf22c89bf54248326aa0bef +SHA512 (NetBSD-6.0/mmeye/binary/sets/modules.tgz) = fd536f114ba71d1ed7241a81f89af7d26a8b554b6fa12ccb16d2d4e6e23029be66fbf4d2cb4990c65102bf3206972ca00a329c6a6c8cb86ad283356aa38434bc +RMD160 (NetBSD-6.0/mmeye/binary/sets/modules.tgz) = c2bde6622408d084a8ed7fbeafce2260220c5560 +MD5 (NetBSD-6.0/mmeye/binary/sets/modules.tgz) = d833b7a1b95c96a2fb4c526ddc7b6a62 +SHA1 (NetBSD-6.0/mmeye/binary/sets/tests.tgz) = 28c07cc4ab9c6688c615ecfae68cdd7afeaf627b +SHA512 (NetBSD-6.0/mmeye/binary/sets/tests.tgz) = bdf6463ad028eef4bfb3feb78d43924c4c176b8195509d25d1f98cc772cd1d4edf1820497dfb1baee7dcc142d0e64e78d3203feab0636fe4d821a4cd64250459 +RMD160 (NetBSD-6.0/mmeye/binary/sets/tests.tgz) = f10cf5b11bb96eb0be1c08f698897cb2c609c2f8 +MD5 (NetBSD-6.0/mmeye/binary/sets/tests.tgz) = a0f6fcd15874d6439da5f852487e3539 +SHA1 (NetBSD-6.0/mmeye/binary/sets/text.tgz) = 59d1600b40b17a4c0459e6b3e0a0c2cff1194270 +SHA512 (NetBSD-6.0/mmeye/binary/sets/text.tgz) = 0c44d1c586ad834e2ecca5bf57e88d3315e19341deefb36e8f9584d22328fa255d9e7c26028091e8e0465aea5e68ead7fe343138f54cd219c69eaeb7facdf85f +RMD160 (NetBSD-6.0/mmeye/binary/sets/text.tgz) = 258e107b924fc698dd9ac2933f4b040374cc9291 +MD5 (NetBSD-6.0/mmeye/binary/sets/text.tgz) = 241e3f6acd2a44f23f1368c4897ea43a +SHA1 (NetBSD-6.0/mmeye/INSTALL.html) = 307db90e852c93274d4d475013aa29db682ad785 +SHA512 (NetBSD-6.0/mmeye/INSTALL.html) = 6a10441885d95313036134e897f41508c5823386532d4e57e33d693164d8a6a727f39aad44e3606b614cd037eed7096a2c88962b495f1915dd9db0f1165897dc +RMD160 (NetBSD-6.0/mmeye/INSTALL.html) = efd26420ebc8e2bbca8e756d05a8978b3c8f6a21 +MD5 (NetBSD-6.0/mmeye/INSTALL.html) = 4074818595561d15e823f3fcf0e319ab +SHA1 (NetBSD-6.0/mmeye/INSTALL.more) = 508b142e63e52558c975e9b9e8d3ddd5f392f47a +SHA512 (NetBSD-6.0/mmeye/INSTALL.more) = da8142dcec08c7c1dd64b680e987abed58c6d8685c93c66fc4b1218f18cb64c626949d841b5ee379a09a0b8d1ae8af12a2690d8dbc4f768497f1c3e8e646f377 +RMD160 (NetBSD-6.0/mmeye/INSTALL.more) = 58a81c1cc83e5033ab3a527190e7ee1fae534d76 +MD5 (NetBSD-6.0/mmeye/INSTALL.more) = 248b67d9ac8e481bdfd7952cef78a14e +SHA1 (NetBSD-6.0/mmeye/INSTALL.ps) = 4bf1609d1513b6e41cfc5cb480dee72432e5a416 +SHA512 (NetBSD-6.0/mmeye/INSTALL.ps) = 691a138a6af72a7e42cc03c71d6bcde5c210ec570507ee25333e1ef9702aa689be0c7d46009aea72dc1dbca93c52a46f1745c1dc985725fa5e63922c4f5927e2 +RMD160 (NetBSD-6.0/mmeye/INSTALL.ps) = 4387c8bab777418797ccf13a05abc4a085b28fab +MD5 (NetBSD-6.0/mmeye/INSTALL.ps) = 98a48fdc04e24e9d6976363721d644aa +SHA1 (NetBSD-6.0/mmeye/INSTALL.txt) = 75f5b090195d57c0542212c1b5eed5e5ccd3297e +SHA512 (NetBSD-6.0/mmeye/INSTALL.txt) = 7c1310578154afee26aa66db4198dc5ba98b9f985f05c9e6a3847fe88e947e1161d541527dd1986ff3ca20ad92468483a2195013ccb8d16e89914006f1d0b566 +RMD160 (NetBSD-6.0/mmeye/INSTALL.txt) = e05dd82511b132d9047eddeee16043524246867b +MD5 (NetBSD-6.0/mmeye/INSTALL.txt) = e3de50b8b8480113536fa86b62245902 +SHA1 (NetBSD-6.0/mvme68k/binary/kernel/netbsd-GENERIC.gz) = a13aee658df1b52a7aaf3029d425e922ec26d4c1 +SHA512 (NetBSD-6.0/mvme68k/binary/kernel/netbsd-GENERIC.gz) = 218d038a60dc542188f10c56e096434ebd26acddb4919ceb7ef4263ee85a3d25c60e9265683298fccfdcdb6b7d155138428f5029d37c11455d8f49077e0753cc +RMD160 (NetBSD-6.0/mvme68k/binary/kernel/netbsd-GENERIC.gz) = 5963381f5dff4d47bd58e488fdead7f9e4886d26 +MD5 (NetBSD-6.0/mvme68k/binary/kernel/netbsd-GENERIC.gz) = 86d45589986fb0bb05dc8c7dc77278a1 +SHA1 (NetBSD-6.0/mvme68k/binary/kernel/netbsd-VME147.gz) = ea20eed9edbc71eca530c3280770e6f8b09fa270 +SHA512 (NetBSD-6.0/mvme68k/binary/kernel/netbsd-VME147.gz) = 75a7255373b228b1932477a121111add15fa0ec8b03594794c6b6e3c45055f7ca2be29923b263ffab7ab51b3c9bebc9d8280ea701916b76f581dcc18bb510584 +RMD160 (NetBSD-6.0/mvme68k/binary/kernel/netbsd-VME147.gz) = ea31d6a830019327b2c3435afdfd947d8464ef23 +MD5 (NetBSD-6.0/mvme68k/binary/kernel/netbsd-VME147.gz) = 15c5a42f970736283e7a6a0849bd86d4 +SHA1 (NetBSD-6.0/mvme68k/binary/kernel/netbsd-VME162.gz) = 041755caacc323b08d0d4bc7d7d50fb178374f24 +SHA512 (NetBSD-6.0/mvme68k/binary/kernel/netbsd-VME162.gz) = 0f9165f9574da412d25c74601c42f6678b78ae78c04b0eb0753dce9266289fb656071115c32425e79dbb88df2482971d3808095228ce56fa7124ba34a396b0d2 +RMD160 (NetBSD-6.0/mvme68k/binary/kernel/netbsd-VME162.gz) = d93f72e9bf72b15a7f740977f51270620e17afe6 +MD5 (NetBSD-6.0/mvme68k/binary/kernel/netbsd-VME162.gz) = 0c35781afea5d9df108ffe2ff82563f9 +SHA1 (NetBSD-6.0/mvme68k/binary/kernel/netbsd-VME167.gz) = 4ede6bb44a66a1ca0582e2bd6b38d94dc66e5c22 +SHA512 (NetBSD-6.0/mvme68k/binary/kernel/netbsd-VME167.gz) = 33feb4ceaa5352e85ed445bb355d997181f69cfe2b08de57a631be7c93c85cb1f42d052bd6de489f6ac631c88c77192785d170e41c0ec6315b88fd429d88f3bf +RMD160 (NetBSD-6.0/mvme68k/binary/kernel/netbsd-VME167.gz) = 6768bab2219da0e3ef78324a701e0fb112c18153 +MD5 (NetBSD-6.0/mvme68k/binary/kernel/netbsd-VME167.gz) = 6e65873511ff8bb90d721f0c2e559bf4 +SHA1 (NetBSD-6.0/mvme68k/binary/kernel/netbsd-VME172.gz) = 01ee771c809080dce253e2acbce1bcdfdd46b055 +SHA512 (NetBSD-6.0/mvme68k/binary/kernel/netbsd-VME172.gz) = 65e0680d9ce92aed2ba08971a434f2a290ccf9f85ce3365327ec8185c5d57e1bdf08593c5ff18e3c0e6581c78ceadd570d25fb1e714edd7896fca09fae727695 +RMD160 (NetBSD-6.0/mvme68k/binary/kernel/netbsd-VME172.gz) = 93136f2a9773f5e243622e756ea3969c3732403d +MD5 (NetBSD-6.0/mvme68k/binary/kernel/netbsd-VME172.gz) = 08a73d99398505743b3de4f5394ffdd7 +SHA1 (NetBSD-6.0/mvme68k/binary/kernel/netbsd-VME177.gz) = e884157c76ca076bd53f3c1752b4f95ade2eacea +SHA512 (NetBSD-6.0/mvme68k/binary/kernel/netbsd-VME177.gz) = 13a0a7e5c50848593ccbf5876cf27988b138582fff9d4f140cc3b63b9d768163ddea65752fd0676614ccbb85f64d0efdd3611ff2fce31837afb9acebcdb63657 +RMD160 (NetBSD-6.0/mvme68k/binary/kernel/netbsd-VME177.gz) = 898154c89255fca36e0ec7051638b32cfb541dfd +MD5 (NetBSD-6.0/mvme68k/binary/kernel/netbsd-VME177.gz) = 77d2383aa5faff6ecc139af1e7dc51fa +SHA1 (NetBSD-6.0/mvme68k/binary/sets/games.tgz) = 16ee93ea4d5fac2fb28fad5c32c8a3d57d011d79 +SHA512 (NetBSD-6.0/mvme68k/binary/sets/games.tgz) = a7f49ab72f50273f66c8dcf408b57ec4668debd5537c5bd0ec59aa0f4fa1d599ba0798d1b283315c4208cbcb608925808ce003b1ade79034886edb8208f9f48d +RMD160 (NetBSD-6.0/mvme68k/binary/sets/games.tgz) = 1e09d99d7fe2e495763f05919472d27a4ba699df +MD5 (NetBSD-6.0/mvme68k/binary/sets/games.tgz) = 8a26f3e864444209088bccf21419a616 +SHA1 (NetBSD-6.0/mvme68k/binary/sets/man.tgz) = 899b9d8242e983a5110ab755651c24f709b5af67 +SHA512 (NetBSD-6.0/mvme68k/binary/sets/man.tgz) = 410999db110d710f4bb498c3d7ae7adc62170c7c2f470ce189c92f6c436c5ea96149659c631ef0b5605caaa025d97dfe1c07c428d86f51239657bd6b71717b15 +RMD160 (NetBSD-6.0/mvme68k/binary/sets/man.tgz) = c1270f68c6d41b351877f71f0396ac34877dfc8d +MD5 (NetBSD-6.0/mvme68k/binary/sets/man.tgz) = df4db2bbfa39ef6a4a215d949653d04a +SHA1 (NetBSD-6.0/mvme68k/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/mvme68k/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/mvme68k/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/mvme68k/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/mvme68k/binary/sets/xserver.tgz) = 1d20fd039546a66b428b854c659ea5e2ee9f8114 +SHA512 (NetBSD-6.0/mvme68k/binary/sets/xserver.tgz) = 091d09049d0af5555feec02065234e281677aeb3ecbab5a19413d924a8b58dc7f64401ef68e68bc52d8b6eeb73e091d351c45805374b8bf276b0181415968561 +RMD160 (NetBSD-6.0/mvme68k/binary/sets/xserver.tgz) = feef5d52278d23637d7b8ba77639bfd96918e90e +MD5 (NetBSD-6.0/mvme68k/binary/sets/xserver.tgz) = b2bd6057c374376388766fc8667eb9a9 +SHA1 (NetBSD-6.0/mvme68k/binary/sets/kern-GENERIC.tgz) = b5f282108361e17368d9ca8615f3021473169abf +SHA512 (NetBSD-6.0/mvme68k/binary/sets/kern-GENERIC.tgz) = 165bec66d47652cb43981780aa068960efd933f9538145f363a559d8cc58d16d78ae5d588d98bb39795cdde762f280b36750211da2ed3a5298b0d94edf2e0bb5 +RMD160 (NetBSD-6.0/mvme68k/binary/sets/kern-GENERIC.tgz) = 1ad2613634bf8c7654f87c4a54c9d3e6c0b1f349 +MD5 (NetBSD-6.0/mvme68k/binary/sets/kern-GENERIC.tgz) = b4b8eee7f4f1854f8632928b5ee516de +SHA1 (NetBSD-6.0/mvme68k/binary/sets/base.tgz) = c3e2ce1f54481094d67ff2a87a6b5000d8130ad2 +SHA512 (NetBSD-6.0/mvme68k/binary/sets/base.tgz) = 02c29cbe0171a6c5312fb1a468e68bb8a5a5258df936c0a31fccb7bc04c8e1293d41ce6f67de08ca5584c6208dd9050c70f99c1c3b8c35a499bf94a957808797 +RMD160 (NetBSD-6.0/mvme68k/binary/sets/base.tgz) = 7920bf359b28e793c0410ce08a98025dd3ea6971 +MD5 (NetBSD-6.0/mvme68k/binary/sets/base.tgz) = c9893e324841703eed47b475c2d37607 +SHA1 (NetBSD-6.0/mvme68k/binary/sets/comp.tgz) = 100d0663bb2c601df55d490315c9b36b7ea700f3 +SHA512 (NetBSD-6.0/mvme68k/binary/sets/comp.tgz) = 70bf8fc817821c6c5061776bac0ee9ebf8567fd19a2d98c751d1073a706290eb9870627b2f1fea650d19a876e8a5215e5e52407437d6be977777013f5f59fa8a +RMD160 (NetBSD-6.0/mvme68k/binary/sets/comp.tgz) = 497fb5a993abc08f005e1f287b8520dbace84549 +MD5 (NetBSD-6.0/mvme68k/binary/sets/comp.tgz) = 24cf494b20e22c8630e6bbba17b96bc1 +SHA1 (NetBSD-6.0/mvme68k/binary/sets/etc.tgz) = c6f1d70ad7bf234c79f4e15508b09c7b0c33f1d8 +SHA512 (NetBSD-6.0/mvme68k/binary/sets/etc.tgz) = 13a8204695757c27b69ed52a02c55a1e2b2d6140a5dfffd8f9f24625a56c9f3bd1f5de868a99c265e5fc759cb80cb7239dbe965c44693fcce6e98e7691076d36 +RMD160 (NetBSD-6.0/mvme68k/binary/sets/etc.tgz) = 7365dfc472b89a3b017cdcf41bf10f928dcf723e +MD5 (NetBSD-6.0/mvme68k/binary/sets/etc.tgz) = 1e8812db12c38683ce12950d00ded70a +SHA1 (NetBSD-6.0/mvme68k/binary/sets/kern-VME147.tgz) = 96374aa39856e13589e98f1552dd756b4f1911e9 +SHA512 (NetBSD-6.0/mvme68k/binary/sets/kern-VME147.tgz) = f31cc707ced4c96b2019d7d44169e203f6df2616d09e7a3f4e2a4f0e4c509e978ba324761bdd26d1ee443e4d72e90e00effc24e537644013d5a2de95f3812574 +RMD160 (NetBSD-6.0/mvme68k/binary/sets/kern-VME147.tgz) = 219ba053784c069875b7434631463f61293bab1c +MD5 (NetBSD-6.0/mvme68k/binary/sets/kern-VME147.tgz) = 5349b757ec12a84df1e102583674646d +SHA1 (NetBSD-6.0/mvme68k/binary/sets/kern-VME162.tgz) = c56ed72a7c0da9fb44d19ece17801d1b7527e05a +SHA512 (NetBSD-6.0/mvme68k/binary/sets/kern-VME162.tgz) = 12078cbbbd7b1093f956b6526643b446890b82c043b17fc97e61259f54fc81cdbd8ebc56a735eb5937bff004b63d7f291e7ea2cd0dad3bd5b07f089df2c83ab7 +RMD160 (NetBSD-6.0/mvme68k/binary/sets/kern-VME162.tgz) = cfddd4246205e867729907015fc6dd16da7fe6e5 +MD5 (NetBSD-6.0/mvme68k/binary/sets/kern-VME162.tgz) = 432a04306d40c933f2e04e5a332800e2 +SHA1 (NetBSD-6.0/mvme68k/binary/sets/kern-VME167.tgz) = 90302a0bc14e084f2643de427e87bc5b04553ab0 +SHA512 (NetBSD-6.0/mvme68k/binary/sets/kern-VME167.tgz) = 62c19ad0fb282a427beb1bf2d0d1b9a1cfc2681bcd04e3fb51ade0e793f26b52d04b5eb28e4c25524244e8c6dad724fc07de7a6544438cbd2a503972999f23ea +RMD160 (NetBSD-6.0/mvme68k/binary/sets/kern-VME167.tgz) = d84d45b735805261e014ae52746e279902ad7e9a +MD5 (NetBSD-6.0/mvme68k/binary/sets/kern-VME167.tgz) = 8d38010b19b455f324d0b08485482395 +SHA1 (NetBSD-6.0/mvme68k/binary/sets/kern-VME172.tgz) = 017724bf77e35e2021308dadafe5a90e59a32498 +SHA512 (NetBSD-6.0/mvme68k/binary/sets/kern-VME172.tgz) = c3ca75dd2287e6af935934a4dabba21f085889383c395c8c72636047d682541ee5669998dd5988e0127879d7b34df260dc9109c292a2c2663ca8cfbed9c03278 +RMD160 (NetBSD-6.0/mvme68k/binary/sets/kern-VME172.tgz) = d8676c3325db3b3f619599f9e7a33cf3b1eb5bf1 +MD5 (NetBSD-6.0/mvme68k/binary/sets/kern-VME172.tgz) = b89cd9b71b5b68285bf36d958a3b8746 +SHA1 (NetBSD-6.0/mvme68k/binary/sets/kern-VME177.tgz) = f9bdc8e89488ba91385adf9f0960633ba7dbf6da +SHA512 (NetBSD-6.0/mvme68k/binary/sets/kern-VME177.tgz) = 642825fa141d2de457a0d3eca1224cdb5b087383dca6ed4f36668be6f6fe9f9e30b942ec5eb177b4733aaad40f6a0eace0f744fba3777eb356dd75d8c113785f +RMD160 (NetBSD-6.0/mvme68k/binary/sets/kern-VME177.tgz) = ef6abd72e2a71a5995c628107f473ceabe2945e6 +MD5 (NetBSD-6.0/mvme68k/binary/sets/kern-VME177.tgz) = 42b79dd96c98e97639d1a9d698673996 +SHA1 (NetBSD-6.0/mvme68k/binary/sets/modules.tgz) = 5479e9142d1f21bc8346cd34e9f00761e2e05f48 +SHA512 (NetBSD-6.0/mvme68k/binary/sets/modules.tgz) = 094b2d20eb3dc973fc212085dcc4d110249fc71eb017ea390b7f9aeffd4d8d0aeb51d421b4c95add33a17ac5d7dae1e3c9fc654f8a4181d078dbe2bac95a96b6 +RMD160 (NetBSD-6.0/mvme68k/binary/sets/modules.tgz) = 187b451690395a8e05f22294016a627e4db4539f +MD5 (NetBSD-6.0/mvme68k/binary/sets/modules.tgz) = 5d3d2aa79488e5f8e90ff7b26f80fc97 +SHA1 (NetBSD-6.0/mvme68k/binary/sets/tests.tgz) = b994ffc0b63206aa7a8ab6de392ec33189894764 +SHA512 (NetBSD-6.0/mvme68k/binary/sets/tests.tgz) = 714ac7fe966021f842409c135711b7adfb03c4b6a095df9527d02d1b83b14db62f1ec1a7eaaaebc68e4f12588e52fab9318c21912f20b8380a7a8b8e30e8576d +RMD160 (NetBSD-6.0/mvme68k/binary/sets/tests.tgz) = ba3293225ace42d8c47037879ba0cecd8f883aaf +MD5 (NetBSD-6.0/mvme68k/binary/sets/tests.tgz) = e32c51104c90b3b684d1d640ba79b46a +SHA1 (NetBSD-6.0/mvme68k/binary/sets/text.tgz) = 61b398a67c4c47f8633d393dda778ac5c1ed8698 +SHA512 (NetBSD-6.0/mvme68k/binary/sets/text.tgz) = 29b9bb0c5aefb3d765eb6204967c3ff14f7a28b0987723c3685a2b34fa799947c876971bf524a8e43b146e9e91e37cbc89a0c4da87c47e9856bdf9d96a67f125 +RMD160 (NetBSD-6.0/mvme68k/binary/sets/text.tgz) = a73c95546d018a1853c6d00f5924da860fe9e5d0 +MD5 (NetBSD-6.0/mvme68k/binary/sets/text.tgz) = b0dbc4ddc47ab74ab24bdc0bede769a2 +SHA1 (NetBSD-6.0/mvme68k/binary/sets/xbase.tgz) = a31e38ba081b5abb671cf5f7350799782a628712 +SHA512 (NetBSD-6.0/mvme68k/binary/sets/xbase.tgz) = fa78acfbace842e0995a7f181193220f80dcae731221bf1722ece1a5bef6de846089b919beebacd7921567105f8ddae9bdaaabe0b065b62a0f18d917f03b54d9 +RMD160 (NetBSD-6.0/mvme68k/binary/sets/xbase.tgz) = 1cb1d631feb356639d3b1362518ba5f09f084510 +MD5 (NetBSD-6.0/mvme68k/binary/sets/xbase.tgz) = dae635ef3bd334e14be8b8b66a227353 +SHA1 (NetBSD-6.0/mvme68k/binary/sets/xcomp.tgz) = fbc80a68ccbef35cab4228a5ce96b22b383d9080 +SHA512 (NetBSD-6.0/mvme68k/binary/sets/xcomp.tgz) = 694780dd165f0831eac6b47ec6fd5c60589749a21e88700965a99154067b76fa374b8f7a55f26963cdba8caafe9548f66b222826cc265393e992addbf19dd468 +RMD160 (NetBSD-6.0/mvme68k/binary/sets/xcomp.tgz) = 7db19d8ccd7dbda6032d9c29a65d03bf9c71644d +MD5 (NetBSD-6.0/mvme68k/binary/sets/xcomp.tgz) = 913bbabb9e401d6a31cc09a3d259b132 +SHA1 (NetBSD-6.0/mvme68k/binary/sets/xetc.tgz) = 1aa27f8388f5bb0aa85eec00e225fc92736da214 +SHA512 (NetBSD-6.0/mvme68k/binary/sets/xetc.tgz) = 1b524f2137ea4cc5f816623a7b042b05b1303664d244b0172799b365cb16df34f0a8a47277077055baf266c7c92d5f112830ed357fa811bdf6bd713b2f90275e +RMD160 (NetBSD-6.0/mvme68k/binary/sets/xetc.tgz) = b50ff4df41b13b9276393e871e976648d344ee7f +MD5 (NetBSD-6.0/mvme68k/binary/sets/xetc.tgz) = d7709463a7a8404b6ef93aeb60755f7f +SHA1 (NetBSD-6.0/mvme68k/binary/sets/xfont.tgz) = 4f8d5c51bdd02bdff0dca66f54e5ebd25e4d6110 +SHA512 (NetBSD-6.0/mvme68k/binary/sets/xfont.tgz) = fbad852b3a697906a2ffb460f8fefe8f9aa9f2088f66423d838abc18941d497bf6f9491934de0e3359159d35c98f205b23bb9c328f832e7e62c99310067687e6 +RMD160 (NetBSD-6.0/mvme68k/binary/sets/xfont.tgz) = 41c3686ef9c2cc25eff4b9923ae3163aa9c28590 +MD5 (NetBSD-6.0/mvme68k/binary/sets/xfont.tgz) = 2ec6dafe4dbe645a90960ade3e86caed +SHA1 (NetBSD-6.0/mvme68k/installation/miniroot/miniroot.fs.gz) = 12df0f0fef9a077c27d02d2960d04ea3a148fa76 +SHA512 (NetBSD-6.0/mvme68k/installation/miniroot/miniroot.fs.gz) = fa3eeb4f14b741311ef72000e6c283195f4513e81a35f9c0a1829dbf8795d0518355b0d54d35a17c56568ac8e6db5977c1a7d4bb902c20786f901efd9b35ec42 +RMD160 (NetBSD-6.0/mvme68k/installation/miniroot/miniroot.fs.gz) = aeeeee1a475c8ef1d595c5cdff5bb3cc765bbea1 +MD5 (NetBSD-6.0/mvme68k/installation/miniroot/miniroot.fs.gz) = 9bff82e8d2d57a3fad2e831272aee965 +SHA1 (NetBSD-6.0/mvme68k/installation/netboot/netboot) = 588e8808e6e24e0a570f529c0dde8f02bcb74edd +SHA512 (NetBSD-6.0/mvme68k/installation/netboot/netboot) = 6e0b6bc3f5de5940811d0929dd0d5f65351402176ae9c8e44a0220b807b41e98c8363d4917b1f506a847c3510bfec3d78584eae8f9e1c337130b37da4d3c6f07 +RMD160 (NetBSD-6.0/mvme68k/installation/netboot/netboot) = f1239616c5743fba614065450b1aa9ca8f4057f5 +MD5 (NetBSD-6.0/mvme68k/installation/netboot/netboot) = ee5d8acc83e9f62ee902acd1da69b3d5 +SHA1 (NetBSD-6.0/mvme68k/installation/netboot/sboot) = 5f45e50e16e46d9ab20ad20d929d1a01e4d60ad5 +SHA512 (NetBSD-6.0/mvme68k/installation/netboot/sboot) = bcd667220dd50d44aa895c0d76b9ee906dd6e3ff72d9bb80167cf48ddb6456c5cb8c06829e66ee06cf69c99e50afa3005f23a6854fc56ea2a027b50315eace2c +RMD160 (NetBSD-6.0/mvme68k/installation/netboot/sboot) = eee81405c2dd838804a4d13219b431e93120fdae +MD5 (NetBSD-6.0/mvme68k/installation/netboot/sboot) = bd2f963054643f0ffa22af1ea8ecda92 +SHA1 (NetBSD-6.0/mvme68k/installation/tapeimage/bootst) = df842ee6dc97b75a8f8b8e20996f60fa5c0e6ff9 +SHA512 (NetBSD-6.0/mvme68k/installation/tapeimage/bootst) = 3a6900acfffe7118e262864abea6c325e1e69060f2b47556b8865f2f28458beb29e56d96a61a8b98520530ba3d6b5ee4e0d5499cc698497445e0d480d0b9466b +RMD160 (NetBSD-6.0/mvme68k/installation/tapeimage/bootst) = 78ea882ed8fd3cadb3b25971c7d0ad2ef159918b +MD5 (NetBSD-6.0/mvme68k/installation/tapeimage/bootst) = 720e708780805b3a7afa57bcdb9ee62b +SHA1 (NetBSD-6.0/mvme68k/installation/tapeimage/netbsd-RAMDISK.symbols.gz) = 0c590bfc2ae0c74a96ac421e16e9f6aea312d63f +SHA512 (NetBSD-6.0/mvme68k/installation/tapeimage/netbsd-RAMDISK.symbols.gz) = 1f91be15380c61c4b2eebc8e34fb6eba768dc06fe958ba03cd1a074ef76e77c490d63484834b458bef181f18a5dd84444dcb33b4ed1b35360f7df9ab727a5088 +RMD160 (NetBSD-6.0/mvme68k/installation/tapeimage/netbsd-RAMDISK.symbols.gz) = 49fe1be9202c415a147b25ca21b57c4e91f3d886 +MD5 (NetBSD-6.0/mvme68k/installation/tapeimage/netbsd-RAMDISK.symbols.gz) = 387b741997770fa953dd689bdc7c2dce +SHA1 (NetBSD-6.0/mvme68k/installation/tapeimage/netbsd-RAMDISK.gz) = 071feb6189682ed7fde6e75790b17ed023512e15 +SHA512 (NetBSD-6.0/mvme68k/installation/tapeimage/netbsd-RAMDISK.gz) = 029ef207dc80563c3d28369d7f6b1a99dae4ca573dccae9983bf3d135cbef8aece9d69a8fafe0c989bf5fc851d5a31d61c77911f7680dc4584a9229f582359f5 +RMD160 (NetBSD-6.0/mvme68k/installation/tapeimage/netbsd-RAMDISK.gz) = 6ca56e2be45d06a300f533941a582caafcbe5623 +MD5 (NetBSD-6.0/mvme68k/installation/tapeimage/netbsd-RAMDISK.gz) = 16c9e88acf91351f83fcec78132304bd +SHA1 (NetBSD-6.0/mvme68k/installation/tapeimage/stboot) = 652f8b35ed92540699c4a0b92d781bab584ff9ed +SHA512 (NetBSD-6.0/mvme68k/installation/tapeimage/stboot) = 63627858e9ea5ddf22d56e9f5bbc94c53a5fa45eb877b7b540931eaee973bf82251afaf6acf6078456f9aec047eb60b7bd66e694bafaa2210b51b0e83e19fd21 +RMD160 (NetBSD-6.0/mvme68k/installation/tapeimage/stboot) = 1283f83860ab4f66692d5ef01d0cdeceb40668b8 +MD5 (NetBSD-6.0/mvme68k/installation/tapeimage/stboot) = a54cfad8cf02a1a31a004dbc5c0a037e +SHA1 (NetBSD-6.0/mvme68k/INSTALL.html) = e3f98f5f338b9417a3f88ccc83fda9eb47696c0e +SHA512 (NetBSD-6.0/mvme68k/INSTALL.html) = b1750f826b36c84a821126455bdba2e1116bd51cd3b404c7b0c0b80110130e81e19105cd5d04563d31824e996820e1992486827b818f3f9a01d87f2b2d4da46b +RMD160 (NetBSD-6.0/mvme68k/INSTALL.html) = d6ab4cf012544dae8696f8f41208dd27ddc1ea7b +MD5 (NetBSD-6.0/mvme68k/INSTALL.html) = cd685f3e5b2052919547bfd9c8d98d0e +SHA1 (NetBSD-6.0/mvme68k/INSTALL.more) = 82746f9fb96a2db4cec433f8bad448fccaa98eef +SHA512 (NetBSD-6.0/mvme68k/INSTALL.more) = 676952c9168c0dcaea1eef58271884f95e8ad80380e33a060e29be2da7e7b139a731369e6cc0a112779be95c412de4be19f716284a3724b41f93cc5075e93b9d +RMD160 (NetBSD-6.0/mvme68k/INSTALL.more) = 79436013f39135308106f0d08b8a0fc951773a09 +MD5 (NetBSD-6.0/mvme68k/INSTALL.more) = 95f12215d3961d47f7cc70f786c331da +SHA1 (NetBSD-6.0/mvme68k/INSTALL.ps) = b2c39b95dd800c754733c8986e8f279a5895b9f9 +SHA512 (NetBSD-6.0/mvme68k/INSTALL.ps) = 120009d7f5781b9c060f3852d92bc047590b3d86d6491aa700c61d935ce8bccec1ddcca64f60fe17ffffa66871ec9c9908d42b738f8e37def53c97ac3a339c6a +RMD160 (NetBSD-6.0/mvme68k/INSTALL.ps) = 1cc7939281b187b32afa1a30955dfc3751d8dc4b +MD5 (NetBSD-6.0/mvme68k/INSTALL.ps) = b0c09fe08cf758e2dea14a23111c0c2f +SHA1 (NetBSD-6.0/mvme68k/INSTALL.txt) = d25191ccd7930c3335bacbc56dfcbfd7ab04091d +SHA512 (NetBSD-6.0/mvme68k/INSTALL.txt) = 581736f1c9236b74a0321e060d27305911aa735244a5b2e54825617cd97fa5bc1523472b87b65057fb3bc0f08216c7b53e60dca0c8ead238d7ea3da16502f16a +RMD160 (NetBSD-6.0/mvme68k/INSTALL.txt) = 05b193bfebc12030dcbe3c96273582360eb132e3 +MD5 (NetBSD-6.0/mvme68k/INSTALL.txt) = c895e463555bd32f7b61fa481b63213d +SHA1 (NetBSD-6.0/mvmeppc/binary/kernel/netbsd-GENERIC.gz) = 418f7d15770b902578623141540daa7987ed2659 +SHA512 (NetBSD-6.0/mvmeppc/binary/kernel/netbsd-GENERIC.gz) = f8ad97d747d2ffc1de7408ae9360afe25fb82eb60f73fc62198432ecb059aa64dfdc7ed74fc0d63e70a815d12414c6c9f1d8e5a717d614bafa0c9c299548ab9a +RMD160 (NetBSD-6.0/mvmeppc/binary/kernel/netbsd-GENERIC.gz) = e3603ef7455506046e4f789e2341020d81bfb46b +MD5 (NetBSD-6.0/mvmeppc/binary/kernel/netbsd-GENERIC.gz) = 713e8e8d42cebf7dea0ae4e96670a52a +SHA1 (NetBSD-6.0/mvmeppc/binary/sets/games.tgz) = fbf69640b362df2446d7414ac3a13db100c289eb +SHA512 (NetBSD-6.0/mvmeppc/binary/sets/games.tgz) = d86b41d79aea4204ccf45306937a5ec45629e37873a5956c0280fd1d54cf4a808542d097f9d978fd3277791554ce8a6fb4d0ccd46e30210549d5cce1145bb499 +RMD160 (NetBSD-6.0/mvmeppc/binary/sets/games.tgz) = fd2aed1eb51f4db522fb5163e8fde4c040b55d30 +MD5 (NetBSD-6.0/mvmeppc/binary/sets/games.tgz) = 997ae5fb42196a787df89873be321e47 +SHA1 (NetBSD-6.0/mvmeppc/binary/sets/man.tgz) = 899b9d8242e983a5110ab755651c24f709b5af67 +SHA512 (NetBSD-6.0/mvmeppc/binary/sets/man.tgz) = 410999db110d710f4bb498c3d7ae7adc62170c7c2f470ce189c92f6c436c5ea96149659c631ef0b5605caaa025d97dfe1c07c428d86f51239657bd6b71717b15 +RMD160 (NetBSD-6.0/mvmeppc/binary/sets/man.tgz) = c1270f68c6d41b351877f71f0396ac34877dfc8d +MD5 (NetBSD-6.0/mvmeppc/binary/sets/man.tgz) = df4db2bbfa39ef6a4a215d949653d04a +SHA1 (NetBSD-6.0/mvmeppc/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/mvmeppc/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/mvmeppc/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/mvmeppc/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/mvmeppc/binary/sets/xbase.tgz) = b7c8146146ebc15191c1bf53f51f8f980fe8c816 +SHA512 (NetBSD-6.0/mvmeppc/binary/sets/xbase.tgz) = 091f5d00414a9ad478811bfb0e953f2a204869bc5e310790886a59c11953974cf7068cd9a96c8823856ab2687ffa2ac31e97494f47338bfe31d80217382c59f1 +RMD160 (NetBSD-6.0/mvmeppc/binary/sets/xbase.tgz) = 4bd1bfdc7c1e1619de63fb83276c21039b945357 +MD5 (NetBSD-6.0/mvmeppc/binary/sets/xbase.tgz) = e621806afa0fcc9cdcef0f9b3c7dfcbd +SHA1 (NetBSD-6.0/mvmeppc/binary/sets/xcomp.tgz) = 960dd33b61e19dec92096a54791aca1cdf56ce54 +SHA512 (NetBSD-6.0/mvmeppc/binary/sets/xcomp.tgz) = 111dd50041e4008aeadb898c3d08f9995c5c13a41ccc20993b4ad51c81d7f6ee3b4dab16158ac7436d085b80e4a643b236a9c97edd3e915125a1466154538420 +RMD160 (NetBSD-6.0/mvmeppc/binary/sets/xcomp.tgz) = 0cf8b9a8d1489a32ba0b5a277d90e429c40650fb +MD5 (NetBSD-6.0/mvmeppc/binary/sets/xcomp.tgz) = 4ba4077ca2c0edf71813165fcf5321fb +SHA1 (NetBSD-6.0/mvmeppc/binary/sets/xfont.tgz) = 4711fcbade0238d60b7b89cf0d7873b03d7ed1f7 +SHA512 (NetBSD-6.0/mvmeppc/binary/sets/xfont.tgz) = c29130f55f536f602253a7f92f073ebf6ba02baea09f8011530bbf7e03ae96594334f0c60b29a8bceaffc3eb8b152db47548e38a3c8a14abc5fe35bc5d1d7d93 +RMD160 (NetBSD-6.0/mvmeppc/binary/sets/xfont.tgz) = 3b01af0f8e34367988d559fe0fbb0acbbafb0b2b +MD5 (NetBSD-6.0/mvmeppc/binary/sets/xfont.tgz) = 6ba15ed12217b726d9129db8e942a048 +SHA1 (NetBSD-6.0/mvmeppc/binary/sets/xserver.tgz) = 05aac7e617e0cac05a88062fef29bb459da7a1d1 +SHA512 (NetBSD-6.0/mvmeppc/binary/sets/xserver.tgz) = 19fb5af5d6afd78839a22e5c0694a492047b5200c569cbf58c676ff32ec250b21edcfe2ed00b65092fdac374d1ab9eaaed6113c69bc03009cf458aedc6014913 +RMD160 (NetBSD-6.0/mvmeppc/binary/sets/xserver.tgz) = 774d2a1072b8d122790ad189a6d2ada2ad99e7cf +MD5 (NetBSD-6.0/mvmeppc/binary/sets/xserver.tgz) = 3daf1477cadf3593e9ba45e3703fe8a5 +SHA1 (NetBSD-6.0/mvmeppc/binary/sets/kern-GENERIC.tgz) = cb6794f87c6c90ffe561a49bb2b3b48a5dacb40a +SHA512 (NetBSD-6.0/mvmeppc/binary/sets/kern-GENERIC.tgz) = 6ee4daa27b1f69c1df2bcfb09ba9efd43a3ffd07e7de964e8f6a59ab46e0f36681a410527be024a58dff6f2efcb8f7a5af5da857fc36cca6d6bb8b71a3fd7c4e +RMD160 (NetBSD-6.0/mvmeppc/binary/sets/kern-GENERIC.tgz) = 809b466fff3437d0e9ef68e9380b08145900b9cb +MD5 (NetBSD-6.0/mvmeppc/binary/sets/kern-GENERIC.tgz) = 21a47714184c5a998e528ceac6d8acb3 +SHA1 (NetBSD-6.0/mvmeppc/binary/sets/base.tgz) = cd5e92a746545a809e765ded7acbaac7de15f633 +SHA512 (NetBSD-6.0/mvmeppc/binary/sets/base.tgz) = ae16a9e58ccadf19e57966b608b0230cdeb066f65997cf36749dd72597ad80741f9a5a8f6f9b49e7ff42fe071c07fbdcc237e076ffd7a9fc4cfe94e9aecae6ef +RMD160 (NetBSD-6.0/mvmeppc/binary/sets/base.tgz) = e8ce9e46b09fea354214094c65f085f963f9fabb +MD5 (NetBSD-6.0/mvmeppc/binary/sets/base.tgz) = 3480b07c4c07ba28b82c27eb4e566b9b +SHA1 (NetBSD-6.0/mvmeppc/binary/sets/comp.tgz) = f8a50dda9bf86a613d543daad62ea5aeb0455af8 +SHA512 (NetBSD-6.0/mvmeppc/binary/sets/comp.tgz) = 5a042383539c5fa72acca742a572cc185f28e2e82f9b0a05af00a57ba3ef220272f4221718cb05322b6010236af0a29254afb0e7716a7bc1543a72bdb7ab2990 +RMD160 (NetBSD-6.0/mvmeppc/binary/sets/comp.tgz) = e13123ebdbe098433cfe3c82ff350ccf23206004 +MD5 (NetBSD-6.0/mvmeppc/binary/sets/comp.tgz) = 93a0b66d03af7b52d9e2394c7fcc93b4 +SHA1 (NetBSD-6.0/mvmeppc/binary/sets/etc.tgz) = 7295ed78597062a35a244940465c2148ba96ccb1 +SHA512 (NetBSD-6.0/mvmeppc/binary/sets/etc.tgz) = 28ab60b5de702a8c4369ef7a04fd88d92a33eb79c3537c7593f1e2c3b16aecfdfb03582daa36dc97d1ab147d0a217a0354906475dae397970b991e39d88905b1 +RMD160 (NetBSD-6.0/mvmeppc/binary/sets/etc.tgz) = 814c4c6297cc41c8961e92e042c1ceea8d0f7bf5 +MD5 (NetBSD-6.0/mvmeppc/binary/sets/etc.tgz) = 9b00467e487f1dc4c8e6e520f531e48b +SHA1 (NetBSD-6.0/mvmeppc/binary/sets/modules.tgz) = 07df9e6517dc7ab1f7b4d89e4c69a0f6ed5e2551 +SHA512 (NetBSD-6.0/mvmeppc/binary/sets/modules.tgz) = bdb4958d494d5cb163ab0c77759fcf2c7c826e4f026d25fd156a19c44dd337064b604d9e5fcfd2bf60140be482cdfce94ce6d382911b813291ba2bf5a0c424cc +RMD160 (NetBSD-6.0/mvmeppc/binary/sets/modules.tgz) = 43473d4d0defd1cff47ee9f1874161538a4b82ac +MD5 (NetBSD-6.0/mvmeppc/binary/sets/modules.tgz) = b73307a25c9030b40171a0360293a564 +SHA1 (NetBSD-6.0/mvmeppc/binary/sets/tests.tgz) = 9b7fcd1db26e218ce61b5325966cbc8fdf647ec7 +SHA512 (NetBSD-6.0/mvmeppc/binary/sets/tests.tgz) = c18be2b0c91b327f620d40c6ee7890dbff28fb4a431f2fec6a870c7542e08a0545c256547371cb2039a8707ae5d5d0a5b876ab209f7ea4f2ec66e4d5f676f05b +RMD160 (NetBSD-6.0/mvmeppc/binary/sets/tests.tgz) = 78c4ec64a4a643c239af74a89cc617bd5e959fa2 +MD5 (NetBSD-6.0/mvmeppc/binary/sets/tests.tgz) = d6e2627f54fc989e87ba95e4243e933e +SHA1 (NetBSD-6.0/mvmeppc/binary/sets/text.tgz) = 0ef97a5332a5c76de8329dd7dd9d97fe8528a83b +SHA512 (NetBSD-6.0/mvmeppc/binary/sets/text.tgz) = b75d8259b2a0886380f796340d08c4f56ab60002e02c04b09665e87e14eed8cddd86ae483c12e236e7589291f579a516dd049be349fd3af7c63f245cd8ddc0a4 +RMD160 (NetBSD-6.0/mvmeppc/binary/sets/text.tgz) = eaad1bf719adc5b5e1645c5fc77be97c1c946ddf +MD5 (NetBSD-6.0/mvmeppc/binary/sets/text.tgz) = 22b500a7593d8b412fc9c000558444a3 +SHA1 (NetBSD-6.0/mvmeppc/binary/sets/xetc.tgz) = 98938e35cc38b7007b05b049e42e888ec0a93860 +SHA512 (NetBSD-6.0/mvmeppc/binary/sets/xetc.tgz) = 0e9027a638278b6102fab31d408f258e8798bfffc6400e99b434656b81bf13053605caa8c3e8d0744685d359261fd8576c267f5eeb987da4c3a054aaf17bb993 +RMD160 (NetBSD-6.0/mvmeppc/binary/sets/xetc.tgz) = f71d30b8062059ead3243e21c732ebca57eb117d +MD5 (NetBSD-6.0/mvmeppc/binary/sets/xetc.tgz) = e09a8d3ed7015c6b274ef5a025041fa2 +SHA1 (NetBSD-6.0/netwinder/binary/kernel/netbsd-GENERIC.gz) = e5f0ce4b52ffef57f8ecc29a7c26ddb9181a5c59 +SHA512 (NetBSD-6.0/netwinder/binary/kernel/netbsd-GENERIC.gz) = e1d81a5be8964559be0b23b0d6a4ca22f95dac64abf4a1ebc7912cbab18f47ee31ab954d85155feb750926267b7b886c1eead88223b16a4c4a363f8286d5110a +RMD160 (NetBSD-6.0/netwinder/binary/kernel/netbsd-GENERIC.gz) = e270203b95b8a0f7736779454b07957e20ccdbbf +MD5 (NetBSD-6.0/netwinder/binary/kernel/netbsd-GENERIC.gz) = 18ec5abd22e842bdc99a66e283e07231 +SHA1 (NetBSD-6.0/netwinder/binary/sets/games.tgz) = e1d2bb091d8202962133475bc83edb55230b9008 +SHA512 (NetBSD-6.0/netwinder/binary/sets/games.tgz) = a147fe6d0419d53d5a428802d0bb6c9fa8a84a76c96d7d6d7c0d399e5af3a69240116463549a83d53387b0214ba0207796d7c10228d92a684fe7ff0ece3aec16 +RMD160 (NetBSD-6.0/netwinder/binary/sets/games.tgz) = 2be515c495548ba5135ff42a75a8ebbfc35ea776 +MD5 (NetBSD-6.0/netwinder/binary/sets/games.tgz) = 9059a6f2cd41cb58827709c9e9a1649b +SHA1 (NetBSD-6.0/netwinder/binary/sets/man.tgz) = 899b9d8242e983a5110ab755651c24f709b5af67 +SHA512 (NetBSD-6.0/netwinder/binary/sets/man.tgz) = 410999db110d710f4bb498c3d7ae7adc62170c7c2f470ce189c92f6c436c5ea96149659c631ef0b5605caaa025d97dfe1c07c428d86f51239657bd6b71717b15 +RMD160 (NetBSD-6.0/netwinder/binary/sets/man.tgz) = c1270f68c6d41b351877f71f0396ac34877dfc8d +MD5 (NetBSD-6.0/netwinder/binary/sets/man.tgz) = df4db2bbfa39ef6a4a215d949653d04a +SHA1 (NetBSD-6.0/netwinder/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/netwinder/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/netwinder/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/netwinder/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/netwinder/binary/sets/kern-GENERIC.tgz) = 3f337b136bc35343128f53eabc787cf5a5a5a6a4 +SHA512 (NetBSD-6.0/netwinder/binary/sets/kern-GENERIC.tgz) = 2243a1cbdf776e683d5cb32b411adddd35e137dec2bea0e9a2d9df17972a8ebea0302328171c8fdd06da240689991c623b07a953cb8e374ace3607c0bbb6c5f7 +RMD160 (NetBSD-6.0/netwinder/binary/sets/kern-GENERIC.tgz) = bb3ef1387ed7dcee67af89f3662f2eb39a23ee7b +MD5 (NetBSD-6.0/netwinder/binary/sets/kern-GENERIC.tgz) = b370234d8f18c218bc78739602325c44 +SHA1 (NetBSD-6.0/netwinder/binary/sets/base.tgz) = feddaeaf51113aca08fb9dd5689745efcd3ea178 +SHA512 (NetBSD-6.0/netwinder/binary/sets/base.tgz) = 1fc5531cf2b47451e0eff63df4222a4e88f7f0112d4f0b2e43009b39dd98a0550f015833d22fb0d7c0ffa9b699944fb72283715f51e5bdae97d263e167b787b4 +RMD160 (NetBSD-6.0/netwinder/binary/sets/base.tgz) = 4e1e7dcd563d7e68d0cfa8824cfa25bffd17187b +MD5 (NetBSD-6.0/netwinder/binary/sets/base.tgz) = b5f660d9a7fe6f6fa951a3a7c3c0f6a5 +SHA1 (NetBSD-6.0/netwinder/binary/sets/comp.tgz) = 06b1e34718e894be491327ee15f5464e91aaac32 +SHA512 (NetBSD-6.0/netwinder/binary/sets/comp.tgz) = 3f6ea371d7852951a374855e3ed4396b683b752aabe0d47e0e6b1d7243b9468023ec6893076a6d77861ccc6f8ff74957bdb4675adc878fcfa620dda04f13d02b +RMD160 (NetBSD-6.0/netwinder/binary/sets/comp.tgz) = 21fb07ace630d66e088ca8fba7f3de545bf75b0c +MD5 (NetBSD-6.0/netwinder/binary/sets/comp.tgz) = 0b21dce21957ca73da5de9ebbeb3a157 +SHA1 (NetBSD-6.0/netwinder/binary/sets/etc.tgz) = 6eb3f0d4ee4b86c87bd03cc4f93958a42e9079f3 +SHA512 (NetBSD-6.0/netwinder/binary/sets/etc.tgz) = 2de4303f21bd502d062486b8789198bbf3e7f5068888d62d4da08e5e51d58f42ede6ea13c8a83bfbc9d0cc64cc6e11d3f2e949a3c2ad800aa78680d4046aa7d1 +RMD160 (NetBSD-6.0/netwinder/binary/sets/etc.tgz) = 3a77fb3f3a4ea25db5b8b450274bade4192541c8 +MD5 (NetBSD-6.0/netwinder/binary/sets/etc.tgz) = f57f45618396a67a169ab7c0e74be2d5 +SHA1 (NetBSD-6.0/netwinder/binary/sets/modules.tgz) = 780745396f7dee2fcce36e4c401f9462ee620e55 +SHA512 (NetBSD-6.0/netwinder/binary/sets/modules.tgz) = 9e4ffad337fd2e30a157ec7ade8f868043addcc2e8020a950cfd8e515d17bccae185b04ff15dfccebce764c1e0a8f1f722bac33e385ae294700dac0b0c3a5792 +RMD160 (NetBSD-6.0/netwinder/binary/sets/modules.tgz) = af686e341bf03f36fc43b5bfa86015e3204803f9 +MD5 (NetBSD-6.0/netwinder/binary/sets/modules.tgz) = eb5745d3d6289ded145654a58bf4a9e0 +SHA1 (NetBSD-6.0/netwinder/binary/sets/tests.tgz) = 46a999d0afcee9103c765b57765971557cffb18d +SHA512 (NetBSD-6.0/netwinder/binary/sets/tests.tgz) = 0937f49f33fd690da609dff62adf04978e1ca36e61e3357e360e3ca622e406758a12e5909fa0aa431f914eb145625cc7dc3dc1caf09bf2793feec7db45cba00a +RMD160 (NetBSD-6.0/netwinder/binary/sets/tests.tgz) = 7d070858cc4bdbbee9bd6568acf73cc9b70147b0 +MD5 (NetBSD-6.0/netwinder/binary/sets/tests.tgz) = 879591282409cebe2b0c397f9c05f417 +SHA1 (NetBSD-6.0/netwinder/binary/sets/text.tgz) = bc73c2b37be55d902c10db2244412f884dcb2c49 +SHA512 (NetBSD-6.0/netwinder/binary/sets/text.tgz) = cbf470fcdd95eb9bf94d5296d7d728eb537a243ed03448e134e56c6714c6528968d217c69e3ac830045f2b8b5c8c4df451fd24ff2b5b176d37fcd84ca1f07f92 +RMD160 (NetBSD-6.0/netwinder/binary/sets/text.tgz) = 00aeff72db0b05b48fa40bf80b1e24c5a667fd0f +MD5 (NetBSD-6.0/netwinder/binary/sets/text.tgz) = 42470e4348951037fd056476c26dbb77 +SHA1 (NetBSD-6.0/netwinder/binary/sets/xbase.tgz) = 66d3e62a116c56bfaac8ee3257ba675a845b9ab3 +SHA512 (NetBSD-6.0/netwinder/binary/sets/xbase.tgz) = bfc8c00cfc6bf2fcb3d26ff9abb9e6091c5389aeac5370ae475b3c74569e3ccf05494e363544d6c805820e2c7554a1fea936abab6e3212dd4710e2463625006a +RMD160 (NetBSD-6.0/netwinder/binary/sets/xbase.tgz) = 26ff99801c9a84190cca4292c137c17305bec08c +MD5 (NetBSD-6.0/netwinder/binary/sets/xbase.tgz) = 532381165745c160613ef72bcd7e7848 +SHA1 (NetBSD-6.0/netwinder/binary/sets/xcomp.tgz) = 0eed09b5c7a6e8d76c99ddaa31029f414a14d6bd +SHA512 (NetBSD-6.0/netwinder/binary/sets/xcomp.tgz) = b03064377958f9ca9252e83d2933574a5f0fedc89ac864641340f8e50a6d5fa1a074d45a80f0dcb1567ef7d23eb2bc4bec3de866c2d07912ab4122acaf062c35 +RMD160 (NetBSD-6.0/netwinder/binary/sets/xcomp.tgz) = f7a208a7ac2137d4940ec2f78c0658e630ea329e +MD5 (NetBSD-6.0/netwinder/binary/sets/xcomp.tgz) = fa248543b87b553473cc67fd45e385ae +SHA1 (NetBSD-6.0/netwinder/binary/sets/xetc.tgz) = 4e2fdc95511cd90317da41fb941f7ec6f622b84e +SHA512 (NetBSD-6.0/netwinder/binary/sets/xetc.tgz) = 57a60f983fadbdb0a0ef5720c2bda405d4052d460f67976e71a34ad016d25357cd04fbdf48e866c3641dcabc55194a683931a0b36c7f55549a7998c31e42ef88 +RMD160 (NetBSD-6.0/netwinder/binary/sets/xetc.tgz) = fef501d07dce370292072f65ed25dd32df41bfcb +MD5 (NetBSD-6.0/netwinder/binary/sets/xetc.tgz) = efdbfcb8e6fbf0c4cb2094e749c54b1a +SHA1 (NetBSD-6.0/netwinder/binary/sets/xfont.tgz) = b92ebefbcc4a96bdbba5540df3119bed0ee2efdf +SHA512 (NetBSD-6.0/netwinder/binary/sets/xfont.tgz) = 605e099b75b0133d811b12387461856bcf7ef7cc0dddc68490eb6ef51ba284ac2edafcc757feb0665618b119eacd2509c302f42736eb0d582ab7f17f5fdb1b23 +RMD160 (NetBSD-6.0/netwinder/binary/sets/xfont.tgz) = 084a5e8e5f95debf53ba5be9e52230fe72dbb2d0 +MD5 (NetBSD-6.0/netwinder/binary/sets/xfont.tgz) = 02b5344f23cdb9eb4d9cbe8b30c7707e +SHA1 (NetBSD-6.0/netwinder/binary/sets/xserver.tgz) = 570bbfb56fda998c07f8414731eaf79af5b01bd1 +SHA512 (NetBSD-6.0/netwinder/binary/sets/xserver.tgz) = b70eccc78ca3e290869502760fcc8a8378db3d49c402f075e2f12e1453a7fbb68911df18993c0966ce840b837225d577344ec7088d2aea5eac78130e9dcce0ec +RMD160 (NetBSD-6.0/netwinder/binary/sets/xserver.tgz) = 5b7c5740805aebc0ea76f778b429803b25cf9128 +MD5 (NetBSD-6.0/netwinder/binary/sets/xserver.tgz) = d866ffe531725f8c18bd3f88129d09db +SHA1 (NetBSD-6.0/news68k/binary/kernel/netbsd-GENERIC_TINY.gz) = c260c1b8e7017de3a9c7383ebad6833c172b745c +SHA512 (NetBSD-6.0/news68k/binary/kernel/netbsd-GENERIC_TINY.gz) = da338bee7bcaf58401ea3fa629c91fc5732016581d869f2bb8897f252c90e296773eaf35dae48667a753e7119340ac376fff713f3f87e25802fb3874879fcc65 +RMD160 (NetBSD-6.0/news68k/binary/kernel/netbsd-GENERIC_TINY.gz) = 25e70f61645eea330feda79fa0e6302bedeecdc3 +MD5 (NetBSD-6.0/news68k/binary/kernel/netbsd-GENERIC_TINY.gz) = df5ca7bb950327f08e460757a4b03de4 +SHA1 (NetBSD-6.0/news68k/binary/kernel/netbsd-GENERIC.gz) = 96c08009db46bd9bf3e0b1b0b8ea6b96b7772396 +SHA512 (NetBSD-6.0/news68k/binary/kernel/netbsd-GENERIC.gz) = 635ef8e6ee4c767afba768a982f587d6040afeb15585be8a8fcfd44e75bcd9031f8965f1bef2b7fdb955b81b2e09f0dc6a51618b48827898763cd75310669a6b +RMD160 (NetBSD-6.0/news68k/binary/kernel/netbsd-GENERIC.gz) = b9a864c14cc967d2336473c2c2c19eeeefa5b3ec +MD5 (NetBSD-6.0/news68k/binary/kernel/netbsd-GENERIC.gz) = 76b1a1ad9865766e5d7b1ceb1d374f26 +SHA1 (NetBSD-6.0/news68k/binary/kernel/netbsd-INSTALL.symbols.gz) = 620ddb95366fb58c53d115681a205d73fb79bf02 +SHA512 (NetBSD-6.0/news68k/binary/kernel/netbsd-INSTALL.symbols.gz) = 4eb494f02f39ee17205b28f07993fd1c9bbb872f2617aacdb173f9b458603fe284dedcde279eb0b9ffe083b01f485dc04963ec09117c31927e3e97a9b5441f6f +RMD160 (NetBSD-6.0/news68k/binary/kernel/netbsd-INSTALL.symbols.gz) = 3456f6c84edd59e0e1db531ec40b838fdd076d14 +MD5 (NetBSD-6.0/news68k/binary/kernel/netbsd-INSTALL.symbols.gz) = 0898606b528a29a5c2c754d365e1fb22 +SHA1 (NetBSD-6.0/news68k/binary/kernel/netbsd-INSTALL.gz) = 76b25bf6b038d7c48a55bf1f1df350717707af3f +SHA512 (NetBSD-6.0/news68k/binary/kernel/netbsd-INSTALL.gz) = 7aadf02eb4862fc3cf8a0099673414092e8a113e59dfcfda713e430422cc8f03fd4a711ec767b10905ac5feeb6823054e372da6da4f19e15c595712a75dff046 +RMD160 (NetBSD-6.0/news68k/binary/kernel/netbsd-INSTALL.gz) = 4e01f28fc0dd67b8a2b16ac61c27adf4ec83c7e7 +MD5 (NetBSD-6.0/news68k/binary/kernel/netbsd-INSTALL.gz) = 7ecaba69661efb53aea818bfc0df2870 +SHA1 (NetBSD-6.0/news68k/binary/sets/games.tgz) = 16ee93ea4d5fac2fb28fad5c32c8a3d57d011d79 +SHA512 (NetBSD-6.0/news68k/binary/sets/games.tgz) = a7f49ab72f50273f66c8dcf408b57ec4668debd5537c5bd0ec59aa0f4fa1d599ba0798d1b283315c4208cbcb608925808ce003b1ade79034886edb8208f9f48d +RMD160 (NetBSD-6.0/news68k/binary/sets/games.tgz) = 1e09d99d7fe2e495763f05919472d27a4ba699df +MD5 (NetBSD-6.0/news68k/binary/sets/games.tgz) = 8a26f3e864444209088bccf21419a616 +SHA1 (NetBSD-6.0/news68k/binary/sets/man.tgz) = 899b9d8242e983a5110ab755651c24f709b5af67 +SHA512 (NetBSD-6.0/news68k/binary/sets/man.tgz) = 410999db110d710f4bb498c3d7ae7adc62170c7c2f470ce189c92f6c436c5ea96149659c631ef0b5605caaa025d97dfe1c07c428d86f51239657bd6b71717b15 +RMD160 (NetBSD-6.0/news68k/binary/sets/man.tgz) = c1270f68c6d41b351877f71f0396ac34877dfc8d +MD5 (NetBSD-6.0/news68k/binary/sets/man.tgz) = df4db2bbfa39ef6a4a215d949653d04a +SHA1 (NetBSD-6.0/news68k/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/news68k/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/news68k/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/news68k/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/news68k/binary/sets/xserver.tgz) = 1d20fd039546a66b428b854c659ea5e2ee9f8114 +SHA512 (NetBSD-6.0/news68k/binary/sets/xserver.tgz) = 091d09049d0af5555feec02065234e281677aeb3ecbab5a19413d924a8b58dc7f64401ef68e68bc52d8b6eeb73e091d351c45805374b8bf276b0181415968561 +RMD160 (NetBSD-6.0/news68k/binary/sets/xserver.tgz) = feef5d52278d23637d7b8ba77639bfd96918e90e +MD5 (NetBSD-6.0/news68k/binary/sets/xserver.tgz) = b2bd6057c374376388766fc8667eb9a9 +SHA1 (NetBSD-6.0/news68k/binary/sets/kern-GENERIC.tgz) = 6d14a82918f258c781499c87f7ef23fca3c85c68 +SHA512 (NetBSD-6.0/news68k/binary/sets/kern-GENERIC.tgz) = ed399e3bab46335dc4d2bb1f2971692d8a1d8aa22c4196bb340e005c951a3941517d64de8be8c8047a60de791ae934197b38fe02706bcde080f4062a5ffbf431 +RMD160 (NetBSD-6.0/news68k/binary/sets/kern-GENERIC.tgz) = 74c42f841cfb865522b4eda052f46a7b13e491d0 +MD5 (NetBSD-6.0/news68k/binary/sets/kern-GENERIC.tgz) = 6ac0ec8267f457a0d94feba55a094773 +SHA1 (NetBSD-6.0/news68k/binary/sets/base.tgz) = 14763cf9124eb67c9440727bf0559d98d9aa4765 +SHA512 (NetBSD-6.0/news68k/binary/sets/base.tgz) = 24bf851943de08a6e5cb869a69d8d4350f6d6c64988741dbb8691afb927fa8ccb922a7e608da48ef52913796c0e6172c8302b22248c64ce576446d26f26add71 +RMD160 (NetBSD-6.0/news68k/binary/sets/base.tgz) = fc4ad357c41d200d8e12444d1f4e13956521a4d5 +MD5 (NetBSD-6.0/news68k/binary/sets/base.tgz) = 5401468976f41209a9a28889d85f52be +SHA1 (NetBSD-6.0/news68k/binary/sets/comp.tgz) = 6b20fee4bcb085b5b09893416ce5eee6a96ca5bd +SHA512 (NetBSD-6.0/news68k/binary/sets/comp.tgz) = 3550045bb700ea29604590e25cd9e6305459476a837f67b4d746e62ce0facc8218aca1d03f2dd570e2590802f32079e438ad4e977a96f9a8939dd986d725d898 +RMD160 (NetBSD-6.0/news68k/binary/sets/comp.tgz) = 85fb356111807dbc811b8fe2fb3d294e4544b358 +MD5 (NetBSD-6.0/news68k/binary/sets/comp.tgz) = 223302daf2a8f7f52863763374438b3e +SHA1 (NetBSD-6.0/news68k/binary/sets/etc.tgz) = 575f76fc225f509cec73dbc1e6a213d4370c221f +SHA512 (NetBSD-6.0/news68k/binary/sets/etc.tgz) = 4705c91993153a30b1bf6bab9f1d0b75d9bc29ccbd698d26c44ae70fadeb4a8390298eb1e0e590f0da62748d9429e8e5927558a31d2efe0ef068a9ca353681b4 +RMD160 (NetBSD-6.0/news68k/binary/sets/etc.tgz) = 7ce6e09c062f61b659f2c16138516b3629c010bf +MD5 (NetBSD-6.0/news68k/binary/sets/etc.tgz) = 234be1ba6587866294eb09b75439840b +SHA1 (NetBSD-6.0/news68k/binary/sets/kern-GENERIC_TINY.tgz) = 119015b6a9a67300144e248352a3842857ba86e9 +SHA512 (NetBSD-6.0/news68k/binary/sets/kern-GENERIC_TINY.tgz) = 2eecd5ff4fd2a1ca0edc61ff92c804f5202ffedc5b6e74c5c0be372f74cf533e4b4f1b6a69625a155a33661185e1a56943947ab1c98fa8b4dc3892526781950a +RMD160 (NetBSD-6.0/news68k/binary/sets/kern-GENERIC_TINY.tgz) = 5477d4127ff479fa19aa58a3de57bbd3a4cc0b90 +MD5 (NetBSD-6.0/news68k/binary/sets/kern-GENERIC_TINY.tgz) = fd4f85a1589e4907b314ae996b3aa08a +SHA1 (NetBSD-6.0/news68k/binary/sets/modules.tgz) = 1885df3fb4ea56feab816bd8dc5e0dc08fae234b +SHA512 (NetBSD-6.0/news68k/binary/sets/modules.tgz) = beeb1e94ef6f34b7525c0c2de9bfe9927aa443bfdc5be8c4a5546a27483c0ca45006d3f546d93bc0036f25804e7827ea1b8fd943e7642bc73c4b6c75710362ed +RMD160 (NetBSD-6.0/news68k/binary/sets/modules.tgz) = e3ed23f75e48c70efbdf3b5ec9c28ec41886d878 +MD5 (NetBSD-6.0/news68k/binary/sets/modules.tgz) = e4db103ff1b7f68a57e8fe813b2b8d3c +SHA1 (NetBSD-6.0/news68k/binary/sets/tests.tgz) = 984686c1f0ad93ff8200e810482527b87bad3de3 +SHA512 (NetBSD-6.0/news68k/binary/sets/tests.tgz) = 508704556a3bc66c9f5f88a6377d34d81edf9aaace78a4496c550021dd5a88c2ff85d5663ff2aa42c4e7a74721249b2dddabd50bf597572b016794c42d22a622 +RMD160 (NetBSD-6.0/news68k/binary/sets/tests.tgz) = 06cb486210f5e4ef2ec33d863cf995780caa24df +MD5 (NetBSD-6.0/news68k/binary/sets/tests.tgz) = 60053afffd0ad1c95c2654ce6a991d21 +SHA1 (NetBSD-6.0/news68k/binary/sets/text.tgz) = edd7603519c0dbdddbe9b9c8d9ddf066d62ee617 +SHA512 (NetBSD-6.0/news68k/binary/sets/text.tgz) = b5c7ca241708d02df4df5a6bf43b6329cdb063a922bdf23955b3807cf813d10718cdd1a7a4c3167e0869d5f8f0a742ee275951a72fa2cbfbd32a0afa37d3e49e +RMD160 (NetBSD-6.0/news68k/binary/sets/text.tgz) = c54012faa763171bbd263ba23d4d2495e7cf2762 +MD5 (NetBSD-6.0/news68k/binary/sets/text.tgz) = 2088a3dfd39fd763db42fe375a460a3e +SHA1 (NetBSD-6.0/news68k/binary/sets/xbase.tgz) = 9b8940f65ca6a841b84406a22a13971665edc464 +SHA512 (NetBSD-6.0/news68k/binary/sets/xbase.tgz) = 4a7d78ad9cf1b84c183fc731bac2fce861f94bc26c7a1681ab1d62a9b761ba89538469688b24588f6c671503a1b66a1e521c2eeef2fd528d21dc0351272e56e8 +RMD160 (NetBSD-6.0/news68k/binary/sets/xbase.tgz) = 85735e089a6ac5293e7438a609dd11105cd4eb25 +MD5 (NetBSD-6.0/news68k/binary/sets/xbase.tgz) = b6f52c8fde2fb1a5372a12d2f321e9c5 +SHA1 (NetBSD-6.0/news68k/binary/sets/xcomp.tgz) = 63a79437c028936698509a386963708082356d29 +SHA512 (NetBSD-6.0/news68k/binary/sets/xcomp.tgz) = 25791832de667b9a44f341f7267f09aaa6b9a4216452ceaab8b56dc6ea5fca3be2da53868b624f47a275edf19ada59dfed40e355e2ff1f62ab96bb54448c1e00 +RMD160 (NetBSD-6.0/news68k/binary/sets/xcomp.tgz) = e681ae34bd83be8dbb6945cef3a129bc1538b66a +MD5 (NetBSD-6.0/news68k/binary/sets/xcomp.tgz) = c87752020f2ad29a80262eae4bbeaece +SHA1 (NetBSD-6.0/news68k/binary/sets/xetc.tgz) = 76661bc6d6851cb2ae57f3a7f25f816a33360a2b +SHA512 (NetBSD-6.0/news68k/binary/sets/xetc.tgz) = a1994fbd97492275e9128c5fc764dc7cf5539bee26bb9d13d9f3fcc14429858e794ed8a10554570c4f70b87714f8b0ab23269ebbaf44d4fb95d0901dcc28fe81 +RMD160 (NetBSD-6.0/news68k/binary/sets/xetc.tgz) = f9f8fc83764439a533110c614e1ef19ffe98361a +MD5 (NetBSD-6.0/news68k/binary/sets/xetc.tgz) = ab945fe1f43ea47433a047babda53a81 +SHA1 (NetBSD-6.0/news68k/binary/sets/xfont.tgz) = 4403bc158b92ded3d27646c6c0858aa6c117cb8d +SHA512 (NetBSD-6.0/news68k/binary/sets/xfont.tgz) = 79e31eee0397803ec17a9413b50a5d501fbc3515e4080a0e9e053498c64557809cddfd5718f131d3c451a231c4a38ff4f40b50ef401af5c204a68b61df8f8ba7 +RMD160 (NetBSD-6.0/news68k/binary/sets/xfont.tgz) = b7e19b89a1f67382428aeaf248710dade3b0672e +MD5 (NetBSD-6.0/news68k/binary/sets/xfont.tgz) = 8a1f532d7a481f797deb226b66d15ceb +SHA1 (NetBSD-6.0/news68k/installation/floppy/boot.fs) = baea772f5bf7116b8c489a2e75f77c98e308ac5f +SHA512 (NetBSD-6.0/news68k/installation/floppy/boot.fs) = be4dbd6dc24f56ac71f96d60b8ed0e6b4f725bae2b9d39ef1b9e5ea5fe71053f5fea04979676ff13a50685bcbce539bbc93631408c56d29a2924c79370ded347 +RMD160 (NetBSD-6.0/news68k/installation/floppy/boot.fs) = ff9f3a85babe4d597e2ccb4a864eb0c611a7894f +MD5 (NetBSD-6.0/news68k/installation/floppy/boot.fs) = 98f566671f6dd720fb61e8c657bd93e8 +SHA1 (NetBSD-6.0/news68k/INSTALL.html) = 8d9ab316296bfbb751b0a05557f4648ff2990af0 +SHA512 (NetBSD-6.0/news68k/INSTALL.html) = 5916c04ef717b2e47ee36f93a1e3a43a27215b5c688b36520e0f160bda3816d6e4645e2e9e922d564260e8b8a60e46da67fbd3b443832032a66e76153596c4eb +RMD160 (NetBSD-6.0/news68k/INSTALL.html) = a07fa866614d3f5ecfb5642eeb354b6b9c675318 +MD5 (NetBSD-6.0/news68k/INSTALL.html) = 89f43b16d907873c28b8b7b6ab8cb4a9 +SHA1 (NetBSD-6.0/news68k/INSTALL.more) = db7d9b68680f5c20b525bf253e342f2775d04a71 +SHA512 (NetBSD-6.0/news68k/INSTALL.more) = ab50b18effb102ac017c0cad2c054dffe8ccec3876ff9cc6a0353762b5a2b11651296f05b3cf3da76cbb10a4561bc529b5cf113141c742a96fdb73a5358e129c +RMD160 (NetBSD-6.0/news68k/INSTALL.more) = d6aacc53d5c3384704e2ff1f64a4eb9fd474effe +MD5 (NetBSD-6.0/news68k/INSTALL.more) = 4c22b00a52d8ad3cdb12f66d23a069a9 +SHA1 (NetBSD-6.0/news68k/INSTALL.ps) = 021d67431fbc7f9fd378e496c25c28097b72af46 +SHA512 (NetBSD-6.0/news68k/INSTALL.ps) = 224e78f8ddc0149a710511083c55a69e1eb2f37089ad15ce1fbc1c07733055eb5b34ad4c32b2803d1f3050b1c5a038ef1d429af780c0a57c8a4b41fde8d10413 +RMD160 (NetBSD-6.0/news68k/INSTALL.ps) = 86b953fd3860caadf7a681e0d75486cb2ac453d2 +MD5 (NetBSD-6.0/news68k/INSTALL.ps) = 4f2098f135e2d4f945dd6365a55b7bc2 +SHA1 (NetBSD-6.0/news68k/INSTALL.txt) = 1491600e777e5a7a96cc05a7fc5a0ab0edf2072f +SHA512 (NetBSD-6.0/news68k/INSTALL.txt) = 0552976751403a424febde147bdbf34b7e589c0f27225072c9691e30f630e1f49be93c9e75ebbc7d0c6d06ab78419506d4c4313059023e9ae13dbd8d1f5c4445 +RMD160 (NetBSD-6.0/news68k/INSTALL.txt) = 2c6df35393c4ee9d9fb7dcb58002f996c587c32a +MD5 (NetBSD-6.0/news68k/INSTALL.txt) = 9cff69046f721931b5b5ef4bd511d12c +SHA1 (NetBSD-6.0/newsmips/binary/kernel/netbsd-INSTALL.symbols.gz) = 0e0add1125bb456d3210efa5035169e1bd7ae98a +SHA512 (NetBSD-6.0/newsmips/binary/kernel/netbsd-INSTALL.symbols.gz) = 138e28fb744019ee2e89cb8ef1f3e23b5fd296b2f8c12a26245cef11aef9540f12eb2c180e5847d047d74d593e62916694c7f031fda0e3477e42ecdb79da7510 +RMD160 (NetBSD-6.0/newsmips/binary/kernel/netbsd-INSTALL.symbols.gz) = 4ee95362c6f9e38a32cd9e0fe36cdc3aadb91291 +MD5 (NetBSD-6.0/newsmips/binary/kernel/netbsd-INSTALL.symbols.gz) = 0d8837629ba02a89e50b6764649d03a2 +SHA1 (NetBSD-6.0/newsmips/binary/kernel/netbsd-GENERIC.gz) = decd427b7283d775b0356186a50720409c1c2ecf +SHA512 (NetBSD-6.0/newsmips/binary/kernel/netbsd-GENERIC.gz) = 05df61671fb365dba6ee67d097f5e51b372720a260b0dd05913a4cf283f323836aa7b157d88eaa68e4cdfa2a7180e57e3ba8ee3cd538dffe4a6afadc1ce880c9 +RMD160 (NetBSD-6.0/newsmips/binary/kernel/netbsd-GENERIC.gz) = e997c6efa2aacfb924670a53162157c8fbd93bdd +MD5 (NetBSD-6.0/newsmips/binary/kernel/netbsd-GENERIC.gz) = 1b105c1608405606b59942471102880a +SHA1 (NetBSD-6.0/newsmips/binary/kernel/netbsd-INSTALL.gz) = 42aeaa1b3dd454b7ac007db9ac4f9b43ca2bd52f +SHA512 (NetBSD-6.0/newsmips/binary/kernel/netbsd-INSTALL.gz) = f4262b07a27e2166082ed9cd4b0a247fcbd65f3aebc1c1f8e502f5fc931e130627b0906c92263d2f748d3d30d482391c6b72637c29812f98aaed2fd85830cfdf +RMD160 (NetBSD-6.0/newsmips/binary/kernel/netbsd-INSTALL.gz) = ab7e5e64d2b4761006e95f8d1605d767f6ace146 +MD5 (NetBSD-6.0/newsmips/binary/kernel/netbsd-INSTALL.gz) = e23868785597388ddbae56348a08d9d7 +SHA1 (NetBSD-6.0/newsmips/binary/sets/games.tgz) = f56d3e5181634f6a3d7908dcb002ebcb1c5aaff0 +SHA512 (NetBSD-6.0/newsmips/binary/sets/games.tgz) = 0cff50ea13e34fe338edf70da6a28af061580feb4cb0773828adefa631ebd471a96568a3b30ea0f13f3bb116856a1b6aad8a5a52443346f52e4907f4caabc5f1 +RMD160 (NetBSD-6.0/newsmips/binary/sets/games.tgz) = 1538910578dbb8eee2931200fac0ccda44758e5f +MD5 (NetBSD-6.0/newsmips/binary/sets/games.tgz) = 2bd5bd0ce72df5cf92767b8c3f7cc208 +SHA1 (NetBSD-6.0/newsmips/binary/sets/man.tgz) = 899b9d8242e983a5110ab755651c24f709b5af67 +SHA512 (NetBSD-6.0/newsmips/binary/sets/man.tgz) = 410999db110d710f4bb498c3d7ae7adc62170c7c2f470ce189c92f6c436c5ea96149659c631ef0b5605caaa025d97dfe1c07c428d86f51239657bd6b71717b15 +RMD160 (NetBSD-6.0/newsmips/binary/sets/man.tgz) = c1270f68c6d41b351877f71f0396ac34877dfc8d +MD5 (NetBSD-6.0/newsmips/binary/sets/man.tgz) = df4db2bbfa39ef6a4a215d949653d04a +SHA1 (NetBSD-6.0/newsmips/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/newsmips/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/newsmips/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/newsmips/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/newsmips/binary/sets/kern-GENERIC.tgz) = 7b98d2f4f3acbf629e953e6b694d8f4755b8e8bd +SHA512 (NetBSD-6.0/newsmips/binary/sets/kern-GENERIC.tgz) = 5d7e2e9bce3611aee142686bab7a69abc59ddb5e1308694cc88e63645d3b411013765ffa5198cbb44fa445ae258f85cfae976c239875ea26ac4d0439cb497746 +RMD160 (NetBSD-6.0/newsmips/binary/sets/kern-GENERIC.tgz) = 849d144d0090f36a2d013a9f85c9b4c472c595df +MD5 (NetBSD-6.0/newsmips/binary/sets/kern-GENERIC.tgz) = 40ecc8186e3d4328e24ef91e817c5a4e +SHA1 (NetBSD-6.0/newsmips/binary/sets/base.tgz) = c229edbeb3438aa2444933af1633c73b66f23748 +SHA512 (NetBSD-6.0/newsmips/binary/sets/base.tgz) = 8ce8dce68f07ee529d0f079794502bd225475cabe7f0dd351caf01b5acf8a34d5f865eea046c06998db53a2cb23c7c36764314493d537ecad8e69c5908a07dbe +RMD160 (NetBSD-6.0/newsmips/binary/sets/base.tgz) = 6d2365c6adbf64a1b6655c7341a7fa1756878e93 +MD5 (NetBSD-6.0/newsmips/binary/sets/base.tgz) = 650ad75dc13c5edd48f4d8a58759375e +SHA1 (NetBSD-6.0/newsmips/binary/sets/comp.tgz) = d6ce335f1f52b3d77282e7c08c3781202018257f +SHA512 (NetBSD-6.0/newsmips/binary/sets/comp.tgz) = 4c8cac5f9fff3b5334083d5df788b0967f62817e797206393f6b83a9cbb0b78c151408440045b92bc50ac2540e0b5d38ea854f29b6af69c1043952d472cf0a85 +RMD160 (NetBSD-6.0/newsmips/binary/sets/comp.tgz) = 7985588ccbaf837e8fd044a0ea7064aa023245c4 +MD5 (NetBSD-6.0/newsmips/binary/sets/comp.tgz) = ac02ccf4b35b94d87960214974f909ba +SHA1 (NetBSD-6.0/newsmips/binary/sets/etc.tgz) = 1744b2b2050df7622a70aec4c4ab39ff4766b598 +SHA512 (NetBSD-6.0/newsmips/binary/sets/etc.tgz) = 933f4b9af8a1f5033c88ecb680c70b258b36267cbd3d8804aa7d2c0ce797f272a4ffc7266bb369505635e0e0ce0efef285d8fa26704ba28690f1dc6db810c42e +RMD160 (NetBSD-6.0/newsmips/binary/sets/etc.tgz) = c41f76161f0a9ada7ee8cad68d5311f70051c08e +MD5 (NetBSD-6.0/newsmips/binary/sets/etc.tgz) = adb5f50f9862a06a123d1d848dbeaef0 +SHA1 (NetBSD-6.0/newsmips/binary/sets/modules.tgz) = 494b6a3b255bace06cfee70f87d2ac213b190a5f +SHA512 (NetBSD-6.0/newsmips/binary/sets/modules.tgz) = c8274f58ae9d514e72f8d82e46599c655e1b959b744e73340a6a106dce528f83687b7bd7f8e769eab60294e6962a7bc5e0d7173330710ee381219ca6f87b51c7 +RMD160 (NetBSD-6.0/newsmips/binary/sets/modules.tgz) = 3536ddd91df0d4d53e6da53bf30548ac60062349 +MD5 (NetBSD-6.0/newsmips/binary/sets/modules.tgz) = 4cefc39360426c683af0c3031403bd54 +SHA1 (NetBSD-6.0/newsmips/binary/sets/tests.tgz) = 8c653879bccb5f7b67536fb96f92fa52cf11e69f +SHA512 (NetBSD-6.0/newsmips/binary/sets/tests.tgz) = 5cc47261708222b4fe1ca43d1dc014909df674db2c477c9d814e2af319e2c21c66555df78786ec48c08b21c4c8c1ddc8d815967ffaaceb625f61687df9ac46b1 +RMD160 (NetBSD-6.0/newsmips/binary/sets/tests.tgz) = 8712fce841356834ff6036bdcfe58dbb391ffd4e +MD5 (NetBSD-6.0/newsmips/binary/sets/tests.tgz) = ccc445c6ba7fc49d4de4b0dcb26aefff +SHA1 (NetBSD-6.0/newsmips/binary/sets/text.tgz) = 766d9d6d34c79c7be29da59f543f6e029090ecff +SHA512 (NetBSD-6.0/newsmips/binary/sets/text.tgz) = d11a630ead4cf249224c0f887cf6c2ef347983e885f5657c44cc988733880ccfee735f36dd5558ca60ffffb5ea8dab042d016d3824d8e9116cda749516508624 +RMD160 (NetBSD-6.0/newsmips/binary/sets/text.tgz) = 53cfd7b3389f1b71430daad46ff3be2c692690a3 +MD5 (NetBSD-6.0/newsmips/binary/sets/text.tgz) = f0692f4de9721110ecf0e1ecac4bf1d9 +SHA1 (NetBSD-6.0/newsmips/binary/sets/xbase.tgz) = 19fb5f83a2ef362388d812fbe3c4ccad858dd191 +SHA512 (NetBSD-6.0/newsmips/binary/sets/xbase.tgz) = 4774d680e11097be0f6d8b9cdd2a296cfceefdf1c19d0e8188c742efb2603b253b46c2d01084c6bd5470e34ecc6dd81f502a97c9c69e02b9aca1af80f9d3bafb +RMD160 (NetBSD-6.0/newsmips/binary/sets/xbase.tgz) = b52fbd33962b06618a8334439f89a7114cb762a5 +MD5 (NetBSD-6.0/newsmips/binary/sets/xbase.tgz) = d9c670a2392dd2f58f041b18ecd32be6 +SHA1 (NetBSD-6.0/newsmips/binary/sets/xcomp.tgz) = e99076dd0244130e9ae9ac14533df11f058aab3c +SHA512 (NetBSD-6.0/newsmips/binary/sets/xcomp.tgz) = 2869e7c2d397772612ce36217da0c8f7ab0ed5b18694d0620e789854dcd2fbc6763dab632614cb9df7be4c7697065db5f68e9e400fc2068a03e38d98709399b7 +RMD160 (NetBSD-6.0/newsmips/binary/sets/xcomp.tgz) = af2372e9b8ba4ed8a4d8f951b9570e411be2dcf8 +MD5 (NetBSD-6.0/newsmips/binary/sets/xcomp.tgz) = cb05a7f616ecaa766d696b7ab5d9120e +SHA1 (NetBSD-6.0/newsmips/binary/sets/xetc.tgz) = 973a0c9b770b14e156ea2d999b0c155f8675e95f +SHA512 (NetBSD-6.0/newsmips/binary/sets/xetc.tgz) = 4298ae57e88d6a5853a8832cf06c6d294051708ffaff6e2fa28efd06c2a8cf99274f5d1be0bff31248d3d9d9ee7bcb2738fcc9b5a4f55a2f34246cf5e1bd3546 +RMD160 (NetBSD-6.0/newsmips/binary/sets/xetc.tgz) = 4b9023581af4b378be8ce78fa812c832dae9f682 +MD5 (NetBSD-6.0/newsmips/binary/sets/xetc.tgz) = 8eee7c09a6b78148e9b1260abee79e53 +SHA1 (NetBSD-6.0/newsmips/binary/sets/xfont.tgz) = 389d0d14a3b5ebbdf3f49b0c5bca3efcf7155a42 +SHA512 (NetBSD-6.0/newsmips/binary/sets/xfont.tgz) = e246f6527bb91eecd3190cd9eb82157db0a0d868f95acd47bb292caea573405170156e37dfb50d3ec97b00ac7c50cf0893640945575638bd9f958cfbece4bd72 +RMD160 (NetBSD-6.0/newsmips/binary/sets/xfont.tgz) = eab3db1a489e432867ce806385ed12e1b25165ff +MD5 (NetBSD-6.0/newsmips/binary/sets/xfont.tgz) = 4030cc9fd13f8d3524a8c161715edc6b +SHA1 (NetBSD-6.0/newsmips/binary/sets/xserver.tgz) = 2e0e1a1280e01a64615430396697d3a4cc4aabee +SHA512 (NetBSD-6.0/newsmips/binary/sets/xserver.tgz) = e5c9d65657227d24b52db9d109c9a4993c5962c3f8171b1353709464a0ba18c99264bf3cd8dc53478692cf2a297f36bccf15519f1aa198cf1a6392e3557914da +RMD160 (NetBSD-6.0/newsmips/binary/sets/xserver.tgz) = 82a04ae9c10abf44d00acaa3f97f99150e7dc607 +MD5 (NetBSD-6.0/newsmips/binary/sets/xserver.tgz) = 9f3edc37a2f786ee70d5f0e100105971 +SHA1 (NetBSD-6.0/newsmips/installation/floppy/boot1.fs) = d55e9f59aac50a141dbec353c4bc9586faa8d00d +SHA512 (NetBSD-6.0/newsmips/installation/floppy/boot1.fs) = 659476e61e29371975130565ae2e343ad3bc9423a910ef0b08cffe41e87179020c5b2f42f98d351c9957655b67ded13cf6111835e441d2ddd39584bc1a57c7ba +RMD160 (NetBSD-6.0/newsmips/installation/floppy/boot1.fs) = f3becca1f4c20eadf3e77ff4bcb84990a9e543f6 +MD5 (NetBSD-6.0/newsmips/installation/floppy/boot1.fs) = 992e9d201b2a7183a6f8725486e8f2d0 +SHA1 (NetBSD-6.0/newsmips/installation/floppy/boot2.fs) = 2c228b57a187bbfae507d67aae5d0faef2f308ea +SHA512 (NetBSD-6.0/newsmips/installation/floppy/boot2.fs) = 72c6b63777f2171c852f15cfd2c04fd9b21a9cfc423542d0127012be6d5ca85ad15bb33a67b1fb28e1f07f2652f94ae2d2f0c0641c6e860c0ed50d9556eacc59 +RMD160 (NetBSD-6.0/newsmips/installation/floppy/boot2.fs) = 495d95dd6cdcbf0a0cdb07fb8500738e306dd970 +MD5 (NetBSD-6.0/newsmips/installation/floppy/boot2.fs) = 90827190455600b1692585932670fc44 +SHA1 (NetBSD-6.0/newsmips/INSTALL.html) = 3bba0333ef60ff85cbb905deb86171f67a7e7d35 +SHA512 (NetBSD-6.0/newsmips/INSTALL.html) = 4778fb087bc4c44b84fec903f4e00003a41cfa3675a2f712bba28b33773800ad6b7d546074787caff68fd34a885ed84e05a0183a4867bed9c3e881ab30c68c64 +RMD160 (NetBSD-6.0/newsmips/INSTALL.html) = 27d6089590736239f38e1b0638f0b1662465ada6 +MD5 (NetBSD-6.0/newsmips/INSTALL.html) = 5041c29c150843c89b4dfa0c1cea869e +SHA1 (NetBSD-6.0/newsmips/INSTALL.more) = 91afcc03bfa9fd0c378f7d9d22ab81cfe214f36c +SHA512 (NetBSD-6.0/newsmips/INSTALL.more) = fc99840a5b29382c2f54287ded48994162804002b6947d2fc1fe907a0674b3827c64fa52e2bd3de735f387e09627ea254820bcd142f0552374acd2c951b0edec +RMD160 (NetBSD-6.0/newsmips/INSTALL.more) = cdb0bd00e8d126b4736b77688ca2ac9bcc330283 +MD5 (NetBSD-6.0/newsmips/INSTALL.more) = 0dd24b3ef2da6fb2fd0989edf90aecd5 +SHA1 (NetBSD-6.0/newsmips/INSTALL.ps) = 2e236b56c944116ec48df342a4a4ab1414be54c8 +SHA512 (NetBSD-6.0/newsmips/INSTALL.ps) = 22e6e7b9975ffcc75b2560ecc103ab0f3337c0e637fc0b13e73c52b8d726c5a7676f8eb60a931113d2ce9570ca78209008810495d6260b374c61aeb79bf1915a +RMD160 (NetBSD-6.0/newsmips/INSTALL.ps) = 031019f4af07c2dbb384bbb76702d2a6da747a0d +MD5 (NetBSD-6.0/newsmips/INSTALL.ps) = fe0ac420b2c0c7a4fba8bfbbc247c0fb +SHA1 (NetBSD-6.0/newsmips/INSTALL.txt) = d2abcef4ce10c3f567350ad9de6370a0f972f3f8 +SHA512 (NetBSD-6.0/newsmips/INSTALL.txt) = a26df9df3950896c9fb77d728190516f1211b1630dff4969c651ad3f343acd9359a9a6251815c560a6e47071717c53b123d911776d5f5d6b8dee38c12d075381 +RMD160 (NetBSD-6.0/newsmips/INSTALL.txt) = f2ef263bdb545134c7dbadb4509ff94ecf14d84d +MD5 (NetBSD-6.0/newsmips/INSTALL.txt) = fea6e65c9aac2b407af208e4f7272cf9 +SHA1 (NetBSD-6.0/next68k/binary/kernel/netbsd-GENERIC.gz) = 9f78ea3f1d4a4b1c07d0a25487b20560adcb7fab +SHA512 (NetBSD-6.0/next68k/binary/kernel/netbsd-GENERIC.gz) = daae6643ef07004beaaa345b57182f2d2b69e990896734e18ec50ee925e17acf334da7a5478fa0fa38de4062fef3285582c9a4fe352759770e4cd9012d70d6f6 +RMD160 (NetBSD-6.0/next68k/binary/kernel/netbsd-GENERIC.gz) = 2dcc60a3c451aaf9303c328a8471775b83ae066a +MD5 (NetBSD-6.0/next68k/binary/kernel/netbsd-GENERIC.gz) = d4502e039874ee01d7564f7572fa4789 +SHA1 (NetBSD-6.0/next68k/binary/sets/games.tgz) = 16ee93ea4d5fac2fb28fad5c32c8a3d57d011d79 +SHA512 (NetBSD-6.0/next68k/binary/sets/games.tgz) = a7f49ab72f50273f66c8dcf408b57ec4668debd5537c5bd0ec59aa0f4fa1d599ba0798d1b283315c4208cbcb608925808ce003b1ade79034886edb8208f9f48d +RMD160 (NetBSD-6.0/next68k/binary/sets/games.tgz) = 1e09d99d7fe2e495763f05919472d27a4ba699df +MD5 (NetBSD-6.0/next68k/binary/sets/games.tgz) = 8a26f3e864444209088bccf21419a616 +SHA1 (NetBSD-6.0/next68k/binary/sets/man.tgz) = 899b9d8242e983a5110ab755651c24f709b5af67 +SHA512 (NetBSD-6.0/next68k/binary/sets/man.tgz) = 410999db110d710f4bb498c3d7ae7adc62170c7c2f470ce189c92f6c436c5ea96149659c631ef0b5605caaa025d97dfe1c07c428d86f51239657bd6b71717b15 +RMD160 (NetBSD-6.0/next68k/binary/sets/man.tgz) = c1270f68c6d41b351877f71f0396ac34877dfc8d +MD5 (NetBSD-6.0/next68k/binary/sets/man.tgz) = df4db2bbfa39ef6a4a215d949653d04a +SHA1 (NetBSD-6.0/next68k/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/next68k/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/next68k/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/next68k/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/next68k/binary/sets/xserver.tgz) = 1d20fd039546a66b428b854c659ea5e2ee9f8114 +SHA512 (NetBSD-6.0/next68k/binary/sets/xserver.tgz) = 091d09049d0af5555feec02065234e281677aeb3ecbab5a19413d924a8b58dc7f64401ef68e68bc52d8b6eeb73e091d351c45805374b8bf276b0181415968561 +RMD160 (NetBSD-6.0/next68k/binary/sets/xserver.tgz) = feef5d52278d23637d7b8ba77639bfd96918e90e +MD5 (NetBSD-6.0/next68k/binary/sets/xserver.tgz) = b2bd6057c374376388766fc8667eb9a9 +SHA1 (NetBSD-6.0/next68k/binary/sets/kern-GENERIC.tgz) = 86b352f48720312e04260ba1dcf2f6e7e9d31e25 +SHA512 (NetBSD-6.0/next68k/binary/sets/kern-GENERIC.tgz) = 602f5ac04b050c0462d21d4e50a9a8e5c794a3b4442b6df19370ab6dbd6839755bc61e2c7745f777aef417d5c1179ff4a2af52a5880d35eb20d1c5d3a580a844 +RMD160 (NetBSD-6.0/next68k/binary/sets/kern-GENERIC.tgz) = f625cea32a206f3738a72b5ec0b01d8485c7eccc +MD5 (NetBSD-6.0/next68k/binary/sets/kern-GENERIC.tgz) = ff2d20b2f2b0a12231e405b582b61801 +SHA1 (NetBSD-6.0/next68k/binary/sets/base.tgz) = d68bfc49aa82b76a52007a927f1a7bac692aaf18 +SHA512 (NetBSD-6.0/next68k/binary/sets/base.tgz) = 4d2c20f0dcfa061e1a1176d34111225b6c8a94b0742141560ccdc986cd5311906967d06e4294a6f988bcea4cbc09d1a9607810960f2d0be35f4ab2895f68f112 +RMD160 (NetBSD-6.0/next68k/binary/sets/base.tgz) = 6d98b84ec87a909545f72526f63cc27d450865fb +MD5 (NetBSD-6.0/next68k/binary/sets/base.tgz) = e40a7e78d87959c20f37bd937921383d +SHA1 (NetBSD-6.0/next68k/binary/sets/comp.tgz) = eb3082aae89eb8720e91538fd100125c9e6a717f +SHA512 (NetBSD-6.0/next68k/binary/sets/comp.tgz) = 8c695463b6ac0a403023068b670d04c7cbe50a9e3925e19896fddba7f409b2d142e9b2817bf18144d9bb55aefe2d7cd90c1242f9bdd6cea628332277d08f8520 +RMD160 (NetBSD-6.0/next68k/binary/sets/comp.tgz) = 81c05df1b3c2c6a72575a325b2c507081279a587 +MD5 (NetBSD-6.0/next68k/binary/sets/comp.tgz) = 11b81d6d2371e3b3123f0fc776526b80 +SHA1 (NetBSD-6.0/next68k/binary/sets/etc.tgz) = d7697b36fa1c6c814b0745d496709c177b43441d +SHA512 (NetBSD-6.0/next68k/binary/sets/etc.tgz) = 9b4ed551eb36810109e30dee6273d5c18fc918686ba9cab5ffc4ab25a1763e645a179920e7d4ba56be3b15269425e38abf3237e1e6a788b369a4d26d59aa8a6d +RMD160 (NetBSD-6.0/next68k/binary/sets/etc.tgz) = beadac2eb477aca072b36fa2587e46645e908d11 +MD5 (NetBSD-6.0/next68k/binary/sets/etc.tgz) = ebd0202a3d65b7a528b4854483ac669d +SHA1 (NetBSD-6.0/next68k/binary/sets/modules.tgz) = 49e37041d779f3b282c12b3f41d876e4621914f2 +SHA512 (NetBSD-6.0/next68k/binary/sets/modules.tgz) = c8f22b3d92b7089aaf3b5fe563a9d0cbc7124b6e402e53b458881c123468e51b5b4f92d8e8b1a5c0f7ff19fc032bdd012db8dfd801be6330e96e0e79917df08a +RMD160 (NetBSD-6.0/next68k/binary/sets/modules.tgz) = 093e67a0796abb445f0f3b7f6bbfa42a68dff403 +MD5 (NetBSD-6.0/next68k/binary/sets/modules.tgz) = dcf44be798ece88e148faaabe70e2251 +SHA1 (NetBSD-6.0/next68k/binary/sets/tests.tgz) = 28b7d959516205c1231c7f756614c776fdba9576 +SHA512 (NetBSD-6.0/next68k/binary/sets/tests.tgz) = b704bcbe14b260067ea704350ff9b49d49e040a6a87597211de8cea7e05039054c4f4996bd96829a9acc1a97320b3fa3f1ca2300717365e2c13fefac4e13ec11 +RMD160 (NetBSD-6.0/next68k/binary/sets/tests.tgz) = b7ad8dc285efaeb99c3d1384dada9b20cc7104bb +MD5 (NetBSD-6.0/next68k/binary/sets/tests.tgz) = 45d4bf99be70595e367459256c139b65 +SHA1 (NetBSD-6.0/next68k/binary/sets/text.tgz) = e079bed4ddd9e37cd0cb2f514823f81de9200669 +SHA512 (NetBSD-6.0/next68k/binary/sets/text.tgz) = 3f66684ea0cdaaa433f52dc40eb6776091d19e5f53c87c3fa888ceaef29524dcd7b5c08ce8f08df94db7f039026dfe60a963d23f888bdeab70da4bf71592b122 +RMD160 (NetBSD-6.0/next68k/binary/sets/text.tgz) = 692b64c1a4e521caa76fdc109175a636ef4f9d21 +MD5 (NetBSD-6.0/next68k/binary/sets/text.tgz) = ea58b70eb622e2bc8fb610431f9f27c4 +SHA1 (NetBSD-6.0/next68k/binary/sets/xbase.tgz) = 5e093e4987d3ef6e66dee1dbf5d2c2781a7be759 +SHA512 (NetBSD-6.0/next68k/binary/sets/xbase.tgz) = 9bf75e2feb514bf47ead4151dfc44e0bd8361bd2155bdd7f5f5bda16c2ce60edef88cfbfe054161af32ea2804ccc5903b5ecc8a4270b2d19d6e864c7df776ef7 +RMD160 (NetBSD-6.0/next68k/binary/sets/xbase.tgz) = 6c8fe359b16a5d6d7ab318ad8970b36b3a9d8b41 +MD5 (NetBSD-6.0/next68k/binary/sets/xbase.tgz) = 4dc8195a284c6ff792f07b0279a1ffee +SHA1 (NetBSD-6.0/next68k/binary/sets/xcomp.tgz) = 6248c1a2455726a172e7d41ad3b71396d1569c27 +SHA512 (NetBSD-6.0/next68k/binary/sets/xcomp.tgz) = 03272ed1984404a7ed8d6753aae6fd2797b82da0f856173bff109dd46909561af865acf81ec8007e8e95794d41e49caa4ffead9d0f5a304e4fe3a627fc62b5ca +RMD160 (NetBSD-6.0/next68k/binary/sets/xcomp.tgz) = a6fd52049b8fb32c457db212ea0b0f04ae8837f6 +MD5 (NetBSD-6.0/next68k/binary/sets/xcomp.tgz) = 1e5c017075bcb0ddc800674737475134 +SHA1 (NetBSD-6.0/next68k/binary/sets/xetc.tgz) = fc7edd9e51673c25587253ccfa05b06556554596 +SHA512 (NetBSD-6.0/next68k/binary/sets/xetc.tgz) = 6d1f1584a7dbf8ddc3695951796b3951ef5fcae7176c93e5992aa84618b1a935d28baf14dac468cfd50e084414978e824054e08d30b3761e2467aecaa8a2d5cc +RMD160 (NetBSD-6.0/next68k/binary/sets/xetc.tgz) = 287ef7ae8028b2cdfdd081f19a387900bcb49b37 +MD5 (NetBSD-6.0/next68k/binary/sets/xetc.tgz) = 9cc9fc5b70004b4e532fc745ac7c07f8 +SHA1 (NetBSD-6.0/next68k/binary/sets/xfont.tgz) = 66f50766e91abe745da27688863877f1002907c7 +SHA512 (NetBSD-6.0/next68k/binary/sets/xfont.tgz) = 3f1fd3be74c0971fe2217fb8e39f6ca693d07b5a272b3eff1028ee2f012ec2c04239ec90cd90846553e3a066b58fa957d0ab1d3695faaf0063a6c947165e63f4 +RMD160 (NetBSD-6.0/next68k/binary/sets/xfont.tgz) = 185771ae1f0ed1ca9d8e7025f402bb41c5a14519 +MD5 (NetBSD-6.0/next68k/binary/sets/xfont.tgz) = 57e25cb12fb7ae0b3cd06def9e685b7d +SHA1 (NetBSD-6.0/next68k/installation/boot) = 1678cf659734cb8f7d5d034bf1ce6aa506278920 +SHA512 (NetBSD-6.0/next68k/installation/boot) = bf027e98b6c1a81300dfe506c084a9777f4f5f9b4078b35d61ea0a39ff73a5d9abe526f423164ed3c076ce7a33cedf460111142f24861c142a5b2c6485881ab9 +RMD160 (NetBSD-6.0/next68k/installation/boot) = 8d3d5e3786b272a9dda7ca19185e3802639f7f6b +MD5 (NetBSD-6.0/next68k/installation/boot) = ec7ee9f5d5be157c6a9a56ac77835f47 +SHA1 (NetBSD-6.0/next68k/INSTALL.html) = aaf1f7407874cf9d7bdff5b434a74e298b7dc52f +SHA512 (NetBSD-6.0/next68k/INSTALL.html) = b2d952c916578af512363fa118f81950b95b545aac62474194ef2ed4df3fc4fd9f334f7b3171335f7669c8d0992c37140daa86bab57dcb0020dfa39abfcc4ecd +RMD160 (NetBSD-6.0/next68k/INSTALL.html) = 52a08c6bd446a00228899639e98aeb8327f100ee +MD5 (NetBSD-6.0/next68k/INSTALL.html) = f08b6811f0f572819de3b455714166b7 +SHA1 (NetBSD-6.0/next68k/INSTALL.more) = dced1147a6dc54b1365d13a49d0bf57d596653aa +SHA512 (NetBSD-6.0/next68k/INSTALL.more) = 5136e7a75ef6c3a39ca15112414c73c023c560dfbc09d4da60e6435112a4108c192f25b200f0a149a9eafdff3a74001630f972f58dcc2a9d18174286c906b680 +RMD160 (NetBSD-6.0/next68k/INSTALL.more) = fd826a26af8b89375881dc361a7426b7841baa52 +MD5 (NetBSD-6.0/next68k/INSTALL.more) = 0d480ba3bfd38cc17c62d387a740111d +SHA1 (NetBSD-6.0/next68k/INSTALL.ps) = 47541be31baefad1f76a45e45b2050cda159953f +SHA512 (NetBSD-6.0/next68k/INSTALL.ps) = 297a4fb8e5242a764b721a3bea309d123d3f71b67aec903926d5118b42831ba054242783fcbdc19520609ac06f81b733785b5952e24ae23218219046922f8f8a +RMD160 (NetBSD-6.0/next68k/INSTALL.ps) = 56423276a2db90876c067eb51b7c19f1341d261b +MD5 (NetBSD-6.0/next68k/INSTALL.ps) = ed71185d0510303cbb5d8ff681dcfaf5 +SHA1 (NetBSD-6.0/next68k/INSTALL.txt) = 3d70ff39023294025c590934bdaca3fce5dd33bd +SHA512 (NetBSD-6.0/next68k/INSTALL.txt) = d0485c5d3587022d986a53345ed78f49130ef54070d0c45a7812d57400402079855d6cc72401579d1185d2dbeb5e5846efebfa50fda484cc5a1ac719ca7b706a +RMD160 (NetBSD-6.0/next68k/INSTALL.txt) = bd984eb4c13e1ec872ee2517b72c13ac7e90e090 +MD5 (NetBSD-6.0/next68k/INSTALL.txt) = 0cf50370809ab3ff52dc710474d37edb +SHA1 (NetBSD-6.0/ofppc/binary/kernel/netbsd-GENERIC.gz) = 31cf98d9ea175b5ea6fe09455217e660d44f1973 +SHA512 (NetBSD-6.0/ofppc/binary/kernel/netbsd-GENERIC.gz) = 22e1ac76e1fa230f69485f53ac23186a97562a1088b1a99979d9d446dcef8a863f1bd63eb6bf16ebf990b40b161fb75025890d9d52474b82cdb3d497e2056b2a +RMD160 (NetBSD-6.0/ofppc/binary/kernel/netbsd-GENERIC.gz) = 1ade658130f4e40d57cee2ab641234c1e93c3f01 +MD5 (NetBSD-6.0/ofppc/binary/kernel/netbsd-GENERIC.gz) = ae8374ac0ba9ca59c6068561dcad1ba3 +SHA1 (NetBSD-6.0/ofppc/binary/kernel/netbsd-INSTALL.gz) = 0b815e688d07caf3d93190562bcd53f3057ec1b6 +SHA512 (NetBSD-6.0/ofppc/binary/kernel/netbsd-INSTALL.gz) = 43255a25b3044320db3d12f474a70920efe93a52aad3351933ae80bd079a8f93a866fa1c939a92d075161822066dc76ffe314feaf493a783ca51058eba9e96e0 +RMD160 (NetBSD-6.0/ofppc/binary/kernel/netbsd-INSTALL.gz) = 87995ce3c896b4ffcef1eaeef9c7ff27e8c5446f +MD5 (NetBSD-6.0/ofppc/binary/kernel/netbsd-INSTALL.gz) = 008fbd36266fbb4ef45c3c289d07dbd3 +SHA1 (NetBSD-6.0/ofppc/binary/sets/games.tgz) = fbf69640b362df2446d7414ac3a13db100c289eb +SHA512 (NetBSD-6.0/ofppc/binary/sets/games.tgz) = d86b41d79aea4204ccf45306937a5ec45629e37873a5956c0280fd1d54cf4a808542d097f9d978fd3277791554ce8a6fb4d0ccd46e30210549d5cce1145bb499 +RMD160 (NetBSD-6.0/ofppc/binary/sets/games.tgz) = fd2aed1eb51f4db522fb5163e8fde4c040b55d30 +MD5 (NetBSD-6.0/ofppc/binary/sets/games.tgz) = 997ae5fb42196a787df89873be321e47 +SHA1 (NetBSD-6.0/ofppc/binary/sets/man.tgz) = 899b9d8242e983a5110ab755651c24f709b5af67 +SHA512 (NetBSD-6.0/ofppc/binary/sets/man.tgz) = 410999db110d710f4bb498c3d7ae7adc62170c7c2f470ce189c92f6c436c5ea96149659c631ef0b5605caaa025d97dfe1c07c428d86f51239657bd6b71717b15 +RMD160 (NetBSD-6.0/ofppc/binary/sets/man.tgz) = c1270f68c6d41b351877f71f0396ac34877dfc8d +MD5 (NetBSD-6.0/ofppc/binary/sets/man.tgz) = df4db2bbfa39ef6a4a215d949653d04a +SHA1 (NetBSD-6.0/ofppc/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/ofppc/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/ofppc/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/ofppc/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/ofppc/binary/sets/xcomp.tgz) = 960dd33b61e19dec92096a54791aca1cdf56ce54 +SHA512 (NetBSD-6.0/ofppc/binary/sets/xcomp.tgz) = 111dd50041e4008aeadb898c3d08f9995c5c13a41ccc20993b4ad51c81d7f6ee3b4dab16158ac7436d085b80e4a643b236a9c97edd3e915125a1466154538420 +RMD160 (NetBSD-6.0/ofppc/binary/sets/xcomp.tgz) = 0cf8b9a8d1489a32ba0b5a277d90e429c40650fb +MD5 (NetBSD-6.0/ofppc/binary/sets/xcomp.tgz) = 4ba4077ca2c0edf71813165fcf5321fb +SHA1 (NetBSD-6.0/ofppc/binary/sets/xfont.tgz) = 4711fcbade0238d60b7b89cf0d7873b03d7ed1f7 +SHA512 (NetBSD-6.0/ofppc/binary/sets/xfont.tgz) = c29130f55f536f602253a7f92f073ebf6ba02baea09f8011530bbf7e03ae96594334f0c60b29a8bceaffc3eb8b152db47548e38a3c8a14abc5fe35bc5d1d7d93 +RMD160 (NetBSD-6.0/ofppc/binary/sets/xfont.tgz) = 3b01af0f8e34367988d559fe0fbb0acbbafb0b2b +MD5 (NetBSD-6.0/ofppc/binary/sets/xfont.tgz) = 6ba15ed12217b726d9129db8e942a048 +SHA1 (NetBSD-6.0/ofppc/binary/sets/kern-GENERIC.tgz) = 7ace360c931ac41952447fce2d6241a8393a7b3c +SHA512 (NetBSD-6.0/ofppc/binary/sets/kern-GENERIC.tgz) = 9c63f0169c8bf1282c54a5ae3b1396376b69a23b6ac881859a304a9d21aad45f64d0998eae3399cc397489a1c3e1b7f52cdce0ee806c160ae5da3287b113c00b +RMD160 (NetBSD-6.0/ofppc/binary/sets/kern-GENERIC.tgz) = b96e84c0a6d945475f6523d73cabb42ff80caa46 +MD5 (NetBSD-6.0/ofppc/binary/sets/kern-GENERIC.tgz) = 2153bc142bb6f9067287344b5d3703e6 +SHA1 (NetBSD-6.0/ofppc/binary/sets/base.tgz) = 48aef3545f49ee86082480f6712e6c7df6c1c82f +SHA512 (NetBSD-6.0/ofppc/binary/sets/base.tgz) = 580ad38769fc64e5f50a59f726d13d21625392459a03633c4908fbaf16e08715032dd10fbee9f4efe5261beb24169dcdaf86f11d20f2e2bfc7af22f16ce5b10c +RMD160 (NetBSD-6.0/ofppc/binary/sets/base.tgz) = 93fe246dba1352ba0bc5ef955094069e82e777cc +MD5 (NetBSD-6.0/ofppc/binary/sets/base.tgz) = 6a0ea91d58c236cd1d72963bee61dbc8 +SHA1 (NetBSD-6.0/ofppc/binary/sets/comp.tgz) = 7d553fd5460fd823ee474377ad7e4e4a57796d04 +SHA512 (NetBSD-6.0/ofppc/binary/sets/comp.tgz) = 17dff29a91c71c4fcabe616595144201b999b75d56033109f24dfa89e5653ea24890e2657fc007cc0bcbceb749213eb99db5d268db8c96f41f1c2ec203e951ef +RMD160 (NetBSD-6.0/ofppc/binary/sets/comp.tgz) = 79001f2a220166711cf3e076c137d9944cb72d07 +MD5 (NetBSD-6.0/ofppc/binary/sets/comp.tgz) = bb52657afeeafa0a04fc52d5b96130cb +SHA1 (NetBSD-6.0/ofppc/binary/sets/etc.tgz) = b19a807890c2859c0c5dfcc27d97c7b94703ba1c +SHA512 (NetBSD-6.0/ofppc/binary/sets/etc.tgz) = 157110603a432bdf8da99f467e263037d2683372b37c2fb9e8ba7a25a5ed6e44b6d62aa3d60464ea3d0dd101d55b85ff951afde528cc0f61158892a3b379bc90 +RMD160 (NetBSD-6.0/ofppc/binary/sets/etc.tgz) = 8e67db3042b34b9e0ec19853d0209996cb18cc22 +MD5 (NetBSD-6.0/ofppc/binary/sets/etc.tgz) = 7c3ef92dc32ef4a24a29fd071fad94f5 +SHA1 (NetBSD-6.0/ofppc/binary/sets/modules.tgz) = 976ee92c542c431c7eadaf77dc3267c54643aef9 +SHA512 (NetBSD-6.0/ofppc/binary/sets/modules.tgz) = eedd03d73c348500f3df270f002d65d16cdc9f5318ecf14ebc8c4e27af6aff26701d985e5c5a47ed9f37359fb119d61ebe64cbcd726bb5ea7a0b2947aa312a8a +RMD160 (NetBSD-6.0/ofppc/binary/sets/modules.tgz) = 03d76ba89e00f988e16e0a5cd6798fca65852c82 +MD5 (NetBSD-6.0/ofppc/binary/sets/modules.tgz) = 132d39b3a365d6ecd924789660a7b72c +SHA1 (NetBSD-6.0/ofppc/binary/sets/tests.tgz) = f643b7607751a3355cc6e9e8d26fcc1bfdd14a22 +SHA512 (NetBSD-6.0/ofppc/binary/sets/tests.tgz) = 0a517f2c914e449c0bedb3be5e96e76c369be5be270ad8ba2aee4b96f3a3d7afce2bb56de0eef54d97b1194101eb24331dd202605eb58e648b3f79f04b44d96a +RMD160 (NetBSD-6.0/ofppc/binary/sets/tests.tgz) = aca5ea7884341e0dc0f4e06d552b908550cb7dde +MD5 (NetBSD-6.0/ofppc/binary/sets/tests.tgz) = d8c47bef7caa4afa0ea7967d42a59cfa +SHA1 (NetBSD-6.0/ofppc/binary/sets/text.tgz) = 010dbafdbd84074ed3acf0bacea61b34dad4005d +SHA512 (NetBSD-6.0/ofppc/binary/sets/text.tgz) = a8a4fe56016f47a03dd2e23cfb5368111cc7734a7a9dba9ab42081b609c00ac812ec8e73eb75b5dc2f81b847f0bf782257834e09603aac858c8efe1e6755eaf8 +RMD160 (NetBSD-6.0/ofppc/binary/sets/text.tgz) = 263b72d30191910c092ab984458cd1442ba67f3a +MD5 (NetBSD-6.0/ofppc/binary/sets/text.tgz) = a6dfbc450a9aec79555f52694a2971f0 +SHA1 (NetBSD-6.0/ofppc/binary/sets/xbase.tgz) = 292a1ad5d516609f5c3c5e78e83f4f200f967775 +SHA512 (NetBSD-6.0/ofppc/binary/sets/xbase.tgz) = b3c082fb1fe52edc65fb728d9347d51285a761ba8bbb56cf84744f70614c2c1207a8b48c49d5ad598fc09745f3a900ca2bb08cff4381be8f007d6b89faf7c058 +RMD160 (NetBSD-6.0/ofppc/binary/sets/xbase.tgz) = 954ba03beb3cc9b5064c0d9e9008358cf9c490f5 +MD5 (NetBSD-6.0/ofppc/binary/sets/xbase.tgz) = 410d993f39451d776e2c9d9ca55414ac +SHA1 (NetBSD-6.0/ofppc/binary/sets/xetc.tgz) = b83db52f87a7a2ba08d22f29249f2b0d8af31028 +SHA512 (NetBSD-6.0/ofppc/binary/sets/xetc.tgz) = 541ca16e25a0cd271b490773e043e6d66d9d704f4d4bd22458d5f3c4f76f23190264201a80cd57b567d8410ca2944a36e10868c4e2916300d978949d78293b33 +RMD160 (NetBSD-6.0/ofppc/binary/sets/xetc.tgz) = de0ae01a1d264465ca58a678c658f75d2844d04a +MD5 (NetBSD-6.0/ofppc/binary/sets/xetc.tgz) = d60b94274347e3f9073b80da9f5dd874 +SHA1 (NetBSD-6.0/ofppc/binary/sets/xserver.tgz) = e8fd963e80c60b8a85a284484d0d78463038f413 +SHA512 (NetBSD-6.0/ofppc/binary/sets/xserver.tgz) = ca88d3ce0ccd0e82636ae59d4ea4acba9d29ba6fb51be52c6d8de5986d7b037e6062d00bc45390783efd3089de3eabbdbf565929936af7f46c207b705c33176f +RMD160 (NetBSD-6.0/ofppc/binary/sets/xserver.tgz) = a6b1345264d3fcddf0ff72b3005dd71053aba0f5 +MD5 (NetBSD-6.0/ofppc/binary/sets/xserver.tgz) = 8150c6dfee587ce36ff31c34a1929e29 +SHA1 (NetBSD-6.0/ofppc/installation/netboot/netbsd-GENERIC.gz) = 31cf98d9ea175b5ea6fe09455217e660d44f1973 +SHA512 (NetBSD-6.0/ofppc/installation/netboot/netbsd-GENERIC.gz) = 22e1ac76e1fa230f69485f53ac23186a97562a1088b1a99979d9d446dcef8a863f1bd63eb6bf16ebf990b40b161fb75025890d9d52474b82cdb3d497e2056b2a +RMD160 (NetBSD-6.0/ofppc/installation/netboot/netbsd-GENERIC.gz) = 1ade658130f4e40d57cee2ab641234c1e93c3f01 +MD5 (NetBSD-6.0/ofppc/installation/netboot/netbsd-GENERIC.gz) = ae8374ac0ba9ca59c6068561dcad1ba3 +SHA1 (NetBSD-6.0/ofppc/installation/netboot/netbsd-INSTALL.gz) = 0b815e688d07caf3d93190562bcd53f3057ec1b6 +SHA512 (NetBSD-6.0/ofppc/installation/netboot/netbsd-INSTALL.gz) = 43255a25b3044320db3d12f474a70920efe93a52aad3351933ae80bd079a8f93a866fa1c939a92d075161822066dc76ffe314feaf493a783ca51058eba9e96e0 +RMD160 (NetBSD-6.0/ofppc/installation/netboot/netbsd-INSTALL.gz) = 87995ce3c896b4ffcef1eaeef9c7ff27e8c5446f +MD5 (NetBSD-6.0/ofppc/installation/netboot/netbsd-INSTALL.gz) = 008fbd36266fbb4ef45c3c289d07dbd3 +SHA1 (NetBSD-6.0/ofppc/installation/netboot/ofwboot) = 56bb70527f572ae12667a4d9dc71027032602d26 +SHA512 (NetBSD-6.0/ofppc/installation/netboot/ofwboot) = d137aad957d917f4db49ad9b912cf794d5ba9e52ac0f0d1926599dcac166df97c5b81292247b62d15a495134d4c9967ba777b0570701b3340021dcac293ab2d2 +RMD160 (NetBSD-6.0/ofppc/installation/netboot/ofwboot) = 5a6f580e7c000543b09dc7590555ce944b7f2df1 +MD5 (NetBSD-6.0/ofppc/installation/netboot/ofwboot) = 139a6e28174158a78719ab4e67de40b5 +SHA1 (NetBSD-6.0/ofppc/INSTALL.html) = 70ffc237a74825aeff35c638c9dd33b10334c09e +SHA512 (NetBSD-6.0/ofppc/INSTALL.html) = 5df9959e93527b0f53d3866b15fcac4dbce2edd6a1bff082e588348ada3767bd0ca45d99089540fde08ecc73b8c8846ca7a046ada5f1f1072d6cd1e6c3268497 +RMD160 (NetBSD-6.0/ofppc/INSTALL.html) = 3718a3b3de1edc4d81cc61c88146e69d8b126266 +MD5 (NetBSD-6.0/ofppc/INSTALL.html) = 4a16acd4059c24dbcf1ccab96be7928c +SHA1 (NetBSD-6.0/ofppc/INSTALL.more) = 14b22fc68257222ce1d15d02554588760ce4fc62 +SHA512 (NetBSD-6.0/ofppc/INSTALL.more) = e0c15cc5760ad5087d58c7659e8692b18fa805b6df85a7965ce142bb7506d3105c1dea0c7acdecfc51fa63f857dc959e25c74fa0ee871417670e013f4c2b2a1c +RMD160 (NetBSD-6.0/ofppc/INSTALL.more) = b726d0dd772cab274c9b2f6f484d5b1903151827 +MD5 (NetBSD-6.0/ofppc/INSTALL.more) = 40e2acf64e90023938d03f0ff945ab0f +SHA1 (NetBSD-6.0/ofppc/INSTALL.ps) = 16a078ed4ada6fe71e1d5939bacd3a60c10cefbd +SHA512 (NetBSD-6.0/ofppc/INSTALL.ps) = 1d9815a162a77d91aebbfd11e0fe6d386c24be9e734683a6eee3cc49e059e8c4c9e559d00c3bfdbd3ceaaf885c11deb5c985ab4de41f1e1b1c9c5b037d300ec5 +RMD160 (NetBSD-6.0/ofppc/INSTALL.ps) = 83f80393d6bd7845dac2c2f789b14104b5ed3b9e +MD5 (NetBSD-6.0/ofppc/INSTALL.ps) = 9ef011b3eea954489d1e03261175f278 +SHA1 (NetBSD-6.0/ofppc/INSTALL.txt) = 0703c2fc0836a815f8a23c9e295482feced08667 +SHA512 (NetBSD-6.0/ofppc/INSTALL.txt) = e5a59c4554e4dad54c4de8af3ef1fc051a3ed6ddcca88fe60b0f1c5e52c75507268a0cd154482fd7f8633ef0b6de5fa9052334adb93bc787e0f45db400018aea +RMD160 (NetBSD-6.0/ofppc/INSTALL.txt) = b4b1e1c493973acc61f5280eec83fd1a4b386f9e +MD5 (NetBSD-6.0/ofppc/INSTALL.txt) = 167ec8dd0f2430f3baafba98c15b0b77 +SHA1 (NetBSD-6.0/pmax/binary/kernel/netbsd-INSTALL.ecoff.gz) = c3341e74bbfc424f067743c23369e7d4de2320d8 +SHA512 (NetBSD-6.0/pmax/binary/kernel/netbsd-INSTALL.ecoff.gz) = 902237dd2bac97bbf8bc0d70e933307897e375cf760f90531ae39ff8f9abaf1c70091d61678e56448b46d060919eb93b052e0bdcba34482b12174855bf29a941 +RMD160 (NetBSD-6.0/pmax/binary/kernel/netbsd-INSTALL.ecoff.gz) = 12abc208e6d943a92255fa99934e2fbdd98b86d5 +MD5 (NetBSD-6.0/pmax/binary/kernel/netbsd-INSTALL.ecoff.gz) = 3a5c93ed6aedf91145618578c0283312 +SHA1 (NetBSD-6.0/pmax/binary/kernel/netbsd-GENERIC.gz) = c673249c82581fc220eeab9db4826ae70a879f7d +SHA512 (NetBSD-6.0/pmax/binary/kernel/netbsd-GENERIC.gz) = 28c33a6cbb2cb4ad53e3e780c74a903ee93a6350da5a36c0232a57e690b80caf1053dc2bad1badd5631abeb20dbfbd223413762bf576db7363a3bd07aa91ddee +RMD160 (NetBSD-6.0/pmax/binary/kernel/netbsd-GENERIC.gz) = 1c56f35974b50c40595fb19a763e6e13a052136c +MD5 (NetBSD-6.0/pmax/binary/kernel/netbsd-GENERIC.gz) = 27f93c549aa40bae7bae47978622eb2c +SHA1 (NetBSD-6.0/pmax/binary/kernel/netbsd-INSTALL.symbols.gz) = af7b35f9bea1761095521088a9bad8d6122565c9 +SHA512 (NetBSD-6.0/pmax/binary/kernel/netbsd-INSTALL.symbols.gz) = 506859e85d0266360f83d3a7af1deb8f9a84c8f1bbab10c1bd8b9b43bdf8ff7056629450f8aff2ed6f3424ff2034cd36e21144bceaaac6048fe54f58982dfa8f +RMD160 (NetBSD-6.0/pmax/binary/kernel/netbsd-INSTALL.symbols.gz) = 71b182d23dfaa77e92597e840c0d5cb502b9ff7b +MD5 (NetBSD-6.0/pmax/binary/kernel/netbsd-INSTALL.symbols.gz) = f70b79efeefcd03ef2b47a6d61b723c8 +SHA1 (NetBSD-6.0/pmax/binary/kernel/netbsd-INSTALL.gz) = f22aa49d239f1c2b49fc2779dbc71b79d6470468 +SHA512 (NetBSD-6.0/pmax/binary/kernel/netbsd-INSTALL.gz) = 82136634c9a3ea07a6eb23ad3e6d4214d796f54d406de73cd23f0da45a3872bae0f7f120ddb67aab0da05ef88feb21bb63ec1adf880469ee5d4eda2e32080732 +RMD160 (NetBSD-6.0/pmax/binary/kernel/netbsd-INSTALL.gz) = 351fe6fec563003dcb4a0045c740ba3f2fcb73ad +MD5 (NetBSD-6.0/pmax/binary/kernel/netbsd-INSTALL.gz) = 50f2b444f3462f71810f3c93b47083ff +SHA1 (NetBSD-6.0/pmax/binary/sets/games.tgz) = 27d9f98fecb3495e51939df9f107e81e527af26f +SHA512 (NetBSD-6.0/pmax/binary/sets/games.tgz) = 46bb4e10313cfffaaf4f7fa2157474ef940f94bcc9f84b46f829c7615bbf45e4e01edee7b7efb84bc28561e0712c37cfc737f9c2a0d9a73b67c80c8aa0f3a9af +RMD160 (NetBSD-6.0/pmax/binary/sets/games.tgz) = 947feea90ec2698a65d555cb78a29a001b086589 +MD5 (NetBSD-6.0/pmax/binary/sets/games.tgz) = 355f00978fed8e8da6a251e591be5387 +SHA1 (NetBSD-6.0/pmax/binary/sets/man.tgz) = 899b9d8242e983a5110ab755651c24f709b5af67 +SHA512 (NetBSD-6.0/pmax/binary/sets/man.tgz) = 410999db110d710f4bb498c3d7ae7adc62170c7c2f470ce189c92f6c436c5ea96149659c631ef0b5605caaa025d97dfe1c07c428d86f51239657bd6b71717b15 +RMD160 (NetBSD-6.0/pmax/binary/sets/man.tgz) = c1270f68c6d41b351877f71f0396ac34877dfc8d +MD5 (NetBSD-6.0/pmax/binary/sets/man.tgz) = df4db2bbfa39ef6a4a215d949653d04a +SHA1 (NetBSD-6.0/pmax/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/pmax/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/pmax/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/pmax/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/pmax/binary/sets/kern-GENERIC.tgz) = 1ae699dc77ef033860c3fcc0df198c6ec15bf312 +SHA512 (NetBSD-6.0/pmax/binary/sets/kern-GENERIC.tgz) = 1a29fbe70596378ab0f543dd010c24ca327822d743152ce0405eb0e4ab268224b91d346d23b9ee1eec706b4cbe88ccdea27cb6a9b115ce9ddcdaced115a58682 +RMD160 (NetBSD-6.0/pmax/binary/sets/kern-GENERIC.tgz) = 5edbc95d6df7a073b545902862a9e012a981b36b +MD5 (NetBSD-6.0/pmax/binary/sets/kern-GENERIC.tgz) = d9d9dab85e423b5953eb17bdf8072375 +SHA1 (NetBSD-6.0/pmax/binary/sets/base.tgz) = a7e09afd631257929bbc0a4c6705fd56cafdda30 +SHA512 (NetBSD-6.0/pmax/binary/sets/base.tgz) = 8313b9e6146645955a135e9f9c69b90688f9011ef4087a7911e842ff13802150347ac4e7e9b3f60313a06300e90e93c192910741fd427705709be5f669a45701 +RMD160 (NetBSD-6.0/pmax/binary/sets/base.tgz) = 52eb2bdd47d2a4ae8ac2b780e70006dcc79f4cf6 +MD5 (NetBSD-6.0/pmax/binary/sets/base.tgz) = 3b726d62e4341637cf824c141cdc362c +SHA1 (NetBSD-6.0/pmax/binary/sets/comp.tgz) = 9cc5684de31ac3b6c086f3716926eccbfaec6191 +SHA512 (NetBSD-6.0/pmax/binary/sets/comp.tgz) = fbead7650935dcbea46ef3e11ef03468287b0461cbb70b51e330e641dd7e246bd602bc92935980e3e8ea8100e8ea487906763fc615e477462a9644201a7f616f +RMD160 (NetBSD-6.0/pmax/binary/sets/comp.tgz) = def96b7d151cc9405fe72c51f7ca95b552f3bd46 +MD5 (NetBSD-6.0/pmax/binary/sets/comp.tgz) = 93a3bdd6f9461cc642955b749cddb59a +SHA1 (NetBSD-6.0/pmax/binary/sets/etc.tgz) = 73127a1dcbea90c9029538e87773bc7846ac2016 +SHA512 (NetBSD-6.0/pmax/binary/sets/etc.tgz) = b96b30df1576538bcbaddcf471cd4d87258c06d199077d35d4ea37dfc9c3f388bd62c1ea8c3634ee501d6f28409bd966b791bf3eef8741ca2234c12e1101008a +RMD160 (NetBSD-6.0/pmax/binary/sets/etc.tgz) = 44ef8ce24cdd12aa5af0cbbf700abeef900e12e5 +MD5 (NetBSD-6.0/pmax/binary/sets/etc.tgz) = 0dd976e6a6c855f02a86fc0fb624b4af +SHA1 (NetBSD-6.0/pmax/binary/sets/modules.tgz) = 9ed1e0f57d9ee14dc3850e541f0b95132a3048c2 +SHA512 (NetBSD-6.0/pmax/binary/sets/modules.tgz) = 7a367e78224326f43584bb7cfa1aedd74763ccfca9d6abc8587882ecb1b8276851ead5ff1afbe9cd16accfd0d415e26db6604d3a9c3a1bac78d94107a57d033b +RMD160 (NetBSD-6.0/pmax/binary/sets/modules.tgz) = cff6f3fc309012a3f45c047ea5238f83432235a5 +MD5 (NetBSD-6.0/pmax/binary/sets/modules.tgz) = 825fa6d6cac00e2629ec059fcb68008b +SHA1 (NetBSD-6.0/pmax/binary/sets/tests.tgz) = 802f716b73250eee2696cac4b6e3395833c0237d +SHA512 (NetBSD-6.0/pmax/binary/sets/tests.tgz) = f56cba629167f2f679a460679faaf566f4baf053d644a71fd70fa3041aa592aa0a53b98876ce474b48f46a582401a882161005360fdddc49246f094680b1029f +RMD160 (NetBSD-6.0/pmax/binary/sets/tests.tgz) = a9b17f97265bdfb69402190690d77306f42ecb6b +MD5 (NetBSD-6.0/pmax/binary/sets/tests.tgz) = 54dd7a96d4abee24bb0019a846d77825 +SHA1 (NetBSD-6.0/pmax/binary/sets/text.tgz) = a0b59e7fb204b9db40df7edda528e8ca8b4e3fd6 +SHA512 (NetBSD-6.0/pmax/binary/sets/text.tgz) = fb7c0d5cb17bb2ef1ffeefa5791bab7932a05e33cd064f279d99eebe07a52f1420aa64a8c6acf191efacbfd130509fb427e6d5d8f14c042b3c0e5e285282592b +RMD160 (NetBSD-6.0/pmax/binary/sets/text.tgz) = b0495549753b7c3a8abb342045ef4f65e7b640d5 +MD5 (NetBSD-6.0/pmax/binary/sets/text.tgz) = 9f9e6d5b8f9dbb70b845a9aba07ffff4 +SHA1 (NetBSD-6.0/pmax/binary/sets/xbase.tgz) = 99d83d866f2f15b6030b0533990e012ab59b1f46 +SHA512 (NetBSD-6.0/pmax/binary/sets/xbase.tgz) = 238db55892d9cbb0bd5dacb225a16e694c79af2fe461f06563a65c5d2c5b3abfc823ab26f23c54bc1514568018726baab0258aac0e52ccf7615d59c2a6ef324a +RMD160 (NetBSD-6.0/pmax/binary/sets/xbase.tgz) = 16560205f7564558bc22495116ace64618834133 +MD5 (NetBSD-6.0/pmax/binary/sets/xbase.tgz) = 384d33f9a8ec5c7bc8e104869e3e493a +SHA1 (NetBSD-6.0/pmax/binary/sets/xcomp.tgz) = 6b6b8d6b522b0546a13a304195765526158f6eb2 +SHA512 (NetBSD-6.0/pmax/binary/sets/xcomp.tgz) = 37af51b256f03e8b4c61d4c67724cead53115ccbfda7d597f3b00a020bd8f4c1fff4f6206e5fe8246e0b3fae50c7dc1df313858670a6e1729b1155e0f97e9b23 +RMD160 (NetBSD-6.0/pmax/binary/sets/xcomp.tgz) = 91d9a2cecb3955beabb71191b73d3586f2c370bd +MD5 (NetBSD-6.0/pmax/binary/sets/xcomp.tgz) = 9028e22a82276249cc188f83101af806 +SHA1 (NetBSD-6.0/pmax/binary/sets/xetc.tgz) = 2171c5c0cb3143aa83fb8e55d4d98fd87d3e556d +SHA512 (NetBSD-6.0/pmax/binary/sets/xetc.tgz) = a63407a7d884ea60761ccdee9279c37b790aa08defced01410786e0e020a63b5a4e4cfd503a0ef09e555d04a98a99dbfcfb087c476070771f8b5b5a205b4495a +RMD160 (NetBSD-6.0/pmax/binary/sets/xetc.tgz) = fa4c1f7437db71fb1a3122cc366591b39b00fa07 +MD5 (NetBSD-6.0/pmax/binary/sets/xetc.tgz) = be3b5f617ddd47650cf9423451320c4a +SHA1 (NetBSD-6.0/pmax/binary/sets/xfont.tgz) = ca16714159668bc20017cbb9a81fe3746171e383 +SHA512 (NetBSD-6.0/pmax/binary/sets/xfont.tgz) = 077ab3a7540abb8d4039b7f017ff52dcb5aae2ba5a984dd12b04d22908863cc60db8aa67b5f772a584aabbe05a74426534eeced9f323aa07c9225c8333c41f3f +RMD160 (NetBSD-6.0/pmax/binary/sets/xfont.tgz) = 33beb97b3267941786413a7c5624d78297f5ccf6 +MD5 (NetBSD-6.0/pmax/binary/sets/xfont.tgz) = c262ee8846a85c1e5b00a8ecbe754dcc +SHA1 (NetBSD-6.0/pmax/binary/sets/xserver.tgz) = 86332fccabc2c7b8e7ef7f8fa9eebc2f22c8afba +SHA512 (NetBSD-6.0/pmax/binary/sets/xserver.tgz) = e02ed6aa6333bd8941d02f15a3797f862f3fe47b5afce08d60021a06d5ed9db56e8bf802920e8b7614ff5e3127706b195ab9a678710b7b6afb6b70e0f3a7f636 +RMD160 (NetBSD-6.0/pmax/binary/sets/xserver.tgz) = 4bc06df7b2012be80b61ef6b9860a4698b815353 +MD5 (NetBSD-6.0/pmax/binary/sets/xserver.tgz) = 5dd0ae8362aa55b5c7ab207d771834f3 +SHA1 (NetBSD-6.0/pmax/installation/diskimage/diskimage.gz) = 013da364eedff1ef317fe4933205a1f6e45a7520 +SHA512 (NetBSD-6.0/pmax/installation/diskimage/diskimage.gz) = 9a415703b540ea67b99a367bf8a2dbd73c18fc1aff0ee2b3ffedb858d09cfa1b3e7bc62a654061963394f3540c50259ad343edfc41518fa444332d7ab9ea5e8e +RMD160 (NetBSD-6.0/pmax/installation/diskimage/diskimage.gz) = 3c7faef744c1c309dbad390121852ca1ad8ed0f1 +MD5 (NetBSD-6.0/pmax/installation/diskimage/diskimage.gz) = 2e40475c5dfbfa75ac856a0a02f4afd7 +SHA1 (NetBSD-6.0/pmax/installation/miniroot/miniroot.fs.gz) = fb7b259d7649170e5eaa31217417b6e75291529f +SHA512 (NetBSD-6.0/pmax/installation/miniroot/miniroot.fs.gz) = 3ef73219ab90c01753bf53dc325b64e26b8b41a7cd78ff1fcb85c4d27ab44b2979b6d312c17383ae9f8c3d24c968f5b896fd04a0679e64a47ea859b578022722 +RMD160 (NetBSD-6.0/pmax/installation/miniroot/miniroot.fs.gz) = 4f8d0f80c84f93b4ea5d9025c4fd3227c2880641 +MD5 (NetBSD-6.0/pmax/installation/miniroot/miniroot.fs.gz) = 3e2cc1da2be2c9ae099bd488393a9904 +SHA1 (NetBSD-6.0/pmax/installation/netboot/diskimage.tgz) = de0f5cd5da27716499b56ae61afe5ca6a8bb0839 +SHA512 (NetBSD-6.0/pmax/installation/netboot/diskimage.tgz) = 0283bc16d8fef0704b0d90bda6213d05e63271053ce59cb20d6cf0dc3a76bb8ed711e968de5a194d2d900becf83eb4fccbd82c22ed868c9a79b7cfbbc43acef7 +RMD160 (NetBSD-6.0/pmax/installation/netboot/diskimage.tgz) = a46875bffd27ea9d145b5e5f2a286a49c5b93cdb +MD5 (NetBSD-6.0/pmax/installation/netboot/diskimage.tgz) = a491535a6424e97d5c52207404922ba9 +SHA1 (NetBSD-6.0/pmax/INSTALL.html) = 416fb09d6569c88845b26c89d9062106799cb772 +SHA512 (NetBSD-6.0/pmax/INSTALL.html) = cc06ccfbe9a109b6873a6e280baa5d401d3adb507160e145446e0c6d3c042cd5ba2f9edbe1c8d9731722d12fcc42bf40c5ff7a8e1746d096c182fe92437d2072 +RMD160 (NetBSD-6.0/pmax/INSTALL.html) = c40efcbd9facf5dce4471b1adf725830cd53b934 +MD5 (NetBSD-6.0/pmax/INSTALL.html) = 140966d090ff98ea58dc24cf673a5e11 +SHA1 (NetBSD-6.0/pmax/INSTALL.more) = c737caf24e7e33dd11ee48d0f0b1c0ec2efe8010 +SHA512 (NetBSD-6.0/pmax/INSTALL.more) = e014f63f15cfe131b38adf13500caab4ba7d43a7dce6432b2d688e916c3939ac851e5cb9af544db231cf729e5e39f223b1a73cff5ad66a92714aac71546c863d +RMD160 (NetBSD-6.0/pmax/INSTALL.more) = 3d69b81b9dacf7933a2b0e9c76568f9ccd212330 +MD5 (NetBSD-6.0/pmax/INSTALL.more) = 7aae0fb416c11b3ba0558595afc3af37 +SHA1 (NetBSD-6.0/pmax/INSTALL.ps) = 64b1af6366baed6f548759b6a09fdbbfbb85dbf2 +SHA512 (NetBSD-6.0/pmax/INSTALL.ps) = ec6c213be8ee3af8e2720fcce970c9e8d5e220b1b94ba5f1ef1d8fd4a4c1ae773d522e077e28aadbb4c78a814ea4c06e2f1a915de8e8628f2602cd8705ff786a +RMD160 (NetBSD-6.0/pmax/INSTALL.ps) = 17eac5c26ecf0947848d6742ba0aeb54d5b7ad21 +MD5 (NetBSD-6.0/pmax/INSTALL.ps) = 242d97c9cf75db873cb975d2788a24c5 +SHA1 (NetBSD-6.0/pmax/INSTALL.txt) = 90f4bfa985417eff921768c47ffc495b066292f6 +SHA512 (NetBSD-6.0/pmax/INSTALL.txt) = 36a7a301319525765fa1ae6c4d73b93c02b59a6f532f0dd1f96503a330daf0ba903f97df81dbd906bd54f83a83332efb28a8450d3a99ec5214abe0ed5369041f +RMD160 (NetBSD-6.0/pmax/INSTALL.txt) = 02fe56f81cd11b4c65a13da0868e887ccfd7d511 +MD5 (NetBSD-6.0/pmax/INSTALL.txt) = c6a7c6addcfbd8f1b1bc708946065b52 +SHA1 (NetBSD-6.0/prep/binary/kernel/netbsd-INSTALL.symbols.gz) = 4a2e47a10e1c8913a04a5c574a0f09b82540b23d +SHA512 (NetBSD-6.0/prep/binary/kernel/netbsd-INSTALL.symbols.gz) = 07c86d3b4d188d94141d181b1828e0548bf1e9597c6b470e7a35c787e7c830905fdc63ea4c8ea3f8310378f2e2bb55097c915d1785379d30c12861047d95af12 +RMD160 (NetBSD-6.0/prep/binary/kernel/netbsd-INSTALL.symbols.gz) = 70b4600b73a7d8b937790bb9d69c68e82fdf559f +MD5 (NetBSD-6.0/prep/binary/kernel/netbsd-INSTALL.symbols.gz) = b0f9598d18b5ff0081a3dcc02e4ae185 +SHA1 (NetBSD-6.0/prep/binary/kernel/netbsd-GENERIC.gz) = aadff547ddd7061ee0fe0c72833b691eaeae554a +SHA512 (NetBSD-6.0/prep/binary/kernel/netbsd-GENERIC.gz) = 57a25d74b982bbd519271f24456cd5de583e9e5c7e2ef7d8850d6aa64fcccddc9a2e6545c3ed7323e087d04116c2c78ace5b427b14fc3542435ba3bb9497e4b5 +RMD160 (NetBSD-6.0/prep/binary/kernel/netbsd-GENERIC.gz) = 9a642cc44881b1f2b6049710d159f7a4ffa0f25d +MD5 (NetBSD-6.0/prep/binary/kernel/netbsd-GENERIC.gz) = 2a37ae4ea5cdc2702db0dba34cf7be3c +SHA1 (NetBSD-6.0/prep/binary/kernel/netbsd-INSTALL.gz) = c138618a1e3ab93778033de4e66966f08e047d2b +SHA512 (NetBSD-6.0/prep/binary/kernel/netbsd-INSTALL.gz) = b4045a71215ac632950cae3022d9d2d7ce9af9d225ffd8a0e775093e934cc4b0492f1e95167bcb7bc245bb9d5f3390de974158b0d0ea8146fd54bc40199ed10f +RMD160 (NetBSD-6.0/prep/binary/kernel/netbsd-INSTALL.gz) = 5a2a9371e99acf25730bdd8e9826afc16257560b +MD5 (NetBSD-6.0/prep/binary/kernel/netbsd-INSTALL.gz) = 3aaa4706000b77fc8078bf2dc572c746 +SHA1 (NetBSD-6.0/prep/binary/kernel/netbsd-INSTALL_SMALL.symbols.gz) = 1ef4af8edaba52436270f4eabc0549fd8c57767d +SHA512 (NetBSD-6.0/prep/binary/kernel/netbsd-INSTALL_SMALL.symbols.gz) = fba7441719c1023b2719179ad017ac8e4c7a99499d2152ce75dc54014cfb55eecd0bb50e549ce976e1a5d58b420cd60416db364ed8633682a7c9c66a22af1329 +RMD160 (NetBSD-6.0/prep/binary/kernel/netbsd-INSTALL_SMALL.symbols.gz) = 428a02bccd74b8b6462a0ec5ecfebab5a9576def +MD5 (NetBSD-6.0/prep/binary/kernel/netbsd-INSTALL_SMALL.symbols.gz) = 901fb77c124b0ba7923d535a65a06fa6 +SHA1 (NetBSD-6.0/prep/binary/kernel/netbsd-INSTALL_SMALL.gz) = ec4f1dffaaffea221d480df7dfe89d7a129dd9b1 +SHA512 (NetBSD-6.0/prep/binary/kernel/netbsd-INSTALL_SMALL.gz) = d5ee09d3d063a6a816b7fd0fd3fa3d0251e1b056ec75368bf557e79836afc0292274d3642d9afedbfb4893a4d4cca97e4f1d0d859db60e3a8b644d9826e57d94 +RMD160 (NetBSD-6.0/prep/binary/kernel/netbsd-INSTALL_SMALL.gz) = 0bfa88f9965abca2ffa342158b4e1621183887e1 +MD5 (NetBSD-6.0/prep/binary/kernel/netbsd-INSTALL_SMALL.gz) = 8d52534cc5095a06286d6644f2ede176 +SHA1 (NetBSD-6.0/prep/binary/sets/games.tgz) = fbf69640b362df2446d7414ac3a13db100c289eb +SHA512 (NetBSD-6.0/prep/binary/sets/games.tgz) = d86b41d79aea4204ccf45306937a5ec45629e37873a5956c0280fd1d54cf4a808542d097f9d978fd3277791554ce8a6fb4d0ccd46e30210549d5cce1145bb499 +RMD160 (NetBSD-6.0/prep/binary/sets/games.tgz) = fd2aed1eb51f4db522fb5163e8fde4c040b55d30 +MD5 (NetBSD-6.0/prep/binary/sets/games.tgz) = 997ae5fb42196a787df89873be321e47 +SHA1 (NetBSD-6.0/prep/binary/sets/man.tgz) = 899b9d8242e983a5110ab755651c24f709b5af67 +SHA512 (NetBSD-6.0/prep/binary/sets/man.tgz) = 410999db110d710f4bb498c3d7ae7adc62170c7c2f470ce189c92f6c436c5ea96149659c631ef0b5605caaa025d97dfe1c07c428d86f51239657bd6b71717b15 +RMD160 (NetBSD-6.0/prep/binary/sets/man.tgz) = c1270f68c6d41b351877f71f0396ac34877dfc8d +MD5 (NetBSD-6.0/prep/binary/sets/man.tgz) = df4db2bbfa39ef6a4a215d949653d04a +SHA1 (NetBSD-6.0/prep/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/prep/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/prep/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/prep/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/prep/binary/sets/xcomp.tgz) = 960dd33b61e19dec92096a54791aca1cdf56ce54 +SHA512 (NetBSD-6.0/prep/binary/sets/xcomp.tgz) = 111dd50041e4008aeadb898c3d08f9995c5c13a41ccc20993b4ad51c81d7f6ee3b4dab16158ac7436d085b80e4a643b236a9c97edd3e915125a1466154538420 +RMD160 (NetBSD-6.0/prep/binary/sets/xcomp.tgz) = 0cf8b9a8d1489a32ba0b5a277d90e429c40650fb +MD5 (NetBSD-6.0/prep/binary/sets/xcomp.tgz) = 4ba4077ca2c0edf71813165fcf5321fb +SHA1 (NetBSD-6.0/prep/binary/sets/xfont.tgz) = 4711fcbade0238d60b7b89cf0d7873b03d7ed1f7 +SHA512 (NetBSD-6.0/prep/binary/sets/xfont.tgz) = c29130f55f536f602253a7f92f073ebf6ba02baea09f8011530bbf7e03ae96594334f0c60b29a8bceaffc3eb8b152db47548e38a3c8a14abc5fe35bc5d1d7d93 +RMD160 (NetBSD-6.0/prep/binary/sets/xfont.tgz) = 3b01af0f8e34367988d559fe0fbb0acbbafb0b2b +MD5 (NetBSD-6.0/prep/binary/sets/xfont.tgz) = 6ba15ed12217b726d9129db8e942a048 +SHA1 (NetBSD-6.0/prep/binary/sets/kern-GENERIC.tgz) = 7ea9bbc043530351e4dfc3ac54ce19938a412ec4 +SHA512 (NetBSD-6.0/prep/binary/sets/kern-GENERIC.tgz) = 0123955eb6ead53c99c21e1dcd5b17f62f228c35e8d17c9f540291f0022574e2ae331a9aebc2ed947cc0cabf439fa47c59e8f820eb8e5241b6446eb79c11bdee +RMD160 (NetBSD-6.0/prep/binary/sets/kern-GENERIC.tgz) = ef4531ac387b909f96b2cd3079ba8f12ecc61aa9 +MD5 (NetBSD-6.0/prep/binary/sets/kern-GENERIC.tgz) = 3d31ea9358a8ba0d7cb49ae1baf77e52 +SHA1 (NetBSD-6.0/prep/binary/sets/base.tgz) = 586f23dd6c50c12204650c92632bf016c9e4d57e +SHA512 (NetBSD-6.0/prep/binary/sets/base.tgz) = 712c63416a188e041d85155a36248e5580df0aace895b045b9a2a6cb68f5cb80315dd7f731e5a79139ee19d670c7278e44561336e1224c56a71f89ece1aa79ac +RMD160 (NetBSD-6.0/prep/binary/sets/base.tgz) = 11a21367c332428fc4e855764763276bae636fb3 +MD5 (NetBSD-6.0/prep/binary/sets/base.tgz) = 8d8b79b420ca775f8a7f33a109e40f0a +SHA1 (NetBSD-6.0/prep/binary/sets/comp.tgz) = 2ecb14f0695750113144390d254e685c1c41331a +SHA512 (NetBSD-6.0/prep/binary/sets/comp.tgz) = 7f8528e32862466f82158d4a60e46cf04a9c451b13655d2f25e929bf9df3dcda5c90e1e491457be3a82caea35cb2cfafdd307286e82bbddc466e8b929f44c322 +RMD160 (NetBSD-6.0/prep/binary/sets/comp.tgz) = 8ac4b55abc59b0089485a58d43d304c23dfa7519 +MD5 (NetBSD-6.0/prep/binary/sets/comp.tgz) = 7dc818422b8bdb702d921d284f0f1246 +SHA1 (NetBSD-6.0/prep/binary/sets/etc.tgz) = 56d8194e33b3ee4a1c059b1435e89a915add1275 +SHA512 (NetBSD-6.0/prep/binary/sets/etc.tgz) = 4b5eb6c9222bdcc591d9e6ad9e0781fcaa6a3bb981fe7d5f4b7137ec8df902b9fb979ea419db313dc1a823dbbdc284204b46872516d8f801f18854f75da74d68 +RMD160 (NetBSD-6.0/prep/binary/sets/etc.tgz) = 4b2fb8d900c22be6844c8931cf4c660954d123e4 +MD5 (NetBSD-6.0/prep/binary/sets/etc.tgz) = 553a0fb84d187ff3c420d5b5dc7287eb +SHA1 (NetBSD-6.0/prep/binary/sets/modules.tgz) = 60eb72b005b0e80f397d42ed5d78fea15e867a1c +SHA512 (NetBSD-6.0/prep/binary/sets/modules.tgz) = 98ef7da109a52a1814d3a7ff1c6377fd30140cc9783a919d6b3331226b1ea3c7b168598fb3102533637e24ad48be9f265063c0a55043e6614ae5959a56ba0aba +RMD160 (NetBSD-6.0/prep/binary/sets/modules.tgz) = 214a8c4490e3ba6d6a4861d19bc88700de79a2b8 +MD5 (NetBSD-6.0/prep/binary/sets/modules.tgz) = 775b2278852b97f68453f62cb4a1fabd +SHA1 (NetBSD-6.0/prep/binary/sets/tests.tgz) = baf4e3d6a0237d7eac65eca2d3e571ccde49c97d +SHA512 (NetBSD-6.0/prep/binary/sets/tests.tgz) = beea30696935343ffd119c696e826a617a189dd4e9be2a08f468207f0dfa518af4164a1c0bfb6e8d796f609888ef2e1c8d2b1481c58309cd3077cf361118052a +RMD160 (NetBSD-6.0/prep/binary/sets/tests.tgz) = 8547af5c43e56924032b7b7205c61c7dfb90c018 +MD5 (NetBSD-6.0/prep/binary/sets/tests.tgz) = fad9ca518beadf4a15db6b0aace1d019 +SHA1 (NetBSD-6.0/prep/binary/sets/text.tgz) = 265ca8e29442ca31af66219963a9931d7f71fcd0 +SHA512 (NetBSD-6.0/prep/binary/sets/text.tgz) = 50cd104f35d738fded65600514abc46f96dbcc010f13cade2131a3aad0feb7cf1208360d5869114ca13276096a83e4960ff2f342c1c58b04c26232bc23a8d950 +RMD160 (NetBSD-6.0/prep/binary/sets/text.tgz) = bf0370ee7934a80fdd3dadfe68b2124a7d1a3784 +MD5 (NetBSD-6.0/prep/binary/sets/text.tgz) = 2305e5d5fe891fca62f8500eaf7e32ec +SHA1 (NetBSD-6.0/prep/binary/sets/xbase.tgz) = a9c6040c6de18dcf42371b7eb0eaa88cb005f1e6 +SHA512 (NetBSD-6.0/prep/binary/sets/xbase.tgz) = 2f5640b41005ccc6b989454a60ae68f9637d701aca7e62a0c5f9965efda0bed43891a239be22ef2f837d0769ce54a649b9e357a920f007778e182d7362feb3e3 +RMD160 (NetBSD-6.0/prep/binary/sets/xbase.tgz) = b171d2bf07e02360363a642a9ccf6b624bdb85cf +MD5 (NetBSD-6.0/prep/binary/sets/xbase.tgz) = f1029043dab956ff0864f197dc1c0875 +SHA1 (NetBSD-6.0/prep/binary/sets/xetc.tgz) = 3d9da3ee21149017269ed1870b2c5c1096e9ed50 +SHA512 (NetBSD-6.0/prep/binary/sets/xetc.tgz) = d971316b80d139e87b2f7fa47f64ecc41a6285e002986165268e551b0ab059ffa332b9e9278b1e86d60829dac01f8c7cdd3a36f047f0e4a50469046456dbce46 +RMD160 (NetBSD-6.0/prep/binary/sets/xetc.tgz) = e6a7c17de4ac3a609498d8005165277e34f40b8d +MD5 (NetBSD-6.0/prep/binary/sets/xetc.tgz) = 8ad7ef8013d48e0ca196e8fd2a4fd0aa +SHA1 (NetBSD-6.0/prep/binary/sets/xserver.tgz) = 16190128b64666ba44729a72387061d80fd14c1e +SHA512 (NetBSD-6.0/prep/binary/sets/xserver.tgz) = 8f9b3a559b5b53dc2161128db89509e12bb3adc951dd51141212c5082e3afc19b6bd5d960900e7986c72a6ee664ebab7473e2119657c1f34cfebb05737655b6f +RMD160 (NetBSD-6.0/prep/binary/sets/xserver.tgz) = d62cfac8d16c1e56e866fe621b3cb5bbace44d07 +MD5 (NetBSD-6.0/prep/binary/sets/xserver.tgz) = eafffc08a401b7b8e92e47968dc8faaf +SHA1 (NetBSD-6.0/prep/installation/floppy/generic_com0.fs) = 7bfb784953be9b7b783a4d7927b8795441ec6096 +SHA512 (NetBSD-6.0/prep/installation/floppy/generic_com0.fs) = 59567fa24b9801e9aaba2fa0b85245b3c1a34894e6f2f58c39877bdb3053b3e21cce4cad703d60626466a2c0d2cd75715919df4a3acacefa627d19946123a840 +RMD160 (NetBSD-6.0/prep/installation/floppy/generic_com0.fs) = 0614c7375a11ffba581e95ea182aef3b59f7f624 +MD5 (NetBSD-6.0/prep/installation/floppy/generic_com0.fs) = b93c25c459836cca031a48a788ac7c78 +SHA1 (NetBSD-6.0/prep/installation/floppy/generic.fs) = c4d629bee0746f9d60ffb5ee501e4e9e73ef3724 +SHA512 (NetBSD-6.0/prep/installation/floppy/generic.fs) = 4df78c22f6a3d4ad414bb85ff6305a0d5caa97cc88375f3bdb2f3872e8103135f5716e72d564fe5fd3b7c1dbf7353f5464317ca30feb7187599186320da0a912 +RMD160 (NetBSD-6.0/prep/installation/floppy/generic.fs) = 7e34800d3411adb3862a914554d3ad27f7775e02 +MD5 (NetBSD-6.0/prep/installation/floppy/generic.fs) = c40503911a43d7bb98c5a5224c776666 +SHA1 (NetBSD-6.0/prep/installation/floppy/sysinst_com0.fs) = 3d67fecfe7d82c9cf7479152b092bd106b87f2fd +SHA512 (NetBSD-6.0/prep/installation/floppy/sysinst_com0.fs) = 929443de2610ee9409ed76468aa9645a917bdc03366267e8483cc83bbcecb35208acc06ef0d2520d389b408b566c113f5e6b71f5568a7e1c029532979221682f +RMD160 (NetBSD-6.0/prep/installation/floppy/sysinst_com0.fs) = 51197c7d8ae21a29cf54064c3cf11f8d1eeef956 +MD5 (NetBSD-6.0/prep/installation/floppy/sysinst_com0.fs) = d1e27f1504e7dfeeab0714332e89fda2 +SHA1 (NetBSD-6.0/prep/installation/floppy/sysinst.fs) = 47998496e145c48564efadaf91f3ba4aede44ccd +SHA512 (NetBSD-6.0/prep/installation/floppy/sysinst.fs) = 6688642f8ad525611b7757bfaa63c958abc0cc1f0c17219df85055c7d97c20896156a543992bbcaf08bfe1bfe36e112e8c8af8610c971585dffa27ae2083d410 +RMD160 (NetBSD-6.0/prep/installation/floppy/sysinst.fs) = d674830e0387841948abeb5e194ab60d9ab942fd +MD5 (NetBSD-6.0/prep/installation/floppy/sysinst.fs) = 3164ba344aa2283cc7aca4efbd627dd3 +SHA1 (NetBSD-6.0/prep/installation/floppy/sysinst_small_com0.fs) = 2614d29a10f74be3e6ec6563046d2129976f3e1e +SHA512 (NetBSD-6.0/prep/installation/floppy/sysinst_small_com0.fs) = 061156a6e9e1f9130d9ae085838526f027f3f4263ed03ebc3b5a4532e75243715bc554e4a0ad307401c792f35334d79653642e0d2e1e438dbacc246cda1a92fc +RMD160 (NetBSD-6.0/prep/installation/floppy/sysinst_small_com0.fs) = 58ef2e610b17686a92958917250c4252bf2d2530 +MD5 (NetBSD-6.0/prep/installation/floppy/sysinst_small_com0.fs) = e1b821660c4f9a7b22a9069631fcefcb +SHA1 (NetBSD-6.0/prep/installation/floppy/sysinst_small.fs) = 73f7d288f4026018498e79c14d362eeb5e25ef01 +SHA512 (NetBSD-6.0/prep/installation/floppy/sysinst_small.fs) = b65d0794537f5dea1b2a3d6afbd08b85d6d97193a6f0c69928b2edb3fd90c1202035df882878e8f45ddca7214a1abd28e312ab6c334a0708bea0daa1a2686a94 +RMD160 (NetBSD-6.0/prep/installation/floppy/sysinst_small.fs) = b40f136693485d517b455f0443614a487904776b +MD5 (NetBSD-6.0/prep/installation/floppy/sysinst_small.fs) = 3d605afd5b9a7b57949f448c43e8274c +SHA1 (NetBSD-6.0/prep/INSTALL.html) = 2674ff3a673f19a61cac4e2877a5656f053b2a3f +SHA512 (NetBSD-6.0/prep/INSTALL.html) = aabbf165a39dc0207f39cfd27508821de8e50d26892baa27daf1a9b1a01841777fa59a147baa2fc082ebe5ee1f7cafd27674ea44c3e9410179bfbafb33130b49 +RMD160 (NetBSD-6.0/prep/INSTALL.html) = a818880156d01aebc4c92e2e82677fb0890e92c4 +MD5 (NetBSD-6.0/prep/INSTALL.html) = c716d934eb76805dd4acbd677ef13fe5 +SHA1 (NetBSD-6.0/prep/INSTALL.more) = f408ad8a753e682120f22e8763d9e20d8eeda7ed +SHA512 (NetBSD-6.0/prep/INSTALL.more) = 0a27fc0b1bc6bdf44bc2aced239066f13e352ff248d8ed50d430e676bba3132f26ba807259fda765738bc915a6765fab2fd2e97e04b0166a50cefc4c88de38d2 +RMD160 (NetBSD-6.0/prep/INSTALL.more) = 5cc22227f3a244681cc352cc364650ad683c2fc1 +MD5 (NetBSD-6.0/prep/INSTALL.more) = 69c4b26606cf1e071a451c5afab13cd0 +SHA1 (NetBSD-6.0/prep/INSTALL.ps) = 9ab023c53af56e033541d6c27abf9b666b3f6a06 +SHA512 (NetBSD-6.0/prep/INSTALL.ps) = b68f21d8587797e750a6eabe92273481a396bf68d62e300e6e07139439144660d1e8769404b109759707bccf02a97b27fde4aed219f2b760e9e1f65c0b8c7016 +RMD160 (NetBSD-6.0/prep/INSTALL.ps) = baf09ab6b65aa90ca2f415e4428e21edf2d6d7a5 +MD5 (NetBSD-6.0/prep/INSTALL.ps) = dd269cf99b1eb54e0f7c376c10330ec4 +SHA1 (NetBSD-6.0/prep/INSTALL.txt) = 38f3b013b2b744dd7e21df3db8308dad808e45cd +SHA512 (NetBSD-6.0/prep/INSTALL.txt) = 2a42b7a45500710fd4df5f3883f8fef5aac4416c41a54c532ce358255541fbf3cd1e5ae03863f1721d845c82caab792d5c8d85feba2cd87225edc8f5606de585 +RMD160 (NetBSD-6.0/prep/INSTALL.txt) = 71583c4ea3b65f1e17ccede286d6025fb6f281cf +MD5 (NetBSD-6.0/prep/INSTALL.txt) = 15bc48222a898edd8de0a70f559c4a4e +SHA1 (NetBSD-6.0/rs6000/binary/kernel/netbsd-INSTALL.symbols.gz) = e7fddbe9a6fe76bfec3ec556acf83101b6b1b27d +SHA512 (NetBSD-6.0/rs6000/binary/kernel/netbsd-INSTALL.symbols.gz) = 7a96ad902221852bdbc290707be328b8374e69d7339165e8af54a65abc17707a1177c2534306ba28e066eaca2eb1cd9bd76fcceaffef911926dacd88c22e3edb +RMD160 (NetBSD-6.0/rs6000/binary/kernel/netbsd-INSTALL.symbols.gz) = 3f5d25d432d08fa0458c087a3928d3370e60d080 +MD5 (NetBSD-6.0/rs6000/binary/kernel/netbsd-INSTALL.symbols.gz) = f7adcf576fff9a965730d8cb07b677c3 +SHA1 (NetBSD-6.0/rs6000/binary/kernel/netbsd-GENERIC.gz) = 3786662f4c42751a4ad0475d5b7674ba8ecf6113 +SHA512 (NetBSD-6.0/rs6000/binary/kernel/netbsd-GENERIC.gz) = d0ecc5a21218668d185cc74f70ccd066dd08c39ca5e092966623857e7e0e0a9e0d350a055e8f54ed96a046e970ac6e8fbefe3aca12f8cbb238a1240858353dfb +RMD160 (NetBSD-6.0/rs6000/binary/kernel/netbsd-GENERIC.gz) = edfd5c086e4207543b08fa1125d137a436a17caa +MD5 (NetBSD-6.0/rs6000/binary/kernel/netbsd-GENERIC.gz) = d2909133467c780a0364052df6f5a906 +SHA1 (NetBSD-6.0/rs6000/binary/kernel/netbsd-INSTALL.gz) = 0588aeaa722ae0065f1e5d92187e088c75000be7 +SHA512 (NetBSD-6.0/rs6000/binary/kernel/netbsd-INSTALL.gz) = 53b6d6603b831ffbb5016ab99f61a20fad9900bbd76b18cd33608c499ad1d2b7a07dd3d0ea386bc27f1f9a8fe68db48691e128186cb4a810c82eca63e8e04e8c +RMD160 (NetBSD-6.0/rs6000/binary/kernel/netbsd-INSTALL.gz) = 4bbcd396759fe15f6052ec4ebf5b1ab0d1780a77 +MD5 (NetBSD-6.0/rs6000/binary/kernel/netbsd-INSTALL.gz) = 2a0d673dd3b76fbdef31325f905bf6f2 +SHA1 (NetBSD-6.0/rs6000/binary/sets/man.tgz) = 899b9d8242e983a5110ab755651c24f709b5af67 +SHA512 (NetBSD-6.0/rs6000/binary/sets/man.tgz) = 410999db110d710f4bb498c3d7ae7adc62170c7c2f470ce189c92f6c436c5ea96149659c631ef0b5605caaa025d97dfe1c07c428d86f51239657bd6b71717b15 +RMD160 (NetBSD-6.0/rs6000/binary/sets/man.tgz) = c1270f68c6d41b351877f71f0396ac34877dfc8d +MD5 (NetBSD-6.0/rs6000/binary/sets/man.tgz) = df4db2bbfa39ef6a4a215d949653d04a +SHA1 (NetBSD-6.0/rs6000/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/rs6000/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/rs6000/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/rs6000/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/rs6000/binary/sets/kern-GENERIC.tgz) = 953706a28ce3b7a195c738f805b6ecf878555e93 +SHA512 (NetBSD-6.0/rs6000/binary/sets/kern-GENERIC.tgz) = a699aa0db691fd82015721bf9aab0b201574798731a795112cbe358a61f7fc3b4b1b0540abd25fc52b4c44692b81c4fe400dc6f90315d97563c32c1e2ef12a27 +RMD160 (NetBSD-6.0/rs6000/binary/sets/kern-GENERIC.tgz) = 697ddaf6582c2712860f4c5abd80537b50da0059 +MD5 (NetBSD-6.0/rs6000/binary/sets/kern-GENERIC.tgz) = 6d7ea95cdb07cb265eda9f09ca484ac9 +SHA1 (NetBSD-6.0/rs6000/binary/sets/base.tgz) = c973cd9af8b007e754b99ead0517ab7bed7d3fa3 +SHA512 (NetBSD-6.0/rs6000/binary/sets/base.tgz) = a82112dc5f53f010f6c259a543502b6a0d90259169233b2b043786cfa677ace8ed63f648dd738cc08730d6ac35233a2b1b60cd606222f399546b5f0a61488656 +RMD160 (NetBSD-6.0/rs6000/binary/sets/base.tgz) = 0e84db039067d0ee045bdae56557595dfeb51935 +MD5 (NetBSD-6.0/rs6000/binary/sets/base.tgz) = af2472e60e90aafe55028b419b776975 +SHA1 (NetBSD-6.0/rs6000/binary/sets/comp.tgz) = 2dcac8a8c80d565b5373277deec9a67aee293370 +SHA512 (NetBSD-6.0/rs6000/binary/sets/comp.tgz) = b6b94000d67080ab3ff62768c3afa85ee4a63a0ee62440648bb8c1728c6e4df9b72cc13927e012d9eee0a73792f2ce5e22d6c9d86eaa7c4a6789643177b44371 +RMD160 (NetBSD-6.0/rs6000/binary/sets/comp.tgz) = fc6b3a3b6bb9613f29c50451190dba5fc7884df2 +MD5 (NetBSD-6.0/rs6000/binary/sets/comp.tgz) = e7c6fcfdf054fef00feececd660789ca +SHA1 (NetBSD-6.0/rs6000/binary/sets/etc.tgz) = 302c5ba7b8efb24364748a665f5cfb824f6068b5 +SHA512 (NetBSD-6.0/rs6000/binary/sets/etc.tgz) = 1ab1027b3082336f54fa330dd4d21924a42a4f76602d35bb2108229b745b305356c5f944247d0b9bfda63f66318a8ad6525eaf5af42cb3a8d0c3cf6e8b4d45b7 +RMD160 (NetBSD-6.0/rs6000/binary/sets/etc.tgz) = 21418d6a16eb9e779b5e6d86cc411c9ab531453b +MD5 (NetBSD-6.0/rs6000/binary/sets/etc.tgz) = 695e526865e9cf18c91a35647fd75bf8 +SHA1 (NetBSD-6.0/rs6000/binary/sets/games.tgz) = 0a7cc1be35944ade7ef1c617e0bb5f1a60a891e5 +SHA512 (NetBSD-6.0/rs6000/binary/sets/games.tgz) = dacf177fc2affd7189a7cb7b166bf0b3f6b1a92cf1358f1dad2c5e364d28a7183f841befea024435b0f125cf4008741c26f98e5860ea3872d7a8c36e0e699430 +RMD160 (NetBSD-6.0/rs6000/binary/sets/games.tgz) = 2620719e3f39dc3137ebb8f47fcbe482d77ff5e7 +MD5 (NetBSD-6.0/rs6000/binary/sets/games.tgz) = 175c85d188b3c9b4922c4aaa7adc3dc3 +SHA1 (NetBSD-6.0/rs6000/binary/sets/modules.tgz) = a710b61251bc52c73e64a0254489fd7ca7fb766b +SHA512 (NetBSD-6.0/rs6000/binary/sets/modules.tgz) = a39d57fa5428c4734bf521afdd1356df4213980a9180b4bb28731b5ff7c22b606b2b2189cfba9741cc98fa049ae01a26516c1096969f2b0b17d24e1d1112eb94 +RMD160 (NetBSD-6.0/rs6000/binary/sets/modules.tgz) = ebbd79b609edee28f4c8331d5dfef0e510f67d9e +MD5 (NetBSD-6.0/rs6000/binary/sets/modules.tgz) = 825a589361390bbf9d409497e022b2ef +SHA1 (NetBSD-6.0/rs6000/binary/sets/tests.tgz) = a0eb45c7b71306f6cacafd52bf8f7f06b9d5fabc +SHA512 (NetBSD-6.0/rs6000/binary/sets/tests.tgz) = 4a95458b6a260485c6fa3d136abc9c76c6764f870d30bbf4f7c78c86233241366f84bc5cf7d7be0a3ccf49afd7f5c95e0f732d4164d6f32a01f953ac51a529de +RMD160 (NetBSD-6.0/rs6000/binary/sets/tests.tgz) = 67ec4f342cf6d25a56f4b0b62675b12df01ae445 +MD5 (NetBSD-6.0/rs6000/binary/sets/tests.tgz) = 1ccae2c93acbafe1ffc9dc329c8a73de +SHA1 (NetBSD-6.0/rs6000/binary/sets/text.tgz) = ec4ec898eb442d2f8d86aaca0ce5490c7dc1722b +SHA512 (NetBSD-6.0/rs6000/binary/sets/text.tgz) = cbf687bd4d20115e4f993b08ed41dde158b39a0133af78503c41b3240e7f7aeef3a015594eeb423d6a8c7d74549646e06170eb7dee86d76919163083c81a27d9 +RMD160 (NetBSD-6.0/rs6000/binary/sets/text.tgz) = e638a4bf115fc0fa2e4ef7d5399d79597762b94d +MD5 (NetBSD-6.0/rs6000/binary/sets/text.tgz) = 6e84e62deb9c45636b7047e88a6b1dce +SHA1 (NetBSD-6.0/rs6000/binary/sets/xbase.tgz) = 143ea7f8f94f52bf946db4dbf3fccb963f0006fd +SHA512 (NetBSD-6.0/rs6000/binary/sets/xbase.tgz) = 66442666aa2e6b9139ae8acf690e1c671edb34160977f786332b6f18c87d8be537160b4d8a114b48660a09cdb349890514b9cd6c3cf12a2f5c3e49e6ef070ed0 +RMD160 (NetBSD-6.0/rs6000/binary/sets/xbase.tgz) = f28a5be274784cb9b35ca7c9a452e6fb1758562f +MD5 (NetBSD-6.0/rs6000/binary/sets/xbase.tgz) = ba48685231270484c0e79da384a77a28 +SHA1 (NetBSD-6.0/rs6000/binary/sets/xcomp.tgz) = 1b1dda90e8376c39a124f39cb8f09824e1d88599 +SHA512 (NetBSD-6.0/rs6000/binary/sets/xcomp.tgz) = c53a3e10df7ec1ddc2687ebf299a37f0b721f83df64797b64968bf1ebf2cdf7becd0ea8505a6a77864e9119c8817aa78deccac0d198b9c815f750a248fdbd5ba +RMD160 (NetBSD-6.0/rs6000/binary/sets/xcomp.tgz) = 4d57950bc653c7030f7ccae430f5b00812f106c2 +MD5 (NetBSD-6.0/rs6000/binary/sets/xcomp.tgz) = 0cbd6372a9d8cc2488e23708a105f563 +SHA1 (NetBSD-6.0/rs6000/binary/sets/xetc.tgz) = a1c99d1c17918fad811cf27b08625a0b1461f583 +SHA512 (NetBSD-6.0/rs6000/binary/sets/xetc.tgz) = 567bf3cde35f4e54ad9875625c64895d28a5c8accbfb0d5339ca523a9192c312db7ee3c44f9fde3fb5a765839630d282fa59fbe483f5deed16811bb82d8bb3be +RMD160 (NetBSD-6.0/rs6000/binary/sets/xetc.tgz) = 263747682247c8c38b367970ff103f92d92b0fae +MD5 (NetBSD-6.0/rs6000/binary/sets/xetc.tgz) = e69bc3b1b38e787aff9d1df386ac63e6 +SHA1 (NetBSD-6.0/rs6000/binary/sets/xfont.tgz) = ebe1c8e3f81f06dc9a816b1ff31240517e9b102d +SHA512 (NetBSD-6.0/rs6000/binary/sets/xfont.tgz) = 11f0db11eacf0ee00ecafa091c0f9cee84402dcf44a4467d809355d464eb698ff805acfc3da5752b167a2398a1f1080c93e3ca1ed8f08a6129ffe4e4a2402da1 +RMD160 (NetBSD-6.0/rs6000/binary/sets/xfont.tgz) = 7997ed31cdf3895e1fc12b024314c1b72d94be89 +MD5 (NetBSD-6.0/rs6000/binary/sets/xfont.tgz) = 9e4241f680bc0b0303a0aa682b61b1c9 +SHA1 (NetBSD-6.0/rs6000/binary/sets/xserver.tgz) = e0f7bcff652a034a14b70eb608f9d48a21cff87e +SHA512 (NetBSD-6.0/rs6000/binary/sets/xserver.tgz) = 9838dce48efcde1f60ff163b1c5da7a19d414c730d97d8db7ed19ac77a52f27f2294ba24de75f15fd4d11a30a97830ca2f68b4311379505208025b2ea4913644 +RMD160 (NetBSD-6.0/rs6000/binary/sets/xserver.tgz) = 9072c3c3519475c71ea42925c529ce5e323e9661 +MD5 (NetBSD-6.0/rs6000/binary/sets/xserver.tgz) = 997077c1eb372bf091c82bf06f96f7b6 +SHA1 (NetBSD-6.0/rs6000/installation/bootfs/boot.fs.gz) = 56e0afc45b285ce022bd561db40dcda0eb2fdca4 +SHA512 (NetBSD-6.0/rs6000/installation/bootfs/boot.fs.gz) = c88fa6848032305418c173e9bca58e76545523b762e5ef4f65bc84f1f820e5813a37dcd256af8b0352f5d6f6e1c700d888f5633d1ce58664cbc5886114aa5332 +RMD160 (NetBSD-6.0/rs6000/installation/bootfs/boot.fs.gz) = c575e56387f6956fd086bfeb5f85fed7a9fb4c27 +MD5 (NetBSD-6.0/rs6000/installation/bootfs/boot.fs.gz) = d47804a5227b204d2bea50e243a749ae +SHA1 (NetBSD-6.0/rs6000/INSTALL.html) = 0f891193771ae2bbe138549727d4df583dc39a94 +SHA512 (NetBSD-6.0/rs6000/INSTALL.html) = 84b1ae87d5befd27db8ed74276b95a91228bf60a05ecf610adacbddc7905cebbfa3909eb6fe8bed0c8f31bb92112fad398f9d4594204057892a538c16861551e +RMD160 (NetBSD-6.0/rs6000/INSTALL.html) = ca2e4dce100c234133c9da46ffb498d84e0115d3 +MD5 (NetBSD-6.0/rs6000/INSTALL.html) = 031cc1f873f6c8d6f6472b991915701e +SHA1 (NetBSD-6.0/rs6000/INSTALL.more) = d86963437bc21fb0eb944b4562b79aefcec5c511 +SHA512 (NetBSD-6.0/rs6000/INSTALL.more) = 130cf1977b54ee32332c7c1a2f35e9c19c088753ad8755ce48965aebc1cc19cd89f37f073749ee5f8b84223a8e8b3fc4a68993e0b22d35663c5850c419a0c84e +RMD160 (NetBSD-6.0/rs6000/INSTALL.more) = 7e35c4d92d61591cf32e7fc4f272734817b60eb8 +MD5 (NetBSD-6.0/rs6000/INSTALL.more) = 4bb3c03008a5857e2c1f7b30cd76f10e +SHA1 (NetBSD-6.0/rs6000/INSTALL.ps) = 52af7c1bd8dc0f193c6ebaad3320a0d9b9c82497 +SHA512 (NetBSD-6.0/rs6000/INSTALL.ps) = 44c13947238205228eecd13b48642f68179745ae8441ed58db4a3e7103c431a86c86d9ca88d0f71c656f1f0d54e2ebed8b395dbe1a9a437ccac79f91df7ff56b +RMD160 (NetBSD-6.0/rs6000/INSTALL.ps) = 545bc23ee542bce73f526bfb4184cc2b9314b0f4 +MD5 (NetBSD-6.0/rs6000/INSTALL.ps) = 06416001febd58f722bad81cc2a585d8 +SHA1 (NetBSD-6.0/rs6000/INSTALL.txt) = cfc54ae2bb8482e56b8b0e130285a78532b9772f +SHA512 (NetBSD-6.0/rs6000/INSTALL.txt) = 9fe957ce5896aa3ca77bf2b62a785904d22b21250e1ed6a18ca0b0e68268ba76f314948e052a0bbea78abe78e95a2d5ca51bf70b7cde2d935ab802a1e276b888 +RMD160 (NetBSD-6.0/rs6000/INSTALL.txt) = aa823cc8082e6b246dc65bce012fec305a7d3ef4 +MD5 (NetBSD-6.0/rs6000/INSTALL.txt) = b47464cee8c76f0b619c0a70acca22ca +SHA1 (NetBSD-6.0/sandpoint/binary/kernel/netbsd-INSTALL.symbols.gz) = d09224835f9948e426f67e0008e9e40de1a39635 +SHA512 (NetBSD-6.0/sandpoint/binary/kernel/netbsd-INSTALL.symbols.gz) = b130c4fc02e1783188dcb4b5a3f8fc88f4294cd331d3beddb039364aa8557c61cf050ccaf520fbbd8badeb018e1c676b589d6eff6a17189ae8edd3dc7d6f94d6 +RMD160 (NetBSD-6.0/sandpoint/binary/kernel/netbsd-INSTALL.symbols.gz) = cb79e2871b79e109038c8b7e62ec213695e9aff1 +MD5 (NetBSD-6.0/sandpoint/binary/kernel/netbsd-INSTALL.symbols.gz) = 5f38dd4085224ecbd6ecae5e07a92e1d +SHA1 (NetBSD-6.0/sandpoint/binary/kernel/netbsd-GENERIC.gz) = c315b6db09ef1d0161ad647352d9983b72da2ba9 +SHA512 (NetBSD-6.0/sandpoint/binary/kernel/netbsd-GENERIC.gz) = 27bf14f92d278fe7b4174cb265862fbd24c96a006f99e5d241f52fee928fdcaed13528f058d6e5cf78656ab7e0e17e974394a2dff8ab37664689ac8eeb457c61 +RMD160 (NetBSD-6.0/sandpoint/binary/kernel/netbsd-GENERIC.gz) = 4aa32ba67c19f07cc67a13835b3773b2bb8178d4 +MD5 (NetBSD-6.0/sandpoint/binary/kernel/netbsd-GENERIC.gz) = 87054c981c0647f65a1aa363c3ad3074 +SHA1 (NetBSD-6.0/sandpoint/binary/kernel/netbsd-INSTALL.gz) = b43de7e1f292d5d1e050668babd148e3310cbe81 +SHA512 (NetBSD-6.0/sandpoint/binary/kernel/netbsd-INSTALL.gz) = 0c591bfbaab13c5c0d03a50e0914a97444f87d9513ea48a96fa84e05ea1bed95a63a7ae3cf77c5c71f79cf774f1d1eef2b866c6125173e97027882bb37c38565 +RMD160 (NetBSD-6.0/sandpoint/binary/kernel/netbsd-INSTALL.gz) = 3bc37d3a7d32ba229944341349eee1d7498487c5 +MD5 (NetBSD-6.0/sandpoint/binary/kernel/netbsd-INSTALL.gz) = 1812ae09823196a8493b490db6d35829 +SHA1 (NetBSD-6.0/sandpoint/binary/kernel/netbsd-INSTALL_KURO.symbols.gz) = 81f74ee4373718b36152d797c812097688ce515e +SHA512 (NetBSD-6.0/sandpoint/binary/kernel/netbsd-INSTALL_KURO.symbols.gz) = e26f69d2d4df43224e12a922b2d1602678db53a8f7f5823776047ed0f1106e6ffcbaf6d88a4101a75bd3b298737971a99d82b806f78e70a7039dc1e8c027a0cb +RMD160 (NetBSD-6.0/sandpoint/binary/kernel/netbsd-INSTALL_KURO.symbols.gz) = 32e0b167f67afd79e83b8b5da906e7eb9822640b +MD5 (NetBSD-6.0/sandpoint/binary/kernel/netbsd-INSTALL_KURO.symbols.gz) = 31c633e475629988bf3addc50252b158 +SHA1 (NetBSD-6.0/sandpoint/binary/kernel/netbsd-INSTALL_KURO.gz) = b857802c9d1b447b451a50601e7592b6c72208a7 +SHA512 (NetBSD-6.0/sandpoint/binary/kernel/netbsd-INSTALL_KURO.gz) = ef8318f98fc351491b88805dfb1150beb5bac352b18504bbe4756fb9fc54b064ee442999e08fa2a0b82306e717dd100a8a45e02814c5a03d168f33d05c34bd1c +RMD160 (NetBSD-6.0/sandpoint/binary/kernel/netbsd-INSTALL_KURO.gz) = 4add6bd73eeaf1c25a9d732adad0e24304e39b39 +MD5 (NetBSD-6.0/sandpoint/binary/kernel/netbsd-INSTALL_KURO.gz) = 61015da4f88490480f8553e59599dbd2 +SHA1 (NetBSD-6.0/sandpoint/binary/kernel/netbsd-KUROBOX.gz) = a2b339d5cb7d614c94341cd9dc8928597275fdbf +SHA512 (NetBSD-6.0/sandpoint/binary/kernel/netbsd-KUROBOX.gz) = 44b9aa3d91de2f2e0d1c3ec42000182ad97fde311c2bebed17f21fa2165e9f2d574a2fff2330d9f9c2534e595e78bf1eb25e605158e62bf9c65fa449d4d426ef +RMD160 (NetBSD-6.0/sandpoint/binary/kernel/netbsd-KUROBOX.gz) = 8548f8853cf766e38388c6f16da063334cb4a8a1 +MD5 (NetBSD-6.0/sandpoint/binary/kernel/netbsd-KUROBOX.gz) = 9b8e45e5e31d018a614b2f9f2ec67f95 +SHA1 (NetBSD-6.0/sandpoint/binary/sets/games.tgz) = fbf69640b362df2446d7414ac3a13db100c289eb +SHA512 (NetBSD-6.0/sandpoint/binary/sets/games.tgz) = d86b41d79aea4204ccf45306937a5ec45629e37873a5956c0280fd1d54cf4a808542d097f9d978fd3277791554ce8a6fb4d0ccd46e30210549d5cce1145bb499 +RMD160 (NetBSD-6.0/sandpoint/binary/sets/games.tgz) = fd2aed1eb51f4db522fb5163e8fde4c040b55d30 +MD5 (NetBSD-6.0/sandpoint/binary/sets/games.tgz) = 997ae5fb42196a787df89873be321e47 +SHA1 (NetBSD-6.0/sandpoint/binary/sets/man.tgz) = 899b9d8242e983a5110ab755651c24f709b5af67 +SHA512 (NetBSD-6.0/sandpoint/binary/sets/man.tgz) = 410999db110d710f4bb498c3d7ae7adc62170c7c2f470ce189c92f6c436c5ea96149659c631ef0b5605caaa025d97dfe1c07c428d86f51239657bd6b71717b15 +RMD160 (NetBSD-6.0/sandpoint/binary/sets/man.tgz) = c1270f68c6d41b351877f71f0396ac34877dfc8d +MD5 (NetBSD-6.0/sandpoint/binary/sets/man.tgz) = df4db2bbfa39ef6a4a215d949653d04a +SHA1 (NetBSD-6.0/sandpoint/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/sandpoint/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/sandpoint/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/sandpoint/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/sandpoint/binary/sets/xbase.tgz) = b7c8146146ebc15191c1bf53f51f8f980fe8c816 +SHA512 (NetBSD-6.0/sandpoint/binary/sets/xbase.tgz) = 091f5d00414a9ad478811bfb0e953f2a204869bc5e310790886a59c11953974cf7068cd9a96c8823856ab2687ffa2ac31e97494f47338bfe31d80217382c59f1 +RMD160 (NetBSD-6.0/sandpoint/binary/sets/xbase.tgz) = 4bd1bfdc7c1e1619de63fb83276c21039b945357 +MD5 (NetBSD-6.0/sandpoint/binary/sets/xbase.tgz) = e621806afa0fcc9cdcef0f9b3c7dfcbd +SHA1 (NetBSD-6.0/sandpoint/binary/sets/xcomp.tgz) = 960dd33b61e19dec92096a54791aca1cdf56ce54 +SHA512 (NetBSD-6.0/sandpoint/binary/sets/xcomp.tgz) = 111dd50041e4008aeadb898c3d08f9995c5c13a41ccc20993b4ad51c81d7f6ee3b4dab16158ac7436d085b80e4a643b236a9c97edd3e915125a1466154538420 +RMD160 (NetBSD-6.0/sandpoint/binary/sets/xcomp.tgz) = 0cf8b9a8d1489a32ba0b5a277d90e429c40650fb +MD5 (NetBSD-6.0/sandpoint/binary/sets/xcomp.tgz) = 4ba4077ca2c0edf71813165fcf5321fb +SHA1 (NetBSD-6.0/sandpoint/binary/sets/xfont.tgz) = 4711fcbade0238d60b7b89cf0d7873b03d7ed1f7 +SHA512 (NetBSD-6.0/sandpoint/binary/sets/xfont.tgz) = c29130f55f536f602253a7f92f073ebf6ba02baea09f8011530bbf7e03ae96594334f0c60b29a8bceaffc3eb8b152db47548e38a3c8a14abc5fe35bc5d1d7d93 +RMD160 (NetBSD-6.0/sandpoint/binary/sets/xfont.tgz) = 3b01af0f8e34367988d559fe0fbb0acbbafb0b2b +MD5 (NetBSD-6.0/sandpoint/binary/sets/xfont.tgz) = 6ba15ed12217b726d9129db8e942a048 +SHA1 (NetBSD-6.0/sandpoint/binary/sets/xserver.tgz) = 05aac7e617e0cac05a88062fef29bb459da7a1d1 +SHA512 (NetBSD-6.0/sandpoint/binary/sets/xserver.tgz) = 19fb5af5d6afd78839a22e5c0694a492047b5200c569cbf58c676ff32ec250b21edcfe2ed00b65092fdac374d1ab9eaaed6113c69bc03009cf458aedc6014913 +RMD160 (NetBSD-6.0/sandpoint/binary/sets/xserver.tgz) = 774d2a1072b8d122790ad189a6d2ada2ad99e7cf +MD5 (NetBSD-6.0/sandpoint/binary/sets/xserver.tgz) = 3daf1477cadf3593e9ba45e3703fe8a5 +SHA1 (NetBSD-6.0/sandpoint/binary/sets/kern-GENERIC.tgz) = 3120fc2c7bad39d27640482bb99222862238a9bd +SHA512 (NetBSD-6.0/sandpoint/binary/sets/kern-GENERIC.tgz) = 38c1992332ac419fa5e630965bf0bac621fbea752cdec3c147bafdff55bf8b24343913cec8e645b3170cddb071ed501781a47048be08d03c21154c7cf0e2ff6c +RMD160 (NetBSD-6.0/sandpoint/binary/sets/kern-GENERIC.tgz) = 3964f06ff1e895fe07b28c6758713c82cf0eec72 +MD5 (NetBSD-6.0/sandpoint/binary/sets/kern-GENERIC.tgz) = 1ff2a1c2e3cb2d7f2fd9a270d9cae445 +SHA1 (NetBSD-6.0/sandpoint/binary/sets/base.tgz) = 9e8d3d9c03cbd6db0b99c34641dab20f5835b6bb +SHA512 (NetBSD-6.0/sandpoint/binary/sets/base.tgz) = 4eb8d796b52589cc4132777dbfeb5295ef44bbe83e1e7c804540d39b98dbf66d7b0805a8e00dcab835309c9a69b3ca518288e0992e53b773d588339da9bbe0ac +RMD160 (NetBSD-6.0/sandpoint/binary/sets/base.tgz) = 48e26330269decea0489889a395af45b39ad55ff +MD5 (NetBSD-6.0/sandpoint/binary/sets/base.tgz) = 2f7c4bf56ff06bf89e9c5d49b1154805 +SHA1 (NetBSD-6.0/sandpoint/binary/sets/comp.tgz) = 8f217e53da02ee1bf5445f76ccccd7262aaad680 +SHA512 (NetBSD-6.0/sandpoint/binary/sets/comp.tgz) = 71a6e2221f054534477100908bb3ae686e88eeed96bc7d28920b39863d10881e6951d39011f65415d50c2cadc78874582a1d7f0505c29fbef25800003310febb +RMD160 (NetBSD-6.0/sandpoint/binary/sets/comp.tgz) = 8507052499e85b2c4d6fd985f3d0ddc099732443 +MD5 (NetBSD-6.0/sandpoint/binary/sets/comp.tgz) = cb3a0690211b22d68a64e941711cc03e +SHA1 (NetBSD-6.0/sandpoint/binary/sets/etc.tgz) = 6b44f637dd5d01718b446128da95e0bb37c1682a +SHA512 (NetBSD-6.0/sandpoint/binary/sets/etc.tgz) = 8795d966d0da1b5419f50e577036167ab6e5de5589080ed0ee6903e0d3b59ae9bfd2395d7951b2b38a025acc39daf302a3d22212e0a6ba94344889d7f99d9d57 +RMD160 (NetBSD-6.0/sandpoint/binary/sets/etc.tgz) = df0e4d773d5a180fba5b21b73cb6aabdaec11487 +MD5 (NetBSD-6.0/sandpoint/binary/sets/etc.tgz) = c8ec3910d995970ea51634c4f126474a +SHA1 (NetBSD-6.0/sandpoint/binary/sets/kern-KUROBOX.tgz) = b4c7f1bc4058463ebb759d84f0ed8a5613cb3c44 +SHA512 (NetBSD-6.0/sandpoint/binary/sets/kern-KUROBOX.tgz) = 50df0ca65f4f7ed454cc4176eb26b63df738d658536d63dfcacf8ea6def0cf3f4778d686b19ff4f5b32dd07e862f9b0d753ac34c93eedc21f47bd27a0ab5a7df +RMD160 (NetBSD-6.0/sandpoint/binary/sets/kern-KUROBOX.tgz) = a86947596f1a0b658f0cf664ddd67c05385efb56 +MD5 (NetBSD-6.0/sandpoint/binary/sets/kern-KUROBOX.tgz) = 30f2e8b4824b9cedf289c6cdd46df34e +SHA1 (NetBSD-6.0/sandpoint/binary/sets/modules.tgz) = 7c4b66eea61f3cd7bebee7421f78ddabdce86b26 +SHA512 (NetBSD-6.0/sandpoint/binary/sets/modules.tgz) = db987ae1a97bcaec2085bec2e33c49a53dedad2499e91db24570b50b6f83cd3387e2be0fd6f23dd0611f676133c5fb524c06a4c42c864b41acd74b88e1a2eb34 +RMD160 (NetBSD-6.0/sandpoint/binary/sets/modules.tgz) = 24ff5d8cba57c1fd9aac448c121d8b5446c3d7aa +MD5 (NetBSD-6.0/sandpoint/binary/sets/modules.tgz) = 380e4c6e51bf10cf6fd605b12332badf +SHA1 (NetBSD-6.0/sandpoint/binary/sets/tests.tgz) = 45a3f3ff64bc425bfd332e018456252756b0b3af +SHA512 (NetBSD-6.0/sandpoint/binary/sets/tests.tgz) = 37a7200f8d06849b2eb8e82a19284edcba07a3445ffa40725f288d09eb4e6dba18856b97c64b24373c3c191343c64df2bb2cd5ea8b1367ccae239cb1db9755b8 +RMD160 (NetBSD-6.0/sandpoint/binary/sets/tests.tgz) = ff0eaa5ae045658f2e34b26ee39f41fc03f40589 +MD5 (NetBSD-6.0/sandpoint/binary/sets/tests.tgz) = 19128cd2482ccb19f4486a6090b89d41 +SHA1 (NetBSD-6.0/sandpoint/binary/sets/text.tgz) = 8f4f8a5d09b63477d2a051e2d628b512363ae893 +SHA512 (NetBSD-6.0/sandpoint/binary/sets/text.tgz) = e24825ec69e7b195c384e0fc83bd56a39598721ee30bde5dafc433e24fbedc2e5555a628ec1df0427cff6691f11040e244abd2f8f518421cdf53a94aca7752c6 +RMD160 (NetBSD-6.0/sandpoint/binary/sets/text.tgz) = 264071e66052088a2a9c93b7d030331aa64dc522 +MD5 (NetBSD-6.0/sandpoint/binary/sets/text.tgz) = 3a05d3c0c3a0074852621cc38b0afe82 +SHA1 (NetBSD-6.0/sandpoint/binary/sets/xetc.tgz) = 80be15e90a6779956ecd9acecae91936d1417c2d +SHA512 (NetBSD-6.0/sandpoint/binary/sets/xetc.tgz) = fa0fd709723b8c3768f9797e34f30dc3cd8a16e3bf178beb883ccddf5041f196fe85828a32e3296c24f96a8a942927aac4587142705d7cd6ce8ffbcc6d4a2fda +RMD160 (NetBSD-6.0/sandpoint/binary/sets/xetc.tgz) = 02d7f0088ce5bda4f14607ca80de273d00a82137 +MD5 (NetBSD-6.0/sandpoint/binary/sets/xetc.tgz) = e285972d692807df05e4f96ac34ef6f0 +SHA1 (NetBSD-6.0/sandpoint/installation/altboot.bin) = 56c653262e9e672cd47728f06dbf1428a7a16604 +SHA512 (NetBSD-6.0/sandpoint/installation/altboot.bin) = 0ff15a1e8f4fdff1c97f5539c69c4f40e1bbec0ceb6d3ae0df8e6e472fa25dd1b44398135cff0995ca21389819fba455b70a59e2af6fcc817781e09b1b11a3f5 +RMD160 (NetBSD-6.0/sandpoint/installation/altboot.bin) = 7fd0c6c48de76b1fb04eb16a2cbd53531f67d78f +MD5 (NetBSD-6.0/sandpoint/installation/altboot.bin) = a2b44c7df7a4199c917096623275d178 +SHA1 (NetBSD-6.0/sandpoint/installation/altboot) = 420331106c0a0f28c0cb27f39016852d65f47533 +SHA512 (NetBSD-6.0/sandpoint/installation/altboot) = 7569cc668f087aa5a2af3ed0f231cdc8a0364cf7f64fcb06b08b3aab17e3bd295bcc8f2c8175f1efe73a1e7cca4ba459d35e65872fa8436d729697517dedfe29 +RMD160 (NetBSD-6.0/sandpoint/installation/altboot) = ef26fc304a3f7bfa4717b03a4544207b44e2c382 +MD5 (NetBSD-6.0/sandpoint/installation/altboot) = a5c881881c99da3587d7db293ce8b453 +SHA1 (NetBSD-6.0/sandpoint/installation/altboot.img) = 9db4851a0e6349ca1ae912e60a329b8f250bb51b +SHA512 (NetBSD-6.0/sandpoint/installation/altboot.img) = 2bfb5c17dcfa6f1619f398a6f994f57be2f2a5e5bee0d2542bfe076f46d13567cf5519ccbea8bc97962122073bcb002309509caa06eab11014ee85766d813410 +RMD160 (NetBSD-6.0/sandpoint/installation/altboot.img) = a140607e1b7ba43d76b22db739253f59234398bd +MD5 (NetBSD-6.0/sandpoint/installation/altboot.img) = f007fcb1d420ec5ab2f662013f78663a +SHA1 (NetBSD-6.0/sandpoint/INSTALL.html) = 87c1358b7dd97f4166607bc031ee8fd603d8a2c9 +SHA512 (NetBSD-6.0/sandpoint/INSTALL.html) = b27b71a7b9fe4a37e2ffe20eb09588a3e3aa1337aa7936c064a35752b02ff8b1f560f053206db9ddc4b0a7a5f9163f221dba4690c54f3791fdccdf791b1893ed +RMD160 (NetBSD-6.0/sandpoint/INSTALL.html) = 790a76dee78dc46f35cf2b4f6078d699707d2adb +MD5 (NetBSD-6.0/sandpoint/INSTALL.html) = b1a454f7901f9b043c6993ba09ce7e20 +SHA1 (NetBSD-6.0/sandpoint/INSTALL.more) = 60d0c93b382dfe57cc87c292f3cb53f66bc0ef7e +SHA512 (NetBSD-6.0/sandpoint/INSTALL.more) = 6b1ac0a4e00aee1bcf54d434b02b41102927bb125be551b0cf8cd25016104b3a03f3bf40506bc6076ed3af4a8128a81f733d523e5ccc3679cd8b51bba105cc27 +RMD160 (NetBSD-6.0/sandpoint/INSTALL.more) = 46c78bd1d9df63eeed2f580faaabbac38f5757dd +MD5 (NetBSD-6.0/sandpoint/INSTALL.more) = f317efc426b562d069a20655d45d361a +SHA1 (NetBSD-6.0/sandpoint/INSTALL.ps) = f67cac326fc01aa5d0e47013afb174ce0962a46b +SHA512 (NetBSD-6.0/sandpoint/INSTALL.ps) = ab10cc2d28735af2a34ab85a4c84d7da346375a964a65ba9a328cd93b4b55c6badba306bd7093be08b662695d8ad82e96c4def014a7bac3f711767c9b741c33f +RMD160 (NetBSD-6.0/sandpoint/INSTALL.ps) = 5db8cd9595e21ecf5132a9bfb2574aaa01260515 +MD5 (NetBSD-6.0/sandpoint/INSTALL.ps) = c36aec246e63cd311c87bdd6ff54f28a +SHA1 (NetBSD-6.0/sandpoint/INSTALL.txt) = 545b47f56ca866c03078d60d49d3276d4d000648 +SHA512 (NetBSD-6.0/sandpoint/INSTALL.txt) = d7a925733a465005a83a915d9c58ded20149a6118013493b687c7b0ef2e816d8340631828ce1ec7ca13400c0d7a2dbe86c4fed363baf84ba288cb57a47384f89 +RMD160 (NetBSD-6.0/sandpoint/INSTALL.txt) = 1a30cf24c59bd8394d8748102ceb9027d81d66d1 +MD5 (NetBSD-6.0/sandpoint/INSTALL.txt) = 25fb074abc8d6bd5c9aec25dcf7c3667 +SHA1 (NetBSD-6.0/sbmips-mipseb/binary/kernel/netbsd-GENERIC.gz) = f23f0dec597709dddd3a0ee1d355f7beb9110b46 +SHA512 (NetBSD-6.0/sbmips-mipseb/binary/kernel/netbsd-GENERIC.gz) = c07b4b1360396b00184b77c19fda5ddb4463eef2fddf2c9ba43cbc4e7b0548e79999928db4f662046f73e282051bef9912f497c91b3757d60a1a11a520c3703f +RMD160 (NetBSD-6.0/sbmips-mipseb/binary/kernel/netbsd-GENERIC.gz) = 22b4ec375839d277a7cddcfdf9df0a122a9cba19 +MD5 (NetBSD-6.0/sbmips-mipseb/binary/kernel/netbsd-GENERIC.gz) = b4ee3e5e49f3bdf6fed5e7f9028fe2f1 +SHA1 (NetBSD-6.0/sbmips-mipseb/binary/sets/games.tgz) = f56d3e5181634f6a3d7908dcb002ebcb1c5aaff0 +SHA512 (NetBSD-6.0/sbmips-mipseb/binary/sets/games.tgz) = 0cff50ea13e34fe338edf70da6a28af061580feb4cb0773828adefa631ebd471a96568a3b30ea0f13f3bb116856a1b6aad8a5a52443346f52e4907f4caabc5f1 +RMD160 (NetBSD-6.0/sbmips-mipseb/binary/sets/games.tgz) = 1538910578dbb8eee2931200fac0ccda44758e5f +MD5 (NetBSD-6.0/sbmips-mipseb/binary/sets/games.tgz) = 2bd5bd0ce72df5cf92767b8c3f7cc208 +SHA1 (NetBSD-6.0/sbmips-mipseb/binary/sets/man.tgz) = 899b9d8242e983a5110ab755651c24f709b5af67 +SHA512 (NetBSD-6.0/sbmips-mipseb/binary/sets/man.tgz) = 410999db110d710f4bb498c3d7ae7adc62170c7c2f470ce189c92f6c436c5ea96149659c631ef0b5605caaa025d97dfe1c07c428d86f51239657bd6b71717b15 +RMD160 (NetBSD-6.0/sbmips-mipseb/binary/sets/man.tgz) = c1270f68c6d41b351877f71f0396ac34877dfc8d +MD5 (NetBSD-6.0/sbmips-mipseb/binary/sets/man.tgz) = df4db2bbfa39ef6a4a215d949653d04a +SHA1 (NetBSD-6.0/sbmips-mipseb/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/sbmips-mipseb/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/sbmips-mipseb/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/sbmips-mipseb/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/sbmips-mipseb/binary/sets/xbase.tgz) = d81c7fe75a90f1b2111a066e78f1f2b3e8edcd8c +SHA512 (NetBSD-6.0/sbmips-mipseb/binary/sets/xbase.tgz) = c241391fcde4a685a0a2af6f843844ac2e918024c447a2b5ea2cf5300f69acc42fdadf53d3b0348f10723b786bcc0f420e68fe36228375bf3cb5140de41eb40f +RMD160 (NetBSD-6.0/sbmips-mipseb/binary/sets/xbase.tgz) = 2fbf60b64c0b7ac2be72ebf998d9d7390fc40705 +MD5 (NetBSD-6.0/sbmips-mipseb/binary/sets/xbase.tgz) = cd23ca0f6b359c4d695d4494a147d40f +SHA1 (NetBSD-6.0/sbmips-mipseb/binary/sets/xcomp.tgz) = c8f5ff5ea9f9bbe231f92d8b7f3bfcbd2897069f +SHA512 (NetBSD-6.0/sbmips-mipseb/binary/sets/xcomp.tgz) = c7590075195019078b68ec5f87e36479ae2e7b7749c523df4ef21c9d881c343cda9f5c2bba897dd313329a76fe5c18e920d92827878d98ce08a7dc776352cd02 +RMD160 (NetBSD-6.0/sbmips-mipseb/binary/sets/xcomp.tgz) = bc60e267cb6e11b4a7305f8b7074084e179e0ff5 +MD5 (NetBSD-6.0/sbmips-mipseb/binary/sets/xcomp.tgz) = 8e58ee51667def3bd015f79769c0d932 +SHA1 (NetBSD-6.0/sbmips-mipseb/binary/sets/xfont.tgz) = c551bd13179b9508c2e3a7e19cec323e8ba21844 +SHA512 (NetBSD-6.0/sbmips-mipseb/binary/sets/xfont.tgz) = 764527f2f3f4686759fcae3fd093f4e00f34e1249994126221a6f9afe73d4cf8ddfbe8b8311798da2ed38c52466a44bb26ea08ad5aab1c08eebcc9019b4223f7 +RMD160 (NetBSD-6.0/sbmips-mipseb/binary/sets/xfont.tgz) = b3a365bedf8b4a20f3920d0e33b9a42fce288953 +MD5 (NetBSD-6.0/sbmips-mipseb/binary/sets/xfont.tgz) = adac8939da213a0195cc1d351f979199 +SHA1 (NetBSD-6.0/sbmips-mipseb/binary/sets/xserver.tgz) = 686f6e6d722c9676351ab058736f7077b4ebd2f6 +SHA512 (NetBSD-6.0/sbmips-mipseb/binary/sets/xserver.tgz) = 5c818f22edbeac7325228af99d6da6e44b5eb659c7c9fcc6b332071e97a0a490081eda7f9e0f22d6a3f3a589ae34179b434751a6191db5c664683d7510aecedc +RMD160 (NetBSD-6.0/sbmips-mipseb/binary/sets/xserver.tgz) = 0e9f066095b505c7f062bf877147189a7a2f0649 +MD5 (NetBSD-6.0/sbmips-mipseb/binary/sets/xserver.tgz) = cdd2e5127838437df40af161e0c8398f +SHA1 (NetBSD-6.0/sbmips-mipseb/binary/sets/kern-GENERIC.tgz) = 3dee2d103b30c27015f41f351b45247d1f1067af +SHA512 (NetBSD-6.0/sbmips-mipseb/binary/sets/kern-GENERIC.tgz) = d9393724341c9d8036646fc768c21cb510aa4915555460753caded9c1f7a5355501d801e72ffb12e3ac1d25a57797b3b9b8c38787f7ae42906c6dbfecd0bf384 +RMD160 (NetBSD-6.0/sbmips-mipseb/binary/sets/kern-GENERIC.tgz) = 9e22ac41f53032ad9194b1b0002c56c13211cf65 +MD5 (NetBSD-6.0/sbmips-mipseb/binary/sets/kern-GENERIC.tgz) = 6b9b0560a05738c70d580a25e0c5f203 +SHA1 (NetBSD-6.0/sbmips-mipseb/binary/sets/base.tgz) = 61ec72dd34b2103b7b2f3228ee7766133a089c29 +SHA512 (NetBSD-6.0/sbmips-mipseb/binary/sets/base.tgz) = 9aa13fa9008c18633f949ee74c5aaa5fa1d58d59459e48cf5f161d3f11e133a0cdaf7caa941a4e435076644ea799d7c9e73274267b18c3401866fdae5444f491 +RMD160 (NetBSD-6.0/sbmips-mipseb/binary/sets/base.tgz) = ebc31ee01aa8cf119d20f5e084d536bcc610623b +MD5 (NetBSD-6.0/sbmips-mipseb/binary/sets/base.tgz) = 828ed9e45442d989a4a5233b6523d82e +SHA1 (NetBSD-6.0/sbmips-mipseb/binary/sets/comp.tgz) = 705bd29c423e517e231920389f853990b8103339 +SHA512 (NetBSD-6.0/sbmips-mipseb/binary/sets/comp.tgz) = 33d7feebe4ce7a3f8a4317c49f10f51e69e40374a9291c6b9e657f3e965d533702513b92dba0cba318a786f33fb5f275237be13870c093dc229d2c826a6b15ae +RMD160 (NetBSD-6.0/sbmips-mipseb/binary/sets/comp.tgz) = ea75f4ad366964a45cc5c8aac35cee5a56460d6a +MD5 (NetBSD-6.0/sbmips-mipseb/binary/sets/comp.tgz) = e37746a52cc63d8d2992aef55484bb81 +SHA1 (NetBSD-6.0/sbmips-mipseb/binary/sets/etc.tgz) = 9b4b768dc9d999330aa8fe804d604738fbabf650 +SHA512 (NetBSD-6.0/sbmips-mipseb/binary/sets/etc.tgz) = 6e56a5122f29741aa02b651671d5ecdaef0adac94f52c8d550ab8a17352d3fa6755a87c13bd707d1a7f4259fef1c77e4ec85699cabb96bac5c47b82f2fdb6086 +RMD160 (NetBSD-6.0/sbmips-mipseb/binary/sets/etc.tgz) = c2c3fbfe163cc38ff774413c1be35f0fee0b0c3f +MD5 (NetBSD-6.0/sbmips-mipseb/binary/sets/etc.tgz) = 3d6d678755b01ec623ed215f7e1bbbc6 +SHA1 (NetBSD-6.0/sbmips-mipseb/binary/sets/modules.tgz) = de0c98fc8b4bb81299edb50e3f99f222ac383dcf +SHA512 (NetBSD-6.0/sbmips-mipseb/binary/sets/modules.tgz) = c279717a8c4a6c66f3dff4e22d72466cf7b2c82070bba336bce5e659dc520c8c1fa1ef80f6f3154b665e0fb76dc2745ac8cf3996389209966f3976c36dc591c2 +RMD160 (NetBSD-6.0/sbmips-mipseb/binary/sets/modules.tgz) = 80479a2131441999c8d251d822e00800e4f69b9c +MD5 (NetBSD-6.0/sbmips-mipseb/binary/sets/modules.tgz) = cef9345e5430560c5955adee76e537c5 +SHA1 (NetBSD-6.0/sbmips-mipseb/binary/sets/tests.tgz) = 92c135698d2030f4b378f18fc991c9f4efbcbf1a +SHA512 (NetBSD-6.0/sbmips-mipseb/binary/sets/tests.tgz) = 7fde9b55e820f169c4d1820d5b3f213f460c81bf892df6bff0ccf47ee73054c651c7277d956af77eb6f3d75648c7916be72d08dc3970601dc872662f009e9117 +RMD160 (NetBSD-6.0/sbmips-mipseb/binary/sets/tests.tgz) = 38049cb62625ec093f26a53f6fdad2bce0b5a2ee +MD5 (NetBSD-6.0/sbmips-mipseb/binary/sets/tests.tgz) = dfc74f3ea392e2c963257cb48926147c +SHA1 (NetBSD-6.0/sbmips-mipseb/binary/sets/text.tgz) = f8ddb7ac8fe765ad3760b3c00516f209f31ba211 +SHA512 (NetBSD-6.0/sbmips-mipseb/binary/sets/text.tgz) = 9e8f6eb5da98c7c88d96d539e5379bf98f0d6726b84c5d4c2e1236d515d3cc31a4e1deedf1beab8335084f0c8d2795e8bef3391feff024d654877cd105254e03 +RMD160 (NetBSD-6.0/sbmips-mipseb/binary/sets/text.tgz) = fc5441996f0f1650b41b80cdeacd377cec93c8ca +MD5 (NetBSD-6.0/sbmips-mipseb/binary/sets/text.tgz) = 22ad03bdad15b336ac4f73bc31c29d78 +SHA1 (NetBSD-6.0/sbmips-mipseb/binary/sets/xetc.tgz) = f89ac267632b07b88fa020f09c395a6766a2b9b1 +SHA512 (NetBSD-6.0/sbmips-mipseb/binary/sets/xetc.tgz) = 59325ee391ab258e507fad56e2f38e5062c2ca15599c71ed06bd0373dfb109d61605dad949434d521d5ab9ea6139ee099919d485cb6d680d20b1bffc6881fd9a +RMD160 (NetBSD-6.0/sbmips-mipseb/binary/sets/xetc.tgz) = 6e805117acfbb8c9af9eb6f105b15c11447faaa8 +MD5 (NetBSD-6.0/sbmips-mipseb/binary/sets/xetc.tgz) = 3e113c15bdfceb0a896ebfcee6e75172 +SHA1 (NetBSD-6.0/sbmips-mipsel/binary/kernel/netbsd-GENERIC.gz) = 017c9fbd7101f94f65ae9f0a41a1a028a8bd3435 +SHA512 (NetBSD-6.0/sbmips-mipsel/binary/kernel/netbsd-GENERIC.gz) = 45e2aa91e69a575f02a48dd776cc7401f37e60905ffc986634f53829aabc87d2dfc52840fc92821a3611b61e728f415ac44ab19f73db85786962df64d87b60c6 +RMD160 (NetBSD-6.0/sbmips-mipsel/binary/kernel/netbsd-GENERIC.gz) = 56ea720eb521974e26c07d74f93fcebd6e67de91 +MD5 (NetBSD-6.0/sbmips-mipsel/binary/kernel/netbsd-GENERIC.gz) = e5f16d9d0838695b251b809dd42e10b9 +SHA1 (NetBSD-6.0/sbmips-mipsel/binary/sets/games.tgz) = 27d9f98fecb3495e51939df9f107e81e527af26f +SHA512 (NetBSD-6.0/sbmips-mipsel/binary/sets/games.tgz) = 46bb4e10313cfffaaf4f7fa2157474ef940f94bcc9f84b46f829c7615bbf45e4e01edee7b7efb84bc28561e0712c37cfc737f9c2a0d9a73b67c80c8aa0f3a9af +RMD160 (NetBSD-6.0/sbmips-mipsel/binary/sets/games.tgz) = 947feea90ec2698a65d555cb78a29a001b086589 +MD5 (NetBSD-6.0/sbmips-mipsel/binary/sets/games.tgz) = 355f00978fed8e8da6a251e591be5387 +SHA1 (NetBSD-6.0/sbmips-mipsel/binary/sets/man.tgz) = 899b9d8242e983a5110ab755651c24f709b5af67 +SHA512 (NetBSD-6.0/sbmips-mipsel/binary/sets/man.tgz) = 410999db110d710f4bb498c3d7ae7adc62170c7c2f470ce189c92f6c436c5ea96149659c631ef0b5605caaa025d97dfe1c07c428d86f51239657bd6b71717b15 +RMD160 (NetBSD-6.0/sbmips-mipsel/binary/sets/man.tgz) = c1270f68c6d41b351877f71f0396ac34877dfc8d +MD5 (NetBSD-6.0/sbmips-mipsel/binary/sets/man.tgz) = df4db2bbfa39ef6a4a215d949653d04a +SHA1 (NetBSD-6.0/sbmips-mipsel/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/sbmips-mipsel/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/sbmips-mipsel/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/sbmips-mipsel/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/sbmips-mipsel/binary/sets/xbase.tgz) = 76468fcada5a9e26652aa9f0f9f3c94829a317e9 +SHA512 (NetBSD-6.0/sbmips-mipsel/binary/sets/xbase.tgz) = b2adcfc2dedef30b21b885c8fc757d0479541744a280a9997fbeaa9c881009ab4b0019e0001a540a8eb6db5f84db87b365e420bb2d4270af209821bdb080369c +RMD160 (NetBSD-6.0/sbmips-mipsel/binary/sets/xbase.tgz) = 1e0074d03d9fbb3373e0a427b25cc7097bf6d3c8 +MD5 (NetBSD-6.0/sbmips-mipsel/binary/sets/xbase.tgz) = a8f29ec2e3768405942f97af3dd08ee7 +SHA1 (NetBSD-6.0/sbmips-mipsel/binary/sets/xcomp.tgz) = d8ac89f3f6ff20abb0adabc49227afdb74aa2040 +SHA512 (NetBSD-6.0/sbmips-mipsel/binary/sets/xcomp.tgz) = 4f03213fb061dae9421747209628d06ede6bbb71a7560a9e1a54796b907f1620146a33fdce52974227a21acedcc210b99e15c4fdd36432eba60c1041a92d8cee +RMD160 (NetBSD-6.0/sbmips-mipsel/binary/sets/xcomp.tgz) = 6be5e72b9b57c9bdf8ed8ea127e2a73830feeecb +MD5 (NetBSD-6.0/sbmips-mipsel/binary/sets/xcomp.tgz) = 59a7ea141587417be38ab1f6056cc780 +SHA1 (NetBSD-6.0/sbmips-mipsel/binary/sets/xetc.tgz) = b9f6b1a54ffab37b11f4c6e717b481cd087fb609 +SHA512 (NetBSD-6.0/sbmips-mipsel/binary/sets/xetc.tgz) = 72f35e65f3a90967e250a2006d500619b3824f7f5c3d7494554f153ec5cda5b28c445f28c34a1e4463f40da5855e8d4257726411796967fe37763d90cf7fe461 +RMD160 (NetBSD-6.0/sbmips-mipsel/binary/sets/xetc.tgz) = 1169c246f91189fd0c4ae86ac27a92f5c2edda3e +MD5 (NetBSD-6.0/sbmips-mipsel/binary/sets/xetc.tgz) = 8f3c52cc5af1cafaf7b0d0f884a5b537 +SHA1 (NetBSD-6.0/sbmips-mipsel/binary/sets/xfont.tgz) = d06848571034f3b7fc975082f1de37b912acb18c +SHA512 (NetBSD-6.0/sbmips-mipsel/binary/sets/xfont.tgz) = 66a1013c935bee5e7e5d24325a527522306bcded7ced63790f2e58831b3ed91176a1b9510b2159be63504d5167d48d534919927ffc6e225ae2bb2487f90a9ede +RMD160 (NetBSD-6.0/sbmips-mipsel/binary/sets/xfont.tgz) = c9502843a5d4dd7e996e8d158c519cf7f8575cbd +MD5 (NetBSD-6.0/sbmips-mipsel/binary/sets/xfont.tgz) = e812899176eac2bf65a6d949ac3f3424 +SHA1 (NetBSD-6.0/sbmips-mipsel/binary/sets/xserver.tgz) = ff805022f409202f3346c45475c7ec0f8187218e +SHA512 (NetBSD-6.0/sbmips-mipsel/binary/sets/xserver.tgz) = f2bb3810a5572b519980126a3d934f63b5ab5c2fcf9fb8166c556bd3cc14cfaa151d582086bb1506ac9ac7e21d4e70a5cd5c3faed96212d8a14a0b5bafdcc4c1 +RMD160 (NetBSD-6.0/sbmips-mipsel/binary/sets/xserver.tgz) = d5ae336337cc77f7f55f542b3457918d6fc0efe8 +MD5 (NetBSD-6.0/sbmips-mipsel/binary/sets/xserver.tgz) = 92447a1560887d337d22e2deed0670a6 +SHA1 (NetBSD-6.0/sbmips-mipsel/binary/sets/kern-GENERIC.tgz) = 8c185e51bf6d6c63d23ce62fd86e5f7bfb3d3845 +SHA512 (NetBSD-6.0/sbmips-mipsel/binary/sets/kern-GENERIC.tgz) = 6f1a341b96a6890f1bfe68a588e74639caec8c320b72bac774f03d8f7e71d9198887b791e6528a10bd201bb14537e2f83a4e81aa402adc5bd57e4ada3c8022a9 +RMD160 (NetBSD-6.0/sbmips-mipsel/binary/sets/kern-GENERIC.tgz) = 43be2a6c07b4b366d31b2b74ce7666d0337cb84c +MD5 (NetBSD-6.0/sbmips-mipsel/binary/sets/kern-GENERIC.tgz) = 1ad137c19b7c2df8bcb8bfbe053466d6 +SHA1 (NetBSD-6.0/sbmips-mipsel/binary/sets/base.tgz) = d0664b8cdc36b3e6b0381b6a9de9c7556bd383ef +SHA512 (NetBSD-6.0/sbmips-mipsel/binary/sets/base.tgz) = 737f1bed2c71e1473483bec24e7e48be28fca93e0ccb7e124661569d1960fa99bfdfc7f8e86bd3a61f744593346ef767b1ae2ed0c1e2fb9c5b421dd2b8125dcb +RMD160 (NetBSD-6.0/sbmips-mipsel/binary/sets/base.tgz) = 130c2d1408fad9b0c2e8c612b6d720a6c92674b6 +MD5 (NetBSD-6.0/sbmips-mipsel/binary/sets/base.tgz) = c2623377960d1a7fe4db1ffff70882f2 +SHA1 (NetBSD-6.0/sbmips-mipsel/binary/sets/comp.tgz) = ed63cf25383b8110ece9e4cb4752fe762b636cd5 +SHA512 (NetBSD-6.0/sbmips-mipsel/binary/sets/comp.tgz) = f699747ae04f024400653aa5bf5be624e4cd0bd92c9086ee8f89ce9327c5adb27e7cc53f1a85904b3e0f2cbbb49e45a3098fc803e131338a3100a56f1628218e +RMD160 (NetBSD-6.0/sbmips-mipsel/binary/sets/comp.tgz) = ca975dc6b36da0208cc2a79c346e74fe367ba833 +MD5 (NetBSD-6.0/sbmips-mipsel/binary/sets/comp.tgz) = 063da88eb27db9b012142fbec1707b34 +SHA1 (NetBSD-6.0/sbmips-mipsel/binary/sets/etc.tgz) = a6430055b2ccc0d418f11c4eb5628d091998d4f3 +SHA512 (NetBSD-6.0/sbmips-mipsel/binary/sets/etc.tgz) = 51a2c3cbb860e042c3ecc234e1e0645489a5546ccf0c87a2925f32c01dfb3fbc1dd088b4bc947cb27c731b9645f234e13fa9e805665be34aa3fe9318c51d12a7 +RMD160 (NetBSD-6.0/sbmips-mipsel/binary/sets/etc.tgz) = a7c1913e10b8fdc44a191159b5b6278728bd8a0a +MD5 (NetBSD-6.0/sbmips-mipsel/binary/sets/etc.tgz) = 690495c3b0cbba76f83085422161887c +SHA1 (NetBSD-6.0/sbmips-mipsel/binary/sets/modules.tgz) = 37c4fabb3a3edebf715572a4c7deca5c2f63508f +SHA512 (NetBSD-6.0/sbmips-mipsel/binary/sets/modules.tgz) = 2245821ee48c5a4a4c7ad378c2d726975b18a3f04b1e4cf04e78ee0c15855502eca0673b11420af837146c9003ec6c9899b815a37aef06632b9e8a00f4f95f0d +RMD160 (NetBSD-6.0/sbmips-mipsel/binary/sets/modules.tgz) = 2ae1af8e754811706b0d5633f2631a306eee664a +MD5 (NetBSD-6.0/sbmips-mipsel/binary/sets/modules.tgz) = 3136834e1ac671cf35958f353e33d8c0 +SHA1 (NetBSD-6.0/sbmips-mipsel/binary/sets/tests.tgz) = d3118b0c152c61b20933e5dc38272991b808fce0 +SHA512 (NetBSD-6.0/sbmips-mipsel/binary/sets/tests.tgz) = ce817f1900de3b09a7b063abed50f10f78042f3000f1bb031963db7eb1666fb55b42ffcf446370b4ef2541ea86739e43c9bf0771aba86f5bcd62e6181975a62b +RMD160 (NetBSD-6.0/sbmips-mipsel/binary/sets/tests.tgz) = 6fe992cf685d12015118ce0faf06d77b241e10d6 +MD5 (NetBSD-6.0/sbmips-mipsel/binary/sets/tests.tgz) = d59a11116844dc6e6a754ab8676e30f3 +SHA1 (NetBSD-6.0/sbmips-mipsel/binary/sets/text.tgz) = 82712c2413930b0726af1cc8e3d7f7183e789534 +SHA512 (NetBSD-6.0/sbmips-mipsel/binary/sets/text.tgz) = 2681e2fd0973fa7573dd6a1746ba7c491956a82256a8522cbb65c267402ba700da71b0ce44c65269787385e596913ba1042eca4542e5751f55beaa2679d673d7 +RMD160 (NetBSD-6.0/sbmips-mipsel/binary/sets/text.tgz) = aba3f473d85e3a8fd5ae41ca25c7433a22b11f36 +MD5 (NetBSD-6.0/sbmips-mipsel/binary/sets/text.tgz) = 0b2dbc9b54843ba81289bc994b3fcf7a +SHA1 (NetBSD-6.0/sgimips/binary/kernel/netbsd-INSTALL32_IP2x.symbols.gz) = b1a8652e56663a63c6376ecf20ccf9f8f876a9e8 +SHA512 (NetBSD-6.0/sgimips/binary/kernel/netbsd-INSTALL32_IP2x.symbols.gz) = 3e4a01eeec83c7da8725badd449c51dcc677203373d1ca0725a157a6f9ebee86fa8ca7d66e1936420569e7152fe9bf2089764b94132aa04d61e36661ea0d1b32 +RMD160 (NetBSD-6.0/sgimips/binary/kernel/netbsd-INSTALL32_IP2x.symbols.gz) = ae01910e3901d7adf1b925f13b4520e46bce2917 +MD5 (NetBSD-6.0/sgimips/binary/kernel/netbsd-INSTALL32_IP2x.symbols.gz) = 14b2804f6c6f16940d4bdda28c6426e1 +SHA1 (NetBSD-6.0/sgimips/binary/kernel/netbsd-GENERIC32_IP12.ecoff.gz) = 532b94eea6032bf2867a860f78973c95b3baf210 +SHA512 (NetBSD-6.0/sgimips/binary/kernel/netbsd-GENERIC32_IP12.ecoff.gz) = a3017e2f1bc7d008d45d53f3733ed573c18de5d44c2c7a1e969f2938119a5d6996c1eb913e7ef6b28cddfb2e6da4e4ddb6aaddbb9caa6c43b90d046f2ba396db +RMD160 (NetBSD-6.0/sgimips/binary/kernel/netbsd-GENERIC32_IP12.ecoff.gz) = bfbcc81a415674512ffdaa8ad7180d4499fd410d +MD5 (NetBSD-6.0/sgimips/binary/kernel/netbsd-GENERIC32_IP12.ecoff.gz) = 01742badd90ac599c850ef5d7f98de49 +SHA1 (NetBSD-6.0/sgimips/binary/kernel/netbsd-GENERIC32_IP12.gz) = 1040bc406f9543efe4f2a6c198d136ef45d0e9f7 +SHA512 (NetBSD-6.0/sgimips/binary/kernel/netbsd-GENERIC32_IP12.gz) = 1bb8fe9e495603393f69f25ac5fe57d8f26e64cc1573af4088d3e2929d8043ecff721d38b0d4f3f6b6934661df6f6f2790d1d506ced6f8f21b57c1f1554e79a2 +RMD160 (NetBSD-6.0/sgimips/binary/kernel/netbsd-GENERIC32_IP12.gz) = eece122ff5df495cfee6fafeba2fb086cce6623b +MD5 (NetBSD-6.0/sgimips/binary/kernel/netbsd-GENERIC32_IP12.gz) = 8bc4a605a8cb06bfcf835aa4a5b16411 +SHA1 (NetBSD-6.0/sgimips/binary/kernel/netbsd-GENERIC32_IP2x.ecoff.gz) = 0fa0539d5bdaa751a71d3df4a573adb90d742cb3 +SHA512 (NetBSD-6.0/sgimips/binary/kernel/netbsd-GENERIC32_IP2x.ecoff.gz) = 4e94bbc422b322b6b250a8cdf31144cb97f6349a2cd075b8720497dbae36dc9f90d0b48da549bbfd3d7908bdf078cc95e300bde365df6e204008a0af85a5e7e6 +RMD160 (NetBSD-6.0/sgimips/binary/kernel/netbsd-GENERIC32_IP2x.ecoff.gz) = ec847458dd2c3b20dcd27d5bc14ced2601c998e5 +MD5 (NetBSD-6.0/sgimips/binary/kernel/netbsd-GENERIC32_IP2x.ecoff.gz) = e74b65c6a2f141174323dfe40cc0e730 +SHA1 (NetBSD-6.0/sgimips/binary/kernel/netbsd-GENERIC32_IP2x.gz) = 2c863ba399e4aad44ef7b76dc60bcedbc112d1dc +SHA512 (NetBSD-6.0/sgimips/binary/kernel/netbsd-GENERIC32_IP2x.gz) = 27c329497ed9ac49c096071c6250b01135b590b9d2f5d79366f53409b4abf9daeca15f323a35521b9a79f4264d5784e1d49dec269cc51ee0df52a686bf6fea88 +RMD160 (NetBSD-6.0/sgimips/binary/kernel/netbsd-GENERIC32_IP2x.gz) = 410dae1e4c4a5b3f2b9b000c413faa6ccedddd5e +MD5 (NetBSD-6.0/sgimips/binary/kernel/netbsd-GENERIC32_IP2x.gz) = 0538c7187f0c5778a89a660749018ccc +SHA1 (NetBSD-6.0/sgimips/binary/kernel/netbsd-GENERIC32_IP3x.gz) = 1968926bf27f4cb8f5fac47a22ed3327dfb52c43 +SHA512 (NetBSD-6.0/sgimips/binary/kernel/netbsd-GENERIC32_IP3x.gz) = 0d5d484b19505ebbebda2daff665c43c77aa9e087946daf198684f7cba944f11e2dde344930e99ef4a24c02c6fb83009115b45a0100b955b0dc8450c00fc2f38 +RMD160 (NetBSD-6.0/sgimips/binary/kernel/netbsd-GENERIC32_IP3x.gz) = 4194967cb2a542b818e0f4670e194e91c6b20635 +MD5 (NetBSD-6.0/sgimips/binary/kernel/netbsd-GENERIC32_IP3x.gz) = 2d25467ddd2b88d4110211ab86f1c77b +SHA1 (NetBSD-6.0/sgimips/binary/kernel/netbsd-INSTALL32_IP2x.ecoff.gz) = 8bbc293222db73fb4be9015b07e05070c413de50 +SHA512 (NetBSD-6.0/sgimips/binary/kernel/netbsd-INSTALL32_IP2x.ecoff.gz) = 7c0f743299c829bea945e1f927dce38ad44b07f012949532d1e0f73bf3f44bb5931f1772db34b8598cb46b1e8d522c1de29e537105e8f4f1c10057bebaabe33c +RMD160 (NetBSD-6.0/sgimips/binary/kernel/netbsd-INSTALL32_IP2x.ecoff.gz) = 4c67683e70c5c31659196601d15fc98de34dbd10 +MD5 (NetBSD-6.0/sgimips/binary/kernel/netbsd-INSTALL32_IP2x.ecoff.gz) = e3cb87e4586bd5e1ec2602cf7767495f +SHA1 (NetBSD-6.0/sgimips/binary/kernel/netbsd-INSTALL32_IP2x.gz) = 66a33c0bed49bb9e1dd95cb3c79f944ee56fea31 +SHA512 (NetBSD-6.0/sgimips/binary/kernel/netbsd-INSTALL32_IP2x.gz) = f3dfc078ef7e21741758b7e3ea76af80772a1d3218b0178ce825814bd16a895115df7122b394c58f63af6b2128e57a95064ae3fc44a5a3e56d8a03327bf3174f +RMD160 (NetBSD-6.0/sgimips/binary/kernel/netbsd-INSTALL32_IP2x.gz) = c60e7094e3801d730f699b7a67c4403ced988c92 +MD5 (NetBSD-6.0/sgimips/binary/kernel/netbsd-INSTALL32_IP2x.gz) = 2c406bbd7ec78cc4c97dcdc48ee476d1 +SHA1 (NetBSD-6.0/sgimips/binary/kernel/netbsd-INSTALL32_IP3x.symbols.gz) = af7722c589f536235fb6d25f27231a6a3eacd3c4 +SHA512 (NetBSD-6.0/sgimips/binary/kernel/netbsd-INSTALL32_IP3x.symbols.gz) = f7b6acf595cbb8e7a54b34b458c39c384ea0e3ce44fcd142c7f71cb08551b56624969872fde0f90614e40582bc45fa3e41be31de0de954ce43fcd34375cd5d04 +RMD160 (NetBSD-6.0/sgimips/binary/kernel/netbsd-INSTALL32_IP3x.symbols.gz) = 3b853ba98c7c4016aeec80103318c1147aa52ac6 +MD5 (NetBSD-6.0/sgimips/binary/kernel/netbsd-INSTALL32_IP3x.symbols.gz) = 001d3d08526a1d35fe6a2d66baa59ff9 +SHA1 (NetBSD-6.0/sgimips/binary/kernel/netbsd-INSTALL32_IP3x.gz) = 9fef8eeac9eedbd6ce7744b13c0e14efc835c1fd +SHA512 (NetBSD-6.0/sgimips/binary/kernel/netbsd-INSTALL32_IP3x.gz) = d4af0b7ffc0596e209e19161bce14533610fd414350b761a58873c16858c3f44f2bc20135f7f14ffc9458dbfc029dfebb998e19f02176c9718f6a6406ea5b262 +RMD160 (NetBSD-6.0/sgimips/binary/kernel/netbsd-INSTALL32_IP3x.gz) = 420fe89a1bf2f952113c22d083512456f98738db +MD5 (NetBSD-6.0/sgimips/binary/kernel/netbsd-INSTALL32_IP3x.gz) = 7081086c1dca701908d84d74c29fc81e +SHA1 (NetBSD-6.0/sgimips/binary/sets/games.tgz) = f56d3e5181634f6a3d7908dcb002ebcb1c5aaff0 +SHA512 (NetBSD-6.0/sgimips/binary/sets/games.tgz) = 0cff50ea13e34fe338edf70da6a28af061580feb4cb0773828adefa631ebd471a96568a3b30ea0f13f3bb116856a1b6aad8a5a52443346f52e4907f4caabc5f1 +RMD160 (NetBSD-6.0/sgimips/binary/sets/games.tgz) = 1538910578dbb8eee2931200fac0ccda44758e5f +MD5 (NetBSD-6.0/sgimips/binary/sets/games.tgz) = 2bd5bd0ce72df5cf92767b8c3f7cc208 +SHA1 (NetBSD-6.0/sgimips/binary/sets/man.tgz) = 899b9d8242e983a5110ab755651c24f709b5af67 +SHA512 (NetBSD-6.0/sgimips/binary/sets/man.tgz) = 410999db110d710f4bb498c3d7ae7adc62170c7c2f470ce189c92f6c436c5ea96149659c631ef0b5605caaa025d97dfe1c07c428d86f51239657bd6b71717b15 +RMD160 (NetBSD-6.0/sgimips/binary/sets/man.tgz) = c1270f68c6d41b351877f71f0396ac34877dfc8d +MD5 (NetBSD-6.0/sgimips/binary/sets/man.tgz) = df4db2bbfa39ef6a4a215d949653d04a +SHA1 (NetBSD-6.0/sgimips/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/sgimips/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/sgimips/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/sgimips/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/sgimips/binary/sets/base.tgz) = d02636d2688644bf3230c10bf072000a44cd2f5a +SHA512 (NetBSD-6.0/sgimips/binary/sets/base.tgz) = abc4fb8ba2047eb2c99070b0b7a22e29a071c44ef8ce3d896969648dfb6ead55d396e8a7c0716e34e45f51565c6e29011d0e35cb914cab4691c8672a29f24fbc +RMD160 (NetBSD-6.0/sgimips/binary/sets/base.tgz) = f91ad6342293731972f28cb6286e6926b3de10e0 +MD5 (NetBSD-6.0/sgimips/binary/sets/base.tgz) = ff1da3a02630406282d40b75528def3e +SHA1 (NetBSD-6.0/sgimips/binary/sets/comp.tgz) = 27ba59fd7d5e90f91446a151f804437f8c249e8b +SHA512 (NetBSD-6.0/sgimips/binary/sets/comp.tgz) = f119dbb5c22cab49fdd8f0dec15407fa520d1d8eb02cb4550bd01f88d49378b4999e0041f6da8d4ee2bfa4712590a5345a184ead5a4b014d80c79c459bb34e3e +RMD160 (NetBSD-6.0/sgimips/binary/sets/comp.tgz) = 9cf77a31c5419a857ccf19a148eaf510a4d83aed +MD5 (NetBSD-6.0/sgimips/binary/sets/comp.tgz) = 2a2b72f824b9953fe580cb284a37c96c +SHA1 (NetBSD-6.0/sgimips/binary/sets/etc.tgz) = 6140d0c55fb88e07b633da0abfd0d5a345eb908b +SHA512 (NetBSD-6.0/sgimips/binary/sets/etc.tgz) = da25730f805732e0d4b90612dd9b5236f6fed96c75f022f4d1053495d897f7355b5d75b95f010b041795d6331285a2ab0ada3f34175b611147b295e697d54eb9 +RMD160 (NetBSD-6.0/sgimips/binary/sets/etc.tgz) = 79973e6b9ad3344bb4e64ed23a1ba9bcd16fb8a1 +MD5 (NetBSD-6.0/sgimips/binary/sets/etc.tgz) = c96ede97a5ce906a1fb580fc1dabbf94 +SHA1 (NetBSD-6.0/sgimips/binary/sets/modules.tgz) = a206108d50c0e8a138571adf8a674334de685263 +SHA512 (NetBSD-6.0/sgimips/binary/sets/modules.tgz) = bfb96bc27db44cc540d3ca143099e2574ca9a42eeea307eb3b835b624b52ebc14fead54754fb3d95916e6f4c2fecafcaedebaf28a32ec0c1e1b798caf9a7e44c +RMD160 (NetBSD-6.0/sgimips/binary/sets/modules.tgz) = 9114bd11fa6c211d72726f5e88458396165a6fe4 +MD5 (NetBSD-6.0/sgimips/binary/sets/modules.tgz) = 8f298135900ed72db173ffa002c4103b +SHA1 (NetBSD-6.0/sgimips/binary/sets/tests.tgz) = b10f0716cc4a705193fe7485de5b6123153a40a0 +SHA512 (NetBSD-6.0/sgimips/binary/sets/tests.tgz) = 79061c6367c51f6b0769e7ad724d440d055cefcc6ce1bf1730e602b2080af16be5a7f74a3c57391567dfb62f49588721bee5704d71039527c4269add0bd8420f +RMD160 (NetBSD-6.0/sgimips/binary/sets/tests.tgz) = 869f46c688b7d65e6f93dcf06e4d406fea799082 +MD5 (NetBSD-6.0/sgimips/binary/sets/tests.tgz) = b02332c28d31942e96e416d4dbf2f6d8 +SHA1 (NetBSD-6.0/sgimips/binary/sets/kern-GENERIC32_IP12.tgz) = 18e386c5766aa3391d5d29a7d55ae1eb3b69af2b +SHA512 (NetBSD-6.0/sgimips/binary/sets/kern-GENERIC32_IP12.tgz) = 8caad11aefe7fe71d346fbe3950fcaeb08a3454793e24f12c83b91c3078ef4e15f44c94cf47aa785e8b975f7403f0de2be38fa3ad3a48798e70efcdded5eed0d +RMD160 (NetBSD-6.0/sgimips/binary/sets/kern-GENERIC32_IP12.tgz) = 8e7531be01ac24bab8b898224ae33df0e84d637c +MD5 (NetBSD-6.0/sgimips/binary/sets/kern-GENERIC32_IP12.tgz) = 2f1a7076fdb72698d28a9d8032b79943 +SHA1 (NetBSD-6.0/sgimips/binary/sets/kern-GENERIC32_IP2x.tgz) = 4097c0cfecd7e8766e4542ffd936ac18fb9ed32f +SHA512 (NetBSD-6.0/sgimips/binary/sets/kern-GENERIC32_IP2x.tgz) = 9595785d477c04e57b81e2dd71957dfc3309fad013b7210d93d2501e64c308b57af9a22581ac3e61d8f3ec91aa62d49bb01ed5ab1eaf90557f41c0d4d3c3096f +RMD160 (NetBSD-6.0/sgimips/binary/sets/kern-GENERIC32_IP2x.tgz) = 2479e9e6495e16753c6c0e3e8dead0c49095c245 +MD5 (NetBSD-6.0/sgimips/binary/sets/kern-GENERIC32_IP2x.tgz) = 8661ec66f60bce4cb75af3d6756580c5 +SHA1 (NetBSD-6.0/sgimips/binary/sets/kern-GENERIC32_IP3x.tgz) = a5a29b61f5eba57e0bcdbd6af9ecfb9a4485a90b +SHA512 (NetBSD-6.0/sgimips/binary/sets/kern-GENERIC32_IP3x.tgz) = 4a5c4ebea7ddfad9bf8f3536212eeed17f22dbd74a38b7f48bd7963c6c7c4f29da10ec6454053a441db830cd5c18a3a342b6ad22f5fbb9d97104b683b94685cd +RMD160 (NetBSD-6.0/sgimips/binary/sets/kern-GENERIC32_IP3x.tgz) = 3bae9be1ed83ab2eeb80905c1e1bcfc59a4b6f7b +MD5 (NetBSD-6.0/sgimips/binary/sets/kern-GENERIC32_IP3x.tgz) = e402bda170a73a296a773b851afa1a3b +SHA1 (NetBSD-6.0/sgimips/binary/sets/text.tgz) = 11418c012b904e8a99e91493d36fdca3f6e6f006 +SHA512 (NetBSD-6.0/sgimips/binary/sets/text.tgz) = 501a9e78e9310aeb3f0c766464b5453e2718f23b5d3290428ad775977cd2a42b5444b91d7b1707ae9991b58af14f376d9d93cebdc54c74ea8d20ed06a7e0387d +RMD160 (NetBSD-6.0/sgimips/binary/sets/text.tgz) = 272adf1723ad8ab137b985946e64ca3b27055199 +MD5 (NetBSD-6.0/sgimips/binary/sets/text.tgz) = 0f6d77a90f9714d54517c4b5660150fa +SHA1 (NetBSD-6.0/sgimips/binary/sets/xbase.tgz) = 0e912b46017d4afca665692603e483e95d627af5 +SHA512 (NetBSD-6.0/sgimips/binary/sets/xbase.tgz) = 54c6bb297c09510019a0e21816018b7f8abbecd3e9dab5f5dd48d1cf35493b0cb0ec5ca01f1bbc9066fa1b964cf550119c1678a70d80d4471d9df73627655bb6 +RMD160 (NetBSD-6.0/sgimips/binary/sets/xbase.tgz) = d8b979b953547c386cf66488db96771f3923cc2f +MD5 (NetBSD-6.0/sgimips/binary/sets/xbase.tgz) = c04dfa38a56e78bf0d075dd4d333a869 +SHA1 (NetBSD-6.0/sgimips/binary/sets/xcomp.tgz) = d764bc540d10ebb805e8c976e8b300d9c6a108e0 +SHA512 (NetBSD-6.0/sgimips/binary/sets/xcomp.tgz) = a6795d24491875468bdabf17698ee483c0aaeaae64772667083049c7f2b2ae82943277cd41fe870c085ae7498f6546d971362d77e62f6150f40aa23f6b92d732 +RMD160 (NetBSD-6.0/sgimips/binary/sets/xcomp.tgz) = 99f0489f322b26960b51a53e24fd03faccccc512 +MD5 (NetBSD-6.0/sgimips/binary/sets/xcomp.tgz) = d6e8029f965bcade40d027658ea70e14 +SHA1 (NetBSD-6.0/sgimips/binary/sets/xetc.tgz) = bcbb9c22987ffa1ec653920c5013030fb974d73c +SHA512 (NetBSD-6.0/sgimips/binary/sets/xetc.tgz) = 7e2ad6276a043e98c194a03fc38f3754193c0f75bfbb79cc855bf08d7336d01763d7df89edb3ac63056a403d08e7e21b43a1b4468c34cb2969024bf5894988e2 +RMD160 (NetBSD-6.0/sgimips/binary/sets/xetc.tgz) = 35c9e251920fa14e32a68f6d811ec8ef81a233b1 +MD5 (NetBSD-6.0/sgimips/binary/sets/xetc.tgz) = baf2f338baf24e78da645312b33eab7b +SHA1 (NetBSD-6.0/sgimips/binary/sets/xfont.tgz) = 43b823091c3c5b340538ecf7cbd17be47e6d5692 +SHA512 (NetBSD-6.0/sgimips/binary/sets/xfont.tgz) = 63a18f59b0c2ef7eab2ba7526fe2815155e476426d34e21e06d2c00fc872cc01bc241704971524c9c6410f420650a7d69914205a45a1b232413e9ccbff2d6b93 +RMD160 (NetBSD-6.0/sgimips/binary/sets/xfont.tgz) = 3cee7affdad412ed072636553915fab9f0d23ca2 +MD5 (NetBSD-6.0/sgimips/binary/sets/xfont.tgz) = 0be724043d9312d60c89901238982903 +SHA1 (NetBSD-6.0/sgimips/binary/sets/xserver.tgz) = f604963ee4c952665400bd5742f6ac3925903291 +SHA512 (NetBSD-6.0/sgimips/binary/sets/xserver.tgz) = 2f5d36f2f728aeed88a3a2e8da36acb3117018fe92f97769babe2b37670c0ad9cce319bded4a4c78d7859c12df4124fdb2faed33abaae1b4cea20098582ff99e +RMD160 (NetBSD-6.0/sgimips/binary/sets/xserver.tgz) = c18f29c81d11389a45b5c8a6226ec1e7c074582c +MD5 (NetBSD-6.0/sgimips/binary/sets/xserver.tgz) = 41d79391ddbccae7930228219015083b +SHA1 (NetBSD-6.0/sgimips/installation/diskimage/diskimage.gz) = 5acd23fd19ce75e45f071d5de6396668b89ea681 +SHA512 (NetBSD-6.0/sgimips/installation/diskimage/diskimage.gz) = 007da5ebfe4af418c4f696956cb768575b656dd40297cb39dea7b03146bf48aa22fe9f288325737b6904f5e08b89c79d60a375dce4d885fc83f3bb85595507b2 +RMD160 (NetBSD-6.0/sgimips/installation/diskimage/diskimage.gz) = d4fabae9c31423c0557937fd07cc796f48f392fa +MD5 (NetBSD-6.0/sgimips/installation/diskimage/diskimage.gz) = 8575ffc5db9771c5aa948ab437c80e1a +SHA1 (NetBSD-6.0/sgimips/installation/netboot/diskimage.tgz) = 075e8acd73646b2b89509714ba7ca7a001cb72a1 +SHA512 (NetBSD-6.0/sgimips/installation/netboot/diskimage.tgz) = e0dc8dfb79ee590decb7c315fd4b8cf7a55a2981a3752aeddc25afd83a79fd72d6852f9823ab857077cfe40c9619dc8b537ab1227c42441b43b2fb9129a419a3 +RMD160 (NetBSD-6.0/sgimips/installation/netboot/diskimage.tgz) = 4b4d8d21878765a902c28673fa2ff2fe62ccbc55 +MD5 (NetBSD-6.0/sgimips/installation/netboot/diskimage.tgz) = 250ed8b78bb6bc799d92f3e82d62003a +SHA1 (NetBSD-6.0/sgimips/INSTALL.html) = 57dd965aef89b4c8190886a37ab3fff06021b8eb +SHA512 (NetBSD-6.0/sgimips/INSTALL.html) = c1e5774651642601daaedef68c0337dbf8d634abddc9eaf8d33d38358076f49867df6644d0c8c7e8e730c2d37a2a35af9c7c03dbd817f5b4eae5d7383e900190 +RMD160 (NetBSD-6.0/sgimips/INSTALL.html) = a5c94dcca469b47cb176426a8cbd4c0e2df210e5 +MD5 (NetBSD-6.0/sgimips/INSTALL.html) = 7c4d8de6801d46c1dac589fc304590a5 +SHA1 (NetBSD-6.0/sgimips/INSTALL.more) = b9c2017ba93cbb87b7d0a88fd6912eb81a9b7ed7 +SHA512 (NetBSD-6.0/sgimips/INSTALL.more) = ca9a739d8c56336ebbfffb856904a4753e8948cf8c1a4da057f212cffaba7493c07467bcd0608923d1dc3deb76ceac989cc556cd025380ad1f80109a46aa6746 +RMD160 (NetBSD-6.0/sgimips/INSTALL.more) = 0e733569f0cd6acc3de8e7b3acdac89953e554d7 +MD5 (NetBSD-6.0/sgimips/INSTALL.more) = a43c8c4a3aea3585e8de329c8efef129 +SHA1 (NetBSD-6.0/sgimips/INSTALL.ps) = e61b0904bc556853037f1a9564486e0962a8b8e2 +SHA512 (NetBSD-6.0/sgimips/INSTALL.ps) = 122ebadac3919533845714c90f87c59a65722d6e79f50bf231866f2917e6d4ebcb4a8b5da8e4ac9acbe4e333e841611ef80665b7e69427db90d4843e5f630c8b +RMD160 (NetBSD-6.0/sgimips/INSTALL.ps) = efbc102832be0cee24ce3a5810999c5ea9c4b18e +MD5 (NetBSD-6.0/sgimips/INSTALL.ps) = e86216add5a2ed163e13a17c6ff291f2 +SHA1 (NetBSD-6.0/sgimips/INSTALL.txt) = 104c1ef873cfbe774ba106e437168053539b65b1 +SHA512 (NetBSD-6.0/sgimips/INSTALL.txt) = 8b5ad1ef07604c0e8ac5ec2c7f43a4c483610a7ad7ac4c15a13c4151652500a21b203569bcc9ecbb53e035f8b90e1c7e3fc81d985fe3817685957865fb4924cf +RMD160 (NetBSD-6.0/sgimips/INSTALL.txt) = 7cc2ca6174d6b5e2ed23f8db3d6b62bb02c41637 +MD5 (NetBSD-6.0/sgimips/INSTALL.txt) = 99bca5bfeb2112666aba79a96379899a +SHA1 (NetBSD-6.0/shared/ALL/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/shared/ALL/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/shared/ALL/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/shared/ALL/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/shared/ALL/man.tgz) = 899b9d8242e983a5110ab755651c24f709b5af67 +SHA512 (NetBSD-6.0/shared/ALL/man.tgz) = 410999db110d710f4bb498c3d7ae7adc62170c7c2f470ce189c92f6c436c5ea96149659c631ef0b5605caaa025d97dfe1c07c428d86f51239657bd6b71717b15 +RMD160 (NetBSD-6.0/shared/ALL/man.tgz) = c1270f68c6d41b351877f71f0396ac34877dfc8d +MD5 (NetBSD-6.0/shared/ALL/man.tgz) = df4db2bbfa39ef6a4a215d949653d04a +SHA1 (NetBSD-6.0/shared/arm/games.tgz) = e1d2bb091d8202962133475bc83edb55230b9008 +SHA512 (NetBSD-6.0/shared/arm/games.tgz) = a147fe6d0419d53d5a428802d0bb6c9fa8a84a76c96d7d6d7c0d399e5af3a69240116463549a83d53387b0214ba0207796d7c10228d92a684fe7ff0ece3aec16 +RMD160 (NetBSD-6.0/shared/arm/games.tgz) = 2be515c495548ba5135ff42a75a8ebbfc35ea776 +MD5 (NetBSD-6.0/shared/arm/games.tgz) = 9059a6f2cd41cb58827709c9e9a1649b +SHA1 (NetBSD-6.0/shared/arm/xbase.tgz) = 875fd641f969ec00f854ca1334d084947450c740 +SHA512 (NetBSD-6.0/shared/arm/xbase.tgz) = 75d0c9e9685b6b7bb706df7427c8b52f59c4fc4d0e725b02ee18024f75a546dc41de5f1a5d8552a8d2c84bdf87856e5857b0f12914801ca7b36b69536d617b4e +RMD160 (NetBSD-6.0/shared/arm/xbase.tgz) = 1a4d099d59b2bd882e99f1b2df1c7bf22b890d48 +MD5 (NetBSD-6.0/shared/arm/xbase.tgz) = 5eb9c573c5a0c96701f268a3470a58b9 +SHA1 (NetBSD-6.0/shared/arm/xcomp.tgz) = 8d7469a85b7433c89690cce74e6b3f4e66cf0647 +SHA512 (NetBSD-6.0/shared/arm/xcomp.tgz) = 411304cf66e300a7f162128203099bb4d6eebc4a93ba18ed7caf79f30b31cc7ffcede85c4e1bad02c3f5f8a27d009fb71f3ce5862c1d8aa477f39a25c535fdaa +RMD160 (NetBSD-6.0/shared/arm/xcomp.tgz) = 822d26e0ee08b72ca8b991f0709a8c1bf0399208 +MD5 (NetBSD-6.0/shared/arm/xcomp.tgz) = 5af361f0334d28119d703064278b3ed3 +SHA1 (NetBSD-6.0/shared/arm/xetc.tgz) = 222d14c205f1018cc5a86eb03214d18cda2abb82 +SHA512 (NetBSD-6.0/shared/arm/xetc.tgz) = fb82261996aa772fd8a9022eadebf899ee04ee70229ee4fe07758ca14937bdb34752c8218eb4c5b722b6208f719891493bbc141372fcfa503de83e0a61aa7387 +RMD160 (NetBSD-6.0/shared/arm/xetc.tgz) = 511ebfe5076f361b7f7ca03a265d16052a16d259 +MD5 (NetBSD-6.0/shared/arm/xetc.tgz) = 165cffbb6d2c79663198d80c82afac1e +SHA1 (NetBSD-6.0/shared/arm/xfont.tgz) = ce0e141beeffeb5b470478e9887e4127da85de3c +SHA512 (NetBSD-6.0/shared/arm/xfont.tgz) = 5d98354ff77103793d56af3192ab5f9afcde62208791976064ac33a149f994e0227dd5dd28ed544eeac5ea504e5212d5fb9e7d05e59e5a48a2fe4062e34e3106 +RMD160 (NetBSD-6.0/shared/arm/xfont.tgz) = 4d09f5e82fec875ef0ea328809465e7a98f2ebfc +MD5 (NetBSD-6.0/shared/arm/xfont.tgz) = be26b3890261302420b09976a1d38144 +SHA1 (NetBSD-6.0/shared/arm/xserver.tgz) = 4ccfef1d49179603286042088bec0218c6b2031d +SHA512 (NetBSD-6.0/shared/arm/xserver.tgz) = 809fc0a9065c1b9e7cd17aeb0d41cfd3158efd6c585556af01c4a3c93f0df3646a2ff77c6994449a703a408c0988fc1aa68cf34c7e297a3056d73ded57034c12 +RMD160 (NetBSD-6.0/shared/arm/xserver.tgz) = 403604404261764c74f10fab774c4653fd20cc9b +MD5 (NetBSD-6.0/shared/arm/xserver.tgz) = 914f909b6878cef16a92765a8cbb52ca +SHA1 (NetBSD-6.0/shared/m68k/games.tgz) = 16ee93ea4d5fac2fb28fad5c32c8a3d57d011d79 +SHA512 (NetBSD-6.0/shared/m68k/games.tgz) = a7f49ab72f50273f66c8dcf408b57ec4668debd5537c5bd0ec59aa0f4fa1d599ba0798d1b283315c4208cbcb608925808ce003b1ade79034886edb8208f9f48d +RMD160 (NetBSD-6.0/shared/m68k/games.tgz) = 1e09d99d7fe2e495763f05919472d27a4ba699df +MD5 (NetBSD-6.0/shared/m68k/games.tgz) = 8a26f3e864444209088bccf21419a616 +SHA1 (NetBSD-6.0/shared/m68k/xbase.tgz) = ffc6dc889560371042dd12a5486a9a2c499b86a9 +SHA512 (NetBSD-6.0/shared/m68k/xbase.tgz) = 9aa2ba4d703a13020acf8543d1efcde76b6f0f4b411be20f804709b3802e537be1e651eba469830c4fd4777a379ea9936200a3a3eb4b1a702c04bb81aafcc723 +RMD160 (NetBSD-6.0/shared/m68k/xbase.tgz) = 3ecf53e7414ef859a47fe5afc108cf3bfa82fb1d +MD5 (NetBSD-6.0/shared/m68k/xbase.tgz) = a6af002ce158cf72eb5c6a7cde2c0989 +SHA1 (NetBSD-6.0/shared/m68k/xcomp.tgz) = e13548b8974f5d55e98caf17b2b4bbbcf2430370 +SHA512 (NetBSD-6.0/shared/m68k/xcomp.tgz) = e4b13c798df04ffef88e72100e2db5af400e5ae255cd7a1ca2907736b8138a59045b6f3bd8531b5753d0b87eadb1b5f801043a929bb25d1611e4be693c1da954 +RMD160 (NetBSD-6.0/shared/m68k/xcomp.tgz) = 3b1f4e26ddd57e69afd9709553c1bf70d6e29ea0 +MD5 (NetBSD-6.0/shared/m68k/xcomp.tgz) = 894bb9aa05b164d9923682165d708335 +SHA1 (NetBSD-6.0/shared/m68k/xetc.tgz) = d2ca34bd668e108cbbfd4b45720823663339f8bd +SHA512 (NetBSD-6.0/shared/m68k/xetc.tgz) = 431ca465f300e7eb5d4dbd44c43e412a296fb4d3129217e752f86a720e8a8bdf736c9add05a45518a4f3e6cffa32381ef61e9186d360b68a5f8c64d87e385fb5 +RMD160 (NetBSD-6.0/shared/m68k/xetc.tgz) = 4c5d664679856b02b694534cd6afdf20597e6d53 +MD5 (NetBSD-6.0/shared/m68k/xetc.tgz) = 72bd67556ac14ea0ce147374af0ba624 +SHA1 (NetBSD-6.0/shared/m68k/xfont.tgz) = 24ca4cb77a59246b1b05e0a91fed21c63259d12b +SHA512 (NetBSD-6.0/shared/m68k/xfont.tgz) = 8dc297fb6205a995767e68e77cc21169234dfb66a86bbcd2e1828fd32efeda0a25c9f2a9b1a39b97fe8d7b24f8cd5cf6160859af6be2259876f39ee4e76c405b +RMD160 (NetBSD-6.0/shared/m68k/xfont.tgz) = d2f134959940e6667aca185f01e388c05dc6bc85 +MD5 (NetBSD-6.0/shared/m68k/xfont.tgz) = 3c96c1f0a13cd7d277ca35622ac9c058 +SHA1 (NetBSD-6.0/shared/m68k/xserver.tgz) = 1d20fd039546a66b428b854c659ea5e2ee9f8114 +SHA512 (NetBSD-6.0/shared/m68k/xserver.tgz) = 091d09049d0af5555feec02065234e281677aeb3ecbab5a19413d924a8b58dc7f64401ef68e68bc52d8b6eeb73e091d351c45805374b8bf276b0181415968561 +RMD160 (NetBSD-6.0/shared/m68k/xserver.tgz) = feef5d52278d23637d7b8ba77639bfd96918e90e +MD5 (NetBSD-6.0/shared/m68k/xserver.tgz) = b2bd6057c374376388766fc8667eb9a9 +SHA1 (NetBSD-6.0/shared/mipseb/games.tgz) = f56d3e5181634f6a3d7908dcb002ebcb1c5aaff0 +SHA512 (NetBSD-6.0/shared/mipseb/games.tgz) = 0cff50ea13e34fe338edf70da6a28af061580feb4cb0773828adefa631ebd471a96568a3b30ea0f13f3bb116856a1b6aad8a5a52443346f52e4907f4caabc5f1 +RMD160 (NetBSD-6.0/shared/mipseb/games.tgz) = 1538910578dbb8eee2931200fac0ccda44758e5f +MD5 (NetBSD-6.0/shared/mipseb/games.tgz) = 2bd5bd0ce72df5cf92767b8c3f7cc208 +SHA1 (NetBSD-6.0/shared/mipseb/xbase.tgz) = d81c7fe75a90f1b2111a066e78f1f2b3e8edcd8c +SHA512 (NetBSD-6.0/shared/mipseb/xbase.tgz) = c241391fcde4a685a0a2af6f843844ac2e918024c447a2b5ea2cf5300f69acc42fdadf53d3b0348f10723b786bcc0f420e68fe36228375bf3cb5140de41eb40f +RMD160 (NetBSD-6.0/shared/mipseb/xbase.tgz) = 2fbf60b64c0b7ac2be72ebf998d9d7390fc40705 +MD5 (NetBSD-6.0/shared/mipseb/xbase.tgz) = cd23ca0f6b359c4d695d4494a147d40f +SHA1 (NetBSD-6.0/shared/mipseb/xcomp.tgz) = c8f5ff5ea9f9bbe231f92d8b7f3bfcbd2897069f +SHA512 (NetBSD-6.0/shared/mipseb/xcomp.tgz) = c7590075195019078b68ec5f87e36479ae2e7b7749c523df4ef21c9d881c343cda9f5c2bba897dd313329a76fe5c18e920d92827878d98ce08a7dc776352cd02 +RMD160 (NetBSD-6.0/shared/mipseb/xcomp.tgz) = bc60e267cb6e11b4a7305f8b7074084e179e0ff5 +MD5 (NetBSD-6.0/shared/mipseb/xcomp.tgz) = 8e58ee51667def3bd015f79769c0d932 +SHA1 (NetBSD-6.0/shared/mipseb/xfont.tgz) = c551bd13179b9508c2e3a7e19cec323e8ba21844 +SHA512 (NetBSD-6.0/shared/mipseb/xfont.tgz) = 764527f2f3f4686759fcae3fd093f4e00f34e1249994126221a6f9afe73d4cf8ddfbe8b8311798da2ed38c52466a44bb26ea08ad5aab1c08eebcc9019b4223f7 +RMD160 (NetBSD-6.0/shared/mipseb/xfont.tgz) = b3a365bedf8b4a20f3920d0e33b9a42fce288953 +MD5 (NetBSD-6.0/shared/mipseb/xfont.tgz) = adac8939da213a0195cc1d351f979199 +SHA1 (NetBSD-6.0/shared/mipseb/xserver.tgz) = 686f6e6d722c9676351ab058736f7077b4ebd2f6 +SHA512 (NetBSD-6.0/shared/mipseb/xserver.tgz) = 5c818f22edbeac7325228af99d6da6e44b5eb659c7c9fcc6b332071e97a0a490081eda7f9e0f22d6a3f3a589ae34179b434751a6191db5c664683d7510aecedc +RMD160 (NetBSD-6.0/shared/mipseb/xserver.tgz) = 0e9f066095b505c7f062bf877147189a7a2f0649 +MD5 (NetBSD-6.0/shared/mipseb/xserver.tgz) = cdd2e5127838437df40af161e0c8398f +SHA1 (NetBSD-6.0/shared/mipsel/games.tgz) = 27d9f98fecb3495e51939df9f107e81e527af26f +SHA512 (NetBSD-6.0/shared/mipsel/games.tgz) = 46bb4e10313cfffaaf4f7fa2157474ef940f94bcc9f84b46f829c7615bbf45e4e01edee7b7efb84bc28561e0712c37cfc737f9c2a0d9a73b67c80c8aa0f3a9af +RMD160 (NetBSD-6.0/shared/mipsel/games.tgz) = 947feea90ec2698a65d555cb78a29a001b086589 +MD5 (NetBSD-6.0/shared/mipsel/games.tgz) = 355f00978fed8e8da6a251e591be5387 +SHA1 (NetBSD-6.0/shared/mipsel/xbase.tgz) = 76468fcada5a9e26652aa9f0f9f3c94829a317e9 +SHA512 (NetBSD-6.0/shared/mipsel/xbase.tgz) = b2adcfc2dedef30b21b885c8fc757d0479541744a280a9997fbeaa9c881009ab4b0019e0001a540a8eb6db5f84db87b365e420bb2d4270af209821bdb080369c +RMD160 (NetBSD-6.0/shared/mipsel/xbase.tgz) = 1e0074d03d9fbb3373e0a427b25cc7097bf6d3c8 +MD5 (NetBSD-6.0/shared/mipsel/xbase.tgz) = a8f29ec2e3768405942f97af3dd08ee7 +SHA1 (NetBSD-6.0/shared/mipsel/xcomp.tgz) = d8ac89f3f6ff20abb0adabc49227afdb74aa2040 +SHA512 (NetBSD-6.0/shared/mipsel/xcomp.tgz) = 4f03213fb061dae9421747209628d06ede6bbb71a7560a9e1a54796b907f1620146a33fdce52974227a21acedcc210b99e15c4fdd36432eba60c1041a92d8cee +RMD160 (NetBSD-6.0/shared/mipsel/xcomp.tgz) = 6be5e72b9b57c9bdf8ed8ea127e2a73830feeecb +MD5 (NetBSD-6.0/shared/mipsel/xcomp.tgz) = 59a7ea141587417be38ab1f6056cc780 +SHA1 (NetBSD-6.0/shared/mipsel/xetc.tgz) = b9f6b1a54ffab37b11f4c6e717b481cd087fb609 +SHA512 (NetBSD-6.0/shared/mipsel/xetc.tgz) = 72f35e65f3a90967e250a2006d500619b3824f7f5c3d7494554f153ec5cda5b28c445f28c34a1e4463f40da5855e8d4257726411796967fe37763d90cf7fe461 +RMD160 (NetBSD-6.0/shared/mipsel/xetc.tgz) = 1169c246f91189fd0c4ae86ac27a92f5c2edda3e +MD5 (NetBSD-6.0/shared/mipsel/xetc.tgz) = 8f3c52cc5af1cafaf7b0d0f884a5b537 +SHA1 (NetBSD-6.0/shared/mipsel/xfont.tgz) = d06848571034f3b7fc975082f1de37b912acb18c +SHA512 (NetBSD-6.0/shared/mipsel/xfont.tgz) = 66a1013c935bee5e7e5d24325a527522306bcded7ced63790f2e58831b3ed91176a1b9510b2159be63504d5167d48d534919927ffc6e225ae2bb2487f90a9ede +RMD160 (NetBSD-6.0/shared/mipsel/xfont.tgz) = c9502843a5d4dd7e996e8d158c519cf7f8575cbd +MD5 (NetBSD-6.0/shared/mipsel/xfont.tgz) = e812899176eac2bf65a6d949ac3f3424 +SHA1 (NetBSD-6.0/shared/mipsel/xserver.tgz) = ff805022f409202f3346c45475c7ec0f8187218e +SHA512 (NetBSD-6.0/shared/mipsel/xserver.tgz) = f2bb3810a5572b519980126a3d934f63b5ab5c2fcf9fb8166c556bd3cc14cfaa151d582086bb1506ac9ac7e21d4e70a5cd5c3faed96212d8a14a0b5bafdcc4c1 +RMD160 (NetBSD-6.0/shared/mipsel/xserver.tgz) = d5ae336337cc77f7f55f542b3457918d6fc0efe8 +MD5 (NetBSD-6.0/shared/mipsel/xserver.tgz) = 92447a1560887d337d22e2deed0670a6 +SHA1 (NetBSD-6.0/shared/powerpc/games.tgz) = fbf69640b362df2446d7414ac3a13db100c289eb +SHA512 (NetBSD-6.0/shared/powerpc/games.tgz) = d86b41d79aea4204ccf45306937a5ec45629e37873a5956c0280fd1d54cf4a808542d097f9d978fd3277791554ce8a6fb4d0ccd46e30210549d5cce1145bb499 +RMD160 (NetBSD-6.0/shared/powerpc/games.tgz) = fd2aed1eb51f4db522fb5163e8fde4c040b55d30 +MD5 (NetBSD-6.0/shared/powerpc/games.tgz) = 997ae5fb42196a787df89873be321e47 +SHA1 (NetBSD-6.0/shared/powerpc/xbase.tgz) = b7c8146146ebc15191c1bf53f51f8f980fe8c816 +SHA512 (NetBSD-6.0/shared/powerpc/xbase.tgz) = 091f5d00414a9ad478811bfb0e953f2a204869bc5e310790886a59c11953974cf7068cd9a96c8823856ab2687ffa2ac31e97494f47338bfe31d80217382c59f1 +RMD160 (NetBSD-6.0/shared/powerpc/xbase.tgz) = 4bd1bfdc7c1e1619de63fb83276c21039b945357 +MD5 (NetBSD-6.0/shared/powerpc/xbase.tgz) = e621806afa0fcc9cdcef0f9b3c7dfcbd +SHA1 (NetBSD-6.0/shared/powerpc/xcomp.tgz) = 960dd33b61e19dec92096a54791aca1cdf56ce54 +SHA512 (NetBSD-6.0/shared/powerpc/xcomp.tgz) = 111dd50041e4008aeadb898c3d08f9995c5c13a41ccc20993b4ad51c81d7f6ee3b4dab16158ac7436d085b80e4a643b236a9c97edd3e915125a1466154538420 +RMD160 (NetBSD-6.0/shared/powerpc/xcomp.tgz) = 0cf8b9a8d1489a32ba0b5a277d90e429c40650fb +MD5 (NetBSD-6.0/shared/powerpc/xcomp.tgz) = 4ba4077ca2c0edf71813165fcf5321fb +SHA1 (NetBSD-6.0/shared/powerpc/xfont.tgz) = 4711fcbade0238d60b7b89cf0d7873b03d7ed1f7 +SHA512 (NetBSD-6.0/shared/powerpc/xfont.tgz) = c29130f55f536f602253a7f92f073ebf6ba02baea09f8011530bbf7e03ae96594334f0c60b29a8bceaffc3eb8b152db47548e38a3c8a14abc5fe35bc5d1d7d93 +RMD160 (NetBSD-6.0/shared/powerpc/xfont.tgz) = 3b01af0f8e34367988d559fe0fbb0acbbafb0b2b +MD5 (NetBSD-6.0/shared/powerpc/xfont.tgz) = 6ba15ed12217b726d9129db8e942a048 +SHA1 (NetBSD-6.0/shared/powerpc/xserver.tgz) = 05aac7e617e0cac05a88062fef29bb459da7a1d1 +SHA512 (NetBSD-6.0/shared/powerpc/xserver.tgz) = 19fb5af5d6afd78839a22e5c0694a492047b5200c569cbf58c676ff32ec250b21edcfe2ed00b65092fdac374d1ab9eaaed6113c69bc03009cf458aedc6014913 +RMD160 (NetBSD-6.0/shared/powerpc/xserver.tgz) = 774d2a1072b8d122790ad189a6d2ada2ad99e7cf +MD5 (NetBSD-6.0/shared/powerpc/xserver.tgz) = 3daf1477cadf3593e9ba45e3703fe8a5 +SHA1 (NetBSD-6.0/shared/sh3eb/games.tgz) = 37e15b0950aaaf1af36427ae5dd5866c1879b6b3 +SHA512 (NetBSD-6.0/shared/sh3eb/games.tgz) = e674abb1b1966acbc581a8f8b3e37841f48656e66f3302077cbb2de443487912b99521336ec5dc096fa3c7769b2d7623e1d1720a079407ec1861d32159a72ebc +RMD160 (NetBSD-6.0/shared/sh3eb/games.tgz) = 36070071e8315d2352be1b3e563ce7ef7625d184 +MD5 (NetBSD-6.0/shared/sh3eb/games.tgz) = 0016145b46957b95dd158b4441dfb010 +SHA1 (NetBSD-6.0/shared/sh3eb/xbase.tgz) = 564bce6dd7c37b5e941e41d50f363c133fdf8f97 +SHA512 (NetBSD-6.0/shared/sh3eb/xbase.tgz) = 23b3306254c789331542e63974f9d7cdc54d99ba2cd67cf6a1c97f09afa4f6cf6aa8798e37b7c38f4a55afd1572154f291fa1bf2e2a1fc87165fd6bd7f89fb80 +RMD160 (NetBSD-6.0/shared/sh3eb/xbase.tgz) = 476fbd8301bec0795a01552728ada44204d2dbe6 +MD5 (NetBSD-6.0/shared/sh3eb/xbase.tgz) = 9fbbbdb3acfa4ccd9f0b309ea0ed0700 +SHA1 (NetBSD-6.0/shared/sh3eb/xcomp.tgz) = 526a278a13833073e6231e879abdec85400ca888 +SHA512 (NetBSD-6.0/shared/sh3eb/xcomp.tgz) = d2081a7536e3d7fa27a363afd8f6eb5fc3de4606f11b4857be2f1df59934da9d3d16e0df3a6edf4cdf52c8f579e0e4c06f07de0959b5213c21be1a8fdc2ee134 +RMD160 (NetBSD-6.0/shared/sh3eb/xcomp.tgz) = 4a767ff08e9bcf98f886849cabebd1300397256f +MD5 (NetBSD-6.0/shared/sh3eb/xcomp.tgz) = a23a2d8be9298497b4b6d39fda330bf4 +SHA1 (NetBSD-6.0/shared/sh3eb/xetc.tgz) = 93a5cfbbfdc641f91ab363d4b65d1158d71c0cfc +SHA512 (NetBSD-6.0/shared/sh3eb/xetc.tgz) = 85a67734801e81e129a37b73ae62211459fb16d4e52a945ef21a4bb908dd7d1d775233956086dd3d59af45bcea24fbd6f54a2a9175756d242b57e07d10767548 +RMD160 (NetBSD-6.0/shared/sh3eb/xetc.tgz) = 6fb055d0e1b6264bf1ec396236d903218832377a +MD5 (NetBSD-6.0/shared/sh3eb/xetc.tgz) = af954b56e624948145b91aa451d77392 +SHA1 (NetBSD-6.0/shared/sh3eb/xfont.tgz) = 6139c05273b6feeecdfcd11cbe0da91256d12a11 +SHA512 (NetBSD-6.0/shared/sh3eb/xfont.tgz) = bb849454ede88d39ca60d6c513c833c2b29ea548adedb9f76870839174a3daa838d38a6ad701c78bfc164e690c5ebda9c9d00d4c23ad816df9f1962313afdbf2 +RMD160 (NetBSD-6.0/shared/sh3eb/xfont.tgz) = ea8f123f9f78b429b77ff15c924803da1da2068d +MD5 (NetBSD-6.0/shared/sh3eb/xfont.tgz) = a87cb6769c37ae20dbf0dd70cef93d11 +SHA1 (NetBSD-6.0/shared/sh3eb/xserver.tgz) = 6cd4fdb0ff00ef5d89b47e68e538c86e395b2054 +SHA512 (NetBSD-6.0/shared/sh3eb/xserver.tgz) = e3b575cab95e297a05a26a03eeff0cf843d665ebdfd103846ad544bef1d04f93aa20ceab09b1dfaae8f59d89ebb1cbef400b7521bdb41f7542f23156540aa4c0 +RMD160 (NetBSD-6.0/shared/sh3eb/xserver.tgz) = 7e52b98276b4d097f7babe918e6768ae9d7945db +MD5 (NetBSD-6.0/shared/sh3eb/xserver.tgz) = a505ab4ce0801aabe21fe6038b63809f +SHA1 (NetBSD-6.0/shared/sh3el/games.tgz) = 2040b4af557a62f2ade5fc9fcfe4cab3df88c7e2 +SHA512 (NetBSD-6.0/shared/sh3el/games.tgz) = 8b5071337dc844042537c24c75660e61c9709cd10cbbeab059a84da6d482260b73365ff3870f85060c130a291b6f02be174d288127ca62ce4d291a6982192317 +RMD160 (NetBSD-6.0/shared/sh3el/games.tgz) = 28acfa5a131d52df7c157e2edca1dd0f20e774dc +MD5 (NetBSD-6.0/shared/sh3el/games.tgz) = d82c46dbc0021fd4694e464042936052 +SHA1 (NetBSD-6.0/shared/sh3el/xcomp.tgz) = 53aa1e2a910e8eed09dc07f8b724804f53fe5e2f +SHA512 (NetBSD-6.0/shared/sh3el/xcomp.tgz) = 24645da85419528015cdaefd0c835741fa801392e795b363bdfc39558e75e7f384511c0668d12e2440114b7c543c7532aaec438048f08d35c54c9c7a748f20c0 +RMD160 (NetBSD-6.0/shared/sh3el/xcomp.tgz) = 60a461ffc1f1562274110d65c72a541ee131cd21 +MD5 (NetBSD-6.0/shared/sh3el/xcomp.tgz) = f1d2650a8d7a4ecd60fda8e1aaf8c09b +SHA1 (NetBSD-6.0/shared/sh3el/xetc.tgz) = 1636a6fe3e01f6d8a07a19cd204a6807c8caa4c7 +SHA512 (NetBSD-6.0/shared/sh3el/xetc.tgz) = 9cea4ba4af287dd57e591d4269f2f2582010250316f323746ac56b12cefcf2590b93fbb0197c665f61b1df41dcca62d17fb6ad80d4b1feb8ac8265e91e15074f +RMD160 (NetBSD-6.0/shared/sh3el/xetc.tgz) = 5f68e3f96f7bb9ae07fccdb1d058e4b1307b4b29 +MD5 (NetBSD-6.0/shared/sh3el/xetc.tgz) = da84d97230787283e215a4ee1c4053ad +SHA1 (NetBSD-6.0/shared/sh3el/xfont.tgz) = 97439ccf6840b18b1e9885f5504a401bf1a93650 +SHA512 (NetBSD-6.0/shared/sh3el/xfont.tgz) = 3d15541f7d7ae2128f44355bf110415adfa4e5182829259d2c6f7a4217feff99e236d13c5bb7bbeb724ff1a09ac1f58f02bdd6eef528bc416ec3118db6fc7d45 +RMD160 (NetBSD-6.0/shared/sh3el/xfont.tgz) = cdc9fcdb5fd5032803d5bba18db58f3ea6d62c85 +MD5 (NetBSD-6.0/shared/sh3el/xfont.tgz) = a8466a0477c6c443eafe99e9d1c61131 +SHA1 (NetBSD-6.0/shark/binary/kernel/netbsd-INSTALL.symbols.gz) = 4033fc14abf440fef2f4e6370dead899e4983721 +SHA512 (NetBSD-6.0/shark/binary/kernel/netbsd-INSTALL.symbols.gz) = 17fb47f8b2731f8fe73376ab664040eefdc64690156e26acad0791871e64e5d401ea95f592a034eaf963ceebc919a6d54c06874c8be8141b049637cc55aabc84 +RMD160 (NetBSD-6.0/shark/binary/kernel/netbsd-INSTALL.symbols.gz) = 9de247cfdaae7ee9022f6d09030b58665536dd2f +MD5 (NetBSD-6.0/shark/binary/kernel/netbsd-INSTALL.symbols.gz) = c89c4849f164a941bc9a17cb89ca4dc2 +SHA1 (NetBSD-6.0/shark/binary/kernel/netbsd-GENERIC.aout.gz) = 98a104383326606b65c14160cf13b700c0d0becc +SHA512 (NetBSD-6.0/shark/binary/kernel/netbsd-GENERIC.aout.gz) = 60c184cc2a78026b2ae297623a540618e63a58962e578fa8ecb0e68c5e94e9c64fe910da565b6e9427e0e99aae311e8645e2083a4cd02373f08c514a29fa9bfc +RMD160 (NetBSD-6.0/shark/binary/kernel/netbsd-GENERIC.aout.gz) = c1569194e6d7d526911ecc813919db5103eba092 +MD5 (NetBSD-6.0/shark/binary/kernel/netbsd-GENERIC.aout.gz) = 77f58eeb32ecae1a67c7821cfef3e1f1 +SHA1 (NetBSD-6.0/shark/binary/kernel/netbsd-GENERIC.gz) = 3aec79cc4bd37f7777e326445a18e4d551f4dc23 +SHA512 (NetBSD-6.0/shark/binary/kernel/netbsd-GENERIC.gz) = 46894446ed52b86e01d7fed75aa5285670d2d32a972be76a1019ea797583fff37423f4d9d40c29c394d123365b9a196fc7bb3824dc5952f6407b21198127cdba +RMD160 (NetBSD-6.0/shark/binary/kernel/netbsd-GENERIC.gz) = e34c8493497296b2d98dc0522d2d4d58b56a3546 +MD5 (NetBSD-6.0/shark/binary/kernel/netbsd-GENERIC.gz) = 9ccf14a3d80b596f8e594c2e7db89224 +SHA1 (NetBSD-6.0/shark/binary/kernel/netbsd-INSTALL.aout.gz) = 08fdda8c99f112770acb58f662e7dc7f92e211aa +SHA512 (NetBSD-6.0/shark/binary/kernel/netbsd-INSTALL.aout.gz) = eb7dd72ec967546883dbf9e50fc9bf770e8aced07020c03f93abdc0c9bd6b1a03ff320a3f5167f74caf732ff37495e7507628e0ea213ae8fbf209fbfc2ed2368 +RMD160 (NetBSD-6.0/shark/binary/kernel/netbsd-INSTALL.aout.gz) = 97cd05778ad6cbef869bfd1ef9bda107db56b099 +MD5 (NetBSD-6.0/shark/binary/kernel/netbsd-INSTALL.aout.gz) = f174a788515cbae3b497a13a1f27b68b +SHA1 (NetBSD-6.0/shark/binary/kernel/netbsd-INSTALL.gz) = 78fa421384bc331c7bf1194c90f45969e0b9f9ca +SHA512 (NetBSD-6.0/shark/binary/kernel/netbsd-INSTALL.gz) = c97fe5aa7c364929d749ee65dec8b6a7736da39e4d3366dfd8b17e67e8b5e56f9d37a0b8b4437c161602bfd265b486378ac272fc4e7917851b64faf8a9389370 +RMD160 (NetBSD-6.0/shark/binary/kernel/netbsd-INSTALL.gz) = ef146283b89c96c7d68bef166e853a83df6a65ee +MD5 (NetBSD-6.0/shark/binary/kernel/netbsd-INSTALL.gz) = dda410ee10ec3e07d4b962e08e5895c6 +SHA1 (NetBSD-6.0/shark/binary/sets/games.tgz) = e1d2bb091d8202962133475bc83edb55230b9008 +SHA512 (NetBSD-6.0/shark/binary/sets/games.tgz) = a147fe6d0419d53d5a428802d0bb6c9fa8a84a76c96d7d6d7c0d399e5af3a69240116463549a83d53387b0214ba0207796d7c10228d92a684fe7ff0ece3aec16 +RMD160 (NetBSD-6.0/shark/binary/sets/games.tgz) = 2be515c495548ba5135ff42a75a8ebbfc35ea776 +MD5 (NetBSD-6.0/shark/binary/sets/games.tgz) = 9059a6f2cd41cb58827709c9e9a1649b +SHA1 (NetBSD-6.0/shark/binary/sets/man.tgz) = 899b9d8242e983a5110ab755651c24f709b5af67 +SHA512 (NetBSD-6.0/shark/binary/sets/man.tgz) = 410999db110d710f4bb498c3d7ae7adc62170c7c2f470ce189c92f6c436c5ea96149659c631ef0b5605caaa025d97dfe1c07c428d86f51239657bd6b71717b15 +RMD160 (NetBSD-6.0/shark/binary/sets/man.tgz) = c1270f68c6d41b351877f71f0396ac34877dfc8d +MD5 (NetBSD-6.0/shark/binary/sets/man.tgz) = df4db2bbfa39ef6a4a215d949653d04a +SHA1 (NetBSD-6.0/shark/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/shark/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/shark/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/shark/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/shark/binary/sets/xetc.tgz) = 222d14c205f1018cc5a86eb03214d18cda2abb82 +SHA512 (NetBSD-6.0/shark/binary/sets/xetc.tgz) = fb82261996aa772fd8a9022eadebf899ee04ee70229ee4fe07758ca14937bdb34752c8218eb4c5b722b6208f719891493bbc141372fcfa503de83e0a61aa7387 +RMD160 (NetBSD-6.0/shark/binary/sets/xetc.tgz) = 511ebfe5076f361b7f7ca03a265d16052a16d259 +MD5 (NetBSD-6.0/shark/binary/sets/xetc.tgz) = 165cffbb6d2c79663198d80c82afac1e +SHA1 (NetBSD-6.0/shark/binary/sets/xfont.tgz) = ce0e141beeffeb5b470478e9887e4127da85de3c +SHA512 (NetBSD-6.0/shark/binary/sets/xfont.tgz) = 5d98354ff77103793d56af3192ab5f9afcde62208791976064ac33a149f994e0227dd5dd28ed544eeac5ea504e5212d5fb9e7d05e59e5a48a2fe4062e34e3106 +RMD160 (NetBSD-6.0/shark/binary/sets/xfont.tgz) = 4d09f5e82fec875ef0ea328809465e7a98f2ebfc +MD5 (NetBSD-6.0/shark/binary/sets/xfont.tgz) = be26b3890261302420b09976a1d38144 +SHA1 (NetBSD-6.0/shark/binary/sets/kern-GENERIC.tgz) = 436b25de68b7e666f29611394561037b31f1a9b7 +SHA512 (NetBSD-6.0/shark/binary/sets/kern-GENERIC.tgz) = 64acef2068786ba3afa466eda01db892f03fb48db03ad9ee0817f6a78b8019225beac65553dcd733d9858b4c35da337cbb20a7efa7019e77178e637dd5cb25f2 +RMD160 (NetBSD-6.0/shark/binary/sets/kern-GENERIC.tgz) = 83396c190ee6331e8297e4abc20d5b940b654e23 +MD5 (NetBSD-6.0/shark/binary/sets/kern-GENERIC.tgz) = a00e97b04a6d5affc36743311bc2293e +SHA1 (NetBSD-6.0/shark/binary/sets/base.tgz) = fa2c393fa435744e1b106d19470278c97d9419fb +SHA512 (NetBSD-6.0/shark/binary/sets/base.tgz) = a6ec0e86858f7c9faef7b4df4f2a951fa120af290d18d06598bb82b54541fe1a36d60b47f03da404a0d97889a5ea582db0a13b4a1827acf9e1842c70c90fcc0c +RMD160 (NetBSD-6.0/shark/binary/sets/base.tgz) = 151c8a2e662926762a132b689b24943ac8b93c01 +MD5 (NetBSD-6.0/shark/binary/sets/base.tgz) = 787953226e7c5d1aeb78aba04cb18579 +SHA1 (NetBSD-6.0/shark/binary/sets/comp.tgz) = d37041a235ddf0a129bfa9f1d5e11d2fdb77816f +SHA512 (NetBSD-6.0/shark/binary/sets/comp.tgz) = 19427e8b7dc48941e4e54ff0b8841358a551599c43862f830a752551044f96ed39bbd8038348fb3f3bf15ee831e0638cc4a3b4f0c04037222666f017cb11b862 +RMD160 (NetBSD-6.0/shark/binary/sets/comp.tgz) = 58df952b8aea84f1e0bc2658871408502eef4667 +MD5 (NetBSD-6.0/shark/binary/sets/comp.tgz) = ef10bf2cdec1811b1d3a2d3376201583 +SHA1 (NetBSD-6.0/shark/binary/sets/etc.tgz) = 07309c170d21a4c786ac5a12f5e792580788cd76 +SHA512 (NetBSD-6.0/shark/binary/sets/etc.tgz) = 6424ecfc34615c6fd1acb909b70414806e516119f30df73b70ee7128e69060da9457043da999de6011e7556a6685091cd30f4033e0ab7ea8cb0a2c6cc02c03ec +RMD160 (NetBSD-6.0/shark/binary/sets/etc.tgz) = b2fa61062310af5511249b80505cefc966801f9b +MD5 (NetBSD-6.0/shark/binary/sets/etc.tgz) = 1b69ed72ccfb0af799b148825a53bc9c +SHA1 (NetBSD-6.0/shark/binary/sets/modules.tgz) = 3ef4de9b2730972b94688f3674b121eeabd2448d +SHA512 (NetBSD-6.0/shark/binary/sets/modules.tgz) = 7c29c66462378dc8d7e7d5bfce324b012383176d8b381e83122808920f2d88d80665547a6e2974738fb6b1268aeacc4a7cde9ef17faec3d9d5c155ae2544cd37 +RMD160 (NetBSD-6.0/shark/binary/sets/modules.tgz) = ae6f3aba96b1b9b2d2a412754a42296afc85a69c +MD5 (NetBSD-6.0/shark/binary/sets/modules.tgz) = 5f374bf40599728af733192b3a546d7e +SHA1 (NetBSD-6.0/shark/binary/sets/tests.tgz) = 62e58a9b83eec5a0fb21b9fe7f5845e5315811e7 +SHA512 (NetBSD-6.0/shark/binary/sets/tests.tgz) = 43d78bd32bff49e6f6c62914cd16916e41541fb446913c688d0fe4fdbcf5fff6d5605688ec165f8e856a418bba4f36c7d7233b8344c86b954ce104e963abe0a0 +RMD160 (NetBSD-6.0/shark/binary/sets/tests.tgz) = 560f27cf65beada1eb6e62458b7450968218fd37 +MD5 (NetBSD-6.0/shark/binary/sets/tests.tgz) = 4d39b8cb6664b022b300186cb7afa8e6 +SHA1 (NetBSD-6.0/shark/binary/sets/text.tgz) = 663a9a70c81324796717d31e46d5e8c00620a132 +SHA512 (NetBSD-6.0/shark/binary/sets/text.tgz) = ae6817fabcfae5fd0a9f35787e6d9af82d64a14c6d532c1a54c347c367d23c6ccc274eb813a23e4bb4dcb036b829437130400c418ffd0eb9c36858443f8d9b84 +RMD160 (NetBSD-6.0/shark/binary/sets/text.tgz) = 51994c6b412ee1e6834b270482f8c0dbbc95a835 +MD5 (NetBSD-6.0/shark/binary/sets/text.tgz) = c93688098447ac5ebf664bfb3362615e +SHA1 (NetBSD-6.0/shark/binary/sets/xbase.tgz) = 2782c3a99b0cdb6ea4c4b29543f6f06b24c1726f +SHA512 (NetBSD-6.0/shark/binary/sets/xbase.tgz) = 90a42af846fd7479e30789a28c7908b2b70416e7824d7f78c31b378c5e1dd38d4eb797f4430f6dd9baf051afe1750ad4bacdd3e93f2b65b2ad92945f682a1685 +RMD160 (NetBSD-6.0/shark/binary/sets/xbase.tgz) = 6b4e44c69f47563964562f18c42a5bc5a99e750a +MD5 (NetBSD-6.0/shark/binary/sets/xbase.tgz) = 1c370ba00bea97b4afbef7e3bc919655 +SHA1 (NetBSD-6.0/shark/binary/sets/xcomp.tgz) = 997e19373b3e9b90464e849f1d635e33235aa5f7 +SHA512 (NetBSD-6.0/shark/binary/sets/xcomp.tgz) = 1e9d84d70a45aa3ea4d4bff9066594e853b9af68912e58bc933060f2b652ceea2d40231e04debed15dc569ec3d1d2d3682b3042b009c0738f17bf11979f2e86e +RMD160 (NetBSD-6.0/shark/binary/sets/xcomp.tgz) = 60b1ce3cf224d2caf6d4c9757761c8145d4bcc4f +MD5 (NetBSD-6.0/shark/binary/sets/xcomp.tgz) = 0bd79975afc5e2dbf542c8ab9363b664 +SHA1 (NetBSD-6.0/shark/binary/sets/xserver.tgz) = cf7350b715c568255b8d095503eed754c3d1ff31 +SHA512 (NetBSD-6.0/shark/binary/sets/xserver.tgz) = 3c88b006114891f2e3aaac95d15f25de6c8ac1dd00802097d1885f015326e926a297dcdf6c9c10a798ff73242e3130a7e359bd7f4bab45b23408a628da011725 +RMD160 (NetBSD-6.0/shark/binary/sets/xserver.tgz) = e9a9b2579181cfc7974ab1586990bbb0f2470299 +MD5 (NetBSD-6.0/shark/binary/sets/xserver.tgz) = 795a4afd76d016cb1868344522fb0fb4 +SHA1 (NetBSD-6.0/shark/installation/instkernel/netbsd.gz) = 08fdda8c99f112770acb58f662e7dc7f92e211aa +SHA512 (NetBSD-6.0/shark/installation/instkernel/netbsd.gz) = eb7dd72ec967546883dbf9e50fc9bf770e8aced07020c03f93abdc0c9bd6b1a03ff320a3f5167f74caf732ff37495e7507628e0ea213ae8fbf209fbfc2ed2368 +RMD160 (NetBSD-6.0/shark/installation/instkernel/netbsd.gz) = 97cd05778ad6cbef869bfd1ef9bda107db56b099 +MD5 (NetBSD-6.0/shark/installation/instkernel/netbsd.gz) = f174a788515cbae3b497a13a1f27b68b +SHA1 (NetBSD-6.0/shark/INSTALL.html) = ee446561ae849bf3326e81939b2071c706bbbe7e +SHA512 (NetBSD-6.0/shark/INSTALL.html) = 01bd9dca202f365a64c9f523cf025abc31a7180a8b45f843d1e60cfe4682329aedc8a892b8e2a6a230bfda1803c6740b6d9fe415992f5a2206425cd875ca3e1f +RMD160 (NetBSD-6.0/shark/INSTALL.html) = c73d5cfb8e656b4634046ab9dabaa09772f8e383 +MD5 (NetBSD-6.0/shark/INSTALL.html) = 4207442c91faf52d0f3778fb77943ec0 +SHA1 (NetBSD-6.0/shark/INSTALL.more) = 9259e39f2fbc92e793da04efa5acb0318ee257c6 +SHA512 (NetBSD-6.0/shark/INSTALL.more) = a9510586f73298c7b0b8af60cf30b86d4588b90682b73adc3f14cb862f0f7ec0f103ff62eda6d4a141a2c5a24fa13d108f08817829a00545f8400ff9785460dc +RMD160 (NetBSD-6.0/shark/INSTALL.more) = f80b0169a0a6cc36d204319f0e5ea6ac9e3c6256 +MD5 (NetBSD-6.0/shark/INSTALL.more) = cc98ec10bfc9ee19abfac7bb78843b52 +SHA1 (NetBSD-6.0/shark/INSTALL.ps) = d63b6262c2b64c83f763fdc888153b4d5785a5d7 +SHA512 (NetBSD-6.0/shark/INSTALL.ps) = e7082fc171e77f43761b8f8dba6443f9a76103be8b964d70e845940cec689c10579d8e5a6aa80bbb008cbde61c125fe348a3db7d157235df9dd6b53d247c3b8d +RMD160 (NetBSD-6.0/shark/INSTALL.ps) = 5ae64ccead4bce193eef02a56c1883be5836e3f6 +MD5 (NetBSD-6.0/shark/INSTALL.ps) = b80bf37de21a0d2a7c1891ea18ee27cc +SHA1 (NetBSD-6.0/shark/INSTALL.txt) = 21743fee95f9d668c37c80415896d05a652d8e5f +SHA512 (NetBSD-6.0/shark/INSTALL.txt) = 80bc5a7e1ef3338c29c29b51f72b5c014bb10a7e7f367912ecc1e6633c7882ad23c119733c81dbcc4d7ff5178303dc555fa42951a48d364613ff52048d8e500d +RMD160 (NetBSD-6.0/shark/INSTALL.txt) = 15c92de408750d0c47946ad7c7c7371a79e1e2c6 +MD5 (NetBSD-6.0/shark/INSTALL.txt) = ba3059416376468dad953da22a4bf29e +SHA1 (NetBSD-6.0/source/sets/sharesrc.tgz) = 87a69ce98fc413c46524823e16dcd0dce768698c +SHA512 (NetBSD-6.0/source/sets/sharesrc.tgz) = aedb194ace955f8c15820ae3e6d8bdbf67992da79f8cb3d2d0a2ad409819a78c7d3921fda193a982a6f032f92113fc807e0ad2eb064a82da98b8f5ec957bc53a +RMD160 (NetBSD-6.0/source/sets/sharesrc.tgz) = 8e03f055e853b3b44d48cbafde267da9acd549f2 +MD5 (NetBSD-6.0/source/sets/sharesrc.tgz) = cdf8ab923e83b705dfc8e47e47ebdecf +SHA1 (NetBSD-6.0/source/sets/gnusrc.tgz) = a5bb46c56b0f27a47dbaa3690758336bdc472292 +SHA512 (NetBSD-6.0/source/sets/gnusrc.tgz) = d94945054d64c9b16ddf2b3fbcf0dc8aa41965f76e469e8da0fc822082189d87324169709f5a95aa8461209522d3cdb387f52beaada7ecefb46571b021d925bf +RMD160 (NetBSD-6.0/source/sets/gnusrc.tgz) = 562debda10c4d28bc11f9760fa7f7797f062a9fb +MD5 (NetBSD-6.0/source/sets/gnusrc.tgz) = b72569083f678e665d6658cbd2c3e587 +SHA1 (NetBSD-6.0/source/sets/syssrc.tgz) = 8206633fc5ac0f890ecffdd50176768236cd4cc6 +SHA512 (NetBSD-6.0/source/sets/syssrc.tgz) = 566104c4324710005c869e065dc03889e85824910520d097a88c1bd5219adc750b3ef8d0057a7d98a7d535002c4c6e04594d98b5be138b8e29d74b1f3965b045 +RMD160 (NetBSD-6.0/source/sets/syssrc.tgz) = 8f26506a9ce36e2a163026804d629e30628f8c4b +MD5 (NetBSD-6.0/source/sets/syssrc.tgz) = 8ece18d74c2fbd264198467f47e8b4bb +SHA1 (NetBSD-6.0/source/sets/src.tgz) = bada9cb20d00977af0fc80b465ae9bd20648c893 +SHA512 (NetBSD-6.0/source/sets/src.tgz) = 981158338e0123f59b5a38f3f5c3a4fb8142f0280e49db0af5f0753512035113887bdcc9aa3f980761b51abf625764d0e89ca4de41cb80145f5ef7239676d1b2 +RMD160 (NetBSD-6.0/source/sets/src.tgz) = 90dc01e48266e240dd95962496cd2a1aa1ca90f9 +MD5 (NetBSD-6.0/source/sets/src.tgz) = 58e1e661d9640ca3eb542ac3086580f3 +SHA1 (NetBSD-6.0/source/sets/xsrc.tgz) = 73f98faff9d1b90c50d50d50a1f17e6880f43f12 +SHA512 (NetBSD-6.0/source/sets/xsrc.tgz) = dbcf2591e42422a0ddb15529b35cd7e1f198589459806239d9efc917c5b604cd152fda76c5fd5a8e912410ee1fc25e561f7e505b63461192406a121e84fe3784 +RMD160 (NetBSD-6.0/source/sets/xsrc.tgz) = 617e6308cfbb0899c230ceea2d843c197c4f4804 +MD5 (NetBSD-6.0/source/sets/xsrc.tgz) = 68d1535d0baed6625f6dd95fd20758ba +SHA1 (NetBSD-6.0/sparc/binary/kernel/netbsd-GENERIC.MP.gz) = 496928e218106c5bc8d32bd6c736eddf69258416 +SHA512 (NetBSD-6.0/sparc/binary/kernel/netbsd-GENERIC.MP.gz) = cc26d9ef454d86c7e95a122eb0ef5d6f9dc742b0f9718d0a798e9666974d977de44d90025f38c2947c9d161c3b52a9eb8f42aa866a0198d310f7defd7f472db8 +RMD160 (NetBSD-6.0/sparc/binary/kernel/netbsd-GENERIC.MP.gz) = 3ccc735931179c31c8f2d4b5ce1e9f96121ff695 +MD5 (NetBSD-6.0/sparc/binary/kernel/netbsd-GENERIC.MP.gz) = 61be9899c92c833cb52f77b6f8e6aee4 +SHA1 (NetBSD-6.0/sparc/binary/kernel/netbsd-GENERIC.gz) = 7b45c74363d7977534a97b006e114ef4051246c0 +SHA512 (NetBSD-6.0/sparc/binary/kernel/netbsd-GENERIC.gz) = fc19ac6cf8544def619f803ab7573083991e050b8d551e9c4967d1e327e4ebfe51137f516815152fc00dceed5879309ba4e5e9c420b088378c0323c739df8cdc +RMD160 (NetBSD-6.0/sparc/binary/kernel/netbsd-GENERIC.gz) = 86944c7c8fbed3cad7ddfef09833eee06231c3bd +MD5 (NetBSD-6.0/sparc/binary/kernel/netbsd-GENERIC.gz) = 2daad7afb8771cd536a5bd668d3e981b +SHA1 (NetBSD-6.0/sparc/binary/kernel/netbsd-GENERIC_SCSI3.gz) = 1138b7a86c5bb93d6b3904164e3841031880b675 +SHA512 (NetBSD-6.0/sparc/binary/kernel/netbsd-GENERIC_SCSI3.gz) = df36f0aac760c383f970b2dd9e13a4e6e3ca28d47846c904cc07ba11b6e289fe6c8319a40fd51850e5ced7a4585d61c83f489769cfe8aac189b650116f8faeeb +RMD160 (NetBSD-6.0/sparc/binary/kernel/netbsd-GENERIC_SCSI3.gz) = e95d11e401563a66d9cc798db312d3f2a1b96c5f +MD5 (NetBSD-6.0/sparc/binary/kernel/netbsd-GENERIC_SCSI3.gz) = 0aaca233a00a9fce3265a749b9a2852d +SHA1 (NetBSD-6.0/sparc/binary/kernel/netbsd-GENERIC_SUN4U.gz) = 0732f8665299b419119c4507e525a6c992f20656 +SHA512 (NetBSD-6.0/sparc/binary/kernel/netbsd-GENERIC_SUN4U.gz) = dcd45f52ade746443eeb910f331ccbce2d48eaf03f2e49c7ac75940b36e2097e41ed5873224bf664e4bd935ba17b1503a61640427a7d9ea87ecdcad39f7eee60 +RMD160 (NetBSD-6.0/sparc/binary/kernel/netbsd-GENERIC_SUN4U.gz) = 568b09bb65717c3ae1b2f2e3a5b1c15316a3c53d +MD5 (NetBSD-6.0/sparc/binary/kernel/netbsd-GENERIC_SUN4U.gz) = 785d8668cfd1df9f6bd6af6587636e0f +SHA1 (NetBSD-6.0/sparc/binary/kernel/netbsd-KRUPS.gz) = bd5c8ef678bdeca11a32980b732803967ab0398f +SHA512 (NetBSD-6.0/sparc/binary/kernel/netbsd-KRUPS.gz) = 1c79b7d19dbab9bb132529d1bf10f6a3d9f8bdbf006d1296721c5a987812cf55a077368b75b4775e1425dda56afde6ab35f5995648187c623dcdb3154d2a050a +RMD160 (NetBSD-6.0/sparc/binary/kernel/netbsd-KRUPS.gz) = 93604d098cedbfd647a5ac6ea9409928bebc48d6 +MD5 (NetBSD-6.0/sparc/binary/kernel/netbsd-KRUPS.gz) = 7108981b6236f991fca67fe58d6eae81 +SHA1 (NetBSD-6.0/sparc/binary/kernel/netbsd-MRCOFFEE.gz) = 976e0a56648d3e03356d7f76426971fa523e4551 +SHA512 (NetBSD-6.0/sparc/binary/kernel/netbsd-MRCOFFEE.gz) = 172bd67678acdf034d897369d1d92be25dd684dbd14f362fad6c9655f7d5265caf4b57d495c570eebc1e53a87c53374d8f552656fa66366d3ac6221ccf98a752 +RMD160 (NetBSD-6.0/sparc/binary/kernel/netbsd-MRCOFFEE.gz) = b3a6897f2e3eb5acfe2d87f7d377697caeb3b007 +MD5 (NetBSD-6.0/sparc/binary/kernel/netbsd-MRCOFFEE.gz) = 7ea122d02744bc1fc5e42853992c908a +SHA1 (NetBSD-6.0/sparc/binary/kernel/netbsd-MRCOFFEE_OFW.gz) = 181bf7c2d1cd731f71c5334a5d0d097749f166af +SHA512 (NetBSD-6.0/sparc/binary/kernel/netbsd-MRCOFFEE_OFW.gz) = 63f26657f4bdde1cff58858fd5ffda69867a45d8148c4b4cf13804281389f34026a09f9f228eb670ff01ed8a02e99affb67b7a170fdcdda5f8f5cb128eaa9ece +RMD160 (NetBSD-6.0/sparc/binary/kernel/netbsd-MRCOFFEE_OFW.gz) = fabe6d8566d88af5324ffa952c57f0fad3accd95 +MD5 (NetBSD-6.0/sparc/binary/kernel/netbsd-MRCOFFEE_OFW.gz) = 8a5f7d38f6ddc835e528d51886df36e7 +SHA1 (NetBSD-6.0/sparc/binary/sets/man.tgz) = 899b9d8242e983a5110ab755651c24f709b5af67 +SHA512 (NetBSD-6.0/sparc/binary/sets/man.tgz) = 410999db110d710f4bb498c3d7ae7adc62170c7c2f470ce189c92f6c436c5ea96149659c631ef0b5605caaa025d97dfe1c07c428d86f51239657bd6b71717b15 +RMD160 (NetBSD-6.0/sparc/binary/sets/man.tgz) = c1270f68c6d41b351877f71f0396ac34877dfc8d +MD5 (NetBSD-6.0/sparc/binary/sets/man.tgz) = df4db2bbfa39ef6a4a215d949653d04a +SHA1 (NetBSD-6.0/sparc/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/sparc/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/sparc/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/sparc/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/sparc/binary/sets/kern-GENERIC.MP.tgz) = c77b07953f63e5e21d1313e08dacf592acbddeef +SHA512 (NetBSD-6.0/sparc/binary/sets/kern-GENERIC.MP.tgz) = 40e533f5b17404c1d1137cee7e541193f5f6ad323bc615ba5db6a1dfd4816a27eb54b26d272886dbedc9184e85b36ba1ef6e798e140f84e669475eebdd61a015 +RMD160 (NetBSD-6.0/sparc/binary/sets/kern-GENERIC.MP.tgz) = 2e067f3f9ef9697eba5185ff0d15d847c6e277a4 +MD5 (NetBSD-6.0/sparc/binary/sets/kern-GENERIC.MP.tgz) = 496e0471d0eb80e227337bdaa45db5b2 +SHA1 (NetBSD-6.0/sparc/binary/sets/base.tgz) = 952c71b877521b1af63302bbe4c072b482c3723e +SHA512 (NetBSD-6.0/sparc/binary/sets/base.tgz) = 14dc66a667648834321d8bde6c4f9e07c582ac569ceda4991552119282b53690521a89cb0fc06e2c0952f75d9dbc6c9c554f922e74111f4d42c94085bd4697ec +RMD160 (NetBSD-6.0/sparc/binary/sets/base.tgz) = e57ecaa3098d2ae780c38e3e085c6f164498cd95 +MD5 (NetBSD-6.0/sparc/binary/sets/base.tgz) = b9fb689a8d63084ad2d6a4089028296d +SHA1 (NetBSD-6.0/sparc/binary/sets/comp.tgz) = 59f49bbeaebf959d30414d0cacca3724359d55e8 +SHA512 (NetBSD-6.0/sparc/binary/sets/comp.tgz) = a800a26ddca7c79ccda284ab3b5e815cc4b53c409ca78bb00f386348e4ae973edf66440a931d9fe2ab0f8a16e329d885c3a2f190780600ca4e205936d7d01e8d +RMD160 (NetBSD-6.0/sparc/binary/sets/comp.tgz) = 3a0cc6492eb72ee033ccd0b60c0c1698fa6b49d1 +MD5 (NetBSD-6.0/sparc/binary/sets/comp.tgz) = 39c91111ea991ede7ef81fa845ac319d +SHA1 (NetBSD-6.0/sparc/binary/sets/etc.tgz) = 7cca1a9e594b2122f17b67a26d15e2051403bc68 +SHA512 (NetBSD-6.0/sparc/binary/sets/etc.tgz) = 191f890e7588a17a3258e92d51a91407281c97fe84e2ce68f6fc1db48b95011b1c15f86cc3bef58dff5b167c8ee1608fb42c22b55b78df7461a60827882bb0e4 +RMD160 (NetBSD-6.0/sparc/binary/sets/etc.tgz) = 39d06e86cfc8d3fb588c5b95371ece29ef11b5de +MD5 (NetBSD-6.0/sparc/binary/sets/etc.tgz) = f909a9a70e65ad480468d1de75f057b0 +SHA1 (NetBSD-6.0/sparc/binary/sets/games.tgz) = 352b9089651bdd1ba05526f34fd99bf8e89db039 +SHA512 (NetBSD-6.0/sparc/binary/sets/games.tgz) = bd7c551fde89b7339d6b652a2583322c662bf0d4b69ce143034253f9764cfefabc5abe45d8e8850f7b9ee2d5714cda13f26f1d516679b544c096d27cbaf87b08 +RMD160 (NetBSD-6.0/sparc/binary/sets/games.tgz) = 9e71d26c198691e30f653c47b3b725ab54f1144e +MD5 (NetBSD-6.0/sparc/binary/sets/games.tgz) = f6932706a5fba3dc666106b7b84ea734 +SHA1 (NetBSD-6.0/sparc/binary/sets/kern-GENERIC_SCSI3.tgz) = e5359bdc3fc08e7fc7b5f0ffae289d8e3bbebe72 +SHA512 (NetBSD-6.0/sparc/binary/sets/kern-GENERIC_SCSI3.tgz) = 88e1c0850a758a10d7752c1c64d4d80b5fc9935eb8cd9f4869585ca42cb5706bb6c1fa38467e7ba67a28f0b3e4e12df989839b1c7f6a777785e919eda6c4e464 +RMD160 (NetBSD-6.0/sparc/binary/sets/kern-GENERIC_SCSI3.tgz) = 6486dfa05e73ea92b83ab42151f3978fb8d9cb3b +MD5 (NetBSD-6.0/sparc/binary/sets/kern-GENERIC_SCSI3.tgz) = 8965e59f45390938dd1f4cca3b47b215 +SHA1 (NetBSD-6.0/sparc/binary/sets/kern-GENERIC.tgz) = 0803f566c7ab3cc4ac8bdb66f0e6e93e44f6780b +SHA512 (NetBSD-6.0/sparc/binary/sets/kern-GENERIC.tgz) = ac72f82075f9cd2d7a5aaa4556f0e6efcdd6207ecfd3c6eef2773281f9088fca35169b68987c3a95f8481670fbd637caaccc48a6fea450c5334e1a5a61a009ab +RMD160 (NetBSD-6.0/sparc/binary/sets/kern-GENERIC.tgz) = 4a8db5843d949d1d2b6c45e23313628ef2db07ae +MD5 (NetBSD-6.0/sparc/binary/sets/kern-GENERIC.tgz) = 7c8d15c09c139fc7445d83e669004f26 +SHA1 (NetBSD-6.0/sparc/binary/sets/xcomp.tgz) = 4671cf1becbd220fb0693d8dc580bf90fd558a38 +SHA512 (NetBSD-6.0/sparc/binary/sets/xcomp.tgz) = a37753c7f879f4d7205dfa23488b6fda40aa098cdf5d998f3b8335c487d2bffc7d9edbd57de2f12dfce586d60f2044f1617173fa6902e821a74dacc314382b98 +RMD160 (NetBSD-6.0/sparc/binary/sets/xcomp.tgz) = ed445184a03edb2cf1bf204e9cbbd04ce6f8367e +MD5 (NetBSD-6.0/sparc/binary/sets/xcomp.tgz) = 82dc6b78584e5997bcdf436f37400177 +SHA1 (NetBSD-6.0/sparc/binary/sets/kern-GENERIC_SUN4U.tgz) = 478f84d19aae7f5aee8ddfdb45eb9aa37a21a3d3 +SHA512 (NetBSD-6.0/sparc/binary/sets/kern-GENERIC_SUN4U.tgz) = b9168217a02a3da991b5b3fb069097b663dea23088a529f16ea09dc12c233bc4d63b4310fbc8e26285e6bc9cd566144141898743fc8617bd9296956432b2f9b2 +RMD160 (NetBSD-6.0/sparc/binary/sets/kern-GENERIC_SUN4U.tgz) = e9e53c86f42b75fcc12853ed2dfd5423b0968581 +MD5 (NetBSD-6.0/sparc/binary/sets/kern-GENERIC_SUN4U.tgz) = ee3736e6af879f5d4e0cc369bfa579b5 +SHA1 (NetBSD-6.0/sparc/binary/sets/kern-KRUPS.tgz) = bc69fd900a788cd8ce5d7413b4716f656814b804 +SHA512 (NetBSD-6.0/sparc/binary/sets/kern-KRUPS.tgz) = 64c42a3748d62926aa10870c08331bce20b67f6b50afd13a19a76b232b2f9f2d1c2fa04819cf88f211badbdff0cc1684ca48ca7f1c6d8f44859257764e882842 +RMD160 (NetBSD-6.0/sparc/binary/sets/kern-KRUPS.tgz) = 18df230d31af7e526b9f6fb3254061e6601a9b15 +MD5 (NetBSD-6.0/sparc/binary/sets/kern-KRUPS.tgz) = 1057e644aef74d636a558c03dd9f7e7e +SHA1 (NetBSD-6.0/sparc/binary/sets/kern-MRCOFFEE.tgz) = 58b500435295d07ef47bd1702ce2f8c5fe798e8c +SHA512 (NetBSD-6.0/sparc/binary/sets/kern-MRCOFFEE.tgz) = f3657cd11910995d2bf8e4140f4df4d6829311de9d5a4fa39a980af3577035ad7cc1189066aa0d9093803727b0e1405e9e2c5bbad4db8e4e172e9d5d000c2541 +RMD160 (NetBSD-6.0/sparc/binary/sets/kern-MRCOFFEE.tgz) = 91c5e94452446fb8838dfadab79d8f0c915669a5 +MD5 (NetBSD-6.0/sparc/binary/sets/kern-MRCOFFEE.tgz) = 2535895e15ea9dc1c4806df090d1bc81 +SHA1 (NetBSD-6.0/sparc/binary/sets/kern-MRCOFFEE_OFW.tgz) = cc966bc2458bae8bdd3995d423ae83707d0a0a38 +SHA512 (NetBSD-6.0/sparc/binary/sets/kern-MRCOFFEE_OFW.tgz) = 35967055f863081ef3d16144c5324ab62c2e44942100202414961a58b8b3e1243e8a2b3e2ff4d7075df0e624d9da1ff7889f8c9dc710c888f6654d8d845233d9 +RMD160 (NetBSD-6.0/sparc/binary/sets/kern-MRCOFFEE_OFW.tgz) = 5451d5da667a2a57e3af6df7119703db7a2ec8a2 +MD5 (NetBSD-6.0/sparc/binary/sets/kern-MRCOFFEE_OFW.tgz) = 8cb1f508b5103088f400e7422e23a34f +SHA1 (NetBSD-6.0/sparc/binary/sets/modules.tgz) = 6519d6696e013f8a9e51d2856aac1390c0c3e69a +SHA512 (NetBSD-6.0/sparc/binary/sets/modules.tgz) = 4dd5d8721c4d0733813e1fc884e9242cbf957f33ccf92fa7a8f3255bcf1af3598de843e15ad052a696cd95065251cae8a6927816c041732a6f12823657ef22fd +RMD160 (NetBSD-6.0/sparc/binary/sets/modules.tgz) = cab574162ec0996f845835763055d6e65bb4ceb4 +MD5 (NetBSD-6.0/sparc/binary/sets/modules.tgz) = a60477fd2b83a211972512c035679276 +SHA1 (NetBSD-6.0/sparc/binary/sets/tests.tgz) = 816dc19db04ba2f95dcf80c62598f9fec7fa92ff +SHA512 (NetBSD-6.0/sparc/binary/sets/tests.tgz) = 80c23ac0ed623404542d3e6b6e7dc8194ae876c6a0d17b250151ce6e941e874a033dcce8afa002fbe3d875b1c79687e392fa6f527fa46ec0e3c82ae31cfd5eb9 +RMD160 (NetBSD-6.0/sparc/binary/sets/tests.tgz) = 834ebf4c2126e3ec1b2226e48564ab87d7ff8da0 +MD5 (NetBSD-6.0/sparc/binary/sets/tests.tgz) = 9d0c1bd587f83df1b0090f88357f8531 +SHA1 (NetBSD-6.0/sparc/binary/sets/text.tgz) = 92d7911a1d761b73c8d2080e819705f901d1ce6d +SHA512 (NetBSD-6.0/sparc/binary/sets/text.tgz) = 4e8e2f2abc8cf95a4672ef492e091142b6cc4a4baafddb6fc123fa5b3cc3d67a16e61ab4a7b188dac4b8ea198d8c88c1c81ffe1eca70f9900780a8a134257c36 +RMD160 (NetBSD-6.0/sparc/binary/sets/text.tgz) = 4d5ca8f6d680d3389d6b90c45875bcc4b4e962f3 +MD5 (NetBSD-6.0/sparc/binary/sets/text.tgz) = c16beb242b426177d80af90e40266abf +SHA1 (NetBSD-6.0/sparc/binary/sets/xbase.tgz) = 2809df01d9a0aa85270f6f77341cf50d72bc78bc +SHA512 (NetBSD-6.0/sparc/binary/sets/xbase.tgz) = 886f26f21f95ea17ef60d28fabebf415485d13647d335b237a4ee954039c7c6dfc0d9e68c06aec52ef463b6c2b7b88cd6baf514f2c5b567b8f5421c99df12672 +RMD160 (NetBSD-6.0/sparc/binary/sets/xbase.tgz) = 499a1e2a76a05fa4a0b3b53438d60b8434198695 +MD5 (NetBSD-6.0/sparc/binary/sets/xbase.tgz) = 82bb74d040bf256d711afb55db6c4066 +SHA1 (NetBSD-6.0/sparc/binary/sets/xetc.tgz) = 997196c30074dcc988f2dfa2a7f5dfc8c31df3db +SHA512 (NetBSD-6.0/sparc/binary/sets/xetc.tgz) = 09670a40f33c9902b5b22c4400f9e8151f1985504cc1c956df68697e3bd6a7b841391d6dd32cdbba42aebf42f4a1cdd3559c5783f79da236603dc6b5cf86d33c +RMD160 (NetBSD-6.0/sparc/binary/sets/xetc.tgz) = 50061239bbe31a4dce18784bfcece78a234e6ef5 +MD5 (NetBSD-6.0/sparc/binary/sets/xetc.tgz) = 12ae04f5957291f424568bb61a138079 +SHA1 (NetBSD-6.0/sparc/binary/sets/xfont.tgz) = 7e5ccc7436f81855bd5e20960adaddd9b9851fd5 +SHA512 (NetBSD-6.0/sparc/binary/sets/xfont.tgz) = f263bf4a2b1bc795c1c4dcaf0db819dca08e90c51b41c144911f897a991a3575dcbbac203060d8f51842c85c6e85c4839297fb7307353a38b1a46e1b446d29a3 +RMD160 (NetBSD-6.0/sparc/binary/sets/xfont.tgz) = cb721308df7413a821278143750bf95844eb4d82 +MD5 (NetBSD-6.0/sparc/binary/sets/xfont.tgz) = 9de78b2d18118d7435a6c95d8a503ae4 +SHA1 (NetBSD-6.0/sparc/binary/sets/xserver.tgz) = 0d3b410b9501560307d3b9b17a431be0da1de869 +SHA512 (NetBSD-6.0/sparc/binary/sets/xserver.tgz) = d3dceb5ebfb5085e905e8121c952a97bf7035bbd4e60898d913fbaf58c147181ae7c97f913a122e9ce83523d05a585d1e771139192d42c44fa85e60e2bed762a +RMD160 (NetBSD-6.0/sparc/binary/sets/xserver.tgz) = fd59e7a1c949c113ec555a9ee63ab369f64559fa +MD5 (NetBSD-6.0/sparc/binary/sets/xserver.tgz) = a89a1c519c6d6759f810717fc0ec43ab +SHA1 (NetBSD-6.0/sparc/installation/bootfs/netbsd.ram.aout.gz) = c2c368ba46549cb580707b799f4f0f88b26128de +SHA512 (NetBSD-6.0/sparc/installation/bootfs/netbsd.ram.aout.gz) = 9fb6bef663b2fb68b9bf3591834f6e653c0b3b7f69ac8c40f2479efaa5d0641140d87623fe8eeb8a21cb0e0065ceacb57d6a5db4e1905db97f7dffa52ba8b565 +RMD160 (NetBSD-6.0/sparc/installation/bootfs/netbsd.ram.aout.gz) = 8fbcdca0f8214901d1fec117c567cfe93865e391 +MD5 (NetBSD-6.0/sparc/installation/bootfs/netbsd.ram.aout.gz) = 1cf0fdefa01fee95d494b3418ea4a0ea +SHA1 (NetBSD-6.0/sparc/installation/bootfs/boot.fs.gz) = e36798e87b9d195c7df8602883c775f8f4268448 +SHA512 (NetBSD-6.0/sparc/installation/bootfs/boot.fs.gz) = acd6ad2fa9c1618b4b14d6a63679e347aad6302001e36ea63c58968252ce993df23af7e05e590b72efbcdbc1013192b1862d70d7737fc2fa804249410c9d2724 +RMD160 (NetBSD-6.0/sparc/installation/bootfs/boot.fs.gz) = 986addabcfd9f0b1faccd9fed0081f88e78f2aaf +MD5 (NetBSD-6.0/sparc/installation/bootfs/boot.fs.gz) = 93526666c7879bc6391c5b7c38b24cb0 +SHA1 (NetBSD-6.0/sparc/installation/bootfs/instfs.tgz) = 98f621b007b19382a0d529f2056cd8c82feb863f +SHA512 (NetBSD-6.0/sparc/installation/bootfs/instfs.tgz) = 7131f92cd02791f6d351a8ea5d8b5fe93b643ba5975522e85bf81da8f69157ebb21f80f5696beca47809a9732e79e85c7e97e07a33e830eeac2f9542685a01ce +RMD160 (NetBSD-6.0/sparc/installation/bootfs/instfs.tgz) = dc7168f774cac7e9f7eba640dc55c878ab2c16db +MD5 (NetBSD-6.0/sparc/installation/bootfs/instfs.tgz) = 80ed52c842f1d4d56d4506d293e30b57 +SHA1 (NetBSD-6.0/sparc/installation/bootfs/netbsd.ram.symbols.gz) = 673b10e3d23ee6e204bdba91b52b0b50304cb8e3 +SHA512 (NetBSD-6.0/sparc/installation/bootfs/netbsd.ram.symbols.gz) = edf95ecf1f6133e5228d4f8b6a8d004c1f172354acfa34f1235a488456a69b2fd19cd959f97a0a7d06f007347815672bfce07a3ee25ae511ce73a6e5de217267 +RMD160 (NetBSD-6.0/sparc/installation/bootfs/netbsd.ram.symbols.gz) = 8829961d6f2e5487af4bd4418335139d06916659 +MD5 (NetBSD-6.0/sparc/installation/bootfs/netbsd.ram.symbols.gz) = 75ea54ba199fcf8a56054d15e4fb3b96 +SHA1 (NetBSD-6.0/sparc/installation/bootfs/netbsd.ram.gz) = 8eb131ce31d568ee4fb0674f1732052bc686bb18 +SHA512 (NetBSD-6.0/sparc/installation/bootfs/netbsd.ram.gz) = 7345380b1e2e1140564b9886e4d2afc5dc21dacf7148a5680283abc41f7249a8e8512db23ca58533ebf5bffc588bb6a28b18c7e0eb5d50c8a5a06da4043af319 +RMD160 (NetBSD-6.0/sparc/installation/bootfs/netbsd.ram.gz) = 37ae0d93bd4532ff69c9187a1fd8ee3b75e97671 +MD5 (NetBSD-6.0/sparc/installation/bootfs/netbsd.ram.gz) = dc1f591b5bca88a07ff8e67a1c3dc01d +SHA1 (NetBSD-6.0/sparc/installation/miniroot/miniroot.fs.gz) = 4e71664ebc1dc62f55992a935734fe61f52177cd +SHA512 (NetBSD-6.0/sparc/installation/miniroot/miniroot.fs.gz) = 3cf2607774e1aa7343ed57c78034828878665e9a041561702daf18539a0775d27768ad89d9336c77d897a0f040c71c8cefdd555c00397d26fded0b6ce72c1dc3 +RMD160 (NetBSD-6.0/sparc/installation/miniroot/miniroot.fs.gz) = 39fff07e0ce17f0c62c3a399173b5a8681fa3559 +MD5 (NetBSD-6.0/sparc/installation/miniroot/miniroot.fs.gz) = 0355cc648c33e3ed61ac4ff2f51edd04 +SHA1 (NetBSD-6.0/sparc/installation/netboot/rootfs.tgz) = 98f621b007b19382a0d529f2056cd8c82feb863f +SHA512 (NetBSD-6.0/sparc/installation/netboot/rootfs.tgz) = 7131f92cd02791f6d351a8ea5d8b5fe93b643ba5975522e85bf81da8f69157ebb21f80f5696beca47809a9732e79e85c7e97e07a33e830eeac2f9542685a01ce +RMD160 (NetBSD-6.0/sparc/installation/netboot/rootfs.tgz) = dc7168f774cac7e9f7eba640dc55c878ab2c16db +MD5 (NetBSD-6.0/sparc/installation/netboot/rootfs.tgz) = 80ed52c842f1d4d56d4506d293e30b57 +SHA1 (NetBSD-6.0/sparc/installation/netboot/boot.net) = af35e94ca3d3ca7e07084d17c7d16370c2be1949 +SHA512 (NetBSD-6.0/sparc/installation/netboot/boot.net) = 42e02f39699d1ef5f76a2a07641f5405b74a0ce72df8c1306cdc1bf9e8e176b0857a4c6c1098a35bdaaebb729e887633bfc91cd7ed4316ff549b474e4b29932f +RMD160 (NetBSD-6.0/sparc/installation/netboot/boot.net) = 5f64296269674b5af481fa3a55d6268bafcdd50c +MD5 (NetBSD-6.0/sparc/installation/netboot/boot.net) = 9a2b02686d556555bf350f6eb35e07f1 +SHA1 (NetBSD-6.0/sparc/installation/netboot/bootjs.net) = 9bba50438d03cdef774f7572e6260bf1feb544f4 +SHA512 (NetBSD-6.0/sparc/installation/netboot/bootjs.net) = afa66b734ea6f3f9551680c5dc1af1ce43de4b385eed1c732dbf22f676e5adf1432a2048a494932650e36667405df0160b3d1cb87d4d78b5d064dfab2d366cd0 +RMD160 (NetBSD-6.0/sparc/installation/netboot/bootjs.net) = b2cde57103124271b4b9332cb99a7b7e01db3477 +MD5 (NetBSD-6.0/sparc/installation/netboot/bootjs.net) = b6958131d22fe5ced08a41671ddfa073 +SHA1 (NetBSD-6.0/sparc/installation/tape/tapefile1.gz) = c2c368ba46549cb580707b799f4f0f88b26128de +SHA512 (NetBSD-6.0/sparc/installation/tape/tapefile1.gz) = 9fb6bef663b2fb68b9bf3591834f6e653c0b3b7f69ac8c40f2479efaa5d0641140d87623fe8eeb8a21cb0e0065ceacb57d6a5db4e1905db97f7dffa52ba8b565 +RMD160 (NetBSD-6.0/sparc/installation/tape/tapefile1.gz) = 8fbcdca0f8214901d1fec117c567cfe93865e391 +MD5 (NetBSD-6.0/sparc/installation/tape/tapefile1.gz) = 1cf0fdefa01fee95d494b3418ea4a0ea +SHA1 (NetBSD-6.0/sparc/installation/tape/tapefile2) = 98f621b007b19382a0d529f2056cd8c82feb863f +SHA512 (NetBSD-6.0/sparc/installation/tape/tapefile2) = 7131f92cd02791f6d351a8ea5d8b5fe93b643ba5975522e85bf81da8f69157ebb21f80f5696beca47809a9732e79e85c7e97e07a33e830eeac2f9542685a01ce +RMD160 (NetBSD-6.0/sparc/installation/tape/tapefile2) = dc7168f774cac7e9f7eba640dc55c878ab2c16db +MD5 (NetBSD-6.0/sparc/installation/tape/tapefile2) = 80ed52c842f1d4d56d4506d293e30b57 +SHA1 (NetBSD-6.0/sparc/INSTALL.html) = 8213ae2b753d10e3eec349c15a7cabde6ae1c3d5 +SHA512 (NetBSD-6.0/sparc/INSTALL.html) = 7a12bfc31cddfda66761861cb87fc54deb5f683863b41ff44152198ea44e9489c8cce0d4702c278e2586dd3189e5c31692a02a3f17b112bfa19f1134571ff8f9 +RMD160 (NetBSD-6.0/sparc/INSTALL.html) = 77a4274595de342e22766d8c468e2a324c26fbf5 +MD5 (NetBSD-6.0/sparc/INSTALL.html) = 80cd31d110f62b89b7b910ee0aecd7b8 +SHA1 (NetBSD-6.0/sparc/INSTALL.more) = fce351f89d2da1fb9f709bbe890892db755f56c4 +SHA512 (NetBSD-6.0/sparc/INSTALL.more) = 496bb7e73d2dda1eb01518c40ab3abc767b8fb6a8b406b07176b9e926c2f4d0e5512bfdc9c26dbfa1b3a4c5069355f6ee1bb8ad8c1d459b71011ea9034f89d17 +RMD160 (NetBSD-6.0/sparc/INSTALL.more) = 89c6de032d286741f2ddde15e4b796205a8b8511 +MD5 (NetBSD-6.0/sparc/INSTALL.more) = 308ae548170c8b1b5a9bf59f64b1df7f +SHA1 (NetBSD-6.0/sparc/INSTALL.ps) = 3e6e3cbbf8141043fce33e2245513a9683be0edd +SHA512 (NetBSD-6.0/sparc/INSTALL.ps) = 93b81d3ba2fd2e1fa3ef46360e92e247fa72b320af7b0e60ab35fd90cdd10d7bc3dfc03920b4a8b209ef95facc74e047630cdec03cabe06edde21e795e158e60 +RMD160 (NetBSD-6.0/sparc/INSTALL.ps) = 8d4373a814dc88c7865b14a59e27731783e711e5 +MD5 (NetBSD-6.0/sparc/INSTALL.ps) = ecde0171eda632b616139caf04081ec4 +SHA1 (NetBSD-6.0/sparc/INSTALL.txt) = 556744433939c09c3ef5ee3e9b12c1570ebb1211 +SHA512 (NetBSD-6.0/sparc/INSTALL.txt) = 1686bb5982301002cb580022760f12fe9160a4fe826d7e0fe74cc4a480c891d31099d5219678b0768c0fbc04be329f0f40511d739c201a5e43367b5a27e72545 +RMD160 (NetBSD-6.0/sparc/INSTALL.txt) = cbc495189f2ce52328d87a1a73dc8452ad23e723 +MD5 (NetBSD-6.0/sparc/INSTALL.txt) = 17100faaf077e73c2549484e7623550f +SHA1 (NetBSD-6.0/sparc64/binary/kernel/netbsd-INSTALL.symbols.gz) = b76da4e7c7cdcdbebd2148ee815c24554b0c4bee +SHA512 (NetBSD-6.0/sparc64/binary/kernel/netbsd-INSTALL.symbols.gz) = f31c311444a309674e2718baab015b47c0139523e7996a29ab8d3e97a941b5d74be8765571bf3239375c979fff1e963d32d2dbae19ad5c7dedcbd79a8827575f +RMD160 (NetBSD-6.0/sparc64/binary/kernel/netbsd-INSTALL.symbols.gz) = 95a34099fb1159f17619713ae37d3c6337b479c5 +MD5 (NetBSD-6.0/sparc64/binary/kernel/netbsd-INSTALL.symbols.gz) = ab2e1333f6d957074854ea8f92320442 +SHA1 (NetBSD-6.0/sparc64/binary/kernel/netbsd-GENERIC.UP.gz) = 961388f6e1c9522c0d8f19f0a471f14d3c35fef7 +SHA512 (NetBSD-6.0/sparc64/binary/kernel/netbsd-GENERIC.UP.gz) = 7b3fc655414c6c2334e46315eb91ee562b94400f5729e0a33dcc9e9a79c431b4b5e0c124541b9666731740ce365c034718671348a494c43167eb0b73966133a2 +RMD160 (NetBSD-6.0/sparc64/binary/kernel/netbsd-GENERIC.UP.gz) = e02a398cd00c0b8ab7bc3b6dbd52e767b18e3275 +MD5 (NetBSD-6.0/sparc64/binary/kernel/netbsd-GENERIC.UP.gz) = 200fd2ad96dfa6ec886585e20d4b4b06 +SHA1 (NetBSD-6.0/sparc64/binary/kernel/netbsd-GENERIC.gz) = bf5fe38aaa01c9b2e9963b540f1550562789da22 +SHA512 (NetBSD-6.0/sparc64/binary/kernel/netbsd-GENERIC.gz) = c2b63ce56ff32ddaa96642ae15a33143a245b9239560c86e51e78db333d8bfd19e761d6cbe27ce69647a62fa4c76317670f0d22aa491a2cadf45dae18573511f +RMD160 (NetBSD-6.0/sparc64/binary/kernel/netbsd-GENERIC.gz) = 65f66c6c7f87e3be728339a1b294b4240b14b953 +MD5 (NetBSD-6.0/sparc64/binary/kernel/netbsd-GENERIC.gz) = 44d6f63922847e6f53d78f10bc776e3d +SHA1 (NetBSD-6.0/sparc64/binary/kernel/netbsd-INSTALL.gz) = 1fe47cdf745a00c31a47faf1155eb0f9af2ec4fc +SHA512 (NetBSD-6.0/sparc64/binary/kernel/netbsd-INSTALL.gz) = 7a10dbbdcfdcad97fec4ef476e9b6c876a3bb80b78fb4634e3f502b043b392faaf457b90ff572cc9fcf35c8c26fc908fe035b5859ed66ea2f0db490d2638f9a4 +RMD160 (NetBSD-6.0/sparc64/binary/kernel/netbsd-INSTALL.gz) = 06d3a86dbdb12e0b810888233ed79bc735ab13c7 +MD5 (NetBSD-6.0/sparc64/binary/kernel/netbsd-INSTALL.gz) = 203f7a8aad11cea65388e14dec6a65f9 +SHA1 (NetBSD-6.0/sparc64/binary/sets/man.tgz) = 899b9d8242e983a5110ab755651c24f709b5af67 +SHA512 (NetBSD-6.0/sparc64/binary/sets/man.tgz) = 410999db110d710f4bb498c3d7ae7adc62170c7c2f470ce189c92f6c436c5ea96149659c631ef0b5605caaa025d97dfe1c07c428d86f51239657bd6b71717b15 +RMD160 (NetBSD-6.0/sparc64/binary/sets/man.tgz) = c1270f68c6d41b351877f71f0396ac34877dfc8d +MD5 (NetBSD-6.0/sparc64/binary/sets/man.tgz) = df4db2bbfa39ef6a4a215d949653d04a +SHA1 (NetBSD-6.0/sparc64/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/sparc64/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/sparc64/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/sparc64/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/sparc64/binary/sets/kern-GENERIC.UP.tgz) = 643e8b15fb356856d93258e6c5d05cb14eb7d569 +SHA512 (NetBSD-6.0/sparc64/binary/sets/kern-GENERIC.UP.tgz) = 26c4eb3392f80d4ba7c28038f548e59a04a84742962da3340fb49d09ef42b2e3debc1387710b3c4baa6c735370b5daaa23a6f4da91f1be6552ae4c0cd314f4de +RMD160 (NetBSD-6.0/sparc64/binary/sets/kern-GENERIC.UP.tgz) = 37e5fdfd623c179edfa002163e005518b26fab7d +MD5 (NetBSD-6.0/sparc64/binary/sets/kern-GENERIC.UP.tgz) = 70d61e4a2588eb3242e66d0cd4cf1b1e +SHA1 (NetBSD-6.0/sparc64/binary/sets/base.tgz) = cdce0eb09c71244d8362eb4e09c0bdbd92fb4900 +SHA512 (NetBSD-6.0/sparc64/binary/sets/base.tgz) = 455fa6b72e5735a13b3106260b7cb5cabeefd3ca83603dd9daf3805a0abe55acc6b484ad8b4875590e5d949c35b8476cec136f79f8ecfcd7b12cbeee44d6f305 +RMD160 (NetBSD-6.0/sparc64/binary/sets/base.tgz) = 13508c9d394104d0c0b460a895f796e091ca8635 +MD5 (NetBSD-6.0/sparc64/binary/sets/base.tgz) = cdafa4124cc784a56444f96fb24a7a34 +SHA1 (NetBSD-6.0/sparc64/binary/sets/comp.tgz) = 71040515074d030a65e0200afe6dbd6955251af6 +SHA512 (NetBSD-6.0/sparc64/binary/sets/comp.tgz) = 52a075300885b0d15ac960430ac3ed1ecb4434cd0bb2de216c6d8c27239011544628ad1ccd87076ac9d40d64e0c088cc2ce0e928902f80629cea11631f30e35c +RMD160 (NetBSD-6.0/sparc64/binary/sets/comp.tgz) = 96bd6b8b5758360970d9d5b703019bf660aa56d5 +MD5 (NetBSD-6.0/sparc64/binary/sets/comp.tgz) = be2c961313f29bb9c0282516867850d2 +SHA1 (NetBSD-6.0/sparc64/binary/sets/etc.tgz) = e3bae514025003988d5de6ffcc14e130ee8da818 +SHA512 (NetBSD-6.0/sparc64/binary/sets/etc.tgz) = 2e5d76dc66495eb24d8abd5eed70cb05cfef3190e81875f0d6e6da67af962b0de0062bc4e9758859647ebc5d4334bd9bc28a20508f8ddecc7c183de8174a4ed4 +RMD160 (NetBSD-6.0/sparc64/binary/sets/etc.tgz) = 3fe88c6bd07952ad383d6ab1dbb7d6c3d5315b4a +MD5 (NetBSD-6.0/sparc64/binary/sets/etc.tgz) = 810c7b6940fd2e8049abf4318577f5fa +SHA1 (NetBSD-6.0/sparc64/binary/sets/games.tgz) = a40f5681634cff38215edeb22795d4e5f3f35324 +SHA512 (NetBSD-6.0/sparc64/binary/sets/games.tgz) = ff66f16eea28f3191abed7466b21d1c1969f0556cb5a9a61e5167bb7a2c4e55ed8682222a389a04d44306b39b424be25623cf8bcd41c97139960ee48ba91199d +RMD160 (NetBSD-6.0/sparc64/binary/sets/games.tgz) = c3cc1abe005bc98e0afebadc87f0181ba1fd8d6d +MD5 (NetBSD-6.0/sparc64/binary/sets/games.tgz) = a70797dbec20b831d406952468b8376a +SHA1 (NetBSD-6.0/sparc64/binary/sets/kern-GENERIC.tgz) = c047c462dd890c992df60d0f23657638875f90c2 +SHA512 (NetBSD-6.0/sparc64/binary/sets/kern-GENERIC.tgz) = 79ca275266c148fa3db47ac564e8f764c75b80a8243a0a32bbd3cd3392621b47733afdedf64f3a2103a99c03ee2f63494d892260951b85949e1383d3bf8c5673 +RMD160 (NetBSD-6.0/sparc64/binary/sets/kern-GENERIC.tgz) = c0b40543a2674c1db7d554e9ad19f8e289683de8 +MD5 (NetBSD-6.0/sparc64/binary/sets/kern-GENERIC.tgz) = a9346477bd0ae3d50b4b82f8f8da8531 +SHA1 (NetBSD-6.0/sparc64/binary/sets/modules.tgz) = c24c622359c9e5f8a05c03adb30e56c8a9862abd +SHA512 (NetBSD-6.0/sparc64/binary/sets/modules.tgz) = f2f834fded5c1142611bd5ff4ebcec67db75f620256fb27689e4cc626785a1bdf90235965e2fc4f2ee7c0ba574e73063e7f13d7f85d291dd23395074517abb9d +RMD160 (NetBSD-6.0/sparc64/binary/sets/modules.tgz) = 6a1b6845fc699f9837a88fc3c18585162a7a0aaa +MD5 (NetBSD-6.0/sparc64/binary/sets/modules.tgz) = e8588a8eed7bb775dfb236cfc8c458d4 +SHA1 (NetBSD-6.0/sparc64/binary/sets/tests.tgz) = 1103500cca9a6dcabfafd50046f15e035a1d0914 +SHA512 (NetBSD-6.0/sparc64/binary/sets/tests.tgz) = cc628d649f4d16af2300baf5edbf075bc43c91b027c19dcd59b6f1be0ff1b02a3f8f97eb88db2f2bcfa93f69ef02653021f416c546dcdb0f0aa5bf4726257f79 +RMD160 (NetBSD-6.0/sparc64/binary/sets/tests.tgz) = ce47518fd68d02d821bb4b4060ea3a775f64e37e +MD5 (NetBSD-6.0/sparc64/binary/sets/tests.tgz) = 2444ea500f4f8363d339a5eb58b50e27 +SHA1 (NetBSD-6.0/sparc64/binary/sets/text.tgz) = 09bdcb54fb74d5ae4e43b5b74a6a35467e385e09 +SHA512 (NetBSD-6.0/sparc64/binary/sets/text.tgz) = 82834b26dc0a102bdb5da4744fe2677fb50a6018b34a656d7f0813919bfe66168e37b5b47ad027ee6912fb77cceaa5a1cc33eef8269eb6a8a9f42368d01b3037 +RMD160 (NetBSD-6.0/sparc64/binary/sets/text.tgz) = 376a9a61492aed41b486fa58060edcb472152739 +MD5 (NetBSD-6.0/sparc64/binary/sets/text.tgz) = 69cce7d6bb4cb104cc27f75f17da32e2 +SHA1 (NetBSD-6.0/sparc64/binary/sets/xbase.tgz) = 865d8aa735ba57980974089ee2e44d79c69cd036 +SHA512 (NetBSD-6.0/sparc64/binary/sets/xbase.tgz) = 2b7f8d15caf6a2b831bdba3e8a2d4f78633f3350d0fc93f107c35cba746c1423c966313224422832484166e384a54b1fc2c75cba78ab138bf36e81c5468c2952 +RMD160 (NetBSD-6.0/sparc64/binary/sets/xbase.tgz) = ec680d9c70f3e6729a19167932b552a727c628a5 +MD5 (NetBSD-6.0/sparc64/binary/sets/xbase.tgz) = a1907a4afda2ea247a6b54b158ac97f3 +SHA1 (NetBSD-6.0/sparc64/binary/sets/xcomp.tgz) = c0b90da52efa86aadb3af4b7de3773c29289c65c +SHA512 (NetBSD-6.0/sparc64/binary/sets/xcomp.tgz) = d3774cc192c6ea74391dc0323db4f7e1695f290908c1ba68f885a9e670fb2c31f9a0c831a6020cd1a98e1b93691e02fadb260b26d8c6d252e9638ebf9cc0e8e5 +RMD160 (NetBSD-6.0/sparc64/binary/sets/xcomp.tgz) = 40969f50dcfbfd6948b48f819a7f84957bf14134 +MD5 (NetBSD-6.0/sparc64/binary/sets/xcomp.tgz) = 681754abde2de73609efdcbc7370dbe4 +SHA1 (NetBSD-6.0/sparc64/binary/sets/xetc.tgz) = 43c0a0b2db4bc88c509eb0d271a99e11f823babb +SHA512 (NetBSD-6.0/sparc64/binary/sets/xetc.tgz) = 4d28ba7d6db0b7c7cb005697eabd739544bae3e3128eb29b8ce62297b26b81d944d0992a6ca3522a51bb83ca874c4a5cf844e06a7aac0a6ab26b30838016faf2 +RMD160 (NetBSD-6.0/sparc64/binary/sets/xetc.tgz) = bf885030bc65c540373a06e2b4c6257a5b634b61 +MD5 (NetBSD-6.0/sparc64/binary/sets/xetc.tgz) = 006f8b77a6fb41dad2dcbf2f28efdb8f +SHA1 (NetBSD-6.0/sparc64/binary/sets/xfont.tgz) = adf52a9866ae0e4b1e871102f664dd42907d327f +SHA512 (NetBSD-6.0/sparc64/binary/sets/xfont.tgz) = a02de6961b726d4f5fc291ac48a0a59d0f991ba96fd83788e766be8591e94a64eae0fdb23262f965042348516c52a173e332b8d90b21457d9089b7478273221c +RMD160 (NetBSD-6.0/sparc64/binary/sets/xfont.tgz) = b458181e798b9b33d15ad35adfb734a0b597d042 +MD5 (NetBSD-6.0/sparc64/binary/sets/xfont.tgz) = cf37180a29cdf9bd6a34a24a8608e6bd +SHA1 (NetBSD-6.0/sparc64/binary/sets/xserver.tgz) = 6ac9cf2e66f22ee56ef1d692e9bed5ae97092088 +SHA512 (NetBSD-6.0/sparc64/binary/sets/xserver.tgz) = b6c611b3360d537e94339536354d0a5904137b519e4debab49a93a874429a115cee276f3550a6db23ec9caeb17af3ab162999d181189311a66d65f5230a3a99c +RMD160 (NetBSD-6.0/sparc64/binary/sets/xserver.tgz) = eb216c772571b79eb35e44285f8bed559eeb4fd7 +MD5 (NetBSD-6.0/sparc64/binary/sets/xserver.tgz) = e7994f53d2b295259dfb313f86d4fe4d +SHA1 (NetBSD-6.0/sparc64/installation/miniroot/miniroot.fs.gz) = dcedff4706750585b89433f833cfe99fdd454400 +SHA512 (NetBSD-6.0/sparc64/installation/miniroot/miniroot.fs.gz) = 94360d4f72150432307bd097e8fa02b18bf3d63ea095b8cecfb4de863ab367c73268116681bb94083bef6445842d4718bfdeec200f57124e95c1de8dfff96b4a +RMD160 (NetBSD-6.0/sparc64/installation/miniroot/miniroot.fs.gz) = 344981ca28094153d14b7d36321dc5e747f214cf +MD5 (NetBSD-6.0/sparc64/installation/miniroot/miniroot.fs.gz) = 8e457a7c91b800f997cdaf6a17e79bc8 +SHA1 (NetBSD-6.0/sparc64/installation/misc/boot.fs.gz) = d5afbef3f3b358e77789ea7e9f22298a77415d22 +SHA512 (NetBSD-6.0/sparc64/installation/misc/boot.fs.gz) = aba7c9613d7a34e3b939644d37b0a8fb6c27fa0a8aa208aa729499b367f76fc6d5e1a9a06a5a779748c2d2ebfdf9521ac2fcd484608bf64ee3fa0eee8b97fd5c +RMD160 (NetBSD-6.0/sparc64/installation/misc/boot.fs.gz) = bb8a8ed04649c3369dd5893897f7ea2ce7085739 +MD5 (NetBSD-6.0/sparc64/installation/misc/boot.fs.gz) = b9aef29dae0ef2a33611cd4655ff58f0 +SHA1 (NetBSD-6.0/sparc64/installation/misc/bootblk) = 9aee0c29c2eeb5c2e61aa9bfcd289e88c1fe1e97 +SHA512 (NetBSD-6.0/sparc64/installation/misc/bootblk) = 294708defc60602553eef0ae08ed910845b4c89ed72f33493c5fedad3737c9ae1cc96e947a11227e52505c62e04ad6d1f8f1f292df7e7885346acb824c4ea3fe +RMD160 (NetBSD-6.0/sparc64/installation/misc/bootblk) = 28bd7d5c0fe6f33afb9627a3e3c8950ca062afa8 +MD5 (NetBSD-6.0/sparc64/installation/misc/bootblk) = 16b4c89c82c34d5795a50c811941022c +SHA1 (NetBSD-6.0/sparc64/installation/misc/installboot) = d1cb90b57a258cef3671cc649d50aa7ea6f73f4e +SHA512 (NetBSD-6.0/sparc64/installation/misc/installboot) = bf100237898c168e020c365da754b8a659b7cbc01ab310fd9b77a2ab60982c67e5f28cfbc7cd152ec37bc9591c1d0402c850803d57a45591282f774b97da3e2e +RMD160 (NetBSD-6.0/sparc64/installation/misc/installboot) = 64f2ea944507466a6f5a61367e6190897cf00dc5 +MD5 (NetBSD-6.0/sparc64/installation/misc/installboot) = 7436c373285d89dc76dc705c3bbba5c0 +SHA1 (NetBSD-6.0/sparc64/installation/misc/instfs.tgz) = 3715a9104cdd1744835ef982a2a95525a5500c42 +SHA512 (NetBSD-6.0/sparc64/installation/misc/instfs.tgz) = 17a2112d5279ffd1a5889e55cf8e7081d564c330645f8c90082e324d413568db5bb58f8281a5b8e22d566b8699c326fa1661a0eb31d4b167874ea828a283bcc6 +RMD160 (NetBSD-6.0/sparc64/installation/misc/instfs.tgz) = 1065f4e43c679d182e72c654ce6a236f57350137 +MD5 (NetBSD-6.0/sparc64/installation/misc/instfs.tgz) = 75c25d3de06e50ff85364600e40380f4 +SHA1 (NetBSD-6.0/sparc64/installation/misc/ofwboot) = 42516022d9da6a2cd08daa28c5e60e68c6accd8b +SHA512 (NetBSD-6.0/sparc64/installation/misc/ofwboot) = 1d63340007e8aefb0f0a725f444f8cd8bd62c68045c0ba6bede194f5d5f4c05a795f728ae00b4cdf65dd82cfa163c2f954ebc2a8caa54b35a908a337f1cac736 +RMD160 (NetBSD-6.0/sparc64/installation/misc/ofwboot) = 53bf739509e7c3fe2f4ef8cad8aecec6fed9fd1e +MD5 (NetBSD-6.0/sparc64/installation/misc/ofwboot) = dfafb8bbdf16b3219ff2b38d69dffb87 +SHA1 (NetBSD-6.0/sparc64/installation/netboot/ofwboot.net) = 42516022d9da6a2cd08daa28c5e60e68c6accd8b +SHA512 (NetBSD-6.0/sparc64/installation/netboot/ofwboot.net) = 1d63340007e8aefb0f0a725f444f8cd8bd62c68045c0ba6bede194f5d5f4c05a795f728ae00b4cdf65dd82cfa163c2f954ebc2a8caa54b35a908a337f1cac736 +RMD160 (NetBSD-6.0/sparc64/installation/netboot/ofwboot.net) = 53bf739509e7c3fe2f4ef8cad8aecec6fed9fd1e +MD5 (NetBSD-6.0/sparc64/installation/netboot/ofwboot.net) = dfafb8bbdf16b3219ff2b38d69dffb87 +SHA1 (NetBSD-6.0/sparc64/INSTALL.html) = 0422ec241b04a9456f70ae28d29c7bc2be78b7f4 +SHA512 (NetBSD-6.0/sparc64/INSTALL.html) = 15bd5a5a0362c4412c416767608ce7b9580ebe8777ad15fa529af5a2e658a250000fa4a8d9313e2f7f718bc904518943d0ef095d8f0ba50deb50997f6a447fe7 +RMD160 (NetBSD-6.0/sparc64/INSTALL.html) = d534bc86ddea48b776c562b00bf67b686b91ea9d +MD5 (NetBSD-6.0/sparc64/INSTALL.html) = 90c6044241bca2933db37134f775bf07 +SHA1 (NetBSD-6.0/sparc64/INSTALL.more) = 055a5f58c1a926fdc7d272cf573eddd0c868ef7f +SHA512 (NetBSD-6.0/sparc64/INSTALL.more) = 403ee0491131f45d867e10305a65b801f95bd8fa195bfd4e95499d63ba74851774ef14f1fcc8cbd03220f973050903279438f15cb824ae2b294ead99c7d07bcc +RMD160 (NetBSD-6.0/sparc64/INSTALL.more) = 1744bae9283a6f0e12f95e382f3bedd44bb6da14 +MD5 (NetBSD-6.0/sparc64/INSTALL.more) = c42b30d10ac37a1ac1270335414e796b +SHA1 (NetBSD-6.0/sparc64/INSTALL.ps) = 60073507d2c04d97ccd9cbbf5fc51458cfd12509 +SHA512 (NetBSD-6.0/sparc64/INSTALL.ps) = 86c33bcc6fb6ff78056914afa17cfbd8efbea1f2100569f4169ba49d1033e4a86ea3ce49d1c5932012712bdf49bd356dcbe59aea4f8271c822482722dc08c7ce +RMD160 (NetBSD-6.0/sparc64/INSTALL.ps) = 51b6801d68738b1606a65969c2ae3c3fa811310f +MD5 (NetBSD-6.0/sparc64/INSTALL.ps) = bfeb86c3637bf7b5af6fcb553b62ab1b +SHA1 (NetBSD-6.0/sparc64/INSTALL.txt) = 518f7cf7bfb65b40a409b78375c0276569ac5540 +SHA512 (NetBSD-6.0/sparc64/INSTALL.txt) = f3e1503729f62b588c53747850b7907b92d823f702ec484925d3c0173c6dd866626ef500b8b581f72d54ce4b2aa72788a5543d98c72408a5060067b832e93a88 +RMD160 (NetBSD-6.0/sparc64/INSTALL.txt) = 2716b124f107462bce88b2bc12d54d5d5aaaef81 +MD5 (NetBSD-6.0/sparc64/INSTALL.txt) = 26984ffe79eab5c070bafdc74267e26a +SHA1 (NetBSD-6.0/sun2/binary/kernel/netbsd-RAMDISK.symbols.gz) = a1a418aa1a4815cd42b51d842b61002b4acded14 +SHA512 (NetBSD-6.0/sun2/binary/kernel/netbsd-RAMDISK.symbols.gz) = 272b8dc02294eb259adca2d15a6ea1633066c7708a1d8461d5d299bc7ff5887510fd6f20f490a781813fd61e6f95eed92ef03ba3b4f846ba4ecfe6b7a1d91682 +RMD160 (NetBSD-6.0/sun2/binary/kernel/netbsd-RAMDISK.symbols.gz) = c69407e3e5bddd21575929744fd986e7795c7382 +MD5 (NetBSD-6.0/sun2/binary/kernel/netbsd-RAMDISK.symbols.gz) = c47a2dcd2bac0d4ade29e3ceba7b8b90 +SHA1 (NetBSD-6.0/sun2/binary/kernel/netbsd-DISKLESS.gz) = c6cb928563370afd5d467adbd4d24a0ac37bc8c0 +SHA512 (NetBSD-6.0/sun2/binary/kernel/netbsd-DISKLESS.gz) = e24a4feb31212693c9c77732473107dc01cbe19c4d23a3f50a7028079f669e66c5252b9d39904e4d1daab0af8ac020b993f36f027df256a008249a8879d848f9 +RMD160 (NetBSD-6.0/sun2/binary/kernel/netbsd-DISKLESS.gz) = b3bd2f4f03f92c810f3b21d3163d4fad1383a0a9 +MD5 (NetBSD-6.0/sun2/binary/kernel/netbsd-DISKLESS.gz) = 2d2987883fb76005f8b4ca0686fdb261 +SHA1 (NetBSD-6.0/sun2/binary/kernel/netbsd-FOURMEG.gz) = 83451516991b23dddcd67b3d4aed3d4d5eef0af9 +SHA512 (NetBSD-6.0/sun2/binary/kernel/netbsd-FOURMEG.gz) = 8ea5066dcd3ab85ca812a169d2a385befcf5717e1dca01c4d5a9daae2368498c1eedcb683aa76d912be0cb6193217c33a5819d8c597521a21fd9ccc5c4f84932 +RMD160 (NetBSD-6.0/sun2/binary/kernel/netbsd-FOURMEG.gz) = f8dbe58a262e48a7a1bdddfad8bcbf4c02455f93 +MD5 (NetBSD-6.0/sun2/binary/kernel/netbsd-FOURMEG.gz) = f717bd51debc97e9efb5979b5ba425e8 +SHA1 (NetBSD-6.0/sun2/binary/kernel/netbsd-GENERIC.gz) = 89a4c10827c07a9100a4cf7692012221e6f7d99d +SHA512 (NetBSD-6.0/sun2/binary/kernel/netbsd-GENERIC.gz) = f53dd3eaf33dac52acfcbd6657269783ca14c1a33ea4e0cdf47fe96f3a620961e07905d5eccc2e15ff75cb0910f9e47d8a37487c7a8b455db494b5690d9ce5cf +RMD160 (NetBSD-6.0/sun2/binary/kernel/netbsd-GENERIC.gz) = dca21703d8350ff9c84920da0fe38b4e96b58c73 +MD5 (NetBSD-6.0/sun2/binary/kernel/netbsd-GENERIC.gz) = 5be2117280d7f1f78689744e44903f49 +SHA1 (NetBSD-6.0/sun2/binary/kernel/netbsd-INSTALL.gz) = 31619c78adb4831a8ae456942ee6a31c5bc0576b +SHA512 (NetBSD-6.0/sun2/binary/kernel/netbsd-INSTALL.gz) = 08d1e00c5013bfab18920543807657eb480d54d0270d1699a9a583ac0c8fd4df0750924727ee2723c7ad6bd1c0450c5c89378c450b412ab6d6e6c8be723f2b86 +RMD160 (NetBSD-6.0/sun2/binary/kernel/netbsd-INSTALL.gz) = 3d651236509dbd65a585082b2adffa0abd47c298 +MD5 (NetBSD-6.0/sun2/binary/kernel/netbsd-INSTALL.gz) = d39784e7514b56ad37120e1accca74e9 +SHA1 (NetBSD-6.0/sun2/binary/kernel/netbsd-RAMDISK.gz) = abe6ff67ad153c993974749b41bbf6b2e207792a +SHA512 (NetBSD-6.0/sun2/binary/kernel/netbsd-RAMDISK.gz) = 63fcbf6f7b5582b69aa77b4dcfed2125f32b40a622b2eb533eefd92bf829513488e37c4947c44e004ec8006a7e35030fb3e500f1584922101d376e9cc67dc8aa +RMD160 (NetBSD-6.0/sun2/binary/kernel/netbsd-RAMDISK.gz) = aa2ba7c4930e6f557f809407458f12a5fe2da818 +MD5 (NetBSD-6.0/sun2/binary/kernel/netbsd-RAMDISK.gz) = 10a7099f6bfc84a63eb89985f93dfab6 +SHA1 (NetBSD-6.0/sun2/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/sun2/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/sun2/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/sun2/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/sun2/binary/sets/kern-DISKLESS.tgz) = a6ddacc5894ed442e82fc8ad75e4ba5a85acbdd0 +SHA512 (NetBSD-6.0/sun2/binary/sets/kern-DISKLESS.tgz) = 7b0afaf8fcafd005d56142659c130fa14fed8681f0907c262b52ba367db985390c1ada5b3c22705655fb8fdbdb2577f112b2e867dae8a47d30da17db9f68dca1 +RMD160 (NetBSD-6.0/sun2/binary/sets/kern-DISKLESS.tgz) = b1566d3099e8654a48e74a7f4b959d22ce72241a +MD5 (NetBSD-6.0/sun2/binary/sets/kern-DISKLESS.tgz) = 320ebbbe9568d045ad4dc2f4284e45e5 +SHA1 (NetBSD-6.0/sun2/binary/sets/base.tgz) = cdfdfc1f6d5fd3fab1cd9e5546d1060a4cb16b45 +SHA512 (NetBSD-6.0/sun2/binary/sets/base.tgz) = d7a0059ea7babe24d603084826c5a338b33ef3ac4ce1a6039f926692141f28e32d654656a85e995aa000742f8971b33d3e4fad8dbee8a9e6b3cac2c15b9cf01d +RMD160 (NetBSD-6.0/sun2/binary/sets/base.tgz) = 3652a11470a78517f725320750e8a61c5328510f +MD5 (NetBSD-6.0/sun2/binary/sets/base.tgz) = 3505f44ff71277ff11e5402646e110ef +SHA1 (NetBSD-6.0/sun2/binary/sets/comp.tgz) = 40c4eb1b75f3e903a92ea86d8919fd23a56e470d +SHA512 (NetBSD-6.0/sun2/binary/sets/comp.tgz) = a52435520af63ae741654d81bdd5abd611857aaa19dc757bce5c841fa13b15d878780509be22a31ed893a2a4ca1c29548c5a737a2a650a7241805b518f9c70ac +RMD160 (NetBSD-6.0/sun2/binary/sets/comp.tgz) = d51f8b1dbebe3ba6c4c3623351e647981b20f9da +MD5 (NetBSD-6.0/sun2/binary/sets/comp.tgz) = cfdfa248cfcb4e2ae4af64f3f8a4eddf +SHA1 (NetBSD-6.0/sun2/binary/sets/etc.tgz) = 5872a9f5eeb6004802bba9df4a0d4ec1dfccea8d +SHA512 (NetBSD-6.0/sun2/binary/sets/etc.tgz) = 617be23175e9c578e834e039720a0c23357cd24b22639c5641a54c5b36ccb725446cda8e3c3def6e8e73c39c1f90065c348a0ea990f7a50384ba9a65ada10e16 +RMD160 (NetBSD-6.0/sun2/binary/sets/etc.tgz) = fa533eae2fafa51d8e2643dbe20be6ac179f5d05 +MD5 (NetBSD-6.0/sun2/binary/sets/etc.tgz) = ea43e005a9a50dcbbf704fa27745eb78 +SHA1 (NetBSD-6.0/sun2/binary/sets/games.tgz) = 97fe1f17370ab456fea7c21c66dabbaefbb8bf39 +SHA512 (NetBSD-6.0/sun2/binary/sets/games.tgz) = 2dfb36fb06f40d0ce519fe3808d53b8babd8bc9ae810c4fadb09e84e93e57b88b893c04cecbaf062c4ed2257eacec30127513aaca5c91ef9234da9226f366c4f +RMD160 (NetBSD-6.0/sun2/binary/sets/games.tgz) = 6affdde9886085d8acd3bef196096dbff77fd99f +MD5 (NetBSD-6.0/sun2/binary/sets/games.tgz) = 7eeaf3572032c8e522266e0283594105 +SHA1 (NetBSD-6.0/sun2/binary/sets/kern-FOURMEG.tgz) = 81e4d6b63aa15ea1f60604aa24a21d0eb4ddedf0 +SHA512 (NetBSD-6.0/sun2/binary/sets/kern-FOURMEG.tgz) = 117485cb1d871f3e643c009a998998885011c1d2d826ec2db092d0e3569a21fc63618a73a803332fdd936ecb30738e76f75be3e76ee17d71b190a8bb188aa873 +RMD160 (NetBSD-6.0/sun2/binary/sets/kern-FOURMEG.tgz) = 3c7e6d14f1a2a9b288f245ad0d6f115469b060c2 +MD5 (NetBSD-6.0/sun2/binary/sets/kern-FOURMEG.tgz) = f9ac31754f27f2e22aff03c5ce4e166d +SHA1 (NetBSD-6.0/sun2/binary/sets/kern-GENERIC.tgz) = 05b5ac2735fe34a61df42c13670bf7a758b8c37a +SHA512 (NetBSD-6.0/sun2/binary/sets/kern-GENERIC.tgz) = d5273855067665e77291f477adc2bcf482db2ac749b078502d04bc53b103977f4f16da05acbe917a97d4bba20626dd1954132939cfcf168cf8b75f5e12fe71b6 +RMD160 (NetBSD-6.0/sun2/binary/sets/kern-GENERIC.tgz) = bf5c45b36a68224af25aca91aa2eac8d213442c9 +MD5 (NetBSD-6.0/sun2/binary/sets/kern-GENERIC.tgz) = baac1013c64948cd3fb2bff22a21e5c4 +SHA1 (NetBSD-6.0/sun2/binary/sets/man.tgz) = 9bb0fc4bb2f60df3acbdcbd6d03d11e52227c70f +SHA512 (NetBSD-6.0/sun2/binary/sets/man.tgz) = 3bdb75b91c18982b39f2c2842d9260749491f16c6da624510c603ef0e897298f6ecd620a63a96ccf21354f6a4008b4723249635280e4e956a4668d1984faf7f5 +RMD160 (NetBSD-6.0/sun2/binary/sets/man.tgz) = 3b28f01096b5070887994e84b171cd6c59f0ad94 +MD5 (NetBSD-6.0/sun2/binary/sets/man.tgz) = 06cfb9c81392e3ae7b04daa01475db38 +SHA1 (NetBSD-6.0/sun2/binary/sets/modules.tgz) = 0ff7c443e874d15372f107b6772b5004ee0ff6d2 +SHA512 (NetBSD-6.0/sun2/binary/sets/modules.tgz) = ad3913a8edf4494515dab3a4df4a56799f7cb2cf335ca9e4cf78e61a8b92f161cf2148ea2201ce9e9a6966872c5ee749b69642205ef4fa475aae1b3671e49d69 +RMD160 (NetBSD-6.0/sun2/binary/sets/modules.tgz) = ecbeaeb92cd60504c907b743ebf8bc729483eb35 +MD5 (NetBSD-6.0/sun2/binary/sets/modules.tgz) = 94f595d3a8f52f8b7b202c1715896b1e +SHA1 (NetBSD-6.0/sun2/binary/sets/tests.tgz) = 4651980ab126f0fb7fa3282e401fed649129dd46 +SHA512 (NetBSD-6.0/sun2/binary/sets/tests.tgz) = 4fcec0fde688d32f2f53d0c3d6ec9218a2c670f0006b421ab907098f7210481d0ef690d9e8415dd5201be799f83b303a8a2a5b4f8b35af16b311b4996a353b93 +RMD160 (NetBSD-6.0/sun2/binary/sets/tests.tgz) = d260affd3d3656aa73171aca7e8f40f2f502a645 +MD5 (NetBSD-6.0/sun2/binary/sets/tests.tgz) = 801c9c531d070d152c1f259dd1111f64 +SHA1 (NetBSD-6.0/sun2/binary/sets/text.tgz) = b76b4bc516bd7a1747415f9bdbd6af7370cded48 +SHA512 (NetBSD-6.0/sun2/binary/sets/text.tgz) = 5654c7217b9d02e327c7803de1dc67d5df4225d1399c3c0a433728fb2fc124ddf0fb2e8cc89d304e03a7c1104a1e1b6ff665b5b29825e3afb0acb43f37fa327a +RMD160 (NetBSD-6.0/sun2/binary/sets/text.tgz) = 89f288a449a1049aabef74f6033bf00611123bf7 +MD5 (NetBSD-6.0/sun2/binary/sets/text.tgz) = bc500c71253fd2e2b3bb1dac2bf2b738 +SHA1 (NetBSD-6.0/sun2/installation/miniroot/miniroot.fs.gz) = 74ae5c6fe766a40a9bf149885809186bdaae96ff +SHA512 (NetBSD-6.0/sun2/installation/miniroot/miniroot.fs.gz) = 4c7ab73a13c13b3b4cd7a01e12ca25d7a385691dee2b830fb94885c9eece4e62c45cdb9e3961b5426f0e979b2e0f2e951c52774231129f824787ee6daa8d8ed1 +RMD160 (NetBSD-6.0/sun2/installation/miniroot/miniroot.fs.gz) = 032b6ddf1452800c8f824983c6d3c1310ba723dc +MD5 (NetBSD-6.0/sun2/installation/miniroot/miniroot.fs.gz) = 6d2927b0648b018b2726f7159e60a911 +SHA1 (NetBSD-6.0/sun2/installation/netboot/bootyy) = f97ac30d2c6258791d64d408e295cc2f48e7892b +SHA512 (NetBSD-6.0/sun2/installation/netboot/bootyy) = c0aa6a81071323564d4445ae06b9e0629b32b118bf6c516e28109d3c2d7a72613b8a2005b6f968a43acc6115e3edba57f15c314b77a774cfbb977ff668dd946b +RMD160 (NetBSD-6.0/sun2/installation/netboot/bootyy) = 3de2112b92a222b55ffeff2d5930ed5eccf70a7a +MD5 (NetBSD-6.0/sun2/installation/netboot/bootyy) = 7a6fce60607e791e1c40186b0b7a5403 +SHA1 (NetBSD-6.0/sun2/installation/netboot/netboot) = f0ab4e961148d2d8885a47a4fd1b2bc1350e4978 +SHA512 (NetBSD-6.0/sun2/installation/netboot/netboot) = b462fb05ea093921b40a1042c15b0013a848c7b022f22523e3dfe73e0141b35982d26825812604bbfcb735f8851fafe9709979d90fb1db21ee552f0e93db6a86 +RMD160 (NetBSD-6.0/sun2/installation/netboot/netboot) = c7c6416042d8ed641a8ed033541a7757492229ba +MD5 (NetBSD-6.0/sun2/installation/netboot/netboot) = 52d961060a7035f07cb1946d71736289 +SHA1 (NetBSD-6.0/sun2/installation/tapeimage/MakeBootTape) = 1c24969b0bded7ed9bed7203e9c577d896d25566 +SHA512 (NetBSD-6.0/sun2/installation/tapeimage/MakeBootTape) = 33eeb495736ac60dabd87faf803defa85f2e400f49b1b4078c16aff18404673a7e668676dc90eb92dc597835ccac8abe26fb68ecb22ddc5afd5afd7de8f2d680 +RMD160 (NetBSD-6.0/sun2/installation/tapeimage/MakeBootTape) = 234492df364f78e2aef3c9cd8ac4496077ba2760 +MD5 (NetBSD-6.0/sun2/installation/tapeimage/MakeBootTape) = 924860ba84acf16d29a70783d6e106a3 +SHA1 (NetBSD-6.0/sun2/installation/tapeimage/MakeInstTape) = 75b8d9faa2e1960a48354922aef5c25c76f66ee6 +SHA512 (NetBSD-6.0/sun2/installation/tapeimage/MakeInstTape) = ba61feb33064bdb843f8cd563135cc8fe28e9bbbaf8d1ac2eba2c5e1ad083daba83b47295f3c677caa014c9be7606ef6a40a6c1bc9b07e4eaed139d8299be97d +RMD160 (NetBSD-6.0/sun2/installation/tapeimage/MakeInstTape) = 198879d5058f7ee226c4c669f3a7429bb49c12ce +MD5 (NetBSD-6.0/sun2/installation/tapeimage/MakeInstTape) = 58a95592c402c3f752f4c801fa3d20a7 +SHA1 (NetBSD-6.0/sun2/installation/tapeimage/tapeboot) = 1612942dd5bbca5773de6ac02723ea898ea4e172 +SHA512 (NetBSD-6.0/sun2/installation/tapeimage/tapeboot) = c5b75882d4b9041edfd74cbf9dc4df8393e687503043e77af766452d780cc8a5584b916d0a792748730e9c87bd52803bbfc0a043720e611079a5cdcce6243bff +RMD160 (NetBSD-6.0/sun2/installation/tapeimage/tapeboot) = 61a36a8d1737147b7b4587353f974c87fca2b442 +MD5 (NetBSD-6.0/sun2/installation/tapeimage/tapeboot) = 751ee54f544a63177c273ea6757dbdc0 +SHA1 (NetBSD-6.0/sun2/INSTALL.html) = 40cf15ad864adcc8d6216b9d4220cc3eab1463ff +SHA512 (NetBSD-6.0/sun2/INSTALL.html) = 0992031a6cae198c16b08553e94277a39b34886cf0bfea343b95493439d79868cd50a1c2b9f2ce9852068b43beb7ee2a2016480c3ea452b9d62a25b71c72d567 +RMD160 (NetBSD-6.0/sun2/INSTALL.html) = f7aaba481555931612488d204c9a256899f04efb +MD5 (NetBSD-6.0/sun2/INSTALL.html) = ccf725a8f39711748946cc414f688dde +SHA1 (NetBSD-6.0/sun2/INSTALL.more) = 21b6ecc61f6d15fd2b54511150b840b242996f02 +SHA512 (NetBSD-6.0/sun2/INSTALL.more) = 5c43f22fe85470c7069ea524ff18570a1a3605a956157d9f662cf8b76fa6f52e4eef41e765488ae00b491830cde3b148254ed5bec6b20db0f5661d29ff0f7fce +RMD160 (NetBSD-6.0/sun2/INSTALL.more) = 9adc2008a6388ec7ce907c23ac6f1de1f941c979 +MD5 (NetBSD-6.0/sun2/INSTALL.more) = 79afb0a5f30435a2731e455a85884a28 +SHA1 (NetBSD-6.0/sun2/INSTALL.ps) = 37c7ffa52cf698e058442a61d937a0ad09fa0156 +SHA512 (NetBSD-6.0/sun2/INSTALL.ps) = 09998f504688d7144d223f857edd4273bf00c1c50b1ec47294db2be1abdc050cbf73d0037c0b88279fb1028fde2556bbcadc2d4fbb7466834385905c46f3d688 +RMD160 (NetBSD-6.0/sun2/INSTALL.ps) = cac0f152af9ddd8fd643b2578688e7db03a3deb5 +MD5 (NetBSD-6.0/sun2/INSTALL.ps) = b2a094aacd3846aa4c121629daa938fb +SHA1 (NetBSD-6.0/sun2/INSTALL.txt) = 90377374ac7c61d0fb6bafdaecd790a86fe7a447 +SHA512 (NetBSD-6.0/sun2/INSTALL.txt) = c37c159387cdfa0f40268a16c5a55cef0473b31f51e5c978ec948fe4964d3e9574dd9bbbd758eccb9304a9af6d8216b38aa256676a36537b480a5606b2cb1fde +RMD160 (NetBSD-6.0/sun2/INSTALL.txt) = b16dee40608a6b8e8022df13c27783e34e48279f +MD5 (NetBSD-6.0/sun2/INSTALL.txt) = b33826d2ef20420c36a3723256cd4488 +SHA1 (NetBSD-6.0/sun3/binary/kernel/netbsd-DISKLESS3X.gz) = 08ec51564fa19e69828a501a60ac05c687f8471f +SHA512 (NetBSD-6.0/sun3/binary/kernel/netbsd-DISKLESS3X.gz) = d31891f04947a6295085ee899ccb5d532b5e50eb66d1c4f7f7779aae9a1c711b54e142c1d26f45ce10f6ef6815894fe545b436d40cc0ba05149e02885981f029 +RMD160 (NetBSD-6.0/sun3/binary/kernel/netbsd-DISKLESS3X.gz) = a71a82ee59a431dd5c7a6d5100d84fd264ca4e4c +MD5 (NetBSD-6.0/sun3/binary/kernel/netbsd-DISKLESS3X.gz) = 261995193793314b7306c5753aed0e23 +SHA1 (NetBSD-6.0/sun3/binary/kernel/netbsd-DISKLESS.gz) = 941fbb0e064253228f04d4baaa8e2db4a09b8d88 +SHA512 (NetBSD-6.0/sun3/binary/kernel/netbsd-DISKLESS.gz) = 2013168c4985c258bd2f605cda56dd678c394580edf2afa1fb37fd243b748b4d50e049a2f4b314ee5b70f30d181ec684d886094258115a0cdf0e485c120a2628 +RMD160 (NetBSD-6.0/sun3/binary/kernel/netbsd-DISKLESS.gz) = 6028696adecea1922e0bdb1d757a4d70725c3639 +MD5 (NetBSD-6.0/sun3/binary/kernel/netbsd-DISKLESS.gz) = a49e05dd12628e1fcf1a30e8815ea72e +SHA1 (NetBSD-6.0/sun3/binary/kernel/netbsd-RAMDISK.symbols.gz) = be5066fcab92b01e828769c3766ac902896a9dae +SHA512 (NetBSD-6.0/sun3/binary/kernel/netbsd-RAMDISK.symbols.gz) = cc0f0b30fa4b28c2fbaf9229568530ee61e17b9ec8515242e53d4d6ac32d1f3ace313c4d138ff173a2301e208ded7389e93551a4a05d7f9a5bf536a8566c2de2 +RMD160 (NetBSD-6.0/sun3/binary/kernel/netbsd-RAMDISK.symbols.gz) = 832199c94540e3274e2376b17e23144cf99af3c7 +MD5 (NetBSD-6.0/sun3/binary/kernel/netbsd-RAMDISK.symbols.gz) = fb76fe7920f7c1e0138270f64dd90315 +SHA1 (NetBSD-6.0/sun3/binary/kernel/netbsd-GENERIC.gz) = a1458c3d482f170ce26ff1b4ae12fcbe82206cd0 +SHA512 (NetBSD-6.0/sun3/binary/kernel/netbsd-GENERIC.gz) = 703f16ca7fb7cddbf33e84bf7859d73ad619464c859927767e6f3e292c63b7da65ed90d20a32cb7364f425c41aff05e0a08f7ba4e7bcfaa04804f4389425d402 +RMD160 (NetBSD-6.0/sun3/binary/kernel/netbsd-GENERIC.gz) = 5a542bbb7c45f6940f5c9a63deba729d2d6e8b75 +MD5 (NetBSD-6.0/sun3/binary/kernel/netbsd-GENERIC.gz) = 28729a3aab91b7b81a0bb5af1378c67c +SHA1 (NetBSD-6.0/sun3/binary/kernel/netbsd-GENERIC3X.gz) = 50f6f8937a0b18960660908aea8a5cd490175077 +SHA512 (NetBSD-6.0/sun3/binary/kernel/netbsd-GENERIC3X.gz) = 2798612a5e0d6d60f80dded7a22bdd6c1f5a64709b65fa33bfe8dfa873c38da0269b0a080185efe2025b5682ba9fd18bb3063a1133f8227cdc41acb03fc4bc2c +RMD160 (NetBSD-6.0/sun3/binary/kernel/netbsd-GENERIC3X.gz) = ecd36a3bb10a07cb7dacfd2a8add6b4e51eddcf1 +MD5 (NetBSD-6.0/sun3/binary/kernel/netbsd-GENERIC3X.gz) = 63a3954b02444ee35ebdfc8a280c6eb8 +SHA1 (NetBSD-6.0/sun3/binary/kernel/netbsd-INSTALL.gz) = 2da156899061f57aabfe77a55081e1281cc46107 +SHA512 (NetBSD-6.0/sun3/binary/kernel/netbsd-INSTALL.gz) = a316b1fb791d3df671cf366c911756cd9e87735247eda75372d73075bd8ec8bfae4aba620740f86cfe8011ffe0614777d480d4979ca021912702ce5699865244 +RMD160 (NetBSD-6.0/sun3/binary/kernel/netbsd-INSTALL.gz) = 51a1809d8ddf6701d556d858a18416a72afb0f37 +MD5 (NetBSD-6.0/sun3/binary/kernel/netbsd-INSTALL.gz) = b4a756c7502efd5883243e26139d206a +SHA1 (NetBSD-6.0/sun3/binary/kernel/netbsd-INSTALL3X.gz) = 78f041430b2aafc6768aef55603c4427f90c44ed +SHA512 (NetBSD-6.0/sun3/binary/kernel/netbsd-INSTALL3X.gz) = be3a7f26745d4693d2393f0ee044871dca2ec554f8897b7ec54bba85ff3cd75143a548fa0880bb76810d2811018c9c3b5e8cc44fbe163588b82c0344a2f0cf81 +RMD160 (NetBSD-6.0/sun3/binary/kernel/netbsd-INSTALL3X.gz) = 9d21135a1448a6fdc1fa052c56434cf809e43046 +MD5 (NetBSD-6.0/sun3/binary/kernel/netbsd-INSTALL3X.gz) = 0ff6857605eea16d5d90a85b77335229 +SHA1 (NetBSD-6.0/sun3/binary/kernel/netbsd-RAMDISK.gz) = 6f90c82aa6150d861190e41dca228549cedcc458 +SHA512 (NetBSD-6.0/sun3/binary/kernel/netbsd-RAMDISK.gz) = e4e4f5901d286b164f9e4b471f6084a6ba879c91b21b4e86f44650ccf0447698a11f33008d75cb3e12673396094d91e2d715e24b596727cb97c125340fa82abe +RMD160 (NetBSD-6.0/sun3/binary/kernel/netbsd-RAMDISK.gz) = 13e4983150a8508d64c022000d27b77c1e0da384 +MD5 (NetBSD-6.0/sun3/binary/kernel/netbsd-RAMDISK.gz) = 6ce2d84c334909c66b0d54b928fdcb2d +SHA1 (NetBSD-6.0/sun3/binary/kernel/netbsd-RAMDISK3X.symbols.gz) = 6c31ae63d1149ae040b2f04fdcce0f41aa8095af +SHA512 (NetBSD-6.0/sun3/binary/kernel/netbsd-RAMDISK3X.symbols.gz) = f986b22aef0685dbb454c95d9f0f6b7379a15b365f56f3a13e1357b8b2bf7fb787b09eb4b474d06dd78e6869152e6493177f911929f972a819f688af90854d1e +RMD160 (NetBSD-6.0/sun3/binary/kernel/netbsd-RAMDISK3X.symbols.gz) = 18640447fceaf27b7ebfd19917bf40521718c441 +MD5 (NetBSD-6.0/sun3/binary/kernel/netbsd-RAMDISK3X.symbols.gz) = 639d60631052afddcfb58f64847964c8 +SHA1 (NetBSD-6.0/sun3/binary/kernel/netbsd-RAMDISK3X.gz) = 78efb67e8cb813af99a12a1c67c9238916bb1071 +SHA512 (NetBSD-6.0/sun3/binary/kernel/netbsd-RAMDISK3X.gz) = ef27cfba56aff6b13544132e71513598e68e488cb27b7038442279eaec9d6a715cf9196ce98d93acfc4a7e89cb679e5ce787f7c4b14a661a2113b1a987861a9f +RMD160 (NetBSD-6.0/sun3/binary/kernel/netbsd-RAMDISK3X.gz) = 556c68e9415f0795d58c4f8c491eed75755a59fa +MD5 (NetBSD-6.0/sun3/binary/kernel/netbsd-RAMDISK3X.gz) = ff2a3fad6f6dd6504713e5874b3eb8cb +SHA1 (NetBSD-6.0/sun3/binary/sets/games.tgz) = 16ee93ea4d5fac2fb28fad5c32c8a3d57d011d79 +SHA512 (NetBSD-6.0/sun3/binary/sets/games.tgz) = a7f49ab72f50273f66c8dcf408b57ec4668debd5537c5bd0ec59aa0f4fa1d599ba0798d1b283315c4208cbcb608925808ce003b1ade79034886edb8208f9f48d +RMD160 (NetBSD-6.0/sun3/binary/sets/games.tgz) = 1e09d99d7fe2e495763f05919472d27a4ba699df +MD5 (NetBSD-6.0/sun3/binary/sets/games.tgz) = 8a26f3e864444209088bccf21419a616 +SHA1 (NetBSD-6.0/sun3/binary/sets/man.tgz) = 899b9d8242e983a5110ab755651c24f709b5af67 +SHA512 (NetBSD-6.0/sun3/binary/sets/man.tgz) = 410999db110d710f4bb498c3d7ae7adc62170c7c2f470ce189c92f6c436c5ea96149659c631ef0b5605caaa025d97dfe1c07c428d86f51239657bd6b71717b15 +RMD160 (NetBSD-6.0/sun3/binary/sets/man.tgz) = c1270f68c6d41b351877f71f0396ac34877dfc8d +MD5 (NetBSD-6.0/sun3/binary/sets/man.tgz) = df4db2bbfa39ef6a4a215d949653d04a +SHA1 (NetBSD-6.0/sun3/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/sun3/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/sun3/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/sun3/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/sun3/binary/sets/xcomp.tgz) = e13548b8974f5d55e98caf17b2b4bbbcf2430370 +SHA512 (NetBSD-6.0/sun3/binary/sets/xcomp.tgz) = e4b13c798df04ffef88e72100e2db5af400e5ae255cd7a1ca2907736b8138a59045b6f3bd8531b5753d0b87eadb1b5f801043a929bb25d1611e4be693c1da954 +RMD160 (NetBSD-6.0/sun3/binary/sets/xcomp.tgz) = 3b1f4e26ddd57e69afd9709553c1bf70d6e29ea0 +MD5 (NetBSD-6.0/sun3/binary/sets/xcomp.tgz) = 894bb9aa05b164d9923682165d708335 +SHA1 (NetBSD-6.0/sun3/binary/sets/xetc.tgz) = d2ca34bd668e108cbbfd4b45720823663339f8bd +SHA512 (NetBSD-6.0/sun3/binary/sets/xetc.tgz) = 431ca465f300e7eb5d4dbd44c43e412a296fb4d3129217e752f86a720e8a8bdf736c9add05a45518a4f3e6cffa32381ef61e9186d360b68a5f8c64d87e385fb5 +RMD160 (NetBSD-6.0/sun3/binary/sets/xetc.tgz) = 4c5d664679856b02b694534cd6afdf20597e6d53 +MD5 (NetBSD-6.0/sun3/binary/sets/xetc.tgz) = 72bd67556ac14ea0ce147374af0ba624 +SHA1 (NetBSD-6.0/sun3/binary/sets/xfont.tgz) = 24ca4cb77a59246b1b05e0a91fed21c63259d12b +SHA512 (NetBSD-6.0/sun3/binary/sets/xfont.tgz) = 8dc297fb6205a995767e68e77cc21169234dfb66a86bbcd2e1828fd32efeda0a25c9f2a9b1a39b97fe8d7b24f8cd5cf6160859af6be2259876f39ee4e76c405b +RMD160 (NetBSD-6.0/sun3/binary/sets/xfont.tgz) = d2f134959940e6667aca185f01e388c05dc6bc85 +MD5 (NetBSD-6.0/sun3/binary/sets/xfont.tgz) = 3c96c1f0a13cd7d277ca35622ac9c058 +SHA1 (NetBSD-6.0/sun3/binary/sets/kern-DISKLESS.tgz) = 00b387b99dc84b6128941ae2b849feb76c7f88c8 +SHA512 (NetBSD-6.0/sun3/binary/sets/kern-DISKLESS.tgz) = 0b2cf325d14f69c5905bd6d832adfdc806bec302780811c6ad50ecbb646de07d1e91dd0cf16873b0128a44688f9e810d83ae7c6a4415b8393ea0567fe77d5f32 +RMD160 (NetBSD-6.0/sun3/binary/sets/kern-DISKLESS.tgz) = 71913a5ec9bab31e74ff27ab154715fd84b34a96 +MD5 (NetBSD-6.0/sun3/binary/sets/kern-DISKLESS.tgz) = 6988897d69e304577b9f493c44425ddb +SHA1 (NetBSD-6.0/sun3/binary/sets/base.tgz) = 43ba28352421316629ca0c4a93709af5e5b588cd +SHA512 (NetBSD-6.0/sun3/binary/sets/base.tgz) = 1b0efd643066d4cc5d689a64ba97092091ac8b94ac5244ca7955b27aa6ce60eaec0f020390d9ed60c00f894312fce76d1ca0555ac4626a4c5c140beb57b97ba4 +RMD160 (NetBSD-6.0/sun3/binary/sets/base.tgz) = 46456971e8d821c310f3ac304fcda320396916be +MD5 (NetBSD-6.0/sun3/binary/sets/base.tgz) = ed8d7947e7e5282728b94a7fbae41ea3 +SHA1 (NetBSD-6.0/sun3/binary/sets/comp.tgz) = 960167513f2de6e53e0512ba9d8a8fa891d7f096 +SHA512 (NetBSD-6.0/sun3/binary/sets/comp.tgz) = a6d2d94ad9a752263254736253c7be190d2baa69140ca1e40c06719dfb89dd5660fa83c72392b2c5b30c0caee058cb049029b8414fdd48017fba2615781dc08b +RMD160 (NetBSD-6.0/sun3/binary/sets/comp.tgz) = 9d995295dc5806397c31541ccd589210c0f675b2 +MD5 (NetBSD-6.0/sun3/binary/sets/comp.tgz) = 3f277a5219ca41a91776606698660e31 +SHA1 (NetBSD-6.0/sun3/binary/sets/etc.tgz) = be0c7f05a0122f7fa7e2bf1cf643080c5b434c1b +SHA512 (NetBSD-6.0/sun3/binary/sets/etc.tgz) = 64d9a05110471e97c99c53479a14ba17dedd7c42f1471e26e2b8e73770d94a27b77ca12ab6cc014f8c131fb6757a26a565d4b8c71e78cab8dbbd21608fa76c33 +RMD160 (NetBSD-6.0/sun3/binary/sets/etc.tgz) = c4c29b032978e5a6f803c353d4d5b5ab4c58985d +MD5 (NetBSD-6.0/sun3/binary/sets/etc.tgz) = 68851b8898496b07817e828fee991233 +SHA1 (NetBSD-6.0/sun3/binary/sets/kern-DISKLESS3X.tgz) = a63f54a0db8362478ef1f3fbbc18060e3834723a +SHA512 (NetBSD-6.0/sun3/binary/sets/kern-DISKLESS3X.tgz) = 5ff8b7a463fc5e0edd17f47d2c59a01f9c53f23db8e73ba7bb0e67c73cd84d2688a22aa8e6b56bdccc29a0056fafeb6c984ea6a34a01e454a93d62eb2c54b623 +RMD160 (NetBSD-6.0/sun3/binary/sets/kern-DISKLESS3X.tgz) = 6ff482b8e336432022ac05a24c376d746fe7f8e8 +MD5 (NetBSD-6.0/sun3/binary/sets/kern-DISKLESS3X.tgz) = 1f49b690f568492ba1d2ff5cfd76ec6c +SHA1 (NetBSD-6.0/sun3/binary/sets/kern-GENERIC.tgz) = 9eb75c58a99f7b046dab7888235bf8162b10834c +SHA512 (NetBSD-6.0/sun3/binary/sets/kern-GENERIC.tgz) = 9cdcf4835398df2124cc418b977f1cdffaa87d4edaff2c61ded06b44cbd5aa656743e74abd4b5ccd5f7232e0890f4786523d4438feed288bf77df1482fbbb9fd +RMD160 (NetBSD-6.0/sun3/binary/sets/kern-GENERIC.tgz) = 8a50ed11d968a35170c50ddfcd51c3cfeaa7dfc0 +MD5 (NetBSD-6.0/sun3/binary/sets/kern-GENERIC.tgz) = 510f2e6a9de0cd18e8dfc6cce74964d2 +SHA1 (NetBSD-6.0/sun3/binary/sets/kern-GENERIC3X.tgz) = fc31315a9d236278dc8b6dda1e1385680e35eb4c +SHA512 (NetBSD-6.0/sun3/binary/sets/kern-GENERIC3X.tgz) = 9de034f2f6ee9cf0c65ba4fc41bf7147205c9918263131957d8555c7d54997d98dead2108ec2fac89805d371e673bd66abb93715b61f3c7a71c9db8caf761c40 +RMD160 (NetBSD-6.0/sun3/binary/sets/kern-GENERIC3X.tgz) = d1b03f8e7188324e362e4fbd7764d4218a3a98d4 +MD5 (NetBSD-6.0/sun3/binary/sets/kern-GENERIC3X.tgz) = b8b84407a1e0d4e215a494aee08eafa8 +SHA1 (NetBSD-6.0/sun3/binary/sets/modules.tgz) = 7c6df8904730e2b7d3ea7e98d3a88ee7450e937c +SHA512 (NetBSD-6.0/sun3/binary/sets/modules.tgz) = 95d55d7951896249f4b1b3c38ba80c75c415ffee77e3294f40f8680756cb1cd5b5c2b74740ccd66f218474f220f9603feb81bf9e6d72fa130a9ec3c595abba63 +RMD160 (NetBSD-6.0/sun3/binary/sets/modules.tgz) = 485905b274e58b342035d5485507e7c018ee62f0 +MD5 (NetBSD-6.0/sun3/binary/sets/modules.tgz) = 5350f1aec24cf27edd1c4d50c916ba33 +SHA1 (NetBSD-6.0/sun3/binary/sets/tests.tgz) = b76bdb5e8311a0fe1f22aab836007d5cbaf92618 +SHA512 (NetBSD-6.0/sun3/binary/sets/tests.tgz) = 475835a862280be0709e09a8ea5eb132d8c068c63df12dcc925ff3268250afbde228b593f66061d2b946dabc19eeebbb1a4fd313a751c4e5fd8a63ba63f2fdc4 +RMD160 (NetBSD-6.0/sun3/binary/sets/tests.tgz) = 58e77c597950e782b3c75967d864ebbc961ffede +MD5 (NetBSD-6.0/sun3/binary/sets/tests.tgz) = 729752bb47500babd316c4776ba02e80 +SHA1 (NetBSD-6.0/sun3/binary/sets/text.tgz) = edf2e1f8352a2c45287ecff9c473da4673473a6f +SHA512 (NetBSD-6.0/sun3/binary/sets/text.tgz) = 2098084f46640c2f45b0fb916a2123eacc2e390faaa04e3a8ea99d93f41c4ca5ba77d4192805b13a053ad8262aecccc2228448c9f048c03c96ca51869f342ebd +RMD160 (NetBSD-6.0/sun3/binary/sets/text.tgz) = 1adc9b33d9aec637e1f8e7888f07076d500b2ea6 +MD5 (NetBSD-6.0/sun3/binary/sets/text.tgz) = 60c2eabb16dd9df538a98153e2dc7dc7 +SHA1 (NetBSD-6.0/sun3/binary/sets/xbase.tgz) = 404b75757bcc91b281fbd5ec9b9333e6c106579d +SHA512 (NetBSD-6.0/sun3/binary/sets/xbase.tgz) = 0f1604049c7e1caac48d610304a1490d2e55dcf3f6a325139eaa57a38211836c479b1dc070cc3b8b0afcdddac7a84b679d96330f65f86015a80b7800fdca633e +RMD160 (NetBSD-6.0/sun3/binary/sets/xbase.tgz) = b1e258608f09cd175c9e15844371daff5fe0f027 +MD5 (NetBSD-6.0/sun3/binary/sets/xbase.tgz) = a7ecfb2c66b224ecf2460fe5c6715f0b +SHA1 (NetBSD-6.0/sun3/binary/sets/xserver.tgz) = 88091f11f474465d1a996569643d6e22cf08f717 +SHA512 (NetBSD-6.0/sun3/binary/sets/xserver.tgz) = 36de7d4b8be72d53d5f90a144d278359da55008917d2747419d3347d53989e9ceca6230fb2596d4ce6257d1bc9f171c6b9a8e738af86930adc8535e726a8e356 +RMD160 (NetBSD-6.0/sun3/binary/sets/xserver.tgz) = e161f48499d8f1ca64b22d65365704f65344875a +MD5 (NetBSD-6.0/sun3/binary/sets/xserver.tgz) = 6ed6442ab169c491e991c8074512bb48 +SHA1 (NetBSD-6.0/sun3/installation/miniroot/miniroot.fs.gz) = 8b01f52ec164477fb5ec72725d941e3330c7da94 +SHA512 (NetBSD-6.0/sun3/installation/miniroot/miniroot.fs.gz) = fb6995a81aeb2f9fb89e096290cf0921e92b1b2be0adaf95dd2b62c89bbd047b0879231d4e5805a68bd023026ce563bf6f0fc3214ecfabc449650dee9790385f +RMD160 (NetBSD-6.0/sun3/installation/miniroot/miniroot.fs.gz) = 54d3f3d3782536c89d2b6bbf6abb793617c83925 +MD5 (NetBSD-6.0/sun3/installation/miniroot/miniroot.fs.gz) = f9994dd6a5b9837915a4ff01a7c9baa2 +SHA1 (NetBSD-6.0/sun3/installation/netboot/netboot) = 88a9ccc7444c4692483705ef90da4af422b33497 +SHA512 (NetBSD-6.0/sun3/installation/netboot/netboot) = f0810823fbe7335cc83516a71bdf4d5ab281fc2fb71309d76cb979e741af00d81b55e4b298af07e4932ec8e70a79518ace9af7ebc3b5d8a3328555785a8c2d2b +RMD160 (NetBSD-6.0/sun3/installation/netboot/netboot) = 57b89f091bf51dfda7a3b1b3e92bdd0c7e96e958 +MD5 (NetBSD-6.0/sun3/installation/netboot/netboot) = 9041ee544a0625228cbbb93e06d2961f +SHA1 (NetBSD-6.0/sun3/installation/tapeimage/MakeBootTape) = 2b66897333fbeba29a086477f6d25026b6d60e55 +SHA512 (NetBSD-6.0/sun3/installation/tapeimage/MakeBootTape) = db9307323e7dc0d394fb2b8e012c86df51109357851f2c5ee7894468d4e3b54465ca5015141621fd9d28aeb7a2eef0beac987fc7faeee223f9571ff4589d1036 +RMD160 (NetBSD-6.0/sun3/installation/tapeimage/MakeBootTape) = 986f20c8bab33006ea857b9f925b964ab43b9b03 +MD5 (NetBSD-6.0/sun3/installation/tapeimage/MakeBootTape) = 68ea84a134fa2781294912ca85d4b1ee +SHA1 (NetBSD-6.0/sun3/installation/tapeimage/MakeInstTape) = a242866885b14ec2e624319b2fe1fc4f940a422f +SHA512 (NetBSD-6.0/sun3/installation/tapeimage/MakeInstTape) = bd5950ce181ae973784c56bed18085fdfd6fd8b1a46d83564c798c130bc265f7a811cb896be8b9f8f78f014aa1a1d37e34b307a7f806ad8f7790ce2308856b61 +RMD160 (NetBSD-6.0/sun3/installation/tapeimage/MakeInstTape) = cb0330a75c5b5fa600e3789d81ff75f1c1d81078 +MD5 (NetBSD-6.0/sun3/installation/tapeimage/MakeInstTape) = fdc38b08d909159925b6a4efca11a498 +SHA1 (NetBSD-6.0/sun3/installation/tapeimage/tapeboot) = 276be9760458783489c93cea994dc73289ace945 +SHA512 (NetBSD-6.0/sun3/installation/tapeimage/tapeboot) = 7d6f1a348f99e42960f1697105d2771228a921860b0bd78624e96efcd9dde839412511e414f824ea78f4d5c938141c96d896acb3af426fbb393bbc69825c6c57 +RMD160 (NetBSD-6.0/sun3/installation/tapeimage/tapeboot) = 585b74fc55271ea82d4c2e3a38cd3bd7fc9cebd4 +MD5 (NetBSD-6.0/sun3/installation/tapeimage/tapeboot) = 6e786930e4f263c8fd65c0684b10f17f +SHA1 (NetBSD-6.0/sun3/INSTALL.html) = e1f85d7f20325efe213999b96d606094b64a2c3e +SHA512 (NetBSD-6.0/sun3/INSTALL.html) = 571b45b18a5fa33d705470440bfc49b38b19f5625aa26b79241f27232a4e902c1689e6acfa563d95204a6bc5a9955565fdd915673db770f739003c8838a7b680 +RMD160 (NetBSD-6.0/sun3/INSTALL.html) = 10984fb54cdde46e9dfe3567fff0a41e2f2fddfa +MD5 (NetBSD-6.0/sun3/INSTALL.html) = b221aa68f0c0063c7d4ceb493971636b +SHA1 (NetBSD-6.0/sun3/INSTALL.more) = 3f54bfd9cb004fe817d400878e005dd81f1d2850 +SHA512 (NetBSD-6.0/sun3/INSTALL.more) = 6b56e0d51f7423f74aa64a269fe9a0787b0a71d54f8582242d874066df05cc6bb4840ff6d3fd2817f4919b707ff621ca00a77f32938ece1dada70d8a3e6eedef +RMD160 (NetBSD-6.0/sun3/INSTALL.more) = 40aec024ba64af07553ff888f3140e1e6793ac68 +MD5 (NetBSD-6.0/sun3/INSTALL.more) = 9c67417a5a30c173b09f1a8b518032d1 +SHA1 (NetBSD-6.0/sun3/INSTALL.ps) = b83169ce92b3dc6bd83a1ca5e858120f8b91db45 +SHA512 (NetBSD-6.0/sun3/INSTALL.ps) = 546cc770038d3194ca5dfab82113644f6b4fbb5930b9560c14550234858d0bb0edc7fe1fe24d44413042dc7f2c64dc5e4002f3fb60b9893c76f0b80dbe02ae02 +RMD160 (NetBSD-6.0/sun3/INSTALL.ps) = 1110e213ad092c715e1c5314d9c11d4e4d0cd977 +MD5 (NetBSD-6.0/sun3/INSTALL.ps) = 848bd14e183958c567bdde20345d9b7b +SHA1 (NetBSD-6.0/sun3/INSTALL.txt) = f37f80d7db1daf78f66d91f7f76ac9caecc69d65 +SHA512 (NetBSD-6.0/sun3/INSTALL.txt) = aaa6abd3508681ed137796f3f64187fe0e9c7ec26f0d0f81ae73a4e2853ef5aa6b70e861ba69fad5ab51d62f1b09440a0f3f033ef2443a8b12ffc2129e5efdb1 +RMD160 (NetBSD-6.0/sun3/INSTALL.txt) = dfcd996574e4d266e95640301662f4928e3a343b +MD5 (NetBSD-6.0/sun3/INSTALL.txt) = 194d8eac56ca75bff60e3d8c6e003ab1 +SHA1 (NetBSD-6.0/vax/binary/kernel/netbsd-GENERIC.MP.gz) = 71d44bf3bd2a39ac207a085a22a8310014e4b062 +SHA512 (NetBSD-6.0/vax/binary/kernel/netbsd-GENERIC.MP.gz) = 875f45349bf522e4f63d8f1261433b3e109df5ce7c3ee1edd13e2d4526616b7863507dc305d954300308a4c650b9fa12168219d0deb6622b517442b34e10bcfa +RMD160 (NetBSD-6.0/vax/binary/kernel/netbsd-GENERIC.MP.gz) = 357c54bfe13253c5fec2c4ca6cd18909b6a3a6a4 +MD5 (NetBSD-6.0/vax/binary/kernel/netbsd-GENERIC.MP.gz) = 5aa951b5c5cb5592f950fa3882b2f60f +SHA1 (NetBSD-6.0/vax/binary/kernel/netbsd-GENERIC.gz) = 9b77cf6513c4cf4fdb0081400a46c34a1c0cf04b +SHA512 (NetBSD-6.0/vax/binary/kernel/netbsd-GENERIC.gz) = ff9d18b6c5d3bcd7bf4ea6e341e77180a7c68b034c61e02dc3d540389e9690faf7a157587847b3f1c25199cee097178b0b658118daddd136aa5f5856dcec1c38 +RMD160 (NetBSD-6.0/vax/binary/kernel/netbsd-GENERIC.gz) = 2ed49d64a3f42845c08a8ae30d45569492895cc3 +MD5 (NetBSD-6.0/vax/binary/kernel/netbsd-GENERIC.gz) = 26548ca549cfa4f7c9be70e52a981d69 +SHA1 (NetBSD-6.0/vax/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/vax/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/vax/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/vax/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/vax/binary/sets/kern-GENERIC.MP.tgz) = d4cac92dc06ec7b3c4ec9ca0d60dd1ace1814e50 +SHA512 (NetBSD-6.0/vax/binary/sets/kern-GENERIC.MP.tgz) = 3b10e201e963285a8c3d9319e818510701756a3c33003a5536d273e886cc0b3c02ffe10e762d5d7b4aee2d0098d3600396afc2baafea64cc268fa032203a46f9 +RMD160 (NetBSD-6.0/vax/binary/sets/kern-GENERIC.MP.tgz) = d9b4a6a9c85abeee0178536cd1b5c4f0322067a4 +MD5 (NetBSD-6.0/vax/binary/sets/kern-GENERIC.MP.tgz) = 15126f47c08adefe93c7261b6eeeddec +SHA1 (NetBSD-6.0/vax/binary/sets/base.tgz) = 9b83f88ab7d06a112cfff79b6657912bddb77987 +SHA512 (NetBSD-6.0/vax/binary/sets/base.tgz) = de7c42524163a5d9de7fda440cd2523834d5c46e4e992724a4a7af5e0768e5b105909e9a60e603b2a942cade3795cf4cc2bb22c7627453eda92bf662da83a16a +RMD160 (NetBSD-6.0/vax/binary/sets/base.tgz) = 3059d6e4a7d54ebc9c529f90719ca561ebbe8036 +MD5 (NetBSD-6.0/vax/binary/sets/base.tgz) = d06066c8a452b8a7831de680a420ea4c +SHA1 (NetBSD-6.0/vax/binary/sets/comp.tgz) = 3ad25c223276936b26916121fe8341524e2e51a6 +SHA512 (NetBSD-6.0/vax/binary/sets/comp.tgz) = 852dc3d7a01fc8e11e66723930d90e7141d974b976d8f7986f068fb5202dad396ef2762400c1e9e02b0d6c5a087435a56f65e502079eec9d9e86c24cf81782bb +RMD160 (NetBSD-6.0/vax/binary/sets/comp.tgz) = a4e74e817807d4d79a43ac450109b14474fda740 +MD5 (NetBSD-6.0/vax/binary/sets/comp.tgz) = cf51957de39d3a72c7dda2633d39e705 +SHA1 (NetBSD-6.0/vax/binary/sets/etc.tgz) = 21f4ff8b449498081fd6dde92b43eaca86d886ef +SHA512 (NetBSD-6.0/vax/binary/sets/etc.tgz) = c6e43ea57dd0b53f9e0a995aa872d9f7f1d8852fbe7105e125116f577d0ce2acb1e8deddc6a8dcb51e272a982cf549706b23bb26b0acedad416ceef8910a6461 +RMD160 (NetBSD-6.0/vax/binary/sets/etc.tgz) = dd7a5f74812906801bf474d265a4846f069c00ef +MD5 (NetBSD-6.0/vax/binary/sets/etc.tgz) = fbb2c18ea3be98a3624f54b834399ee9 +SHA1 (NetBSD-6.0/vax/binary/sets/games.tgz) = cd79679fa36349431355dcd14b8a058476f20086 +SHA512 (NetBSD-6.0/vax/binary/sets/games.tgz) = f68c931765849554222cc439d5761411d36e8e95b4331d15525e73f77b31249c220b9de4c2061f5e35207e75e27d5d6ade99a7eadf2baf54fc8eeb16ac243dbe +RMD160 (NetBSD-6.0/vax/binary/sets/games.tgz) = 7da1dd4ece7e9062635f7b0766af245e2624c032 +MD5 (NetBSD-6.0/vax/binary/sets/games.tgz) = 995e32bef1b920f33c5d7eb946441682 +SHA1 (NetBSD-6.0/vax/binary/sets/kern-GENERIC.tgz) = 6e61cfb380e7cf45e2094ef64d26d44ee33fd086 +SHA512 (NetBSD-6.0/vax/binary/sets/kern-GENERIC.tgz) = 0d35a882e1e98796099bedc0157fc30978b2e43ef0627be603036259069dc13503fee5dd57b2e9da74dd5c2cb1bb823f4bf91d98259d84b993977bae05d8c10c +RMD160 (NetBSD-6.0/vax/binary/sets/kern-GENERIC.tgz) = 3e2f321e7934e6597ea83627934e88d2214baad3 +MD5 (NetBSD-6.0/vax/binary/sets/kern-GENERIC.tgz) = 2efb4b8d6a76ebb59f4ce1171e1502db +SHA1 (NetBSD-6.0/vax/binary/sets/man.tgz) = 9c2da95fb72f9fd1eaa8f7baf5fe45496c8b4615 +SHA512 (NetBSD-6.0/vax/binary/sets/man.tgz) = 1a158e92b8414d92745a06fe1c721047e87fd768d7158e078c3a17de1d2634463f8f6b022a001f5f9010e14f0eedf6d5a94e4b73b4dd0ed9ac4576abbf2aeaf4 +RMD160 (NetBSD-6.0/vax/binary/sets/man.tgz) = d2485fd19bffbc6103f8aa7521e52c8f652fafa2 +MD5 (NetBSD-6.0/vax/binary/sets/man.tgz) = 83e81f5c82acdf7ee76ef5854eca3f5b +SHA1 (NetBSD-6.0/vax/binary/sets/modules.tgz) = 4e60e0177f0e5d6e42ee875a7c30cc612c22ca64 +SHA512 (NetBSD-6.0/vax/binary/sets/modules.tgz) = 0e5926279b9534cb9bd34ff0c4d49fa4cd467966829d080ec8ab739039536f42173c2ec91aea40ca37d94625a5b395c3f55ce7936f963bd8d970d1a81fcff8af +RMD160 (NetBSD-6.0/vax/binary/sets/modules.tgz) = 54b0d690b929b4df06adc044864e76d47f09c844 +MD5 (NetBSD-6.0/vax/binary/sets/modules.tgz) = aa18ce8768d9fd88206d465fd1ae155d +SHA1 (NetBSD-6.0/vax/binary/sets/tests.tgz) = ec975a37d490f45fb9e7f0f30f0ec46fc0038531 +SHA512 (NetBSD-6.0/vax/binary/sets/tests.tgz) = 33b8686c97da76e031a9678103ba99a83cc4189545b4020241a83084585f0eb200c0cb44634e578c8882cd849f80151383a54511c80d1a35964a3567f8e6b314 +RMD160 (NetBSD-6.0/vax/binary/sets/tests.tgz) = c27fcdf838dfc43c1527fde3fba2735065a5d12c +MD5 (NetBSD-6.0/vax/binary/sets/tests.tgz) = 3789eac68014743577dfe22503dd98a5 +SHA1 (NetBSD-6.0/vax/binary/sets/text.tgz) = c7dcf12545842d5563887c983d694fa569d25ab3 +SHA512 (NetBSD-6.0/vax/binary/sets/text.tgz) = 50a7ad69dc23c0d178a3f835e9bed7305cbe432a92cf947e64e28316ac94ddd7def90e91c53515d0cd3ac26c5df23d3f60932ba688ab04525d635555b6078a6a +RMD160 (NetBSD-6.0/vax/binary/sets/text.tgz) = 24ae1e1016b492c3dd575099936598d00d8ac6fa +MD5 (NetBSD-6.0/vax/binary/sets/text.tgz) = 99863a74757bc9677befe8c6ef049685 +SHA1 (NetBSD-6.0/vax/binary/sets/xbase.tgz) = 35f6a1b09f246736f7c1c6049831ca0704fe53d1 +SHA512 (NetBSD-6.0/vax/binary/sets/xbase.tgz) = d2d0b6a5702e4a87e4823ce7478f5c8f1527045d96040680960e3d96f98f64e40ac7263ad2ca4c4272d4d253fcb41b7e296a9d27f9ffa7dc03be6c437835878e +RMD160 (NetBSD-6.0/vax/binary/sets/xbase.tgz) = e2455fc04171cd3aef8662a36820552811c7657b +MD5 (NetBSD-6.0/vax/binary/sets/xbase.tgz) = ec8b6356f82d4ccb90e93dd78e5c741f +SHA1 (NetBSD-6.0/vax/binary/sets/xcomp.tgz) = ebadf7653d6173ccc73d1228338a4df09eb7dce2 +SHA512 (NetBSD-6.0/vax/binary/sets/xcomp.tgz) = a4c4cfaaea473e617870a92bfce40fbc2e34413f31ec2159554031c4312dc1e605079a9e0fd3774967bba9cc27bf9efc97899f09959bd401726ceeeec7006790 +RMD160 (NetBSD-6.0/vax/binary/sets/xcomp.tgz) = e6d1591328fcc0af7336d22a5426f72c8343ad49 +MD5 (NetBSD-6.0/vax/binary/sets/xcomp.tgz) = 1cc0fa0971f06c2bd9e296db9d6d6fa5 +SHA1 (NetBSD-6.0/vax/binary/sets/xetc.tgz) = 2c85388aa75c419cc5651c053b00710471a87350 +SHA512 (NetBSD-6.0/vax/binary/sets/xetc.tgz) = 38c9f1abf9d6ff828c361a2c58690f70a7d707aa739f7ded9f256b414e7b78c11ff4f915a59f99884afd5ef0b874c1c1b70aa438f6bdff07e354d67d2257bf72 +RMD160 (NetBSD-6.0/vax/binary/sets/xetc.tgz) = b1186ef0c975fa76d8d4d0c62e24ae86cb3d433c +MD5 (NetBSD-6.0/vax/binary/sets/xetc.tgz) = 46ca22a86d8052c1044717eb907d7874 +SHA1 (NetBSD-6.0/vax/binary/sets/xfont.tgz) = e9a33e8d99378b3944fc21aa983c02707831f0bf +SHA512 (NetBSD-6.0/vax/binary/sets/xfont.tgz) = 3d09f4edf49bfa98c7817cdb1b91aa4ec902dc87c1765e9a92f143bf4918a60e011fe614a70d9dd926ca2a019a33e5f0dc2d7198205f2273e755049dd8d5a2a1 +RMD160 (NetBSD-6.0/vax/binary/sets/xfont.tgz) = 9ae96f8628d6a35053f093acee972bdd8b6722cd +MD5 (NetBSD-6.0/vax/binary/sets/xfont.tgz) = 6e95a6fd030425bb19f0505b9308d20d +SHA1 (NetBSD-6.0/vax/binary/sets/xserver.tgz) = aa6c021940fae979a4a3a3cd01a138808c49621d +SHA512 (NetBSD-6.0/vax/binary/sets/xserver.tgz) = 540455f89e8dfe7d376322ab95288e96e54aa0531aab7cb96e0b1354f85ef64778cbf265bfc2fca7827879a286d80b15f9e973d62594e5bf02df4b0add15be0c +RMD160 (NetBSD-6.0/vax/binary/sets/xserver.tgz) = 84dee738690e4487d7f28cba1d3f61ab9eb12240 +MD5 (NetBSD-6.0/vax/binary/sets/xserver.tgz) = e2df86b6bfa5259e72d02f40de72491b +SHA1 (NetBSD-6.0/vax/installation/bootfs/boot.fs) = c4d1340eb7d2ea1d555a46fcf2071fa2f091d1d1 +SHA512 (NetBSD-6.0/vax/installation/bootfs/boot.fs) = 155e7faaf14e619309c3ca8cc163e08d6bd3cac41b4d38dc5dc4cd4736e99003a2b6a6d0ffb6cb698772f43d31f577732b9933a71fb1f6315af16dfae34d4f66 +RMD160 (NetBSD-6.0/vax/installation/bootfs/boot.fs) = 52a2200dbef9e624d7ca91eb6d2110599b8010b1 +MD5 (NetBSD-6.0/vax/installation/bootfs/boot.fs) = f02d1ee9291b0dd37f0dc75d0a27ad10 +SHA1 (NetBSD-6.0/vax/installation/miniroot/miniroot.fs.gz) = 5aed885a0dde234caed611cca0f474dc6cf8461b +SHA512 (NetBSD-6.0/vax/installation/miniroot/miniroot.fs.gz) = 3d647213e86ccb976107853ab81ec82d339d2cc7c7bda4cc0c416f55e521c7a43a73523c7f9ff6e590531f019badcd414f1bdab4c95db0806a606065c6803ef4 +RMD160 (NetBSD-6.0/vax/installation/miniroot/miniroot.fs.gz) = 6ddb63ee115a7b4a78546092ac7b8cee7c056921 +MD5 (NetBSD-6.0/vax/installation/miniroot/miniroot.fs.gz) = 0f860ac5f201e72f4b22392027b25117 +SHA1 (NetBSD-6.0/vax/installation/netboot/install.ram.gz) = 8f48dc649fe71a6f861a9f96e2b63679971b762c +SHA512 (NetBSD-6.0/vax/installation/netboot/install.ram.gz) = 857920e536fe08897d7e20c62c74a5606ea791d97111740222c8998ee4a1a9ae05f52ac27b5580d5f78a70f75d5a9ea9446802a85297a13411b98ebe8a84a3e1 +RMD160 (NetBSD-6.0/vax/installation/netboot/install.ram.gz) = 9c94e2d64328f88eb7157d6a47e5aec15b1da2a3 +MD5 (NetBSD-6.0/vax/installation/netboot/install.ram.gz) = 23d3d0b714186b3e2e7b70d5f0a1ce21 +SHA1 (NetBSD-6.0/vax/installation/netboot/boot) = 738e9f280ab9874a2eb21af8627d70e2abd2ba0c +SHA512 (NetBSD-6.0/vax/installation/netboot/boot) = 934496142a69c247ce8b96ea6de19e0cbe0d9e4e8a1ae1043f4d60926c6b3deb30132f3bdc346b3422f1fea02da3a3feaf900d64a9759d265b33fe81ab3da070 +RMD160 (NetBSD-6.0/vax/installation/netboot/boot) = 8a60febc408768e89ebb1a834bffaa06a72d3503 +MD5 (NetBSD-6.0/vax/installation/netboot/boot) = f238dc1fafca2d7f1a83a22b6cb31091 +SHA1 (NetBSD-6.0/vax/installation/netboot/install.ram.symbols.gz) = 6b57f7a857c24539639cce3ed41ed5de16ec233b +SHA512 (NetBSD-6.0/vax/installation/netboot/install.ram.symbols.gz) = e9ac802e948631231eda425e5bab76bf14bc59462613eb6c1025708d67f54c67e9b928cbf33253473605c6239842667eba5e58240d6cb53afc5c80c8546357f5 +RMD160 (NetBSD-6.0/vax/installation/netboot/install.ram.symbols.gz) = 5a6ea2a19caafd034e75e9440d1e139d1af3ef0c +MD5 (NetBSD-6.0/vax/installation/netboot/install.ram.symbols.gz) = 712856f65322faccd1b116c548d40196 +SHA1 (NetBSD-6.0/vax/INSTALL.html) = 8d850ffd9374c9bdc63e37fa14dc63eda02a93fe +SHA512 (NetBSD-6.0/vax/INSTALL.html) = 3c93355dbfd0cbad25eb74c8497975855706a20dafe8a1baa64d0b53801d5e02d81a93c3347c52950fdd424623cbb58c7a0aa58b7989e89116b157f9d18bef51 +RMD160 (NetBSD-6.0/vax/INSTALL.html) = 42d4d65000e12d8f2cbe30f6743d84d7a040bb05 +MD5 (NetBSD-6.0/vax/INSTALL.html) = bbad6392f6badb4a1d0ee2977b9df90c +SHA1 (NetBSD-6.0/vax/INSTALL.more) = 624b96b802364eb833ca077dc706d75b5f68f336 +SHA512 (NetBSD-6.0/vax/INSTALL.more) = 300954b8c1f3c47a1a45d773f8c7bad3c12dbc292485b7a7206289f56584ce12befa89b8d315511c3e3f7c407de9ca068fbdaae9d75c52dff72a8f8a9b5e4a55 +RMD160 (NetBSD-6.0/vax/INSTALL.more) = ab1b5238e9eb5ad1c937c75901199023c08d2434 +MD5 (NetBSD-6.0/vax/INSTALL.more) = e634a224d0d67c5cc1c7dffd98156b79 +SHA1 (NetBSD-6.0/vax/INSTALL.ps) = 57710ab0d4450b0692b07eb812c9c7e6d70a49d5 +SHA512 (NetBSD-6.0/vax/INSTALL.ps) = 0afac140d664edbb10a41c6dd646c797b78e37c1d36aa4804653fbef64171ddf9688d7220755553ff4add8891bd97f083bde4b03c93fe579f1e9d030c83f3d07 +RMD160 (NetBSD-6.0/vax/INSTALL.ps) = e84f468d6f328faa9889cf2ad76cab5846c45da0 +MD5 (NetBSD-6.0/vax/INSTALL.ps) = 51b9a2a1046494b2443503636fa223da +SHA1 (NetBSD-6.0/vax/INSTALL.txt) = 0a4b816342615d9a4e60cbc99bfea81afe41d0f1 +SHA512 (NetBSD-6.0/vax/INSTALL.txt) = b1853a3be6cd17449c4e5539945812b9ba87e02e07877dfe791e04c3db39ed1577e795d7d5e3b1048fc60eca5694592bb5671982c24aaa1f78e3783ede603ded +RMD160 (NetBSD-6.0/vax/INSTALL.txt) = f774566773432a691acf285d569dabcf5037ecfb +MD5 (NetBSD-6.0/vax/INSTALL.txt) = 43a9353717d9309c11fb5f4a9685942d +SHA1 (NetBSD-6.0/x68k/binary/kernel/netbsd-INSTALL.symbols.gz) = 0e3d568ade336cd6e538d567ea11a965d49588cf +SHA512 (NetBSD-6.0/x68k/binary/kernel/netbsd-INSTALL.symbols.gz) = 721a7e1ec94d9a37f37eb30b96d66b19d387090964ee93233de36771e4d106e72cdbeb4b0b17f8d490d9f64484b8a511526841c511b2d33624bd626b4388b623 +RMD160 (NetBSD-6.0/x68k/binary/kernel/netbsd-INSTALL.symbols.gz) = 176ba2b94555c5bda82260a075ba295021d61e8a +MD5 (NetBSD-6.0/x68k/binary/kernel/netbsd-INSTALL.symbols.gz) = aa03bcea1e574f24c1ef0eeb364f1c8d +SHA1 (NetBSD-6.0/x68k/binary/kernel/netbsd-GENERIC.gz) = 9a7796c7abf7b4828ee7eb7125b73f5ccd25e2db +SHA512 (NetBSD-6.0/x68k/binary/kernel/netbsd-GENERIC.gz) = 58c7f85cf73d90a04c42c502a3dedd779d9f5013a58f0df8a279cf559dedb80b6bdf2a22804284fa58a7df9c1ba8a8f0454d3f76a43787a7372afb58d5d734b3 +RMD160 (NetBSD-6.0/x68k/binary/kernel/netbsd-GENERIC.gz) = efce8e9537f895492b5becab7878dec07fafe7c1 +MD5 (NetBSD-6.0/x68k/binary/kernel/netbsd-GENERIC.gz) = adf275bc0aec4a8ba50661637b7707e5 +SHA1 (NetBSD-6.0/x68k/binary/kernel/netbsd-INSTALL.gz) = e5fee2392b742d34a50bd2236dc4ba26acdd57e2 +SHA512 (NetBSD-6.0/x68k/binary/kernel/netbsd-INSTALL.gz) = 6aa21ef102224a5194fd6709b70a47788e073ad0d325dbe3b982a19a24c67b421acb003496ddf42804785b0dae9bb32dccde617e7d6d9185511205ab390cdcb3 +RMD160 (NetBSD-6.0/x68k/binary/kernel/netbsd-INSTALL.gz) = 7251ea070e26aa877c85b9eabffd62cd6ee4b04c +MD5 (NetBSD-6.0/x68k/binary/kernel/netbsd-INSTALL.gz) = e5e8b74d980cbbbc0324cab3da12af0b +SHA1 (NetBSD-6.0/x68k/binary/sets/games.tgz) = 16ee93ea4d5fac2fb28fad5c32c8a3d57d011d79 +SHA512 (NetBSD-6.0/x68k/binary/sets/games.tgz) = a7f49ab72f50273f66c8dcf408b57ec4668debd5537c5bd0ec59aa0f4fa1d599ba0798d1b283315c4208cbcb608925808ce003b1ade79034886edb8208f9f48d +RMD160 (NetBSD-6.0/x68k/binary/sets/games.tgz) = 1e09d99d7fe2e495763f05919472d27a4ba699df +MD5 (NetBSD-6.0/x68k/binary/sets/games.tgz) = 8a26f3e864444209088bccf21419a616 +SHA1 (NetBSD-6.0/x68k/binary/sets/man.tgz) = 899b9d8242e983a5110ab755651c24f709b5af67 +SHA512 (NetBSD-6.0/x68k/binary/sets/man.tgz) = 410999db110d710f4bb498c3d7ae7adc62170c7c2f470ce189c92f6c436c5ea96149659c631ef0b5605caaa025d97dfe1c07c428d86f51239657bd6b71717b15 +RMD160 (NetBSD-6.0/x68k/binary/sets/man.tgz) = c1270f68c6d41b351877f71f0396ac34877dfc8d +MD5 (NetBSD-6.0/x68k/binary/sets/man.tgz) = df4db2bbfa39ef6a4a215d949653d04a +SHA1 (NetBSD-6.0/x68k/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/x68k/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/x68k/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/x68k/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/x68k/binary/sets/xcomp.tgz) = e13548b8974f5d55e98caf17b2b4bbbcf2430370 +SHA512 (NetBSD-6.0/x68k/binary/sets/xcomp.tgz) = e4b13c798df04ffef88e72100e2db5af400e5ae255cd7a1ca2907736b8138a59045b6f3bd8531b5753d0b87eadb1b5f801043a929bb25d1611e4be693c1da954 +RMD160 (NetBSD-6.0/x68k/binary/sets/xcomp.tgz) = 3b1f4e26ddd57e69afd9709553c1bf70d6e29ea0 +MD5 (NetBSD-6.0/x68k/binary/sets/xcomp.tgz) = 894bb9aa05b164d9923682165d708335 +SHA1 (NetBSD-6.0/x68k/binary/sets/xfont.tgz) = 24ca4cb77a59246b1b05e0a91fed21c63259d12b +SHA512 (NetBSD-6.0/x68k/binary/sets/xfont.tgz) = 8dc297fb6205a995767e68e77cc21169234dfb66a86bbcd2e1828fd32efeda0a25c9f2a9b1a39b97fe8d7b24f8cd5cf6160859af6be2259876f39ee4e76c405b +RMD160 (NetBSD-6.0/x68k/binary/sets/xfont.tgz) = d2f134959940e6667aca185f01e388c05dc6bc85 +MD5 (NetBSD-6.0/x68k/binary/sets/xfont.tgz) = 3c96c1f0a13cd7d277ca35622ac9c058 +SHA1 (NetBSD-6.0/x68k/binary/sets/kern-GENERIC.tgz) = 253e2e072ae66dd896be3d6d936c637bb96ef2c2 +SHA512 (NetBSD-6.0/x68k/binary/sets/kern-GENERIC.tgz) = e2b9221ffad2c150f1529243197e7672c58a41d865dcf02a7252c1bb1f0fdb644e8c6bc3250f16f2091748d2a009badd12c0cbda2ae2b186bbfa0b6302957293 +RMD160 (NetBSD-6.0/x68k/binary/sets/kern-GENERIC.tgz) = cd78ce4ed94bd540d9cfcf2d3a6d51fd83cbef95 +MD5 (NetBSD-6.0/x68k/binary/sets/kern-GENERIC.tgz) = a41a26a51d64ac00f3d0b1f5657a5400 +SHA1 (NetBSD-6.0/x68k/binary/sets/base.tgz) = 97339969786af5934c8db561afd33bf2fdd5cb77 +SHA512 (NetBSD-6.0/x68k/binary/sets/base.tgz) = a5cb607f828570f11ae3653032d442cc191339a00037cc6c37635c726fb2b06a9bf1d2dec7e71bfb824ac11810ff1ccbff55ec69659c66112b36fd28521a304c +RMD160 (NetBSD-6.0/x68k/binary/sets/base.tgz) = f77783ac8537a39ac77014b7fd8860269a6aae0c +MD5 (NetBSD-6.0/x68k/binary/sets/base.tgz) = 752b937da621346aaab5b18ac1fc9f3a +SHA1 (NetBSD-6.0/x68k/binary/sets/comp.tgz) = 5b2f871bf928a68b7ffdf2b2f45e5ee80a8c83a0 +SHA512 (NetBSD-6.0/x68k/binary/sets/comp.tgz) = d037edaa7d8b4a275a39771f2f7ffd4dd46f68a3107af0ca88f9ce205370c756904c6c0bcb7f6138fabeaf0bfb504ce541253c9d6d2892675e7e308358045047 +RMD160 (NetBSD-6.0/x68k/binary/sets/comp.tgz) = b371813449f8d913bf22466d52a7a238522b8a5d +MD5 (NetBSD-6.0/x68k/binary/sets/comp.tgz) = efab43faa3de48943a5ba3b96a07741d +SHA1 (NetBSD-6.0/x68k/binary/sets/etc.tgz) = 52e6167471d4788f7f060166de8f23a31f731596 +SHA512 (NetBSD-6.0/x68k/binary/sets/etc.tgz) = ce530878bf230e22786bac9ce6075958eebb52c5119b760ebc183b8f7b2fa59297797768461a44f708b9ce993c21a96e0f49b207c79208e25eea93412889babc +RMD160 (NetBSD-6.0/x68k/binary/sets/etc.tgz) = ad019f3b95e8cc9d3320909dee7dd91ff45a4da6 +MD5 (NetBSD-6.0/x68k/binary/sets/etc.tgz) = 9f179baf30026ced05db113a623006b9 +SHA1 (NetBSD-6.0/x68k/binary/sets/modules.tgz) = d52fa0ed8a899526add267f705735e9dcbb62a14 +SHA512 (NetBSD-6.0/x68k/binary/sets/modules.tgz) = af60d178109bc5330363f041d688e46e36e1894ca0320c7a1735f5de483349a38e63b316b297a5bbf7fb282c1f69539698f7704e759a27c1c833239ec775e371 +RMD160 (NetBSD-6.0/x68k/binary/sets/modules.tgz) = 5e3db9d5547a118143f5eac40b442cf27dce8a52 +MD5 (NetBSD-6.0/x68k/binary/sets/modules.tgz) = 18d52b98a32e1b37501fb2056be5d356 +SHA1 (NetBSD-6.0/x68k/binary/sets/tests.tgz) = 469b2b371980f0bd11407497ee2c104536867df3 +SHA512 (NetBSD-6.0/x68k/binary/sets/tests.tgz) = bfb64b49fd88386e2012b827d9af754bbc75a21e63650da66a8add45b54bfc700a3d22a3c6e98e8736309f1a1015f82c366e51ac6539556f1645b28d3d018ad5 +RMD160 (NetBSD-6.0/x68k/binary/sets/tests.tgz) = 8e674a86bd2551876719f842f61850d6505b290e +MD5 (NetBSD-6.0/x68k/binary/sets/tests.tgz) = 5c524dfbbb575f61ff958baa317a4808 +SHA1 (NetBSD-6.0/x68k/binary/sets/text.tgz) = c8b514b008fdd482c7df7df5849c5bbcd04d289c +SHA512 (NetBSD-6.0/x68k/binary/sets/text.tgz) = 37fe61c52eaa54e8de5709bb3494efe1845a0946c65ed007ec0785902d44acbb3b971bd31b53305ce72d4d32180a56f280a4b29a2a9dcb83c443299edcfe0ea8 +RMD160 (NetBSD-6.0/x68k/binary/sets/text.tgz) = d927619390ecab77ada3966395d227967cb38a43 +MD5 (NetBSD-6.0/x68k/binary/sets/text.tgz) = 1854795033d3fb974637643eed84359a +SHA1 (NetBSD-6.0/x68k/binary/sets/xbase.tgz) = 012b5faed219406f267667b7d5047ea9e85ac58a +SHA512 (NetBSD-6.0/x68k/binary/sets/xbase.tgz) = 88b65e79f9801e1d3a0da5d3407754c7d48911bf86e5262fb8d02c46c5653b6fd55e6588177771ff82740b12fc84c8a19e207cee83ceee3a772e5beb182ae72b +RMD160 (NetBSD-6.0/x68k/binary/sets/xbase.tgz) = e5d43999d4316d561ee7689321c04698af4ed5b4 +MD5 (NetBSD-6.0/x68k/binary/sets/xbase.tgz) = e5cdea5cf19b94dc3ef382951ef923e3 +SHA1 (NetBSD-6.0/x68k/binary/sets/xetc.tgz) = bf1f9fa57ffed50beb8d7d455c95928d560bf224 +SHA512 (NetBSD-6.0/x68k/binary/sets/xetc.tgz) = 3bf13d97afb20cb5e7098d9837f0a1bf471e49ec53672948373fcdb23c25c56fcb6de974a021c7e3bcb00e6069e0a68c5a84cd187e4304af129b3db66942d953 +RMD160 (NetBSD-6.0/x68k/binary/sets/xetc.tgz) = d2f0715f277a6de929f1504d50ce1b5fe27327fc +MD5 (NetBSD-6.0/x68k/binary/sets/xetc.tgz) = 85342c60f299840da352a811f666392c +SHA1 (NetBSD-6.0/x68k/binary/sets/xserver.tgz) = 54b441f5b0afb06e26e816a729b259abe8b3c234 +SHA512 (NetBSD-6.0/x68k/binary/sets/xserver.tgz) = a81cf87de57b646f79cbbdf5cf9a69c90bb2f97adccc1310bfaf639313c3027b04cb7591d49cf7dd07f4f6210e971656c7ae8980d8e0a1e854fbbc87ccfd91d0 +RMD160 (NetBSD-6.0/x68k/binary/sets/xserver.tgz) = 0ddef8e502a8ca10a21d59aa99f9476dbac2d29f +MD5 (NetBSD-6.0/x68k/binary/sets/xserver.tgz) = e60e100d889a7377fd708a441d2a818a +SHA1 (NetBSD-6.0/x68k/installation/floppy/sysinst1.fs) = 0c52f0ff358294b5fefca38d963f7fcc3c6dfe93 +SHA512 (NetBSD-6.0/x68k/installation/floppy/sysinst1.fs) = aeaba8cc7f83d83ec41a0ffef1a01203de34a89ad6028f8d5df06b2a6523b82ca44f13370f0f2f03e65cf2bb8a76532868471f25ddac4a8e53aa2f8a57f4be57 +RMD160 (NetBSD-6.0/x68k/installation/floppy/sysinst1.fs) = 396eff107455609a3b7322595660741e14a57077 +MD5 (NetBSD-6.0/x68k/installation/floppy/sysinst1.fs) = e1a273155ed6f80cc365bf441909a914 +SHA1 (NetBSD-6.0/x68k/installation/floppy/sysinst2.fs) = 35344d834aba89ce14574026bdc0c3648c4bed0d +SHA512 (NetBSD-6.0/x68k/installation/floppy/sysinst2.fs) = 59d6206fafca21e1ad29ef12d869f7ad81855f0b1124625278db71dff739a76bc36da83a1bfa4ee920602a246f3f925e4c383ab8ad5455ae3cc19408347da8ed +RMD160 (NetBSD-6.0/x68k/installation/floppy/sysinst2.fs) = ee5f34edcf9ae13406c1db031b9d99cf2e485c4f +MD5 (NetBSD-6.0/x68k/installation/floppy/sysinst2.fs) = c5cf691f0b3380cfa9ed93158a0598a2 +SHA1 (NetBSD-6.0/x68k/installation/misc/gz124x5f.lzh) = 50ef2f563b410530f5f52a857705848973a870a4 +SHA512 (NetBSD-6.0/x68k/installation/misc/gz124x5f.lzh) = 7df17f64a217eaba1374a2833326824d43acbe84a8e47e558ec805053fb3d93e07619d5c89287951eb7e6961068aa8e534f74b7da87106d3c0f306bf5191acbe +RMD160 (NetBSD-6.0/x68k/installation/misc/gz124x5f.lzh) = 2ebf89a1a5ee6564bbd9bdcb5a8d2716f4bc121d +MD5 (NetBSD-6.0/x68k/installation/misc/gz124x5f.lzh) = e27b76e450d506e3cd555f8ae3a99e61 +SHA1 (NetBSD-6.0/x68k/installation/misc/gzip.x) = 639b9edf903ccc07259e146ac141cc8c102bab95 +SHA512 (NetBSD-6.0/x68k/installation/misc/gzip.x) = cac2274fa0b5e1ac2ef978b8a09c001cf3e3acdeaf7131e93677b4fb13d56412bcfee86fe886758866d6daffb67f54dd6fa4c2796bda49ca0e59e4d3a113e7d6 +RMD160 (NetBSD-6.0/x68k/installation/misc/gzip.x) = 7c431086e8719f5e48c9d698808a1ae74a78b2d1 +MD5 (NetBSD-6.0/x68k/installation/misc/gzip.x) = 69fb6553b4cf7d3825b53c8d7bf5a865 +SHA1 (NetBSD-6.0/x68k/installation/misc/loadbsd.0) = 45a858903634d838d7525fff2db12467195ce1d5 +SHA512 (NetBSD-6.0/x68k/installation/misc/loadbsd.0) = 7c67ae6947fb128acfe72dab897edc0d8cb4c8e82b1886337ed07b5d031e0e550ff791b470f0276ef0fb920b4d6eefdc574efec0dc04116b05b510684ad8044d +RMD160 (NetBSD-6.0/x68k/installation/misc/loadbsd.0) = 4b30a14f171cf026efa10f44dd0357cc2db91d17 +MD5 (NetBSD-6.0/x68k/installation/misc/loadbsd.0) = 25b2b8aa6efadacb72cf96f497a38d5a +SHA1 (NetBSD-6.0/x68k/installation/misc/loadbsd.html) = 9cd27c39d6fa54fc2c534e4e6dfb30f86764ea49 +SHA512 (NetBSD-6.0/x68k/installation/misc/loadbsd.html) = 71544bd6ce6c3139654cd55ec1ed293fee603e733fb2cde6574ace66df4ee8450182cf890c4519313ac74bc0d43919340cf277c329e6b7a66734aa33d6465593 +RMD160 (NetBSD-6.0/x68k/installation/misc/loadbsd.html) = d43cd8e0a08f11a2bdd4fcf2d8489761a8dfd629 +MD5 (NetBSD-6.0/x68k/installation/misc/loadbsd.html) = 3228e40e5e967fb87b75ee462388f92a +SHA1 (NetBSD-6.0/x68k/installation/misc/loadbsd.x) = 9ecad059bb18bfc8fb33c165f63a15770326d3bf +SHA512 (NetBSD-6.0/x68k/installation/misc/loadbsd.x) = 7ed4df332f2e65e5db31f95bc7635f2ea1f5b638727509ff16ee7a531a0006addf16f1da4eceb727d4148dcad8686b3dc960760d289f361fbdb2177e1089032f +RMD160 (NetBSD-6.0/x68k/installation/misc/loadbsd.x) = ead03264a128cab57ebeb615b42e3688b5641f80 +MD5 (NetBSD-6.0/x68k/installation/misc/loadbsd.x) = 4b9bcac67fd51cd5bf95911a5431b49a +SHA1 (NetBSD-6.0/x68k/installation/misc/rawrite.doc) = e2cab55990a4835524655fbaf2ade5d9eee29c17 +SHA512 (NetBSD-6.0/x68k/installation/misc/rawrite.doc) = d9df8ac2fe18ff8cc13ad62af9107e821c40ca41cd0ae6d3cd0dd1c55351f8b0f7bb2cdd7f0917a16738d11e0230c0ec233f2297b8603f3a619ef99b0eb1ed9a +RMD160 (NetBSD-6.0/x68k/installation/misc/rawrite.doc) = ada5298cb0d2df6d1833f32ff21cc97244376748 +MD5 (NetBSD-6.0/x68k/installation/misc/rawrite.doc) = 53481a27e630ca1b583cd953d24d13ca +SHA1 (NetBSD-6.0/x68k/installation/misc/rawrite.lzh) = 575e26ad9625ca21e5f3aad4c32fbbe01312c97f +SHA512 (NetBSD-6.0/x68k/installation/misc/rawrite.lzh) = 36104c3fcd87dbedc2421541f14f54151087348f45f69508e5916c3570915f0b0fc355b3c075e4c1cc3907094abe87e14c85ff333e0064403c8230d93719ea0a +RMD160 (NetBSD-6.0/x68k/installation/misc/rawrite.lzh) = 4c0538916a9ca007aa9ba66ea42c6c46a4c563f2 +MD5 (NetBSD-6.0/x68k/installation/misc/rawrite.lzh) = c15b00572229133bf9505876ea120a31 +SHA1 (NetBSD-6.0/x68k/installation/misc/rawrite.x) = 30e3d4504bfbf7c55a77a19435d75bb1069ed596 +SHA512 (NetBSD-6.0/x68k/installation/misc/rawrite.x) = 06d706b3581dc972d282ef9a6d254740b721a43d5f9c6325af7fb3d1fc8402071887b0ca99c720c5d02c8edcab6086b819faa69640ba4463c1713b168d432059 +RMD160 (NetBSD-6.0/x68k/installation/misc/rawrite.x) = 844aa4ab7dbef030c140e543475f24fc60f0a075 +MD5 (NetBSD-6.0/x68k/installation/misc/rawrite.x) = 6efe87d85560d8d6e3eec7a7b9d1545a +SHA1 (NetBSD-6.0/x68k/INSTALL.html) = 5ef0d8d03b7f3f600444752d3763c17000da1e3b +SHA512 (NetBSD-6.0/x68k/INSTALL.html) = 94181608314a1dcc1fa0c634060b28ce229883affc9f64c33d9eeae09b21f9f88149deff8d84a7f64b6b5e7cfb741b6c43d9ccdd2ccdd4c9d6e043f22452adb5 +RMD160 (NetBSD-6.0/x68k/INSTALL.html) = a5e8a1d8e28859a3e08b662d2363d758baf23eac +MD5 (NetBSD-6.0/x68k/INSTALL.html) = c7154e6e818d1490ce1dbc392bb8207e +SHA1 (NetBSD-6.0/x68k/INSTALL.more) = 9771b22f8b8b9a5a3ad2aead71a06bccd63caae8 +SHA512 (NetBSD-6.0/x68k/INSTALL.more) = 4f3561d62f5d3a6f1f936d476d783dca2d4caaa50e21d8571ac795a8f3a06ad10f490d02b05ae8e51ed3e6eeb7aba645215339632aa61c99b93c4c4b37ee5329 +RMD160 (NetBSD-6.0/x68k/INSTALL.more) = a8994368a67cb7bd6df0232815e6c21a1a69537b +MD5 (NetBSD-6.0/x68k/INSTALL.more) = 13d4f52ad2a72fc92e24c1467463be66 +SHA1 (NetBSD-6.0/x68k/INSTALL.ps) = 3dfb26b142ddfa2771a49a371bcbf72cacd74f7c +SHA512 (NetBSD-6.0/x68k/INSTALL.ps) = bc12356b462b30559d05d0ce0ccc73f07fda3f5575121bf2911db6c638375416e4a79364f7727ea1adef19ed2679e86600c960585e9ef7899ed583d630655b20 +RMD160 (NetBSD-6.0/x68k/INSTALL.ps) = f46789b092425a148d38cae66d987253e12efecd +MD5 (NetBSD-6.0/x68k/INSTALL.ps) = 34b1b9c1a6ef25bb677408f0a869ed52 +SHA1 (NetBSD-6.0/x68k/INSTALL.txt) = 7371dc6f22eece4157c00dfb01f59a035f305da6 +SHA512 (NetBSD-6.0/x68k/INSTALL.txt) = 600911e35b9c641ee4315452cc4b534e844695af852328eec243632f462b0685acad59f35588c46d5c083f745ea5c1ab1df32e8e4f2307409dc5dd8cdafe110c +RMD160 (NetBSD-6.0/x68k/INSTALL.txt) = 8f3c307f17b591859a241414a6a0f33f592e811a +MD5 (NetBSD-6.0/x68k/INSTALL.txt) = 6bd22ee53bf58cae2454a2f8627718f9 +SHA1 (NetBSD-6.0/zaurus/binary/kernel/netbsd-GENERIC.gz) = 7f4cbcd7d5390357b1873da969b0a7cca60e73c1 +SHA512 (NetBSD-6.0/zaurus/binary/kernel/netbsd-GENERIC.gz) = 0c552ce725209b5686341ac0101cb7969a5a43ab8ba5d1b9a540fa07979e93921acfca844622ee00f5be4d3b06598ef4750772767b72b754e5cae22735ec24e1 +RMD160 (NetBSD-6.0/zaurus/binary/kernel/netbsd-GENERIC.gz) = 2ba59423e410d54f3a829f2ce9e5bcbd43b5b840 +MD5 (NetBSD-6.0/zaurus/binary/kernel/netbsd-GENERIC.gz) = 4cd87eddf3285a67e0f463d4896db002 +SHA1 (NetBSD-6.0/zaurus/binary/kernel/netbsd-C700.gz) = 01cc33fb982cd5f2b188d4688147750a94863fe2 +SHA512 (NetBSD-6.0/zaurus/binary/kernel/netbsd-C700.gz) = ceac21a76cc922a67cbf4d8cc83f471015d36d0896efabbf232ebec9217a3d56f8cea43f3e1c22bc527b32be5179898822807a041ef418e3fd6ff942d09dbac7 +RMD160 (NetBSD-6.0/zaurus/binary/kernel/netbsd-C700.gz) = 781cc21ea042587fe9f4c0fe9305ae159f5a15e5 +MD5 (NetBSD-6.0/zaurus/binary/kernel/netbsd-C700.gz) = 95bcd094f576b6f49e7a1bdbb5048a13 +SHA1 (NetBSD-6.0/zaurus/binary/sets/games.tgz) = e1d2bb091d8202962133475bc83edb55230b9008 +SHA512 (NetBSD-6.0/zaurus/binary/sets/games.tgz) = a147fe6d0419d53d5a428802d0bb6c9fa8a84a76c96d7d6d7c0d399e5af3a69240116463549a83d53387b0214ba0207796d7c10228d92a684fe7ff0ece3aec16 +RMD160 (NetBSD-6.0/zaurus/binary/sets/games.tgz) = 2be515c495548ba5135ff42a75a8ebbfc35ea776 +MD5 (NetBSD-6.0/zaurus/binary/sets/games.tgz) = 9059a6f2cd41cb58827709c9e9a1649b +SHA1 (NetBSD-6.0/zaurus/binary/sets/man.tgz) = 899b9d8242e983a5110ab755651c24f709b5af67 +SHA512 (NetBSD-6.0/zaurus/binary/sets/man.tgz) = 410999db110d710f4bb498c3d7ae7adc62170c7c2f470ce189c92f6c436c5ea96149659c631ef0b5605caaa025d97dfe1c07c428d86f51239657bd6b71717b15 +RMD160 (NetBSD-6.0/zaurus/binary/sets/man.tgz) = c1270f68c6d41b351877f71f0396ac34877dfc8d +MD5 (NetBSD-6.0/zaurus/binary/sets/man.tgz) = df4db2bbfa39ef6a4a215d949653d04a +SHA1 (NetBSD-6.0/zaurus/binary/sets/misc.tgz) = 982918d46b2da2693dded747147baed27160d325 +SHA512 (NetBSD-6.0/zaurus/binary/sets/misc.tgz) = 54a45fa2bf5c57e3b63e23a95b6ca74f3b8e6b8f655715663ec5f83f713a9c6149b8b1ccc298dfa2eff9e81376f9f64107b35841cbd20ee62be6575539e01c81 +RMD160 (NetBSD-6.0/zaurus/binary/sets/misc.tgz) = 9c9161a1e855276c6aa3fe61de655dbea3ec9a43 +MD5 (NetBSD-6.0/zaurus/binary/sets/misc.tgz) = 7b0005d0512287e8a34e24c043582fb8 +SHA1 (NetBSD-6.0/zaurus/binary/sets/xcomp.tgz) = 8d7469a85b7433c89690cce74e6b3f4e66cf0647 +SHA512 (NetBSD-6.0/zaurus/binary/sets/xcomp.tgz) = 411304cf66e300a7f162128203099bb4d6eebc4a93ba18ed7caf79f30b31cc7ffcede85c4e1bad02c3f5f8a27d009fb71f3ce5862c1d8aa477f39a25c535fdaa +RMD160 (NetBSD-6.0/zaurus/binary/sets/xcomp.tgz) = 822d26e0ee08b72ca8b991f0709a8c1bf0399208 +MD5 (NetBSD-6.0/zaurus/binary/sets/xcomp.tgz) = 5af361f0334d28119d703064278b3ed3 +SHA1 (NetBSD-6.0/zaurus/binary/sets/xetc.tgz) = 222d14c205f1018cc5a86eb03214d18cda2abb82 +SHA512 (NetBSD-6.0/zaurus/binary/sets/xetc.tgz) = fb82261996aa772fd8a9022eadebf899ee04ee70229ee4fe07758ca14937bdb34752c8218eb4c5b722b6208f719891493bbc141372fcfa503de83e0a61aa7387 +RMD160 (NetBSD-6.0/zaurus/binary/sets/xetc.tgz) = 511ebfe5076f361b7f7ca03a265d16052a16d259 +MD5 (NetBSD-6.0/zaurus/binary/sets/xetc.tgz) = 165cffbb6d2c79663198d80c82afac1e +SHA1 (NetBSD-6.0/zaurus/binary/sets/xfont.tgz) = ce0e141beeffeb5b470478e9887e4127da85de3c +SHA512 (NetBSD-6.0/zaurus/binary/sets/xfont.tgz) = 5d98354ff77103793d56af3192ab5f9afcde62208791976064ac33a149f994e0227dd5dd28ed544eeac5ea504e5212d5fb9e7d05e59e5a48a2fe4062e34e3106 +RMD160 (NetBSD-6.0/zaurus/binary/sets/xfont.tgz) = 4d09f5e82fec875ef0ea328809465e7a98f2ebfc +MD5 (NetBSD-6.0/zaurus/binary/sets/xfont.tgz) = be26b3890261302420b09976a1d38144 +SHA1 (NetBSD-6.0/zaurus/binary/sets/kern-C700.tgz) = 645cc6b6c3250ead1e2e121bcc179be2e9056b65 +SHA512 (NetBSD-6.0/zaurus/binary/sets/kern-C700.tgz) = 833883cb8aada6c391917ec890282011d2cfa6c5068d9483ab1b8c9b74361baa093b1c6b074dd5cd89709eb67636cbba1a6be292c23b28b8ff7578194c427263 +RMD160 (NetBSD-6.0/zaurus/binary/sets/kern-C700.tgz) = 0867bac200dd8bd12d1c4d225d392a175e06f24a +MD5 (NetBSD-6.0/zaurus/binary/sets/kern-C700.tgz) = d1c5388985d5693d492ec75713ef3ccd +SHA1 (NetBSD-6.0/zaurus/binary/sets/base.tgz) = fcee164dc5d4cd72f3c9841b7c7fbe295c4b3e6a +SHA512 (NetBSD-6.0/zaurus/binary/sets/base.tgz) = 910606c4dedf523e5db213165fd5a244a655a40a7c4686e7a8e80f015d8ca496a1770b1a94532e118ad7cb4d2f4cfd0abb4e07560e0507275b4a27fefa3fb8af +RMD160 (NetBSD-6.0/zaurus/binary/sets/base.tgz) = c1f5fb6f7b18486f08cacbf1ea6cef5d852a3b4d +MD5 (NetBSD-6.0/zaurus/binary/sets/base.tgz) = e646c1da6b4ca9c38607d97cbbb6871a +SHA1 (NetBSD-6.0/zaurus/binary/sets/comp.tgz) = 9af4ccb1edd8eea77f32d50aad4592c483bc41bc +SHA512 (NetBSD-6.0/zaurus/binary/sets/comp.tgz) = b3eecf648f57fcc3af7ed707bf7f584db4aff71b7755986652e80e2a11e83b7a663263800f143d4dfe668bff0dd606f7733f1ae36be132f70c888a45e210d14c +RMD160 (NetBSD-6.0/zaurus/binary/sets/comp.tgz) = ef64fdf6c3e118e4aab5264d457278d625408275 +MD5 (NetBSD-6.0/zaurus/binary/sets/comp.tgz) = c22150f0e6684dc1d64fef0abf882dec +SHA1 (NetBSD-6.0/zaurus/binary/sets/etc.tgz) = 04a520449ff803fefaf80b0beaee929122d9a5bd +SHA512 (NetBSD-6.0/zaurus/binary/sets/etc.tgz) = a109dffb85cd44758b30a9fd7b5eeb0e68b43babb96984974662ede674c4e4b06cddfdb84fd4377cdcf66944506547585f2e4e1fde1dd2c6ba0c823fec5af6e7 +RMD160 (NetBSD-6.0/zaurus/binary/sets/etc.tgz) = 1412ce7fbadb5bc2a7ea54662dc5af065a52fd06 +MD5 (NetBSD-6.0/zaurus/binary/sets/etc.tgz) = fdcf4276a2adc8bc6b8899a0f92827b2 +SHA1 (NetBSD-6.0/zaurus/binary/sets/kern-GENERIC.tgz) = 5a4db67f97cbf15dfa86f3d1bdd1e0fbf45cf2c3 +SHA512 (NetBSD-6.0/zaurus/binary/sets/kern-GENERIC.tgz) = d47f1b328c845abe0a131e5fec333a5badbbde60e1abb1c2a01032128350ae33a69df720f9a5a944e93a9c29e04b669f530d7d4b803d9262edef1ce8953099d9 +RMD160 (NetBSD-6.0/zaurus/binary/sets/kern-GENERIC.tgz) = 57cc4468fe4f292c4798dcaf7c7ee8b6a79c72cd +MD5 (NetBSD-6.0/zaurus/binary/sets/kern-GENERIC.tgz) = 7b6a87debe65e4d987181b2a600a0cc9 +SHA1 (NetBSD-6.0/zaurus/binary/sets/modules.tgz) = 97cf73286143f2ee9d1d75d291226b14382bc3e9 +SHA512 (NetBSD-6.0/zaurus/binary/sets/modules.tgz) = 819d952342aedefae4120c8b0f3aa362089528ea9a604479b4242154b52e76688353386c6c6fe7f675086997459a1038f74037840642d4d522145be09d13b01c +RMD160 (NetBSD-6.0/zaurus/binary/sets/modules.tgz) = 1c5ade56f427ccb12d516da4b60266496a0dbe7f +MD5 (NetBSD-6.0/zaurus/binary/sets/modules.tgz) = fdf54f31acaaf41ae7e04155dc2ed8e3 +SHA1 (NetBSD-6.0/zaurus/binary/sets/tests.tgz) = d267f0e6d994c769d85698d5fe84dc84d3eb0aea +SHA512 (NetBSD-6.0/zaurus/binary/sets/tests.tgz) = 400bcfd917639182daf83eddf20aa476be42285c8c5fdeb187b5086c7c00b0ebf2a0aa7badb7f4e1e43e70f43c46972003a4e6b4dd95eb5b7d621e2f8a562623 +RMD160 (NetBSD-6.0/zaurus/binary/sets/tests.tgz) = b8578e18377c21e4f0bc5509eddaacca4e439849 +MD5 (NetBSD-6.0/zaurus/binary/sets/tests.tgz) = ae201c948e67c3c74b0f5f89dde362ce +SHA1 (NetBSD-6.0/zaurus/binary/sets/text.tgz) = 3467c94a0c6bcd54efe8849c282fa26f9f02624a +SHA512 (NetBSD-6.0/zaurus/binary/sets/text.tgz) = 0f24772a93aa15de7b2a40e237ea5efeb0f701a6c3645b7add0e478bfcfb3d3050a74d80b1328eb821591ee0464e051572f2afa6bb2935d34ae369809546cf65 +RMD160 (NetBSD-6.0/zaurus/binary/sets/text.tgz) = 6acb227a392a29ef30d17e861ec681c56da75790 +MD5 (NetBSD-6.0/zaurus/binary/sets/text.tgz) = b4ed717b1487f24bf1768305e0c0065d +SHA1 (NetBSD-6.0/zaurus/binary/sets/xbase.tgz) = 8b5a46ee79d9bffd6d6eb0af06ff3928029b7a92 +SHA512 (NetBSD-6.0/zaurus/binary/sets/xbase.tgz) = c675ab7e92391becf93b9894115e5149b1ef4b4cb9b2f41a58a12c0009c8c1999de4aa8e239f82308c5892accac5cbbe0a3d380f30134bec29b433a5357d1cfc +RMD160 (NetBSD-6.0/zaurus/binary/sets/xbase.tgz) = 81d52af994bb130ce57e83468b7ce350f107f3bd +MD5 (NetBSD-6.0/zaurus/binary/sets/xbase.tgz) = 02cd86601f44cd4ba11e466236b04e1d +SHA1 (NetBSD-6.0/zaurus/binary/sets/xserver.tgz) = e293d1143593154074951807e155c8e87adff50a +SHA512 (NetBSD-6.0/zaurus/binary/sets/xserver.tgz) = 060d8e60ec568aebafef85ab34b527dafe11516ef5761598e2ba79e5e7994cd4f710812e857fd20bb1e09b0df5692ef1e10949273027c66ce2255e2b15f78132 +RMD160 (NetBSD-6.0/zaurus/binary/sets/xserver.tgz) = 8ea704c20eb2aafb79603904423f7e137136ef4e +MD5 (NetBSD-6.0/zaurus/binary/sets/xserver.tgz) = f8d5d948e6ccb12094636c6d4106f895 +SHA1 (NetBSD-6.0/zaurus/installation/kernel/netbsd-INSTALL_C700) = 08e381ea42ccb632460555771fd7fe6bae057a24 +SHA512 (NetBSD-6.0/zaurus/installation/kernel/netbsd-INSTALL_C700) = de5d9f71284b987f67077a0fcf2273d11418b73108ada25e4807614752eea38d58b8d32c53e86293a0492d05a842e81f44e5e5e5bdf3f0ca76e440263becd5ff +RMD160 (NetBSD-6.0/zaurus/installation/kernel/netbsd-INSTALL_C700) = 91c741493cd043610e542d01a4cde6ed30469be3 +MD5 (NetBSD-6.0/zaurus/installation/kernel/netbsd-INSTALL_C700) = 5544b1f0b4a87402fc0fc5951aa303ae +SHA1 (NetBSD-6.0/zaurus/installation/kernel/netbsd-INSTALL) = a54eadb65290c45af5e6ae4d0cb0b803640fa2b0 +SHA512 (NetBSD-6.0/zaurus/installation/kernel/netbsd-INSTALL) = e78fc99a17c732908af345a40f102ae8eef248f4c5c3a4fad85a8e9d497346f86b65096e816aba26975a71780672040c148f40fc4879cf0b6f5d5ec7f6aa34af +RMD160 (NetBSD-6.0/zaurus/installation/kernel/netbsd-INSTALL) = e0bde1431f7c4b3f649b2721c0c38f02ad273bc3 +MD5 (NetBSD-6.0/zaurus/installation/kernel/netbsd-INSTALL) = 02bd814abd9951fec27c269ddefb6346 +SHA1 (NetBSD-6.0/zaurus/installation/zbsdmod.o) = 6f5a55fa2497fac0ae75f20df2074eaedde0aa0c +SHA512 (NetBSD-6.0/zaurus/installation/zbsdmod.o) = 46e48ce8f3e637b5e708a066847e2f7449c8134f8f8d327e3ace9116cae4fc7b77aeee136cb797e00000277c4d224dcb10d946aff983be3292690580ba666b8b +RMD160 (NetBSD-6.0/zaurus/installation/zbsdmod.o) = b96bdc9f3009ddb56d5b4b05e01e2cc3862a9e11 +MD5 (NetBSD-6.0/zaurus/installation/zbsdmod.o) = 49e746ab92af22b281d4c15eecf85c10 +SHA1 (NetBSD-6.0/zaurus/installation/zboot) = 142512f9c4e5a1a3762dc5b96416392a19fba367 +SHA512 (NetBSD-6.0/zaurus/installation/zboot) = 30520adab63612d4cf76919b21d2262235d3e2996c5a308f050e480acee5f544aad94993e53cd1e7490ef054b2fecfab7db0483ca1f9c045287debeedd84300e +RMD160 (NetBSD-6.0/zaurus/installation/zboot) = ebd6148f2ed15ea48fd7a2f2a273136661287134 +MD5 (NetBSD-6.0/zaurus/installation/zboot) = da83febbb31821d4b68c07a9c9487946 +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v1.4.11 (NetBSD) + +iQIcBAEBAgAGBQJQfDnGAAoJEAZJc6xMSnBuq9AP/1n7mninneKOiCjD5RTtdS96 +sjxa7DbX1xd8ZIL+klchZurlqqKeBdk63gALDo6VpAsSbNH45R0Ib9rzvJiwSkRK +7PHPqijtxgACFV4UclrUXWts+Px6AS8QxMfuLgRwu0KETYMnuR8Ghp9YD6xIGqaw +kG5Pfnqs2qWi9Q/70uTlmJgl3iEj/KStdDyxcmH2VlejtAGxJxqVVwQ6XpAu5z1Z +OVMmoZoReFeDiTZAydf0VzvwyfmHuPvXKfO8Z+PhkFboAUfuIKIO8DfljQ7A5OBp +oEEK1nnjeac59KWPAvI4IbXfVuC1o2rEYmLHz9vBxHKiPf9SxL4XjNbZozejXsMD +h1NWWt4q6nD4nGQaOPyR4afN0ZWluC+6cASQ+Srmr/0QJbsBwgtXuKza2vwNs0iC +IF80PL1iPjDPmf1CQnOZqJktUfv4aeAcwNs8oiq+toIlgOkIwCzFQFjflny9pRKp +/YOxwFY8izCb6pu0/3LM2CSutwDEkR7I6aAn65BFW0ia6Ty5azf9iIFOAIbzefkH +AP1CJKn36vgtcny/R9KueIw/50Hok2rrFrDqzC8mMq5j3Pletm/4equmVu27e+uc +0jTiNwCHb6ZvuoO7d1clrIEEJPEXe66Xcmj9iJzo+Ai1nhCj1BDNZnj9zHbIwPIQ +6yQgxCHP9Ney/0j1V+sF +=nHXc +-----END PGP SIGNATURE----- +EOF + cat > expected16 << EOF +Good signature for b.gpg made Mon Sep 10 00:15:38 2012 +signature 2048/RSA (Encrypt or Sign) 1b68dcfcc0596823 2004-01-12 +fingerprint: d415 9deb 336d e4cc cdfa 00cd 1b68 dcfc c059 6823 +uid Alistair Crooks +uid Alistair Crooks +uid Alistair Crooks +uid Alistair Crooks +encryption 2048/RSA (Encrypt or Sign) 79deb61e488eee74 2004-01-12 +fingerprint: 57c0 c1e6 bf71 8845 416b 9522 79de b61e 488e ee74 + +EOF + cat >expected17 < +uid Alistair Crooks +uid Alistair Crooks +uid Alistair Crooks +encryption 2048/RSA (Encrypt or Sign) 79deb61e488eee74 2004-01-12 +fingerprint: 57c0 c1e6 bf71 8845 416b 9522 79de b61e 488e ee74 + +EOF + cat >expected18 < +uid Alistair Crooks +uid Alistair Crooks +uid Alistair Crooks +encryption 2048/RSA (Encrypt or Sign) 79deb61e488eee74 2004-01-12 +fingerprint: 57c0 c1e6 bf71 8845 416b 9522 79de b61e 488e ee74 + +EOF + cat >expected19 < +encryption 4096/RSA (Encrypt or Sign) 9ff2c24fdf2ce620 2009-06-23 [Expiry 2019-06-21] +fingerprint: 1915 0801 fbd8 f45d 89f2 0205 9ff2 c24f df2c e620 + +EOF + cat >expected20 <expected21 < +uid Alistair Crooks +uid Alistair Crooks +uid Alistair Crooks +encryption 2048/RSA (Encrypt or Sign) 79deb61e488eee74 2004-01-12 +fingerprint: 57c0 c1e6 bf71 8845 416b 9522 79de b61e 488e ee74 + +EOF + cat >expected22 < +uid Alistair Crooks +uid Alistair Crooks +uid Alistair Crooks +encryption 2048/RSA (Encrypt or Sign) 79deb61e488eee74 2004-01-12 +fingerprint: 57c0 c1e6 bf71 8845 416b 9522 79de b61e 488e ee74 + +EOF + cat >expected23 < +encryption 4096/RSA (Encrypt or Sign) 9ff2c24fdf2ce620 2009-06-23 [Expiry 2019-06-21] +fingerprint: 1915 0801 fbd8 f45d 89f2 0205 9ff2 c24f df2c e620 + +EOF + cat >expected24 < +uid Alistair Crooks +uid Alistair Crooks +uid Alistair Crooks +encryption 2048/RSA (Encrypt or Sign) 79deb61e488eee74 2004-01-12 +fingerprint: 57c0 c1e6 bf71 8845 416b 9522 79de b61e 488e ee74 + +EOF + cat >expected25 < +encryption 4096/RSA (Encrypt or Sign) 9ff2c24fdf2ce620 2009-06-23 [Expiry 2019-06-21] +fingerprint: 1915 0801 fbd8 f45d 89f2 0205 9ff2 c24f df2c e620 + +EOF + cat >expected26 < +encryption 4096/RSA (Encrypt or Sign) 9ff2c24fdf2ce620 2009-06-23 [Expiry 2019-06-21] +fingerprint: 1915 0801 fbd8 f45d 89f2 0205 9ff2 c24f df2c e620 + +EOF + cat >expected27 < +encryption 4096/RSA (Encrypt or Sign) 9ff2c24fdf2ce620 2009-06-23 [Expiry 2019-06-21] +fingerprint: 1915 0801 fbd8 f45d 89f2 0205 9ff2 c24f df2c e620 + +EOF + cat >expected28 < +encryption 4096/RSA (Encrypt or Sign) 9ff2c24fdf2ce620 2009-06-23 [Expiry 2019-06-21] +fingerprint: 1915 0801 fbd8 f45d 89f2 0205 9ff2 c24f df2c e620 + +EOF + cat >expected29 < +encryption 4096/RSA (Encrypt or Sign) 9ff2c24fdf2ce620 2009-06-23 [Expiry 2019-06-21] +fingerprint: 1915 0801 fbd8 f45d 89f2 0205 9ff2 c24f df2c e620 + +EOF + cat >expected30 < +encryption 4096/RSA (Encrypt or Sign) 9ff2c24fdf2ce620 2009-06-23 [Expiry 2019-06-21] +fingerprint: 1915 0801 fbd8 f45d 89f2 0205 9ff2 c24f df2c e620 + +EOF + uudecode <expected32 < +uid Alistair Crooks +uid Alistair Crooks +uid Alistair Crooks +encryption 2048/RSA (Encrypt or Sign) 79deb61e488eee74 2004-01-12 +fingerprint: 57c0 c1e6 bf71 8845 416b 9522 79de b61e 488e ee74 + +Good signature for b.gpg made Mon Sep 10 00:15:38 2012 +signature 2048/RSA (Encrypt or Sign) 1b68dcfcc0596823 2004-01-12 +fingerprint: d415 9deb 336d e4cc cdfa 00cd 1b68 dcfc c059 6823 +uid Alistair Crooks +uid Alistair Crooks +uid Alistair Crooks +uid Alistair Crooks +encryption 2048/RSA (Encrypt or Sign) 79deb61e488eee74 2004-01-12 +fingerprint: 57c0 c1e6 bf71 8845 416b 9522 79de b61e 488e ee74 + +Good signature for b.gpg made Mon Sep 10 00:15:38 2012 +signature 2048/RSA (Encrypt or Sign) 1b68dcfcc0596823 2004-01-12 +fingerprint: d415 9deb 336d e4cc cdfa 00cd 1b68 dcfc c059 6823 +uid Alistair Crooks +uid Alistair Crooks +uid Alistair Crooks +uid Alistair Crooks +encryption 2048/RSA (Encrypt or Sign) 79deb61e488eee74 2004-01-12 +fingerprint: 57c0 c1e6 bf71 8845 416b 9522 79de b61e 488e ee74 + +EOF + uudecode <expected34 < +uid Alistair Crooks +uid Alistair Crooks +uid Alistair Crooks +encryption 2048/RSA (Encrypt or Sign) 79deb61e488eee74 2004-01-12 +fingerprint: 57c0 c1e6 bf71 8845 416b 9522 79de b61e 488e ee74 + +EOF + cat >expected35 < in1.asc << EOF +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA256 + +# .NetBSD: Makefile,v 1.5.10.1 2012/05/06 18:14:16 agc Exp . + +SUBDIR+= lib .WAIT +SUBDIR+= bin + +.include +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v1.4.11 (NetBSD) + +iF4EAREIAAYFAlCFMdYACgkQJj/nhWLi/H7CkQEAgDQrFwPD76JC+6FnOKEz/9DP +H7WjRRMoIQNTGC3ZXRsA/1xah8eFePQDmTO1sQGnINbgX9vZ7GAFOgTjW7+tVb7H +=wtKb +-----END PGP SIGNATURE----- +EOF + uudecode << EOF +begin-base64 644 in2.gpg +owGbwMvMwCGoZv+8NenRnzrGNU1JzJl5RgGtHj+VOfX8Ukucgl2sFHwTs1PTMnNS +dcoUDPVM9QwN9AwVjAwMjfQNTPUNzBQMLawMTawMzRQS05MVXCsKFPQUuLiCQ51c +PIO0bTlzMpMU9MIdPUMQQkmZeVxcepl5yTmlKakKNknFKXrFpUkpmUV6udl2XB1x +LAyCHAxsrEwgZzBwcQrAnFfzjeGv9GtuvQj7X/Kv5IQ8f2s9n/36yaOmu9HPs8/V +8pg+SdfaxMhwdEOjtLVOGtuaizmXnJ8oa4fN/bfL0WfP1smOn38vsLFlBQA= +==== +EOF + cat > in2.asc << EOF +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA256 + +# .NetBSD: Makefile,v 1.5.10.1 2012/05/06 18:14:16 agc Exp . + +SUBDIR+= lib .WAIT +SUBDIR+= bin + +.include +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v1.4.11 (NetBSD) + +iF4EAREIAAYFAlCFSQoACgkQJj/nhWLi/H6aKAD9HCLTwY8CwiqTXrzKxHZ5lHQn +qEZbcbXjkCxlk+m/PHUA/2Whlc0t5ZtmI221LQy5inTnzpu1U75E5lJvw0YMTdXJ +=v788 +-----END PGP SIGNATURE----- +EOF + cat > expected36 << EOF +Good signature for in1.gpg made Mon Oct 22 04:45:41 2012 +signature 2048/DSA 263fe78562e2fc7e 2012-10-21 +fingerprint: d2e5 07b6 5d59 33d3 9c8d a618 263f e785 62e2 fc7e +uid David Armstrong (Test DSA key - do not use) +encryption 2048/Elgamal (Encrypt Only) 53d1f21240f293c6 2012-10-21 [Expiry 2014-10-21] +fingerprint: 6a83 d4aa 791f d8af a967 5e44 53d1 f212 40f2 93c6 + +EOF + cat >expected37 < +encryption 2048/Elgamal (Encrypt Only) 53d1f21240f293c6 2012-10-21 [Expiry 2014-10-21] +fingerprint: 6a83 d4aa 791f d8af a967 5e44 53d1 f212 40f2 93c6 + +EOF + cat >expected38 < +encryption 2048/Elgamal (Encrypt Only) 53d1f21240f293c6 2012-10-21 [Expiry 2014-10-21] +fingerprint: 6a83 d4aa 791f d8af a967 5e44 53d1 f212 40f2 93c6 + +EOF + cat >expected39 < +encryption 2048/Elgamal (Encrypt Only) 53d1f21240f293c6 2012-10-21 [Expiry 2014-10-21] +fingerprint: 6a83 d4aa 791f d8af a967 5e44 53d1 f212 40f2 93c6 + +EOF + cat >expected40 < +EOF + cat >expected41 < +EOF + cat >expected42 < +EOF + cat >expected43 < +EOF + cat >expected44 < +encryption 2048/Elgamal (Encrypt Only) 53d1f21240f293c6 2012-10-21 [Expiry 2014-10-21] +fingerprint: 6a83 d4aa 791f d8af a967 5e44 53d1 f212 40f2 93c6 + +EOF + cat >expected45 < +encryption 2048/Elgamal (Encrypt Only) 53d1f21240f293c6 2012-10-21 [Expiry 2014-10-21] +fingerprint: 6a83 d4aa 791f d8af a967 5e44 53d1 f212 40f2 93c6 + +EOF + cat >expected46 < +encryption 4096/RSA (Encrypt or Sign) 9ff2c24fdf2ce620 2009-06-23 [Expiry 2019-06-21] +fingerprint: 1915 0801 fbd8 f45d 89f2 0205 9ff2 c24f df2c e620 + +EOF + atf_check -s eq:0 -o file:expected36 -e empty env TZ=US/Pacific netpgpverify -k dsa-pubring.gpg in1.gpg + atf_check -s eq:0 -o file:expected37 -e empty env TZ=US/Pacific netpgpverify -k dsa-pubring.gpg < in1.gpg + atf_check -s eq:0 -o file:expected38 -e empty env TZ=US/Pacific netpgpverify -k dsa-pubring.gpg in1.asc + atf_check -s eq:0 -o file:expected39 -e empty env TZ=US/Pacific netpgpverify -k dsa-pubring.gpg < in1.asc + atf_check -s eq:0 -o file:expected40 -e empty env TZ=US/Pacific netpgpverify -k dsa-pubring.gpg -c cat in1.gpg + atf_check -s eq:0 -o file:expected41 -e empty env TZ=US/Pacific netpgpverify -k dsa-pubring.gpg -c cat < in1.gpg + atf_check -s eq:0 -o file:expected42 -e empty env TZ=US/Pacific netpgpverify -k dsa-pubring.gpg -c cat in1.asc + atf_check -s eq:0 -o file:expected43 -e empty env TZ=US/Pacific netpgpverify -k dsa-pubring.gpg -c cat < in1.asc + atf_check -s eq:0 -o file:expected44 -e empty env TZ=US/Pacific netpgpverify -k dsa-pubring.gpg in2.gpg + atf_check -s eq:0 -o file:expected45 -e empty env TZ=US/Pacific netpgpverify -k dsa-pubring.gpg in2.asc +} + +atf_init_test_cases() { + atf_add_test_case netpgpverify_rsa + atf_add_test_case netpgpverify_dsa +} diff --git a/tests/usr.bin/pr/Makefile b/tests/usr.bin/pr/Makefile new file mode 100644 index 000000000..16272823b --- /dev/null +++ b/tests/usr.bin/pr/Makefile @@ -0,0 +1,13 @@ +# $NetBSD: Makefile,v 1.2 2011/05/03 14:11:51 jruoho Exp $ + +.include + +TESTSDIR= ${TESTSBASE}/usr.bin/pr + +TESTS_SH= t_basic + +FILESDIR= ${TESTSDIR} +FILES+= d_basic.in +FILES+= d_basic.out + +.include diff --git a/tests/usr.bin/pr/d_basic.in b/tests/usr.bin/pr/d_basic.in new file mode 100644 index 000000000..4e36f6e5f --- /dev/null +++ b/tests/usr.bin/pr/d_basic.in @@ -0,0 +1,2 @@ +123 456 789 +abc def ghi diff --git a/tests/usr.bin/pr/d_basic.out b/tests/usr.bin/pr/d_basic.out new file mode 100644 index 000000000..e187104a4 --- /dev/null +++ b/tests/usr.bin/pr/d_basic.out @@ -0,0 +1 @@ +123 456 789 abc def ghi diff --git a/tests/usr.bin/pr/t_basic.sh b/tests/usr.bin/pr/t_basic.sh new file mode 100644 index 000000000..6bd80dd21 --- /dev/null +++ b/tests/usr.bin/pr/t_basic.sh @@ -0,0 +1,46 @@ +# $NetBSD: t_basic.sh,v 1.4 2012/03/13 05:40:00 jruoho Exp $ +# +# Copyright (c) 2011 The NetBSD Foundation, Inc. +# All rights reserved. +# +# This code is derived from software contributed to The NetBSD Foundation +# by Jukka Ruohonen. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +atf_test_case basic +basic_head() { + atf_set "descr" "A basic test of pr(1) (cf. PR bin/41880)" +} + +basic_body() { + + # The output file was generated with "pr (GNU coreutils) 6.10". + # + atf_check -s ignore -o file:$(atf_get_srcdir)/d_basic.out \ + -x "pr -t -2 $(atf_get_srcdir)/d_basic.in" +} + +atf_init_test_cases() { + atf_add_test_case basic +} diff --git a/tests/usr.bin/rump_server/Makefile b/tests/usr.bin/rump_server/Makefile new file mode 100644 index 000000000..9a95464d2 --- /dev/null +++ b/tests/usr.bin/rump_server/Makefile @@ -0,0 +1,10 @@ +# $NetBSD: Makefile,v 1.1 2011/02/03 15:38:18 pooka Exp $ +# + +.include + +TESTSDIR= ${TESTSBASE}/usr.bin/rump_server + +TESTS_SH= t_disk + +.include diff --git a/tests/usr.bin/rump_server/t_disk.sh b/tests/usr.bin/rump_server/t_disk.sh new file mode 100644 index 000000000..bf1e7e1b9 --- /dev/null +++ b/tests/usr.bin/rump_server/t_disk.sh @@ -0,0 +1,130 @@ +# $NetBSD: t_disk.sh,v 1.5 2013/02/19 21:08:25 joerg Exp $ +# +# Copyright (c) 2011 The NetBSD Foundation, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +server='rump_server -lrumpvfs' +export RUMP_SERVER='unix://commsock' + +startsrv() +{ + + atf_check -s exit:0 ${server} $@ ${RUMP_SERVER} +} + +test_case() +{ + local name="${1}"; shift + + atf_test_case "${name}" cleanup + eval "${name}_head() { \ + atf_set "require.progs" "rump_server" ; \ + }" + eval "${name}_body() { \ + ${name}_prefun ; \ + startsrv $@ ; \ + ${name} ; \ + }" + eval "${name}_cleanup() { \ + [ -f halted ] && return 0 ; rump.halt ; + }" +} + +test_case size -d key=/img,hostpath=the.img,size=32k +size() +{ + atf_check -s exit:0 -o inline:'32768\n' stat -f %z the.img +} + +test_case offset -d key=/img,hostpath=the.img,size=32k,offset=16k +offset() +{ + atf_check -s exit:0 -o inline:'49152\n' stat -f %z the.img +} + +test_case notrunc -d key=/img,hostpath=the.img,size=8k,offset=16k +notrunc_prefun() +{ + dd if=/dev/zero of=the.img bs=1 oseek=65535 count=1 +} +notrunc() +{ + atf_check -s exit:0 -o inline:'65536\n' stat -f %z the.img +} + +test_case data -d key=/img,hostpath=the.img,size=8k,offset=16k +data() +{ + echo 'test string' | dd of=testfile ibs=512 count=1 conv=sync + atf_check -s exit:0 -e ignore -x \ + "dd if=testfile | rump.dd of=/img bs=512 count=1" + + # cheap fsync + atf_check -s exit:0 rump.halt + touch halted + atf_check -s exit:0 -e ignore -o file:testfile \ + dd if=the.img iseek=16k bs=1 count=512 +} + +test_case type_chr -d key=/img,hostpath=the.img,size=32k,type=chr +type_chr() +{ + atf_check -s exit:0 -o inline:'Character Device\n' \ + env LD_PRELOAD=/usr/lib/librumphijack.so stat -f %HT /rump/img +} + +test_case type_reg -d key=/img,hostpath=the.img,size=32k,type=reg +type_reg() +{ + atf_check -s exit:0 -o inline:'Regular File\n' \ + env LD_PRELOAD=/usr/lib/librumphijack.so stat -f %HT /rump/img +} + +test_case type_blk -d key=/img,hostpath=the.img,size=32k,type=blk +type_blk() +{ + atf_check -s exit:0 -o inline:'Block Device\n' \ + env LD_PRELOAD=/usr/lib/librumphijack.so stat -f %HT /rump/img +} + +test_case type_blk_default -d key=/img,hostpath=the.img,size=32k +type_blk_default() +{ + atf_check -s exit:0 -o inline:'Block Device\n' \ + env LD_PRELOAD=/usr/lib/librumphijack.so stat -f %HT /rump/img +} + +atf_init_test_cases() +{ + + atf_add_test_case size + atf_add_test_case offset + atf_add_test_case notrunc + atf_add_test_case data + atf_add_test_case type_chr + atf_add_test_case type_reg + atf_add_test_case type_blk + atf_add_test_case type_blk_default +} diff --git a/tests/usr.bin/sdiff/Makefile b/tests/usr.bin/sdiff/Makefile new file mode 100644 index 000000000..10ec5bfba --- /dev/null +++ b/tests/usr.bin/sdiff/Makefile @@ -0,0 +1,39 @@ +# $NetBSD: Makefile,v 1.1 2012/03/17 16:33:15 jruoho Exp $ + +NOMAN= # defined + +.include + +TESTSDIR= ${TESTSBASE}/usr.bin/sdiff + +TESTS_SH= t_sdiff + +FILESDIR= ${TESTSDIR} +FILES= d_dot.in +FILES+= d_flags_l.out +FILES+= d_flags_s.out +FILES+= d_flags_w.out +FILES+= d_iflags_a1.out +FILES+= d_iflags_a2.out +FILES+= d_iflags_b1.out +FILES+= d_iflags_b2.out +FILES+= d_iflags_c1.out +FILES+= d_iflags_c2.out +FILES+= d_iflags_d1.out +FILES+= d_iflags_d2.out +FILES+= d_input1 +FILES+= d_input2 +FILES+= d_oneline.in +FILES+= d_oneline_a.out +FILES+= d_oneline_b.out +FILES+= d_same.out +FILES+= d_short.out +FILES+= d_tabends.in +FILES+= d_tabends_a.out +FILES+= d_tabends_b.out +FILES+= d_tabends_c.out +FILES+= d_tabs.out +FILES+= d_tabs1.in +FILES+= d_tabs2.in + +.include diff --git a/tests/usr.bin/sdiff/d_dot.in b/tests/usr.bin/sdiff/d_dot.in new file mode 100644 index 000000000..9c558e357 --- /dev/null +++ b/tests/usr.bin/sdiff/d_dot.in @@ -0,0 +1 @@ +. diff --git a/tests/usr.bin/sdiff/d_flags_l.out b/tests/usr.bin/sdiff/d_flags_l.out new file mode 100644 index 000000000..c7afce0d9 --- /dev/null +++ b/tests/usr.bin/sdiff/d_flags_l.out @@ -0,0 +1,102 @@ +Policy: /usr/bin/lynx, Emulation: native + > native-issetugid: permit + > native-mprotect: permit + > native-mmap: permit + native-__sysctl: permit + > native-fsread: filename eq "/var/run/ld.so.hints" then perm + > native-fstat: permit + native-close: permit + native-connect: sockaddr eq "inet-[127.0.0.1]:53" then perm | native-fsread: filename match "/usr/lib/libssl.so.*" then p + native-connect: sockaddr match "inet-\\\[*\\\]:80" then per | native-read: permit + native-exit: permit | native-fsread: filename match "/usr/lib/libcrypto.so.*" the + native-fcntl: cmd eq "F_SETFD" then permit | native-fsread: filename match "/usr/lib/libncurses.so.*" th + native-fsread: filename eq "/" then permit | native-fsread: filename match "/usr/lib/libc.so.*" then per + native-fsread: filename match "/: *" | native-munmap: permit + native-fsread: filename eq "/etc/lynx.cfg" then permit | native-sigprocmask: permit + native-fsread: filename eq "/etc/malloc.conf" then permit + native-fsread: filename eq "/etc/resolv.conf" then permit | native-getpid: permit + native-fsread: filename eq "/etc/utmp" then permit < + native-fsread: filename eq "/home" then permit < + native-fsread: filename eq "$HOME" then permit < + native-fsread: filename eq "$HOME/.lynx-keymaps" then permi < + native-fsread: filename eq "$HOME/.lynxrc" then permit < + native-fsread: filename eq "$HOME/.mailcap" then permit < + native-fsread: filename eq "$HOME/.mime.types" then permit < + native-fsread: filename eq "$HOME/.terminfo" then permit < + native-fsread: filename eq "$HOME/.terminfo.db" then permit < + native-fsread: filename eq "/obj" then permit < + native-fsread: filename eq "/tmp" then permit + > native-fswrite: filename match "/tmp/lynx-*" then permit + native-fsread: filename match "/tmp/lynx-*/." then permit + > native-fsread: filename eq "$HOME" then permit + > native-fsread: filename eq "/etc/lynx.cfg" then permit + > native-fsread: filename eq "/" then permit + > native-fsread: filename eq "/usr/obj/bin/systrace/." then p + > native-fsread: filename eq "/usr/obj/bin" then permit + > native-fcntl: permit + > native-getdirentries: permit + > native-lseek: permit + > native-fsread: filename eq "/usr/obj" then permit + native-fsread: filename eq "/usr" then permit + native-fsread: filename eq "/usr/bin" then permit + native-fsread: filename eq "/usr/games" then permit + native-fsread: filename eq "/usr/include" then permit + native-fsread: filename eq "/usr/lib" then permit + native-fsread: filename match "/usr/lib/libc.so.*" then per < + native-fsread: filename match "/usr/lib/libcrypto.so.*" the < + native-fsread: filename match "/usr/lib/libncurses.so.*" th < + native-fsread: filename match "/usr/lib/libssl.so.*" then p < + native-fsread: filename eq "/usr/libdata" then permit + native-fsread: filename eq "/usr/libexec" then permit + native-fsread: filename eq "/usr/lkm" then permit + native-fsread: filename eq "/usr/local" then permit + native-fsread: filename eq "/usr/mdec" then permit + native-fsread: filename eq "/usr/obj" then permit | native-fsread: filename eq "/home" then permit + native-fsread: filename eq "/usr/obj/bin" then permit | native-fsread: filename eq "/obj" then permit + native-fsread: filename eq "/usr/obj/bin/systrace/." then p | native-fsread: filename eq "$HOME/.lynxrc" then permit + > native-fsread: filename match "/: *" + native-fsread: filename eq "/usr/obj/bin/systrace/.mailcap" + > native-fsread: filename eq "$HOME/.mailcap" then permit + native-fsread: filename eq "/usr/obj/bin/systrace/.mime.typ + > native-fsread: filename eq "$HOME/.mime.types" then permit + > native-sigaction: permit + > native-ioctl: permit + > native-fsread: filename eq "$HOME/.terminfo.db" then permit + > native-fsread: filename eq "$HOME/.terminfo" then permit + native-fsread: filename eq "/usr/share/misc/terminfo.db" th + > native-pread: permit + > native-write: permit + > native-fsread: filename eq "$HOME/.lynx-keymaps" then permi + native-fsread: filename eq "/var/run/dev.db" then permit + native-fsread: filename eq "/var/run/ld.so.hints" then perm | native-fsread: filename eq "/etc/utmp" then permit + native-fstat: permit < + native-fswrite: filename match "/tmp/lynx-*" then permit < + native-getdirentries: permit < + native-getpid: permit < + native-gettimeofday: permit < + native-ioctl: permit < + native-issetugid: permit < + native-lseek: permit < + native-mmap: permit < + native-mprotect: prot eq "PROT_READ" then permit < + native-mprotect: prot eq "PROT_READ|PROT_EXEC" then permit < + native-mprotect: prot eq "PROT_READ|PROT_WRITE" then permit < + native-mprotect: prot eq "PROT_READ|PROT_WRITE|PROT_EXEC" t < + native-munmap: permit < + native-nanosleep: permit < + native-poll: permit + native-pread: permit | native-nanosleep: permit + native-read: permit | native-gettimeofday: permit + native-recvfrom: permit | native-fsread: filename eq "/etc/resolv.conf" then permit + native-select: permit < + native-sendto: true then permit < + native-sigaction: permit < + native-sigprocmask: permit < + native-socket: sockdom eq "AF_INET" and socktype eq "SOCK_D + > native-connect: sockaddr eq "inet-[127.0.0.1]:53" then perm + > native-sendto: true then permit + > native-select: permit + > native-recvfrom: permit + native-socket: sockdom eq "AF_INET" and socktype eq "SOCK_S + native-write: permit | native-connect: sockaddr match "inet-\\\[*\\\]:80" then per + > native-exit: permit diff --git a/tests/usr.bin/sdiff/d_flags_s.out b/tests/usr.bin/sdiff/d_flags_s.out new file mode 100644 index 000000000..19179fe51 --- /dev/null +++ b/tests/usr.bin/sdiff/d_flags_s.out @@ -0,0 +1,79 @@ + > native-issetugid: permit + > native-mprotect: permit + > native-mmap: permit + > native-fsread: filename eq "/var/run/ld.so.hints" then perm + > native-fstat: permit + native-connect: sockaddr eq "inet-[127.0.0.1]:53" then perm | native-fsread: filename match "/usr/lib/libssl.so.*" then p + native-connect: sockaddr match "inet-\\\[*\\\]:80" then per | native-read: permit + native-exit: permit | native-fsread: filename match "/usr/lib/libcrypto.so.*" the + native-fcntl: cmd eq "F_SETFD" then permit | native-fsread: filename match "/usr/lib/libncurses.so.*" th + native-fsread: filename eq "/" then permit | native-fsread: filename match "/usr/lib/libc.so.*" then per + native-fsread: filename match "/: *" | native-munmap: permit + native-fsread: filename eq "/etc/lynx.cfg" then permit | native-sigprocmask: permit + native-fsread: filename eq "/etc/resolv.conf" then permit | native-getpid: permit + native-fsread: filename eq "/etc/utmp" then permit < + native-fsread: filename eq "/home" then permit < + native-fsread: filename eq "$HOME" then permit < + native-fsread: filename eq "$HOME/.lynx-keymaps" then permi < + native-fsread: filename eq "$HOME/.lynxrc" then permit < + native-fsread: filename eq "$HOME/.mailcap" then permit < + native-fsread: filename eq "$HOME/.mime.types" then permit < + native-fsread: filename eq "$HOME/.terminfo" then permit < + native-fsread: filename eq "$HOME/.terminfo.db" then permit < + native-fsread: filename eq "/obj" then permit < + > native-fswrite: filename match "/tmp/lynx-*" then permit + > native-fsread: filename eq "$HOME" then permit + > native-fsread: filename eq "/etc/lynx.cfg" then permit + > native-fsread: filename eq "/" then permit + > native-fsread: filename eq "/usr/obj/bin/systrace/." then p + > native-fsread: filename eq "/usr/obj/bin" then permit + > native-fcntl: permit + > native-getdirentries: permit + > native-lseek: permit + > native-fsread: filename eq "/usr/obj" then permit + native-fsread: filename match "/usr/lib/libc.so.*" then per < + native-fsread: filename match "/usr/lib/libcrypto.so.*" the < + native-fsread: filename match "/usr/lib/libncurses.so.*" th < + native-fsread: filename match "/usr/lib/libssl.so.*" then p < + native-fsread: filename eq "/usr/obj" then permit | native-fsread: filename eq "/home" then permit + native-fsread: filename eq "/usr/obj/bin" then permit | native-fsread: filename eq "/obj" then permit + native-fsread: filename eq "/usr/obj/bin/systrace/." then p | native-fsread: filename eq "$HOME/.lynxrc" then permit + > native-fsread: filename match "/: *" + > native-fsread: filename eq "$HOME/.mailcap" then permit + > native-fsread: filename eq "$HOME/.mime.types" then permit + > native-sigaction: permit + > native-ioctl: permit + > native-fsread: filename eq "$HOME/.terminfo.db" then permit + > native-fsread: filename eq "$HOME/.terminfo" then permit + > native-pread: permit + > native-write: permit + > native-fsread: filename eq "$HOME/.lynx-keymaps" then permi + native-fsread: filename eq "/var/run/ld.so.hints" then perm | native-fsread: filename eq "/etc/utmp" then permit + native-fstat: permit < + native-fswrite: filename match "/tmp/lynx-*" then permit < + native-getdirentries: permit < + native-getpid: permit < + native-gettimeofday: permit < + native-ioctl: permit < + native-issetugid: permit < + native-lseek: permit < + native-mmap: permit < + native-mprotect: prot eq "PROT_READ" then permit < + native-mprotect: prot eq "PROT_READ|PROT_EXEC" then permit < + native-mprotect: prot eq "PROT_READ|PROT_WRITE" then permit < + native-mprotect: prot eq "PROT_READ|PROT_WRITE|PROT_EXEC" t < + native-munmap: permit < + native-nanosleep: permit < + native-pread: permit | native-nanosleep: permit + native-read: permit | native-gettimeofday: permit + native-recvfrom: permit | native-fsread: filename eq "/etc/resolv.conf" then permit + native-select: permit < + native-sendto: true then permit < + native-sigaction: permit < + native-sigprocmask: permit < + > native-connect: sockaddr eq "inet-[127.0.0.1]:53" then perm + > native-sendto: true then permit + > native-select: permit + > native-recvfrom: permit + native-write: permit | native-connect: sockaddr match "inet-\\\[*\\\]:80" then per + > native-exit: permit diff --git a/tests/usr.bin/sdiff/d_flags_w.out b/tests/usr.bin/sdiff/d_flags_w.out new file mode 100644 index 000000000..19ea79bf6 --- /dev/null +++ b/tests/usr.bin/sdiff/d_flags_w.out @@ -0,0 +1,102 @@ +Policy: /usr/bin/lynx, Emulation: native Policy: /usr/bin/lynx, Emulation: native + > native-issetugid: permit + > native-mprotect: permit + > native-mmap: permit + native-__sysctl: permit native-__sysctl: permit + > native-fsread: filename eq "/var/run/ld.so.hints" then pe + > native-fstat: permit + native-close: permit native-close: permit + native-connect: sockaddr eq "inet-[127.0.0.1]:53" then pe | native-fsread: filename match "/usr/lib/libssl.so.*" then + native-connect: sockaddr match "inet-\\\[*\\\]:80" then p | native-read: permit + native-exit: permit | native-fsread: filename match "/usr/lib/libcrypto.so.*" t + native-fcntl: cmd eq "F_SETFD" then permit | native-fsread: filename match "/usr/lib/libncurses.so.*" + native-fsread: filename eq "/" then permit | native-fsread: filename match "/usr/lib/libc.so.*" then p + native-fsread: filename match "/: | native-munmap: permit + native-fsread: filename eq "/etc/lynx.cfg" then permit | native-sigprocmask: permit + native-fsread: filename eq "/etc/malloc.conf" then permit native-fsread: filename eq "/etc/malloc.conf" then permit + native-fsread: filename eq "/etc/resolv.conf" then permit | native-getpid: permit + native-fsread: filename eq "/etc/utmp" then permit < + native-fsread: filename eq "/home" then permit < + native-fsread: filename eq "$HOME" then permit < + native-fsread: filename eq "$HOME/.lynx-keymaps" then per < + native-fsread: filename eq "$HOME/.lynxrc" then permit < + native-fsread: filename eq "$HOME/.mailcap" then permit < + native-fsread: filename eq "$HOME/.mime.types" then permi < + native-fsread: filename eq "$HOME/.terminfo" then permit < + native-fsread: filename eq "$HOME/.terminfo.db" then perm < + native-fsread: filename eq "/obj" then permit < + native-fsread: filename eq "/tmp" then permit native-fsread: filename eq "/tmp" then permit + > native-fswrite: filename match "/tmp/lynx-*" then permit + native-fsread: filename match "/tmp/lynx-*/." then permit native-fsread: filename match "/tmp/lynx-*/." then permit + > native-fsread: filename eq "$HOME" then permit + > native-fsread: filename eq "/etc/lynx.cfg" then permit + > native-fsread: filename eq "/" then permit + > native-fsread: filename eq "/usr/obj/bin/systrace/." then + > native-fsread: filename eq "/usr/obj/bin" then permit + > native-fcntl: permit + > native-getdirentries: permit + > native-lseek: permit + > native-fsread: filename eq "/usr/obj" then permit + native-fsread: filename eq "/usr" then permit native-fsread: filename eq "/usr" then permit + native-fsread: filename eq "/usr/bin" then permit native-fsread: filename eq "/usr/bin" then permit + native-fsread: filename eq "/usr/games" then permit native-fsread: filename eq "/usr/games" then permit + native-fsread: filename eq "/usr/include" then permit native-fsread: filename eq "/usr/include" then permit + native-fsread: filename eq "/usr/lib" then permit native-fsread: filename eq "/usr/lib" then permit + native-fsread: filename match "/usr/lib/libc.so.*" then p < + native-fsread: filename match "/usr/lib/libcrypto.so.*" t < + native-fsread: filename match "/usr/lib/libncurses.so.*" < + native-fsread: filename match "/usr/lib/libssl.so.*" then < + native-fsread: filename eq "/usr/libdata" then permit native-fsread: filename eq "/usr/libdata" then permit + native-fsread: filename eq "/usr/libexec" then permit native-fsread: filename eq "/usr/libexec" then permit + native-fsread: filename eq "/usr/lkm" then permit native-fsread: filename eq "/usr/lkm" then permit + native-fsread: filename eq "/usr/local" then permit native-fsread: filename eq "/usr/local" then permit + native-fsread: filename eq "/usr/mdec" then permit native-fsread: filename eq "/usr/mdec" then permit + native-fsread: filename eq "/usr/obj" then permit | native-fsread: filename eq "/home" then permit + native-fsread: filename eq "/usr/obj/bin" then permit | native-fsread: filename eq "/obj" then permit + native-fsread: filename eq "/usr/obj/bin/systrace/." then | native-fsread: filename eq "$HOME/.lynxrc" then permit + > native-fsread: filename match "/: + native-fsread: filename eq "/usr/obj/bin/systrace/.mailca native-fsread: filename eq "/usr/obj/bin/systrace/.mailca + > native-fsread: filename eq "$HOME/.mailcap" then permit + native-fsread: filename eq "/usr/obj/bin/systrace/.mime.t native-fsread: filename eq "/usr/obj/bin/systrace/.mime.t + > native-fsread: filename eq "$HOME/.mime.types" then permi + > native-sigaction: permit + > native-ioctl: permit + > native-fsread: filename eq "$HOME/.terminfo.db" then perm + > native-fsread: filename eq "$HOME/.terminfo" then permit + native-fsread: filename eq "/usr/share/misc/terminfo.db" native-fsread: filename eq "/usr/share/misc/terminfo.db" + > native-pread: permit + > native-write: permit + > native-fsread: filename eq "$HOME/.lynx-keymaps" then per + native-fsread: filename eq "/var/run/dev.db" then permit native-fsread: filename eq "/var/run/dev.db" then permit + native-fsread: filename eq "/var/run/ld.so.hints" then pe | native-fsread: filename eq "/etc/utmp" then permit + native-fstat: permit < + native-fswrite: filename match "/tmp/lynx-*" then permit < + native-getdirentries: permit < + native-getpid: permit < + native-gettimeofday: permit < + native-ioctl: permit < + native-issetugid: permit < + native-lseek: permit < + native-mmap: permit < + native-mprotect: prot eq "PROT_READ" then permit < + native-mprotect: prot eq "PROT_READ|PROT_EXEC" then permi < + native-mprotect: prot eq "PROT_READ|PROT_WRITE" then perm < + native-mprotect: prot eq "PROT_READ|PROT_WRITE|PROT_EXEC" < + native-munmap: permit < + native-nanosleep: permit < + native-poll: permit native-poll: permit + native-pread: permit | native-nanosleep: permit + native-read: permit | native-gettimeofday: permit + native-recvfrom: permit | native-fsread: filename eq "/etc/resolv.conf" then permit + native-select: permit < + native-sendto: true then permit < + native-sigaction: permit < + native-sigprocmask: permit < + native-socket: sockdom eq "AF_INET" and socktype eq "SOCK native-socket: sockdom eq "AF_INET" and socktype eq "SOCK + > native-connect: sockaddr eq "inet-[127.0.0.1]:53" then pe + > native-sendto: true then permit + > native-select: permit + > native-recvfrom: permit + native-socket: sockdom eq "AF_INET" and socktype eq "SOCK native-socket: sockdom eq "AF_INET" and socktype eq "SOCK + native-write: permit | native-connect: sockaddr match "inet-\\\[*\\\]:80" then p + > native-exit: permit diff --git a/tests/usr.bin/sdiff/d_iflags_a1.out b/tests/usr.bin/sdiff/d_iflags_a1.out new file mode 100644 index 000000000..2a0f5328a --- /dev/null +++ b/tests/usr.bin/sdiff/d_iflags_a1.out @@ -0,0 +1,100 @@ +Policy: /usr/bin/lynx, Emulation: native Policy: /usr/bin/lynx, Emulation: native + > native-issetugid: permit + > native-mprotect: permit + > native-mmap: permit + native-__sysctl: permit native-__sysctl: permit + > native-fsread: filename eq "/var/run/ld.so.hints" then pe + > native-fstat: permit + native-close: permit native-close: permit + native-connect: sockaddr eq "inet-[127.0.0.1]:53" then pe | native-fsread: filename match "/usr/lib/libssl.so.*" then + native-connect: sockaddr match "inet-\\\[*\\\]:80" then p | native-read: permit + native-exit: permit | native-fsread: filename match "/usr/lib/libcrypto.so.*" t + native-fcntl: cmd eq "F_SETFD" then permit | native-fsread: filename match "/usr/lib/libncurses.so.*" + native-fsread: filename eq "/" then permit | native-fsread: filename match "/usr/lib/libc.so.*" then p + native-fsread: filename match "/: | native-munmap: permit + native-fsread: filename eq "/etc/lynx.cfg" then permit | native-sigprocmask: permit + native-fsread: filename eq "/etc/malloc.conf" then permit native-fsread: filename eq "/etc/malloc.conf" then permit + native-fsread: filename eq "/etc/resolv.conf" then permit | native-getpid: permit + native-fsread: filename eq "/etc/utmp" then permit < + native-fsread: filename eq "/home" then permit < + native-fsread: filename eq "$HOME" then permit < + native-fsread: filename eq "$HOME/.lynx-keymaps" then per < + native-fsread: filename eq "$HOME/.lynxrc" then permit < + native-fsread: filename eq "$HOME/.mailcap" then permit < + native-fsread: filename eq "$HOME/.mime.types" then permi < + native-fsread: filename eq "$HOME/.terminfo" then permit < + native-fsread: filename eq "$HOME/.terminfo.db" then perm < + native-fsread: filename eq "/obj" then permit < + native-fsread: filename eq "/tmp" then permit native-fsread: filename eq "/tmp" then permit + native-fsread: filename match "/tmp/lynx-*/." then permit native-fswrite: filename match "/tmp/lynx-*" then permit + ) native-fsread: filename match "/tmp/lynx-*/." then permit + > native-fsread: filename eq "$HOME" then permit + > native-fsread: filename eq "/etc/lynx.cfg" then permit + > native-fsread: filename eq "/" then permit + > native-fsread: filename eq "/usr/obj/bin/systrace/." then + > native-fsread: filename eq "/usr/obj/bin" then permit + > native-fcntl: permit + > native-getdirentries: permit + > native-lseek: permit + > native-fsread: filename eq "/usr/obj" then permit + native-fsread: filename eq "/usr" then permit native-fsread: filename eq "/usr" then permit + native-fsread: filename eq "/usr/bin" then permit native-fsread: filename eq "/usr/bin" then permit + native-fsread: filename eq "/usr/games" then permit native-fsread: filename eq "/usr/games" then permit + native-fsread: filename eq "/usr/include" then permit native-fsread: filename eq "/usr/include" then permit + native-fsread: filename eq "/usr/lib" then permit native-fsread: filename eq "/usr/lib" then permit + native-fsread: filename match "/usr/lib/libc.so.*" then p native-fsread: filename eq "/usr/libdata" then permit + native-fsread: filename match "/usr/lib/libcrypto.so.*" t native-fsread: filename eq "/usr/libexec" then permit + native-fsread: filename match "/usr/lib/libncurses.so.*" native-fsread: filename eq "/usr/lkm" then permit + native-fsread: filename match "/usr/lib/libssl.so.*" then native-fsread: filename eq "/usr/local" then permit + native-fsread: filename eq "/usr/libdata" then permit native-fsread: filename eq "/usr/mdec" then permit + native-fsread: filename eq "/usr/libexec" then permit native-fsread: filename eq "/home" then permit + native-fsread: filename eq "/usr/lkm" then permit native-fsread: filename eq "/obj" then permit + native-fsread: filename eq "/usr/local" then permit native-fsread: filename eq "$HOME/.lynxrc" then permit + native-fsread: filename eq "/usr/mdec" then permit native-fsread: filename match "/: + native-fsread: filename eq "/usr/obj" then permit native-fsread: filename eq "/usr/obj/bin/systrace/.mailca + native-fsread: filename eq "/usr/obj/bin" then permit native-fsread: filename eq "$HOME/.mailcap" then permit + native-fsread: filename eq "/usr/obj/bin/systrace/." then native-fsread: filename eq "/usr/obj/bin/systrace/.mime.t + native-fsread: filename eq "/usr/obj/bin/systrace/.mailca ( + native-fsread: filename eq "/usr/obj/bin/systrace/.mime.t ( + > native-fsread: filename eq "$HOME/.mime.types" then permi + > native-sigaction: permit + > native-ioctl: permit + > native-fsread: filename eq "$HOME/.terminfo.db" then perm + > native-fsread: filename eq "$HOME/.terminfo" then permit + native-fsread: filename eq "/usr/share/misc/terminfo.db" native-fsread: filename eq "/usr/share/misc/terminfo.db" + > native-pread: permit + > native-write: permit + > native-fsread: filename eq "$HOME/.lynx-keymaps" then per + native-fsread: filename eq "/var/run/dev.db" then permit native-fsread: filename eq "/var/run/dev.db" then permit + native-fsread: filename eq "/var/run/ld.so.hints" then pe | native-fsread: filename eq "/etc/utmp" then permit + native-fstat: permit < + native-fswrite: filename match "/tmp/lynx-*" then permit < + native-getdirentries: permit < + native-getpid: permit < + native-gettimeofday: permit < + native-ioctl: permit < + native-issetugid: permit < + native-lseek: permit < + native-mmap: permit < + native-mprotect: prot eq "PROT_READ" then permit < + native-mprotect: prot eq "PROT_READ|PROT_EXEC" then permi < + native-mprotect: prot eq "PROT_READ|PROT_WRITE" then perm < + native-mprotect: prot eq "PROT_READ|PROT_WRITE|PROT_EXEC" < + native-munmap: permit < + native-nanosleep: permit < + native-poll: permit native-poll: permit + native-pread: permit | native-nanosleep: permit + native-read: permit | native-gettimeofday: permit + native-recvfrom: permit | native-fsread: filename eq "/etc/resolv.conf" then permit + native-select: permit < + native-sendto: true then permit < + native-sigaction: permit < + native-sigprocmask: permit < + native-socket: sockdom eq "AF_INET" and socktype eq "SOCK native-socket: sockdom eq "AF_INET" and socktype eq "SOCK + > native-connect: sockaddr eq "inet-[127.0.0.1]:53" then pe + > native-sendto: true then permit + > native-select: permit + > native-recvfrom: permit + native-socket: sockdom eq "AF_INET" and socktype eq "SOCK native-socket: sockdom eq "AF_INET" and socktype eq "SOCK + native-write: permit | native-connect: sockaddr match "inet-\\\[*\\\]:80" then p + > native-exit: permit diff --git a/tests/usr.bin/sdiff/d_iflags_a2.out b/tests/usr.bin/sdiff/d_iflags_a2.out new file mode 100644 index 000000000..4e0d349b7 --- /dev/null +++ b/tests/usr.bin/sdiff/d_iflags_a2.out @@ -0,0 +1,96 @@ +Policy: /usr/bin/lynx, Emulation: native Policy: /usr/bin/lynx, Emulation: native + native-issetugid: permit < + native-mprotect: permit < + native-mmap: permit < + native-__sysctl: permit native-__sysctl: permit + native-fsread: filename eq "/var/run/ld.so.hints" then pe < + native-fstat: permit < + native-close: permit native-close: permit + native-fsread: filename match "/usr/lib/libssl.so.*" then | native-connect: sockaddr eq "inet-[127.0.0.1]:53" then pe + native-read: permit | native-connect: sockaddr match "inet-\\\[*\\\]:80" then p + native-fsread: filename match "/usr/lib/libcrypto.so.*" t | native-exit: permit + native-fsread: filename match "/usr/lib/libncurses.so.*" | native-fcntl: cmd eq "F_SETFD" then permit + native-fsread: filename match "/usr/lib/libc.so.*" then p | native-fsread: filename eq "/" then permit + native-munmap: permit | native-fsread: filename match "/: + native-sigprocmask: permit | native-fsread: filename eq "/etc/lynx.cfg" then permit + native-fsread: filename eq "/etc/malloc.conf" then permit native-fsread: filename eq "/etc/malloc.conf" then permit + native-getpid: permit | native-fsread: filename eq "/etc/resolv.conf" then permit + > native-fsread: filename eq "/etc/utmp" then permit + > native-fsread: filename eq "/home" then permit + > native-fsread: filename eq "$HOME" then permit + > native-fsread: filename eq "$HOME/.lynx-keymaps" then per + > native-fsread: filename eq "$HOME/.lynxrc" then permit + > native-fsread: filename eq "$HOME/.mailcap" then permit + > native-fsread: filename eq "$HOME/.mime.types" then permi + > native-fsread: filename eq "$HOME/.terminfo" then permit + > native-fsread: filename eq "$HOME/.terminfo.db" then perm + > native-fsread: filename eq "/obj" then permit + native-fsread: filename eq "/tmp" then permit native-fsread: filename eq "/tmp" then permit + native-fswrite: filename match "/tmp/lynx-*" then permit native-fsread: filename match "/tmp/lynx-*/." then permit + native-fsread: filename match "/tmp/lynx-*/." then permit ( + native-fsread: filename eq "$HOME" then permit < + native-fsread: filename eq "/etc/lynx.cfg" then permit < + native-fsread: filename eq "/" then permit < + native-fsread: filename eq "/usr/obj/bin/systrace/." then < + native-fsread: filename eq "/usr/obj/bin" then permit < + native-fcntl: permit < + native-getdirentries: permit < + native-lseek: permit < + native-fsread: filename eq "/usr/obj" then permit < + native-fsread: filename eq "/usr" then permit native-fsread: filename eq "/usr" then permit + native-fsread: filename eq "/usr/bin" then permit native-fsread: filename eq "/usr/bin" then permit + native-fsread: filename eq "/usr/games" then permit native-fsread: filename eq "/usr/games" then permit + native-fsread: filename eq "/usr/include" then permit native-fsread: filename eq "/usr/include" then permit + native-fsread: filename eq "/usr/lib" then permit native-fsread: filename eq "/usr/lib" then permit + native-fsread: filename eq "/usr/libdata" then permit native-fsread: filename match "/usr/lib/libc.so.*" then p + native-fsread: filename eq "/usr/libexec" then permit native-fsread: filename match "/usr/lib/libcrypto.so.*" t + native-fsread: filename eq "/usr/lkm" then permit native-fsread: filename match "/usr/lib/libncurses.so.*" + native-fsread: filename eq "/usr/local" then permit native-fsread: filename match "/usr/lib/libssl.so.*" then + native-fsread: filename eq "/usr/mdec" then permit native-fsread: filename eq "/usr/libdata" then permit + native-fsread: filename eq "/home" then permit native-fsread: filename eq "/usr/libexec" then permit + native-fsread: filename eq "/obj" then permit native-fsread: filename eq "/usr/lkm" then permit + native-fsread: filename eq "$HOME/.lynxrc" then permit native-fsread: filename eq "/usr/local" then permit + native-fsread: filename match "/: native-fsread: filename eq "/usr/mdec" then permit + native-fsread: filename eq "/usr/obj/bin/systrace/.mailca native-fsread: filename eq "/usr/obj" then permit + native-fsread: filename eq "$HOME/.mailcap" then permit native-fsread: filename eq "/usr/obj/bin" then permit + native-fsread: filename eq "/usr/obj/bin/systrace/.mime.t native-fsread: filename eq "/usr/obj/bin/systrace/." then + ) native-fsread: filename eq "/usr/obj/bin/systrace/.mailca + ) native-fsread: filename eq "/usr/obj/bin/systrace/.mime.t + native-fsread: filename eq "$HOME/.mime.types" then permi < + native-sigaction: permit < + native-ioctl: permit < + native-fsread: filename eq "$HOME/.terminfo.db" then perm < + native-fsread: filename eq "$HOME/.terminfo" then permit < + native-fsread: filename eq "/usr/share/misc/terminfo.db" native-fsread: filename eq "/usr/share/misc/terminfo.db" + native-pread: permit < + native-write: permit < + native-fsread: filename eq "$HOME/.lynx-keymaps" then per < + native-fsread: filename eq "/var/run/dev.db" then permit native-fsread: filename eq "/var/run/dev.db" then permit + native-fsread: filename eq "/etc/utmp" then permit | native-fsread: filename eq "/var/run/ld.so.hints" then pe + native-poll: permit | native-fstat: permit + native-nanosleep: permit | native-fswrite: filename match "/tmp/lynx-*" then permit + > native-getdirentries: permit + > native-getpid: permit + native-gettimeofday: permit native-gettimeofday: permit + native-fsread: filename eq "/etc/resolv.conf" then permit | native-ioctl: permit + native-socket: sockdom eq "AF_INET" and socktype eq "SOCK | native-issetugid: permit + native-connect: sockaddr eq "inet-[127.0.0.1]:53" then pe | native-lseek: permit + native-sendto: true then permit | native-mmap: permit + native-select: permit | native-mprotect: prot eq "PROT_READ" then permit + > native-mprotect: prot eq "PROT_READ|PROT_EXEC" then permi + > native-mprotect: prot eq "PROT_READ|PROT_WRITE" then perm + > native-mprotect: prot eq "PROT_READ|PROT_WRITE|PROT_EXEC" + > native-munmap: permit + > native-nanosleep: permit + > native-poll: permit + > native-pread: permit + > native-read: permit + native-recvfrom: permit native-recvfrom: permit + > native-select: permit + > native-sendto: true then permit + > native-sigaction: permit + > native-sigprocmask: permit + > native-socket: sockdom eq "AF_INET" and socktype eq "SOCK + native-socket: sockdom eq "AF_INET" and socktype eq "SOCK native-socket: sockdom eq "AF_INET" and socktype eq "SOCK + native-connect: sockaddr match "inet-\\\[*\\\]:80" then p | native-write: permit + native-exit: permit < diff --git a/tests/usr.bin/sdiff/d_iflags_b1.out b/tests/usr.bin/sdiff/d_iflags_b1.out new file mode 100644 index 000000000..3e548b693 --- /dev/null +++ b/tests/usr.bin/sdiff/d_iflags_b1.out @@ -0,0 +1,69 @@ + > native-issetugid: permit + > native-mprotect: permit + > native-mmap: permit + > native-fsread: filename eq "/var/run/ld.so.hints" then pe + > native-fstat: permit + native-connect: sockaddr eq "inet-[127.0.0.1]:53" then pe | native-fsread: filename match "/usr/lib/libssl.so.*" then + native-connect: sockaddr match "inet-\\\[*\\\]:80" then p | native-read: permit + native-exit: permit | native-fsread: filename match "/usr/lib/libcrypto.so.*" t + native-fcntl: cmd eq "F_SETFD" then permit | native-fsread: filename match "/usr/lib/libncurses.so.*" + native-fsread: filename eq "/" then permit | native-fsread: filename match "/usr/lib/libc.so.*" then p + native-fsread: filename match "/: | native-munmap: permit + native-fsread: filename eq "/etc/lynx.cfg" then permit | native-sigprocmask: permit + native-fsread: filename eq "/etc/resolv.conf" then permit | native-getpid: permit + native-fsread: filename eq "/etc/utmp" then permit < + native-fsread: filename eq "/home" then permit < + native-fsread: filename eq "$HOME" then permit < + native-fsread: filename eq "$HOME/.lynx-keymaps" then per < + native-fsread: filename eq "$HOME/.lynxrc" then permit < + native-fsread: filename eq "$HOME/.mailcap" then permit < + native-fsread: filename eq "$HOME/.mime.types" then permi < + native-fsread: filename eq "$HOME/.terminfo" then permit < + native-fsread: filename eq "$HOME/.terminfo.db" then perm < + native-fsread: filename eq "/obj" then permit < + > native-fsread: filename eq "$HOME" then permit + > native-fsread: filename eq "/etc/lynx.cfg" then permit + > native-fsread: filename eq "/" then permit + > native-fsread: filename eq "/usr/obj/bin/systrace/." then + > native-fsread: filename eq "/usr/obj/bin" then permit + > native-fcntl: permit + > native-getdirentries: permit + > native-lseek: permit + > native-fsread: filename eq "/usr/obj" then permit + > native-fsread: filename eq "$HOME/.mime.types" then permi + > native-sigaction: permit + > native-ioctl: permit + > native-fsread: filename eq "$HOME/.terminfo.db" then perm + > native-fsread: filename eq "$HOME/.terminfo" then permit + > native-pread: permit + > native-write: permit + > native-fsread: filename eq "$HOME/.lynx-keymaps" then per + native-fsread: filename eq "/var/run/ld.so.hints" then pe | native-fsread: filename eq "/etc/utmp" then permit + native-fstat: permit < + native-fswrite: filename match "/tmp/lynx-*" then permit < + native-getdirentries: permit < + native-getpid: permit < + native-gettimeofday: permit < + native-ioctl: permit < + native-issetugid: permit < + native-lseek: permit < + native-mmap: permit < + native-mprotect: prot eq "PROT_READ" then permit < + native-mprotect: prot eq "PROT_READ|PROT_EXEC" then permi < + native-mprotect: prot eq "PROT_READ|PROT_WRITE" then perm < + native-mprotect: prot eq "PROT_READ|PROT_WRITE|PROT_EXEC" < + native-munmap: permit < + native-nanosleep: permit < + native-pread: permit | native-nanosleep: permit + native-read: permit | native-gettimeofday: permit + native-recvfrom: permit | native-fsread: filename eq "/etc/resolv.conf" then permit + native-select: permit < + native-sendto: true then permit < + native-sigaction: permit < + native-sigprocmask: permit < + > native-connect: sockaddr eq "inet-[127.0.0.1]:53" then pe + > native-sendto: true then permit + > native-select: permit + > native-recvfrom: permit + native-write: permit | native-connect: sockaddr match "inet-\\\[*\\\]:80" then p + > native-exit: permit diff --git a/tests/usr.bin/sdiff/d_iflags_b2.out b/tests/usr.bin/sdiff/d_iflags_b2.out new file mode 100644 index 000000000..4504c36ec --- /dev/null +++ b/tests/usr.bin/sdiff/d_iflags_b2.out @@ -0,0 +1,65 @@ + native-issetugid: permit < + native-mprotect: permit < + native-mmap: permit < + native-fsread: filename eq "/var/run/ld.so.hints" then pe < + native-fstat: permit < + native-fsread: filename match "/usr/lib/libssl.so.*" then | native-connect: sockaddr eq "inet-[127.0.0.1]:53" then pe + native-read: permit | native-connect: sockaddr match "inet-\\\[*\\\]:80" then p + native-fsread: filename match "/usr/lib/libcrypto.so.*" t | native-exit: permit + native-fsread: filename match "/usr/lib/libncurses.so.*" | native-fcntl: cmd eq "F_SETFD" then permit + native-fsread: filename match "/usr/lib/libc.so.*" then p | native-fsread: filename eq "/" then permit + native-munmap: permit | native-fsread: filename match "/: + native-sigprocmask: permit | native-fsread: filename eq "/etc/lynx.cfg" then permit + native-getpid: permit | native-fsread: filename eq "/etc/resolv.conf" then permit + > native-fsread: filename eq "/etc/utmp" then permit + > native-fsread: filename eq "/home" then permit + > native-fsread: filename eq "$HOME" then permit + > native-fsread: filename eq "$HOME/.lynx-keymaps" then per + > native-fsread: filename eq "$HOME/.lynxrc" then permit + > native-fsread: filename eq "$HOME/.mailcap" then permit + > native-fsread: filename eq "$HOME/.mime.types" then permi + > native-fsread: filename eq "$HOME/.terminfo" then permit + > native-fsread: filename eq "$HOME/.terminfo.db" then perm + > native-fsread: filename eq "/obj" then permit + native-fsread: filename eq "$HOME" then permit < + native-fsread: filename eq "/etc/lynx.cfg" then permit < + native-fsread: filename eq "/" then permit < + native-fsread: filename eq "/usr/obj/bin/systrace/." then < + native-fsread: filename eq "/usr/obj/bin" then permit < + native-fcntl: permit < + native-getdirentries: permit < + native-lseek: permit < + native-fsread: filename eq "/usr/obj" then permit < + native-fsread: filename eq "$HOME/.mime.types" then permi < + native-sigaction: permit < + native-ioctl: permit < + native-fsread: filename eq "$HOME/.terminfo.db" then perm < + native-fsread: filename eq "$HOME/.terminfo" then permit < + native-pread: permit < + native-write: permit < + native-fsread: filename eq "$HOME/.lynx-keymaps" then per < + native-fsread: filename eq "/etc/utmp" then permit | native-fsread: filename eq "/var/run/ld.so.hints" then pe + native-poll: permit | native-fstat: permit + native-nanosleep: permit | native-fswrite: filename match "/tmp/lynx-*" then permit + > native-getdirentries: permit + > native-getpid: permit + native-fsread: filename eq "/etc/resolv.conf" then permit | native-ioctl: permit + native-socket: sockdom eq "AF_INET" and socktype eq "SOCK | native-issetugid: permit + native-connect: sockaddr eq "inet-[127.0.0.1]:53" then pe | native-lseek: permit + native-sendto: true then permit | native-mmap: permit + native-select: permit | native-mprotect: prot eq "PROT_READ" then permit + > native-mprotect: prot eq "PROT_READ|PROT_EXEC" then permi + > native-mprotect: prot eq "PROT_READ|PROT_WRITE" then perm + > native-mprotect: prot eq "PROT_READ|PROT_WRITE|PROT_EXEC" + > native-munmap: permit + > native-nanosleep: permit + > native-poll: permit + > native-pread: permit + > native-read: permit + > native-select: permit + > native-sendto: true then permit + > native-sigaction: permit + > native-sigprocmask: permit + > native-socket: sockdom eq "AF_INET" and socktype eq "SOCK + native-connect: sockaddr match "inet-\\\[*\\\]:80" then p | native-write: permit + native-exit: permit < diff --git a/tests/usr.bin/sdiff/d_iflags_c1.out b/tests/usr.bin/sdiff/d_iflags_c1.out new file mode 100644 index 000000000..e9ac88e54 --- /dev/null +++ b/tests/usr.bin/sdiff/d_iflags_c1.out @@ -0,0 +1,99 @@ +Policy: /usr/bin/lynx, Emulation: native ( + > native-issetugid: permit + > native-mprotect: permit + > native-mmap: permit + native-__sysctl: permit ( + > native-fsread: filename eq "/var/run/ld.so.hints" then pe + > native-fstat: permit + native-close: permit ( + native-connect: sockaddr eq "inet-[127.0.0.1]:53" then pe | native-fsread: filename match "/usr/lib/libssl.so.*" then + native-connect: sockaddr match "inet-\\\[*\\\]:80" then p | native-read: permit + native-exit: permit | native-fsread: filename match "/usr/lib/libcrypto.so.*" t + native-fcntl: cmd eq "F_SETFD" then permit | native-fsread: filename match "/usr/lib/libncurses.so.*" + native-fsread: filename eq "/" then permit | native-fsread: filename match "/usr/lib/libc.so.*" then p + native-fsread: filename match "/: | native-munmap: permit + native-fsread: filename eq "/etc/lynx.cfg" then permit | native-sigprocmask: permit + native-fsread: filename eq "/etc/malloc.conf" then permit ( + native-fsread: filename eq "/etc/resolv.conf" then permit | native-getpid: permit + native-fsread: filename eq "/etc/utmp" then permit < + native-fsread: filename eq "/home" then permit < + native-fsread: filename eq "$HOME" then permit < + native-fsread: filename eq "$HOME/.lynx-keymaps" then per < + native-fsread: filename eq "$HOME/.lynxrc" then permit < + native-fsread: filename eq "$HOME/.mailcap" then permit < + native-fsread: filename eq "$HOME/.mime.types" then permi < + native-fsread: filename eq "$HOME/.terminfo" then permit < + native-fsread: filename eq "$HOME/.terminfo.db" then perm < + native-fsread: filename eq "/obj" then permit < + native-fsread: filename eq "/tmp" then permit ( + native-fsread: filename match "/tmp/lynx-*/." then permit ( + > native-fsread: filename eq "$HOME" then permit + > native-fsread: filename eq "/etc/lynx.cfg" then permit + > native-fsread: filename eq "/" then permit + > native-fsread: filename eq "/usr/obj/bin/systrace/." then + > native-fsread: filename eq "/usr/obj/bin" then permit + > native-fcntl: permit + > native-getdirentries: permit + > native-lseek: permit + > native-fsread: filename eq "/usr/obj" then permit + native-fsread: filename eq "/usr" then permit ( + native-fsread: filename eq "/usr/bin" then permit ( + native-fsread: filename eq "/usr/games" then permit ( + native-fsread: filename eq "/usr/include" then permit ( + native-fsread: filename eq "/usr/lib" then permit ( + native-fsread: filename match "/usr/lib/libc.so.*" then p ( + native-fsread: filename match "/usr/lib/libcrypto.so.*" t ( + native-fsread: filename match "/usr/lib/libncurses.so.*" ( + native-fsread: filename match "/usr/lib/libssl.so.*" then ( + native-fsread: filename eq "/usr/libdata" then permit ( + native-fsread: filename eq "/usr/libexec" then permit ( + native-fsread: filename eq "/usr/lkm" then permit ( + native-fsread: filename eq "/usr/local" then permit ( + native-fsread: filename eq "/usr/mdec" then permit ( + native-fsread: filename eq "/usr/obj" then permit ( + native-fsread: filename eq "/usr/obj/bin" then permit ( + native-fsread: filename eq "/usr/obj/bin/systrace/." then ( + native-fsread: filename eq "/usr/obj/bin/systrace/.mailca ( + native-fsread: filename eq "/usr/obj/bin/systrace/.mime.t ( + > native-fsread: filename eq "$HOME/.mime.types" then permi + > native-sigaction: permit + > native-ioctl: permit + > native-fsread: filename eq "$HOME/.terminfo.db" then perm + > native-fsread: filename eq "$HOME/.terminfo" then permit + native-fsread: filename eq "/usr/share/misc/terminfo.db" ( + > native-pread: permit + > native-write: permit + > native-fsread: filename eq "$HOME/.lynx-keymaps" then per + native-fsread: filename eq "/var/run/dev.db" then permit ( + native-fsread: filename eq "/var/run/ld.so.hints" then pe | native-fsread: filename eq "/etc/utmp" then permit + native-fstat: permit < + native-fswrite: filename match "/tmp/lynx-*" then permit < + native-getdirentries: permit < + native-getpid: permit < + native-gettimeofday: permit < + native-ioctl: permit < + native-issetugid: permit < + native-lseek: permit < + native-mmap: permit < + native-mprotect: prot eq "PROT_READ" then permit < + native-mprotect: prot eq "PROT_READ|PROT_EXEC" then permi < + native-mprotect: prot eq "PROT_READ|PROT_WRITE" then perm < + native-mprotect: prot eq "PROT_READ|PROT_WRITE|PROT_EXEC" < + native-munmap: permit < + native-nanosleep: permit < + native-poll: permit ( + native-pread: permit | native-nanosleep: permit + native-read: permit | native-gettimeofday: permit + native-recvfrom: permit | native-fsread: filename eq "/etc/resolv.conf" then permit + native-select: permit < + native-sendto: true then permit < + native-sigaction: permit < + native-sigprocmask: permit < + native-socket: sockdom eq "AF_INET" and socktype eq "SOCK ( + > native-connect: sockaddr eq "inet-[127.0.0.1]:53" then pe + > native-sendto: true then permit + > native-select: permit + > native-recvfrom: permit + native-socket: sockdom eq "AF_INET" and socktype eq "SOCK ( + native-write: permit | native-connect: sockaddr match "inet-\\\[*\\\]:80" then p + > native-exit: permit diff --git a/tests/usr.bin/sdiff/d_iflags_c2.out b/tests/usr.bin/sdiff/d_iflags_c2.out new file mode 100644 index 000000000..fe7af0ebe --- /dev/null +++ b/tests/usr.bin/sdiff/d_iflags_c2.out @@ -0,0 +1,94 @@ +Policy: /usr/bin/lynx, Emulation: native ( + native-issetugid: permit < + native-mprotect: permit < + native-mmap: permit < + native-__sysctl: permit ( + native-fsread: filename eq "/var/run/ld.so.hints" then pe < + native-fstat: permit < + native-close: permit ( + native-fsread: filename match "/usr/lib/libssl.so.*" then | native-connect: sockaddr eq "inet-[127.0.0.1]:53" then pe + native-read: permit | native-connect: sockaddr match "inet-\\\[*\\\]:80" then p + native-fsread: filename match "/usr/lib/libcrypto.so.*" t | native-exit: permit + native-fsread: filename match "/usr/lib/libncurses.so.*" | native-fcntl: cmd eq "F_SETFD" then permit + native-fsread: filename match "/usr/lib/libc.so.*" then p | native-fsread: filename eq "/" then permit + native-munmap: permit | native-fsread: filename match "/: + native-sigprocmask: permit | native-fsread: filename eq "/etc/lynx.cfg" then permit + native-fsread: filename eq "/etc/malloc.conf" then permit ( + native-getpid: permit | native-fsread: filename eq "/etc/resolv.conf" then permit + > native-fsread: filename eq "/etc/utmp" then permit + > native-fsread: filename eq "/home" then permit + > native-fsread: filename eq "$HOME" then permit + > native-fsread: filename eq "$HOME/.lynx-keymaps" then per + > native-fsread: filename eq "$HOME/.lynxrc" then permit + > native-fsread: filename eq "$HOME/.mailcap" then permit + > native-fsread: filename eq "$HOME/.mime.types" then permi + > native-fsread: filename eq "$HOME/.terminfo" then permit + > native-fsread: filename eq "$HOME/.terminfo.db" then perm + > native-fsread: filename eq "/obj" then permit + native-fsread: filename eq "/tmp" then permit ( + native-fswrite: filename match "/tmp/lynx-*" then permit ( + native-fsread: filename match "/tmp/lynx-*/." then permit ( + native-fsread: filename eq "$HOME" then permit < + native-fsread: filename eq "/etc/lynx.cfg" then permit < + native-fsread: filename eq "/" then permit < + native-fsread: filename eq "/usr/obj/bin/systrace/." then < + native-fsread: filename eq "/usr/obj/bin" then permit < + native-fcntl: permit < + native-getdirentries: permit < + native-lseek: permit < + native-fsread: filename eq "/usr/obj" then permit < + native-fsread: filename eq "/usr" then permit ( + native-fsread: filename eq "/usr/bin" then permit ( + native-fsread: filename eq "/usr/games" then permit ( + native-fsread: filename eq "/usr/include" then permit ( + native-fsread: filename eq "/usr/lib" then permit ( + native-fsread: filename eq "/usr/libdata" then permit ( + native-fsread: filename eq "/usr/libexec" then permit ( + native-fsread: filename eq "/usr/lkm" then permit ( + native-fsread: filename eq "/usr/local" then permit ( + native-fsread: filename eq "/usr/mdec" then permit ( + native-fsread: filename eq "/home" then permit ( + native-fsread: filename eq "/obj" then permit ( + native-fsread: filename eq "$HOME/.lynxrc" then permit ( + native-fsread: filename match "/: ( + native-fsread: filename eq "/usr/obj/bin/systrace/.mailca ( + native-fsread: filename eq "$HOME/.mailcap" then permit ( + native-fsread: filename eq "/usr/obj/bin/systrace/.mime.t ( + native-fsread: filename eq "$HOME/.mime.types" then permi < + native-sigaction: permit < + native-ioctl: permit < + native-fsread: filename eq "$HOME/.terminfo.db" then perm < + native-fsread: filename eq "$HOME/.terminfo" then permit < + native-fsread: filename eq "/usr/share/misc/terminfo.db" ( + native-pread: permit < + native-write: permit < + native-fsread: filename eq "$HOME/.lynx-keymaps" then per < + native-fsread: filename eq "/var/run/dev.db" then permit ( + native-fsread: filename eq "/etc/utmp" then permit | native-fsread: filename eq "/var/run/ld.so.hints" then pe + native-poll: permit | native-fstat: permit + native-nanosleep: permit | native-fswrite: filename match "/tmp/lynx-*" then permit + > native-getdirentries: permit + > native-getpid: permit + native-gettimeofday: permit ( + native-fsread: filename eq "/etc/resolv.conf" then permit | native-ioctl: permit + native-socket: sockdom eq "AF_INET" and socktype eq "SOCK | native-issetugid: permit + native-connect: sockaddr eq "inet-[127.0.0.1]:53" then pe | native-lseek: permit + native-sendto: true then permit | native-mmap: permit + native-select: permit | native-mprotect: prot eq "PROT_READ" then permit + > native-mprotect: prot eq "PROT_READ|PROT_EXEC" then permi + > native-mprotect: prot eq "PROT_READ|PROT_WRITE" then perm + > native-mprotect: prot eq "PROT_READ|PROT_WRITE|PROT_EXEC" + > native-munmap: permit + > native-nanosleep: permit + > native-poll: permit + > native-pread: permit + > native-read: permit + native-recvfrom: permit ( + > native-select: permit + > native-sendto: true then permit + > native-sigaction: permit + > native-sigprocmask: permit + > native-socket: sockdom eq "AF_INET" and socktype eq "SOCK + native-socket: sockdom eq "AF_INET" and socktype eq "SOCK ( + native-connect: sockaddr match "inet-\\\[*\\\]:80" then p | native-write: permit + native-exit: permit < diff --git a/tests/usr.bin/sdiff/d_iflags_d1.out b/tests/usr.bin/sdiff/d_iflags_d1.out new file mode 100644 index 000000000..3e548b693 --- /dev/null +++ b/tests/usr.bin/sdiff/d_iflags_d1.out @@ -0,0 +1,69 @@ + > native-issetugid: permit + > native-mprotect: permit + > native-mmap: permit + > native-fsread: filename eq "/var/run/ld.so.hints" then pe + > native-fstat: permit + native-connect: sockaddr eq "inet-[127.0.0.1]:53" then pe | native-fsread: filename match "/usr/lib/libssl.so.*" then + native-connect: sockaddr match "inet-\\\[*\\\]:80" then p | native-read: permit + native-exit: permit | native-fsread: filename match "/usr/lib/libcrypto.so.*" t + native-fcntl: cmd eq "F_SETFD" then permit | native-fsread: filename match "/usr/lib/libncurses.so.*" + native-fsread: filename eq "/" then permit | native-fsread: filename match "/usr/lib/libc.so.*" then p + native-fsread: filename match "/: | native-munmap: permit + native-fsread: filename eq "/etc/lynx.cfg" then permit | native-sigprocmask: permit + native-fsread: filename eq "/etc/resolv.conf" then permit | native-getpid: permit + native-fsread: filename eq "/etc/utmp" then permit < + native-fsread: filename eq "/home" then permit < + native-fsread: filename eq "$HOME" then permit < + native-fsread: filename eq "$HOME/.lynx-keymaps" then per < + native-fsread: filename eq "$HOME/.lynxrc" then permit < + native-fsread: filename eq "$HOME/.mailcap" then permit < + native-fsread: filename eq "$HOME/.mime.types" then permi < + native-fsread: filename eq "$HOME/.terminfo" then permit < + native-fsread: filename eq "$HOME/.terminfo.db" then perm < + native-fsread: filename eq "/obj" then permit < + > native-fsread: filename eq "$HOME" then permit + > native-fsread: filename eq "/etc/lynx.cfg" then permit + > native-fsread: filename eq "/" then permit + > native-fsread: filename eq "/usr/obj/bin/systrace/." then + > native-fsread: filename eq "/usr/obj/bin" then permit + > native-fcntl: permit + > native-getdirentries: permit + > native-lseek: permit + > native-fsread: filename eq "/usr/obj" then permit + > native-fsread: filename eq "$HOME/.mime.types" then permi + > native-sigaction: permit + > native-ioctl: permit + > native-fsread: filename eq "$HOME/.terminfo.db" then perm + > native-fsread: filename eq "$HOME/.terminfo" then permit + > native-pread: permit + > native-write: permit + > native-fsread: filename eq "$HOME/.lynx-keymaps" then per + native-fsread: filename eq "/var/run/ld.so.hints" then pe | native-fsread: filename eq "/etc/utmp" then permit + native-fstat: permit < + native-fswrite: filename match "/tmp/lynx-*" then permit < + native-getdirentries: permit < + native-getpid: permit < + native-gettimeofday: permit < + native-ioctl: permit < + native-issetugid: permit < + native-lseek: permit < + native-mmap: permit < + native-mprotect: prot eq "PROT_READ" then permit < + native-mprotect: prot eq "PROT_READ|PROT_EXEC" then permi < + native-mprotect: prot eq "PROT_READ|PROT_WRITE" then perm < + native-mprotect: prot eq "PROT_READ|PROT_WRITE|PROT_EXEC" < + native-munmap: permit < + native-nanosleep: permit < + native-pread: permit | native-nanosleep: permit + native-read: permit | native-gettimeofday: permit + native-recvfrom: permit | native-fsread: filename eq "/etc/resolv.conf" then permit + native-select: permit < + native-sendto: true then permit < + native-sigaction: permit < + native-sigprocmask: permit < + > native-connect: sockaddr eq "inet-[127.0.0.1]:53" then pe + > native-sendto: true then permit + > native-select: permit + > native-recvfrom: permit + native-write: permit | native-connect: sockaddr match "inet-\\\[*\\\]:80" then p + > native-exit: permit diff --git a/tests/usr.bin/sdiff/d_iflags_d2.out b/tests/usr.bin/sdiff/d_iflags_d2.out new file mode 100644 index 000000000..4504c36ec --- /dev/null +++ b/tests/usr.bin/sdiff/d_iflags_d2.out @@ -0,0 +1,65 @@ + native-issetugid: permit < + native-mprotect: permit < + native-mmap: permit < + native-fsread: filename eq "/var/run/ld.so.hints" then pe < + native-fstat: permit < + native-fsread: filename match "/usr/lib/libssl.so.*" then | native-connect: sockaddr eq "inet-[127.0.0.1]:53" then pe + native-read: permit | native-connect: sockaddr match "inet-\\\[*\\\]:80" then p + native-fsread: filename match "/usr/lib/libcrypto.so.*" t | native-exit: permit + native-fsread: filename match "/usr/lib/libncurses.so.*" | native-fcntl: cmd eq "F_SETFD" then permit + native-fsread: filename match "/usr/lib/libc.so.*" then p | native-fsread: filename eq "/" then permit + native-munmap: permit | native-fsread: filename match "/: + native-sigprocmask: permit | native-fsread: filename eq "/etc/lynx.cfg" then permit + native-getpid: permit | native-fsread: filename eq "/etc/resolv.conf" then permit + > native-fsread: filename eq "/etc/utmp" then permit + > native-fsread: filename eq "/home" then permit + > native-fsread: filename eq "$HOME" then permit + > native-fsread: filename eq "$HOME/.lynx-keymaps" then per + > native-fsread: filename eq "$HOME/.lynxrc" then permit + > native-fsread: filename eq "$HOME/.mailcap" then permit + > native-fsread: filename eq "$HOME/.mime.types" then permi + > native-fsread: filename eq "$HOME/.terminfo" then permit + > native-fsread: filename eq "$HOME/.terminfo.db" then perm + > native-fsread: filename eq "/obj" then permit + native-fsread: filename eq "$HOME" then permit < + native-fsread: filename eq "/etc/lynx.cfg" then permit < + native-fsread: filename eq "/" then permit < + native-fsread: filename eq "/usr/obj/bin/systrace/." then < + native-fsread: filename eq "/usr/obj/bin" then permit < + native-fcntl: permit < + native-getdirentries: permit < + native-lseek: permit < + native-fsread: filename eq "/usr/obj" then permit < + native-fsread: filename eq "$HOME/.mime.types" then permi < + native-sigaction: permit < + native-ioctl: permit < + native-fsread: filename eq "$HOME/.terminfo.db" then perm < + native-fsread: filename eq "$HOME/.terminfo" then permit < + native-pread: permit < + native-write: permit < + native-fsread: filename eq "$HOME/.lynx-keymaps" then per < + native-fsread: filename eq "/etc/utmp" then permit | native-fsread: filename eq "/var/run/ld.so.hints" then pe + native-poll: permit | native-fstat: permit + native-nanosleep: permit | native-fswrite: filename match "/tmp/lynx-*" then permit + > native-getdirentries: permit + > native-getpid: permit + native-fsread: filename eq "/etc/resolv.conf" then permit | native-ioctl: permit + native-socket: sockdom eq "AF_INET" and socktype eq "SOCK | native-issetugid: permit + native-connect: sockaddr eq "inet-[127.0.0.1]:53" then pe | native-lseek: permit + native-sendto: true then permit | native-mmap: permit + native-select: permit | native-mprotect: prot eq "PROT_READ" then permit + > native-mprotect: prot eq "PROT_READ|PROT_EXEC" then permi + > native-mprotect: prot eq "PROT_READ|PROT_WRITE" then perm + > native-mprotect: prot eq "PROT_READ|PROT_WRITE|PROT_EXEC" + > native-munmap: permit + > native-nanosleep: permit + > native-poll: permit + > native-pread: permit + > native-read: permit + > native-select: permit + > native-sendto: true then permit + > native-sigaction: permit + > native-sigprocmask: permit + > native-socket: sockdom eq "AF_INET" and socktype eq "SOCK + native-connect: sockaddr match "inet-\\\[*\\\]:80" then p | native-write: permit + native-exit: permit < diff --git a/tests/usr.bin/sdiff/d_input1 b/tests/usr.bin/sdiff/d_input1 new file mode 100644 index 000000000..686e8ea22 --- /dev/null +++ b/tests/usr.bin/sdiff/d_input1 @@ -0,0 +1,72 @@ +Policy: /usr/bin/lynx, Emulation: native + native-__sysctl: permit + native-close: permit + native-connect: sockaddr eq "inet-[127.0.0.1]:53" then permit + native-connect: sockaddr match "inet-\\\[*\\\]:80" then permit + native-exit: permit + native-fcntl: cmd eq "F_SETFD" then permit + native-fsread: filename eq "/" then permit + native-fsread: filename match "/: *" then permit + native-fsread: filename eq "/etc/lynx.cfg" then permit + native-fsread: filename eq "/etc/malloc.conf" then permit + native-fsread: filename eq "/etc/resolv.conf" then permit + native-fsread: filename eq "/etc/utmp" then permit + native-fsread: filename eq "/home" then permit + native-fsread: filename eq "$HOME" then permit + native-fsread: filename eq "$HOME/.lynx-keymaps" then permit + native-fsread: filename eq "$HOME/.lynxrc" then permit + native-fsread: filename eq "$HOME/.mailcap" then permit + native-fsread: filename eq "$HOME/.mime.types" then permit + native-fsread: filename eq "$HOME/.terminfo" then permit + native-fsread: filename eq "$HOME/.terminfo.db" then permit + native-fsread: filename eq "/obj" then permit + native-fsread: filename eq "/tmp" then permit + native-fsread: filename match "/tmp/lynx-*/." then permit + native-fsread: filename eq "/usr" then permit + native-fsread: filename eq "/usr/bin" then permit + native-fsread: filename eq "/usr/games" then permit + native-fsread: filename eq "/usr/include" then permit + native-fsread: filename eq "/usr/lib" then permit + native-fsread: filename match "/usr/lib/libc.so.*" then permit + native-fsread: filename match "/usr/lib/libcrypto.so.*" then permit + native-fsread: filename match "/usr/lib/libncurses.so.*" then permit + native-fsread: filename match "/usr/lib/libssl.so.*" then permit + native-fsread: filename eq "/usr/libdata" then permit + native-fsread: filename eq "/usr/libexec" then permit + native-fsread: filename eq "/usr/lkm" then permit + native-fsread: filename eq "/usr/local" then permit + native-fsread: filename eq "/usr/mdec" then permit + native-fsread: filename eq "/usr/obj" then permit + native-fsread: filename eq "/usr/obj/bin" then permit + native-fsread: filename eq "/usr/obj/bin/systrace/." then permit + native-fsread: filename eq "/usr/obj/bin/systrace/.mailcap" then permit + native-fsread: filename eq "/usr/obj/bin/systrace/.mime.types" then permit + native-fsread: filename eq "/usr/share/misc/terminfo.db" then permit + native-fsread: filename eq "/var/run/dev.db" then permit + native-fsread: filename eq "/var/run/ld.so.hints" then permit + native-fstat: permit + native-fswrite: filename match "/tmp/lynx-*" then permit + native-getdirentries: permit + native-getpid: permit + native-gettimeofday: permit + native-ioctl: permit + native-issetugid: permit + native-lseek: permit + native-mmap: permit + native-mprotect: prot eq "PROT_READ" then permit + native-mprotect: prot eq "PROT_READ|PROT_EXEC" then permit + native-mprotect: prot eq "PROT_READ|PROT_WRITE" then permit + native-mprotect: prot eq "PROT_READ|PROT_WRITE|PROT_EXEC" then permit + native-munmap: permit + native-nanosleep: permit + native-poll: permit + native-pread: permit + native-read: permit + native-recvfrom: permit + native-select: permit + native-sendto: true then permit + native-sigaction: permit + native-sigprocmask: permit + native-socket: sockdom eq "AF_INET" and socktype eq "SOCK_DGRAM" then permit + native-socket: sockdom eq "AF_INET" and socktype eq "SOCK_STREAM" then permit + native-write: permit diff --git a/tests/usr.bin/sdiff/d_input2 b/tests/usr.bin/sdiff/d_input2 new file mode 100644 index 000000000..70e1b57f5 --- /dev/null +++ b/tests/usr.bin/sdiff/d_input2 @@ -0,0 +1,69 @@ +Policy: /usr/bin/lynx, Emulation: native + native-issetugid: permit + native-mprotect: permit + native-mmap: permit + native-__sysctl: permit + native-fsread: filename eq "/var/run/ld.so.hints" then permit + native-fstat: permit + native-close: permit + native-fsread: filename match "/usr/lib/libssl.so.*" then permit + native-read: permit + native-fsread: filename match "/usr/lib/libcrypto.so.*" then permit + native-fsread: filename match "/usr/lib/libncurses.so.*" then permit + native-fsread: filename match "/usr/lib/libc.so.*" then permit + native-munmap: permit + native-sigprocmask: permit + native-fsread: filename eq "/etc/malloc.conf" then permit + native-getpid: permit + native-fsread: filename eq "/tmp" then permit + native-fswrite: filename match "/tmp/lynx-*" then permit + native-fsread: filename match "/tmp/lynx-*/." then permit + native-fsread: filename eq "$HOME" then permit + native-fsread: filename eq "/etc/lynx.cfg" then permit + native-fsread: filename eq "/" then permit + native-fsread: filename eq "/usr/obj/bin/systrace/." then permit + native-fsread: filename eq "/usr/obj/bin" then permit + native-fcntl: permit + native-getdirentries: permit + native-lseek: permit + native-fsread: filename eq "/usr/obj" then permit + native-fsread: filename eq "/usr" then permit + native-fsread: filename eq "/usr/bin" then permit + native-fsread: filename eq "/usr/games" then permit + native-fsread: filename eq "/usr/include" then permit + native-fsread: filename eq "/usr/lib" then permit + native-fsread: filename eq "/usr/libdata" then permit + native-fsread: filename eq "/usr/libexec" then permit + native-fsread: filename eq "/usr/lkm" then permit + native-fsread: filename eq "/usr/local" then permit + native-fsread: filename eq "/usr/mdec" then permit + native-fsread: filename eq "/home" then permit + native-fsread: filename eq "/obj" then permit + native-fsread: filename eq "$HOME/.lynxrc" then permit + native-fsread: filename match "/: *" then permit + native-fsread: filename eq "/usr/obj/bin/systrace/.mailcap" then permit + native-fsread: filename eq "$HOME/.mailcap" then permit + native-fsread: filename eq "/usr/obj/bin/systrace/.mime.types" then permit + native-fsread: filename eq "$HOME/.mime.types" then permit + native-sigaction: permit + native-ioctl: permit + native-fsread: filename eq "$HOME/.terminfo.db" then permit + native-fsread: filename eq "$HOME/.terminfo" then permit + native-fsread: filename eq "/usr/share/misc/terminfo.db" then permit + native-pread: permit + native-write: permit + native-fsread: filename eq "$HOME/.lynx-keymaps" then permit + native-fsread: filename eq "/var/run/dev.db" then permit + native-fsread: filename eq "/etc/utmp" then permit + native-poll: permit + native-nanosleep: permit + native-gettimeofday: permit + native-fsread: filename eq "/etc/resolv.conf" then permit + native-socket: sockdom eq "AF_INET" and socktype eq "SOCK_DGRAM" then permit + native-connect: sockaddr eq "inet-[127.0.0.1]:53" then permit + native-sendto: true then permit + native-select: permit + native-recvfrom: permit + native-socket: sockdom eq "AF_INET" and socktype eq "SOCK_STREAM" then permit + native-connect: sockaddr match "inet-\\\[*\\\]:80" then permit + native-exit: permit diff --git a/tests/usr.bin/sdiff/d_oneline.in b/tests/usr.bin/sdiff/d_oneline.in new file mode 100644 index 000000000..acbe86c7c --- /dev/null +++ b/tests/usr.bin/sdiff/d_oneline.in @@ -0,0 +1 @@ +abcd diff --git a/tests/usr.bin/sdiff/d_oneline_a.out b/tests/usr.bin/sdiff/d_oneline_a.out new file mode 100644 index 000000000..99560a6dd --- /dev/null +++ b/tests/usr.bin/sdiff/d_oneline_a.out @@ -0,0 +1 @@ + > abcd diff --git a/tests/usr.bin/sdiff/d_oneline_b.out b/tests/usr.bin/sdiff/d_oneline_b.out new file mode 100644 index 000000000..7300b1de1 --- /dev/null +++ b/tests/usr.bin/sdiff/d_oneline_b.out @@ -0,0 +1 @@ +abcd < diff --git a/tests/usr.bin/sdiff/d_same.out b/tests/usr.bin/sdiff/d_same.out new file mode 100644 index 000000000..bce894420 --- /dev/null +++ b/tests/usr.bin/sdiff/d_same.out @@ -0,0 +1,72 @@ +Policy: /usr/bin/lynx, Emulation: native Policy: /usr/bin/lynx, Emulation: native + native-__sysctl: permit native-__sysctl: permit + native-close: permit native-close: permit + native-connect: sockaddr eq "inet-[127.0.0.1]:53" then perm native-connect: sockaddr eq "inet-[127.0.0.1]:53" then perm + native-connect: sockaddr match "inet-\\\[*\\\]:80" then per native-connect: sockaddr match "inet-\\\[*\\\]:80" then per + native-exit: permit native-exit: permit + native-fcntl: cmd eq "F_SETFD" then permit native-fcntl: cmd eq "F_SETFD" then permit + native-fsread: filename eq "/" then permit native-fsread: filename eq "/" then permit + native-fsread: filename match "/: *" native-fsread: filename match "/: *" + native-fsread: filename eq "/etc/lynx.cfg" then permit native-fsread: filename eq "/etc/lynx.cfg" then permit + native-fsread: filename eq "/etc/malloc.conf" then permit native-fsread: filename eq "/etc/malloc.conf" then permit + native-fsread: filename eq "/etc/resolv.conf" then permit native-fsread: filename eq "/etc/resolv.conf" then permit + native-fsread: filename eq "/etc/utmp" then permit native-fsread: filename eq "/etc/utmp" then permit + native-fsread: filename eq "/home" then permit native-fsread: filename eq "/home" then permit + native-fsread: filename eq "$HOME" then permit native-fsread: filename eq "$HOME" then permit + native-fsread: filename eq "$HOME/.lynx-keymaps" then permi native-fsread: filename eq "$HOME/.lynx-keymaps" then permi + native-fsread: filename eq "$HOME/.lynxrc" then permit native-fsread: filename eq "$HOME/.lynxrc" then permit + native-fsread: filename eq "$HOME/.mailcap" then permit native-fsread: filename eq "$HOME/.mailcap" then permit + native-fsread: filename eq "$HOME/.mime.types" then permit native-fsread: filename eq "$HOME/.mime.types" then permit + native-fsread: filename eq "$HOME/.terminfo" then permit native-fsread: filename eq "$HOME/.terminfo" then permit + native-fsread: filename eq "$HOME/.terminfo.db" then permit native-fsread: filename eq "$HOME/.terminfo.db" then permit + native-fsread: filename eq "/obj" then permit native-fsread: filename eq "/obj" then permit + native-fsread: filename eq "/tmp" then permit native-fsread: filename eq "/tmp" then permit + native-fsread: filename match "/tmp/lynx-*/." then permit native-fsread: filename match "/tmp/lynx-*/." then permit + native-fsread: filename eq "/usr" then permit native-fsread: filename eq "/usr" then permit + native-fsread: filename eq "/usr/bin" then permit native-fsread: filename eq "/usr/bin" then permit + native-fsread: filename eq "/usr/games" then permit native-fsread: filename eq "/usr/games" then permit + native-fsread: filename eq "/usr/include" then permit native-fsread: filename eq "/usr/include" then permit + native-fsread: filename eq "/usr/lib" then permit native-fsread: filename eq "/usr/lib" then permit + native-fsread: filename match "/usr/lib/libc.so.*" then per native-fsread: filename match "/usr/lib/libc.so.*" then per + native-fsread: filename match "/usr/lib/libcrypto.so.*" the native-fsread: filename match "/usr/lib/libcrypto.so.*" the + native-fsread: filename match "/usr/lib/libncurses.so.*" th native-fsread: filename match "/usr/lib/libncurses.so.*" th + native-fsread: filename match "/usr/lib/libssl.so.*" then p native-fsread: filename match "/usr/lib/libssl.so.*" then p + native-fsread: filename eq "/usr/libdata" then permit native-fsread: filename eq "/usr/libdata" then permit + native-fsread: filename eq "/usr/libexec" then permit native-fsread: filename eq "/usr/libexec" then permit + native-fsread: filename eq "/usr/lkm" then permit native-fsread: filename eq "/usr/lkm" then permit + native-fsread: filename eq "/usr/local" then permit native-fsread: filename eq "/usr/local" then permit + native-fsread: filename eq "/usr/mdec" then permit native-fsread: filename eq "/usr/mdec" then permit + native-fsread: filename eq "/usr/obj" then permit native-fsread: filename eq "/usr/obj" then permit + native-fsread: filename eq "/usr/obj/bin" then permit native-fsread: filename eq "/usr/obj/bin" then permit + native-fsread: filename eq "/usr/obj/bin/systrace/." then p native-fsread: filename eq "/usr/obj/bin/systrace/." then p + native-fsread: filename eq "/usr/obj/bin/systrace/.mailcap" native-fsread: filename eq "/usr/obj/bin/systrace/.mailcap" + native-fsread: filename eq "/usr/obj/bin/systrace/.mime.typ native-fsread: filename eq "/usr/obj/bin/systrace/.mime.typ + native-fsread: filename eq "/usr/share/misc/terminfo.db" th native-fsread: filename eq "/usr/share/misc/terminfo.db" th + native-fsread: filename eq "/var/run/dev.db" then permit native-fsread: filename eq "/var/run/dev.db" then permit + native-fsread: filename eq "/var/run/ld.so.hints" then perm native-fsread: filename eq "/var/run/ld.so.hints" then perm + native-fstat: permit native-fstat: permit + native-fswrite: filename match "/tmp/lynx-*" then permit native-fswrite: filename match "/tmp/lynx-*" then permit + native-getdirentries: permit native-getdirentries: permit + native-getpid: permit native-getpid: permit + native-gettimeofday: permit native-gettimeofday: permit + native-ioctl: permit native-ioctl: permit + native-issetugid: permit native-issetugid: permit + native-lseek: permit native-lseek: permit + native-mmap: permit native-mmap: permit + native-mprotect: prot eq "PROT_READ" then permit native-mprotect: prot eq "PROT_READ" then permit + native-mprotect: prot eq "PROT_READ|PROT_EXEC" then permit native-mprotect: prot eq "PROT_READ|PROT_EXEC" then permit + native-mprotect: prot eq "PROT_READ|PROT_WRITE" then permit native-mprotect: prot eq "PROT_READ|PROT_WRITE" then permit + native-mprotect: prot eq "PROT_READ|PROT_WRITE|PROT_EXEC" t native-mprotect: prot eq "PROT_READ|PROT_WRITE|PROT_EXEC" t + native-munmap: permit native-munmap: permit + native-nanosleep: permit native-nanosleep: permit + native-poll: permit native-poll: permit + native-pread: permit native-pread: permit + native-read: permit native-read: permit + native-recvfrom: permit native-recvfrom: permit + native-select: permit native-select: permit + native-sendto: true then permit native-sendto: true then permit + native-sigaction: permit native-sigaction: permit + native-sigprocmask: permit native-sigprocmask: permit + native-socket: sockdom eq "AF_INET" and socktype eq "SOCK_D native-socket: sockdom eq "AF_INET" and socktype eq "SOCK_D + native-socket: sockdom eq "AF_INET" and socktype eq "SOCK_S native-socket: sockdom eq "AF_INET" and socktype eq "SOCK_S + native-write: permit native-write: permit diff --git a/tests/usr.bin/sdiff/d_short.out b/tests/usr.bin/sdiff/d_short.out new file mode 100644 index 000000000..7a3346017 --- /dev/null +++ b/tests/usr.bin/sdiff/d_short.out @@ -0,0 +1,15 @@ +Policy: /usr/bin/lynx, Emulation: native + native-issetugid: permit + native-mprotect: permit + native-mmap: permit + native-__sysctl: permit + native-close: permit + native-fsread: filename match "/usr/lib/libssl.so.*" then permit + native-read: permit + native-fsread: filename match "/usr/lib/libcrypto.so.*" then permit + native-fsread: filename match "/usr/lib/libncurses.so.*" then permit + native-fsread: filename match "/usr/lib/libc.so.*" then permit + native-munmap: permit + native-sigprocmask: permit + native-fsread: filename eq "/etc/malloc.conf" then permit + native-fsread: filename eq "/etc/resolv.conf" then permit diff --git a/tests/usr.bin/sdiff/d_tabends.in b/tests/usr.bin/sdiff/d_tabends.in new file mode 100644 index 000000000..0547049d4 --- /dev/null +++ b/tests/usr.bin/sdiff/d_tabends.in @@ -0,0 +1,17 @@ + +0 +01 +012 +0123 +01234 +012345 +0123456 +01234567 +012345670 +0123456701 +01234567012 +012345670123 +0123456701234 +01234567012345 +012345670123456 +0123456701234567 diff --git a/tests/usr.bin/sdiff/d_tabends_a.out b/tests/usr.bin/sdiff/d_tabends_a.out new file mode 100644 index 000000000..423bd02ce --- /dev/null +++ b/tests/usr.bin/sdiff/d_tabends_a.out @@ -0,0 +1,17 @@ + < +0 < +01 < +012 < +0123 < +01234 < +012345 < +0123456 < +01234567 < +012345670 < +0123456701 < +01234567012 < +012345670123 < +0123456701234 < +0123456701234 < +0123456701234 < +0123456701234 < diff --git a/tests/usr.bin/sdiff/d_tabends_b.out b/tests/usr.bin/sdiff/d_tabends_b.out new file mode 100644 index 000000000..b18070545 --- /dev/null +++ b/tests/usr.bin/sdiff/d_tabends_b.out @@ -0,0 +1,17 @@ + > + > 0 + > 01 + > 012 + > 0123 + > 01234 + > 012345 + > 0123456 + > 01234567 + > 012345670 + > 0123456701 + > 01234567012 + > 012345670123 + > 0123456701234 + > 0123456701234 + > 0123456701234 + > 0123456701234 diff --git a/tests/usr.bin/sdiff/d_tabends_c.out b/tests/usr.bin/sdiff/d_tabends_c.out new file mode 100644 index 000000000..c3013824a --- /dev/null +++ b/tests/usr.bin/sdiff/d_tabends_c.out @@ -0,0 +1,17 @@ + < +0 < +01 < +012 < +0123 < +01234 < +012345 < +0123456 < +01234567 < +01234567 < +01234567 < +01234567 < +01234567 < +01234567 < +01234567 < +01234567 < +01234567 < diff --git a/tests/usr.bin/sdiff/d_tabs.out b/tests/usr.bin/sdiff/d_tabs.out new file mode 100644 index 000000000..eb34bace6 --- /dev/null +++ b/tests/usr.bin/sdiff/d_tabs.out @@ -0,0 +1,102 @@ +Policy: /usr/bin/lynx, Emulation: native Policy: /usr/bin/lynx, Emulation: native + > native-issetugid: permit + > native-mprotect: permit + > native-mmap: permit + native-__sysctl: permit native-__sysctl: permit + > native-fsread: filename eq "/var/run/ld.so.hints" then pe + > native-fstat: permit + native-close: permit native-close: permit + native-connect: sockaddr eq "inet-[127.0.0.1]:53" then | native-fsread: filename match "/usr/lib/libssl.so.*" then + native-connect: sockaddr match "inet-\\\[*\\\]:80" then | native-read: permit + native-exit: permit | native-fsread: filename match "/usr/lib/libcrypto.so.*" t + native-fcntl: cmd eq "F_SETFD" then permit | native-fsread: filename match "/usr/lib/libncurses.so.*" + native-fsread: filename eq "/" then permit | native-fsread: filename match "/usr/lib/libc.so.*" then p + native-fsread: filename match "/ | native-munmap: permit + native-fsread: filename eq "/etc/lynx.cfg" then permit | native-sigprocmask: permit + native-fsread: filename eq "/etc/malloc.conf" then perm native-fsread: filename eq "/etc/malloc.conf" then permit + native-fsread: filename eq "/etc/resolv.conf" then perm | native-getpid: permit + native-fsread: filename eq "/etc/utmp" then permit < + native-fsread: filename eq "/home" then permit < + native-fsread: filename eq "$HOME" then permit < + native-fsread: filename eq "$HOME/.lynx-keymaps" then p < + native-fsread: filename eq "$HOME/.lynxrc" then permit < + native-fsread: filename eq "$HOME/.mailcap" then permit < + native-fsread: filename eq "$HOME/.mime.types" then per < + native-fsread: filename eq "$HOME/.terminfo" then permi < + native-fsread: filename eq "$HOME/.terminfo.db" then pe < + native-fsread: filename eq "/obj" then permit < + native-fsread: filename eq "/tmp" then permit native-fsread: filename eq "/tmp" then permit + > native-fswrite: filename match "/tmp/lynx-*" then permit + native-fsread: filename match "/tmp/lynx-*/." then perm native-fsread: filename match "/tmp/lynx-*/." then permit + > native-fsread: filename eq "$HOME" then permit + > native-fsread: filename eq "/etc/lynx.cfg" then permit + > native-fsread: filename eq "/" then permit + > native-fsread: filename eq "/usr/obj/bin/systrace/." then + > native-fsread: filename eq "/usr/obj/bin" then permit + > native-fcntl: permit + > native-getdirentries: permit + > native-lseek: permit + > native-fsread: filename eq "/usr/obj" then permit + native-fsread: filename eq "/usr" then permit native-fsread: filename eq "/usr" then permit + native-fsread: filename eq "/usr/bin" then permit native-fsread: filename eq "/usr/bin" then permit + native-fsread: filename eq "/usr/games" then permit native-fsread: filename eq "/usr/games" then permit + native-fsread: filename eq "/usr/include" then permit native-fsread: filename eq "/usr/include" then permit + native-fsread: filename eq "/usr/lib" then permit native-fsread: filename eq "/usr/lib" then permit + native-fsread: filename match "/usr/lib/libc.so.*" then < + native-fsread: filename match "/usr/lib/libcrypto.so.*" < + native-fsread: filename match "/usr/lib/libncurses.so.* < + native-fsread: filename match "/usr/lib/libssl.so.*" th < + native-fsread: filename eq "/usr/libdata" then permit native-fsread: filename eq "/usr/libdata" then permit + native-fsread: filename eq "/usr/libexec" then permit native-fsread: filename eq "/usr/libexec" then permit + native-fsread: filename eq "/usr/lkm" then permit native-fsread: filename eq "/usr/lkm" then permit + native-fsread: filename eq "/usr/local" then permit native-fsread: filename eq "/usr/local" then permit + native-fsread: filename eq "/usr/mdec" then permit native-fsread: filename eq "/usr/mdec" then permit + native-fsread: filename eq "/usr/obj" then permit | native-fsread: filename eq "/home" then permit + native-fsread: filename eq "/usr/obj/bin" then permit | native-fsread: filename eq "/obj" then permit + native-fsread: filename eq "/usr/obj/bin/systrace/." th | native-fsread: filename eq "$HOME/.lynxrc" then permit + > native-fsread: filename match "/: + native-fsread: filename eq "/usr/obj/bin/systrace/.mail native-fsread: filename eq "/usr/obj/bin/systrace/.mailca + > native-fsread: filename eq "$HOME/.mailcap" then permit + native-fsread: filename eq "/usr/obj/bin/systrace/.mime native-fsread: filename eq "/usr/obj/bin/systrace/.mime.t + > native-fsread: filename eq "$HOME/.mime.types" then permi + > native-sigaction: permit + > native-ioctl: permit + > native-fsread: filename eq "$HOME/.terminfo.db" then perm + > native-fsread: filename eq "$HOME/.terminfo" then permit + native-fsread: filename eq "/usr/share/misc/terminfo.db native-fsread: filename eq "/usr/share/misc/terminfo.db" + > native-pread: permit + > native-write: permit + > native-fsread: filename eq "$HOME/.lynx-keymaps" then per + native-fsread: filename eq "/var/run/dev.db" then permi native-fsread: filename eq "/var/run/dev.db" then permit + native-fsread: filename eq "/var/run/ld.so.hints" then | native-fsread: filename eq "/etc/utmp" then permit + native-fstat: permit < + native-fswrite: filename match "/tmp/lynx-*" then permi < + native-getdirentries: permit < + native-getpid: permit < + native-gettimeofday: permit < + native-ioctl: permit < + native-issetugid: permit < + native-lseek: permit < + native-mmap: permit < + native-mprotect: prot eq "PROT_READ" then permit < + native-mprotect: prot eq "PROT_READ|PROT_EXEC" then per < + native-mprotect: prot eq "PROT_READ|PROT_WRITE" then pe < + native-mprotect: prot eq "PROT_READ|PROT_WRITE|PROT_EXE < + native-munmap: permit < + native-nanosleep: permit < + native-poll: permit native-poll: permit + native-pread: permit | native-nanosleep: permit + native-read: permit | native-gettimeofday: permit + native-recvfrom: permit | native-fsread: filename eq "/etc/resolv.conf" then permit + native-select: permit < + native-sendto: true then permit < + native-sigaction: permit < + native-sigprocmask: permit < + native-socket: sockdom eq "AF_INET" and socktype eq "SO native-socket: sockdom eq "AF_INET" and socktype eq "SOCK + > native-connect: sockaddr eq "inet-[127.0.0.1]:53" then pe + > native-sendto: true then permit + > native-select: permit + > native-recvfrom: permit + native-socket: sockdom eq "AF_INET" and socktype eq "SO native-socket: sockdom eq "AF_INET" and socktype eq "SOCK + native-write: permit | native-connect: sockaddr match "inet-\\\[*\\\]:80" then p + > native-exit: permit diff --git a/tests/usr.bin/sdiff/d_tabs1.in b/tests/usr.bin/sdiff/d_tabs1.in new file mode 100644 index 000000000..b5a1834a3 --- /dev/null +++ b/tests/usr.bin/sdiff/d_tabs1.in @@ -0,0 +1,72 @@ +Policy: /usr/bin/lynx, Emulation: native + native-__sysctl: permit + native-close: permit + native-connect: sockaddr eq "inet-[127.0.0.1]:53" then permit + native-connect: sockaddr match "inet-\\\[*\\\]:80" then permit + native-exit: permit + native-fcntl: cmd eq "F_SETFD" then permit + native-fsread: filename eq "/" then permit + native-fsread: filename match "/: *" then permit + native-fsread: filename eq "/etc/lynx.cfg" then permit + native-fsread: filename eq "/etc/malloc.conf" then permit + native-fsread: filename eq "/etc/resolv.conf" then permit + native-fsread: filename eq "/etc/utmp" then permit + native-fsread: filename eq "/home" then permit + native-fsread: filename eq "$HOME" then permit + native-fsread: filename eq "$HOME/.lynx-keymaps" then permit + native-fsread: filename eq "$HOME/.lynxrc" then permit + native-fsread: filename eq "$HOME/.mailcap" then permit + native-fsread: filename eq "$HOME/.mime.types" then permit + native-fsread: filename eq "$HOME/.terminfo" then permit + native-fsread: filename eq "$HOME/.terminfo.db" then permit + native-fsread: filename eq "/obj" then permit + native-fsread: filename eq "/tmp" then permit + native-fsread: filename match "/tmp/lynx-*/." then permit + native-fsread: filename eq "/usr" then permit + native-fsread: filename eq "/usr/bin" then permit + native-fsread: filename eq "/usr/games" then permit + native-fsread: filename eq "/usr/include" then permit + native-fsread: filename eq "/usr/lib" then permit + native-fsread: filename match "/usr/lib/libc.so.*" then permit + native-fsread: filename match "/usr/lib/libcrypto.so.*" then permit + native-fsread: filename match "/usr/lib/libncurses.so.*" then permit + native-fsread: filename match "/usr/lib/libssl.so.*" then permit + native-fsread: filename eq "/usr/libdata" then permit + native-fsread: filename eq "/usr/libexec" then permit + native-fsread: filename eq "/usr/lkm" then permit + native-fsread: filename eq "/usr/local" then permit + native-fsread: filename eq "/usr/mdec" then permit + native-fsread: filename eq "/usr/obj" then permit + native-fsread: filename eq "/usr/obj/bin" then permit + native-fsread: filename eq "/usr/obj/bin/systrace/." then permit + native-fsread: filename eq "/usr/obj/bin/systrace/.mailcap" then permit + native-fsread: filename eq "/usr/obj/bin/systrace/.mime.types" then permit + native-fsread: filename eq "/usr/share/misc/terminfo.db" then permit + native-fsread: filename eq "/var/run/dev.db" then permit + native-fsread: filename eq "/var/run/ld.so.hints" then permit + native-fstat: permit + native-fswrite: filename match "/tmp/lynx-*" then permit + native-getdirentries: permit + native-getpid: permit + native-gettimeofday: permit + native-ioctl: permit + native-issetugid: permit + native-lseek: permit + native-mmap: permit + native-mprotect: prot eq "PROT_READ" then permit + native-mprotect: prot eq "PROT_READ|PROT_EXEC" then permit + native-mprotect: prot eq "PROT_READ|PROT_WRITE" then permit + native-mprotect: prot eq "PROT_READ|PROT_WRITE|PROT_EXEC" then permit + native-munmap: permit + native-nanosleep: permit + native-poll: permit + native-pread: permit + native-read: permit + native-recvfrom: permit + native-select: permit + native-sendto: true then permit + native-sigaction: permit + native-sigprocmask: permit + native-socket: sockdom eq "AF_INET" and socktype eq "SOCK_DGRAM" then permit + native-socket: sockdom eq "AF_INET" and socktype eq "SOCK_STREAM" then permit + native-write: permit diff --git a/tests/usr.bin/sdiff/d_tabs2.in b/tests/usr.bin/sdiff/d_tabs2.in new file mode 100644 index 000000000..d00f4155d --- /dev/null +++ b/tests/usr.bin/sdiff/d_tabs2.in @@ -0,0 +1,69 @@ +Policy: /usr/bin/lynx, Emulation: native + native-issetugid: permit + native-mprotect: permit + native-mmap: permit + native-__sysctl: permit + native-fsread: filename eq "/var/run/ld.so.hints" then permit + native-fstat: permit + native-close: permit + native-fsread: filename match "/usr/lib/libssl.so.*" then permit + native-read: permit + native-fsread: filename match "/usr/lib/libcrypto.so.*" then permit + native-fsread: filename match "/usr/lib/libncurses.so.*" then permit + native-fsread: filename match "/usr/lib/libc.so.*" then permit + native-munmap: permit + native-sigprocmask: permit + native-fsread: filename eq "/etc/malloc.conf" then permit + native-getpid: permit + native-fsread: filename eq "/tmp" then permit + native-fswrite: filename match "/tmp/lynx-*" then permit + native-fsread: filename match "/tmp/lynx-*/." then permit + native-fsread: filename eq "$HOME" then permit + native-fsread: filename eq "/etc/lynx.cfg" then permit + native-fsread: filename eq "/" then permit + native-fsread: filename eq "/usr/obj/bin/systrace/." then permit + native-fsread: filename eq "/usr/obj/bin" then permit + native-fcntl: permit + native-getdirentries: permit + native-lseek: permit + native-fsread: filename eq "/usr/obj" then permit + native-fsread: filename eq "/usr" then permit + native-fsread: filename eq "/usr/bin" then permit + native-fsread: filename eq "/usr/games" then permit + native-fsread: filename eq "/usr/include" then permit + native-fsread: filename eq "/usr/lib" then permit + native-fsread: filename eq "/usr/libdata" then permit + native-fsread: filename eq "/usr/libexec" then permit + native-fsread: filename eq "/usr/lkm" then permit + native-fsread: filename eq "/usr/local" then permit + native-fsread: filename eq "/usr/mdec" then permit + native-fsread: filename eq "/home" then permit + native-fsread: filename eq "/obj" then permit + native-fsread: filename eq "$HOME/.lynxrc" then permit + native-fsread: filename match "/: *" then permit + native-fsread: filename eq "/usr/obj/bin/systrace/.mailcap" then permit + native-fsread: filename eq "$HOME/.mailcap" then permit + native-fsread: filename eq "/usr/obj/bin/systrace/.mime.types" then permit + native-fsread: filename eq "$HOME/.mime.types" then permit + native-sigaction: permit + native-ioctl: permit + native-fsread: filename eq "$HOME/.terminfo.db" then permit + native-fsread: filename eq "$HOME/.terminfo" then permit + native-fsread: filename eq "/usr/share/misc/terminfo.db" then permit + native-pread: permit + native-write: permit + native-fsread: filename eq "$HOME/.lynx-keymaps" then permit + native-fsread: filename eq "/var/run/dev.db" then permit + native-fsread: filename eq "/etc/utmp" then permit + native-poll: permit + native-nanosleep: permit + native-gettimeofday: permit + native-fsread: filename eq "/etc/resolv.conf" then permit + native-socket: sockdom eq "AF_INET" and socktype eq "SOCK_DGRAM" then permit + native-connect: sockaddr eq "inet-[127.0.0.1]:53" then permit + native-sendto: true then permit + native-select: permit + native-recvfrom: permit + native-socket: sockdom eq "AF_INET" and socktype eq "SOCK_STREAM" then permit + native-connect: sockaddr match "inet-\\\[*\\\]:80" then permit + native-exit: permit diff --git a/tests/usr.bin/sdiff/t_sdiff.sh b/tests/usr.bin/sdiff/t_sdiff.sh new file mode 100644 index 000000000..2d6fc2dcc --- /dev/null +++ b/tests/usr.bin/sdiff/t_sdiff.sh @@ -0,0 +1,206 @@ +# $NetBSD: t_sdiff.sh,v 1.1 2012/03/17 16:33:15 jruoho Exp $ +# +# Copyright (c) 2008, 2009 The NetBSD Foundation, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +atf_test_case flags +flags_head() +{ + atf_set "descr" "Checks -l, -s and -w flags" +} +flags_body() +{ + atf_check -o file:$(atf_get_srcdir)/d_flags_l.out -s eq:1 \ + sdiff -l "$(atf_get_srcdir)/d_input1" "$(atf_get_srcdir)/d_input2" + + atf_check -o file:$(atf_get_srcdir)/d_flags_s.out -s eq:1 \ + sdiff -s "$(atf_get_srcdir)/d_input1" "$(atf_get_srcdir)/d_input2" + + atf_check -o file:$(atf_get_srcdir)/d_flags_w.out -s eq:1 \ + sdiff -w 125 "$(atf_get_srcdir)/d_input1" "$(atf_get_srcdir)/d_input2" +} + +atf_test_case iflags +iflags_head() +{ + atf_set "descr" "Checks flags -l, -s and -w combined with -I" +} +iflags_body() +{ + tail1="-w 125 -I .*filename.* $(atf_get_srcdir)/d_input1 $(atf_get_srcdir)/d_input2" + tail2="-w 125 -I .*filename.* $(atf_get_srcdir)/d_input2 $(atf_get_srcdir)/d_input1" + + atf_check -o file:$(atf_get_srcdir)/d_iflags_a1.out -s eq:1 sdiff ${tail1} + atf_check -o file:$(atf_get_srcdir)/d_iflags_a2.out -s eq:1 sdiff ${tail2} + atf_check -o file:$(atf_get_srcdir)/d_iflags_b1.out -s eq:1 sdiff -s ${tail1} + atf_check -o file:$(atf_get_srcdir)/d_iflags_b2.out -s eq:1 sdiff -s ${tail2} + atf_check -o file:$(atf_get_srcdir)/d_iflags_c1.out -s eq:1 sdiff -l ${tail1} + atf_check -o file:$(atf_get_srcdir)/d_iflags_c2.out -s eq:1 sdiff -l ${tail2} + atf_check -o file:$(atf_get_srcdir)/d_iflags_d1.out -s eq:1 sdiff -s ${tail1} + atf_check -o file:$(atf_get_srcdir)/d_iflags_d2.out -s eq:1 sdiff -s ${tail2} +} + +atf_test_case tabs +tabs_head() +{ + atf_set "descr" "Checks comparing files containing tabs" +} +tabs_body() +{ + atf_check -o file:$(atf_get_srcdir)/d_tabs.out -s eq:1 \ + sdiff "$(atf_get_srcdir)/d_tabs1.in" "$(atf_get_srcdir)/d_tabs2.in" +} + +atf_test_case tabends +tabends_head() +{ + atf_set "descr" "Checks correct handling of lines ended with tabs" +} +tabends_body() +{ + atf_check -o file:$(atf_get_srcdir)/d_tabends_a.out -s eq:1 \ + sdiff -w30 "$(atf_get_srcdir)/d_tabends.in" /dev/null + + atf_check -o file:$(atf_get_srcdir)/d_tabends_b.out -s eq:1 \ + sdiff -w30 /dev/null "$(atf_get_srcdir)/d_tabends.in" + + atf_check -o file:$(atf_get_srcdir)/d_tabends_c.out -s eq:1 \ + sdiff -w19 "$(atf_get_srcdir)/d_tabends.in" /dev/null +} + +atf_test_case merge +merge_head() +{ + atf_set "descr" "Checks interactive merging" +} +merge_body() +{ + merge_tail="-o merge.out $(atf_get_srcdir)/d_input1 \ +$(atf_get_srcdir)/d_input2 >/dev/null ; cat merge.out" + + cp $(atf_get_srcdir)/d_input* . + + atf_check -o file:d_input1 -x "yes l | sdiff ${merge_tail}" + atf_check -o file:d_input2 -x "yes r | sdiff ${merge_tail}" + + atf_check -o file:d_input1 -x \ + "yes el | EDITOR=cat VISUAL=cat sdiff ${merge_tail}" + atf_check -o file:d_input2 -x \ + "yes er | EDITOR=cat VISUAL=cat sdiff ${merge_tail}" + + atf_check -o file:d_input1 -x "yes l | sdiff -s ${merge_tail}" + atf_check -o file:d_input2 -x "yes r | sdiff -s ${merge_tail}" + atf_check -o file:d_input1 -x "yes l | sdiff -l ${merge_tail}" + atf_check -o file:d_input2 -x "yes r | sdiff -l ${merge_tail}" + atf_check -o file:d_input1 -x "yes l | sdiff -ls ${merge_tail}" + atf_check -o file:d_input2 -x "yes r | sdiff -ls ${merge_tail}" + + atf_check -o file:d_input1 -x "{ while :; do echo s; echo l; \ +echo v; echo l; done; } | sdiff ${merge_tail}" + + atf_check -o file:d_input2 -x "{ while :; do echo s; echo r; \ +echo v; echo r; done; } | sdiff ${merge_tail}" +} + +atf_test_case same +same_head() +{ + atf_set "descr" "Checks comparing file with itself" +} +same_body() +{ + atf_check -o file:$(atf_get_srcdir)/d_same.out \ + sdiff "$(atf_get_srcdir)/d_input1" "$(atf_get_srcdir)/d_input1" +} + +atf_test_case oneline +oneline_head() +{ + atf_set "descr" "Checks comparing one-line files" +} +oneline_body() +{ + atf_check -o file:$(atf_get_srcdir)/d_oneline_a.out -s eq:1 \ + sdiff /dev/null "$(atf_get_srcdir)/d_oneline.in" + + atf_check -o file:$(atf_get_srcdir)/d_oneline_b.out -s eq:1 \ + sdiff "$(atf_get_srcdir)/d_oneline.in" /dev/null +} + +atf_test_case dot +dot_head() +{ + atf_set "descr" "Checks comparing with file containing only one character" +} +dot_body() +{ + echo ". <" > expout + atf_check -o file:expout -s eq:1 sdiff "$(atf_get_srcdir)/d_dot.in" /dev/null + + echo " > ." > expout + atf_check -o file:expout -s eq:1 sdiff /dev/null "$(atf_get_srcdir)/d_dot.in" +} + +atf_test_case stdin +stdin_head() +{ + atf_set "descr" "Checks reading data from stdin" +} +stdin_body() +{ + echo " > stdin" > expout + atf_check -o file:expout -s eq:1 -x \ + "echo stdin | sdiff /dev/null /dev/stdin" + + echo "stdin <" > expout + atf_check -o file:expout -s eq:1 -x \ + "echo stdin | sdiff /dev/stdin /dev/null" +} + +atf_test_case short +short_head() +{ + atf_set "descr" "Checks premature stop of merging" +} +short_body() +{ + atf_check -o file:$(atf_get_srcdir)/d_short.out -x \ + "printf \"r\\nl\\nr\\nl\" | sdiff -o merge.out $(atf_get_srcdir)/d_input1 \ +$(atf_get_srcdir)/d_input2 >/dev/null ; cat merge.out" +} + +atf_init_test_cases() +{ + atf_add_test_case flags + atf_add_test_case iflags + atf_add_test_case tabs + atf_add_test_case tabends + atf_add_test_case merge + atf_add_test_case same + atf_add_test_case oneline + atf_add_test_case dot + atf_add_test_case stdin + atf_add_test_case short +} diff --git a/tests/usr.bin/sed/Makefile b/tests/usr.bin/sed/Makefile new file mode 100644 index 000000000..c85bafd83 --- /dev/null +++ b/tests/usr.bin/sed/Makefile @@ -0,0 +1,11 @@ +# $NetBSD: Makefile,v 1.3 2012/03/27 12:32:47 jruoho Exp $ + +.include + +TESTSDIR= ${TESTSBASE}/usr.bin/sed +TESTS_SH= t_sed + +FILESDIR= ${TESTSDIR} +FILES+= d_c2048.in + +.include diff --git a/tests/usr.bin/sed/d_c2048.in b/tests/usr.bin/sed/d_c2048.in new file mode 100644 index 000000000..96ea71ecd --- /dev/null +++ b/tests/usr.bin/sed/d_c2048.in @@ -0,0 +1 @@ +s/1/abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabc\/defghij/ diff --git a/tests/usr.bin/sed/t_sed.sh b/tests/usr.bin/sed/t_sed.sh new file mode 100644 index 000000000..892feb905 --- /dev/null +++ b/tests/usr.bin/sed/t_sed.sh @@ -0,0 +1,127 @@ +# $NetBSD: t_sed.sh,v 1.5 2013/03/14 06:03:44 jmmv Exp $ +# +# Copyright (c) 2012 The NetBSD Foundation, Inc. +# All rights reserved. +# +# This code is derived from software contributed to The NetBSD Foundation +# by Jukka Ruohonen and David A. Holland. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +atf_test_case c2048 +c2048_head() { + atf_set "descr" "Test that sed(1) does not fail when the " \ + "2048'th character is a backslash (PR bin/25899)" +} + +c2048_body() { + + atf_check -s exit:0 -o inline:'foo\n' -e empty \ + -x "echo foo | sed -f $(atf_get_srcdir)/d_c2048.in" +} + +atf_test_case emptybackref +emptybackref_head() { + atf_set "descr" "Test that sed(1) handles " \ + "empty back references (PR bin/28126)" +} + +emptybackref_body() { + + atf_check -o inline:"foo1bar1\n" \ + -x "echo foo1bar1 | sed -ne '/foo\(.*\)bar\1/p'" + + atf_expect_fail "PR bin/28126" + + atf_check -o inline:"foobar\n" \ + -x "echo foobar | sed -ne '/foo\(.*\)bar\1/p'" +} + +atf_test_case longlines +longlines_head() { + atf_set "descr" "Test that sed(1) handles " \ + "long lines correctly (PR bin/42261)" +} + +longlines_body() { + + str=$(awk 'BEGIN {while(x<2043){printf "x";x++}}') + echo $str > input + + atf_check -o save:output -x "echo x | sed s,x,${str},g" + atf_check -s exit:0 -o empty -e empty -x "diff input output" +} + +atf_test_case rangeselection +rangeselection_head() { + atf_set "descr" "Test that sed(1) handles " \ + "range selection correctly" +} + +rangeselection_body() { + # basic cases + atf_check -o inline:"D\n" \ + -x "printf 'A\nB\nC\nD\n' | sed '1,3d'" + atf_check -o inline:"A\n" \ + -x "printf 'A\nB\nC\nD\n' | sed '2,4d'" + # two nonoverlapping ranges + atf_check -o inline:"C\n" \ + -x "printf 'A\nB\nC\nD\nE\n' | sed '1,2d;4,5d'" + # overlapping ranges; the first prevents the second from being entered + atf_check -o inline:"D\nE\n" \ + -x "printf 'A\nB\nC\nD\nE\n' | sed '1,3d;3,5d'" + # the 'n' command can also prevent ranges from being entered + atf_check -o inline:"B\nB\nC\nD\n" \ + -x "printf 'A\nB\nC\nD\n' | sed '1,3s/A/B/;1,3n;1,3s/B/C/'" + atf_check -o inline:"B\nC\nC\nD\n" \ + -x "printf 'A\nB\nC\nD\n' | sed '1,3s/A/B/;1,3n;2,3s/B/C/'" + + # basic cases using regexps + atf_check -o inline:"D\n" \ + -x "printf 'A\nB\nC\nD\n' | sed '/A/,/C/d'" + atf_check -o inline:"A\n" \ + -x "printf 'A\nB\nC\nD\n' | sed '/B/,/D/d'" + # two nonoverlapping ranges + atf_check -o inline:"C\n" \ + -x "printf 'A\nB\nC\nD\nE\n' | sed '/A/,/B/d;/D/,/E/d'" + # two overlapping ranges; the first blocks the second as above + atf_check -o inline:"D\nE\n" \ + -x "printf 'A\nB\nC\nD\nE\n' | sed '/A/,/C/d;/C/,/E/d'" + # the 'n' command makes some lines invisible to downstreap regexps + atf_check -o inline:"B\nC\nC\nD\n" \ + -x "printf 'A\nB\nC\nD\n' | sed '/A/,/C/s/A/B/;1,3n;/B/,/C/s/B/C/'" + + # a range ends at the *first* matching end line + atf_check -o inline:"D\nC\n" \ + -x "printf 'A\nB\nC\nD\nC\n' | sed '/A/,/C/d'" + # another matching start line within the range has no effect + atf_check -o inline:"D\nC\n" \ + -x "printf 'A\nB\nA\nC\nD\nC\n' | sed '/A/,/C/d'" +} + +atf_init_test_cases() { + atf_add_test_case c2048 + atf_add_test_case emptybackref + atf_add_test_case longlines + atf_add_test_case rangeselection +} diff --git a/tests/usr.bin/shmif_dumpbus/Makefile b/tests/usr.bin/shmif_dumpbus/Makefile new file mode 100644 index 000000000..b434c8c4c --- /dev/null +++ b/tests/usr.bin/shmif_dumpbus/Makefile @@ -0,0 +1,13 @@ +# $NetBSD: Makefile,v 1.3 2011/03/11 10:35:29 pooka Exp $ +# + +.include + +TESTSDIR= ${TESTSBASE}/usr.bin/shmif_dumpbus +FILESDIR= ${TESTSDIR} + +TESTS_SH= t_basic + +FILES+= d_pcap.out.bz2.uue d_pkthdrs.out.bz2.uue shmbus.bz2.uue + +.include diff --git a/tests/usr.bin/shmif_dumpbus/d_pcap.out.bz2.uue b/tests/usr.bin/shmif_dumpbus/d_pcap.out.bz2.uue new file mode 100644 index 000000000..5bc3348e7 --- /dev/null +++ b/tests/usr.bin/shmif_dumpbus/d_pcap.out.bz2.uue @@ -0,0 +1,104 @@ +begin 644 d_pcap.out.bz2 +M0EIH.3%!62936=O8'&4!%NW?@$`00`5_\0@B0``.Y_X@8"=^\@0```````!P +M```````![XY0O$\'N'"@P'!M=O2E=5*>#>[0M50X0`Q@V@,$-!@@$%T!A:`P +MNATWD`,83$T&",0R,)AE/4?O1O52E*@P`$`820U`]4JH-#(#0-`)/5*JFU,: +MAIDQ--,`("DJ$*>E&F@!B:9'J>H%0J0>BI0``:`#P[E![R+ZY%2,<&JMJ-E3 +M46V)*F;;EK75-K&QM&I2K*&T&T6+/K6_NM*C]*2HP@P@TB)E$3A/FJ+(T01D +MEE3)*^*HLJRIC"2U2*M!2L$O=47PI1'PJ+)#2".()^T@)^44*>9`3@D/Q2`G +MVD!-(%K\?\`````````````````````````````````!`D````D````````` +M`````````````````````````````)"```2$```````````````````````` +M````0``````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M````````````````]]]]]]]]]]]]]]]]\]_U>^N]_A_'^7[OYZ?8#!^`0.`X +M-W=&9F```````]]`-/L!@_`)))``````````*?;[]``````````````````` +M````````````````````````#P``!;;;;0```'./'CQX\ +M>/'CQX\]]/ODW8-=SN^=SF_;]WWM/UWKN][\SQTV<,++++++9E55"JRD964C +M*RD964C*RD964C*RD964C*RD969F4C*RF5F:2222222ZZZ2222222222ZZZ2 +M222155555569E5ZA"1F835JZZ2222222_2ZZ2222222222ZZZ2222222222Z +MZZ2222222222ZZZ22225555557)NPDA8BUYY[\["YG,W,XZ +M0ZI3(:35+77/7,ERN5RNJ#J*U!J646HJIJB32D)4$%2$(L$/23K?/G?/O?.[ +MWWI()MWWWWWWSN]]Z$D?"0.)(_CSGOG+V]`#ODDD@``!(+:M@MX%L@MX%L%M +M@MX%L@MX%L%M@MX%L@MX%L%M@MX%L%M@;NZ```=MMJ2#I))T=_.][WO3=W=U +MX\[[50XD`D),$@##G.6\;VXXX\MC-"@U#LAV@]U!V@Z0Z0\J.DV39-DV39-9 +M-O,<9-DV39-DV3:>9QDT'.R;)LFR;)LFDT','*'=!\0?$'U!V@X@X@X@X@X@ +MX@X@X@X@X@X@X@X@X@Y(.0.(Q$TEJ+46HM1]?9/LT,I35%FD1K8&)PC7A-DV +M3:U59-DV39%1*@^H/D#X@^H.(/J#B#B#B#B#B#B#B#B#B#B#B#B#B#D#B#B# +MB#D]/4GJ:,EB*DDTDQ@S1:AW$@(KX(2E50B555WWWO>-Z?'Q^>6QB11WO;[C +M>GU]?7EL8?S`2H!B2*$>]Z_9QZ?GQ^>6QAY)(H0;0D`"/>]>9MZ?GY^>6QF@ +M$"H$=[VWFGI]?7UY;&)'>]ON:>GU]?7EL9HH\D(H0>]Z]9MZ?GY^>6QFBCP) +M*A!:$@6"0`520``'O>MXWI^?GYY;&:*/"%0@][UZS;T_/S\\MC#P@*$%`EY] +M?7UYY\_/S,SY\^?*`/GDDDG0``$@MJV"W@6P6V"W@6R"W@6P6V"W@6R"W@6P +M6V"W@6R"W@6P6V!N[H``!O;;62#I))T=[WO>]'..MMNNDDD +MDDDDE022YG'MQQQY?M55&BB)(5EE%%%%%%%%%%%%%`"HH)) +M$O&U77222222225XR7,X]N../+]JJHT40$`66444444]1,S$9F(S,1F8C,Q% +M$DN9U\<NLS/U\^?%`/GDDDG +M>@``2"VK8+>!;!;8+>!;(+>!;!=XMW>6EL@MX%L%M@MX%L7=WEMI!;8&[N@` +M`&[VVLP=&9F7IWO>][WI;;:\[YTAPPYSE\SCXXXX\OVJJC11A\D`8(#NAWH> +M!7B#I#J#B%W1R\,1F8C,Q&9B,S$9F(666"+++!%EE@BB27W./CZ_/SR_:MKV +MKIX05#ITQ&4BJ15(JD52*I%4BJ16>>>;SKGKKSKSOK;GJVNW3P@J&4BJ15(J +MD52*I%4BJ15(Z>>>;SKKXXX_/+]JJT80$!0@LH$44"**$S$S$S$S$S$S$Z>G +MIZ7,Z^../SR_:JM&$!`4(+."2+!%F)F)F)F)F)F)F)F!&B27O.OCCC\\OVJK +M1A`0%""R@3,3,3,3.1)<$X8F8110!0R27,X]N./SR_:JM$!`4(,));W +MO[[[[WN^][WO>UK6M:^=[T``$@MJT6V`06V"W@6P6V"W@6R"W@6P6V"W@6R" +MW@6P6V"W@6R!N[H``!N[VUF#O3-[WWL]))))/=[WO>^)"F)<$N4`@54(21AQ +M\OF<<<WQ]<>7[55H@( +M"A!A)+F<>W'''E^U5:(D`4(,))7[55H@("A!A)+F<>W'''E^U5<0`D);(A!0@ +M9)JYG'MQQQY?M56B"`H0822YG'MQQQY?M56B"`H0822YG'MQQQY?M5NST0R, +MHB>"4O?!D49#(HT&JHM6R;)LFR;)LF!-!H49#(H]\^O///?KSZ^O//KSG+EO +MZ_7Z_0`222=[WH``,P!;!;8+>!;(+>!;!;8+>!;(+>!;!;8+>!;(+>!;!;8+ +M>!;!6[O```#=W>UF#O>LS,MO>R2223O>][WQZ%6`@3$MC-YN]9MQQSKTZYX\ +M]MNS[X,AW0[ITARAR@M"+#0DBA*B27,V]OCZX\OVJK0`H("@P!"%0E1)+F<> +MW'''E^U5:(D!0@P^^^^O[.OC^?S^>7-56CY`%"##[[Z_L^?7Q_/Y_/+FJK1\ +M(H08???7]GSZ^/Y_/YY7-56C2`$A*A!A)+F1]?'UQQY +M7-5221H$:$D"PDES(^OKZYSO/S[[/?9YY]>>^R]Z +M*!)))WO>@`!(`$%M@MX%L%M@MX%L@MX%L%M@MX%L@MX%L%M@MX%L@MX%L%;N +M\```-W=WK,'>][F9EM[WLDDDG>][WOCT*X`A"T)5RJ97'?,X^..../+FJK0( +M-"`L0%B`L0%"#"27,CZ^/KCCRYJJT)6@$J*`0*B@$"HH0@4DN9'Q\<<<>7-5 +M6BP$"IA%F$6819A%F"F`HDES(^/CCCCRYJJX`(%L1B`$A*A%$DO61\?''''E +MS55H$622YD?'QQQQYLCX^.../+F +MJKAL$822]9'Q\<<<>7-57#8!A)+UD?'QQQQY]]GON^>YF3.]Z%`DDD[WO0`` +MD`""VP6\"V"VP6\"V06\"V"VP6\"V06\"V"VP6\"V"VP""MW>```&[N[UF#O +M>]S,RV][WO>][WL[WO>]\256"2!8>0`D)=[5;*[V^9Q]W''''ES55PI"LDEZR/;CCCCRYJJX4"+))>LCVXXXX\N:J +MN%`BR27K(]N.../+FJI"*))>>_7UYYF9,^?/GP4"223YWO0``D`6\"V"VP6\"V06\"V"VP6\"V06 +M\"V"VP6\"V06\"V"VP6\!NZ```/-W=WK,'>][F9EM[WO>][))WO>][XDJK.& +M'.WQ]?S^>7-52$422 +MYD>W''''ES54A%$DN9'MQQQQY7-52$422YD>W''''ES5 +M4A%$DN9'MQQQQY][W +MM:UK6I)/>\``D`6\"V"VP6\"V06\"V"VP6\"V06\"V"VP6\"V06\"V"VP6\! +MNZ```9F9G;F6][WOR2223O>][WQ)56<.B2&=[V^YQ]<WQ]<<>7-57`$@*!%DDO61[<<<<>7-52$ +M422YD>W''''ES55P2H$622]9'MQQQQY7-57!*@19) +M+UD>W''''ES54A%$DN9'MQQQY<)JJ0BB27,CVXXX\OSJD(H][U^SSV_/S\\O +MSJDE8D@5)-XY))KWO>][WO:UK6M3WO>]X`!(+:M@$%M@MX%L%M@MX%L@MX%L +M%M@MX%L@MX%L%M@MX%L@MX#=T```[N[I(.DDF[T>][TD[WO>]Z>(0X67YU2ZJR'9#LAYB/"'2'2&1L>_7[./;X^OSR_.J0BCWO7[//;\_/SR_ +M.J0BCWO7[//;\_/SR_.J27ZT`)"5"LDES(]N../+\ZI"*/>]?L\]OS\_/+\Z +MI!`!`J"BBBBBBBBBR27,CXXXX^MWZM^I(2O%555555553IYY[N9'MQQQY?G5 +M(11[WK]GGM^?GYY?G5(@"0%!0E10E10E0%DDN9'MQQQYQY=2JZJ=2"-46J<$ +M$<=36D42T5%8M93,VIM:10-"E6)36EEEE9:T@)\9`3UD!/"J$GK0$X)#TD!/]D!/8D.$ +<@)V2`F0$]$!/:0$]4!/?0$_\7````````M5ZU2M8;`7KK33;500',-455U@\!@/ +M.T7K$JH^L!YM3K6M5L$^!>)T:*I:U*:`-HT]1ZC3GMVDMDD^>,22V26SY_K_%DLD +MED))+)(MMLMP222663_4DLE1"$6RR62?Y6VV72RVR6S5DDMEJV1))9*B$(0B +M(0A"$(LD22V2(EI+26K;^VVR6623.N_?K_&_NIK6M`;F`,8P`;[@``#8```` +M`````````````````````````````9S^O]0&Y@8DD`````N[QB;`$D@2JJ@) +M550$JJHDD```````"20````"20````"20````"20````$D@````$D@````$D +M@````&))`````)F0````&,8`````22`````22`````22`````22`````22`` +M```22`````22`````22`````22`````22`````22`````22`````22`````2 +M2`````22`````;[@```$D@````&V4,W!,R)4VMG$B0NIF[D,YDDDDDDDDDR)), +MU4WWSF7)))G.Y+8QE4J9EW)))))))))))))))))+N[N[DDD +MDDDDDDDDEW=W3.,IMOVUK6@`J#H!V*``)@(`()@`% +M`.P!9R``*@Z`!(`#D`L`03``3`0`+.0`"@'8`)``!T%0`.0"P``J#H``'8H` +M``LY```$@```3`0``*@Z``Y`+``%`.Y``````````````````"0````````` +M````````````````#L4`````````````````````````!4'0```````````` +M````````````!R`6`````````````````````````2`````````````````` +M``2``````````````````````````()@`````````````_\`%P`````````# +MH*@````````````````````````"8"`````````````````````````$@``` +M``````````````````````!9R`````````````````````````!T%0`````` +M````````````!V*``````````````````````````J#H```````````````` +M```7`%P```.0"P`````````03``*''''$I<>\2EQ*4I<2E[+B4I2XG;Q99>N +MV6V69FM26W5MMO:2U?-NK,3S;EEN[9;$LD66)+9$DM;MW;NW4LEW9+4DDJV5 +M)));9N2VZSGGSY[>>_7361`$0*K,S,VV9K(``@R`B``?[_SJ>:U_7],TKGOO +MK82220```````````````$DDD`&`````````````````````````5\\KG%-6 +MJ("[N[MD"6=1=8-^TK/9E?'6*[QA".*KS7+Z;Q]F)>_>@`.@J``#MKKKJM[Q +M>]P``````````````````````"8"`````````````M+J4N.)2E+K[YXQGV_O +MFM9SG,>UA/$[?(M$1$>^@`*2EQQ*2=][679+"6$L*O4L)82PJ6=[9)-VR2;E +MDCKKK7/`#G,`-Y@!K,`-9@!K,!LWF`&^V`&\P`YS`#MO6@#>8`:S!R&\P#NX +MS`#>8`:S`#68`:S`#68V!K>M!R-Y@``&9@``&9@`T`:S#L``-9@!K,`-9@`` +M-:S``P`@``!```"`8(`'&```9F```9F``,"`%ETEDRWN,S```,S```,S`#,L +M)WDF)863#,P`[@#68`<9@!K,```S,&P`.[G,```S,```S,`.,P;#>8'<`!K, +M```S,```S-`'.8=@;[:`)QF`&LP`UF`&LP`UF`&LP`UF`.^\P`WF`&LP`33` +M#4`&LP`0`9F`"`#,P`0`9F`"`#>M:`$-@:S`!`!F8`("XLQ9BS$N+,68LQ9B +MS%F9;"7-@$UF`&LPMT[VIM9EFDRUI+DFERW62S268DG$XWE[HDX28+IEBU;F +M6XDN+)ELQ,L``<:U+-6KB3+5KC2S5JWMV2Y:MS+M:```S,``-Z(0L;RSG68`:S-@-Y@!O,` +M-9@!K,`-9@-F\P`WS@!N9@!K,`-9@!SF`&LP8'`XS`#OF`&LP`UF`&LP`UFP#>88#C>M`"`#,P`0`9F`-H`-9FP&9 +M@!K,`-9@!-9@!K,!AK,`)@`0`0`$`$`!`P,S`*68LQ9BS%F,DG<:S`"`!F8` +M;8`-9@!%F)WNEFEF+,68LUK,`(]_O;>SS9;))+/>M))9+Z9Y]_LWM.F)^,3O +M_U9+))9*=-3O/&=5I[;W$:UY[Y$1$?:``4ZK74Y@#`##$;`#`-[R@'>2(J(( +MC-/6,HAFA[>IJ\YJQ%^\>.V/8B(BP`!UY6O]92EQQ.>JT&0"MAM`"XT(H`8: +MD6]X!].G%4S(EXM$1$?``$O:4S;7'''$JUU>E.>>YSS.>N9\IS3GI5UGU=R. +M7QY`B``!!S6NORGJ/3,YWVQM=\X\B(B/?0`%)2EQ*7'U:^SGN7''$I<=4 +MIF87(BH!+".]YM1#'U^_?M"/+RE65C?)EL.'1$2-:``12G/.O.ZUQ.>:TISS +MG%*9G.T4ISSWY#O9J>:U^U^UK0CA]5\J6B,K,NQ=JN>IPY=$2(]N``I++KK? +M'$N)?4IJU*<\WU2A2E;JUC5*1S/G4Y]]>=:IYYNM][QC&8B(C>@`%-$1>UK] +M^_4(K0C8![HCX`@`WM."/@#7=MWG+Z*=:7[\MYYY]K[61$1'OH +M`"DJ2M00(JTUK2J^]Z]R:[V]Z5=>J]R<0KO7$`0"4N)2]Q?[KWV_T1$1JX`# +MVE-2XE*6:4U.W([VX!@`O!'`!^".`';QFA6=VYC0GK:]O;B +M.KU,/;N*.3374"N<;33J2)FO2I7#>)[$5$35W?;MK&7>YW?2IQ2>]N!Y[M=Y +MU#:&PF,&Q6WEHUIQ9RJ;(NKN[2*)*CH]K&UO??O=[VV>2TZYK.-NS[S,;WSD +M^]A_@$"(`$XDOU/5OM9U/T"`""8``+TI2][WO>]`.P``````````````!:UK +M6M:U@``````!!,``````````#N4I<<2E*THYK'VKVO]GS&-:SFKZ=?+=^WTM +MJUK6LN``I\\\<9]LDG,MM_)9)Q+).)+)-2\6V67^;WDL_2SOUF]Y;%50@Z;6^LB"UE'Q`%=YKD>C'7CWWWLUS>][W/V][WO> +M][9FQ[N,+\$`!0"QL0@JEO=0@^-K*+/N,UK+9F9)/Y.O6<<9;,SOJ6=V]Y/J +M2?HB#7[0/W%AH'#?)6OIF/?>N[WS9MNW;T/BJJKVF9F9F9F9F8(B`(;][G.K +M?!`$!0#\<85$^7W^>_F^W;+9F9)M+W;WDL_FM9+#,_-6S6L'Q0=*?CC"H@55 +M'"`-=XZZ;XOK[V(WUH^WO>]_OF9F9F9F9F]SN,+\@1$0H!\;W4(-FUE"#XZU +MEG\L^_,XXRV9GG4LZ;WELS,DGM._7K7/.3X@*4%E4#XA)?NVCO.PV>[^_5UZ +M9W?Z?TS:^N*_>=[B^;6M:VM``(YO6L_W''$N.9<2I22S]]YO>2S[ +MYS>_FK9K62SYXS>_[5LUK)](`T;W4!RB6LH0_.]Y]EDBR?6]Y+/O;-[RV9F2SQWS>\MF9K4L]]\XXR?5DUK)/J7 +M6O6M:RV9F2?=Z_$D,;%\SEW@9Z_=NHB*SZ[TFKV5=3SM:JJK5,S,S,S,S-?E +M[K\`@`!0"C>ZA!]G];&%"#XUK)^I)X;W]U;-:R?4D]-[R3RMUK)9RUI0.%$M +M90GQ`416X;F\=^^F^7B)WO>]U\S,S,W777776>&L^R6VI9K62S[X\:XXR?RR +M:U[U+/;>\GU9-:R6?C6LGU9-:R3ZE_F]Y/">T\+HS#7Z-ZT]$\ESYSA`3V5F +M1$76?7Z_!$1`4`HWNH0*2OK4L_6]Y+/UK +M6?4LUK)\23LWO)/"W6LE_@$`WNH0;-K*$^('7XV\[7O?FC[Z&]^WO>]_?F;K +MKKKKKKKKKKKQO>?9+)$LUKYJ6=V]Y;,SYJ6>V]Y/JW^3>\D^I?QO>6S,R6/7 +M;6]Y+W6:T&M:^WJ^=GY/JX=2B<>VN'?[[/7=]NNC>/C@@ZM31+:9X1X[2G<7 +MB6_<@^#'.=FC>$F6.3,Z>;NJ>JS+NTAYH7F,X:]CIPB<[7--B"T* +MQ16&<5*F?*R6N(BIS,NR:1JN]$BG.A&8Q)SJMA-LVXQPU)T57D6YS,DS0<1& +MN=[:'KR>ZNCW0*JJJ@`````````````````````````````````````````` +M!UIYMFF[7``.<\9S*S\YXKYU=-7SGO3HUKKKFG.<,=_93.:ZU?3%`.P`2``! +M>E*7O>][W``!(`````````````````````````*`=@````"UK6M:UK"DN..) +M2XM*<_-/+34=>,R[N]\!=E(\K%N%55679F9F9F9F8Q[O>?;9).=;9)S +M99=PEA+"6$L)8)$6R;MDDYEF9DDVGWWG'&2>ENM9+\28UF23XNM9+/36LDG\ +MNM9+.NN^N.)RXE^YI2][]^9F9F9F;KKJ>-:S[)9(EFM9+.S6LE]K-:R3:3ZG?YSISDL^M:R6?/> +MM;S)M)/K>\EG;MF]Y+/K6@U^UQ/IC.^WL^\>ZF'?[[WKNQUO3H4>RG5558AF +M9F9F9F9J[>Z_`(`"E%$O=0GH4#YO6UI0)]76LEGK]S>\MF9DL_?.;WDL^M:R +M6>?NM;S+Q*==9]DLD6>UF]Y)/J6]Y+/#6LDGXNM9+/?] +MF]Y)]2_&]Y+/S>;WDL^M:R6??N;WELS.J2XUS*5KXOC'U.Y^]_OU_OOUK6M; +M[8`"MZUG]DLD3XOI9QQDD^IK^S-Y+/K6LEGKSF]Y;,S)^I)V[9QPR>$D^M;R +M6>LS6?=6S6LEG]Z]<^ZYPZ)\L<6GEZ^]Z[:D[6U(_7+JJJL0S,S-UUUUUUUU +MXWO/LEDBSA/Q/OG.W;)9]\YO>6S,R?M9\!$'MB/T$1.(CC$1``,W9^GC]I=5 +MB_'=V^K6M:V?P`#&O>NOTI<2E*E*8G]6==?JUK;VI%\(BB$1.(C!D1?(1$]\ +M2#5P[:%EQV(^>ZSZ[XZ"T\*^G"Y4$4+;O<"G'M>TZ]Q"6J +M[+4]S>78KIYWBQ2'SJ(EMUZ-'Q7NX0S2#RS?BV1(U]2N$MA:]R::'S+R[T:O +MJ72>XZ)R5=.@_'2'S(?E]X<X````!T%0```````````````````````#H*@`````ZEQQ:4N..+%$` +M1`2@`"#V[8W7NN]5$>_3,69_.T^>MQO>][V[LS,S,S,S-8]YF?/>][]:UK[UO9?"(_21$PB.<6>\['V#- +ME?UM;*JJM^9F9F9FUK6N/55]VV_-MMNZJOGBJKZ/8^C[=57H:E50`'WU\GHL +M7'1R5/LM7^[41][+N[UW@.OH[BJJV:``2O2G[CB4I2I2D>5K7]2E-?JUKFE* +M?N1$``/61$RD1?(WHY!=].^?+5T]>5556^9F9FUK6M:U[SZSG[MM^;;;=550 +M?1][X9SC?&^+'H?;$0^$16X[UG5X8.LE8F/=?3%7]=QVB[RH;TQ>UK6LR``B +M]:_I2XE*5*4WFM:_D1&(C]A$7PB+LBP_S<<$/U^NV^ +M>YOUVP&@0T;NQ:UK6^^``5EQ*4N.)<<3O7]Q+B4J4IO%'HS'XB+.D1``0(BH +MB/T]]SG'^(B/XJ5*%D3[]GWWW5K6M;]D``G>N_TN)2E;KKK]6M:[G2B"(WA$ +M7T$1?"(WN"(0`.KWC\5\92^YQ:^OYHC]C.\Y[\[K'5>J[[UBUK6M]\``SY6O +MZ7$I2_49GOP@(`&41$RD1>82V0`'T2)GDD10V>E;;.?T7Q?&&;6M:W[0`#N= +MZ_I<2E+5:U_9SUT?A$?MV1"``Q$1?"(LA$3"(T_7\VFL/$ZQZUAW]]?KL5$U +ME,HWKB=5FJL,YG9PJ.Y*,<[N70^<5%[2BW*RD>9R(F\NY$]JY:O.)=@A&_>'4RZET +M>=J.K-0RVC]_/KGGGGOW[]3\MLMO^RRPLL++"6PLL++"RPLL);"RPLL++"V0 +M0`0`(@`@`(`(`"`DD++"6P`"`"``@`@`(`(`MI+866%EA9866$MA9866%EA9 +M+)8$`"`!``@`4`(`$`"`!``@`0`(`$`"RVR%EA9866$MA9866%EA982V%EA9 +M866%EA+866%EA9866$MA9824"`!0"VVR2%`"`!``@`0`(`$`MMH`0`(`$`"` +M!``@!?I]29N536;GOM^_902222``>@`#T``````````"222`#``````````` +M``````````````3G,[U,;FJB``PO'?/UIY?&N^O.>/'GDU4GG75K==??=YC- +MI]G7<>_#L4``*`=@/U*4O>][WN```````!R`6``````````````````````` +M#D`L``*2E+B4N#U^_)IN9!NV9'8B\N[M]#/>5BW*JJK5,S,S-UUUUUUQ,\;_ +MVLDFI9)Q)9)YEF[;+J62?O;.U=:ZSG/0_3JMJKL255?18@\_MZSG/OF*8OWO4>Q$0Q@`!KVGN?OY^;;;?:JOOC6,8@]LYSSFI%X1'U$1>$1<1$`!5DS/PB/A:+88D^X?&7S_7RQ[[O6=YSWYYBL? +M8OG<9B(B'WP`%ISOCH>Y55R+'7=57P=COOY+N\8Q/.N;XVZYB^<;[QB\1$1] +MK8`'VI^UWNM:RG.\STI91$HB(F>MF9F9F9F:]N/A$6]!F8`%8YF8`'>D1>$1][1$0`#6LWWR +M4'9[R%!/9V+J9FL]=Z,M5T9C.I*FF/UDX;$LMG.;9,;5\Z/)ZNIMPY3B9]FZ +MGO%1)>Z/EM9SH%G(``=!4!N +ME*7O>][W``````````'8H````````````````````````$$P=2XXM;GGZT^K +M:SY[[G>,?:SGVL7E];.-?6[B(C'F@`'-Z>ZEDFY+)-2R3)9)_.-?O6][S,[? +MF][^:UKWJ:'O?&9]HB+PB,=D>QA^JREVCB(B5[S,S,S,S,U;4]#V$1P2]ES/HN:]=WQH;?)?R- +MQ$1.W;,S,VM:UK3?R]=U5?!C&.O>U570^<55:&M7G.>RE?*_46MYY[K3&/>X +MB(]SH`"DISO.*4I]HS,Z$1SEF9@`1<&9Y!$2U9F8`":<"EIGO>>3,S*=_5?K +MNQ6+?LJ<>E^(B)%VS,S,S,S,.NL>JX'S1Z^>/''>+^Q +MOGZ-XQ]U$1&][``I*T[US2E.OJUK.<_;(B'V$139$0`"(1%@B*S`9`KQN2%J +M_EY=SC&]YWG.>O>\TK[B^XCJ(B#X`"DM3\K.$1["F9N( +MCZ8OHM.S/W7Y7G\^9[+N`B@IL[$+V(-.TB=XR0:<%8GJ\F2?4PD"Y<:4YSF5 +M5=R,BJS+MJ79436'::,N3WQ$XS-&C=Y2V?F&,Q2"[X5J!Z:^MACE553;Y-Y= +MN!S>#+)IB,\[Q2J:M5&_>]?'?N/,E'ON@5555` +M`````````````!X``))))`````````````````````````8OG-]ZO&[7``/I +MC/R]\]\9>--VG==>;XIKO6>:J\>QC,N:X^=>XO@!(``!9R`W2E+WO>][@``` +M`````````D```````````````````````!0K+GB4I2XXU^_*N]JRY?4[62\3 +MF7:J/"=6/,DT1$KO69F;KKKKKKK4]^M?G%R62/R62(O5F)9(6%J6V3O))"V+ +M99N64DCUG.MZUK,SKO^>>UXO7UC1$18[UK6 +MM:UK6M:;7IYS\'/-570\CH>QH=<(B81'7DR/!/<4",>/ZIAW][WKLSU%P)'[ +M*.(B,XP`!26O:>];S6M>OJUK.<[TI2M*4M%2+&(BP="(`$H_F;R/[9D/J>%D +MD1$O/,S,S-K6M:?F_EV.=]53V.1V.^*JL8QGS55YU54.%RE(^B9XO>/C^C,S +MUV"'OM.2W[*)$1%EV9F9F9F9AT`=``#%(B``OQ>V9X(BW2(@`/57.^^U*4O? +M'6\5OJ4<^YWU[[Y6(B-[T`!26)N7A$4V(AX1'HB(`%>Y/.<[XB+U$1``)+]6 +M^Q$+SF.C7%1&9Z[L]K756_8A(B)789F9F9F9M-O&/-=CBYG.<8QMW=57L=_* +MJO(X&AUZ\^-6K76,]TUG&+TB(C.O@`-\^4G.>?*UKN@CYB(L$1X(B`!YL,S\ +M(C4/WH0\=BD*^P]3Y]?9WG/L[>8K3NG6_O:1$1CSP`#KF]/TI2XE(1'U$18( +MC]8$0``91$2B(S\G>BVZ]_7]=M3UC'WM'QT9FY400\ +M-WR*3B$,4?6+J12)WLE9\0Z5LG&A\S,N^.\MO1)E.M;0YE72J0P]P``````````````%0=````````````` +M````````=5E:6]VO'>=^XQO7WV<,S\(C\ +M>+].Y+.<.?O0D2"(B>?S,S,S,S,U;<0`/01%X1&ND1``>9C,_(1%3>/N^<`` +MOJ=@ZDVZES:O4^F:SUV`AQ"EO'3;1$1KMF9F9F9F;F^C@B-[NS,G$1];F9^$ +M16B(@`#@B)G*M9]>^Q3ZSS6M,8QJ41$9]T`!SS>>:4I:@C0B-T1$F$1,(B`! +ME09FHB+-Z$C#?J&]>NV_,_9WG.>NHZPW=]$3B/,Y(`%.;TW2E*:"C,9HB*#< +MS-A$54B+PB,"(^4B*YXPTOLGW/%$3Y$04]&,W&9F9F9EWT?"(UBG[?.``6(B +M0B*>PS,`"1$1$15%=T*C?N<\U>OW9CV9=W`5^M;O%-WUF(B*W\R=`#S4Y>U_ +M<<2EQ2E/U,4`@L1%.D11XB)E(B``Q"(OA$?ES@SV62#^^F<6^B(C[/?XH`.N +M;TW*4N)2I2F\UK7.ZUK*$Z!11`\)7J9V_%3M37(Q$)\=XYSO:2'X]'U`XDY52[W5Y +M=G&J%\/N=7CH35"G"I1&S.6&?%6$R$T\KR;@JWW7RL]WK'KUOT]V$DDD```` +M```````````!=W=W8`Q@````````````````````````.]_/-LTW:X`#$SY7 +MS$\TSSS,\8WEBY>N^<>8O&>^KL=T9I&?)^V]`"8"``$P;I2E[VO>]P`````` +M```````````2```````````````````*2M*'?N+]M?>XQC.LYG[;-<7C77WL +M1$'H<@&N?*;2ENI"6$L+,69?%)82PE@NEKJVRHLZDMF);>]EW9[+ +M;H?LE41$J(9F9F8F9F;>^A8B+"(@`9[AF>"(XQ$0`"4IF>"(E:>=-XQ6.I^_ +M6\O[N(B-[V`=!3CCCF])SG\.QW[UG.<8QQZJJT.O''K4DZ'Q?B^>Z==Z]QGS +MR^=YWO.?9Y]ZSAUO6?8B(8N`$%9<<`Z4;\(6B$5@"`"`%]\1``2`<`$1':%K +M$D,*(5T1$F\9F9F9F9E8M?OU.>4(ZWO>\@1XG),\5B+>W@1QA'E'IN-4D7># +M>.SO4>G/>NVI#I[=;SB(B(>^@`.[UC=*>SGB<\\YI/GGO%*:G.T4INHGGHB$%-_8QC +M?F_L[SG/?D2KZC&XM$1$>^>``9KY6@#U".]Y7B+P!WOB+H`P`H!I^/ +M[WIG$B(C&=@`2O/GGN<_?J4UO5:^SG]SC-:?>;K5C$?`!\29Z31S$>ZB(CWO +M>NP03L7U^_?M5Q]\>LM.,5OV>'Q^]PWQ.%U]P```````````````````!V*````````````````6E/>8OW;.O<>[WG. +M<_?>_>17W6+Q$1'E\@`=WI7CB59<2E*\K)-2WB6$L)82PEA+"6%6=["6+>)8 +ML)82PLB\2$L)82ZWK5(7O9XS``0`WOF61;VB".]RGG?RGD*<9DXU$1$;OL`# +MG.O:;G.^*4S.>+16NYS\G/=A%?>(M['EIVH8M0CVA-=W+>BZOUV^WD6.7]"( +MB(NN`!2].>?9SWFE/OJ4YYO*U*1.=K4IJ]*:I&(]VZQO>V,>Q$1&M;``M._. +MYSM&^8Q^]:S,+6)\JE``$0(GXKG]-[DXUE_TO$YMYN+-,[>^[SG><]7G*\9KUMJ(B(M]\`!KORO,M_3IS+<@._V]ZQP'>DV&])`#O7MA[A^,R`" +M1[9']G#>NMZ^^1$1'VO@`,>4^U2FYS]G/S%*;M2F\6(G`$`$`/>G"XG']TE5 +M\Q::?1'O9=@DQP^A47W=$1$:SZ`!*+TYYYE*7'$I2W:=.>>9<<:\MB$3Q4A$ +MRJDF8M;FK6S6M[J.ZQ.*G2:O>C>X1C-F7>]CR;97Q*AX3FLMN5'"N"*^]O#+7&MCKA\8X')YL]+2(LS-N\7 +MEY=TA]I%*_Q[U3`"P/B,Q%DDX+D5,612(.S?2CADI)X7.CDIXGBAN*,$5 +M2I_WL?UG]Y]Y[SO[]]]]'WT3,S,Q$1$3(``````````````````````````` +M```````````````#K3S;--VN`!6>7$WCS6G.O-_37L7;+[MUHF?:9HS&?3L) +MLA"0A(0D(2$)%)24E)24E)24E)24E)24E)24E)24E)24E)24E)24E)24E)24 +ME)1"$A#B,/C>=\:'B?3,].N1GX>/".ECDAR^U>5$O-DSE1!%Y5*=0YH[(HX( +MX;97A$E,GFSWI(7:S+..:+;]C%]$,=>5(A1!%V +M4"QR1#*&RM$"[[L&+E+[7A&CDW(Z0Q;RC)&>*DWY8QQXFB +MG"-'N9MMU!=[01DY,$8=4]E0YN[+^)ZYS'2<^NM2<[SI.OS+[3E..LG9^KV_ +M>>*BN.\//IJ973\GU*18]ZHZ=2LD8PU[X-$6*>ZHZ:(%L*+<6CO:CA39R6(X +M4Y+V&2,\5I441TV.2C/G.]S$97A&=3JS;Q\R?/F7:>4USD +MZ?G[E]^L\IW=E]/">/W)P1)3"[L-GM*A.2&.]^U[F*>NQ%553)FTS5&>/&3P +MX3\>&U]^LGEXYR3:=WXZ3TZ8YG=8JGG+JIJ_7;C59^[ONTWJQL=:?>N_,W^9RN)T]O"< +M]LOZY=)U^?FIZ$Y3GQD\.O:H]3;9$&>*FMKUE&/_?[=K_OOOI_/,S7WTSN+K +M[X?B>'9/?K)^/Q)KMVU/C];_(KWG=Y]-3..0OJ@BS*DD6ZHOE1XL0QZ>$:.9:R45-GCWDY3PO/6>WAT +MNG"=><_._;7A./?.KSQD\)X[:CCR[N]355,KK.^^KI&&Y829/"!>ZCADN1LI +MDX==$;I02^5!(PRI)#%G7)'#C2B#%*^]'0:T.TWHBR\B:B(K+S+NS:+K-1N+ +MP=:.P$&2F3)&3@MU0Y1O*,D9A4?BCA]"Z*.9+G&UZ1ZE2YO=>D3U4SGDS+>Z +M[^BJJ9/?4&+'+*GF4,>'A&_*!A@O"%A4HR;94990QHIXX(X?:5(]5NFCFE$$ +M8*>=0Y[W-Z[/HBHGTU,SY[+0&\*((]M>$.W2D24GJCID[*&LUII]YW>O54SIUC)U0V5 +M.2/:5,GEW3K]ZU>R'Q`OM0Q +M_\UQJRS3,S'OW[]V9F?>]Z2````````````````N[N[L`8P````````````` +M```````````&9UJ>;F:F[@`&,\35WQUGC:JQ4Y5O=3K6<\\XJM8EM;U\U/+2 +M5+D'.5Q'Y,,OB%/H79':5'=1HC)3W%'#RER4DCA]N[^PY"RJ9-P7(GKV2740 +M<77922.%M:CG--7:>*JIDY6\5O"BF4#QV1[JI[JC)&>*&,!/;XY3R_>^?J>N +M^>4XXR>4VGH\9/#TDUQK4V8E6(:V[^B.N]//IJ9]<>I*.S!$E)[>PP1G7?5\ +M)T]1RDY3IZ]9X3CQ\U?QP\I^^Z9RMBY$%,]4=LN3HIC:@F"Q$$D8.O +M9]MJ[7'>JJIF.;BVJV1=E3Q&2,5%DX1XOQK;(L<:71&Z7A''[DFG9/S\X\[G +MEO\R>4XG63P_%[/**FIGFN"*#'RE1@CTJG?*'/#DH\*.&= +MJ.D4ZIBV^*,THZ1TO2/%&.NJ2/%.M.9>:[$3#^J +MIF[/%"B,85)(D\."F"'/>[LQ&8F;@8+D8ZJ0\6"D7THX>U-DV>D;.BGCPCD* +M,$?VJ`(@`1!EJ73^CWFJ*FOTR?=_:([WL7%C)2YP11K2L0TJ)O?K4\L?L +M7WYR>7IW7:=/'K/*>E]]L[/"==>;)!&2&]GS>?T\AXJ:F?7O,K2;(P9JULD0 +M;:5*I:=1CR@7.B(XHX:(%LJ-GQ3UZMPC1U*\(]"HU*-$9*+B_IYR*=WJ:J9Z +M;2?&A)8](T=D.>[7I$SFR8.#TZ,]5/$;,W[9BDD=,ER-1ZK@:+D[[X&,KTA_.7V +MGXFNV3R]1/+T\)V<[SPGEX3Q^9.R?%XXHY"TZHS[U.:]Z'>O34SHYW%40YQU +M>D3*I>X44113W%'"YT4N"-FBQ$%,''%;2C?52B-$9XJ=E1TT3O?)W$] +MB)JJF;MWGO4G==]>4X]Y)K,[,>_SQJ?K2S7;)W?%]O"$<\HT1IO62 +M;*.F3DI1MY>G'L2SUZ?>]Z:J9.=]]ZI(=WLF#@P1?JIR5'C^7?CUC?GF]S?KU[L"JJJ`````````` +M`````````````````````````````````'SRN<5WFF[7``=9RNJ2'=0Q&UZ\9/#VIKYS +MJ=/SUGA.5[.72?B]=\\N>^3LRIXCAHX*8(X7I>:499EY7NO/(B*JIGI\GL^O +MDQ/#E-^\O'YDZ3?;)\3ROMX3EQUEZ=)UY49,F2F7[8=,E*.2.G6EX1[JN1CF +MEU6:[$.\^FIGJJ3Z;#QP6.B,$4>GAZ=JJ9.2Q#4J>LHP?'/%'# +MFW""+;T<6/[FS@'WI$26>IF9RLS+M('E#\O2> +MVO>=T[O*?KV_4[\Y)Q\]Z\L>-Y.6TY3.U&_*2CG!'"^EYE0]+TC.5'3DXE4S +MFIQ#=YWL355,W"Z4!`@`]%#AYQ6*8VM'AR>RHDILY/2.>5.]49(RRI1T6,G) +M'#HCAB,6Z1F,'6BV^!J2@=-OI#:6T1$5.9EWOAI6:+>F0-0]+Y>DYG*$>E>D8PH8BY3W%'#$+LIC2ABNM3N--/:>*JIF[.8GE=(T4L9+$2ZH_5& +M2,SRR21PUY=&3!WO4;X8/8:Y>&$9$+ET;=9EK>YO+L8LZ#%E+13YQ\U=>>[TG4YNCI&R,AWS,R[D=6@C2GG;1(>D@WI#Z^.:F+F&TGG978IQIZTI +MHQYWIHD0Z1DU47>7?;0ZIC[39;0!OSG;LN[?))=141Q^0:O7\M7#,J/?GSXL +MELDMG_.[);)+8_XLELDMG_RR6R2V?\-\RRV26SBV6R2V\/Z2$`TP#_____________________________________ +M________X'+^>H!`P```````#['(&C```````(@``+7@```]````%48Z``4) +M:\Y``%``/H`!U(`#O=O=L=`=V`#2`#8#*V,E&9CM@=MUNW7=F@6LP!\````( +M(0>]Z[.^O_]5-2G +MM4#]I4_*@`#U&GO_550W_^JJH````!H]3(?^__5554(HC)30PTT#`$$W@1-( +M%/>IH](>D](](R'J``&@`#$TT:--'J-^DD#0:`(V@9!HPF()A,$S0":,>H`` +M$P#0-#]4H)40A!C`"`S$TBGJ@/4C333$-#31B:9#":::`R9,F$TPC)@!`P$T +M,FF)HTR:9#1B9)^A#)IB)Z,C$8AIHGID:9,0"-3U!*?JBJFDFIHVF)A2>$(T +M_433(`/4,T3)D::9``--```&(9,",AIDT8FAB&(`::`:-&F@`&@-!@`C1D!D +MT&$P")2:*-%/3:-!-,A,U3P3TIHFTGAH_548GZHVH>H>H_0F4]1ZAXC*:#:3 +M:GIDFU'J;4>4,Q)FIZGJ/$F)ZC;U4T]33U/4/2>4T]3TGE/4\:I^E/TIZF:3 +M]$1Y0T_2&3(GBCTTU`JI)"1C3`3U&A'HF'J8DWJ!,0C#(GIIB384S(TT$]3Q +M3?ZJ3T:GD&331B!J;0FTT,4S)D">0TU3S1HT--!,&AHWZJ-3TTQ3Q,33$:8" +M83:J9V-0K45+8@O4H`HM("H,@-N/CX^/OM]OM]C"9$$$9`4O0%!I`7(@,@(4 +M666%16%49%EE85AEDC(!($@2#)N3B3DRQ&L50D1%DS(S)2RS,SP1$1$1AAAA +MAA%$41AF9F&9E1EE&%$48888888811%$9'O&6564M9M9596[AA$1AF9F&9E1 +MAAAAAAAAD11%$41D8811%$485919E11AAAAAAAAA1AAA!%$&&%)E2``D0!18 +MJ/)(C[I5(^2HE@")5`08.-!H080(08081(08Q81818141A%A!$6D%5S@+X`P +M"(#`BI`@#$8*A&"%%*4&0:+2@R#16E!D&@"@4`08!"!")""BFKJZNKJZNKJZ +MNKJZNKJZNKJZNKJZNKZ1O>][WO>][WO>][WO>][WZIO>][WO>][WO>][WO>] +M[WO>][WO>][W[WOWK>][WO>_@][WO>]^$\)SG.NW[C(Y&B]C2Z7V?:U.KBBX"L +M6Q.SL225*BGD\GD[.SS5HD-6B0I$$5+8EM&8IBF*5K)-H*@]:@V0&R`2`!2% +MQ<7%@*V@@$`)`N5(14@(W06R`-("\(=V9!?*C"#"!""EB4DDE)9GCS*I6RQ+ +M))*DL2Q*2Q*2S,S5F48QC&,6"WH`6P1*04"D!6D%I`2D!QA$"$$0("MD%`+B +MXN+`*P02Z`T@@4@(%(`!2"T@#2`H%I:6E@JML`"V"4@`4@@E("XX`@L("*P% +MLA9!`I`0+BXN+!`MMDDDM+2TK625*E2M9))4J5*E223J=3J=G8HHO5>F]-ZK +MUGJ/4:-ZS2-&(:1$0HE$HFD5`#*@JY4!6D!&D%4*4DN+BXK6222I4J5K)))4 +MJ5*UDDE2I4K625*E2I4A)*E2I4J1$"I4J5K(BK)*E2I7Q`/%>*\5WB@/%==P +M'77<.NNY!UUW"ZZZX===Q)====)===G29UUUTEUUW'77721UUUUUUW"2LJZZ +MVRS.%58NNMX)===PDZZWA.NMXZZ[IB.NNZ777<2777<)===<)===PEUUW#KK +M>PZZZXDZZZXNNNY`NNNK+,X994.NNX#KKN!UUW'76]"====!UUUT===P)UUW +M)'7788ZZWH.NNSH.NNNCKKN2.NNYB.NNX===P= +M==T%.NNY(ZZ[DG77.\B6XP39;,%MN; +M(DJLI,K,K$),`JDP"J23*PDQ"20DD))"20DD))"20DD)*LP,LJ*S*0"0"0"2 +M0#Z>;`)),K*PDD)*0DI"2D`A`D`DJBLI+,J0DA)(22$D))(20B0B0B7D9F6Y +ME999,S)9@`A22$^'U78\Q9999[0S50+XCB^+XOBMJ`#```,`5_W_'Y1_3 +M1O(7%Q(W);\.I.\WJ]WR^WZ_X#`X*2P>$PN&P\KB,3BL7C +M,;CG5OQ^0R.2R>4OV5O,M+S&6F:S3^AT6CTF +M+_5!IM/^M30ZJ=U>L\>;I[:OX_HZNY^_+U'^_CF]?\TB#U' +MHSW:_74VGI]I1=^IH]KX/ +M;N*/Q>[=;G?^^EI=]\.335E5YZG@?'TU?\5WJX'J^7L_CD_/W<6M^GPX_0^O +M-Y71^WRYE;7_3G?Y]_MT?\_'WZG7_/Y_SLH]CK]O]:%[H=#/O9^?>/9]X@]> +M(">H(/4$!">H"$]0$)Z@(3U`0GJ`A/4!">H"$]0$)Z@(3U`0GJ`A/4!">H"$ +M]0$)Z@(3U`0GJ`A/4!">H"$]0$)Z@(3U`0GJ`A/4!">H"$]0GA/4!">H"$]0 +M$)ZA/">H"$]0$)Z@)Z@(3T0A/1"$]$(3T0A/1"$]$(3T0A/1"$]$(3T0A/1" +M$]$(3T0A/1"$]$(3T0A/1"$]$(3T0A/18H3U#%"E18=Z@+#BPKU#"B%A'J&# +M$+!/4,"(6`>H7\0K\]%?1"OCV]("O(GKJSBNXI1[:128KH]M;D0KF];2(A.' +MLA;Q";O8^00MB#UJ@XM*#VS(7*,0.>H%W-"R/4(B208>%6A=$%/B@T).!0\; +M^A*6-!-Y$+N0@'<00=#SW;T"%[(S_:=H7[/6&=[*&`G;'.>5"I#*92)R/KQR&4B\9[,4\EL0 +M;[<,\P7V8C;U[WCK+6>[?!Y*6F9NOQ>71KEW/MN3RVS4C77%Y;F^8 +M^5P>-F^9M?S>?^D,U9_@\C7&;9_1X=(E3GUB7ES8YS[+GCE7.POR>05TSL!7 +MO'V3SUA^CQ-*.TM>\"\9]"O'0=3PJ\C07S/"^]@SU^G4/Q8IW`SB'Y?YS!YI +MXBGS69P[R"S'ZFL0\R\*C,XMYEE:,QC99XM1ELAE'C%'*9+)/(A'(93&1;Q' +M%965PACQ'!2U^9(S]\F(R\HS\PZNUF1GY29NMI1G[I,N6J,_<^WF)%LCH7'< +MS-QMZ+?1=W-W"XHQ^C[V!;:&J1X#;652/`MVLJD>!;]=5=.YZE]OVNG[G5[K=;S<[#<[FEW%3N=S2TB.YB6"PL0PPP5M;6UM;6UM;6UM;6UM +M;6UM;6UM;6UM;6UM;6UO-YG+X_$X-74[W=TFUV6PUFIH-$AGYW-34QE,AC)7 +M"X*_WQU*24C6UO-Y?(XW#X6_J]]3[S=4FVV?[[#6ZK44&B>3SN=YV#PV&Y^' +ME\IT,EC^%P=_5[ZHIMYN]S2;?:[/9?ML-=K-5QN1QD-#I-,^5O00T.JUK_`) +MX%1!0<)"PRE5Y-!/"0:,C>ET^I_?5_SK=?L/>SVO=W.[WO)D^+PO++\?BS/) +MX_FS/]K2=:@['6]FI[+WVZSN=OW;#O?Q[Z +M+Q_#:^?Q_&D]7GKMWR_^^5--Y#YU$YD_3\]]Z_7[_IP!37UX4_-_;AZ-V8`P +M#``6-+O>U#6*F[*Z!IWL2NJ.P9$U/7C#-]76>,JJXNSU=='-:S56]I6:R1M] +M9K;K(UE%=[K6;.^.JS:8*^5FUE<%6;;&RM9M\GC:RCRV3K-7FX%%RJ[A;;EUW#W']5W%I>9\?YI^;\.155OOY7`YWN_KC<_V\W^>A +M[.=RNCZ^AS>EZNET^C_R"'3>((=1X@AHWB"%`\00U#Q!#6O$$->\00V+Q!#] +MWB"%$\000$+7H"%0H"%MD!"HT!"W"`A;)`0MT@(5*@(6]0$*G0$*I0$*J0$* +MK0$+?H3PJY`0JY`0JY`0JY">%7("%7("%7("%7("%7"$*N$(5<(0JX0A5PA" +MKA"%7"$)$0A(B$)$0A(B$)$0JP0A<`0A<$0A<,0A<00A<40A<80A?R+%"XZ& +M*%*BP_40%AQ87DH800L'RD,$(6!Y:&`$*_\M"_"%??Z%?!"O?,O*`G0N:ZLX +MKN*4K;2*3%=.=:W(A7/GMI$0G'DD+>(3?HQ\@*V"Z343BTB1LPKE&".1$7#?YOMBF\+`YCN30L1EX7N3(L3EE/=F!2^.797O"RN08Y/OBR>3 +MB+\.)0RLJ;XL*A@I9GX[^A?)>-O/D0O$Q9Y3RH2=IRUT\R$DUF7 +M/GN2%MR\CZ+BA;F\UZ;@@V;YBUHH?^D)NSHH1KC-,T4#I$K-HQ*%S8SB*Y!R +MKSD*BA!72=@$4'V3SMA1032F>2HH!>'8D1Q.M!/(D9^^9V>1L&=OV<$C8LY@ +M9P2+_.8/-((I\UF<.A!9A&:Q"&7A49G%H996C,8V66(Y7'Y-!@CD\CD4(?\X +M_)XNR((XG*8?!EH(X'*WT]%Y>Y=FZ1>2]XE+*B\D\M=+0B\DLM<[4B\N7;FG +M%M1G[CW,Q(6]%OH>[FKA<48_1=ZO6(HOV-]O[[!%'II\G[T=ILD8261KMMLT8:91^='M4FJJ;=TU-4[V?WN]J +M-YI-YO*>EH:6EIMU]IWO>]GJ\+U=7?=C\3JZN^WTZNKL[Z=75V>QTZNK?9Z= +M75OIV.QWG3>_ONG>=YXGI]5]-]%G9V[E_.*>GWF<]&DT>@].GTVA_[54.E]6 +MNUNH]?[;'5^RBV>O]M'M_W]VZW.T]^]WE'\*FHW7QW]9O:[A9>H^7$S-5\_Y +MS?R?/[OI.X]#O>A],!%0\E`$@J(@/TN"1^F(@=J=H?(.S+1M%5[O:=YV?Q?1 +MQ,14'Z1$0!#(((@;+CK;%20`0"0$5#R3WO`D_M,&8L&XK6YKU>T=?EV"Q(#Z +M4!=4!RJ`R*`NZ`GH$JB50"J`5$"P"P"P**#1`:*E!#)5!Y_\_H/C_+]ER_)^ +MYYG&$5V,%"?45!T"FM)I&<9YK2HHC]/ANBYS8%O$]S['Q*:-:UL]GSTF8(@9 +M@A14?3`^S]GU=@`V#8-@VEJ@$#ZL52@($(H!<@M!1H"!HHCSW/^YM+5`+E&B +MKB04L!`Q%4H4!`B(Q0"=."O2?K_L>]W/ONHZGJO?_L_`UB(:Q48"!-8@A00* +M%^*#0$"%B@%!`I?`3,S,RJ`%05A:"!&"!`!(@$@C"`@0$2`@1@($4$@($("! +M%4("!`B@$5$@($+E0P8,&#!@P8,&#!@R-8HF8&?GY]@#8-@V#:"#:"!E@(4: +M"!H#2H#AH"Y`+A`N$"X0+A`N$"X0-P"*>K@"!(B*2*2*B,@*([G#APU5 +M,,$0,.'#ZK#:JJH8X:1-(PFM-`UQ:ND1ZCT.*_,Z/D>MXB[:%ZWZGS]_T=E; +M*U[;I),\1`[L5,45!]3H:%>K_*V"PT]L?>@-F@,,@/N0&=0'90">0$\@)Y`3 +MR`GD!/("KJZNKJZNKJZNKLA9T(0'BE08(.B1`-R9QGFM*BW(K"")`9^_WKO> +MUL-?KM9:]50ZC3QF*T.W>"P&?SJM8MZ]K>W>\.KS>KW(7R^WZ_X"U7R2I*1F +M`Q]R1`5W9%%#LM[TOI^)W_4=?QUX4/%A(B!(%$121$411)%$1%$E$41%%Z__ +MW\1^"[N[Y_^">1_`@@+_=Z_?Y=_Y^;-OZMH#F$![B`S\)Q`3B`G$!.(#0H#D +M$!^R`HK]?K]?KY7[]?K]?K*5V)$B(B2(B(B2(B(DB(B(DB+T;=B,2(B(B2(B +M(DB(B(DB(B(DB(B(GL+S[U-Z%X6>"(B(B"(B(B3"+U=NQ$D1$1$D1$1$D81$ +M21%ZNW8B)(B(B)(B(B2(B(DB(C")[]Y^]%ZRW8B)(B(B)(B(B)(B(B),(B(D +MC"(B)+V'X/U'K?BOE/8>O\GR8B(PDB(BS+*B2(B(B2(B(B2(B(DB(B)(B_W? +M`?%?V_=O$\7B\7A\Q^$/3>U^?Y_J_.J:>Q6.?;B`?:@/?A`?1`/WH*&JJJJJ +MJJJJJJJTT2NQ"2(B(DB(B(DB(B(DB(B)(B(B)(B(B2(B(B2(B(DB(B+S[=DB +M(GMEYMZJ\Z\*O!$F$1$21$1$D1$1$D1$1$D1$1$D1$1$D81$3V6;&$1$3XML +M1$1$D1$81)$3_?^,_#^=X7@B];;;$1$1)$1$1)$1$21$1$8D1$7K;=DB(B+^ +M?\7W21$1$21$1$21$81$D1&$1)$1$1(D2)2A*1*1*3I\/9_0=<==U"VR"[+> +M9')*^:FK>RYHO*O"KPD1$1)$1$1)$1$1)$1$7F6[)$1$D1$1$D1$1)$1 +M$1)$1$21$81$D1$1)>5^Q[HB(B"(O.MV,)(B(B)(B(B2,(B(DB(B)+SK=B_L +M?WOIO8>;^F^4_U>3Y,1$D1$1)$1$21$1$27K+=B,(DB()"0D(0D)"0D.ZZOF +M]#U-:UK6ZYV67EYN/LL_6Z%XRROVBL*BL*BL*HR,RBF1$)`)`D"0.^1`$/W@ +M0!"*@^U%5HJ01`@B!85@LBD@D9D9DI9E?'(B(B(PPPPPPBB*(PPPPPHBC### +M####"*(HC(PPPPBC"C#########(BB*(HC(PPBB*(HPHBC########"C##"" +M*(,,*3*,S*JO*]+V;TO2]+UOI>CZ7I>GO3R(B(B2(B(@PB(B)(B(B)(B,(DB +M(B(DB(B(DB(B)(B(B2(B(GI7F7FWJKPJ\)$1$1)$1$1)$JR^@]^W+*=$0P-) +M2>U.B'(Q($44'UUEVG\]HNPN^OVM1P;E1T!0Q+6B0&2#@``6`XPP7:DV/2]? +M]DDDD$DW0*=\C7VQKXV-5Q,5'V)G"1+-FS9LV;/&#S`0()E$7815D"1`D?5% +M\RC++1M$,F0A##5^4@A+10''XE!\=RN7Y;RO*AMEFE6:@ET5+35_[!"$>.@$ +M!XR$`#@(8QC&,8QF.0B0D'-X;][:'D?=[OY&Q_N]O[C_7`O////;$,FBGC9 +M+-.M:UK6M:U_O0@`]/'-CGQETO%\>$0GY-R=E$ +MHQ\!XWB^/M$_-;1D,AXU/SG''.Q]^E/&CT6E+ILGHP,A8Q:UK72"S5+I>'A$ +M`GM>7_!"$4444444447R5%!>+X^/(1R/71FOM\O +MY=F\\O_G'=[K:/I=HZZZ[_$7<7#.N:.=2E<.M:UK7";^"`1\I*`0(PHD(RLA +M(B,MB#H-CWS>N$XJV_[7?\AX?7]KP;KCKOC#-.;2F9)+,QC&,8QC&88A*%%X +MOCX\(C(AST[=(-Z_%?;]D4&GMMOGOG._2Q495U"5*E2_^`I3X=S>?-\W!Z/":G[OM< +M9UOG_9M6K5JU:_*:D44=U4L-X_I+OM^(]K^[L +M/-QFKC/3[_Z+KO,>>>>>7I7(UKFGH6M:UKQ+6N^4(^\A"!`A"`2POCY`/!O> +MOD.9YKNOA='XO7?Y[;<[R*C[0MQ;\ZY)9EK6M:UK6N`D@$J+X^0#P&T_8D(L +MNT_RP^%:M>@W?R>^XC_5JU:M/6MS%KH@H7-/0N):UK6M:_=H`%D8DA(QA`0D +M1;`]9O&V^UV7]N$V75^YYKKKKNY%,<6E'3%'JTTTTTTTTTTY(A.4O%\?'A$) +M&.!YGS>PS,^K7Q_9Z_[G,..NN]#]=*>#&3Q,D9-/0QC&,8QC&/C"Z7B^,0B, +M21$9ZO?GD;SUO0[6];_OYNO==<=R7KL5_)!#%DR9,F3)DR9,CYD+I>+Y0@Z# +MD91U$&$(&(Q/QK.+19C6UVVS7"_,ZG`*5=MTB1)NP_8"X:%7J2UJY>664666 +MH+++YH$`:XNEXOF`(C>=Y=^UWKE`DX7=.([N?\?/;-I92D^_[D]:,?M27&33 +MT5,9&QC&,9,@672\7QX(3ZV_^MW"UN^\>?\K$6C?^:[G]J5*E2]*1''B'R(4 +M1$1"0L-`4V@Z\!-^+Q1_(W?BY&>['4<>+Q;?Q4\Q>E2IGXM4TU_[*9N? +M_OWWN.\7BSUVT.MYZ^(U:M6M@:M6K5JU:M6K5JU:M6K5JUB8JR-6K5JU:M6K5JU:M +M6K5JU:M6O)OS4[J$$)2"-"$E'MI)-)6^(B)*2DI)O)24E)242G!0!X/X0`)P +MN8`$&$&#=NW;MUS=NW;MV[=NW;MV[=NW;MUBUD9R +M8`@`PGK/6ZW)>!V._^BX!UUQW>'4IO%EE%^>R6:>RRRRRRRRRRRRR0L:)$)F +M)2PC(,(0$PP!%AW**DO!.,OO2ML3!?^C*C]60)?GS)"5*E2V`#%JQ\6&*E:P +MPPPPPPPPPPPQ:8$2.,$*"08P($%`00$`$,$*"08,GCC@AU^TKINR/%?DX_+; +MM6[=NW;[,;/&V1LT]#6MO-A:UK6M:V,2(E&D)$1C1AH8!X8)=0E`,-A]XNS, +MTF,!X`PPP5?C[RU*E2I>1:1QV@%*H19"E*52N9,F3)G)S*69,F3)DR$+>$`I +MEK4:D4JS%A1+QR/D^3LM'R1D-+X>#CXWD&>>>>^T:(WR%--5*U +MAIIIIIIIJDTTTV!`V+'&''&'`#`@04!!`0`&ATIY2%/M^_:^?3R&WI)"HV<6 +M$"%']?"D2)#238)::J5K#333333333333360`,`"242$AB1L!&2$H\A&P&C8 +M/Z^VSZ[[<^[^]_U5C6/Y8MP<<"<3W_2X!U!X_1[_CY#IN1WWWOR=8]9]C>JG +M7'7?>&?#-CEAHP8<6?/GSY\\.?/GSY\^=")!\@(2(L"<2B<3.)1W.:]Q7?:T +MUP6>;T24_R[A*5P02PKCDEF6M:URK6M:\J^/"`L_JB`5$I"C4BE4R>$"P(H0 +MA!3HG:X/-=;/B`*F_7[:_^H[6B$"X>1XGA3DY.3C%_\E2I6S6 +MZQRUKZT7L&,.T:-&C1HT:-&C1HTC&`X#10)P@04!!`F`(4-OR58$!Z.[J.II +M+OVXB("PT7Y[J1(DCI@<>P0#XH**A(6&4E%%%%%%%%%%%%%00+@!(`P\!"1$ +M8\&8F*!W<.>YOL7L9S?F=(XXYO)KA=VY>D7#%'(M:UK6M:UK6M89$HD'`@(2 +M(C'D"SGO<;C]/"8RX?DXKN_G\Z\\\\]ZCT?9...;26:MEZ>R6:>CXH@1FS9L +MV;-FS9LV;-FS")A*X2(C,PJ&<<>J(J%$^9V70<)J&]Z_R/Z//]?T/R.!KLG: +M'7;_R/4=KR]MJ4@DG"?$E2FF"[%>I?@ABIIIIIIRY9]SC/$^]Q_3Z[+R>H>9VR4_,VY*?W[`E-DDF"6] +M-/1@LLLLLLLLLLL;C$B+#9!"'R`A(BX%I`2FU_N>P"?(U,)I]RE.^:>[?@]S +MSG?_=O+$D0)2C-V_X^R=<<=:9II*-7--AQ8'S5S9LV;-FS9LV;51F2A&)(." +M'+X^42C3I,9"[Y^\4ZWT]D4*N10(HB&1NWN7_Z_&YCF>U^3AP8PYYYYYYYYQYY\7`@.`/P/X0`)P(&"+&&&`\Y'8^#WCNG +MN$>PGUX?A<([UM0^<$>OJ2FNNW7>PUT8,.+5KKKKKKKKQ5Q'J-"`R&`@%')+ +MYE&65'R/1VIP.L[KS"[@KGHP8:ZZZZ\ +M'7-:UKLLLLLLLJLLLQ&*P?( +M"$B+02B2:EY#G>I\`'7'OC?327GT]@L%@L%@L%@FGP? +M4A&1BR&6J8Q>P8P\9&1D9-FS9LV;-FV:"`KR@4*B3I;40@4R*$($U8%@>SV. +MZ^-ORN>ZVDNGSMDB_*ZZZ[XFZ)3;0"`!`661QRW;*+N##J@"`"RRRRRRRRRR +MS]((`N@TOCY`0EI!8>^V.<>(/=]WA)Y-2AE,E!`Q!B#13:_PE2I4OLU8XY15 +MAL,*44M7+V!4*444P***8*DX,"\7Q\@'D&,382'!^=_+P;9<.K_O_K3\WM*4I5N54%*ZYYZY*YIZ,%==========?MA`&@C*RLG(2(C)"T$XDG$GT/BN&H<- +M[_TFU>3V?GU:9SWW>FZEU+KO4DQFS8)L,]ZC!AU,V;-FS9LV;-FS6%9&7Q\@ +M(3(@MB9B8P8PYYYYYYYYYYYZP9]"\7Q\>#7"8Q +M-0F8>)C<.9H-&]I3^TR9-33O:61^"&+)DR9,F3)DR9,G\^*!"!"$!E07Q\@( +M1X1E/,_F?:K'&:IW3KV9<9G7[/N +M:-K7:,\_)6*QL'?.\=PSS8..XKQW^7?O^MRK'&4V;V'P-TU3;OA:MFVL9E\SSFQ;5L''>V_9^+4O<2-.^=[S8/ +MU<-M&W;!(X*1QFS:AN&S;MQ6M#>#>#>#>-O_+I=+I+I)))))))))))))))))))))))))))))))) +M)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) +M)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) +M)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) +M)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) +M)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) +M)))))))%8K%8K%8K%8K%8K%8C1HT:-&C1HT:-&C1HT:-&C1HT:-&C1HT:-&C +M1HT:-&C1HT:-&C1HT:-&C1HT:-&C1HT:-&C1HT:-&C1HT:-&C1HT:-&C1HT: +M-&C1HT:-&C1HT:-&C1HT:-&C1HT:-&K%8K%8K%9))))))))))))))))))))) +M))))))))))))))))))))))))))))>+O%I$B1(D2)$B1(D2)$B1(D2)$B1+2T +MM+2TM+2TM+2TM+2TM+2TM+2TM+2TB1(D2)$B1(D2)$B1(D2)$B1(D2)$B1(D +M2)$B1(D2)$B1(D2)$B1(D2)$B1(D2)$B1(D2)$B1(D2)$B1(D2)$B1(D2)$B +M1@CN>]YDSE$5#G?9F+?X[=V\T8YS9AY??\;2REG[9]\`OJ/:8UY1B\IE9:7F +M-304%!IM-(^CT^GTZ"!!>,_A``G"!`@8%X#A-D[';9Z=[:L'PP-0<_KT7&^: +MZZZ[X'V$IQC6M;?P-HP486M;?:UK6M:V0D(Q\@($%`+AAEX#A5;WG\L@+DWJ +M=X\H-7#AV=3X4B1)>@_D"RUBRPK"U2M8ML8!"!"UVNUVNUVN\5-34U-34U*T +MK!^6YRNSFAQP<8R""[`R.2 +M69C-/3T]/3T]/3T]/3T=F>%YXR#(,@R#(,@R#()86%A86%A86%A86%@,@YYM +M`#`9AFF<7@M09$9`UQ$77$$`5@^@2'L_YS%?+[W_P:?16(;YAB+"./QMP..: +M;"0BN$-4JE:PTTTTTTTTW1HT:,F82^0$)$/!*))S.:104'C^F\7S-MU,6T_; +M^%MKKSSKVO*ZXH(X:Y9IZ*X*ZZZZZZZZZZ\B$(`8)]H"$"$("`A,LP%H6J(J +M$40SCM_Z[%`O$UQZ7\?<:'0='?]?_#\/_>DAI+,!0%!J:#8I$B0\^%L"Q\/7 +ML&,(>J///////////+&,"`!.$"$1:$=[WG?]Z\2]QA';IN6\\GQ/K_V57."V +MO4"LT&_RU\YSKSSSSVC1I:)7]&IDRTWL6C1HT:-&C1HT:)",QTD)$1DA:`D[ +MOPN/>TS;MN[7L_E:;!;R'"Q%@,,,'\5WKA4J5*EZ8&&&+;&M,6+5UC7&&&&& +M&%EEEEX+9@`P$QERE!.1DA*3%P,PD1QW'[WU+UHY;F4I4J&!4*GX(8E*4I2E +M*4I2E1F*83`0D1&/!,5&,H/($(`!`$W#MQT<$Z2'4_VP."`L86))@DGM\.(( +M((((SN%''F`--60RV&-5K%JXTTTW1HT:-&C1HT1E\?("$J03"9C0+*!1IWKA +M\>;YW31?VMZIS^OYEQQSD1C))*)&3T38&,90QC&,9CJ9D1?'R`A'@D$S"FTY)!)))-D`\]8I6J8-F.4@^`1DM@M!*M"P2.YI)>8Y=]\. +M']>UQ;7$?2^;7F]&,MXXX8/1)!TF="T6A@'R`A(BTA$I;'.0IVG_O$6OQH,8D0&,][VJ4L%*T])_25#%'(I2E +M*4I2E*4JLR+("$B(RT(^C\CG=S>1^>5PU0N7[47]^Z9P40%A&B@)T*,=MN\2 +M22223J`//L)[Z>>M7+V"@\\]<>>>>>?L.P[#*2&PF8B(R0E)4(YKI-T]EQ/` +MVS5-O^$^]V?YMT<<5Q6+X5W1U&65I$O.Y\W=HT("]<^]I$B3*>T<=F +MS9JURQFP8P\0S9LV;-FO9LV;-FS7#'@/``G"!!0!`#+&\,%I3-H^P!8P6!^> +M4MIM;OZG39:VZ?1?U82@3Y+%Z-(D240:P(R,C(9=8X5BNAXB,C(R,C(R,FS9 +MLVVW)R4*I0J)1J1/(($_BI4$!+10@.X^'\]W.SY*$"#$2^#WO;.NN.J4JY?4 +MJ.2692E*B5B4I2E0F$4/D!"1%H1C$H-]T^$X7V[-^-UUVU +M:M5UUUW:*Y9IZ(:ZZZZZZZZZZUR$9??("$B'@K$TB0V/"[^SVN^?X@TBV)/_ +M.X2G3JJCJDJBCDEJJJJJJJJJJP51&`D'R`A(BT2"<(FH2B;T?].]^[YMM&CW +MW2N..><<",8R:>.&26:><8QC&,8QC&,VY"`.2J$M%1J12J9.PL"P)4M%BI)B +M<=+@>COOG]GS7SY+N:XEP0@BK?%4X"_$$$$$5H'''*EZLY:N7L#CCCCCCCCC +MCCLFO/`<(`$X0(*`("$$A,)N$Q;_A[R:WQGO=C'0Y3G+[CCE554$,%5R&.2J +M*JJJJJJJJJJK#4)?("$B'@E$A#_.B\?D7''.+-R+ +M++(YH[*,&'%99DLLLLX;+FS9LV;06(,Q"1$9(6D$YUWIW0'P'VZR'_E++^]O +M:K_$`^Q`#\-+.I$B1D$*!99::&L1:I785A9<*6666667G7GS[4"`-<90A(B, +M=,PGD^4<]7Z5PQB3J^CX7O7C4%%O9F_?ZTR222223*W<<GWTI!!!!FG''X`1L;&Q$2QC8V)BK)&O\;&QL;K:VMK:VMK +M4A(;(.$!"1#H2B28_9R+ND)/APB$`&,?("$=!A,.!,)1./#B*O]^?TOU'GG7GNL*JJM6]>JJ@ABJJJ +MJJJJJJJJJJREE14*B4:<65$EHH:W+YCP)WT<%*LB+;<3']MH:G3YSS=I7$Q3 +M,JA`8*WF?JGDR""""&C1I8ET,T:,8>(:-&C1HT:-&C1HT:,!@?P@`3@E&:`Q +M'"82&\;SCZ)[")/K_[_C\]UQUW8C26M=_56N.25:UK6M:UK6M>244.(0A"(" +M$B'4`@%DGD?ZX'3+:,(GW7N^*XOD]?IZGT.N]OP-U`@.E\SW'&\R\\\\]_W\ +M]*?OGKCNT(0@UM;67BUM:I;*];6UM;6UM;6UM;6UM:(6B4V0A(B,M`>R7\3@ +M?0FF:?3Z2,8E'S^#2GL#P!C&1Z+[ +M%SJ=DTT:GM\S/P*2VT@<>>$!^A==(D2'''*3H,XY:N7G''''''''''''+`@P +M'`"@3D)$/$HF82!\_A_9;MXMZZ3^BI<<E.S%--.K!>TJ7X(:::::::::::::<12 +M/D!"/!*),8GWNWN&`3@$]C$>/9Z#'SD"^!JQ@&````&`CD3"KCW(DDD@DFLL +MXXYIIL(JA335JY>:::::::;"FFFFFA#C!``G"!!*$0`X$A"A%E=>D3`$M<]Z +M23P:J7EY>@L810#Q0/"QQP++30:8LM4K6%EEEEEEEEEEEEJB@'`(`$X0()0` +M@&+$L"`4@/LH/\%;&-NF"K/I8@#E(9?_,,,`XP=.TO@$`0)0A!=Y7EMM +MQEL/L_Y2E2E17(U*CDE4I2E*4I2L2E8:1,@F`A(ATF$H1M5>D;]I?+J8:1C$ +M[=Z_<'''%K7!I1K7)+"M:UK6M:U+6O8$"`QH40$)$/!*))Q.+<'$;MLSFH)^ +M1^[O/B=_^BLV53L+%DL#CX.%2D$$$.0RH,F3)6R?&3)?8V#)DR9,F3)DR9,F +M3)ZN@E,=!@_!G-EHDM< +M00E((T=VCE2I4V;-L-19)LVHLMFFS9LV;-FS9LV;-LD(0"!;5,E4*B4:8P,,,,,,8##``&`H!(,,`T@ +ME\@(1T#P^ITAT$`?M^]Y7TJ[>(N;`)1#U#$)1$7Q\@'@D$AW>Y;9[']??6[IO79='%:,AY75I2M:XK%5]_BN`G'8]1B+U!`F`.)Q./5)4J5+E&`XYAAB=_A#(18M7&&&&&&0) +MAAAECA2*\H%"G5L?6Q#=L8[-D5G99AEF8QNW;MH[)I'\%O?HQ#OFLHJV'9U:F;=6U +M*1PG+/Y+`U3%O+?W9M_1>FH7%YC*.@5IL$;2I]S[KE:7YY3MWA/<3ZM/$>NT +M[^+YUU;-\CRE4Z3&(H9//2KE)*PZ):9=HUN^R.?Y_P_VQ*NTBI#HA+2UZL&- +M@I:Z8W'%2TM+2UK:7N6EI:65`,^@_`_@E&5!!`D`L/-6I0#M^]\[^^MZG&73 +M2,A[GY?=_$====KKKN2:M=<]&"NNNNNNNNNNOYPA"#$(O%\?'48Q,@G9=9PS +M"3P^^_#Y?P;MO&736VP2M:UQ:2URWIEK6M:UK6M>`C$HO%\?'4&`2$AW/Z^" +M^ESWR?_/8[I\#5UPDW@8QDL+&,FGH8QC&,8QC&,*(A(2#Y`0CPZ'YO1] +M)#U7*=7I(.L/E;VE/\3D"RRR3#-99@PXFUM:UK<36XT`&)8F,OCY`/"&D@D# +M#)TEA`>%#H>IA\*?I6:/LD7W/4_#3\`O2)$E(>./$`667"KU99:]@Q+?2ZH< +M[<^?/@"@NEXOCR(A(9C]_U/D\1.:I<-?U?<[:\8S^'K^#<<<6M=N.^MA\M#FUX/P5P#UO?K-LE2I4NT +M#;@8888L?C#%[!B888N,,,,,,6*`'&*!^!_"``@!JS&)`]WHA@2A80]>ZNS& +M6[;N[^R5L=G",U#,N.(((((S^P''B@(..8*3CCF,/$$@6<<_G'''''60`&`` +M7#!&A!@D@`3A`@Z9Q-L_/NKJ$3G'?9^MT>S;-YWI?8\P^7?U:24^\+++*(J[ +M+,&'%999999:K5:K5A*>VHH3$1`I5"HE&G85]9$J$!=O3E0(&7Q+)HY[W6W# +MT?=@@?P?0B`F*W-\Y*E2I9L#335-A6FFK5R\TTTTTTTTTTW1#""";`U[J&27 +MS**IL2XIFDSR\*""4,GH:NHN"47#J/U<3M63K;5JU:M6M0X(4JU>5"I4DLRE +M*4K"I2E*RQ"2\7Q\="D4.!(5$QT&X;!PWIUZ>D)-43+[3_G4\LZ\\Z]S1ZGD +MTILLLDPS668<6-K6ME:UK6X\HE$1>+X^/",HTX3H'M,3,)1.8NZW7O.?]#S> +M+S/7:I^3\"4M:V##$UN'%C;"UK6M:UO.@A"$6'&H0",**Q+Y`0CH2B;@E'/< +MYKCX'$=YXER\),9D''_C:[YM.'7)DR9,F)31H:L"RRWY3`%EK%J@LLLLLLLL +MLM<$6`X/H/P/X)1J1)NW$RCND)0<7\'3^=\W]^P%RZ=GN?"HW;H=EW7V%TW8W +M#RTI^,6668'\-EF'%CLLLLLLLLLLV(PYA*(A.8E'("$B$H!P\WCNZ0%C`>Q` +M.J`?YP5U;=I1\O-/Z/(:V>)3)DR9,FP8%EEK8)<66N7TY\^?/GQY\^?.LRC" +ML=+X^0#H1B91-P2=E^#3'43B>(;[K[_-O////4TTW]1^FF*.2FFFFFFFFFG# +MZ$NGZ3DSY)XYW1M)TQV#A*)W3^+PW[-X_JRBJ=X]=W:OK,Y13K@BA;EQ2K6B +M53[?K.+^+TW3X?`WG;=Q?,@;Y^H*GS?2D_RTI/<&'#AS\.AAPZ_8;'#APX<. +MR;9MFV;9CA$W2\7QU&02@R&N')#Y_Y)SQ.VM:9 +M$^>V6+CR>FOU1ETP08-`2!9`C^WJ?TE2I4K)DR9+K"R90\1$LF3)DR9,F3)D +M>"A8N4=*VSKU.R*N,N\=E'0O/7!KFJ=2Q2SK>X+TV;8YH&G91SC2,*N[\U`] +MYA'AN^=L\%Y39/$;5W;-+:P#L58_BN"K?_,2RJ?=.\UF%X9!4K2\9FWJOH1/ +MI>$O[7JZKJ[/<<\\M_UP76,6J&R7QIGG(G(*-^+X7&8Q[:MN17EB&0=BRSUW +M_F.5B\KRWCR5M>2^%R;6L*\9:UW?`\IOW6/2>/GN2%E7N224R9,2FCP9,F3!\?&3*(A8EDR9,F3)DR +M9,EAP#OH5Y0)PJT1`I%2KZ<0'?;>N)R?[*\;776G7W_D:%$A`4$8!,&`\2$*'7.AX@RT^SW4_$K=A/^R%"! +M"X_H<>:!_`PR$*4F&+5R\PPPPPPS7:[79S`1";Q?'QTPB3HO1.(XKQCM]4>H +M$[$>1]3JML_72/FEL'.I2QEN>^QD]&!C&,8QC&,FRB2(O%\?'D4"3R-%?J=OCJ[SPP/D4`]D",#4]FZ)$B0XY,PL)QS!C#G'''''''' +M''`J&0`A`A%TO%\="(3A+9_B-XX/==W\+!_6VCTG2:O-N.NN]"55:<-4%4DL +MUHJJJJJJJJJJ\($`811(-,(]"1$8Z@F-(1C)Z,"UK6M:UKYQ"`"1`B=(A"4A$)`'$H$7B^/CQ79$4I`D$'0 +M(!2";3V%`"R(29Q&D9`)%P]]]?L?`\VX#7D$Q9D$!>DUO7?N?/[_PO^;L2[$ +MQ+L3$V8_,9\[^2?/GR9:9,^?/G>HSY\^>T"-`D!"*4@72\7QXJ.62DD!)!V) +M%2D`600Y3$[7Z/G?C]7_/BK>2A!A$H0X)2E"$I$([?ITI^_UB4J4J/44J:>6 +M^I2E/*4I2NENRR!H;(H(.S(B9)?,HN*HLD@.:0*0"17$("%((\URW3^_[SMN +MFY/ANZQ@4QX\SO__?+Z+IJVVDDD[8)0##%JDPPQ:N7J####"######$PP)P' +M7#C@.,,..`P#@.@8"&W(@&27S*+BJIN"*M(G*\&BV0D0)#/(HWB('G<'%Y3/ +MXSQ,CR>_QD3(@C[;XV+V-EEEGLRNNB3!77!AQ/URUUO5^K6UK6W$(Q)$"$I` +MB$N)0)2A,!D&0#6&27RI5S"":9!4_(VM%TR+Z2(`A\M4'%414.<5!L0!*`(! +M*(!`G(!!*0@0(.PODJ')(L_^GD>+0LUQXHO"3``HJ%?E912M8M********** +M*7C/H/P/X)0@0'&""!6#W7%`3HT]7N#V$2>*+X^.BD1-O^LI`2T7R^K7$X@+G=\!_*U3*U,=Y_[O>6G)RY\F6EWKI\O +MJ?U[5U#SSSSW$BUWY8%22S*4I2E*4I2E[@(,F@=$.2"8"$B'491*)1)Y$?<> +MF>,`EWS$IQX[5_4QWK[^/&_CQ8L6+%BP8"=P0G"7Q\@'D1B3J.GTQWC:OJI< +ML_W'V.U;7V^P[9R%Y0E'M-;Z#CB2HC6Z1(D]H'''+7TY>P8EG'''+CCCCE9P +MZ@!T@##E@_A``G`@8X$HD+8X;[OWU>BZ?=.Z]=ZQQQRFF._33%')33333333 +M33C`$`BE-\@4&99-@3)+YE%@;$CF'(>7Z?16Z':<9D'P14XT5!TNW]_T#KCK +MJ]26&=?$GGGGGGGK0.&&NK +M\#^$`!(T"`X#2RI@$*!%MLB[;7C0)1MG@8/*W)7Y[=NU:MV[;QQ`ZQ]DC)IZ +M&,OL8QC&,P#(2H<$,'R`A+@1B4%PD'^\_?TUOD>7\WW;KKKN3)JQW\D$,6V( +M`$($(RY:8VJ5*E2T'.N=W2I4J6.`LM]60Q:R`6E%%%%+)DR9,L:U1(D(DQ%,4"A42= +M5"F2EPV77;+2V^M6)8.)X%RP^(P&%F.%MXA^`(0/7YNTD2)/R!QQRV%.7L&) +MR=8<<<<<<;U?`[B_N]>92I\3YV[I'%KCN::Y9I5KC6M:UK6ND6A"81*Q\@(1Y!4)4"9C +MB/KO&40CZ'*N("XAXN^XWCG\L'U=('S3+1Z\6N)Z57O/ZC$(4-B`;BM?SK_ZI"22""2 +M?-.#CLV<(S6LV#&'9LV;-FS9LV;-FM!F.>E+?CM8!-TX+?/I?2M&42;[M"4K7:ANKCDE6M:UK6M:US"TI$)0++X^0#Q +MD$R"QSG\OV-V>]7W6OXE[(71P*?]XW=^;I$DDDDDRV+''@0+++AH`M4K6%EE +MEEEEEEEE+AAP&4`D*!_"`!.!`#,`'@P'`H+,RV6=P."//YONJ]YH=%-6_`8J +ME(((((M@''+U1QR[DZBKJZNKJZNKJZNKH%74U2*4A$4JK42C4B>@\RIE5M$2 +MVWN5/N?=<=JZP;UEW_5====4J5V>WIR2J4I5555552$7S(9$%1?'R^5#`3=" +MI-YN*7B&DD@D@)(!P_#Y&ZZ+ENN[3RM'E>P_QR!$V9`,"HI!7;$%Z/N^-I2G +MC];>I2G,FIJ:_(S]38\+LKYJ:F?J:FIJ:FI>/Q8.Y@HR$A"$A(#GSZ(B(B(B +M+[QNQ$1%N[$1$1>V6[$1>W7J;R[S+R+Q^.(B(BW=B]5;L1$1$1=NQ$1$1$1$ +M1$1$1$6[L1$1$6[L1$1$1$7OGKOD=\7BB(B(B(B(B(O9;=B(GT/^/KD1$1$1 +M$1$1$1>FW8B(B(B(B(B(BW=MW8B(B(B(B(OXWMWQ_R_IOVOPOK_+\GXWR/3] +M$1>Q[L1%Y]NQ=NQ$1;NQ$1$6[L1$1$1$1;NQ$1$"4B4B4B4B4B4F!U*76MB; +M.V]@PW34:UK6M:V34-1(1>T[L1$1%Y=NQ$1$1$1$1%[;;L1$3Q;-VW6S=MW8 +MB(B(B(B(B(B(B(B(B(B(B(B(B(B^[WE7J;R[T+Q^.W=B(B(B(BW=B(B(B(B( +MB(B+T;=B(B(B(B(B(B(O.MV(B(B(B(O%NQ$1$1$1$1%N[$1$1$6[MN[$1$1$ +M1$1$1$1$1$1%Y]NQ$1$1$1$1$1$7V7J?1^U\/"(B(B(B\C=B+=V(B(BW=B(B +M(MW8B(B+RK=B(B+MV(O8K=B)$I-ZT][<<[$1$6[L1$6[L1$1$1/%LW;=;-VW=B(B(B(B(O- +MMV(B(B(B(B(B(B+UENQ$1$1%ZZ\N\R\V\F\?CB(B(B(B(B(B(B(MW8B(BW=B +M(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B(B+SK=B(B(B(B(B+MV(B(B(B(B +M+=V(B(B(MW8MW8B(B_F^F[HB(B(B(B(B(B+T+=B(B(O#=B(MW8B(B(B(B(B( +MOOE_%OC+Q:.)DX^CD:S)X0O:.CHZ.CHZ[1T<8QH2$A(2$A(9U*$@1$1$1$6[ +ML1$1$1$1$1$6[L1$1$1$1;NQ$1$1$1;;L1$1$1$1$1$7H7LEZB\J\=X_'$1$ +M1%YENQ$1$1$1$1$1$2&@4H2$0K%"3M^*H@\_S=%0SR`?A97F\=B<#UWO/H;W +M&`R8K(LD@,@@@#A8#"@8/D!"/$@GEZW$$PG8%<3$]_'NV> +MHSW%S'JLXSR^KVM:XJI][LE]PSKOV,L:QO\,J[EG6:7UD6!;QTCNWKMRK*+8] +M!L5*]=OG:MTOS-OE?4[]L678=\C_CWW-/@>PN;]6!6);%B5:Q+$]5V#L'M+$ +ML2UNN*Y5A'D/36%X+N'[FD?W>4\EB&6:-2N:4JUL:ZAIGPNH=^ +M[]FF:81B&$81SCG'-N:?8_,^I=6]8A=&(8A2.]9!LV;7-H%N6YM76,HZ-@U0UK&O96 +MY;FF:=FF:4[CO^*=Y;>J=]#^J\KRJ72/,>8GWJ+0Q*[.:=RL+N&D89>UH9%I +MEZ?@_5PW$8EVR?9A:&/9Q_)-=`TK1/4>8MS5.]=:T+M%.R;$.>6Y]#3MB^UV +M2^NA=LKKKVP<18%M8=AW6/!7EMTYMT*Y*%0O06=@W.IYK'*/"=8VK@N&SSXWYOG>XX#O6F>2Q[ +MP7-N&W3M'BN&X#O7*JA5,@_H]Y][IVK><_@K' +MGN,]5^;IF=6EW[>-JOK=+*[]977O;7EA'DK*Q+7KRS:^KPO"W/*>\]Y/M"MC +MHGNN]:)_9EDC6JA^:]/Z,8O3O%*RK[FH>`[AW#W7@M&^Y\S?NG?&R;!L6X3J +M%0J'XO89-\+]70,VS;8.@<-FFP:5I7MO:?@J'BMVX35LNWRE8)@G#:!TRH?, +M]E=FV>R[EP&P=2T#'+$QS'+HQJ\O&7E=6+3Z?8M/L:S[TFE?FP2W,:GV!;Q9 +M&A>VXR:GWQM%><%BN%>^=X6NN]_CP'BYMM&29Q5*I5,$QK_#GUJ;UU;./7=F +M_-J74,2YIN$C_#+/6?X6E:'*-.S[#.^8=G&)81Q7'<1]3;LL_JIWYO#8IX;B +MK8YAK&7?>T[T'H.B8M_-@4CANB=*Z)[KM7D,4W3?KXV+T74-,PKH70OI9%Q% +MZ7IT[M6^9A[+^CDT;<(VH>JPSI77.U<\_LYY6.>?%(X+)M +M&US,NY4B?>THV+8)E%Q7%RJYIYRSX6671=VF4;=-.WJ6LR:LS*NT=HX3T6F; +MU@VJ85@V#>4\%9W,,R\!BGQN\;9:5A;E\C"JEKU8X#R%4U*PM0L+4,8IW./+ +M;E[+[7G/YO=;A_M]KWFB9%_MXS_:U.^?$R[=OQ4_1>IR&T]RQ\3K^^Z:IZ;) +MX9AGR+F]98IBE=8Y]#'-^ +MNCT5D899%S<=SRD9=;TUK5M?*R3,KVTSC/;# +M3Q/W@[?,5%B +M&"#\]%@\[NNHA+9^;>>>>O///A?0B=B+Q? +M'QXA$AL7>2COD?4_3MCR!.Y^MA\'Q_W6[=NW;MVZ;M,%,46\\\\]\L7=GOKDEF6>6(!`QC +M&,8QC,`0BR^/D!:&$!`AWG(YI5!"Q1$"044$^/\+?;;1N\/M.??>1E$H$(0C +MIO'WG[;KKKOM/?)3=TJ(ZYZ+]8QC&4L8QE"!"$`,+I>+Y"6A@=9^F3U3.L_+ +M^_C+9J(]_N_>N..?-*JH=*J.26HJJJJJJJJJF(1-1>+X^??M!&)4)^5KWW'3J$^2?S_YT/&.NNN^[%30*5+-.H4JA2E*4J@0A\2A1>+X +M^/1"?\S?LH>"8XWAN[P?>\6XA"A)U'\.$R.NNN[F2BI(*+\T]Q0K54I2E*5, +M`3D`HOCY`6T$8GH?L?KZSA>&_CW6DC$=T;09;ST66"&+*8LN7+ERYH,(!BO*!0J-!`5JT(NKZS89[@]WR)"`VT?CZZNGU=+?Y4J5:NGBB8RB\R:>A +MC&,_1777777"4%9?'R`>C$E9_FUQ'*6O9[UTO5XBU]'K_5?0====UVNYUQQQ +MD\FJR:2=C&,8QC&,9A0PO%\?(RTB,3B,1=[P04%HS=3JOU_B/&<='+7]^]G1 +MNWSH+[I$R9,2F3)CUBP\]>P8GGGGGGGGVRV6SOJ)R4$($+(7 +MD*W"G15[P*[E?KX_GXG6=;E*&YGY)9>'8/7_A!!))).I#M`:JA5YJUUO(]7Z;A?$AZK&=IX.'GO +M4O.O//=T+N+DP+GHP+7A@6M:YUKRHB$K+X^0$1:-VW:4=1T&?K^8W+?/O]=I +M7N.[7#U3SSSSV06NB*5>K/0M>JN^M:UK7$=I0($(D(QA"1$9;M'!^_=0(`M? +M%L_IS/9[O51WS[]Y`A`=Z(0@[_STIV0T\.".9M%&!K6M:UM#6MHC*R +M^/D!:D$HXN>4X[>;7(3?W_IB+79P-YGQWGG7GJI8M."J26:J*JJJJJJJJK?0 +M0.$@@6,L2A42C2T]C,;84X]_FI5.YG]T_X?^:+.Z?35ZNWJKSRKT/0R5;HD@L@R*&?I^E[*O3\Q14Q(!ID`-QU'R:4IFM9HILTMZ72^C==;=;==UGAR;;;:.;K=MKL&CE\43;[?;[?/)GS +MY\^?/=I`0"$@A*4$PE"!`XE")A(&@U +M$IX,PN7;FEAU-6[JX1.'#APX<.'#APX<-T,"02D0($I0`!"@K"!!0$$$,%@! +MSN4@*0\&B^O%LN-QW.-O:&T1UM.G+##![P.6J284Y6L6G`<<<<<<<<<<<NY4,E2I4O$ +M`Y6G.A4ZM:N------------BP4`.!H^0$(\'X?P;\Y04%HKHY[/;[^+F>:TS +M*<31MW;?[^G_GM=AZ;3T]/3TKFGIZ>GRQ_Z:(Z*H*,F6G1HT:-&C1AT5:-%1 +M$:!\@(2T@Y3^3TD:1LW`?8U.2_MV?D\KX6JBWY7/?\=<==C&,9+&R>Y$QC&,8QC& +M,[80!&1F`*R`A(B0]]O*+%BQ8I!`1$0X( +M`PE\?(!X(A((`]@A`*H'7]?W'C\KS7UN^Q132(*F-R7I;'[%E++.0+,[.O9> +MRS,W.O@(!"E*4I2E*5J"*$"B\7Q\D)#J%:02GY^SQ[9Q?NN`BZ'E^=_>ZZZZ +MN*)<"Y9IUK6M:UK7-E@$D`HOCY`6D1D9P5GTNE3`%C#!_7&X[\T>9J.C1\W9 +MVZEQCT@DDD@F/`Q4J7PABU4"C6I"F8VKJJJPKI=+ +M[\7]?/GSDU\,8QC,!`"9R^/D!LFRR +M%Q'+I>C^"Z\\\]\D]&?1%ZFI!.N6:=:UK6N1:UKQ(@%E\?( +M"U]WH)!WU7I?"U_U>:MH]^-*::;L=,,4?SD"$(155555555555.2$@X5$!"1 +M#T@F3FO>>YZK7[#M6,T]03\A[9^IX'X;SSSW[2V(!"$"$1"4(!`#)Y[UZ272 +MFI6M:UK6M:\2(R,6/@G"!!,-!!ULSU.^3`S#[?T[=3LW>8WZ%)*RN+]6#))) +M())@P*7*"E92UPVCJ^;_7M& +MU\IM_2:_)[K&>%(E2I;N&8V0XYBM6P5&+E[`PPPPPPPLRR0`19@/P/X0`$#0 +M0#\'UPAJ:EKGA^)3NNY\*E*:7"8V5>TLF_E:6EI:6EI:6EI:7**GZ2IY*IVJ +MI\I4T53I[?SM_RWF8V0LG;RC1^[S[SB)K_V-+2UOP?!I;U_&D^.9RO!V_D<+,KG?3*>'E_2GORR+W2S?:)62U0T?LI,Q[= +M_X.CL.^P\&"R^TQOV)E_GK+%I.]]X>#TV%/Z?YTMVI)@[T>CK1,3^6$38=._ +M^_![]]??'1Z.Z71FHGI1KMM3A]$8PZDKTZBC_7,Q'H_?BKU9[9I]#?:MQ;7[9^^"*8IO!^H)]?8&_7[!;;T6=FSVLE3XNIN^G-Z.Q^W]?VAG=H +M;Z?]AWI-Y["GWVW)&[_]E4%'0_@F<%K=>I[D%';G:ZV-P-5?;957'C1MQ\WZ +MH=[(R,K>]_O]%(9R^9/"2S7]S/?QU78^4W:!;]7R^G7Y?\>NXW'T])W!SRKW +M9Y'C^KW[^LK/S?N-\+(1#8#52N$PF?XEYDX!ZUQ$KB.RVN6NA^K>CR2=-M.Q +M%<&AO=YN-5L-!Q^=2Z_B?W#=;S7^9[>(_910[90]T\;=M]V*%5U-1=*W_;A] +M,0_<__PE$=DO:7]5%_W6V)XG6]V`A]A_65VWW_!)=+OXC[=B'Z-_@9N%DNE% +M^BX4S=KQ-!@)3">/K[CW +M9+=6>D\,[F57GU>&ZEER*/!4\FF_]^KT\F][^.%Q\;K\*JEZW(X/C^;$YX7E +MR]M_/ST%-/QD9_&"Y'*R6)Q.0ONE[UOH_HN70N.A?QRK7CNQ!;[*3>UM?74H +M:QY089IP^>=A;M-:OZ\N8F'JF:_>NX>F\>*7YK0:"\]3\M\IW5=1G_G +M\IO=:E?+Q>+QY;;U/M*[S(YF5J-# +ML+7MOK%WN][.+C[QO^QJZ55];Y5J:B/ZC\F92,CLZ`[3W#D]K^9"EF#M+G9`[;S3 +MNUYOA>7R[VU^4MJ7I,*6C-0\/G28KLZS,]SKFZ]]E +M_3RN)@HJ*BGMEY<%.Q.*\'LU+B)W6ZOKJ9CNA]25GIJ[0+E_WQ=)U8Z>M)-M +M]M:ZYM\P/_NL?U3[Q_,[H/W\/QEJ+TIO[EZCJ];JW;:X_X"RG7G[CZ^%%[/[ +MZK>ZM-BF"I5'P]YK\93]AI +MPL-U>2@^_)]^?@A:+/X/+04%L:_R5\W\Y'*:Z][PFS_-E@LEVO#TL5+,,EV^ +MSD];NKFWX=]F+S0PMJL7R]+QFU[[/Y?LR)QV[QR>$N_MNFUM]=;Y65EO)75E +MWI-4JJ]7(5M7L?5CMI)[OO=RYOK7(Y7-9KQOM'%M]-14G-_KYYW.R_^V.OK^ +M+L^?P.3_'#7R4IL779?>D^OM>[W5NMV>4;F0A\]3:=OUL;]MGFO!<-=A"+7_ +MO)?M_O]1T//I?=(8>Q\WI7[E\LDQ/U:GP^W:?%\KZ[@[;N6G(2DI<92FUUXV +MSS.OU'SH*7LT%4/T-QX^/DT.='Y11S^NO4J5N`P&$Y75DF5&*"%IH*:M^7H< +M'Q^!8.98+!W?-+SXU%+&[C[676<.1^"I5[R: +M+[9OSWPRG>ZFRL4T]3G<[EN6^DU&X=3V@GMS?9#66;FEVPDF>X/=M% +M-/G]9[>?-ANQ>9Z$J$W6W$YB:9C#;S&XW?[6T]N)M/;K^4PZGP:-/WV6/IOY +M)HK)S\FPU+!A2S_8ZO0O_(7K_)]=!@.1U:11K2U'FH:',N/IA=._+GZCX-JL +M?.O%,GO.I]5D^,7.T\B3M+4YG&+SET.T^?Q)K]+4U$TUU$'$1$!=ZOF1TM]5 +M>V^&OLORXFUO:U*JOB:/2[#Z<3B1=9>W[&T9T?'^>_4.M\^0OSBOD<: +MFLWASF^B^_D>KR/Y35UW;>5WBLIAZ'@='[;'V>7^K/AM9?$W;^5Y:M2?31_MLM)?-MYL[\;)C\?F[)@=#3\&BW:K`]21;[!!5EM)Z]QO9Q154.Q +MH[V:HN\EBNCOOI_--KO+GY&1KNW(QIN@Z=/M]P]M_(Y":RN=#F\KS)B1XO(W +M=GJBL/E,CRF@MEZG^XQ[RNGRW)7K]*#(BY4$1U +M(C_>)$#V[>6E>[SO^W@=[>(2_(\J3VW$0XUIE]73:[+;^RY7-79\.D)7+T7' +M\[YSIZ_^Z\2'+\>2]OB^U]UTLGAX=1-8>C9,O72YOXX"3DYN3DY:K?]9'>#N +M/Z[T\"9SWA'F^W(_Y=L9=[>TB(3M\:U8N,A(2W=H?W\2*BA_^]^KUTK->_)_ +MC`9SP:NARGSMB$I\[D^PQIMU:RV\O-2.I=NTKMWEG;B8DY=W:[6[=N[3@79Y +MTP[QCMV[/O5J=WNR63'.W>"4.XAV[B'<1=W<0.[=NU]PM.>=CX;&0CMV[=NW +M;O*VEWG)5V[=V7`N\N^'2#N[XAWF7QV[N[O)2#MW?G>0R+MV[3P\.HP\Q,,F +M3MWFW>`DY.7DY-V[?W<<[=OZZ;=N\\['=NY'*W;&7>WM(B$=N[5BXR$A+<[' +M=S,5%#NW;MW*S3O)YK`.W;MWE'=L=RCNY/L,:;?.7_OD\!DXL$Z=CUF4CEGB +MN[;].+ZHW!7]V<(0@#_,4(``88!@YF_U7YO'#Z/SFYA5!75KVZ!J_3.(E(&^ +M8_8T&J_5IH)/B]=C'9]0QL=%K.,Z\7T^67O^ZVG7TWCAO1/S>XJ)JS3BV'U$ +MWN-0HLHLIQF?+P^]YO\_([R\^IU7"T%3ZHZIY'`MR;BU.XIG3JVK&SHUTZ=. +MG3HMTZ=.GYTZ50+I>Z=2=J=7!TZ=-G4:H8V-TZ=.G3ITZ=.KBZ=.H9TZ=.G3 +MJS.EL.Z=.G2BRNG3IFZ=.G3ITNNWF\WF\Y;DN.IB4G.I +M[<($BQ)"$)!DDDM4$`)EX#U79SU<9X/7WG99Z"QF14`LJ3,Q2K%4496*99BE*4I7W(NY(IPH2'>']) +!"$Q# +` +end diff --git a/tests/usr.bin/shmif_dumpbus/t_basic.sh b/tests/usr.bin/shmif_dumpbus/t_basic.sh new file mode 100644 index 000000000..10fea105c --- /dev/null +++ b/tests/usr.bin/shmif_dumpbus/t_basic.sh @@ -0,0 +1,86 @@ +# $NetBSD: t_basic.sh,v 1.8 2013/04/07 19:14:03 christos Exp $ +# +# Copyright (c) 2011 The NetBSD Foundation, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +unpack_file() +{ + + atf_check -s exit:0 uudecode $(atf_get_srcdir)/${1}.bz2.uue + atf_check -s exit:0 bunzip2 -f ${1}.bz2 +} + +test_case() +{ + local name="${1}"; shift + + atf_test_case "${name}" + eval "${name}_head() { }" + eval "${name}_body() { \ + unpack_file shmbus ; \ + ${name} ; \ + }" +} + +test_case header +test_case contents +test_case pcap + +ehdr='bus version 2, lock: 0, generation: 22, firstoff: 0x9e414, lastoff: 0x9dfd0' + +header() +{ + + atf_check -s exit:0 -o inline:"${ehdr}\n" shmif_dumpbus -h shmbus +} + +contents() +{ + + unpack_file d_pkthdrs.out + atf_check -s exit:0 -o file:d_pkthdrs.out \ + shmif_dumpbus shmbus +} + +pcap() +{ + + unpack_file d_pcap.out + atf_check -s exit:0 -o ignore shmif_dumpbus -p pcap shmbus +# +# should not fail anymore... +# +# Used to fail for "PR bin/44721" + atf_check -s exit:0 -o file:d_pcap.out -e ignore \ + tcpdump -tt -r pcap +} + +atf_init_test_cases() +{ + + atf_add_test_case header + atf_add_test_case contents + atf_add_test_case pcap +} diff --git a/tests/usr.bin/sort/Makefile b/tests/usr.bin/sort/Makefile new file mode 100644 index 000000000..104012764 --- /dev/null +++ b/tests/usr.bin/sort/Makefile @@ -0,0 +1,15 @@ +# $NetBSD: Makefile,v 1.1 2012/03/17 16:33:15 jruoho Exp $ + +.include + +TESTSDIR= ${TESTSBASE}/usr.bin/sort + +TESTS_SH= t_sort + +FILESDIR= ${TESTSDIR} +FILES= d_any_char_dflag_out.txt +FILES+= d_any_char_fflag_out.txt +FILES+= d_any_char_iflag_out.txt +FILES+= d_any_char_in.txt + +.include diff --git a/tests/usr.bin/sort/d_any_char_dflag_out.txt b/tests/usr.bin/sort/d_any_char_dflag_out.txt new file mode 100644 index 000000000..610c4704e Binary files /dev/null and b/tests/usr.bin/sort/d_any_char_dflag_out.txt differ diff --git a/tests/usr.bin/sort/d_any_char_fflag_out.txt b/tests/usr.bin/sort/d_any_char_fflag_out.txt new file mode 100644 index 000000000..2bfbda8ec Binary files /dev/null and b/tests/usr.bin/sort/d_any_char_fflag_out.txt differ diff --git a/tests/usr.bin/sort/d_any_char_iflag_out.txt b/tests/usr.bin/sort/d_any_char_iflag_out.txt new file mode 100644 index 000000000..99d3ae60e Binary files /dev/null and b/tests/usr.bin/sort/d_any_char_iflag_out.txt differ diff --git a/tests/usr.bin/sort/d_any_char_in.txt b/tests/usr.bin/sort/d_any_char_in.txt new file mode 100644 index 000000000..5963fcacf Binary files /dev/null and b/tests/usr.bin/sort/d_any_char_in.txt differ diff --git a/tests/usr.bin/sort/t_sort.sh b/tests/usr.bin/sort/t_sort.sh new file mode 100644 index 000000000..a36457cb4 --- /dev/null +++ b/tests/usr.bin/sort/t_sort.sh @@ -0,0 +1,1023 @@ +# $NetBSD: t_sort.sh,v 1.1 2012/03/17 16:33:15 jruoho Exp $ +# +# Copyright (c) 2008, 2009, 2010 The NetBSD Foundation, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +atf_test_case basic +basic_head() +{ + atf_set "descr" "Basic functionality test" +} +basic_body() +{ + cat >in <expout <-k + atf_check -o file:-k -x "sort -S -- -k in + atf_check -o inline:'x\n' sort in +} + +atf_test_case null_bytes +null_bytes_head() +{ + atf_set "descr" "Tests the behavior of null bytes" +} +null_bytes_body() +{ + printf '\0b\n\0a\n' >in + atf_check -o inline:'\0a\n\0b\n' sort -S in +} + +atf_test_case long_records +long_records_head() +{ + atf_set "descr" "Tests long lines and keys" +} +long_records_body() +{ + awk 'BEGIN { x="x" + for(i=1; i<=12; i++) x = x x + for(i=15; i<=25; i++) print x i +}' >in + + awk 'BEGIN { x="x" + for(i=1; i<=12; i++) x = x x + for(i=25; i>=15; i--) print x i +}' >out + + atf_check -o file:out sort -r in + atf_check -o file:out sort -k 1,1r -k 1 in +} + +atf_test_case long_file +long_file_head() +{ + atf_set "descr" "Tests with a long file to try to force intermediate" \ + "files" +} +long_file_body() +{ + awk 'BEGIN { for(i=0; i<20000; i++) print rand() }' >in + sort -S -r in | awk '$0 "x" != x { print ; x = $0 "x" }' >out + atf_check -o file:out sort -u -r in +} + +atf_test_case any_char +any_char_head() +{ + atf_set "descr" "Tests with files containing non-printable/extended" \ + "characters" +} +any_char_body() +{ + atf_check -o file:$(atf_get_srcdir)/d_any_char_dflag_out.txt \ + sort -d -k 2 $(atf_get_srcdir)/d_any_char_in.txt + + atf_check -o file:$(atf_get_srcdir)/d_any_char_fflag_out.txt \ + sort -f -k 2 $(atf_get_srcdir)/d_any_char_in.txt + + atf_check -o file:$(atf_get_srcdir)/d_any_char_iflag_out.txt \ + sort -i -k 2 $(atf_get_srcdir)/d_any_char_in.txt +} + +atf_test_case bflag +bflag_head() +{ + atf_set "descr" "Tests the -b flag" +} +bflag_body() +{ + cat >in <in <in <expout <in <expout <in <out <in <in <in <out <in <xx" + atf_check -e ignore sort -c -t: -k2n xx + + atf_check -x "sort -S -k2,2.1b -k2 in >xx" + atf_check -e ignore sort -c -t: -k3n xx + + atf_check -x "sort -S -k2.3 -k2 in >xx" + atf_check -e ignore sort -c -t: -k4n xx + + atf_check -x "sort -S -k2b,2.3 -k2 in >xx" + atf_check -e ignore sort -c -t: -k5n xx + + atf_check -x "sort -S -k2.3,2.1b -k2 in >xx" + atf_check -e ignore sort -c -t: -k6n xx + + atf_check -x "sort -S -k2,2.1b -k2r in >xx" + atf_check -e ignore sort -c -t: -k7n xx + + atf_check -x "sort -S -b -k2,2 -k2 in >xx" + atf_check -e ignore sort -c -t: -k8n xx + + # XXX This test is broken. The standard is not clear on the behavior. + #atf_check -x "sort -S -b -k2,2b -k2 in >xx" + #atf_check -e ignore sort -c -t: -k3n xx +} + +atf_test_case kflag_no_end +kflag_no_end_head() +{ + atf_set "descr" "Tests the -k flag with a field without end" +} +kflag_no_end_body() +{ + cat >in <out <in1 <in2 <out <in <in <out <in <expout <in <expout <in <expout <in <expout <in <out <in1 <in2 <out <in <in <in <out <in <out <out <out <in <expout <in <expout <in <expout <in <expout <./+0 + + atf_check -o file:+0 sort -- +0 +} + +atf_test_case plus_nonmonotone +plus_nonmonotone_head() +{ + atf_set "descr" "Tests += addressing: apparently nonmonotone field" \ + "specs" +} +plus_nonmonotone_body() +{ + cat >in <./+0 + echo 'more contents' >in + cat ./+0 in >expout + + atf_check -o file:expout sort in +0 +} + +atf_test_case plus_bad_tempfile +plus_bad_tempfile_head() +{ + atf_set "descr" "Tests +- addressing: intermediate wrong behavior" \ + "that raised a '+0: No such file or directory' error" +} +plus_bad_tempfile_body() +{ + echo 'good contents' >in + atf_check -o file:in sort -T /tmp +0 in +} + +atf_test_case plus_rflag_invalid +plus_rflag_invalid_head() +{ + atf_set "descr" "Tests +- addressing: invalid record delimiter" +} +plus_rflag_invalid_body() +{ + ( + echo 'z b m f' + echo 'y c o e' + echo 'x a n h' + echo 'x a n g' + ) | tr '\n' '+' >in + + atf_check -o inline:'x a n g+x a n h+z b m f+y c o e+' \ + sort -R + -k2 in +} + +atf_test_case plus_tflag +plus_tflag_head() +{ + atf_set "descr" "Tests +- addressing: using -T caused a 'No such file" \ + "or directory' error" +} +plus_tflag_body() +{ + mkdir ./+ + yes | sed 200000q | sort -T + >/dev/null || atf_fail "program failed" +} + +atf_test_case plus_no_end +plus_no_end_head() +{ + atf_set "descr" "Tests +- addressing: field without end" +} +plus_no_end_body() +{ + cat >in <out < + +TESTSDIR= ${TESTSBASE}/usr.bin/tmux +TESTS_SH= t_tmux + +.include diff --git a/tests/usr.bin/tmux/t_tmux.sh b/tests/usr.bin/tmux/t_tmux.sh new file mode 100644 index 000000000..f1852e5bb --- /dev/null +++ b/tests/usr.bin/tmux/t_tmux.sh @@ -0,0 +1,49 @@ +# $NetBSD: t_tmux.sh,v 1.2 2012/05/19 07:30:37 jruoho Exp $ +# +# Copyright (c) 2012 The NetBSD Foundation, Inc. +# All rights reserved. +# +# This code is derived from software contributed to The NetBSD Foundation +# by Jukka Ruohonen. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +stdincrash() { + atf_check -s ignore -o ignore -e ignore -x \ + "\"tmux list-sessions 0<&-\" & sleep 2; kill $! >/dev/null 2>&1" +} + +atf_test_case stdin +stdin_head() { + atf_set "descr" "Test that tmux(1) does not crash the system " \ + "when stdin(4) is closed (PR kern/46463)" +} + +stdin_body() { + stdincrash +} + +atf_init_test_cases() +{ + atf_add_test_case stdin +} diff --git a/tests/usr.bin/unifdef/Makefile b/tests/usr.bin/unifdef/Makefile new file mode 100644 index 000000000..30363b9aa --- /dev/null +++ b/tests/usr.bin/unifdef/Makefile @@ -0,0 +1,13 @@ +# $NetBSD: Makefile,v 1.2 2011/05/03 14:11:51 jruoho Exp $ + +.include + +TESTSDIR= ${TESTSBASE}/usr.bin/unifdef + +TESTS_SH= t_basic + +FILESDIR= ${TESTSDIR} +FILES+= d_basic.in +FILES+= d_basic.out + +.include diff --git a/tests/usr.bin/unifdef/d_basic.in b/tests/usr.bin/unifdef/d_basic.in new file mode 100644 index 000000000..9de6a94a0 --- /dev/null +++ b/tests/usr.bin/unifdef/d_basic.in @@ -0,0 +1,25 @@ +#if defined(__FreeBSD__) +#include +#else +#include +#endif + +#if defined(__FreeBSD__) + #include + #include + #include + #include + #include + #include +#else +#include +#endif + +#if defined(__FreeBSD__) +#endif + +#ifdef __FreeBSD__ +#include +#else +#include +#endif diff --git a/tests/usr.bin/unifdef/d_basic.out b/tests/usr.bin/unifdef/d_basic.out new file mode 100644 index 000000000..2d52e9e7a --- /dev/null +++ b/tests/usr.bin/unifdef/d_basic.out @@ -0,0 +1,6 @@ +#include + +#include + + +#include diff --git a/tests/usr.bin/unifdef/t_basic.sh b/tests/usr.bin/unifdef/t_basic.sh new file mode 100644 index 000000000..43ca2808d --- /dev/null +++ b/tests/usr.bin/unifdef/t_basic.sh @@ -0,0 +1,62 @@ +# $NetBSD: t_basic.sh,v 1.6 2012/10/15 17:49:58 njoly Exp $ +# +# Copyright (c) 2011 The NetBSD Foundation, Inc. +# All rights reserved. +# +# This code is derived from software contributed to The NetBSD Foundation +# by Jukka Ruohonen. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +atf_test_case basic +basic_head() { + atf_set "descr" "A basic test of unifdef(1) (PR bin/42628)" + atf_set "require.progs" "unifdef" +} + +basic_body() { + + atf_check -s ignore -o file:$(atf_get_srcdir)/d_basic.out \ + -x "unifdef -U__FreeBSD__ $(atf_get_srcdir)/d_basic.in" +} + +atf_test_case lastline +lastline_head() { + atf_set "descr" "Checks with directive on last line (PR bin/47068)" +} + +lastline_body() { + + # With newline after cpp directive + printf '#ifdef foo\n#endif\n' >input + atf_check -o file:input unifdef -Ubar input + + # Without newline after cpp directive + printf '#ifdef foo\n#endif' >input + atf_check -o file:input unifdef -Ubar input +} + +atf_init_test_cases() { + atf_add_test_case basic + atf_add_test_case lastline +} diff --git a/tests/usr.bin/xlint/Makefile b/tests/usr.bin/xlint/Makefile new file mode 100644 index 000000000..3ab3f1abc --- /dev/null +++ b/tests/usr.bin/xlint/Makefile @@ -0,0 +1,9 @@ +# $NetBSD: Makefile,v 1.1 2012/03/17 16:33:15 jruoho Exp $ + +.include + +TESTSDIR= ${TESTSBASE}/usr.bin/xlint + +TESTS_SUBDIRS= lint1 + +.include diff --git a/tests/usr.bin/xlint/lint1/Makefile b/tests/usr.bin/xlint/lint1/Makefile new file mode 100644 index 000000000..87b2f50a1 --- /dev/null +++ b/tests/usr.bin/xlint/lint1/Makefile @@ -0,0 +1,51 @@ +# $NetBSD: Makefile,v 1.1 2012/03/17 16:33:15 jruoho Exp $ + +NOMAN= # defined + +.include + +TESTSDIR= ${TESTSBASE}/usr.bin/xlint/lint1 + +TESTS_SH= t_integration + +FILESDIR= ${TESTSDIR} +FILES+= d_alignof.c +FILES+= d_c99_complex_num.c +FILES+= d_c99_decls_after_stmt.c +FILES+= d_c99_decls_after_stmt2.c +FILES+= d_c99_for_loops.c +FILES+= d_c99_func.c +FILES+= d_c99_recursive_init.c +FILES+= d_c99_struct_init.c +FILES+= d_c99_union_init1.c +FILES+= d_c99_union_init2.c +FILES+= d_c99_union_init3.c +FILES+= d_c9x_array_init.c +FILES+= d_c9x_recursive_init.c +FILES+= d_cast_init.c +FILES+= d_cast_init2.c +FILES+= d_cast_lhs.c +FILES+= d_compound_literals1.c +FILES+= d_compound_literals2.c +FILES+= d_constant_conv1.c +FILES+= d_constant_conv2.c +FILES+= d_cvt_in_ternary.c +FILES+= d_ellipsis_in_switch.c +FILES+= d_gcc_compound_statements1.c +FILES+= d_gcc_compound_statements2.c +FILES+= d_gcc_compound_statements3.c +FILES+= d_gcc_func.c +FILES+= d_gcc_variable_array_init.c +FILES+= d_incorrect_array_size.c +FILES+= d_long_double_int.c +FILES+= d_nested_structs.c +FILES+= d_nolimit_init.c +FILES+= d_packed_structs.c +FILES+= d_shift_to_narrower_type.c +FILES+= d_type_conv1.c +FILES+= d_type_conv2.c +FILES+= d_type_conv3.c +FILES+= d_typename_as_var.c +FILES+= d_zero_sized_arrays.c + +.include diff --git a/tests/usr.bin/xlint/lint1/d_alignof.c b/tests/usr.bin/xlint/lint1/d_alignof.c new file mode 100644 index 000000000..4a6613463 --- /dev/null +++ b/tests/usr.bin/xlint/lint1/d_alignof.c @@ -0,0 +1,6 @@ +/* __alignof__ */ +int +main(void) +{ + return __alignof__(short); +} diff --git a/tests/usr.bin/xlint/lint1/d_c99_complex_num.c b/tests/usr.bin/xlint/lint1/d_c99_complex_num.c new file mode 100644 index 000000000..c3c952e7b --- /dev/null +++ b/tests/usr.bin/xlint/lint1/d_c99_complex_num.c @@ -0,0 +1,7 @@ +double cabs(double _Complex); + +double cabs(double _Complex foo) +{ + double d = __real__ foo; + return d + 0.1fi; +} diff --git a/tests/usr.bin/xlint/lint1/d_c99_decls_after_stmt.c b/tests/usr.bin/xlint/lint1/d_c99_decls_after_stmt.c new file mode 100644 index 000000000..f32a963c7 --- /dev/null +++ b/tests/usr.bin/xlint/lint1/d_c99_decls_after_stmt.c @@ -0,0 +1,5 @@ +void sample(void) +{ + int i = 0; i += 1; + int j = 0; j += 1; +} diff --git a/tests/usr.bin/xlint/lint1/d_c99_decls_after_stmt2.c b/tests/usr.bin/xlint/lint1/d_c99_decls_after_stmt2.c new file mode 100644 index 000000000..960d39235 --- /dev/null +++ b/tests/usr.bin/xlint/lint1/d_c99_decls_after_stmt2.c @@ -0,0 +1,6 @@ +typedef int int_t; +int main(void) { +int i = 0; i += 1; +int_t j = 0; j += 1; +return 0; +} diff --git a/tests/usr.bin/xlint/lint1/d_c99_for_loops.c b/tests/usr.bin/xlint/lint1/d_c99_for_loops.c new file mode 100644 index 000000000..188921d52 --- /dev/null +++ b/tests/usr.bin/xlint/lint1/d_c99_for_loops.c @@ -0,0 +1,10 @@ +/* c99 for loops */ +extern void foo(int); + +int +main(void) +{ + for (int i = 0; i < 10; i++) + foo(i); + return 0; +} diff --git a/tests/usr.bin/xlint/lint1/d_c99_func.c b/tests/usr.bin/xlint/lint1/d_c99_func.c new file mode 100644 index 000000000..b827bfa9f --- /dev/null +++ b/tests/usr.bin/xlint/lint1/d_c99_func.c @@ -0,0 +1,7 @@ +/* C99 __func__ */ + +void +foo(const char *p) { + p = __func__; + foo(p); +} diff --git a/tests/usr.bin/xlint/lint1/d_c99_recursive_init.c b/tests/usr.bin/xlint/lint1/d_c99_recursive_init.c new file mode 100644 index 000000000..347644ffe --- /dev/null +++ b/tests/usr.bin/xlint/lint1/d_c99_recursive_init.c @@ -0,0 +1,13 @@ +/* C99 recursive struct/union initialization */ +struct top { + int i; + char c; + union onion { + short us; + char uc; + } u; + char *s; +} c[] = { + { .s = "foo", .c = 'b', .u = { .uc = 'c' } }, + { .i = 1, .c = 'a', .u = { .us = 2 } }, +}; diff --git a/tests/usr.bin/xlint/lint1/d_c99_struct_init.c b/tests/usr.bin/xlint/lint1/d_c99_struct_init.c new file mode 100644 index 000000000..a94cbd163 --- /dev/null +++ b/tests/usr.bin/xlint/lint1/d_c99_struct_init.c @@ -0,0 +1,10 @@ +/* C99 struct initialization */ +struct { + int i; + char *s; +} c[] = { + { .i = 2, }, + { .s = "foo" }, + { .i = 1, .s = "bar" }, + { .s = "foo", .i = -1 }, +}; diff --git a/tests/usr.bin/xlint/lint1/d_c99_union_init1.c b/tests/usr.bin/xlint/lint1/d_c99_union_init1.c new file mode 100644 index 000000000..0e1a1a832 --- /dev/null +++ b/tests/usr.bin/xlint/lint1/d_c99_union_init1.c @@ -0,0 +1,8 @@ +/* C99 union initialization */ +union { + int i; + char *s; +} c[] = { + { i: 1 }, + { s: "foo" } +}; diff --git a/tests/usr.bin/xlint/lint1/d_c99_union_init2.c b/tests/usr.bin/xlint/lint1/d_c99_union_init2.c new file mode 100644 index 000000000..51d34d450 --- /dev/null +++ b/tests/usr.bin/xlint/lint1/d_c99_union_init2.c @@ -0,0 +1,8 @@ +/* C99 union initialization */ +union { + int i[10]; + short s; +} c[] = { + { s: 2 }, + { i: { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 } }, +}; diff --git a/tests/usr.bin/xlint/lint1/d_c99_union_init3.c b/tests/usr.bin/xlint/lint1/d_c99_union_init3.c new file mode 100644 index 000000000..f5e8b59f4 --- /dev/null +++ b/tests/usr.bin/xlint/lint1/d_c99_union_init3.c @@ -0,0 +1,8 @@ +/* C99 union initialization */ +struct { + int i[10]; + char *s; +} c[] = { + { { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, + "foo" }, +}; diff --git a/tests/usr.bin/xlint/lint1/d_c9x_array_init.c b/tests/usr.bin/xlint/lint1/d_c9x_array_init.c new file mode 100644 index 000000000..66f0e9ec1 --- /dev/null +++ b/tests/usr.bin/xlint/lint1/d_c9x_array_init.c @@ -0,0 +1,6 @@ +/* C9X array initializers */ +int foo[256] = { + [2] = 1, + [3] = 2, + [4 ... 5] = 3 +}; diff --git a/tests/usr.bin/xlint/lint1/d_c9x_recursive_init.c b/tests/usr.bin/xlint/lint1/d_c9x_recursive_init.c new file mode 100644 index 000000000..df907cd7a --- /dev/null +++ b/tests/usr.bin/xlint/lint1/d_c9x_recursive_init.c @@ -0,0 +1,16 @@ +/* C9X struct/union member init, with nested union and trailing member */ +union node { + void *next; + char *data; +}; +struct foo { + int b; + union node n; + int c; +}; + +struct foo f = { + .b = 1, + .n = { .next = 0, }, + .c = 1 +}; diff --git a/tests/usr.bin/xlint/lint1/d_cast_init.c b/tests/usr.bin/xlint/lint1/d_cast_init.c new file mode 100644 index 000000000..36986e800 --- /dev/null +++ b/tests/usr.bin/xlint/lint1/d_cast_init.c @@ -0,0 +1,27 @@ +/* cast initialization */ +typedef unsigned char u_char; +typedef unsigned int size_t; +struct sockaddr_x25 { + u_char x25_len; + u_char x25_family; + short x25_net; + char x25_addr[16]; + struct x25opts { + char op_flags; + char op_psize; + char op_wsize; + char op_speed; + } x25_opts; + short x25_udlen; + char x25_udata[16]; +}; + +struct sockaddr_x25 x25_dgmask = { + (unsigned char)(unsigned char)(unsigned int)(unsigned long)(&((( struct sockaddr_x25 *)0)->x25_udata[1])) , + 0, + 0, + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {0, 0, 0, 0}, + -1, + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, +}; diff --git a/tests/usr.bin/xlint/lint1/d_cast_init2.c b/tests/usr.bin/xlint/lint1/d_cast_init2.c new file mode 100644 index 000000000..9597d3580 --- /dev/null +++ b/tests/usr.bin/xlint/lint1/d_cast_init2.c @@ -0,0 +1,7 @@ +/* cast initialization as the rhs of a - operand */ +struct sockaddr_dl { + char sdl_data[2]; +}; + +int npdl_datasize = sizeof(struct sockaddr_dl) - +((int) ((unsigned long)&((struct sockaddr_dl *) 0)->sdl_data[0])); diff --git a/tests/usr.bin/xlint/lint1/d_cast_lhs.c b/tests/usr.bin/xlint/lint1/d_cast_lhs.c new file mode 100644 index 000000000..eb8656955 --- /dev/null +++ b/tests/usr.bin/xlint/lint1/d_cast_lhs.c @@ -0,0 +1,7 @@ +/* pointer casts are valid lhs lvalues */ +struct sockaddr { }; +void +foo() { + unsigned long p = 6; + ((struct sockaddr *)p) = 0; +} diff --git a/tests/usr.bin/xlint/lint1/d_compound_literals1.c b/tests/usr.bin/xlint/lint1/d_compound_literals1.c new file mode 100644 index 000000000..cd1987ae1 --- /dev/null +++ b/tests/usr.bin/xlint/lint1/d_compound_literals1.c @@ -0,0 +1,11 @@ +/* compound literals */ + +struct p { + short a, b, c, d; +}; + +foo() +{ + struct p me = (struct p) {1, 2, 3, 4}; + me.a = me.b; +} diff --git a/tests/usr.bin/xlint/lint1/d_compound_literals2.c b/tests/usr.bin/xlint/lint1/d_compound_literals2.c new file mode 100644 index 000000000..e4ffb9298 --- /dev/null +++ b/tests/usr.bin/xlint/lint1/d_compound_literals2.c @@ -0,0 +1,18 @@ +/* compound literals */ + +struct p { + short a, b, c, d; +} zz = { + 1, 2, 3, 4 +}; + +struct p *bar(int i) +{ + static struct p q[10]; + return &q[i]; +} + +foo() +{ + *bar(1) = (struct p) { 1, 2, 3, 4 }; +} diff --git a/tests/usr.bin/xlint/lint1/d_constant_conv1.c b/tests/usr.bin/xlint/lint1/d_constant_conv1.c new file mode 100644 index 000000000..53795c5fe --- /dev/null +++ b/tests/usr.bin/xlint/lint1/d_constant_conv1.c @@ -0,0 +1,9 @@ +/* Flag information-losing constant conversion in argument lists */ + +int f(unsigned int); + +void +should_fail() +{ + f(-1); +} diff --git a/tests/usr.bin/xlint/lint1/d_constant_conv2.c b/tests/usr.bin/xlint/lint1/d_constant_conv2.c new file mode 100644 index 000000000..87066c96b --- /dev/null +++ b/tests/usr.bin/xlint/lint1/d_constant_conv2.c @@ -0,0 +1,9 @@ +/* Flag information-losing constant conversion in argument lists */ + +int f(unsigned int); + +void +should_fail() +{ + f(2.1); +} diff --git a/tests/usr.bin/xlint/lint1/d_cvt_in_ternary.c b/tests/usr.bin/xlint/lint1/d_cvt_in_ternary.c new file mode 100644 index 000000000..4a6149c67 --- /dev/null +++ b/tests/usr.bin/xlint/lint1/d_cvt_in_ternary.c @@ -0,0 +1,13 @@ +/* CVT node handling in ?: operator */ +typedef unsigned long int size_t; +struct filecore_direntry { + unsigned len:32; +}; +int +main(void) +{ + struct filecore_direntry dirent = { 0 }; + size_t uio_resid = 0; + size_t bytelen = (((dirent.len)<(uio_resid))?(dirent.len):(uio_resid)); + return bytelen; +} diff --git a/tests/usr.bin/xlint/lint1/d_ellipsis_in_switch.c b/tests/usr.bin/xlint/lint1/d_ellipsis_in_switch.c new file mode 100644 index 000000000..ba4a338d2 --- /dev/null +++ b/tests/usr.bin/xlint/lint1/d_ellipsis_in_switch.c @@ -0,0 +1,11 @@ +int x(void) +{ + int i = 33; + switch (i) { + case 1 ... 40: + break; + default: + break; + } + return 0; +} diff --git a/tests/usr.bin/xlint/lint1/d_gcc_compound_statements1.c b/tests/usr.bin/xlint/lint1/d_gcc_compound_statements1.c new file mode 100644 index 000000000..d970be182 --- /dev/null +++ b/tests/usr.bin/xlint/lint1/d_gcc_compound_statements1.c @@ -0,0 +1,7 @@ +/* GCC compound statements */ + +foo(unsigned long z) +{ + z = ({ unsigned long tmp; tmp = 1; tmp; }); + foo(z); +} diff --git a/tests/usr.bin/xlint/lint1/d_gcc_compound_statements2.c b/tests/usr.bin/xlint/lint1/d_gcc_compound_statements2.c new file mode 100644 index 000000000..fa1ee6730 --- /dev/null +++ b/tests/usr.bin/xlint/lint1/d_gcc_compound_statements2.c @@ -0,0 +1,14 @@ +/* GCC compound statements with non-expressions */ +struct cpu_info { + int bar; +}; + +int +main(void) +{ + return ({ + struct cpu_info *__ci; + __asm__ volatile("movl %%fs:4,%0":"=r" (__ci)); + __ci; + })->bar; +} diff --git a/tests/usr.bin/xlint/lint1/d_gcc_compound_statements3.c b/tests/usr.bin/xlint/lint1/d_gcc_compound_statements3.c new file mode 100644 index 000000000..29e9063dc --- /dev/null +++ b/tests/usr.bin/xlint/lint1/d_gcc_compound_statements3.c @@ -0,0 +1,10 @@ +/* GCC compound statements with void type */ + +void +main(void) +{ + ({ + void *v; + __asm__ volatile("noop"); + }); +} diff --git a/tests/usr.bin/xlint/lint1/d_gcc_func.c b/tests/usr.bin/xlint/lint1/d_gcc_func.c new file mode 100644 index 000000000..459919de2 --- /dev/null +++ b/tests/usr.bin/xlint/lint1/d_gcc_func.c @@ -0,0 +1,7 @@ +/* gcc __FUNCTION__ */ + +void +foo(const char *p) { + p = __FUNCTION__; + foo(p); +} diff --git a/tests/usr.bin/xlint/lint1/d_gcc_variable_array_init.c b/tests/usr.bin/xlint/lint1/d_gcc_variable_array_init.c new file mode 100644 index 000000000..d5b01ad0c --- /dev/null +++ b/tests/usr.bin/xlint/lint1/d_gcc_variable_array_init.c @@ -0,0 +1,7 @@ +/* gcc: variable array initializer */ +void foo(int i) +{ + int array[i]; + while (i--) + foo(array[i] = 0); +} diff --git a/tests/usr.bin/xlint/lint1/d_incorrect_array_size.c b/tests/usr.bin/xlint/lint1/d_incorrect_array_size.c new file mode 100644 index 000000000..c86c0d6b3 --- /dev/null +++ b/tests/usr.bin/xlint/lint1/d_incorrect_array_size.c @@ -0,0 +1,3 @@ +struct foo { + int a[-1]; +}; diff --git a/tests/usr.bin/xlint/lint1/d_long_double_int.c b/tests/usr.bin/xlint/lint1/d_long_double_int.c new file mode 100644 index 000000000..a5a644e3e --- /dev/null +++ b/tests/usr.bin/xlint/lint1/d_long_double_int.c @@ -0,0 +1,7 @@ +/* PR 39639: writing "long double" gave "long int" */ + +int +fail(long double *a, long int *b) +{ + return a == b; +} diff --git a/tests/usr.bin/xlint/lint1/d_nested_structs.c b/tests/usr.bin/xlint/lint1/d_nested_structs.c new file mode 100644 index 000000000..edd3396bd --- /dev/null +++ b/tests/usr.bin/xlint/lint1/d_nested_structs.c @@ -0,0 +1,21 @@ +/* Nested struct */ +typedef void *EditLine; +typedef void *History; + +typedef struct { + EditLine *el; + History *hist; +} el_mode_t; + +struct el_modes_s { + el_mode_t command; + el_mode_t string; + el_mode_t filec; + el_mode_t mime_enc; +}; + +struct el_modes_s elm = { + .command = { .el = 0, .hist = 0, }, + .string = { .el = 0, .hist = 0, }, + .filec = { .el = 0, .hist = 0, }, +}; diff --git a/tests/usr.bin/xlint/lint1/d_nolimit_init.c b/tests/usr.bin/xlint/lint1/d_nolimit_init.c new file mode 100644 index 000000000..68e71b4df --- /dev/null +++ b/tests/usr.bin/xlint/lint1/d_nolimit_init.c @@ -0,0 +1,4 @@ +/* no limit initializers */ +char foo[][4] = { + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" +}; diff --git a/tests/usr.bin/xlint/lint1/d_packed_structs.c b/tests/usr.bin/xlint/lint1/d_packed_structs.c new file mode 100644 index 000000000..71b438496 --- /dev/null +++ b/tests/usr.bin/xlint/lint1/d_packed_structs.c @@ -0,0 +1,35 @@ +/* packed tests */ + +struct in_addr { + int x; +}; +struct ip_timestamp { + char ipt_code; + char ipt_len; + char ipt_ptr; + unsigned int ipt_flg:4, + ipt_oflw:4; + union ipt_timestamp { + int ipt_time[1]; + struct ipt_ta { + struct in_addr ipt_addr; + int ipt_time; + } ipt_ta[1] __packed; + } ipt_timestamp __packed; +} __packed; + +typedef struct __packed { + int x; +} t; + +struct x { + char c; + long l; +} __packed; + +struct y { + char c; + long l; +}; + +int a[sizeof(struct y) - sizeof(struct x) - 1]; diff --git a/tests/usr.bin/xlint/lint1/d_shift_to_narrower_type.c b/tests/usr.bin/xlint/lint1/d_shift_to_narrower_type.c new file mode 100644 index 000000000..0208944a2 --- /dev/null +++ b/tests/usr.bin/xlint/lint1/d_shift_to_narrower_type.c @@ -0,0 +1,24 @@ +// Test that type shifts that result to narrower types don't produce warnings. + +void +foo(void) { + unsigned long l = 100; + unsigned long long ll = 100; + unsigned int i = 100; + unsigned short s = 100; + unsigned char c = 1; + + l = ll >> 32; +// i = ll >> 31; + i = ll >> 32; + s = ll >> 48; + c = ll >> 56; + s = i >> 16; + c = i >> 24; + c = s >> 8; + (void)≪ + (void)&l; + (void)&i; + (void)&s; + (void)&c; +} diff --git a/tests/usr.bin/xlint/lint1/d_type_conv1.c b/tests/usr.bin/xlint/lint1/d_type_conv1.c new file mode 100644 index 000000000..d9e470e94 --- /dev/null +++ b/tests/usr.bin/xlint/lint1/d_type_conv1.c @@ -0,0 +1,11 @@ +/* Flag information-losing type conversion in argument lists */ + +int f(unsigned int); + +void +should_fail() +{ + long long x = 20; + + f(x); +} diff --git a/tests/usr.bin/xlint/lint1/d_type_conv2.c b/tests/usr.bin/xlint/lint1/d_type_conv2.c new file mode 100644 index 000000000..7c2e1f478 --- /dev/null +++ b/tests/usr.bin/xlint/lint1/d_type_conv2.c @@ -0,0 +1,11 @@ +/* Flag information-losing type conversion in argument lists */ + +int f(float); + +void +should_fail() +{ + double x = 2.0; + + f(x); +} diff --git a/tests/usr.bin/xlint/lint1/d_type_conv3.c b/tests/usr.bin/xlint/lint1/d_type_conv3.c new file mode 100644 index 000000000..bc6a8e695 --- /dev/null +++ b/tests/usr.bin/xlint/lint1/d_type_conv3.c @@ -0,0 +1,10 @@ +/* Flag information-losing type conversion in argument lists */ + +int f(unsigned int); + +void +should_fail() +{ + + f(0x7fffffffffffffffLL); +} diff --git a/tests/usr.bin/xlint/lint1/d_typename_as_var.c b/tests/usr.bin/xlint/lint1/d_typename_as_var.c new file mode 100644 index 000000000..248dc7558 --- /dev/null +++ b/tests/usr.bin/xlint/lint1/d_typename_as_var.c @@ -0,0 +1,14 @@ +typedef char h[10]; + +typedef struct { + int i; + char *c; +} fh; + +struct foo { + fh h; + struct { + int x; + int y; + } fl; +}; diff --git a/tests/usr.bin/xlint/lint1/d_zero_sized_arrays.c b/tests/usr.bin/xlint/lint1/d_zero_sized_arrays.c new file mode 100644 index 000000000..9c06c6b5e --- /dev/null +++ b/tests/usr.bin/xlint/lint1/d_zero_sized_arrays.c @@ -0,0 +1,3 @@ +struct foo { +int a[0]; +}; diff --git a/tests/usr.bin/xlint/lint1/t_integration.sh b/tests/usr.bin/xlint/lint1/t_integration.sh new file mode 100644 index 000000000..94d6566ec --- /dev/null +++ b/tests/usr.bin/xlint/lint1/t_integration.sh @@ -0,0 +1,128 @@ +# $NetBSD: t_integration.sh,v 1.1 2012/03/17 16:33:16 jruoho Exp $ +# +# Copyright (c) 2008, 2010 The NetBSD Foundation, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +LINT1=/usr/libexec/lint1 + +Names= + +check_valid() +{ + atf_check -s exit:0 ${LINT1} -g -S "$(atf_get_srcdir)/$1" /dev/null +} + +check_invalid() +{ + atf_check -s not-exit:0 -o ignore -e ignore ${LINT1} -g -S -w \ + "$(atf_get_srcdir)/$1" /dev/null +} + +test_case() +{ + local result="${1}"; shift + local name="${1}"; shift + local descr="${*}" + + atf_test_case ${name} + eval "${name}_head() { + atf_set \"descr\" \"${descr}\"; + atf_set \"require.progs\" \"${LINT1}\"; + }" + eval "${name}_body() { + ${result} d_${name}.c; + }" + + Names="${Names} ${name}" +} + +test_case check_valid c99_struct_init "Checks C99 struct initialization" +test_case check_valid c99_union_init1 "Checks C99 union initialization" +test_case check_valid c99_union_init2 "Checks C99 union initialization" +test_case check_valid c99_union_init3 "Checks C99 union initialization" +test_case check_valid c99_recursive_init "Checks C99 recursive struct/union" \ + "initialization" +test_case check_valid c9x_recursive_init "Checks C9X struct/union member" \ + "init, with nested union and trailing member" +test_case check_valid nested_structs "Checks nested structs" +test_case check_valid packed_structs "Checks packed structs" + +test_case check_valid cast_init "Checks cast initialization" +test_case check_valid cast_init2 "Checks cast initialization as the rhs of a" \ + "- operand" +test_case check_valid cast_lhs "Checks whether pointer casts are valid lhs" \ + "lvalues" + +test_case check_valid gcc_func "Checks GCC __FUNCTION__" +test_case check_valid c99_func "Checks C99 __func__" + +test_case check_valid gcc_variable_array_init "Checks GCC variable array" \ + "initializers" +test_case check_valid c9x_array_init "Checks C9X array initializers" +test_case check_valid c99_decls_after_stmt "Checks C99 decls after statements" +test_case check_valid nolimit_init "Checks no limit initializers" +test_case check_valid zero_sized_arrays "Checks zero sized arrays" + +test_case check_valid compound_literals1 "Checks compound literals" +test_case check_valid compound_literals2 "Checks compound literals" +test_case check_valid gcc_compound_statements1 "Checks GCC compound statements" +test_case check_valid gcc_compound_statements2 "Checks GCC compound" \ + "statements with non-expressions" +test_case check_valid gcc_compound_statements3 "Checks GCC compound" \ + "statements with void type" + +test_case check_valid cvt_in_ternary "Checks CVT nodes handling in ?" \ + "operator" +test_case check_valid ellipsis_in_switch "Checks ellipsis in switch()" +test_case check_valid c99_complex_num "Checks C99 complex numbers" +test_case check_valid c99_for_loops "Checks C99 for loops" +test_case check_valid alignof "Checks __alignof__" +test_case check_valid shift_to_narrower_type "Checks that type shifts that" \ + "result in narrower types do not produce warnings" + +test_case check_invalid constant_conv1 "Checks failing on information-losing" \ + "constant conversion in argument lists" +test_case check_invalid constant_conv2 "Checks failing on information-losing" \ + "constant conversion in argument lists" + +test_case check_invalid type_conv1 "Checks failing on information-losing" \ + "type conversion in argument lists" +test_case check_invalid type_conv2 "Checks failing on information-losing" \ + "type conversion in argument lists" +test_case check_invalid type_conv3 "Checks failing on information-losing" \ + "type conversion in argument lists" + +test_case check_invalid incorrect_array_size "Checks failing on incorrect" \ + "array sizes" + +test_case check_invalid long_double_int "Checks for confusion of 'long" \ + "double' with 'long int'; PR 39639" + +atf_init_test_cases() +{ + for name in ${Names}; do + atf_add_test_case ${name} + done +} diff --git a/tests/usr.sbin/Makefile b/tests/usr.sbin/Makefile new file mode 100644 index 000000000..1a4d1e090 --- /dev/null +++ b/tests/usr.sbin/Makefile @@ -0,0 +1,8 @@ +# $NetBSD: Makefile,v 1.4 2012/04/19 18:51:35 jruoho Exp $ +.include + +TESTSDIR= ${TESTSBASE}/usr.sbin + +TESTS_SUBDIRS+= mtree tcpdump traceroute useradd + +.include diff --git a/tests/usr.sbin/mtree/Makefile b/tests/usr.sbin/mtree/Makefile new file mode 100644 index 000000000..51fef9bd3 --- /dev/null +++ b/tests/usr.sbin/mtree/Makefile @@ -0,0 +1,24 @@ +# $NetBSD: Makefile,v 1.2 2013/01/02 18:11:44 christos Exp $ + +NOMAN= # defined + +.include + +TESTSDIR= ${TESTSBASE}/usr.sbin/mtree + +TESTS_SH= t_mtree + +FILESDIR= ${TESTSDIR} + +FILES+= d_convert.in +FILES+= d_convert_C.out +FILES+= d_convert_C_S.out +FILES+= d_convert_D.out +FILES+= d_convert_D_S.out +FILES+= netbsd6_d_create.out +FILES+= mtree_d_create.out +FILES+= d_merge.in +FILES+= d_merge_C_M.out +FILES+= d_merge_C_M_S.out + +.include diff --git a/tests/usr.sbin/mtree/d_convert.in b/tests/usr.sbin/mtree/d_convert.in new file mode 100644 index 000000000..6a1abb07e --- /dev/null +++ b/tests/usr.sbin/mtree/d_convert.in @@ -0,0 +1,40 @@ +# Similar to d_create.out, but a few entries have been deleted; nlink, +# size and sha256 attributes have been removed; and the order has been +# changed to test sorting. + +# . +. type=dir + a.symlink.1 type=link link=a.file.1 + top.dangling type=link link=nonexistent + top.symlink.b \ + type=link link=b + +# ./b +b type=dir + b.file.2 type=file + b.file.1 type=file +# end ./b, up to "." +.. + + top.file.1 type=file + +# ./a +a type=dir + a.file.2 type=file + +# ./a/1 +1 type=dir + a1.file.1 type=file +# end ./a/1, up to "./a" +.. + + a.file.1 type=file + +# ./a/2 +2 type=dir +# end ./a/2, up to "./a" +.. + +# end ./a, up to "." +.. + diff --git a/tests/usr.sbin/mtree/d_convert_C.out b/tests/usr.sbin/mtree/d_convert_C.out new file mode 100644 index 000000000..de4d9f6e5 --- /dev/null +++ b/tests/usr.sbin/mtree/d_convert_C.out @@ -0,0 +1,14 @@ +. type=dir +./a.symlink.1 type=link link=a.file.1 +./top.dangling type=link link=nonexistent +./top.symlink.b type=link link=b +./b type=dir +./b/b.file.2 type=file +./b/b.file.1 type=file +./top.file.1 type=file +./a type=dir +./a/a.file.2 type=file +./a/1 type=dir +./a/1/a1.file.1 type=file +./a/a.file.1 type=file +./a/2 type=dir diff --git a/tests/usr.sbin/mtree/d_convert_C_S.out b/tests/usr.sbin/mtree/d_convert_C_S.out new file mode 100644 index 000000000..bd03cc458 --- /dev/null +++ b/tests/usr.sbin/mtree/d_convert_C_S.out @@ -0,0 +1,14 @@ +. type=dir +./a.symlink.1 type=link link=a.file.1 +./top.dangling type=link link=nonexistent +./top.file.1 type=file +./top.symlink.b type=link link=b +./a type=dir +./a/a.file.1 type=file +./a/a.file.2 type=file +./a/1 type=dir +./a/1/a1.file.1 type=file +./a/2 type=dir +./b type=dir +./b/b.file.1 type=file +./b/b.file.2 type=file diff --git a/tests/usr.sbin/mtree/d_convert_D.out b/tests/usr.sbin/mtree/d_convert_D.out new file mode 100644 index 000000000..c05947813 --- /dev/null +++ b/tests/usr.sbin/mtree/d_convert_D.out @@ -0,0 +1,14 @@ +type=dir . +type=link link=a.file.1 ./a.symlink.1 +type=link link=nonexistent ./top.dangling +type=link link=b ./top.symlink.b +type=dir ./b +type=file ./b/b.file.2 +type=file ./b/b.file.1 +type=file ./top.file.1 +type=dir ./a +type=file ./a/a.file.2 +type=dir ./a/1 +type=file ./a/1/a1.file.1 +type=file ./a/a.file.1 +type=dir ./a/2 diff --git a/tests/usr.sbin/mtree/d_convert_D_S.out b/tests/usr.sbin/mtree/d_convert_D_S.out new file mode 100644 index 000000000..a777a0b01 --- /dev/null +++ b/tests/usr.sbin/mtree/d_convert_D_S.out @@ -0,0 +1,14 @@ +type=dir . +type=link link=a.file.1 ./a.symlink.1 +type=link link=nonexistent ./top.dangling +type=file ./top.file.1 +type=link link=b ./top.symlink.b +type=dir ./a +type=file ./a/a.file.1 +type=file ./a/a.file.2 +type=dir ./a/1 +type=file ./a/1/a1.file.1 +type=dir ./a/2 +type=dir ./b +type=file ./b/b.file.1 +type=file ./b/b.file.2 diff --git a/tests/usr.sbin/mtree/d_merge.in b/tests/usr.sbin/mtree/d_merge.in new file mode 100644 index 000000000..9efd04b01 --- /dev/null +++ b/tests/usr.sbin/mtree/d_merge.in @@ -0,0 +1,27 @@ +# The last entry for any duplicate node should take precedence. + +. type=dir + +# directory "a" with only one entry, changing from dir to link +./a type=dir +./a/change-dir-to-link type=dir mode=0755 +./a/change-dir-to-link type=link mode=0755 + +# directory "b" with only one entry, changing from link to dir +./b type=dir +./b/change-link-to-dir type=link mode=0755 +./b/change-link-to-dir type=dir mode=0755 + +# directory "c" with multiple entries, one changing from dir to link +./c type=dir +./c/aaa type=file +./c/zzz type=file +./c/change-dir-to-link type=dir mode=0755 +./c/change-dir-to-link type=link mode=0755 + +# directory "d" with multiple entries, one changing from link to dir +./d type=dir +./d/aaa type=file +./d/zzz type=file +./d/change-link-to-dir type=link mode=0755 +./d/change-link-to-dir type=dir mode=0755 diff --git a/tests/usr.sbin/mtree/d_merge_C_M.out b/tests/usr.sbin/mtree/d_merge_C_M.out new file mode 100644 index 000000000..dea996699 --- /dev/null +++ b/tests/usr.sbin/mtree/d_merge_C_M.out @@ -0,0 +1,13 @@ +. type=dir +./a type=dir +./a/change-dir-to-link type=link mode=0755 +./b type=dir +./b/change-link-to-dir type=dir mode=0755 +./c type=dir +./c/aaa type=file +./c/zzz type=file +./c/change-dir-to-link type=link mode=0755 +./d type=dir +./d/aaa type=file +./d/zzz type=file +./d/change-link-to-dir type=dir mode=0755 diff --git a/tests/usr.sbin/mtree/d_merge_C_M_S.out b/tests/usr.sbin/mtree/d_merge_C_M_S.out new file mode 100644 index 000000000..9f02beae7 --- /dev/null +++ b/tests/usr.sbin/mtree/d_merge_C_M_S.out @@ -0,0 +1,13 @@ +. type=dir +./a type=dir +./a/change-dir-to-link type=link mode=0755 +./b type=dir +./b/change-link-to-dir type=dir mode=0755 +./c type=dir +./c/aaa type=file +./c/change-dir-to-link type=link mode=0755 +./c/zzz type=file +./d type=dir +./d/aaa type=file +./d/zzz type=file +./d/change-link-to-dir type=dir mode=0755 diff --git a/tests/usr.sbin/mtree/mtree_d_create.out b/tests/usr.sbin/mtree/mtree_d_create.out new file mode 100644 index 000000000..d27e8988e --- /dev/null +++ b/tests/usr.sbin/mtree/mtree_d_create.out @@ -0,0 +1,55 @@ +# user: x +# machine: x +# tree: x +# date: x + +# . +/set type=file nlink=1 +. type=dir nlink=4 + a.symlink.1 type=link size=8 link=a.file.1 + top.dangling \ + type=link size=11 link=nonexistent + top.file.1 size=18 \ + sha256=74c53aaf0cd9543b7efad969de1058ee38859134ba467500b849811fc3513195 + top.symlink.b \ + type=link size=1 link=b + +# ./a +a type=dir nlink=4 + a.file.1 size=18 \ + sha256=bdbea62f7ccdf862f22254ea871d523845250010d5f233896e800142a859eef2 + a.file.2 size=18 \ + sha256=77876d113fe1b45a41f8d1d3e178aaad7f91fcd93d3df782690625b74ad90fe6 + a.hardlink.b2 \ + nlink=2 size=18 \ + sha256=784fd6b95fe5054d87bf268de51dea043031c5e985f668d4f51e1c759b0f9333 + +# ./a/1 +1 type=dir nlink=2 + a1.file.1 size=21 \ + sha256=a062cd272facdd38c4fdeff2a18947b28c99a28a8fe51f88468978740382e592 +# ./a/1 +.. + + +# ./a/2 +2 type=dir nlink=2 +# ./a/2 +.. + +# ./a +.. + + +# ./b +b type=dir nlink=2 + b.file.1 nlink=2 size=18 \ + sha256=5754b0d97a8238ea0e495ab871667dcab8f1d684e323290ae76f70c47de18998 + b.file.2 nlink=2 size=18 \ + sha256=784fd6b95fe5054d87bf268de51dea043031c5e985f668d4f51e1c759b0f9333 + b.hardlink.1 \ + nlink=2 size=18 \ + sha256=5754b0d97a8238ea0e495ab871667dcab8f1d684e323290ae76f70c47de18998 +# ./b +.. + diff --git a/tests/usr.sbin/mtree/netbsd6_d_create.out b/tests/usr.sbin/mtree/netbsd6_d_create.out new file mode 100644 index 000000000..389ec653e --- /dev/null +++ b/tests/usr.sbin/mtree/netbsd6_d_create.out @@ -0,0 +1,55 @@ +# user: x +# machine: x +# tree: x +# date: x + +# . +/set type=file nlink=1 +. type=dir nlink=4 + a.symlink.1 type=link link=a.file.1 + top.dangling \ + type=link link=nonexistent + top.file.1 size=18 \ + sha256=74c53aaf0cd9543b7efad969de1058ee38859134ba467500b849811fc3513195 + top.symlink.b \ + type=link link=b + +# ./a +a type=dir nlink=4 + a.file.1 size=18 \ + sha256=bdbea62f7ccdf862f22254ea871d523845250010d5f233896e800142a859eef2 + a.file.2 size=18 \ + sha256=77876d113fe1b45a41f8d1d3e178aaad7f91fcd93d3df782690625b74ad90fe6 + a.hardlink.b2 \ + nlink=2 size=18 \ + sha256=784fd6b95fe5054d87bf268de51dea043031c5e985f668d4f51e1c759b0f9333 + +# ./a/1 +1 type=dir nlink=2 + a1.file.1 size=21 \ + sha256=a062cd272facdd38c4fdeff2a18947b28c99a28a8fe51f88468978740382e592 +# ./a/1 +.. + + +# ./a/2 +2 type=dir nlink=2 +# ./a/2 +.. + +# ./a +.. + + +# ./b +b type=dir nlink=2 + b.file.1 nlink=2 size=18 \ + sha256=5754b0d97a8238ea0e495ab871667dcab8f1d684e323290ae76f70c47de18998 + b.file.2 nlink=2 size=18 \ + sha256=784fd6b95fe5054d87bf268de51dea043031c5e985f668d4f51e1c759b0f9333 + b.hardlink.1 \ + nlink=2 size=18 \ + sha256=5754b0d97a8238ea0e495ab871667dcab8f1d684e323290ae76f70c47de18998 +# ./b +.. + diff --git a/tests/usr.sbin/mtree/t_mtree.sh b/tests/usr.sbin/mtree/t_mtree.sh new file mode 100644 index 000000000..20fda75e0 --- /dev/null +++ b/tests/usr.sbin/mtree/t_mtree.sh @@ -0,0 +1,422 @@ +# $NetBSD: t_mtree.sh,v 1.6 2013/02/05 16:49:42 christos Exp $ +# +# Copyright (c) 2009, 2012 The NetBSD Foundation, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +# Postprocess mtree output, canonicalising portions that +# are expected to differ from one run to another. +# + +h_postprocess() +{ + sed -e ' + /^# user: /s/:.*/: x/ + /^# machine: /s/:.*/: x/ + /^# tree: /s/:.*/: x/ + /^# date: /s/:.*/: x/ + ' \ + -e '/type=dir/s/ size=[0-9]*//' +} + +h_check() +{ + diff -Nru "$1" "$2" || atf_fail "files $1 and $2 differ" +} + + +atf_test_case mtree_create +atf_test_case netbsd6_create +create_head() +{ + atf_set "descr" "Create a specfile describing a directory tree" +} + +create_setup() +{ + # create some directories + rm -fr create + mkdir -p create/a/1 create/a/2 create/b + # create some files + for file in create/top.file.1 \ + create/a/a.file.1 \ + create/a/a.file.2 \ + create/a/1/a1.file.1 \ + create/b/b.file.1 \ + create/b/b.file.2 + do + echo "$file" >$file + done + # hard link to file in same dir + ln create/b/b.file.1 create/b/b.hardlink.1 + # hard link to file in another dir + ln create/b/b.file.2 create/a/a.hardlink.b2 + # symlink to file + ln -s a.file.1 create/a.symlink.1 + # symlink to dir + ln -s b create/top.symlink.b + # dangling symlink + ln -s nonexistent create/top.dangling +} + +create_body() +{ + create_setup + + # run mtree and check output + ( cd create && mtree -F ${FLAVOR} -c -k type,nlink,link,size,sha256 ) >output.raw \ + || atf_fail "mtree exit status $?" + h_postprocess output + h_check "$(atf_get_srcdir)/${FLAVOR}_d_create.out" output +} + +mtree_create_head() +{ + FLAVOR=mtree create_head +} +netbsd6_create_head() +{ + FLAVOR=netbsd6 create_head +} + +mtree_create_body() +{ + FLAVOR=mtree create_body +} +netbsd6_create_body() +{ + FLAVOR=netbsd6 create_body +} + + +atf_test_case mtree_check +atf_test_case netbsd6_check +check_head() +{ + atf_set "descr" "Check a directory tree against a specfile" +} + +check_body() +{ + # we use the same directory tree and specfile as in the "create" test + create_setup + + # run mtree and check output + ( cd create && mtree -F ${FLAVOR} ) <"$(atf_get_srcdir)/${FLAVOR}_d_create.out" >output \ + || atf_fail "mtree exit status $?" + h_check /dev/null output +} + +mtree_check_head() +{ + FLAVOR=mtree check_head +} +netbsd6_check_head() +{ + FLAVOR=netbsd6 check_head +} + +mtree_check_body() +{ + FLAVOR=mtree check_body +} +netbsd6_check_body() +{ + FLAVOR=netbsd6 check_body +} + + +atf_test_case mtree_convert_C +atf_test_case netbsd6_convert_C +convert_C_head() +{ + atf_set "descr" "Convert a specfile to mtree -C format, unsorted" +} + +convert_C_body() +{ + mtree -F ${FLAVOR} -C -K all <"$(atf_get_srcdir)/d_convert.in" >output + h_check "$(atf_get_srcdir)/d_convert_C.out" output +} + +mtree_convert_C_head() +{ + FLAVOR=mtree convert_C_head +} +netbsd6_convert_C_head() +{ + FLAVOR=netbsd6 convert_C_head +} + +mtree_convert_C_body() +{ + FLAVOR=mtree convert_C_body +} +netbsd6_convert_C_body() +{ + FLAVOR=netbsd6 convert_C_body +} + + +atf_test_case mtree_convert_C_S +atf_test_case netbsd6_convert_C_S +convert_C_S_head() +{ + atf_set "descr" "Convert a specfile to mtree -C format, sorted" +} + +convert_C_S_body() +{ + mtree -F ${FLAVOR} -C -S -K all <"$(atf_get_srcdir)/d_convert.in" >output + h_check "$(atf_get_srcdir)/d_convert_C_S.out" output +} + +mtree_convert_C_S_head() +{ + FLAVOR=mtree convert_C_S_head +} +netbsd6_convert_C_S_head() +{ + FLAVOR=netbsd6 convert_C_S_head +} + +mtree_convert_C_S_body() +{ + FLAVOR=mtree convert_C_S_body +} +netbsd6_convert_C_S_body() +{ + FLAVOR=netbsd6 convert_C_S_body +} + + +atf_test_case mtree_convert_D +atf_test_case netbsd6_convert_D +convert_D_head() +{ + atf_set "descr" "Convert a specfile to mtree -D format, unsorted" +} + +convert_D_body() +{ + mtree -F ${FLAVOR} -D -K all <"$(atf_get_srcdir)/d_convert.in" >output + h_check "$(atf_get_srcdir)/d_convert_D.out" output +} + +mtree_convert_D_head() +{ + FLAVOR=mtree convert_D_head +} +netbsd6_convert_D_head() +{ + FLAVOR=netbsd6 convert_D_head +} + +mtree_convert_D_body() +{ + FLAVOR=mtree convert_D_body +} +netbsd6_convert_D_body() +{ + FLAVOR=netbsd6 convert_D_body +} + + +atf_test_case mtree_convert_D_S +atf_test_case netbsd6_convert_D_S +convert_D_S_head() +{ + atf_set "descr" "Convert a specfile to mtree -D format, sorted" +} + +convert_D_S_body() +{ + mtree -F ${FLAVOR} -D -S -K all <"$(atf_get_srcdir)/d_convert.in" >output + h_check "$(atf_get_srcdir)/d_convert_D_S.out" output +} + +mtree_convert_D_S_head() +{ + FLAVOR=mtree convert_D_S_head +} +netbsd6_convert_D_S_head() +{ + FLAVOR=netbsd6 convert_D_S_head +} + +mtree_convert_D_S_body() +{ + FLAVOR=mtree convert_D_S_body +} +netbsd6_convert_D_S_body() +{ + FLAVOR=netbsd6 convert_D_S_body +} + + +atf_test_case mtree_ignore +atf_test_case netbs6_ignore +ignore_head() +{ + atf_set "descr" "Test that -d ignores symlinks (PR bin/41061)" +} + +ignore_body() +{ + mkdir newdir + mtree -F ${FLAVOR} -c | mtree -F ${FLAVOR} -Ck uid,gid,mode > mtree.spec + ln -s newdir otherdir + + # This yields "extra: otherdir" even with -d. + # (PR bin/41061) + atf_check -s ignore -o empty -e empty -x "mtree -F ${FLAVOR} -d < mtree.spec" + + # Delete the symlink and re-verify. + # + rm otherdir + atf_check -s ignore -o empty -e empty -x "mtree -F ${FLAVOR} -d < mtree.spec" +} + +mtree_ignore_head() +{ + FLAVOR=mtree ignore_head +} +netbsd6_ignore_head() +{ + FLAVOR=netbsd6 ignore_head +} + +mtree_ignore_body() +{ + FLAVOR=mtree ignore_body +} +netbsd6_ignore_body() +{ + FLAVOR=netbsd6 ignore_body +} + + +atf_test_case mtree_merge +atf_test_case netbsd6_merge +merge_head() +{ + atf_set "descr" "Merge records of different type" +} + +merge_body() +{ + mtree -F ${FLAVOR} -C -M -K all <"$(atf_get_srcdir)/d_merge.in" >output + h_check "$(atf_get_srcdir)/d_merge_C_M.out" output + # same again, with sorting + mtree -F ${FLAVOR} -C -M -S -K all <"$(atf_get_srcdir)/d_merge.in" >output + h_check "$(atf_get_srcdir)/d_merge_C_M_S.out" output +} + +mtree_merge_head() +{ + FLAVOR=mtree merge_head +} +netbsd6_merge_head() +{ + FLAVOR=netbsd6 merge_head +} + +mtree_merge_body() +{ + FLAVOR=mtree merge_body +} +netbsd6_merge_body() +{ + FLAVOR=netbsd6 merge_body +} + + +atf_test_case mtree_nonemptydir +atf_test_case netbsd6_nonemptydir +nonemptydir_head() +{ + atf_set "descr" "Test that new non-empty " \ + "directories are recorded (PR bin/25693)" +} + +nonemptydir_body() +{ + mkdir testdir + cd testdir + + mtree -F ${FLAVOR} -c > mtree.spec + + if [ ! -f mtree.spec ]; then + atf_fail "mtree failed" + fi + + touch bar + atf_check -s ignore -o save:output -x "mtree -F ${FLAVOR} -f mtree.spec" + + if [ ! -n "$(egrep "extra: bar" output)" ]; then + atf_fail "mtree did not record changes (PR bin/25693)" + fi +} + +mtree_nonemptydir_head() +{ + FLAVOR=mtree nonemptydir_head +} +netbsd6_nonemptydir_head() +{ + FLAVOR=netbsd6 nonemptydir_head +} + +mtree_nonemptydir_body() +{ + FLAVOR=mtree nonemptydir_body +} +netbsd6_nonemptydir_body() +{ + FLAVOR=netbsd6 nonemptydir_body +} + + +atf_init_test_cases() +{ + atf_add_test_case mtree_create + atf_add_test_case mtree_check + atf_add_test_case mtree_convert_C + atf_add_test_case mtree_convert_C_S + atf_add_test_case mtree_convert_D + atf_add_test_case mtree_convert_D_S + atf_add_test_case mtree_ignore + atf_add_test_case mtree_merge + atf_add_test_case mtree_nonemptydir + + atf_add_test_case netbsd6_create + atf_add_test_case netbsd6_check + atf_add_test_case netbsd6_convert_C + atf_add_test_case netbsd6_convert_C_S + atf_add_test_case netbsd6_convert_D + atf_add_test_case netbsd6_convert_D_S + atf_add_test_case netbsd6_ignore + atf_add_test_case netbsd6_merge + atf_add_test_case netbsd6_nonemptydir +} diff --git a/tests/usr.sbin/tcpdump/Makefile b/tests/usr.sbin/tcpdump/Makefile new file mode 100644 index 000000000..b93c5083c --- /dev/null +++ b/tests/usr.sbin/tcpdump/Makefile @@ -0,0 +1,9 @@ +# $NetBSD: Makefile,v 1.2 2012/04/14 12:43:05 jruoho Exp $ + +.include + +TESTSDIR= ${TESTSBASE}/usr.sbin/tcpdump + +TESTS_SH= t_tcpdump + +.include diff --git a/tests/usr.sbin/tcpdump/t_tcpdump.sh b/tests/usr.sbin/tcpdump/t_tcpdump.sh new file mode 100644 index 000000000..78c7a9cab --- /dev/null +++ b/tests/usr.sbin/tcpdump/t_tcpdump.sh @@ -0,0 +1,52 @@ +# $NetBSD: t_tcpdump.sh,v 1.3 2012/04/15 03:05:57 christos Exp $ +# +# Copyright (c) 2012 The NetBSD Foundation, Inc. +# All rights reserved. +# +# This code is derived from software contributed to The NetBSD Foundation +# by Jukka Ruohonen. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +prom() { + atf_check -s ignore -o ignore -e ignore -x "tcpdump -c 1 -i $1" & + sleep 2; kill $! >/dev/null 2>&1 +} + +atf_test_case promiscuous +promiscuous_head() { + atf_set "require.user" "root" + atf_set "descr" "Test that switching an interface into and out " \ + "of promiscuous mode does not lockup (PR kern/46328)" +} + +promiscuous_body() { + + for i in $(ifconfig -l); do + echo "Testing $i" + prom $i + done +} + +atf_init_test_cases() { + atf_add_test_case promiscuous +} diff --git a/tests/usr.sbin/traceroute/Makefile b/tests/usr.sbin/traceroute/Makefile new file mode 100644 index 000000000..5a2fa5392 --- /dev/null +++ b/tests/usr.sbin/traceroute/Makefile @@ -0,0 +1,10 @@ +# $NetBSD: Makefile,v 1.1 2010/12/15 00:13:52 pooka Exp $ +# + +.include + +TESTSDIR= ${TESTSBASE}/usr.sbin/traceroute + +TESTS_SH= t_traceroute + +.include diff --git a/tests/usr.sbin/traceroute/t_traceroute.sh b/tests/usr.sbin/traceroute/t_traceroute.sh new file mode 100644 index 000000000..cc2b2f40f --- /dev/null +++ b/tests/usr.sbin/traceroute/t_traceroute.sh @@ -0,0 +1,128 @@ +# $NetBSD: t_traceroute.sh,v 1.5 2013/02/19 21:08:25 joerg Exp $ +# +# Copyright (c) 2010 The NetBSD Foundation, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +netserver=\ +"rump_server -lrumpnet -lrumpnet_net -lrumpnet_netinet -lrumpnet_shmif" + +atf_test_case basic cleanup +basic_head() +{ + + atf_set "descr" "Does a simple three-hop traceroute" + atf_set "require.progs" "rump_server" +} + +cfgendpt () +{ + + sock=${1} + addr=${2} + route=${3} + bus=${4} + + export RUMP_SERVER=${sock} + atf_check -s exit:0 rump.ifconfig shmif0 create + atf_check -s exit:0 rump.ifconfig shmif0 linkstr ${bus} + atf_check -s exit:0 rump.ifconfig shmif0 inet ${addr} netmask 0xffffff00 + atf_check -s exit:0 -o ignore rump.route add default ${route} +} + +threeservers() +{ + + atf_check -s exit:0 ${netserver} unix://commsock1 + atf_check -s exit:0 ${netserver} unix://commsock2 + atf_check -s exit:0 ${netserver} unix://commsock3 + + # configure endpoints + cfgendpt unix://commsock1 1.2.3.4 1.2.3.1 bus1 + cfgendpt unix://commsock3 2.3.4.5 2.3.4.1 bus2 + + # configure the router + export RUMP_SERVER=unix://commsock2 + atf_check -s exit:0 rump.ifconfig shmif0 create + atf_check -s exit:0 rump.ifconfig shmif0 linkstr bus1 + atf_check -s exit:0 rump.ifconfig shmif0 inet 1.2.3.1 netmask 0xffffff00 + + atf_check -s exit:0 rump.ifconfig shmif1 create + atf_check -s exit:0 rump.ifconfig shmif1 linkstr bus2 + atf_check -s exit:0 rump.ifconfig shmif1 inet 2.3.4.1 netmask 0xffffff00 +} + +threecleanup() +{ + env RUMP_SERVER=unix://commsock1 rump.halt + env RUMP_SERVER=unix://commsock2 rump.halt + env RUMP_SERVER=unix://commsock3 rump.halt +} + +threetests() +{ + + threeservers + export RUMP_SERVER=unix://commsock1 + atf_check -s exit:0 -o inline:'1.2.3.1\n2.3.4.5\n' -e ignore -x \ + "rump.traceroute ${1} -n 2.3.4.5 | awk '{print \$2}'" + export RUMP_SERVER=unix://commsock3 + atf_check -s exit:0 -o inline:'2.3.4.1\n1.2.3.4\n' -e ignore -x \ + "rump.traceroute ${1} -n 1.2.3.4 | awk '{print \$2}'" +} + +basic_body() +{ + threetests +} + +basic_cleanup() +{ + threecleanup +} + +atf_test_case basic_icmp cleanup +basic_icmp_head() +{ + + atf_set "descr" "Does an ICMP-based three-hop traceroute" + atf_set "require.progs" "rump_server" +} + +basic_icmp_body() +{ + threetests -I +} + +basic_icmp_cleanup() +{ + threecleanup +} + +atf_init_test_cases() +{ + + atf_add_test_case basic + atf_add_test_case basic_icmp +} diff --git a/tests/usr.sbin/useradd/Makefile b/tests/usr.sbin/useradd/Makefile new file mode 100644 index 000000000..eaf2ea44f --- /dev/null +++ b/tests/usr.sbin/useradd/Makefile @@ -0,0 +1,11 @@ +# $NetBSD: Makefile,v 1.1 2012/04/19 18:51:35 jruoho Exp $ + +NOMAN= # defined + +.include + +TESTSDIR= ${TESTSBASE}/usr.sbin/useradd + +TESTS_SH= t_useradd + +.include diff --git a/tests/usr.sbin/useradd/t_useradd.sh b/tests/usr.sbin/useradd/t_useradd.sh new file mode 100644 index 000000000..c55818e07 --- /dev/null +++ b/tests/usr.sbin/useradd/t_useradd.sh @@ -0,0 +1,50 @@ +# $NetBSD: t_useradd.sh,v 1.1 2012/04/19 18:51:36 jruoho Exp $ +# +# Copyright (c) 2012 The NetBSD Foundation, Inc. +# All rights reserved. +# +# This code is derived from software contributed to The NetBSD Foundation +# by Jukka Ruohonen. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +username="test5678901234567" + +atf_test_case longname cleanup +longname_head() { + atf_set "require.user" "root" + atf_set "descr" "Test that usernames longer than 16 " \ + "characters are allowed (PR bin/39546)" +} + +longname_body() { + atf_expect_fail "PR bin/39546" + atf_check -s exit:0 -o ignore -e ignore -x "useradd $username" +} + +longname_cleanup() { + atf_check -s ignore -o ignore -e ignore -x "userdel $username" +} + +atf_init_test_cases() { + atf_add_test_case longname +}