Importing NetBSD "Kyua" test framework

To do so, a few dependencies have been imported:

 * external/bsd/lutok
 * external/mit/lua
 * external/public-domain/sqlite
 * external/public-domain/xz

The Kyua framework is the new generation of ATF (Automated Test
Framework), it is composed of:

 * external/bsd/atf
 * external/bsd/kyua-atf-compat
 * external/bsd/kyua-cli
 * external/bsd/kyua-tester
 * tests

Kyua/ATF being written in C++, it depends on libstdc++ which is
provided by GCC. As this is not part of the sources, Kyua is only
compiled when the native GCC utils are installed.

To install Kyua do the following:

 * In a cross-build enviromnent, add the following to the build.sh
   commandline: -V MKBINUTILS=yes -V MKGCCCMDS=yes

WARNING:
  At this point the import is still experimental, and not supported
  on native builds (a.k.a make build).

Change-Id: I26aee23c5bbd2d64adcb7c1beb98fe0d479d7ada
This commit is contained in:
Lionel Sambuc 2013-02-26 09:24:42 +01:00 committed by Gerrit Code Review
parent 003ff52ebb
commit 11be35a165
2893 changed files with 502052 additions and 2630 deletions

View file

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

View file

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

File diff suppressed because it is too large Load diff

View file

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

View file

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

View file

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

View file

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

398
etc/mtree/NetBSD.dist.tests Normal file
View file

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

1
external/Makefile vendored
View file

@ -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 <bsd.subdir.mk>

View file

@ -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 <bsd.own.mk>
@ -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

5
external/bsd/atf/Makefile vendored Normal file
View file

@ -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 <bsd.subdir.mk>

7
external/bsd/atf/Makefile.inc vendored Normal file
View file

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

30
external/bsd/atf/dist/AUTHORS vendored Normal file
View file

@ -0,0 +1,30 @@
Authors and contributors Automated Testing Framework
===========================================================================
* Julio Merino <jmmv@NetBSD.org>
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 <martin@NetBSD.org>
Mentored this project during its development as part of the Google Summer
of Code 2007 program.
* Lukasz Strzygowski <qx89l4@gmail.com>
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 <pgoyette@NetBSD.org>
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

12
external/bsd/atf/dist/Atffile vendored Normal file
View file

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

100
external/bsd/atf/dist/COPYING vendored Normal file
View file

@ -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 <jmmv@users.sourceforge.net>
* 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 <jmmv@NetBSD.org>
* 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 <jmmv84@gmail.com>
* 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 <jmmv84@gmail.com>
===========================================================================
vim: filetype=text:textwidth=75:expandtab:shiftwidth=2:softtabstop=2

18
external/bsd/atf/dist/Kyuafile vendored Normal file
View file

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

604
external/bsd/atf/dist/NEWS vendored Normal file
View file

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

40
external/bsd/atf/dist/README vendored Normal file
View file

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

36
external/bsd/atf/dist/atf-c++.hpp vendored Normal file
View file

@ -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 <atf-c++/macros.hpp>
#include <atf-c++/utils.hpp>
#endif // !defined(_ATF_CXX_HPP_)

14
external/bsd/atf/dist/atf-c++/Atffile vendored Normal file
View file

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

14
external/bsd/atf/dist/atf-c++/Kyuafile vendored Normal file
View file

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

View file

@ -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-c++.hpp>
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-c++.hpp>
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

View file

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

View file

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

119
external/bsd/atf/dist/atf-c++/build.cpp vendored Normal file
View file

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

57
external/bsd/atf/dist/atf-c++/build.hpp vendored Normal file
View file

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

View file

@ -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 <cstring>
#include <iostream>
#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);
}

158
external/bsd/atf/dist/atf-c++/check.cpp vendored Normal file
View file

@ -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 <cstring>
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));
}

133
external/bsd/atf/dist/atf-c++/check.hpp vendored Normal file
View file

