diff --git a/Makefile.am b/Makefile.am
index 695e36d7..6b2ae9d6 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -12,4 +12,7 @@ install-data-local:
-$(top_srcdir)/config/install-sh -o $(RUN_AS_USER) -m 755 -d \
$(DESTDIR)$(localstatedir)/run/powerman
-EXTRA_DIST = DISCLAIMER examples/powerman_el72.spec
+EXTRA_DIST = \
+ DISCLAIMER \
+ examples/powerman_el72.spec \
+ config/tap-driver.sh
diff --git a/config/tap-driver.sh b/config/tap-driver.sh
new file mode 100755
index 00000000..90e3fce2
--- /dev/null
+++ b/config/tap-driver.sh
@@ -0,0 +1,691 @@
+#! /bin/sh
+# Copyright (C) 2011-2013 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# This file is maintained in Automake, please report
+# bugs to or send patches to
+# .
+
+scriptversion=2013-12-23.17; # UTC
+
+# Make unconditional expansion of undefined variables an error. This
+# helps a lot in preventing typo-related bugs.
+set -u
+
+me=tap-driver.sh
+
+fatal ()
+{
+ echo "$me: fatal: $*" >&2
+ exit 1
+}
+
+usage_error ()
+{
+ echo "$me: $*" >&2
+ print_usage >&2
+ exit 2
+}
+
+print_usage ()
+{
+ cat <
+ #
+ trap : 1 3 2 13 15
+ if test $merge -gt 0; then
+ exec 2>&1
+ else
+ exec 2>&3
+ fi
+ if test -n "${FLUX_TEST_TIMEOUT:-}" ; then
+ if test -z "${FLUX_SOURCE_DIR:-}"; then
+ if test -n "${top_srcdir:-}" ; then
+ FLUX_SOURCE_DIR="$top_srcdir"
+ else
+ SCRIPT=$(readlink -f "$0")
+ SPATH=$(dirname "$SCRIPT")
+ FLUX_SOURCE_DIR="$SPATH"/..
+ fi
+ fi
+ "${PYTHON:-python3}" -S "${FLUX_SOURCE_DIR}/t/scripts/run_timeout.py" "$FLUX_TEST_TIMEOUT" "$@"
+ else
+ "$@"
+ fi
+ echo $?
+ ) | LC_ALL=C ${AM_TAP_AWK-awk} \
+ -v me="$me" \
+ -v test_script_name="$test_name" \
+ -v log_file="$log_file" \
+ -v trs_file="$trs_file" \
+ -v expect_failure="$expect_failure" \
+ -v merge="$merge" \
+ -v ignore_exit="$ignore_exit" \
+ -v comments="$comments" \
+ -v diag_string="$diag_string" \
+ -v quiet="$TAP_DRIVER_QUIET" \
+'
+# TODO: the usages of "cat >&3" below could be optimized when using
+# GNU awk, and/on on systems that supports /dev/fd/.
+
+# Implementation note: in what follows, `result_obj` will be an
+# associative array that (partly) simulates a TAP result object
+# from the `TAP::Parser` perl module.
+
+## ----------- ##
+## FUNCTIONS ##
+## ----------- ##
+
+function fatal(msg)
+{
+ print me ": " msg | "cat >&2"
+ exit 1
+}
+
+function abort(where)
+{
+ fatal("internal error " where)
+}
+
+# Convert a boolean to a "yes"/"no" string.
+function yn(bool)
+{
+ return bool ? "yes" : "no";
+}
+
+function add_test_result(result)
+{
+ if (!test_results_index)
+ test_results_index = 0
+ test_results_list[test_results_index] = result
+ test_results_index += 1
+ test_results_seen[result] = 1;
+}
+
+# Whether the test script should be re-run by "make recheck".
+function must_recheck()
+{
+ for (k in test_results_seen)
+ if (k != "XFAIL" && k != "PASS" && k != "SKIP")
+ return 1
+ return 0
+}
+
+# Whether the content of the log file associated to this test should
+# be copied into the "global" test-suite.log.
+function copy_in_global_log()
+{
+ for (k in test_results_seen)
+ if (k != "PASS")
+ return 1
+ return 0
+}
+
+function get_global_test_result()
+{
+ if ("ERROR" in test_results_seen)
+ return "ERROR"
+ if ("FAIL" in test_results_seen || "XPASS" in test_results_seen)
+ return "FAIL"
+ all_skipped = 1
+ for (k in test_results_seen)
+ if (k != "SKIP")
+ all_skipped = 0
+ if (all_skipped)
+ return "SKIP"
+ return "PASS";
+}
+
+function summarize_global_test_result()
+{
+ i = 0
+ for (k in test_results_list) {
+ i += 1
+ totals[ test_results_list[k] ] += 1
+ }
+ res = sprintf ("N=%-3d PASS=%-3d FAIL=%d SKIP=%d XPASS=%d XFAIL=%d",
+ i, totals["PASS"], totals["FAIL"],
+ totals["SKIP"], totals["XPASS"],
+ totals["XFAIL"])
+ return res
+}
+
+function stringify_result_obj(result_obj)
+{
+ if (result_obj["is_unplanned"] || result_obj["number"] != testno)
+ return "ERROR"
+
+ if (plan_seen == LATE_PLAN)
+ return "ERROR"
+
+ if (result_obj["directive"] == "TODO")
+ return result_obj["is_ok"] ? "XPASS" : "XFAIL"
+
+ if (result_obj["directive"] == "SKIP")
+ return result_obj["is_ok"] ? "SKIP" : COOKED_FAIL;
+
+ if (length(result_obj["directive"]))
+ abort("in function stringify_result_obj()")
+
+ return result_obj["is_ok"] ? COOKED_PASS : COOKED_FAIL
+}
+
+function decorate_result(result)
+{
+ color_name = color_for_result[result]
+ if (color_name)
+ return color_map[color_name] "" result "" color_map["std"]
+ # If we are not using colorized output, or if we do not know how
+ # to colorize the given result, we should return it unchanged.
+ return result
+}
+
+function report(result, details)
+{
+ if (result ~ /^(X?(PASS|FAIL)|SKIP|ERROR)/)
+ {
+ msg = ": " test_script_name
+ add_test_result(result)
+ }
+ else if (result == "#")
+ {
+ msg = " " test_script_name ":"
+ }
+ else
+ {
+ abort("in function report()")
+ }
+ if (length(details))
+ msg = msg " " details
+ # Output on console might be colorized.
+ if (!quiet || result ~ /^(FAIL|ERROR)/)
+ print decorate_result(result) msg
+ # Log the result in the log file too, to help debugging (this is
+ # especially true when said result is a TAP error or "Bail out!").
+ print result msg | "cat >&3";
+}
+
+function testsuite_error(error_message)
+{
+ report("ERROR", "- " error_message)
+}
+
+function handle_tap_result()
+{
+ details = result_obj["number"];
+ if (length(result_obj["description"]))
+ details = details " " result_obj["description"]
+
+ if (plan_seen == LATE_PLAN)
+ {
+ details = details " # AFTER LATE PLAN";
+ }
+ else if (result_obj["is_unplanned"])
+ {
+ details = details " # UNPLANNED";
+ }
+ else if (result_obj["number"] != testno)
+ {
+ details = sprintf("%s # OUT-OF-ORDER (expecting %d)",
+ details, testno);
+ }
+ else if (result_obj["directive"])
+ {
+ details = details " # " result_obj["directive"];
+ if (length(result_obj["explanation"]))
+ details = details " " result_obj["explanation"]
+ }
+
+ report(stringify_result_obj(result_obj), details)
+}
+
+# `skip_reason` should be empty whenever planned > 0.
+function handle_tap_plan(planned, skip_reason)
+{
+ planned += 0 # Avoid getting confused if, say, `planned` is "00"
+ if (length(skip_reason) && planned > 0)
+ abort("in function handle_tap_plan()")
+ if (plan_seen)
+ {
+ # Error, only one plan per stream is acceptable.
+ testsuite_error("multiple test plans")
+ return;
+ }
+ planned_tests = planned
+ # The TAP plan can come before or after *all* the TAP results; we speak
+ # respectively of an "early" or a "late" plan. If we see the plan line
+ # after at least one TAP result has been seen, assume we have a late
+ # plan; in this case, any further test result seen after the plan will
+ # be flagged as an error.
+ plan_seen = (testno >= 1 ? LATE_PLAN : EARLY_PLAN)
+ # If testno > 0, we have an error ("too many tests run") that will be
+ # automatically dealt with later, so do not worry about it here. If
+ # $plan_seen is true, we have an error due to a repeated plan, and that
+ # has already been dealt with above. Otherwise, we have a valid "plan
+ # with SKIP" specification, and should report it as a particular kind
+ # of SKIP result.
+ if (planned == 0 && testno == 0)
+ {
+ if (length(skip_reason))
+ skip_reason = "- " skip_reason;
+ report("SKIP", skip_reason);
+ }
+}
+
+function extract_tap_comment(line)
+{
+ if (index(line, diag_string) == 1)
+ {
+ # Strip leading `diag_string` from `line`.
+ line = substr(line, length(diag_string) + 1)
+ # And strip any leading and trailing whitespace left.
+ sub("^[ \t]*", "", line)
+ sub("[ \t]*$", "", line)
+ # Return what is left (if any).
+ return line;
+ }
+ return "";
+}
+
+# When this function is called, we know that line is a TAP result line,
+# so that it matches the (perl) RE "^(not )?ok\b".
+function setup_result_obj(line)
+{
+ # Get the result, and remove it from the line.
+ result_obj["is_ok"] = (substr(line, 1, 2) == "ok" ? 1 : 0)
+ sub("^(not )?ok[ \t]*", "", line)
+
+ # If the result has an explicit number, get it and strip it; otherwise,
+ # automatically assing the next progresive number to it.
+ if (line ~ /^[0-9]+$/ || line ~ /^[0-9]+[^a-zA-Z0-9_]/)
+ {
+ match(line, "^[0-9]+")
+ # The final `+ 0` is to normalize numbers with leading zeros.
+ result_obj["number"] = substr(line, 1, RLENGTH) + 0
+ line = substr(line, RLENGTH + 1)
+ }
+ else
+ {
+ result_obj["number"] = testno
+ }
+
+ if (plan_seen == LATE_PLAN)
+ # No further test results are acceptable after a "late" TAP plan
+ # has been seen.
+ result_obj["is_unplanned"] = 1
+ else if (plan_seen && testno > planned_tests)
+ result_obj["is_unplanned"] = 1
+ else
+ result_obj["is_unplanned"] = 0
+
+ # Strip trailing and leading whitespace.
+ sub("^[ \t]*", "", line)
+ sub("[ \t]*$", "", line)
+
+ # This will have to be corrected if we have a "TODO"/"SKIP" directive.
+ result_obj["description"] = line
+ result_obj["directive"] = ""
+ result_obj["explanation"] = ""
+
+ if (index(line, "#") == 0)
+ return # No possible directive, nothing more to do.
+
+ # Directives are case-insensitive.
+ rx = "[ \t]*#[ \t]*([tT][oO][dD][oO]|[sS][kK][iI][pP])[ \t]*"
+
+ # See whether we have the directive, and if yes, where.
+ pos = match(line, rx "$")
+ if (!pos)
+ pos = match(line, rx "[^a-zA-Z0-9_]")
+
+ # If there was no TAP directive, we have nothing more to do.
+ if (!pos)
+ return
+
+ # Let`s now see if the TAP directive has been escaped. For example:
+ # escaped: ok \# SKIP
+ # not escaped: ok \\# SKIP
+ # escaped: ok \\\\\# SKIP
+ # not escaped: ok \ # SKIP
+ if (substr(line, pos, 1) == "#")
+ {
+ bslash_count = 0
+ for (i = pos; i > 1 && substr(line, i - 1, 1) == "\\"; i--)
+ bslash_count += 1
+ if (bslash_count % 2)
+ return # Directive was escaped.
+ }
+
+ # Strip the directive and its explanation (if any) from the test
+ # description.
+ result_obj["description"] = substr(line, 1, pos - 1)
+ # Now remove the test description from the line, that has been dealt
+ # with already.
+ line = substr(line, pos)
+ # Strip the directive, and save its value (normalized to upper case).
+ sub("^[ \t]*#[ \t]*", "", line)
+ result_obj["directive"] = toupper(substr(line, 1, 4))
+ line = substr(line, 5)
+ # Now get the explanation for the directive (if any), with leading
+ # and trailing whitespace removed.
+ sub("^[ \t]*", "", line)
+ sub("[ \t]*$", "", line)
+ result_obj["explanation"] = line
+}
+
+function get_test_exit_message(status)
+{
+ if (status == 0)
+ return ""
+ if (status !~ /^[1-9][0-9]*$/)
+ abort("getting exit status")
+ if (status < 127)
+ exit_details = ""
+ else if (status == 127)
+ exit_details = " (command not found?)"
+ else if (status >= 128 && status <= 255)
+ exit_details = sprintf(" (terminated by signal %d?)", status - 128)
+ else if (status > 256 && status <= 384)
+ # We used to report an "abnormal termination" here, but some Korn
+ # shells, when a child process die due to signal number n, can leave
+ # in $? an exit status of 256+n instead of the more standard 128+n.
+ # Apparently, both behaviours are allowed by POSIX (2008), so be
+ # prepared to handle them both. See also Austing Group report ID
+ # 0000051
+ exit_details = sprintf(" (terminated by signal %d?)", status - 256)
+ else
+ # Never seen in practice.
+ exit_details = " (abnormal termination)"
+ return sprintf("exited with status %d%s", status, exit_details)
+}
+
+function write_test_results()
+{
+ print ":global-test-result: " get_global_test_result() > trs_file
+ print ":recheck: " yn(must_recheck()) > trs_file
+ print ":copy-in-global-log: " yn(copy_in_global_log()) > trs_file
+ for (i = 0; i < test_results_index; i += 1)
+ print ":test-result: " test_results_list[i] > trs_file
+ close(trs_file);
+}
+
+BEGIN {
+
+## ------- ##
+## SETUP ##
+## ------- ##
+
+'"$init_colors"'
+
+# Properly initialized once the TAP plan is seen.
+planned_tests = 0
+
+COOKED_PASS = expect_failure ? "XPASS": "PASS";
+COOKED_FAIL = expect_failure ? "XFAIL": "FAIL";
+
+# Enumeration-like constants to remember which kind of plan (if any)
+# has been seen. It is important that NO_PLAN evaluates "false" as
+# a boolean.
+NO_PLAN = 0
+EARLY_PLAN = 1
+LATE_PLAN = 2
+
+testno = 0 # Number of test results seen so far.
+bailed_out = 0 # Whether a "Bail out!" directive has been seen.
+
+# Whether the TAP plan has been seen or not, and if yes, which kind
+# it is ("early" is seen before any test result, "late" otherwise).
+plan_seen = NO_PLAN
+
+## --------- ##
+## PARSING ##
+## --------- ##
+
+is_first_read = 1
+
+while (1)
+ {
+ # Involutions required so that we are able to read the exit status
+ # from the last input line.
+ st = getline
+ if (st < 0) # I/O error.
+ fatal("I/O error while reading from input stream")
+ else if (st == 0) # End-of-input
+ {
+ if (is_first_read)
+ abort("in input loop: only one input line")
+ break
+ }
+ if (is_first_read)
+ {
+ is_first_read = 0
+ nextline = $0
+ continue
+ }
+ else
+ {
+ curline = nextline
+ nextline = $0
+ $0 = curline
+ }
+ # Copy any input line verbatim into the log file.
+ print | "cat >&3"
+ # Parsing of TAP input should stop after a "Bail out!" directive.
+ if (bailed_out)
+ continue
+
+ # TAP test result.
+ if ($0 ~ /^(not )?ok$/ || $0 ~ /^(not )?ok[^a-zA-Z0-9_]/)
+ {
+ testno += 1
+ setup_result_obj($0)
+ handle_tap_result()
+ }
+ # TAP plan (normal or "SKIP" without explanation).
+ else if ($0 ~ /^1\.\.[0-9]+[ \t]*$/)
+ {
+ # The next two lines will put the number of planned tests in $0.
+ sub("^1\\.\\.", "")
+ sub("[^0-9]*$", "")
+ handle_tap_plan($0, "")
+ continue
+ }
+ # TAP "SKIP" plan, with an explanation.
+ else if ($0 ~ /^1\.\.0+[ \t]*#/)
+ {
+ # The next lines will put the skip explanation in $0, stripping
+ # any leading and trailing whitespace. This is a little more
+ # tricky in truth, since we want to also strip a potential leading
+ # "SKIP" string from the message.
+ sub("^[^#]*#[ \t]*(SKIP[: \t][ \t]*)?", "")
+ sub("[ \t]*$", "");
+ handle_tap_plan(0, $0)
+ }
+ # "Bail out!" magic.
+ # Older versions of prove and TAP::Harness (e.g., 3.17) did not
+ # recognize a "Bail out!" directive when preceded by leading
+ # whitespace, but more modern versions (e.g., 3.23) do. So we
+ # emulate the latter, "more modern" behaviour.
+ else if ($0 ~ /^[ \t]*Bail out!/)
+ {
+ bailed_out = 1
+ # Get the bailout message (if any), with leading and trailing
+ # whitespace stripped. The message remains stored in `$0`.
+ sub("^[ \t]*Bail out![ \t]*", "");
+ sub("[ \t]*$", "");
+ # Format the error message for the
+ bailout_message = "Bail out!"
+ if (length($0))
+ bailout_message = bailout_message " " $0
+ testsuite_error(bailout_message)
+ }
+ # Maybe we have too look for dianogtic comments too.
+ else if (comments != 0)
+ {
+ comment = extract_tap_comment($0);
+ if (length(comment))
+ report("#", comment);
+ }
+ }
+
+## -------- ##
+## FINISH ##
+## -------- ##
+# In quiet mode, issue summary now:
+if (quiet) {
+ printf ("%26s: %5s: %s\n",
+ test_script_name,
+ decorate_result(get_global_test_result()),
+ summarize_global_test_result())
+}
+
+# A "Bail out!" directive should cause us to ignore any following TAP
+# error, as well as a non-zero exit status from the TAP producer.
+if (!bailed_out)
+ {
+ if (!plan_seen)
+ {
+ testsuite_error("missing test plan")
+ }
+ else if (planned_tests != testno)
+ {
+ bad_amount = testno > planned_tests ? "many" : "few"
+ testsuite_error(sprintf("too %s tests run (expected %d, got %d)",
+ bad_amount, planned_tests, testno))
+ }
+ if (!ignore_exit)
+ {
+ # Fetch exit status from the last line.
+ exit_message = get_test_exit_message(nextline)
+ if (exit_message)
+ testsuite_error(exit_message)
+ }
+ }
+
+write_test_results()
+
+exit 0
+
+} # End of "BEGIN" block.
+'
+
+# TODO: document that we consume the file descriptor 3 :-(
+} 3>"$log_file"
+
+test $? -eq 0 || fatal "I/O or internal error"
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/configure.ac b/configure.ac
index 7e61d974..1e2ee073 100644
--- a/configure.ac
+++ b/configure.ac
@@ -126,6 +126,7 @@ AC_CONFIG_FILES( \
src/redfishpower/Makefile \
src/snmppower/Makefile \
src/plmpower/Makefile \
+ src/libtap/Makefile \
etc/Makefile \
etc/libpowerman.pc \
etc/powerman.service \
diff --git a/etc/Makefile.am b/etc/Makefile.am
index e7bda65c..53c58fd5 100644
--- a/etc/Makefile.am
+++ b/etc/Makefile.am
@@ -8,6 +8,9 @@ if WITH_PKG_CONFIG
pkgconfig_DATA = libpowerman.pc
endif
+check_DATA = \
+ devices/vpc.dev
+
pkgsysconfdir = $(sysconfdir)/powerman
pkgsysconf_DATA = \
@@ -70,8 +73,7 @@ pkgsysconf_DATA = \
devices/raritan-px5523.dev \
devices/sentry_cdu.dev \
devices/swpdu.dev \
- devices/vpc.dev \
devices/wti.dev \
devices/wti-rps10.dev
-EXTRA_DIST = $(pkgsysconf_DATA)
+EXTRA_DIST = $(pkgsysconf_DATA) $(check_DATA)
diff --git a/src/Makefile.am b/src/Makefile.am
index d4509e5e..2162ce96 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,4 +1,5 @@
SUBDIRS = \
+ libtap \
liblsd \
libcommon \
powerman \
diff --git a/src/libcommon/Makefile.am b/src/libcommon/Makefile.am
index 77512781..1de04a10 100644
--- a/src/libcommon/Makefile.am
+++ b/src/libcommon/Makefile.am
@@ -15,8 +15,6 @@ libcommon_a_SOURCES = \
error.h \
hprintf.c \
hprintf.h \
- pluglist.c \
- pluglist.h \
powerman.h \
xmalloc.c \
xmalloc.h \
@@ -32,3 +30,27 @@ libcommon_a_SOURCES = \
xsignal.h \
xtime.h \
xtypes.h
+
+TESTS = \
+ test_argv.t \
+ test_xregex.t
+
+check_PROGRAMS = $(TESTS)
+
+TEST_EXTENSIONS = .t
+T_LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) \
+ $(top_srcdir)/config/tap-driver.sh
+
+test_argv_t_CPPFLAGS = \
+ -I$(top_srcdir)/src/libtap
+test_argv_t_SOURCES = test/argv.c
+test_argv_t_LDADD = \
+ $(builddir)/libcommon.a \
+ $(top_builddir)/src/libtap/libtap.la
+
+test_xregex_t_CPPFLAGS = \
+ -I$(top_srcdir)/src/libtap
+test_xregex_t_SOURCES = test/xregex.c
+test_xregex_t_LDADD = \
+ $(builddir)/libcommon.a \
+ $(top_builddir)/src/libtap/libtap.la
diff --git a/test/targv.c b/src/libcommon/test/argv.c
similarity index 63%
rename from test/targv.c
rename to src/libcommon/test/argv.c
index ca444598..cb9a1807 100644
--- a/test/targv.c
+++ b/src/libcommon/test/argv.c
@@ -29,6 +29,7 @@
#include
#include
+#include "tap.h"
#include "argv.h"
int
@@ -36,25 +37,47 @@ main(int argc, char *argv[])
{
char **av;
+ plan(NO_PLAN);
+
av = argv_create("foo bar baz", "");
- assert(argv_length(av) == 3);
+ ok (av != NULL,
+ "argv_create foo bar baz works");
+ ok (argv_length(av) == 3,
+ "argv_length returns 3");
av = argv_append(av, "bonk");
- assert(argv_length(av) == 4);
- assert(strcmp(av[0], "foo") == 0);
- assert(strcmp(av[1], "bar") == 0);
- assert(strcmp(av[2], "baz") == 0);
- assert(strcmp(av[3], "bonk") == 0);
- assert(av[4] == NULL);
+ ok (argv_length(av) == 4,
+ "argv_length returns 4");
+ is (av[0], "foo",
+ "first arg is foo");
+ is (av[1], "bar",
+ "second arg is bar");
+ is (av[2], "baz",
+ "third arg is baz");
+ is (av[3], "bonk",
+ "fourth arg is bonk");
+ ok (av[4] == NULL,
+ "vector is NULL terminated");
argv_destroy(av);
av = argv_create("a,b:c d", ",:");
- assert(argv_length(av) == 4);
- assert(strcmp(av[0], "a") == 0);
- assert(strcmp(av[1], "b") == 0);
- assert(strcmp(av[2], "c") == 0);
- assert(strcmp(av[3], "d") == 0);
- assert(av[4] == NULL);
+ ok (av != NULL,
+ "argv_create a,:c d with , and : separators works");
+ ok (argv_length(av) == 4,
+ "argv_length is 4");
+ is (av[0], "a",
+ "first arg is a");
+ is (av[1], "b",
+ "second arg is b");
+ is (av[2], "c",
+ "third arg is c");
+ is (av[3], "d",
+ "fourth arg is d");
+ ok (av[4] == NULL,
+ "vector is null terminated");
argv_destroy(av);
+ done_testing();
exit(0);
}
+
+// vi:ts=4 sw=4 expandtab
diff --git a/test/tregex.c b/src/libcommon/test/xregex.c
similarity index 55%
rename from test/tregex.c
rename to src/libcommon/test/xregex.c
index 2e94408d..9921986f 100644
--- a/test/tregex.c
+++ b/src/libcommon/test/xregex.c
@@ -27,6 +27,8 @@
#include
#include
+#include "tap.h"
+
#include "xtypes.h"
#include "xregex.h"
#include "xmalloc.h"
@@ -86,54 +88,89 @@ _check_substr_match(void)
rm = xregex_match_create(2);
xregex_compile(re, "foo([0-9]+)bar([0-9]+)", TRUE);
- assert(xregex_exec(re, "xxxfoo1bar2", rm) == TRUE);
+ ok (xregex_exec(re, "xxxfoo1bar2", rm) == TRUE,
+ "regex with substrings matches xxxfoo1bar2");
+
s = xregex_match_sub_strdup(rm, 0);
- assert(s != NULL);
- assert(strcmp(s, "foo1bar2") == 0);
+ ok (s != NULL,
+ "substring 0 matched");
+ is (s, "foo1bar2",
+ "substring 0 is foo1bar2");
xfree(s);
+
s = xregex_match_sub_strdup(rm, 1);
- assert(s != NULL);
- assert(strcmp(s, "1") == 0);
+ ok (s != NULL,
+ "substring 1 matched");
+ is (s, "1",
+ "substring 1 is 1");
xfree(s);
+
s = xregex_match_sub_strdup(rm, 2);
- assert(s != NULL);
- assert(strcmp(s, "2") == 0);
+ ok (s != NULL,
+ "substring 2 matched");
+ is (s, "2",
+ "substring 2 is 2");
xfree(s);
+
s = xregex_match_sub_strdup(rm, 3);
- assert(s == NULL);
+ ok (s == NULL,
+ "substring 4 did NOT match");
+
s = xregex_match_sub_strdup(rm, -1); /* powerman actually does this! */
- assert(s == NULL);
+ ok (s == NULL,
+ "substring -1 did NOT match");
+
s = xregex_match_strdup(rm);
- assert(strcmp(s, "xxxfoo1bar2") == 0);
- assert(xregex_match_strlen(rm) == strlen(s));
+ is (s, "xxxfoo1bar2",
+ "overall match is xxxfoo1bar2");
+
+ ok (xregex_match_strlen(rm) == strlen(s),
+ "xregex_match_strlen returns expected length");
xfree(s);
xregex_match_recycle(rm);
- assert(xregex_exec(re, "foobar2", rm) == FALSE);
+ ok (xregex_exec(re, "foobar2", rm) == FALSE,
+ "regex does NOT match foobar2");
+
s = xregex_match_sub_strdup(rm, 0);
- assert(s == NULL);
+ ok (s == NULL,
+ "substring 0 did NOT match");
s = xregex_match_sub_strdup(rm, 1);
- assert(s == NULL);
+ ok (s == NULL,
+ "substring 1 did NOT match");
xregex_match_recycle(rm);
- assert(xregex_exec(re, "xxxfoo1bar2yyy", rm) == TRUE);
+ ok (xregex_exec(re, "xxxfoo1bar2yyy", rm) == TRUE,
+ "regex does matches xxxfoo1bar2yyy");
+
s = xregex_match_sub_strdup(rm, 0);
- assert(s != NULL);
- assert(strcmp(s, "foo1bar2") == 0);
+ ok (s != NULL,
+ "substring 0 matched");
+ is (s, "foo1bar2",
+ "substring 0 is foo1bar2");
xfree(s);
+
s = xregex_match_sub_strdup(rm, 1);
- assert(s != NULL);
- assert(strcmp(s, "1") == 0);
+ ok (s != NULL,
+ "substring 1 matched");
+ is (s, "1",
+ "substring 1 is 1");
xfree(s);
+
s = xregex_match_sub_strdup(rm, 2);
- assert(s != NULL);
- assert(strcmp(s, "2") == 0);
+ ok (s != NULL,
+ "substring 2 matched");
+ is (s, "2",
+ "substring 2 is 2");
xfree(s);
+
s = xregex_match_strdup(rm);
- assert(strcmp(s, "xxxfoo1bar2") == 0);
- assert(xregex_match_strlen(rm) == strlen(s));
+ is (s, "xxxfoo1bar2",
+ "overall match is xxxfoo1bar2");
+ ok (xregex_match_strlen(rm) == strlen(s),
+ "xregex_match_strlen returned expected length");
xfree(s);
xregex_match_destroy(rm);
@@ -145,18 +182,24 @@ main(int argc, char *argv[])
{
char *s;
- err_init("tregex");
+ plan(NO_PLAN);
- assert(_match("foo", "foo"));
- assert(_match("foo", "fooxxx"));
- assert(_match("foo", "xxxfoo"));
- assert(!_match("foo", "bar"));
+ ok (_match("foo", "foo"),
+ "regex foo matches foo");
+ ok (_match("foo", "fooxxx"),
+ "regex foo matches fooxxx");
+ ok (_match("foo", "xxxfoo"),
+ "regex foo matches xxxfoo");
+ ok (!_match("foo", "bar"),
+ "regex foo does NOT match bar");
_check_substr_match();
/* verify that \\n and \\r are converted into \r and \r */
- assert(!_match("foo\\r\\n", "foo\\r\\n"));
- assert( _match("foo\\r\\n", "foo\r\n"));
+ ok (!_match("foo\\r\\n", "foo\\r\\n"),
+ "regex foo\\\\r\\\\n matches foo\\\\r\\\\n");
+ ok ( _match("foo\\r\\n", "foo\r\n"),
+ "regex foo\\\\r\\\\n does NOT match foo\\r\\n");
/* check a really long string for a regex */
#define LONG_STR_LEN (64*1024*1024)
@@ -169,10 +212,14 @@ main(int argc, char *argv[])
memcpy(s + POS_WONDERFUL, "WONDERFUL", 9);
memcpy(s + POS_COOKIE, "COOKIE", 6);
s[LONG_STR_LEN - 1] = '\0';
- assert( _match("MAGIC", s));
- assert( _match("WONDERFUL", s));
- assert( _match("COOKIE", s));
- assert(!_match("CHOCOLATE", s));
+ ok (_match("MAGIC", s),
+ "regex MAGIC matched %d bytes into a string", POS_MAGIC);
+ ok (_match("WONDERFUL", s),
+ "regex WONDERFUL matched %d bytes into a string", POS_WONDERFUL);
+ ok (_match("COOKIE", s),
+ "regex COOKIE matched %d bytes into a string", POS_COOKIE);
+ ok (!_match("CHOCOLATE", s),
+ "regex CHOCOLATE did NOT match in that long string");
xfree(s);
/* end of line handling should be disabled since end of string
@@ -180,29 +227,42 @@ main(int argc, char *argv[])
* We should be explicitly matching end-of-line sentinels like
* \n in scripts.
*/
- assert(!_match("foo$", "foo"));
- assert(!_match("foo$", "foo\n"));
- assert(!_match("foo\n", "foo"));
- assert(!_match("foo\n", "bar\nfoo"));
- assert( _match("foo\n", "barfoo\n"));
+ ok (!_match("foo$", "foo"),
+ "regex foo$ did NOT match foo");
+ ok (!_match("foo$", "foo\n"),
+ "regex foo$ did NOT match foo\\n");
+ ok (!_match("foo\n", "foo"),
+ "regex foo\\n did NOT match foo");
+ ok (!_match("foo\n", "bar\nfoo"),
+ "regex foo\\n did NOT match bar\\nfoo");
+ ok (_match("foo\n", "barfoo\n"),
+ "regex foo\\n matched barfoo\\n");
/* regex takes first match if there are > 1,
* but leading wildcard matches greedily
*/
- assert(_matchstr("foo", "abfoocdfoo",
- "abfoo"));
- assert(_matchstr_all(".*foo", "abfoocdfoo"));
+ ok (_matchstr("foo", "abfoocdfoo", "abfoo"),
+ "regex takes first match if there are more than one");
+ ok (_matchstr_all(".*foo", "abfoocdfoo"),
+ "leading wildcard matches greedily");
/* check that [:space:] character class works inside bracket
* expression
*/
- assert(_matchstr_all("bar[0-9[:space:]]*foo", "bar 42 foo"));
+ ok (_matchstr_all("bar[0-9[:space:]]*foo", "bar 42 foo"),
+ "[:space:] character class works inside bracket expression");
/* debug apcpdu3 regex
*/
#define B3RX "([0-9])*[^\r\n]*(ON|OFF)\r\n"
- assert(_matchstr_all(B3RX, " 2- Outlet 2 ON\r\n"));
- assert(_matchstr_all(B3RX, " 9- ON\r\n"));
+ ok (_matchstr_all(B3RX, " 2- Outlet 2 ON\r\n"),
+ "apcpdu3 regex test 1 works");
+ ok (_matchstr_all(B3RX, " 9- ON\r\n"),
+ "apcpdu3 regex test 2 works");
+
+ done_testing();
exit(0);
}
+
+// vi:ts=4 sw=4 expandtab
diff --git a/src/libtap/Makefile.am b/src/libtap/Makefile.am
new file mode 100644
index 00000000..46b93fd6
--- /dev/null
+++ b/src/libtap/Makefile.am
@@ -0,0 +1,10 @@
+AM_CFLAGS = \
+ $(WARNING_CFLAGS)
+
+AM_LDFLAGS =
+
+AM_CPPFLAGS =
+
+check_LTLIBRARIES = libtap.la
+
+libtap_la_SOURCES = tap.c tap.h
diff --git a/src/libtap/tap.c b/src/libtap/tap.c
new file mode 100644
index 00000000..152e39e8
--- /dev/null
+++ b/src/libtap/tap.c
@@ -0,0 +1,354 @@
+/*
+libtap - Write tests in C
+Copyright 2012 Jake Gelbman
+This file is licensed under the LGPL
+*/
+
+#define _DEFAULT_SOURCE 1
+
+#include
+#include
+#include
+#include
+#include "tap.h"
+
+static int expected_tests = NO_PLAN;
+static int failed_tests;
+static int current_test;
+static char *todo_mesg;
+
+static char *
+vstrdupf (const char *fmt, va_list args) {
+ char *str;
+ int size;
+ va_list args2;
+ va_copy(args2, args);
+ if (!fmt)
+ fmt = "";
+ size = vsnprintf(NULL, 0, fmt, args2) + 2;
+ str = malloc(size);
+ if (!str) {
+ perror("malloc error");
+ exit(1);
+ }
+ vsprintf(str, fmt, args);
+ va_end(args2);
+ return str;
+}
+
+void
+tap_plan (int tests, const char *fmt, ...) {
+ expected_tests = tests;
+ if (tests == SKIP_ALL) {
+ char *why;
+ va_list args;
+ va_start(args, fmt);
+ why = vstrdupf(fmt, args);
+ va_end(args);
+ printf("1..0 ");
+ diag("SKIP %s\n", why);
+ exit(0);
+ }
+ if (tests != NO_PLAN) {
+ printf("1..%d\n", tests);
+ }
+}
+
+int
+vok_at_loc (const char *file, int line, int test, const char *fmt,
+ va_list args)
+{
+ char *name = vstrdupf(fmt, args);
+ if (!test) {
+ printf("not ");
+ }
+ printf("ok %d", ++current_test);
+ if (*name)
+ printf(" - %s", name);
+ if (todo_mesg) {
+ printf(" # TODO");
+ if (*todo_mesg)
+ printf(" %s", todo_mesg);
+ }
+ printf("\n");
+ if (!test) {
+ printf("# Failed ");
+ if (todo_mesg)
+ printf("(TODO) ");
+ printf("test ");
+ if (*name)
+ printf("'%s'\n# ", name);
+ printf("at %s line %d.\n", file, line);
+ if (!todo_mesg)
+ failed_tests++;
+ }
+ free(name);
+ return test;
+}
+
+int
+ok_at_loc (const char *file, int line, int test, const char *fmt, ...) {
+ va_list args;
+ va_start(args, fmt);
+ vok_at_loc(file, line, test, fmt, args);
+ va_end(args);
+ return test;
+}
+
+static int
+mystrcmp (const char *a, const char *b) {
+ return a == b ? 0 : !a ? -1 : !b ? 1 : strcmp(a, b);
+}
+
+#define eq(a, b) (!mystrcmp(a, b))
+#define ne(a, b) (mystrcmp(a, b))
+
+int
+is_at_loc (const char *file, int line, const char *got, const char *expected,
+ const char *fmt, ...)
+{
+ int test = eq(got, expected);
+ va_list args;
+ va_start(args, fmt);
+ vok_at_loc(file, line, test, fmt, args);
+ va_end(args);
+ if (!test) {
+ diag(" got: '%s'", got);
+ diag(" expected: '%s'", expected);
+ }
+ return test;
+}
+
+int
+isnt_at_loc (const char *file, int line, const char *got, const char *expected,
+ const char *fmt, ...)
+{
+ int test = ne(got, expected);
+ va_list args;
+ va_start(args, fmt);
+ vok_at_loc(file, line, test, fmt, args);
+ va_end(args);
+ if (!test) {
+ diag(" got: '%s'", got);
+ diag(" expected: anything else");
+ }
+ return test;
+}
+
+int
+cmp_ok_at_loc (const char *file, int line, int a, const char *op, int b,
+ const char *fmt, ...)
+{
+ int test = eq(op, "||") ? a || b
+ : eq(op, "&&") ? a && b
+ : eq(op, "|") ? a | b
+ : eq(op, "^") ? a ^ b
+ : eq(op, "&") ? a & b
+ : eq(op, "==") ? a == b
+ : eq(op, "!=") ? a != b
+ : eq(op, "<") ? a < b
+ : eq(op, ">") ? a > b
+ : eq(op, "<=") ? a <= b
+ : eq(op, ">=") ? a >= b
+ : eq(op, "<<") ? a << b
+ : eq(op, ">>") ? a >> b
+ : eq(op, "+") ? a + b
+ : eq(op, "-") ? a - b
+ : eq(op, "*") ? a * b
+ : eq(op, "/") ? a / b
+ : eq(op, "%") ? a % b
+ : diag("unrecognized operator '%s'", op);
+ va_list args;
+ va_start(args, fmt);
+ vok_at_loc(file, line, test, fmt, args);
+ va_end(args);
+ if (!test) {
+ diag(" %d", a);
+ diag(" %s", op);
+ diag(" %d", b);
+ }
+ return test;
+}
+
+static int
+find_mem_diff (const char *a, const char *b, size_t n, size_t *offset) {
+ size_t i;
+ if (a == b)
+ return 0;
+ if (!a || !b)
+ return 2;
+ for (i = 0; i < n; i++) {
+ if (a[i] != b[i]) {
+ *offset = i;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int
+cmp_mem_at_loc (const char *file, int line, const void *got,
+ const void *expected, size_t n, const char *fmt, ...)
+{
+ size_t offset;
+ int diff = find_mem_diff(got, expected, n, &offset);
+ va_list args;
+ va_start(args, fmt);
+ vok_at_loc(file, line, !diff, fmt, args);
+ va_end(args);
+ if (diff == 1) {
+ diag(" Difference starts at offset %d", offset);
+ diag(" got: 0x%02x", ((unsigned char *)got)[offset]);
+ diag(" expected: 0x%02x", ((unsigned char *)expected)[offset]);
+ }
+ else if (diff == 2) {
+ diag(" got: %s", got ? "not NULL" : "NULL");
+ diag(" expected: %s", expected ? "not NULL" : "NULL");
+ }
+ return !diff;
+}
+
+int
+diag (const char *fmt, ...) {
+ va_list args;
+ char *mesg, *line;
+ int i;
+ va_start(args, fmt);
+ if (!fmt)
+ return 0;
+ mesg = vstrdupf(fmt, args);
+ line = mesg;
+ for (i = 0; *line; i++) {
+ char c = mesg[i];
+ if (!c || c == '\n') {
+ mesg[i] = '\0';
+ printf("# %s\n", line);
+ if (!c)
+ break;
+ mesg[i] = c;
+ line = mesg + i + 1;
+ }
+ }
+ free(mesg);
+ va_end(args);
+ return 0;
+}
+
+int
+exit_status () {
+ int retval = 0;
+ if (expected_tests == NO_PLAN) {
+ printf("1..%d\n", current_test);
+ }
+ else if (current_test != expected_tests) {
+ diag("Looks like you planned %d test%s but ran %d.",
+ expected_tests, expected_tests > 1 ? "s" : "", current_test);
+ retval = 2;
+ }
+ if (failed_tests) {
+ diag("Looks like you failed %d test%s of %d run.",
+ failed_tests, failed_tests > 1 ? "s" : "", current_test);
+ retval = 1;
+ }
+ return retval;
+}
+
+int
+bail_out (int ignore, const char *fmt, ...) {
+ va_list args;
+ va_start(args, fmt);
+ printf("Bail out! ");
+ vprintf(fmt, args);
+ printf("\n");
+ va_end(args);
+ exit(255);
+ return 0;
+}
+
+void
+tap_skip (int n, const char *fmt, ...) {
+ char *why;
+ va_list args;
+ va_start(args, fmt);
+ why = vstrdupf(fmt, args);
+ va_end(args);
+ while (n --> 0) {
+ printf("ok %d ", ++current_test);
+ diag("skip %s\n", why);
+ }
+ free(why);
+}
+
+void
+tap_todo (int ignore, const char *fmt, ...) {
+ va_list args;
+ va_start(args, fmt);
+ todo_mesg = vstrdupf(fmt, args);
+ va_end(args);
+}
+
+void
+tap_end_todo () {
+ free(todo_mesg);
+ todo_mesg = NULL;
+}
+
+#ifndef _WIN32
+#include
+#include
+#include
+
+#if defined __APPLE__ || defined BSD
+#define MAP_ANONYMOUS MAP_ANON
+#endif
+
+/* Create a shared memory int to keep track of whether a piece of code executed
+dies. to be used in the dies_ok and lives_ok macros. */
+int
+tap_test_died (int status) {
+ static int *test_died = NULL;
+ int prev;
+ if (!test_died) {
+ test_died = mmap(0, sizeof (int), PROT_READ | PROT_WRITE,
+ MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+ *test_died = 0;
+ }
+ prev = *test_died;
+ *test_died = status;
+ return prev;
+}
+
+int
+like_at_loc (int for_match, const char *file, int line, const char *got,
+ const char *expected, const char *fmt, ...)
+{
+ int test;
+ regex_t re;
+ va_list args;
+ int err = regcomp(&re, expected, REG_EXTENDED);
+ if (err) {
+ char errbuf[256];
+ regerror(err, &re, errbuf, sizeof errbuf);
+ fprintf(stderr, "Unable to compile regex '%s': %s at %s line %d\n",
+ expected, errbuf, file, line);
+ exit(255);
+ }
+ err = regexec(&re, got, 0, NULL, 0);
+ regfree(&re);
+ test = for_match ? !err : err;
+ va_start(args, fmt);
+ vok_at_loc(file, line, test, fmt, args);
+ va_end(args);
+ if (!test) {
+ if (for_match) {
+ diag(" '%s'", got);
+ diag(" doesn't match: '%s'", expected);
+ }
+ else {
+ diag(" '%s'", got);
+ diag(" matches: '%s'", expected);
+ }
+ }
+ return test;
+}
+#endif
diff --git a/src/libtap/tap.h b/src/libtap/tap.h
new file mode 100644
index 00000000..8269e7ea
--- /dev/null
+++ b/src/libtap/tap.h
@@ -0,0 +1,115 @@
+/*
+libtap - Write tests in C
+Copyright 2012 Jake Gelbman
+This file is licensed under the LGPL
+*/
+
+#ifndef __TAP_H__
+#define __TAP_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef va_copy
+#ifdef __va_copy
+#define va_copy __va_copy
+#else
+#define va_copy(d, s) ((d) = (s))
+#endif
+#endif
+
+#include
+#include
+#include
+
+int vok_at_loc (const char *file, int line, int test, const char *fmt,
+ va_list args);
+int ok_at_loc (const char *file, int line, int test, const char *fmt,
+ ...);
+int is_at_loc (const char *file, int line, const char *got,
+ const char *expected, const char *fmt, ...);
+int isnt_at_loc (const char *file, int line, const char *got,
+ const char *expected, const char *fmt, ...);
+int cmp_ok_at_loc (const char *file, int line, int a, const char *op,
+ int b, const char *fmt, ...);
+int cmp_mem_at_loc (const char *file, int line, const void *got,
+ const void *expected, size_t n, const char *fmt, ...);
+int bail_out (int ignore, const char *fmt, ...);
+void tap_plan (int tests, const char *fmt, ...);
+int diag (const char *fmt, ...);
+int exit_status (void);
+void tap_skip (int n, const char *fmt, ...);
+void tap_todo (int ignore, const char *fmt, ...);
+void tap_end_todo (void);
+
+#define NO_PLAN -1
+#define SKIP_ALL -2
+#define ok(...) ok_at_loc(__FILE__, __LINE__, __VA_ARGS__, NULL)
+#define is(...) is_at_loc(__FILE__, __LINE__, __VA_ARGS__, NULL)
+#define isnt(...) isnt_at_loc(__FILE__, __LINE__, __VA_ARGS__, NULL)
+#define cmp_ok(...) cmp_ok_at_loc(__FILE__, __LINE__, __VA_ARGS__, NULL)
+#define cmp_mem(...) cmp_mem_at_loc(__FILE__, __LINE__, __VA_ARGS__, NULL);
+#define plan(...) tap_plan(__VA_ARGS__, NULL)
+#define done_testing() return exit_status()
+#define BAIL_OUT(...) bail_out(0, "" __VA_ARGS__, NULL)
+#define pass(...) ok(1, "" __VA_ARGS__)
+#define fail(...) ok(0, "" __VA_ARGS__)
+
+#define skip(test, ...) do {if (test) {tap_skip(__VA_ARGS__, NULL); break;}
+#define end_skip } while (0)
+
+#define todo(...) tap_todo(0, "" __VA_ARGS__, NULL)
+#define end_todo tap_end_todo()
+
+#define dies_ok(...) dies_ok_common(1, __VA_ARGS__)
+#define lives_ok(...) dies_ok_common(0, __VA_ARGS__)
+
+#ifdef _WIN32
+#define like(...) tap_skip(1, "like is not implemented on Windows")
+#define unlike tap_skip(1, "unlike is not implemented on Windows")
+#define dies_ok_common(...) \
+ tap_skip(1, "Death detection is not supported on Windows")
+#else
+#define like(...) like_at_loc(1, __FILE__, __LINE__, __VA_ARGS__, NULL)
+#define unlike(...) like_at_loc(0, __FILE__, __LINE__, __VA_ARGS__, NULL)
+int like_at_loc (int for_match, const char *file, int line,
+ const char *got, const char *expected,
+ const char *fmt, ...);
+#include
+#include
+#include
+int tap_test_died (int status);
+#define dies_ok_common(for_death, code, ...) \
+ do { \
+ int cpid; \
+ int it_died; \
+ tap_test_died(1); \
+ cpid = fork(); \
+ switch (cpid) { \
+ case -1: \
+ perror("fork error"); \
+ exit(1); \
+ case 0: \
+ close(1); \
+ close(2); \
+ code \
+ tap_test_died(0); \
+ exit(0); \
+ } \
+ if (waitpid(cpid, NULL, 0) < 0) { \
+ perror("waitpid error"); \
+ exit(1); \
+ } \
+ it_died = tap_test_died(0); \
+ if (!it_died) \
+ {code} \
+ ok(for_death ? it_died : !it_died, "" __VA_ARGS__); \
+ } while (0)
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/powerman/Makefile.am b/src/powerman/Makefile.am
index 0f58a28e..90756090 100644
--- a/src/powerman/Makefile.am
+++ b/src/powerman/Makefile.am
@@ -52,6 +52,8 @@ powermand_SOURCES = \
parse_tab.y \
parse_util.c \
parse_util.h \
+ pluglist.c \
+ pluglist.h \
powermand.c
powermand_LDADD = \
@@ -70,3 +72,17 @@ CLEANFILES = \
libpowerman_la_SOURCES = \
libpowerman.c
+
+check_PROGRAMS = \
+ test_pluglist \
+ test_apiclient
+
+test_pluglist_SOURCES = test/pluglist.c
+test_pluglist_LDADD = \
+ $(builddir)/pluglist.o \
+ $(top_builddir)/src/libcommon/libcommon.a \
+ $(top_builddir)/src/liblsd/liblsd.a
+
+test_apiclient_SOURCES = test/apiclient.c
+test_apiclient_LDADD = \
+ $(builddir)/libpowerman.la
diff --git a/src/libcommon/pluglist.c b/src/powerman/pluglist.c
similarity index 100%
rename from src/libcommon/pluglist.c
rename to src/powerman/pluglist.c
diff --git a/src/libcommon/pluglist.h b/src/powerman/pluglist.h
similarity index 100%
rename from src/libcommon/pluglist.h
rename to src/powerman/pluglist.h
diff --git a/test/cli.c b/src/powerman/test/apiclient.c
similarity index 100%
rename from test/cli.c
rename to src/powerman/test/apiclient.c
diff --git a/test/tpl.c b/src/powerman/test/pluglist.c
similarity index 100%
rename from test/tpl.c
rename to src/powerman/test/pluglist.c
diff --git a/test/Makefile.am b/test/Makefile.am
index 80cad0cf..90e983b7 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -1,9 +1,5 @@
-sbin_PROGRAMS = vpcd
-
check_PROGRAMS = \
- tpl \
- tregex \
- targv \
+ vpcd \
baytech \
icebox \
gpib \
@@ -11,7 +7,6 @@ check_PROGRAMS = \
cyclades \
ipmipower \
redfishpower \
- cli \
ilom \
lom \
swpdu \
@@ -26,12 +21,11 @@ dist_check_SCRIPTS = \
TESTS_ENVIRONMENT = env
TESTS_ENVIRONMENT += "PATH_POWERMAN=$(top_builddir)/src/powerman/powerman"
TESTS_ENVIRONMENT += "PATH_POWERMAND=$(top_builddir)/src/powerman/powermand"
-TESTS_ENVIRONMENT += "PATH_ETC=$(top_builddir)/etc"
TESTS_ENVIRONMENT += "PATH_POWERMAN_STONITH=$(top_srcdir)/heartbeat/powerman"
TESTS_ENVIRONMENT += "TEST_SRCDIR=$(top_srcdir)/test"
TESTS_ENVIRONMENT += "TEST_BUILDDIR=$(top_builddir)/test"
-TESTS = t00 t01 t02 t03 t04 t05 t06 t07 t08 t09 t10 t11 t12 t13 \
+TESTS = t00 t01 t02 t03 t06 t07 t08 t09 t10 t11 t12 t13 \
t14 t15 t16 t17 t18 t19 t20 t21 t22 t23 t24 t25 t26 t27 \
t28 t29 t30 t31 t32 t33 t34 t35 t36 t37 t38 t39 t40 t41 \
t42 t43 t44 t46 t47 t48 t49 t50 t51 t52 t53 t54 t55 \
@@ -56,15 +50,6 @@ common_ldadd = \
vpcd_SOURCES = vpcd.c
vpcd_LDADD = $(common_ldadd)
-tpl_SOURCES = tpl.c
-tpl_LDADD = $(common_ldadd)
-
-tregex_SOURCES = tregex.c
-tregex_LDADD = $(common_ldadd)
-
-targv_SOURCES = targv.c
-targv_LDADD = $(common_ldadd)
-
baytech_SOURCES = baytech.c
baytech_LDADD = $(common_ldadd)
@@ -101,11 +86,6 @@ openbmc_httppower_LDADD = $(common_ldadd)
redfish_httppower_SOURCES = redfish-httppower.c
redfish_httppower_LDADD = $(common_ldadd)
-cli_SOURCES = cli.c
-cli_LDADD = \
- -L$(top_builddir)/src/powerman \
- -lpowerman
-
check_DATA = \
mcr.conf sierra.conf \
t07.conf t09.conf t10.conf t17.conf t18.conf t19.conf t20.conf \
diff --git a/test/t00 b/test/t00
index 0410657b..09a2ffd6 100755
--- a/test/t00
+++ b/test/t00
@@ -1,4 +1,4 @@
#!/bin/sh
TEST=t00
-${TEST_BUILDDIR}/tpl -f p493 'foo[1-500]' 'p[1-500]' >$TEST.out 2>&1 || exit 1
+${TEST_BUILDDIR}/../src/powerman/test_pluglist -f p493 'foo[1-500]' 'p[1-500]' >$TEST.out 2>&1 || exit 1
diff $TEST.out ${TEST_SRCDIR}/$TEST.exp >$TEST.diff
diff --git a/test/t01 b/test/t01
index bca941dd..c6b3fd25 100755
--- a/test/t01
+++ b/test/t01
@@ -1,4 +1,4 @@
#!/bin/sh
TEST=t01
-${TEST_BUILDDIR}/tpl 't[1,2,3]' 'p[999-1001]' >$TEST.out 2>&1 || exit 1
+${TEST_BUILDDIR}/../src/powerman/test_pluglist 't[1,2,3]' 'p[999-1001]' >$TEST.out 2>&1 || exit 1
diff $TEST.out ${TEST_SRCDIR}/$TEST.exp >$TEST.diff
diff --git a/test/t02 b/test/t02
index f07abc4b..bab4386d 100755
--- a/test/t02
+++ b/test/t02
@@ -1,4 +1,4 @@
#!/bin/sh
TEST=t02
-${TEST_BUILDDIR}/tpl -p1,2,3,4,5,6 foo[11-15] [1-5] >$TEST.out 2>&1 || exit 1
+${TEST_BUILDDIR}/../src/powerman/test_pluglist -p1,2,3,4,5,6 foo[11-15] [1-5] >$TEST.out 2>&1 || exit 1
diff $TEST.out ${TEST_SRCDIR}/$TEST.exp >$TEST.diff
diff --git a/test/t03 b/test/t03
index 463d13c0..54e475bb 100755
--- a/test/t03
+++ b/test/t03
@@ -1,4 +1,4 @@
#!/bin/sh
TEST=t03
-${TEST_BUILDDIR}/tpl -p 1,2,3,4,5,6,7,8 'foo[1-500]' '[1-500]' >$TEST.out 2>&1 || exit 1
+${TEST_BUILDDIR}/../src/powerman/test_pluglist -p 1,2,3,4,5,6,7,8 'foo[1-500]' '[1-500]' >$TEST.out 2>&1 || exit 1
diff $TEST.out ${TEST_SRCDIR}/$TEST.exp >$TEST.diff
diff --git a/test/t04 b/test/t04
deleted file mode 100755
index 7d15c1a3..00000000
--- a/test/t04
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/bin/sh
-TEST=t04
-${TEST_BUILDDIR}/targv >$TEST.out 2>&1 || exit 1
-diff $TEST.out ${TEST_SRCDIR}/$TEST.exp >$TEST.diff
diff --git a/test/t04.exp b/test/t04.exp
deleted file mode 100644
index e69de29b..00000000
diff --git a/test/t05 b/test/t05
deleted file mode 100755
index d59f82d5..00000000
--- a/test/t05
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/bin/sh
-TEST=t05
-${TEST_BUILDDIR}/tregex >$TEST.out 2>&1 || exit 1
-diff $TEST.out ${TEST_SRCDIR}/$TEST.exp >$TEST.diff
diff --git a/test/t05.exp b/test/t05.exp
deleted file mode 100644
index e69de29b..00000000
diff --git a/test/t49 b/test/t49
index 7de03156..b81a0d5c 100755
--- a/test/t49
+++ b/test/t49
@@ -1,21 +1,23 @@
#!/bin/sh
TEST=t49
+client=$TEST_BUILDDIR/../src/powerman/test_apiclient
+
$PATH_POWERMAND -c ${TEST_BUILDDIR}/$TEST.conf -f -1 2>/dev/null&
sleep 1
-./cli localhost:10104 q t1 >$TEST.out 2>$TEST.err
+$client localhost:10104 q t1 >$TEST.out 2>$TEST.err
test $? = 0 || exit 1
wait
$PATH_POWERMAND -c ${TEST_BUILDDIR}/$TEST.conf -f -1 2>/dev/null&
sleep 1
-./cli localhost:10104 l >>$TEST.out 2>>$TEST.err
+$client localhost:10104 l >>$TEST.out 2>>$TEST.err
test $? = 0 || exit 1
wait
$PATH_POWERMAND -c ${TEST_BUILDDIR}/$TEST.conf -f -1 2>/dev/null&
sleep 1
-./cli localhost:10104 1 t0 >>$TEST.out 2>>$TEST.err
+$client localhost:10104 1 t0 >>$TEST.out 2>>$TEST.err
test $? = 0 || exit 1
wait
diff --git a/test/tpm b/test/tpm
deleted file mode 100755
index 5885c840..00000000
--- a/test/tpm
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/bin/bash
-
-if [ "$PATH_POWERMAND" = "" ]; then
- PATH_POWERMAND=../src/powerman/powermand
-fi
-$PATH_POWERMAND -f -c t51.conf -s