[LTP] [PATCH] Shell wrappers for the checkpoint interface
Stanislav Kholmanskikh
stanislav.kholmanskikh@oracle.com
Wed Jun 8 11:59:04 CEST 2016
This patch provides necessary wrappers to use the checkpoint
API in shell tests.
Big thanks to Cyril and Jan for their comments to the RFC versions.
Signed-off-by: Stanislav Kholmanskikh <stanislav.kholmanskikh@oracle.com>
---
Changes since RFC:
* Single tst_checkpoint binary instead of tst_checkpoint_{wait,wake}
* Changed the order of arguments passed to the binary
* The 'wake' command of the binary requires NR_WAKE paramater.
* Implement wrappers to all TST_CHECKPOINT_ functions
* Use TCID in LTP_IPC_PATH
* Add docs. Noted that the shell functions are compatible to C
counterparts (initialized with tst_reinit).
doc/test-writing-guidelines.txt | 23 ++++++++-
testcases/lib/.gitignore | 1 +
testcases/lib/Makefile | 6 +-
testcases/lib/test.sh | 38 +++++++++++++++
testcases/lib/tst_checkpoint.c | 101 +++++++++++++++++++++++++++++++++++++++
5 files changed, 165 insertions(+), 4 deletions(-)
create mode 100644 testcases/lib/tst_checkpoint.c
diff --git a/doc/test-writing-guidelines.txt b/doc/test-writing-guidelines.txt
index cdff39c..b58a526 100644
--- a/doc/test-writing-guidelines.txt
+++ b/doc/test-writing-guidelines.txt
@@ -583,7 +583,7 @@ As LTP tests are written for Linux, most of the tests involve fork()-ing and
parent-child process synchronization. LTP includes a checkpoint library that
provides wait/wake futex based functions.
-In order to use checkpoints the '.need_chekcpoints' flag in the 'struct
+In order to use checkpoints the '.needs_checkpoints' flag in the 'struct
tst_test' must be set to '1', this causes the test library to initialize
checkpoints before the 'test()' function is called.
@@ -1400,6 +1400,27 @@ else
fi
-------------------------------------------------------------------------------
+2.3.6 Access to the checkpoint interface
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The shell library provides an implementation of the checkpoint interface
+compatible with the C version. All TST_CHECKPOINT_* functions are available.
+
+In order to initialize checkpoints '$TST_NEEDS_CHECKPOINTS' must be set to '1'
+before the inclusion of 'test.sh':
+
+[source,sh]
+-------------------------------------------------------------------------------
+#!/bin/sh
+
+TST_NEEDS_CHECKPOINTS=1
+. test.sh
+-------------------------------------------------------------------------------
+
+Since both the implementations are compatible, it's also possible to start
+a child binary process from a shell test and synchronize with it. This process
+must have checkpoints initialized by calling tst_reinit()'.
+
3. Common problems
------------------
diff --git a/testcases/lib/.gitignore b/testcases/lib/.gitignore
index 8886b34..3227552 100644
--- a/testcases/lib/.gitignore
+++ b/testcases/lib/.gitignore
@@ -1 +1,2 @@
tst_sleep
+tst_checkpoint
diff --git a/testcases/lib/Makefile b/testcases/lib/Makefile
index 0bfb149..c625c6e 100644
--- a/testcases/lib/Makefile
+++ b/testcases/lib/Makefile
@@ -22,10 +22,10 @@
top_srcdir ?= ../..
-include $(top_srcdir)/include/mk/env_pre.mk
+include $(top_srcdir)/include/mk/testcases.mk
-INSTALL_TARGETS := *.sh tst_sleep
+INSTALL_TARGETS := *.sh
-MAKE_TARGETS := tst_sleep
+MAKE_TARGETS := tst_sleep tst_checkpoint
include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/lib/test.sh b/testcases/lib/test.sh
index e118a56..9f1e3be 100644
--- a/testcases/lib/test.sh
+++ b/testcases/lib/test.sh
@@ -100,6 +100,10 @@ tst_exit()
$TST_CLEANUP
fi
+ if [ -n "$LTP_IPC_PATH" -a -f "$LTP_IPC_PATH" ]; then
+ rm -f "$LTP_IPC_PATH"
+ fi
+
# Mask out TINFO
exit $((LTP_RET_VAL & ~16))
}
@@ -383,6 +387,27 @@ tst_su()
su "$usr" -c "PATH=\$PATH:$LTPROOT/testcases/bin/ $@"
}
+TST_CHECKPOINT_WAIT()
+{
+ ROD tst_checkpoint wait 10000 "$1"
+}
+
+TST_CHECKPOINT_WAKE()
+{
+ ROD tst_checkpoint wake 10000 "$1" 1
+}
+
+TST_CHECKPOINT_WAKE2()
+{
+ ROD tst_checkpoint wake 10000 "$1" "$2"
+}
+
+TST_CHECKPOINT_WAKE_AND_WAIT()
+{
+ TST_CHECKPOINT_WAKE
+ TST_CHECKPOINT_WAIT
+}
+
# Check that test name is set
if [ -z "$TCID" ]; then
tst_brkm TBROK "TCID is not defined"
@@ -402,3 +427,16 @@ if [ -z "$LTPROOT" ]; then
else
export LTP_DATAROOT="$LTPROOT/testcases/data/$TCID"
fi
+
+if [ "$TST_NEEDS_CHECKPOINTS" = "1" ]; then
+ LTP_IPC_PATH="/dev/shm/ltp_${TCID}_$$"
+
+ LTP_IPC_SIZE=$(getconf PAGESIZE)
+ if [ $? -ne 0 ]; then
+ tst_brkm TBROK "getconf PAGESIZE failed"
+ fi
+
+ ROD_SILENT dd if=/dev/zero of="$LTP_IPC_PATH" bs="$LTP_IPC_SIZE" count=1
+ ROD_SILENT chmod 600 "$LTP_IPC_PATH"
+ export LTP_IPC_PATH
+fi
diff --git a/testcases/lib/tst_checkpoint.c b/testcases/lib/tst_checkpoint.c
new file mode 100644
index 0000000..712657e
--- /dev/null
+++ b/testcases/lib/tst_checkpoint.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2016 Linux Test Project
+ *
+ * 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 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it would 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, write the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#define TST_NO_DEFAULT_MAIN
+#include "tst_test.h"
+
+static void print_help(void)
+{
+ printf("Usage: tst_checkpoint wait TIMEOUT ID\n");
+ printf(" or: tst_checkpoint wake TIMEOUT ID NR_WAKE\n");
+ printf(" TIMEOUT - timeout in ms\n");
+ printf(" ID - checkpoint id\n");
+ printf(" NR_WAKE - number of processes to wake up\n");
+}
+
+static int get_val(const char *name, const char *arg, unsigned int *val)
+{
+ unsigned long temp;
+ char *e;
+
+ errno = 0;
+ temp = strtoul(arg, &e, 10);
+ if (errno || (e == arg) || (temp > UINT_MAX)) {
+ fprintf(stderr, "ERROR: Invalid %s '%s'\n",
+ name, arg);
+ return -1;
+ }
+
+ *val = temp;
+
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ unsigned int id, timeout, nr_wake;
+ int ret;
+ int type;
+
+ if (argc < 3)
+ goto help;
+
+ if (!strcmp(argv[1], "wait")) {
+ type = 0;
+
+ if (argc != 4)
+ goto help;
+ } else if (!strcmp(argv[1], "wake")) {
+ type = 1;
+
+ if (argc != 5)
+ goto help;
+
+ if (get_val("NR_WAKE", argv[4], &nr_wake))
+ goto help;
+ } else {
+ fprintf(stderr, "ERROR: Invalid COMMAND '%s'\n",
+ argv[1]);
+ goto help;
+ }
+
+ if (get_val("TIMEOUT", argv[2], &timeout)
+ || get_val("ID", argv[3], &id)) {
+ goto help;
+ }
+
+ tst_reinit();
+
+ if (!type)
+ ret = tst_checkpoint_wait(id, timeout);
+ else
+ ret = tst_checkpoint_wake(id, nr_wake, timeout);
+
+ if (ret)
+ return 1;
+ else
+ return 0;
+
+help:
+ print_help();
+ return 1;
+}
--
1.7.1
More information about the ltp
mailing list