@ -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 <atf-c/check.h>
}
#include <cstddef>
#include <memory>
#include <string>
#include <vector>
#include <atf-c++/noncopyable.hpp>
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_)

View file

@ -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 <fcntl.h>
#include <signal.h>
#include <unistd.h>
}
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iostream>
#include <list>
#include <memory>
#include <vector>
#include <atf-c++.hpp>
#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 <stdio.h>\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 <iostream>\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);
}

123
external/bsd/atf/dist/atf-c++/config.cpp vendored Normal file
View file

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

View file

@ -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 <map>
#include <string>
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_)

View file

@ -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 <cstring>
#include <iostream>
#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);
}

View file

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

View file

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

View file

@ -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 <unistd.h>
}
#include <cstdarg>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
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;
}

View file

@ -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 <ostream>
#include <set>
#include <stdexcept>
#include <string>
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_)

View file

@ -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 <unistd.h>
}
#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);
}

View file

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

View file

@ -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 <sys/types.h>
}
#include <iostream>
#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);
}

View file

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

View file

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

View file

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

View file

@ -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 <cstdarg>
#include <cstdio>
#include <cstring>
#include <new>
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;
}

View file

@ -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 <stdexcept>
#include <string>
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_)

View file

@ -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 <cstdio>
#include <new>
#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);
}

View file

@ -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 <stdexcept>
#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));
}

View file

@ -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 <string>
#include <vector>
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_)

View file

@ -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 <cstring>
#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);
}

View file

@ -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 <sys/param.h>
#include <sys/types.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <dirent.h>
#include <libgen.h>
#include <unistd.h>
}
#include <cerrno>
#include <cstdlib>
#include <cstring>
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);
}

View file

@ -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 <sys/types.h>
}
#include <map>
#include <memory>
#include <ostream>
#include <set>
#include <stdexcept>
#include <string>
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_)

View file

@ -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 <sys/types.h>
#include <sys/stat.h>
}
#include <fstream>
#include <cerrno>
#include <cstdio>
#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);
}

View file

@ -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 <sstream>
#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") + "'");
}

View file

@ -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 <istream>
#include <map>
#include <ostream>
#include <stdexcept>
#include <string>
#include <utility>
#include <vector>
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, "<<EOF>>");
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, "<<NEWLINE>>");
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, "<<NEWLINE>>");
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_)

File diff suppressed because it is too large Load diff

View file

@ -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 <signal.h>
#include "../../atf-c/error.h"
#include "../../atf-c/detail/process.h"
}
#include <iostream>
#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();
}

View file

@ -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 <sys/types.h>
#include "../../atf-c/error.h"
#include "../../atf-c/detail/process.h"
}
#include <string>
#include <vector>
#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_)

View file

@ -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 <cstdlib>
#include <cstring>
#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);
}

View file

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

View file

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

View file

@ -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 <fstream>
#include <iostream>
#include <string>
#include <vector>
#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");
}
}

View file

@ -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 <cstdlib>
#include <iostream>
#include <sstream>
#include <utility>
#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);
}

View file

@ -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 <regex.h>
}
#include <cctype>
#include <cstring>
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;
}

View file

@ -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 <stdint.h>
}
#include <sstream>
#include <stdexcept>
#include <string>
#include <vector>
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_)

View file

@ -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 <cstring>
#include <set>
#include <vector>
#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);
}

View file

@ -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 <sys/ioctl.h>
#include <termios.h>
#include <unistd.h>
}
#include <sstream>
#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);
}

View file

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

View file

@ -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 <cstring>
#include <iostream>
#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);
}

222
external/bsd/atf/dist/atf-c++/macros.hpp vendored Normal file
View file

@ -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 <sstream>
#include <stdexcept>
#include <vector>
#include <atf-c++/tests.hpp>
// 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_)

View file

@ -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 <stdexcept>
#include <atf-c++/macros.hpp>
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;
}

View file

@ -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 <fcntl.h>
#include <unistd.h>
}
#include <cerrno>
#include <cstdlib>
#include <iostream>
#include <stdexcept>
#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);
}

View file

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

View file

@ -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 <<EOF
#include <iostream>
#include <atf-c++.hpp>
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

711
external/bsd/atf/dist/atf-c++/tests.cpp vendored Normal file
View file

@ -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 <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <signal.h>
#include <unistd.h>
}
#include <algorithm>
#include <cctype>
#include <cerrno>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iostream>
#include <map>
#include <memory>
#include <sstream>
#include <stdexcept>
#include <vector>
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);
}

127
external/bsd/atf/dist/atf-c++/tests.hpp vendored Normal file
View file

@ -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 <map>
#include <memory>
#include <string>
extern "C" {
#include <atf-c/defs.h>
}
#include <atf-c++/noncopyable.hpp>
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_)

View file

@ -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 <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
}
#include <fstream>
#include <sstream>
#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);
}

View file

@ -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-c++/macros.hpp>
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);
}

104
external/bsd/atf/dist/atf-c++/utils.cpp vendored Normal file
View file

@ -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 <cstdlib>
#include <iostream>
#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());
}

68
external/bsd/atf/dist/atf-c++/utils.hpp vendored Normal file
View file

@ -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 <unistd.h>
}
#include <string>
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_)

View file

@ -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 <sys/stat.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <unistd.h>
}
#include <cstdlib>
#include <iostream>
#include <set>
#include <string>
#include <vector>
#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);
}

37
external/bsd/atf/dist/atf-c.h vendored Normal file
View file

@ -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 <atf-c/error.h>
#include <atf-c/macros.h>
#include <atf-c/utils.h>
#endif /* !defined(ATF_C_H) */

16
external/bsd/atf/dist/atf-c/Atffile vendored Normal file
View file

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

16
external/bsd/atf/dist/atf-c/Kyuafile vendored Normal file
View file

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

776
external/bsd/atf/dist/atf-c/atf-c-api.3 vendored Normal file
View file

@ -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-c.h>
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-c.h>
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

11
external/bsd/atf/dist/atf-c/atf-c.pc.in vendored Normal file
View file

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

View file

@ -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 <atf-c.h>
#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();
}

281
external/bsd/atf/dist/atf-c/build.c vendored Normal file
View file

@ -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 <stdlib.h>
#include <string.h>
#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;
}

42
external/bsd/atf/dist/atf-c/build.h vendored Normal file
View file

@ -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-c/error_fwd.h>
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 */

268
external/bsd/atf/dist/atf-c/build_test.c vendored Normal file
View file

@ -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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <atf-c.h>
#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();
}

488
external/bsd/atf/dist/atf-c/check.c vendored Normal file
View file

@ -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 <sys/wait.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#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;
}

73
external/bsd/atf/dist/atf-c/check.h vendored Normal file
View file

@ -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 <stdbool.h>
#include <atf-c/error_fwd.h>
/* ---------------------------------------------------------------------
* 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 */

539
external/bsd/atf/dist/atf-c/check_test.c vendored Normal file
View file

@ -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 <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <atf-c.h>
#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 <stdio.h>\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 <iostream>\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();
}

164
external/bsd/atf/dist/atf-c/config.c vendored Normal file
View file

@ -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 <ctype.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#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;
}

37
external/bsd/atf/dist/atf-c/config.h vendored Normal file
View file

@ -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 <stdbool.h>
const char *atf_config_get(const char *);
#endif /* !defined(ATF_C_CONFIG_H) */

View file

@ -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 <stdio.h>
#include <string.h>
#include <atf-c.h>
#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();
}

37
external/bsd/atf/dist/atf-c/defs.h.in vendored Normal file
View file

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

View file

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

View file

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

View file

@ -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 <errno.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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;
}

View file

@ -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 <stdarg.h>
#include <stdbool.h>
#include <stddef.h>
#include <atf-c/error_fwd.h>
/* ---------------------------------------------------------------------
* 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 */

Some files were not shown because too many files have changed in this diff Show more